ACKNOWLEDGEMENT VISHNU RAMAKRISHNAN VISHNU SANKER ANAGHA OK PRANAM SREEDHARAN

Size: px
Start display at page:

Download "ACKNOWLEDGEMENT VISHNU RAMAKRISHNAN VISHNU SANKER ANAGHA OK PRANAM SREEDHARAN"

Transcription

1 I ACKNOWLEDGEMENT I take this occasion to thank God, almighty for blessing us with his grace and taking our endeavor to a successful culmination. I extend my sincere and heartfelt thanks to our esteemed guide, Dr. SUDHEEP ELAYIDOM, for providing me with the right guidance and advice at the crucial junctures and for showing me the right way. I extend my sincere thanks to our respected Head of the division Mr. PRAMOD PAVITHRAN, for allowing us to use the facilities available. I would like to thank the other faculty members also, at this occasion. Last but not the least, I would like to thank my friends and family for the support and encouragement they have given me during the course of our work. VISHNU RAMAKRISHNAN VISHNU SANKER ANAGHA OK PRANAM SREEDHARAN

2 II ABSTRACT Money Tree Android Application Modern life offers a plethora of options of services and goods for consumers. As a result, people s expenses have gone up dramatically, e.g., compared to a decade ago, and the cost of living has been increasing day by day. Thus it becomes essential to keep a check on expenses in order to live a good life with a proper budget set up. Money Tree, the Financial Reminder Mobile Application was developed for Android Mobile users to keep track of their expenses and determine whether they are spending as per their set budget. Potential users need to input the required data such as the expense amount, Institution, Category, and Subcategory of the expense. The application allows users to track their expenses daily, weekly, monthly, and yearly in terms of summary, and graphs. This mobile application is a full detailed Financial Reminder tool that will not only help users keep a check on their expenses, but also cut down the unrequired expenses, and thus will help provide a responsible lifestyle.

3 III LIST OF ABBREVIATIONS IDE Integrated Development Environment ADT Android Development Toolkit Nib Next Interface Builder UI User Interface PDF Portable Document Format OS Operating System HTML Hyper Text Markup Language CSS Cascading Style Sheets WP7 Windows Phone 7 plist Property List PC Personal Computer

4 IV TABLE OF CONTENTS Acknowledgement...i Abstract...ii List of Abbreviations...iii 1. Introduction The Android Operating System Need for a Financial Reminder App Eclipse IDE and ADT Plugin Application States Design and Implementation Development DataFlow Diagram Core Data Model Expense View Expense Detail View Category/Sub-Category View...18

5 V Date Picker View Graphs Conclusion Current Advantages and Limitations Appendix Sample Codes Add Budget Add Category Database Handler Notification Service Graph References...80

6 Introduction 1 1. INTRODUCTION With the launch and increase in sales of smart phones over the last few years, people are using mobile applications to get their work done, which makes their lives easier. Mobile applications comprise various different categories such as Entertainment, Sports, Lifestyle, Education, Games, Food and Drink, Health and Fitness, Finance, etc. This application, Money Tree, falls in the Finance Category and serves the important purpose of managing finances which is a very important part of one s life. The software product went through the design, development, and the testing phase as a part of the Software Development Life cycle. The application s interface is designed using custom art elements, the functionality is implemented using Android ADT Plugin in Eclipse IDE, and the phase of testing the product was accomplished successfully. The application is not much user intensive but just comprises of having the users enter the expense amount, date, category, institution and other optional attributes (taking picture of the receipts, entering notes about the expense, adding subcategories to the categories). With this entered information, the user is able to see the expense details daily, weekly,

7 Introduction 2 monthly, and yearly in figures, and graph. The aim of this report is to provide a solution for Android Mobile users on how to manage finances in any circumstance by keeping track of their expenses every day. Ultimately, this contributes to societal well-being. 1.1 THE ANDROID OPERATING SYSTEM Android is an operating system based on the Linux kernel, and designed primarily for touchscreen mobile devices such as smartphones and tablet computers. Initially developed by Android, Inc., which Google backed financially and later bought in 2005, Android was unveiled in 2007 along with the founding of the Open Handset Alliance a consortium of hardware, software, and telecommunication companies devoted to advancing open standards for mobile devices. The first publicly available smartphone running Android, the HTC Dream, was released on October 22, The user interface of Android is based on direct manipulation, using touch inputs that loosely correspond to real-world actions, like swiping, tapping, pinching, and reverse pinching to manipulate on-screen objects. Internal hardware such as accelerometers, gyroscopes, and proximity sensors are

8 Introduction 3 used by some applications to respond to additional user actions, for example adjusting the screen from portrait to landscape depending on how the device is oriented. Android allows users to customize their home screens with shortcuts to applications and widgets, which allow users to display live content, such as s and weather information, directly on the home screen. Applications can further send notifications to the user to inform them of relevant information, such as new s and text messages. Android's source code is released by Google under the Apache License; this permissive licensing allows the software to be freely modified and distributed by device manufacturers, wireless carriers and enthusiast developers. Most Android devices ship with a combination of open source and proprietary software. As of July 2013, Android has the largest number of applications ("apps"), available for download in Google Play store which has had over 1 million apps published, and over 50 billion downloads. A developer survey conducted in April May 2013 found that Android is the most used platform among developers: it is used by 71% of the mobile developers population. Android is popular with technology companies which require a ready-made, low-cost and customizable operating system for high-tech

9 Introduction 4 devices. Despite being primarily designed for phones and tablets, it also has been used in televisions, games consoles, digital cameras, and other electronics. Android's open nature has encouraged a large community of developers and enthusiasts to use the open-source code as a foundation for community-driven projects, which add new features for advanced users or bring Android to devices which were officially released running other operating systems. As of May 2012, Android became the most popular mobile OS, having the largest installed base, and is a market leader in most countries including the United States; there it has had the highest installed base of mobile phones for years. In the third quarter of 2013, Android's share of the global smartphone shipment market led by Samsung products was 81.3%, the highest ever. In most markets Android-powered phones are the most popular comprising more than half of the overall smartphone sales, including the United States market starting with the September November 2013 period. The operating system's success has made it a target for patent litigation as part of the so-called "smartphone wars" between technology companies. As of September 2013, one billion Android devices have been activated.

10 Introduction 5 Fig 1.1 The android operating system architecture

11 Introduction NEED FOR A FINANCIAL REMINDER APPLICATION ON AN ANDROID MOBILE (SMARTPHONE) A smart phone is built on a mobile operating system with advanced technology and computing capabilities. It all started with Symbian in 2000, which was the first modern mobile OS on a smart phone followed by Blackberry in 2002, Apple Android in 2007, Android in 2008 etc. Global smart phone sales increased 47.3 % to 149 million units in the fourth quarter of 2011, according to market research. According to the smart phone recent sales stats globally, IDC says that over 153 million smart phones sold worldwide in Figure 1.2. Share of worldwide smart phone sales by OS(IDC)

12 Introduction 7 The above pictorial representation shows that a lot of people are using Mobile device which works on Android OS. Thus arises a need for an application that serves to manage their lifestyle by managing their finances accordingly. The sole reason behind the need for this application is that when you start finding out where you are spending your money, it becomes easy to figure out how you can save money by cutting back or even eliminating spending in some areas. You can concentrate on saving even a little bit on your biggest expense categories, compared to cutting back a lot on smaller expenses. As this tracking expense becomes a habit, you can get a good picture of how much money you need to maintain your lifestyle. Budget Setting and expense tracking both alter consumer choice. Mental Budgeting leads people to overconsume some goods and underconsume others. Because budgets are set before consumption opportunities arise, they sometimes overestimate or underestimate the money required for a particular amount. On the other hand, expense tracking shows that some expenses are more likely to produce over-or-underconsumption. As people track their expenses, expenses that are relatively easy to categorize those that are more typical examples of their categories will be the most subject to the rigors of budgeting

13 Introduction 8 A number of students at SOE were asked how much they spend per month on their needs and requirements, and nobody was able to provide an exact answer. Thus, they do not know where their money is going. They liked the idea of such an expense tracking tool where with just a few inputs everyday, you can make yourself organized and make your life a bit easier in the long run 1.3 ECLIPSE IDE AND ADT PLUGIN The Eclipse ADT plugin comprises of the interfaces, tools and components required to develop and deploy native applications in android. The development environment to build the Android applications is Eclipse IDE where we can create, test, debug our apps. The apps are written in JAVA language. We can run the apps on Bluestacks Simulator, or in an Android Virtual Device(AVD), or on an attached Android Device. For that, we need to use a USB Connection Cable if we want to test the app on a real device. Everything works in terms of packages with extension.apk in Android. Basically, a package is a directory containing the libraries and the necessary resources like images, header files, XML files, and other resources that we need to import into the project. The drawbacks of using eclipse IDE for native android applications are that

14 Introduction 9 1) The applications are highly unstable 2) Backward compatibility is feeble Fig 1.3 Eclipse IDE screen shot

15 Introduction APPLICATION STATES An Android application can be running in the background or foreground and it becomes very important to know when there is a transition in the state. The behavior of an app changes when it is in background state as the operating system puts limitations to what the app can perform in order to improve the battery life of the phone as well as manage it properly with the foreground app. The system uses notifications while making the transitions like when changing the state from background to foreground or foreground to background. While in the suspended state, no notifications are sent by the operating system. An Android application is usually in one of the following states: 1. Not Running: The application has not been launched in this state or being terminated by the system while running. 2. Inactive: The application is not receiving any events but still running in foreground. 3. Active: The application is running in foreground and receiving events as well.

16 Introduction Background: The application in this state is in background and still working as in the code is executing behind the scenes and the app is not killed. This state usually comes when the application is on it s way to being suspended or when the application needs some extra execution time. 5. Suspended: The application in this state is in background but not executing any code meaning the application still remains in memory but it s not working in terms of executing the code. The operating system does not notify the app when it moves it to thes suspended state. Figure 1.4. State changes in Android app

17 Design and implementation DESIGN AND IMPLEMENTATION 2.1. DEVELOPEMENT Prior to building any application from scratch, it is important to plan the design flow of the application. The user interface design is pretty essential to know how the application is intended to work. Planning an application definitely involves some specific strategies. Many strategic questions come to the mind while designing and planning an application like there might be apps in the app store similar to your idea, what the need of such an application in the market is, what features make your app unique, what will make the people use your app and not the ones designed by others, how much time the application will take to develop, what user requirements either small or big should be considered, what category should the app fall into, etc. After planning the application, next comes the Data Flow Diagrams(DFDs). DFD is simply designing the flow of the application, describing how the navigation of the views will work. If the app is designed involving a team, it becomes very essential to use such kind of tool to help design the app and distribute the idea among

18 Design and implementation 13 the team. After the proper flow of the app, next comes the development phase. Eclipse is an IDE that the developers can download to start building applications. Eclipse comes with the Simulators on which we can run and test the app, Interface builders to build the interfaces visually inside the app, command line tools, and various other tools required. The programming language used to write the application in Eclipse is JAVA. 2.2 DATAFLOW DIAGRAM Fig 2.1 DFD

19 Design and implementation CORE DATA MODEL Fig 2.2 Core Data Model As Figure 2.2 shows, there are 5 entities designed named Money, Expense, Income, Category and SubCategory. Money is the parent entity with the attributes such as amount, category, date, notes, payment source method, photo, subcategory, total amount and the institution. The reason the other two entities Income and Expense inherit from the parent entity

20 Design and implementation 15 Money is that they are supposed to have the same attributes in them, so the common attributes are listed in Money entity. Then there is an entity called category with attributes such as categoryname, ischecked (to determine which is the selected category), selectedsubcategory (sub category selected for the particular category). Category has a to-many relationship with Expense and Income entities as there can be many expenses or incomes for a particular category. Then the category has to-many relationship with entity SubCategory as a category can have many sub-categories. The results that are returned from the Core Data fetch request are managed by a fetched result controller that provide the data for the tableview used in the views. An instance of NSFetchedResultsController is created which acts as an instance variable of a table view controller. When a fetched result controller is initialized, we provide four parameters: 1. Fetch request that contains at least one sort descriptor for the resulting order of the objects. 2. Managed object context which the fetched results controller uses to execute the fetch request. 3. Section name key path that is optional which would order the results

21 Design and implementation 16 by section. Making it nil would just make one section and the results would show in that section itself. 4. Cache name used, which is optional. Making it nil would prevent caching. To execute the fetch request, performfetch: method is called on the controller. The class that uses the fetched results controller implements the NSFetchedResultsController delegate. The controller basically notifies the delegate when the objects changes locations or when there is a modification of the sections. The setincludessubentities will produce the results for both the entities Expense and Income as the request is made on the parent entity Money 2.4 EXPENSE VIEW The expense/income view will contain the list of expenses/incomes made for a particular date. The user can either enter an expense or an income depending on what he chooses Expense Detail View When the expense or the income button on the Block Action Sheet is pressed, it navigates to the next view called the MoneyDetailViewController which basically contains some fields that are supposed to be entered by the user in order to save their

22 Design and implementation 17 daily expenses or incomes. User can take the photo of the receipt (bills), enter the amount, institution and category. Date will be automatically set to the current date and user has the option to fill sub-category, payment source and some notes about the expense/income. The view is presented in a table view style called UITableView in Android which presents the data in rows. When Category row is pressed, it takes the user to another view called Category View with some pre-filled entries in the database. Categories can be added, edited and deleted as well depending on the user needs and requirements. Sub-Category view is displayed when the user taps a category and can add a sub-category related to the category being tapped. The payment source Row presents another screen with a tableview displaying various sources such as Cash, Credit card, Debit Card, Gift Card and Check.

23 Design and implementation 18 Fig 2.3 Add Expense Category/Sub-Category View When the category row on the Expense/Income Detail view is pressed, it brings to another table view with some pre-filled entries in the database. The user can press the

24 Design and implementation 19 edit button to delete the existing categories or add new categories to the existing list. The Subcategory view is displayed in a similar fashion when a particular category is being tapped. The user has the option to add a sub-category to the related category. If all the rows are entered, the user has the flexibility to see the results (expenses) in the reports tab based on Category, Sub-Category, vendor, payment source etc. Figure 2.1 and 2.2 shows the category view. When any of the views is being launched, viewdidload method in Android is being called which instantiates the loading of the view. There are methods like viewwillappear, viewdidappear with little differences and are called accordingly depending on the actions the view has to perform. The new objects are added by referencing to the entity Category and then it s saved to the managed object context and can be retrieved from it later on by a fetch request if needed. New entries are added by using insertnewobjectforentityforname: method on NSEntityDescription which is provided by NSManagedObjectModel class

25 Design and implementation 20 Fig 2.4 Add Category Block Alert view is used in order to pop up an alert when the user tries to save a new category/subcategory without adding a name to it. Android provides UIAlertView component just like UIActionSheet described above, but Block Alert view is more flexible and got many advantages over the built in component in Android as

26 Design and implementation 21 mentioned in Figure 2.3 shows the view for adding sub-category and the block alert while trying to add a subcategory without a name. Fig 2.5 Add Sub Category Date Picker View When the date row on the Expense/Income Detail View (Figure 2.6 and 2.7) is tapped, it moves to a date picker

27 Design and implementation 22 view so that the user can select any date in the picker to see the expense/income made or probably add an expense/income for a particular date. Fig 2.6 Date picker

28 Design and implementation 23 The current date is set up on the date picker. It s a UIDatePicker component available in Android built in interface. The UIDatePicker provides the date and date picker modes which is set up to show the month, date and year. When the date picker is rotated to change the date, datepickervaluechanged: method is called to set the date set up by the user GRAPHS The total expense/income amount and it s summary is seen better if shown graphically. A visual representation is beneficial for the user to get the clear estimate where he needs to cut down his expenses. The user selects a time period and display choice in order to see the total expense amount graphically. When the user selects the bar graph button, a pop up gets displayed allowing the user to choose Expenses or Income in order to see the required results.

29 Design and implementation 24 Fig 2.7 Graph

30 Conclusion CONCLUSION We now present and discuss the limitations of the new product, issues faced, and the remedies to those limitations. While building this expense tracking software tool, the major focus was to make this tool less user intensive and more user productive. The first version of this application is only applicable to the USA. It could have been used in other countries if I would have used currency converters in the application, which I will improvise in the later version. Certain issues were faced while implementing this tool and various important things were kept in mind. For example, the user interface is designed simple yet creative so that the user doesn t face any difficulty in using the software tool and the expense data is persisted on the device even if the user deletes the application from the memory background. Core Data was chosen over SQLite to persist the data which is very beneficial even though the data would reside on the device locally. Cloud functionality is missing. This would allow data to be saved to a Cloud and shared between various devices. The application lacks the feature by which the list of expenses and amount could have been displayed in one file in PDF format making it easily readable for the

31 Conclusion 26 users. Despite of the mentioned flaws, the application would work as a charm for tracking expenses and provides the user, the flexibility to see the reports in any format (PDF, Bar Graphs, Pie-charts, summary etc.). 3.1 CURRENT ADVANTAGES AND LIMITATIONS The application is designed in such a simple and straight forward manner that the user faces no problems or difficulties in using this software tool to track the expenses. Still the application suffers from various limitations which does t create any obstacle in the current version as such but these limitations need to be addressed in the next version of the application. The application interface is embellished with eye soothing colors and smooth interfaces. The application gives a detailed view of the expenses but lacks search functionality and consolidated view. The application is light weight and does no need much hardware specifications and is backward compatible upto android version 2.2 froyo.

32 Appendix APPENDIX 4.1 SAMPLE CODE certain application functions The following is the sample codes for Add budget package com.expensemanager.activities; import java.text.parseexception; import java.text.simpledateformat; import java.util.arraylist; import java.util.collections; import java.util.comparator; import java.util.date; import java.util.list;

33 Appendix 28 import com.expensemanager.r; import com.expensemanager.exception.businessexception; import com.expensemanager.facade.droidexpensefacade; import com.expensemanager.model.category; import com.expensemanager.model.subcategory; import com.expensemanager.util.constants; import android.app.activity; import android.app.alertdialog; import android.app.dialog; import android.content.dialoginterface; import android.os.bundle; import android.util.log; import android.view.view; import android.view.view.onclicklistener; import android.widget.adapterview;

34 Appendix 29 import android.widget.adapterview.onitemselectedlistener; import android.widget.arrayadapter; import android.widget.button; import android.widget.datepicker; import android.widget.edittext; import android.widget.radiobutton; import android.widget.spinner; import android.widget.textview; import android.widget.toast; public class AddBudgetActivity extends Activity implements OnItemSelectedListener, OnClickListener { private DroidExpenseFacade droidexpensefacade; private String categoryselected; private String subcategoryselected;

35 Appendix 30 private List<Category> categories; private int renovacao; private Integer day; private Integer month; private Integer year; private SimpleDateFormat sdf; private static String DATETIME_ISO_STRMASK = "%d-%d-%d %d:%d:%d"; private Spinner subcatspinner; private RadioButton renovacaonenhum; private RadioButton renovacaodiaria; private RadioButton renovacaosemanal; private RadioButton renovacaomensal; private RadioButton renovacaoanual;

36 Appendix 31 private TextView renovacaotv0; private TextView renovacaotv1; private TextView renovacaotv2; private TextView renovacaotv3; private TextView renovacaotv4; /** Called when the activity is first created. public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.add_budget_page); droidexpensefacade = new DroidExpenseFacade(); sdf = new SimpleDateFormat(Constants.DATE_PATTERN);

37 Appendix 32 final Spinner catspinner = (Spinner) findviewbyid(r.id.add_budget_spinner_cat); catspinner.setonitemselectedlistener(this); subcatspinner = (Spinner) findviewbyid(r.id.add_budget_spinner_subcat); subcatspinner.setonitemselectedlistener(this); final Button concluidobutton = (Button) findviewbyid(r.id.add_budget_button_done); final EditText budgetname = (EditText) findviewbyid(r.id.add_budget_edittext_name_value); final EditText budgetvalue = (EditText) findviewbyid(r.id.add_budget_edittext_value); renovacaonenhum = (RadioButton) findviewbyid(r.id.add_budget_radiobutton0); renovacaodiaria = (RadioButton) findviewbyid(r.id.add_budget_radiobutton1);

38 Appendix 33 renovacaosemanal = (RadioButton) findviewbyid(r.id.add_budget_radiobutton2); renovacaomensal = (RadioButton) findviewbyid(r.id.add_budget_radiobutton3); renovacaoanual = (RadioButton) findviewbyid(r.id.add_budget_radiobutton4); renovacaotv0 = (TextView) findviewbyid(r.id.add_budget_textview_renew0); renovacaotv1 = (TextView) findviewbyid(r.id.add_budget_textview_renew1); renovacaotv2 = (TextView) findviewbyid(r.id.add_budget_textview_renew2); renovacaotv3 = (TextView) findviewbyid(r.id.add_budget_textview_renew3); renovacaotv4 = (TextView) findviewbyid(r.id.add_budget_textview_renew4); renovacaonenhum.setonclicklistener(this);

39 Appendix 34 renovacaodiaria.setonclicklistener(this); renovacaosemanal.setonclicklistener(this); renovacaomensal.setonclicklistener(this); renovacaoanual.setonclicklistener(this); renovacaotv0.setonclicklistener(this); renovacaotv1.setonclicklistener(this); renovacaotv2.setonclicklistener(this); renovacaotv3.setonclicklistener(this); renovacaotv4.setonclicklistener(this); renovacaonenhum.setchecked(true); concluidobutton.setonclicklistener(new public void onclick(view v) {

40 Appendix 35 if( budgetvalue.gettext().tostring().trim().length() == 0 budgetname.gettext().tostring().trim().length() == 0 categoryselected.trim().length() == 0 ){ showdialog(constants.dialog_add_budget_empty); else{ try { Date dtocurr = null; if( day!= null && month!= null && year!= null ){ sdf = new SimpleDateFormat("HH"); Date())); int hour = Integer.parseInt(sdf.format(new sdf = new SimpleDateFormat("mm"); Date())); int minute = Integer.parseInt(sdf.format(new sdf = new SimpleDateFormat(Constants.DATETIME_PATTERN); dtocurr =

41 Appendix 36 sdf.parse(string.format(datetime_iso_strmask, year, month, day, hour, minute, 0)); else{ dtocurr = new Date(); droidexpensefacade.addbudget(v.getcontext(), budgetname.gettext().tostring(), Double.parseDouble(budgetValue.getText().toString()), categoryselected, subcategoryselected, dtocurr, renovacao); catch (NumberFormatException e) { Log.e(this.getClass().getName(), e.getmessage()); Toast.makeText(v.getContext(), "Error writing Budget. Contact the system administrator.", Toast.LENGTH_LONG).show(); catch (BusinessException e) { Log.e(this.getClass().getName(), e.getmessage()); Toast.makeText(v.getContext(), "Error writing Budget. Contact the system administrator.", Toast.LENGTH_LONG).show();

42 Appendix 37 catch (ParseException e) { Log.e(this.getClass().getName(), e.getmessage()); Toast.makeText(v.getContext(), "Error writing Budget. Contact the system administrator.", Toast.LENGTH_LONG).show(); MainActivity.LAST_ABA = 2; finish(); ); Button datebutton = (Button) findviewbyid(r.id.add_budget_button_date); datebutton.setonclicklistener(new View.OnClickListener() public void onclick(view v) {

43 Appendix 38 ); dialogdate(); categories = droidexpensefacade.getcategorylist(this); if( categories.size() > 0 ){ Collections.sort(categories, new Comparator<Category>() public int compare(category lhs, Category rhs) { return lhs.getcategoryname().compareto(rhs.getcategoryname()); ); List<String> categoriesnames = new ArrayList<String>();

44 Appendix 39 for( Category category : categories ){ categoriesnames.add(category.getcategoryname()); categoryselected = categories.get(0).getcategoryname(); subcategoryselected = "no"; ArrayAdapter<String> catadapter = new ArrayAdapter<String>(AddBudgetActivity.this, android.r.layout.simple_spinner_dropdown_item, categoriesnames.toarray(new String [categoriesnames.size()])); catadapter.setdropdownviewresource(android.r.layout.simple_spinner_dro pdown_item); // Set this blank adapter to the list view

45 Appendix 40 catspinner.setadapter(catadapter); if( categories.get(0).getsubcategories()!= null && categories.get(0).getsubcategories().size() > 0 ){ List<String> subcategoriesnames = new ArrayList<String>(); subcategoriesnames.add("no"); for( SubCategory subcategory : categories.get(0).getsubcategories() ){ subcategoriesnames.add(subcategory.getsubcategoryname()); ArrayAdapter<String> subcatadapter = new ArrayAdapter<String>(AddBudgetActivity.this, android.r.layout.simple_spinner_dropdown_item,

46 Appendix 41 subcategoriesnames.toarray(new String [subcategoriesnames.size()])); subcatadapter.setdropdownviewresource(android.r.layout.simple_spinner _dropdown_item); // Set this blank adapter to the list view subcatspinner.setadapter(subcatadapter); else{ Toast.makeText(this, "You must add at least one category before creating a budget.", Toast.LENGTH_LONG).show(); protected Dialog oncreatedialog(int id) {

47 Appendix 42 AlertDialog alert; AlertDialog.Builder builder; switch(id) { case Constants.DIALOG_ADD_BUDGET_EMPTY: builder = new AlertDialog.Builder(this); builder.setmessage("the name, value and category of the Budget is required. SubCategory is optional. Want to go back to home screen?").setcancelable(false).setpositivebutton("yes", new DialogInterface.OnClickListener() { public void onclick(dialoginterface dialog, int id) { MainActivity.LAST_ABA = 1; finish(); ).setnegativebutton("no", new DialogInterface.OnClickListener() {

48 Appendix 43 public void onclick(dialoginterface dialog, int id) { //DO NOTHING dialog.cancel(); ); alert = builder.create(); break; default: alert = null; return public void onitemselected(adapterview<?> arg0, View arg1, int arg2, long arg3) {

49 Appendix 44 if( arg0.getid() == R.id.add_budget_spinner_cat ){ categoryselected = (String) arg0.getitematposition(arg2); Category category = null; for( Category categorytmp : categories ){ if( categorytmp.getcategoryname().equals(categoryselected) ){ category = categorytmp; List<String> subcategoriesnames = new ArrayList<String>(); subcategoriesnames.add("no"); for( SubCategory subcategory : category.getsubcategories() ){

50 Appendix 45 subcategoriesnames.add(subcategory.getsubcategoryname()); ArrayAdapter<String> subcatadapter = new ArrayAdapter<String>(AddBudgetActivity.this, android.r.layout.simple_spinner_dropdown_item, subcategoriesnames.toarray(new String [subcategoriesnames.size()])); subcatadapter.setdropdownviewresource(android.r.layout.simple_spinner _dropdown_item); // Set this blank adapter to the list view subcatspinner.setadapter(subcatadapter); else if( arg0.getid() == R.id.add_budget_spinner_subcat ){ subcategoryselected = (String) arg0.getitematposition(arg2);

51 Appendix public void onnothingselected(adapterview<?> arg0) public void onclick(view v) { // CHECK SELECTED switch (v.getid()) { case R.id.add_budget_RadioButton0: renovacaonenhum.setchecked(true); renovacaodiaria.setchecked(false); renovacaosemanal.setchecked(false); renovacaomensal.setchecked(false); renovacaoanual.setchecked(false); renovacao = 0; break;

52 Appendix 47 case R.id.add_budget_RadioButton1: renovacaonenhum.setchecked(false); renovacaodiaria.setchecked(true); renovacaosemanal.setchecked(false); renovacaomensal.setchecked(false); renovacaoanual.setchecked(false); renovacao = 1; break; case R.id.add_budget_RadioButton2: renovacaonenhum.setchecked(false); renovacaodiaria.setchecked(false); renovacaosemanal.setchecked(true); renovacaomensal.setchecked(false); renovacaoanual.setchecked(false); renovacao = 2; break;

53 Appendix 48 case R.id.add_budget_RadioButton3: renovacaonenhum.setchecked(false); renovacaodiaria.setchecked(false); renovacaosemanal.setchecked(false); renovacaomensal.setchecked(true); renovacaoanual.setchecked(false); renovacao = 3; break; case R.id.add_budget_RadioButton4: renovacaonenhum.setchecked(false); renovacaodiaria.setchecked(false); renovacaosemanal.setchecked(false); renovacaomensal.setchecked(false); renovacaoanual.setchecked(true); renovacao = 4; break;

54 Appendix 49 case R.id.add_budget_TextView_renew0: renovacaonenhum.setchecked(true); renovacaodiaria.setchecked(false); renovacaosemanal.setchecked(false); renovacaomensal.setchecked(false); renovacaoanual.setchecked(false); renovacao = 0; break; case R.id.add_budget_TextView_renew1: renovacaonenhum.setchecked(false); renovacaodiaria.setchecked(true); renovacaosemanal.setchecked(false); renovacaomensal.setchecked(false); renovacaoanual.setchecked(false); renovacao = 1; break; case R.id.add_budget_TextView_renew2:

55 Appendix 50 renovacaonenhum.setchecked(false); renovacaodiaria.setchecked(false); renovacaosemanal.setchecked(true); renovacaomensal.setchecked(false); renovacaoanual.setchecked(false); renovacao = 2; break; case R.id.add_budget_TextView_renew3: renovacaonenhum.setchecked(false); renovacaodiaria.setchecked(false); renovacaosemanal.setchecked(false); renovacaomensal.setchecked(true); renovacaoanual.setchecked(false); renovacao = 3; break; case R.id.add_budget_TextView_renew4:

56 Appendix 51 renovacaonenhum.setchecked(false); renovacaodiaria.setchecked(false); renovacaosemanal.setchecked(false); renovacaomensal.setchecked(false); renovacaoanual.setchecked(true); renovacao = 4; break; private void dialogdate() { final Dialog dialog = new Dialog(this); dialog.setcontentview(r.layout.date_layout); dialog.setcancelable(true); dialog.settitle("choose a Date"); dialog.show();

57 Appendix 52 final DatePicker datepicker = (DatePicker) dialog.findviewbyid(r.id.datepicker1); Button btn = (Button) dialog.findviewbyid(r.id.picker_time_button_ok); btn.setonclicklistener(new OnClickListener() { public void onclick(view arg0) { day = datepicker.getdayofmonth(); month = datepicker.getmonth()+1; year = datepicker.getyear(); Toast.makeText(AddBudgetActivity.this, "chosen date: " + day + "/" + month + "/" + year, Toast.LENGTH_SHORT).show(); dialog.cancel();

58 Appendix 53 ); Add category package com.expensemanager.activities; import com.expensemanager.r; import com.expensemanager.facade.droidexpensefacade; import com.expensemanager.util.constants; import android.app.activity; import android.app.alertdialog; import android.app.dialog; import android.content.dialoginterface; import android.os.bundle; import android.view.view;

59 Appendix 54 import android.widget.button; import android.widget.edittext; public class AddCategoryActivity extends Activity { private DroidExpenseFacade droidexpensefacade; /** Called when the activity is first created. public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.add_categ_layout); droidexpensefacade = new DroidExpenseFacade(); final Button concluidobutton = (Button)

60 Appendix 55 findviewbyid(r.id.add_cat_button_done); concluidobutton.setonclicklistener(new public void onclick(view v) { EditText catedittext = (EditText) findviewbyid(r.id.add_cat_edittext_catvalue); if( catedittext.gettext().tostring().trim().length() == 0 ){ showdialog(constants.dialog_add_cat_empty); else{ droidexpensefacade.addcategory(v.getcontext(), catedittext.gettext().tostring()); MainActivity.LAST_ABA = 1;

61 Appendix 56 finish(); protected Dialog oncreatedialog(int id) { AlertDialog alert; AlertDialog.Builder builder; switch(id) { case Constants.DIALOG_ADD_CAT_EMPTY: builder = new AlertDialog.Builder(this); builder.setmessage("the category name is required. Want to go back to home screen?").setcancelable(false)

62 Appendix 57.setPositiveButton("yes", new DialogInterface.OnClickListener() { public void onclick(dialoginterface dialog, int id) { MainActivity.LAST_ABA = 1; finish(); ).setnegativebutton("no", new DialogInterface.OnClickListener() { public void onclick(dialoginterface dialog, int id) { //DO NOTHING dialog.cancel(); ); alert = builder.create(); break; default: alert = null;

63 Appendix 58 return alert;

64 Appendix Database handler package com.expensemanager.helper; import com.expensemanager.util.constants; import android.content.context; import android.database.sqlite.sqlitedatabase; import android.database.sqlite.sqliteopenhelper; import android.util.log; public class DataHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "droidexpense.db"; private static final int DATABASE_VERSION = 13; public DataHelper(Context context) {

65 Appendix 60 super(context, DATABASE_NAME, null, public void oncreate(sqlitedatabase database) { database.execsql(constants.ddl_create_expenses); database.execsql(constants.ddl_create_categories); database.execsql(constants.ddl_create_subcategories); database.execsql(constants.ddl_create_budgets); public void onupgrade(sqlitedatabase db, int oldversion, int newversion) { Log.w(DataHelper.class.getName(), "Upgrading database from

66 Appendix 61 version " + oldversion + " to " + newversion + ", which will destroy all old data"); db.execsql("drop TABLE IF EXISTS " + Constants.TABLE_EXPENSES); db.execsql("drop TABLE IF EXISTS " + Constants.TABLE_CATEGORIES); db.execsql("drop TABLE IF EXISTS " + Constants.TABLE_SUBCATEGORIES); db.execsql("drop TABLE IF EXISTS " + Constants.TABLE_BUDGETS); db.execsql("drop TABLE IF EXISTS " + Constants.TABLE_ACCOUNTS); oncreate(db);

67 Appendix Notification service package com.expensemanager.service; import com.expensemanager.activities.mainactivity; import android.app.notification; import android.app.notificationmanager; import android.app.pendingintent; import android.content.context; import android.content.intent; public class NotificationService public static void sendnotification(context context, String tickertext, String title, String content, int notificationid){ // Create an object of Notification manager

68 Appendix 63 NotificationManager mnotificationmanager = (NotificationManager) context.getsystemservice(context.notification_service); resources int icon = android.r.drawable.stat_sys_warning; // icon from time long when = System.currentTimeMillis(); // notification MainActivity.LAST_ABA=2; Intent notificationintent = new Intent(context, MainActivity.class); PendingIntent contentintent = PendingIntent.getActivity(context, 0, notificationintent, 0); // the next two lines initialize the Notification, using the configurations above Notification notification = new Notification(icon, tickertext, when); notification.setlatesteventinfo(context, title, content, contentintent);

69 Appendix 64 mnotificationmanager.notify(notificationid, notification); Graph package com.expensemanager.activities; import java.io.file; import java.io.fileoutputstream; import java.util.arraylist; import java.util.list; import org.achartengine.chartfactory; import org.achartengine.graphicalview; import org.achartengine.chart.pointstyle; import org.achartengine.model.seriesselection;

70 Appendix 65 import org.achartengine.model.xymultipleseriesdataset; import org.achartengine.model.xyseries; import org.achartengine.renderer.simpleseriesrenderer; import org.achartengine.renderer.xymultipleseriesrenderer; import org.achartengine.renderer.xyseriesrenderer; import org.achartengine.tools.panlistener; import org.achartengine.tools.zoomevent; import org.achartengine.tools.zoomlistener; import com.expensemanager.r; import com.expensemanager.exception.businessexception; import com.expensemanager.facade.droidexpensefacade; import com.expensemanager.holders.totalbymonthholder; import com.expensemanager.util.converter; import android.app.activity;

71 Appendix 66 import android.graphics.bitmap; import android.graphics.color; import android.graphics.bitmap.compressformat; import android.graphics.paint.align; import android.os.bundle; import android.os.environment; import android.util.log; import android.view.view; import android.view.viewgroup.layoutparams; import android.widget.linearlayout; import android.widget.toast; public class ChartActivity extends Activity { public static final String TYPE = "type"; private XYMultipleSeriesDataset mdataset = new

72 Appendix 67 XYMultipleSeriesDataset(); private XYMultipleSeriesRenderer mrenderer = new XYMultipleSeriesRenderer(); private XYSeries mcurrentseries; private XYSeriesRenderer mcurrentrenderer; private String mdateformat; private GraphicalView mchartview; private int index = 0; private DroidExpenseFacade droidexpensefacade;

73 Appendix protected void onrestoreinstancestate(bundle savedstate) { super.onrestoreinstancestate(savedstate); mdataset = (XYMultipleSeriesDataset) savedstate.getserializable("dataset"); mrenderer = (XYMultipleSeriesRenderer) savedstate.getserializable("renderer"); mcurrentseries = (XYSeries) savedstate.getserializable("current_series"); mcurrentrenderer = (XYSeriesRenderer) savedstate.getserializable("current_renderer"); mdateformat = protected void onsaveinstancestate(bundle outstate) { super.onsaveinstancestate(outstate); outstate.putserializable("dataset", mdataset);

74 Appendix 69 outstate.putserializable("renderer", mrenderer); outstate.putserializable("current_series", mcurrentseries); outstate.putserializable("current_renderer", mcurrentrenderer); outstate.putstring("date_format", protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.chart_page); mrenderer.setapplybackgroundcolor(true); mrenderer.setbackgroundcolor(getresources().getcolor(r.color.list_se cond_color)); mrenderer.setaxistitletextsize(22); mrenderer.setxtitle("month"); mrenderer.setytitle("total (Rs)"); mrenderer.setcharttitletextsize(30);

75 Appendix 70 mrenderer.setlabelstextsize(22); mrenderer.setlegendtextsize(24); right mrenderer.setmargins(new int[] { 50, 40, 20, 20 );//top, left, botton, mrenderer.setzoombuttonsvisible(true); mrenderer.setpointsize(10); mrenderer.setcharttitle("chart of Monthly Expenses"); mrenderer.setshowaxes(true); mrenderer.setshowgrid(true); mrenderer.setmarginscolor(color.white); mrenderer.setlabelscolor(color.black); mrenderer.setaxescolor(color.black); )); mrenderer.setgridcolor(getresources().getcolor(r.color.list_main_color String seriestitle = "general " + (mdataset.getseriescount() + 1);

76 Appendix 71 XYSeries series = new XYSeries(seriesTitle); mdataset.addseries(series); mcurrentseries = series; XYSeriesRenderer renderer = new XYSeriesRenderer(); mrenderer.addseriesrenderer(renderer); renderer.setpointstyle(pointstyle.circle); renderer.setcolor(getresources().getcolor(r.color.list_dark_color)); renderer.setfillpoints(true); mcurrentrenderer = renderer; List<TotalByMonthHolder> totais = new ArrayList<TotalByMonthHolder>(); droidexpensefacade = new DroidExpenseFacade(); try { totais = droidexpensefacade.gettotalbymonth(this); catch (BusinessException e1) {

77 Appendix 72 Log.e(this.getClass().getName(), e1.getmessage()); Toast.makeText(this, "[ChartActivity] Error getting total expenditure per month. Contact the system administrator.", Toast.LENGTH_LONG).show(); for( TotalByMonthHolder holder : totais ){ mcurrentseries.add(holder.getmes(), holder.gettotal()); int length = mrenderer.getseriesrenderercount(); for (int i = 0; i < length; i++) { SimpleSeriesRenderer seriesrenderer = mrenderer.getseriesrendererat(i); seriesrenderer.setdisplaychartvalues(true); seriesrenderer.setchartvaluestextsize(30); seriesrenderer.setchartvaluesspacing(25); seriesrenderer.setchartvaluestextalign(align.center);

78 Appendix 73 if (mchartview == null) { LinearLayout layout = (LinearLayout) findviewbyid(r.id.chart_layout); mchartview = ChartFactory.getLineChartView(this, mdataset, mrenderer); mrenderer.setclickenabled(true); mrenderer.setselectablebuffer(100); mchartview.setonclicklistener(new View.OnClickListener() public void onclick(view v) { SeriesSelection seriesselection = mchartview.getcurrentseriesandpoint(); if (seriesselection == null) { else { Toast.makeText(ChartActivity.this, getmonth(seriesselection.getxvalue()) + ", "

79 Appendix 74 + Converter.getDecimalFormat().format(seriesSelection.getValue()), Toast.LENGTH_SHORT).show(); ); mchartview.addzoomlistener(new ZoomListener() { public void zoomapplied(zoomevent e) { String type = "out"; if (e.iszoomin()) { type = "in"; System.out.println("Zoom " + type + " rate " + e.getzoomrate());

80 Appendix 75 public void zoomreset() { System.out.println("Reset");, true, true); mchartview.addpanlistener(new PanListener() { public void panapplied() { System.out.println("New X range=[" + mrenderer.getxaxismin() + ", " + mrenderer.getxaxismax() + "], Y range=[" + mrenderer.getyaxismax() + ", " + mrenderer.getyaxismax() + "]"); ); layout.addview(mchartview, new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

81 Appendix 76 else { mchartview.repaint(); //////////////////////////////////////////////// if (mchartview!= null) { mchartview.repaint(); Bitmap bitmap = mchartview.tobitmap(); try { File file = new File(Environment.getExternalStorageDirectory(), "DroidExpense-Chart" + index++ + ".png"); FileOutputStream output = new FileOutputStream(file); bitmap.compress(compressformat.png, 100, output); catch (Exception e) { e.printstacktrace();

82 Appendix protected void onresume() { super.onresume(); private String getmonth(double monthint){ String mes = null; switch(double.valueof(monthint).intvalue()){ case 1: mes = "January"; break; case 2: mes = "February"; break; case 3:

83 Appendix 78 mes = "March"; break; case 4: mes = "April"; break; case 5: mes = "May"; break; case 6: mes = "June"; break; case 7: mes = "July"; break; case 8: mes = "August"; break;

84 Appendix 79 case 9: mes = "September"; break; case 10: mes = "October"; break; case 11: mes = "November"; break; case 12: mes = "December"; break; return mes;

85 References References 1. "Android Code Analysis". Retrieved June 6, Paul, Ryan (February 24, 2009). "Dream(sheep++): A developer s introduction to Google Android: Ars takes a close look at the technology underlying Google's Linux-based ". Retrieved April 3, "Introducing Fire OS". Retrieved April 3, "Nokia X Platform overview". Retrieved April 3, "Device Compatibility". Retrieved April 3, Paul, Ryan (February 24, 2009). "Dream(sheep++): A developer s introduction to Google Android". ArsTechnica. Retrieved "Philosophy and Goals". Android Open Source Project. Google. Retrieved "Google s iron grip on Android: Controlling open source by any means necessary". ArsTechnica. Retrieved "Announcing the Android 1.0 SDK, release 1". September 9, Retrieved September 21, ArtemRussakovskii (December 9, 2013). "Android (KOT49H) Is Already Rolling Out To All Nexus Devices - Here Are The

86 References OTA ZIP Links For Manual Updating". Android Police. Retrieved 11. "MIPS gets sweet with Honeycomb". Eetimes.com.