Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
RWTH Aachen University Chair of Data Management and Data Exploration Prof. Dr. T. Seidl Proseminar Useful tools for an effcient development of an Android App - The Android SDK Marco Moscher June 2012 Supervision: Dipl.-Ing. Marwan Hassani Declaration of Originality The material in this paper has not previously been submitted for a degree in any University, and to the best of my knowledge contains no material previously published or written by another person except where due to acknowledgement is made in the paper itself. Aachen, June 26, 2012 Contents List of Figures 3 Abstract 5 1 Introduction to Android 1.1 What is Android? . . . . . . . . . . . . . . . . . . . . . . . . . 6 6 2 The Android SDK 2.1 Using the Android SDK . . . . . . . . . . . 2.2 Explaining the fundamental principles . . . 2.2.1 Design a layout . . . . . . . . . . . . 2.2.2 Collaborate layout and functionallity 2.3 Debugging an App using SDK features . . . 2.3.1 DDMS in chorus with LogCat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 9 10 10 12 15 17 3 Advantages of the Android SDK features 20 Bibliography 21 A Appendix 22 A.1 Behind the scenes (Dalvik VM) . . . . . . . . . . . . . . . . . 22 B List of Abbreviations 24 C Source code listings 26 C.1 Java source code . . . . . . . . . . . . . . . . . . . . . . . . . 26 C.2 XML (layout) source code . . . . . . . . . . . . . . . . . . . . 36 3 List of Figures 1.1 Global market share of different mobile OS . . . . . . . . . . . 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 ContactAndCameraExplorer screen shots . . . . . . . . . . . SDK-Manager [8] . . . . . . . . . . . . . . . . . . . . . . . . GUI-Designer compared to XML-Editor . . . . . . . . . . . startActivity() Intent-Object transmitting diagram . . . . . startActivityForResult() Intent-Object transmitting diagram The Eclipse standard debug perspective . . . . . . . . . . . . The Eclipse DDMS perspective . . . . . . . . . . . . . . . . LogCat-View in Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 8 9 11 12 14 16 17 18 A.1 Android component stack [9] . . . . . . . . . . . . . . . . . . . 22 4 Abstract The following article will introduce the Android-SDK for developing Apps for the Android-OS. It will shortly mention the Android-OS, describe how to integrate the SDK in the development environment and mainly focus on the features included by the ADT-Plugin for Eclipse. Especially it will give an introduction in using the Designer and Debugger. For example it will be illustrate how to use the LogCat-Class in chourse with the Debugger for gathering information about a running App. Furthermore the collaboration between layout and functionality will be explained shortly and a introduction in the fundamental programming principles for Android with using Java is given. 5 Chapter 1 Introduction to Android 1.1 What is Android? Android is an operating system (OS) for mobile and hand-held systems. The Android OS was founded in the year 2003 by Andy Rubin and acquired by Google in 2005. Until now the OS is developed by the “Open Handset Alliance” - with Google acting as the main driver [2]. The Android OS is based on the open-source Linux-Kernel and implemented in Java, so everybody is able to contribute to its future. As being licensed under GNU GPLv2 [2] Android SDK is free of charge. Figure 1.1: Global market share of different mobile OS As seen in Figure 1.1 today Android is the leading OS on global mobile device market with 56,1% followed by Apple with the iPhone-OS reaching 6 1.1. What is Android? 7 22,6% [4]. For that reason Apps for the Android OS could reach about 100% more users in contrast to an iPhone App[1]. Chapter 2 The Android SDK The Android SDK will be introduced and demonstrated by two tools coming with it: - Graphical-User-Interface (GUI) Designer - Dalvik-Debug-Monitor-Server (DDMS) These tools along with other important features for implementing, designing and debugging an App, such as Activities, Intents, the ADB, Emulator and LogCat will be explained using the example of a simple App called “ContactAndCameraExplorer”. Figure 2.1: ContactAndCameraExplorer screen shots As shown in the figure 2.1 the App is divided in four different App regions, called “Activities”. On its right the App shows the possibility of accessing the contacts and with “tapping” on an entry, the option to edit e.g., Names and Adresses. On the left it communicates with the built-in camera and handles the bitmap-data, committed by the camera itself, of a taken photo for displaying it as a thumbnail. 8 2.1. Using the Android SDK 2.1 9 Using the Android SDK In order to enable users to participate with the SDK, which includes all API (Application-Programming-Interface) for the currently known Android-Platform versions (1.1 up to 4.0.x) and platform specified compiling/linking tools, Google rolls out the “Android SDK Manager”. This Manager (Figure 2.2) makes it possible to install and manage the necessary tools in a simple way. Furthermore a Java- Figure 2.2: SDK-Manager [8] Development-Kit (JDK) and maybe an Integrated-Development-Environment (IDE) are needed. Over the course of this article I will use the Eclipse IDE with the “Android Development Tools”- Plugin (ADT) designed by Google, especially for Eclipse [5]. This plugin extends the capabilities of the IDE by providing a designer to create a GUI and a debugger to debug an App within the IDE, e.g. by using the DDMS perspective. 2.2. Explaining the fundamental principles 2.2 10 Explaining the fundamental principles A typical Android App consists of classes and layouts using each other. Classes are used to implement the program logic, and create the App basic functionality. These classes use the layout to display information on the screen and to react on user interactions. Usually every class implements one layout, e.g. the “ContactAndCameraExplorer” consists of four class files, where each one uses a different layout file. In this case a class is called Activity. For that reason Activity often means the collaboration between a class (extending the Activity class) and a layout file. Utilizing the SDK in chorus with the ADT plugin a developer does not have to take care of compiling and linking the created layouts. The SDK-Tool aapt (Android-Asset-Packing-Tool) will automatically create the needed Java code of the layout files and merge them into one class called “R”. For using a layout inside a class file the R class has to be imported in the header, as shown in listing 2.1, line 3. Listing 2.1: improting the R class - MainActivity.java (l. 1-3) 1 package mm . dev . contact ; 2 3 import mm . dev . contact . R ; As a consequence a layout file is only used to “describe” the GUI and is written in the Extensible-Markup-Language (XML), listing 2.2. 2.2.1 Design a layout As mentioned before the GUI is described with XML which uses different tagnames to identify the type of an element and a couple of predefined attributes, beginning with the prefix “android:“, to set the different styles. These attributes are nearly the same as the ones used in “Cascading Style Sheets” (CSS) for “styling” a HTML-Site. Listing 2.2: Contact-Example Button - main.xml (l. 8-18) 1 2 3 4 5 6 7 8 9 < Button android:id = " @ + id / contactButton " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " a n d r o i d : l a y o u t _ m a r g i n B o t t o m = " 40 dip " android:onClick = " onChoose " android:text = " @string / bt_init_contact " android:textSize = " 14 pt " android:padding = " 10 dip " 2.2. Explaining the fundamental principles an dr oi d: ba ck gr ou nd = " #506495 ED " 10 11 11 /> Listing 2.2 is an extract of the initial Activity layout and indicates the “ContactExmaple”-Button (compare Figure 2.1). This GUI element receives an ID “contactButton”, to access its information in the further program logic. Additionally e.g., a background color, a padding and an event handler (onChoose() method ) for the onClick-Event are described. Futhermore the SDK provides others input events such as onLongClick(), onFocusChange() and more [7]. As demonstrated in Listing 2.2 there is the possibility to create all App layouts directly in XML (Figure 2.3, right side). Even more it is practicable in another, easier, way by using the GUI-Designer with its What-You-See-Is-What-You-Get (WYSIWYG) Editor (Figure 2.3, left side). Sometimes it can be useful comparing both methods. First drag and drop all needed elements into the layout grid with the GUI-Designer and then finally define its detailed styles in the XML file. Therefore a switch between the designer and the texteditor is always possible. Figure 2.3: GUI-Designer compared to XML-Editor To obtain functionality and interactions within the GUI, the next part presents how to set a layout as the currently window design and how to interact with the mentioned events. 2.2. Explaining the fundamental principles 2.2.2 12 Collaborate layout and functionallity As mentioned before a class file has the ability to access a layout by importing the R-class (cf. Section 2). This class includes all defined ID’s, strings, arrays and other values created within the layout, separated by its category type. R.id.button_contact (category type "id") R.layout.main (category type "layout") Each class that extends the Activity class, can easily set its GUI by using the function setContentView(), passing the layout as parameter by using the R class. Normally this function is placed in the onCreate() method and initiates the layout, as shown in Listing 2.3. Listing 2.3: setContentView() - MainActivity.java (l. 19-26) 1 2 3 4 5 protected void onCreate ( Bundle sa ve dI ns ta nc eS ta te ) { .. ... setContentView ( R . layout . main ) ; } To interact and switch between different GUI’s which is often associated with user interaction - such as a button onClick-Event - the Activity class implements methods like startActivity() and startActivityForResult(). These methods are both initializing another Activity class. public class MainActivity extends Activity { .... ..... public void onChoose( final View button ) { ... .... startAcivity( new Intent( this, ContactExplorerActivity.class ) ); .. } ... } public class ContactExplorerActivity extends ListActivity { ... public void onCreate( Bundle savedInstanceState ) { ... ..... .. } ... } Figure 2.4: startActivity() Intent-Object transmitting diagram Figure 2.4 shows the onChoose() method – onClick-Event for both buttons in the mainLayout (compare Listing 2.2) - calling the startActivity() method for initializing a new class (ContactExplorerActivity) and furthermore another GUI. 2.2. Explaining the fundamental principles 13 Both - startActivity() and startActivityForResult() - methods need an IntentObject as parameter, so that every Activity is aware of its parent class and intention of call (Intent). Therewith and by adding parameters to the Intent-Object, the framework offers the possibility to transfer information between different classes. Listing 2.4: setting Intent parameters - ContactExplorerActivity.java (l. 8289) Intent co n t ac t I nf o r m at i o ns = new Intent ( this , C o n t a c t I n f o r m a t i o n A c t i v i t y . class ) ; c on t a ct I n fo r m a ti o n s . putExtra ( " referenceID " , position ) ; c on t a ct I n fo r m a ti o n s . putExtra ( " vorname " , forename ) ; c on t a ct I n fo r m a ti o n s . putExtra ( " nachname " , surname ) ; 1 2 3 4 5 this . s t a r t A c t i v i t y F o r R e s u l t ( c on t a ct I n fo r m at i o ns , EDIT _CONTA CT_CAL L ) ; 6 The transmitted Intent-Object in Listing 2.4 which communicates between the ContactExplorerActivity and ContactInformationActivity classes includes three parameters, two string-values (vorname, nachname) and an integer-value (referenceID), to transfer needed information. Accessing these parameters in the child class (ContactInformationActivity) is very easy, as shown in Listing 2.5. Listing 2.5: accessing intent parameters - ContactInformationActivity.java (l. 17-34) 1 2 protected void onCreate ( Bundle sa ve dI ns ta nc eS ta te ) { ... 3 // reading data committed by partent activty - through the intent . final Bundle data = getIntent () . getExtras () ; 4 5 6 this . referenceID = data . getInt ( " referenceID " ) ; 7 8 .... 9 10 } In case an Activity class is called with startActivityForResult() - compare figure 2.5 - the affected class has to signal finishing its work flow by calling the finish() method to commit the result intent. Previously, it has to create this intent object, setting its values like in Listing 2.4, and combine this with a result-status-code in the setResult() method. So furthermore the child class can signal its parent class which type of result is transmitted, by setting a significant result-status-code. Thereby the parent class has the ability to interact in a conform way with the result values. To ensure that all these information get transmitted, to indicate the point of loosing information or to eliminate mistakes, the SDK combined with the ADT 2.2. Explaining the fundamental principles 14 public class ContactExplorerActivity extends ListActivity { .... ..... protected void onListItemClick( ListView l, View v, int position, long id) { ... Intent contactInformations = new Intent(...); this.startActivityForResult( contactInformations , EDIT CONTACT CALL); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { ... if( requestCode == EDIT CONTACT CALL ){ public class ContactExplorerActivity extends ListActivity { if( resultCode == Activity.RESULT OK ) { ... //save new contact data, transmitted by data public void onCreate( Bundle savedInstanceState ) { }else{ .. } ... } ..... } ... } } public void saveAndClose( final View view ) { ... Intent changes = new Intent(); //putting data to the result intent changes.putExtra(”referenceID”, this.referenceID); ... setResult(RESULT OK, changes); finish(); } ... } Figure 2.5: startActivityForResult() Intent-Object transmitting diagram plugin for Eclipse brings tools for debugging an App and logging information. 2.3. Debugging an App using SDK features 2.3 15 Debugging an App using SDK features The SDK offers two different types of options for debugging and observing a running App to the developer. Firstly the direct debugging on a mobile device running the Android-OS and secondly the Emulator for executing an App in an emulated OS using a desktop PC. For using a real device the USB debugging option (Settings → Developer options → USB debugging) and the privilege to install unsigned Apps (Settings → Security → Unknown sources) are necessary. Otherwise to use an emulator for simulating a running device a AndroidVirtual-Device (AVD) image is needed. This image can be created with AVDManager (Windows → AVD Manager ), which comes simultaneously with the SDK-Manager (cf. Section 2.1). For debugging an App within the emulator the correct AVD has to be selected in the options dialog (Run → Debug Configurations.. → Targets → Deployment Target Selection Mode → Automatic). By default, if a mobile device is connected, the IDE will use this external device. With clicking on the Bug-Button in the IDE bar the debugger will start its routine. The App gets compiled, transferred and installed on the Android device automatically. At the same time the ADB connects to the debugging server running on the device and supplies information, e.g the log trace (cf. Section 2.3.1). By default Eclipse offers a “Debug” perspective (Figure 2.6) for the standard debugging options. (Window → Open Perspective → Debug) 2.3. Debugging an App using SDK features Figure 2.6: The Eclipse standard debug perspective 16 2.3. Debugging an App using SDK features 2.3.1 17 DDMS in chorus with LogCat An even more complex debugging perspective is the DDMS, Figure 2.7. It offers some more features than the debug perspective that typically comes with Eclipse. In addition it is possible to capture screen shots, gather heap or stack information, to emulate incoming calls, SMS and to fake the current geographic position (GPS). Figure 2.7: The Eclipse DDMS perspective In chorus with the DDMS it is handy to use the SDK Log class. The Log class offers the possibility to throw an error/warning combined with a message out of the running App. These can be separated by different error-levels – verbose 2.3. Debugging an App using SDK features 18 (lowest priority) up to silent (highest) – by using the right methods. In Figure 2.8 the App throws 18 errors at debug (d()-methode →d = debug) and with warning level. The LogCat tool now dumps all thrown errors into a log trace which can be recovered via the LogCat-View (Windows → Show View → LogCat) docked into the DDMS perspective. Figure 2.8: LogCat-View in Eclipse In the example App the Log class is used to observe either entering or leaving a method and even more it logs values getting transmitted between different activities using the Intent-Object, compare the shown Listings 2.6 - 2.8 below. Listing 2.6: logging method calls - MainActivity.java (l. 19-26) 1 2 3 4 protected void onCreate ( Bundle sa ve dI ns ta nc eS ta te ) { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering onCreate () " ) ; ... } Listing 2.7: logging transmitted values - CameraActivty.java (l.37-54) 1 2 3 4 requestCode , int resultCode , Intent data ) { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering onActivityResult () " ) ; Log . d ( MainActivity . MM_INFORMATION , " requestCode : ’" + requestCode + " ’, resultCode : ’" + resultCode + " ’" ) ; ... } 2.3. Debugging an App using SDK features Listing 2.8: throw warings - ContactExplorerActivity.java (l. 61-93) 1 2 3 4 5 6 7 protected void onListItemClick ( ListView l , View v , int position , long id ) { .. if ( names . length >= 2 ) { .... } else { Log . w ( MainActivity . MM_WARNING , this . getClass () . getSimpleName () + " : " + " Current contact [ ’ " + item + " ’] has no surname , splitting and accessing the array would cause an Error ! " ) ; } 8 9 } 19 Chapter 3 Advantages of the Android SDK features In conclusion the Android SDK is a very powerful conjunction of tools and functions for inventing and writing Android Apps. Beginning with a simple installation using the SDK-Manger (cf. Section 2.1) along with many new perspectives and functions coming with the ADT plugin in Eclipse (cf. Section 2.2) until at least the debugging suite (cf. Section 2.3), the SDK supplies many features for a better work flow. For example the programmer does not have to manage and organize the assets or the project internal linking of files. Furthermore it offers many “ready-to-run” Sample-Projects (File → New → Project → Android → Android Sample Project) to become acquainted with SDK and Framework. So even for the first basic program you do not have to have any knowledge about programming Java code or knowing the Android basics - easily create it and “Try & Error” the App. If you are not interested in developing in an IDE, Android also bids the option to use the command-line tools which are even more inefficient [6]. At least it should be mentioned that all features include by the Android SDK and even the Eclipse IDE are open-source tools and free of any charge. This is the, in my opinion, a major point for using Android. In contrast to the famous iPhone there is no need for any budget to invent an App for Android. If you are even interested in developing an iPhone OS App you need to have a Mac-Book, the X-Code IDE, and for sharing your App a developer-license for 99$ a year [1]. So as a result the Android SDK is a powerful development kit for costless and efficient developing Apps for the Android OS offered by Google. 20 Bibliography [1] Apple. Mac developer Program. May 2012. [2] W. Article. Android (operating system). May 2012. [3] A. Becker. Android 2 Grundlagen und Programmierung. dpunkt-Verl, Heidelberg, 2010. [4] Gartner. Gartner Says Worldwide Sales of Mobile Phones Declined 2 Percent in First Quarter of 2012; Previous Year-over-Year Decline Occurred in Second Quarter of 2009. May 2012. [5] Google. ADT Plugin for Eclipse, Android Developers. May 2012. [6] Google. Building and Running from the Command Line. May 2012. [7] Google. Input Events. May 2012. [8] Google. sdk manager packages.png PNG-Grafik. May 2012. Direct link: http://developer.android.com/images/sdk_manager_ packages.png. [9] Google. system-architecture.jpg JPEG-Grafik. May 2012. Direct link: http://developer.android.com/images/ system-architecture.jpg. [10] Google. Using DDMS, Android Developers. May 2012. [11] Google. What is Android?, Android Developers. May 2012. 21 Appendix A Appendix A.1 Behind the scenes (Dalvik VM) As already mentioned before in the article the Android OS uses the Linux-Kernel as the base competent of its OS in the component stack. (cf. Section 1) Figure A.1: Android component stack [9] Building up on this Linux-Kernel, which acts as an abstraction layer between 22 A.1. Behind the scenes (Dalvik VM) 23 the hardware and the rest of the software stack, there will be the Linux typically libraries and the Android-Runtime layer. The Android-Runtime layer implements the Dalvik Virtual Machine, which is used to execute and observed every Android App in the Android-OS. The Dalvik Virtual Machine (DVM) was especially developed and customized for the Android OS to replace the standard Java Virtual Machine - which is used to execute the Java bytecode of an Java application – with a better VM bringing more performance and resource-efficiency on devices with low-memory and relatively slow microprocessors. In case of this performance increase, every App on the Android OS gets granted a single DVM-Instance. This increases the security enormously, because no App can access the registers/RAM allocated to an other running App which prevents memory injections. Futhermore theAndroid-Runtime layer is followed by the Application Framework and Application Layer so that every Android App which is executed in the Dalvik VM (Runtime Layer) has the ability to access the core methods of the Application Framework. This Application Framework offers the ability to use standard methods, e.g. the Window-Manager, Location-Manager or Telephony-Manger. The ability to access these features in a “programmatic simple way” is provided by the Android Software Development Kit, which was explained in the article. Appendix B List of Abbreviations ADB Android-Debug-Bridge ADT Android Development Tools AVD Android-Virtual-Device API Application-Programming-Iterface CSS Cascading-Style-Sheets DDMS Davlik-Debug-Monitor-Server DVM Dalvik-Virtual-Machine GNU GPL GNU general public license GUI Graphical-User-Iintrace GPS global positioning system HTML hypertext markup language ID identifier IDE integrated development environment JDK java development kit OS operating system SDK Software-Development-Kit SMS short message service USB universal serial bus 24 APPENDIX B. LIST OF ABBREVIATIONS VM virtual machine WYSIWYG What-You-See-Is-What-You-Get XML Extensible-Markup-Language 25 Appendix C Source code listings C.1 Java source code Listing C.1: MainActivity.java 1 package mm . dev . contact ; 2 3 4 5 6 7 8 9 import import import import import import import mm . dev . contact . R ; android . app . Activity ; android . content . Intent ; android . os . Bundle ; android . util . Log ; android . view . View ; android . view . Window ; 10 11 public class MainActivity extends Activity { 12 13 14 15 /* Debbuging TAGS */ public static final String MM_WARNING = " mm . dev . WARNINGS " ; public static final String MM_INFORMATION = " mm . dev . INFORMATION " ; 16 17 18 19 20 21 22 23 24 25 @Override protected void onCreate ( Bundle sa ve dI ns ta nc eS ta te ) { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering onCreate () " ) ; super . onCreate ( sa ve dI ns ta nc eS ta te ) ; // remove Widget - Titlebar this . r e q u e s t W i n d o w F e a t u r e ( Window . FEATURE_NO_TITLE ) ; setContentView ( R . layout . main ) ; } 26 27 public void onChoose ( final View button ) { 26 C.1. Java source code 27 Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering onChoose () " ) ; 28 29 // switching between both possible buttons . switch ( button . getId () ) { case R . id . contactButton : // launche the contact - explorer activity Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Starting ContactExplorerActivity "); startActivity ( new Intent ( this , C o n t a c t E x p l o r e r A c t i v i t y . class ) ) ; break ; 30 31 32 33 34 35 36 37 case R . id . cameraButton : // launche the camera activity Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Starting CameraActivity "); startActivity ( new Intent ( this , CameraActivity . class ) ); break ; 38 39 40 41 42 43 default : Log . w ( MainActivity . MM_WARNING , this . getClass () . getSimpleName () + " : " + " undefind Button - ID [ ’ " + button . getId () + " ’] was committed ! " ) ; break ; 44 45 46 } 47 48 } 49 50 51 } C.1. Java source code 28 Listing C.2: CameraActivity.java 1 package mm . dev . contact ; 2 3 4 5 6 7 8 9 10 11 12 13 import import import import import import import import import import import mm . dev . contact . R ; android . app . Activity ; android . content . Intent ; android . graphics . Bitmap ; android . os . Bundle ; android . util . Log ; android . view . View ; android . view . Window ; android . widget . ImageView ; android . widget . TextView ; android . widget . Toast ; 14 15 public class CameraActivity extends Activity { 16 17 private static final int C A M E R A _ A C T I V I T Y _ C A L L = 1911; 18 19 20 21 22 23 24 25 26 27 @Override protected void onCreate ( Bundle sa ve dI ns ta nc eS ta te ) { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering onCreate () " ) ; // TODO Auto - generated method stub super . onCreate ( sa ve dI ns ta nc eS ta te ) ; // remove Widget - Titlebar this . r e q u e s t W i n d o w F e a t u r e ( Window . FEATURE_NO_TITLE ) ; setContentView ( R . layout . camera_view ) ; } 28 29 30 31 32 public void takePicture ( final View view ) { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering takePicture () " ) ; Intent c a m e r a R e s p o n s e I n t e n t = new Intent ( android . provider . MediaStore . A C T I O N _ I M A G E _ C A P T U R E ) ; s t a r t A c t i v i t y F o r R e s u l t ( cameraResponseIntent , CAMERA_ACTIVITY_CALL ); 33 34 } 35 36 37 38 39 @Override protected void onActivityResult ( int requestCode , int resultCode , Intent data ) { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering onActivityResult () "); Log . d ( MainActivity . MM_INFORMATION , " requestCode : ’" + requestCode + " ’, resultCode : ’" + resultCode + " ’" ) ; C.1. Java source code 29 40 if ( requestCode == C A M E R A _ A C T I V I T Y _ C A L L ) { if ( resultCode == Activity . RESULT_OK ) { // get the transmitted bitmap data and load it into the image view Bitmap createdImage = ( Bitmap ) data . getExtras () . get ( " data " ) ; ImageView activ ityIma geView = ( ImageView ) findViewById ( R . id . cameraImage ) ; acti vityIm ageVi ew . setImageBitmap ( createdImage ) ; TextView label = ( TextView ) findViewById ( R . id . pictureHeadline ) ; label . setText ( R . string . tx_taken_picture ) ; } else { Log . w ( MainActivity . MM_WARNING , this . getClass () . getSimpleName () + " : " + " Unkown resultCode [ ’ " + resultCode + " ’] no Operation defined . " ) ; Toast . makeText ( this , " Please take an new picture ! " , Toast . LENGTH_LONG ) . show () ; } } 41 42 43 44 45 46 47 48 49 50 51 52 53 } 54 55 } C.1. Java source code 30 Listing C.3: ContactExplorerActivity.java 1 package mm . dev . contact ; 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import import import import import import import import import import import import import import import java . util . ArrayList ; mm . dev . contact . R ; android . app . Activity ; android . app . ListActivity ; android . content . ContentResolver ; android . content . Intent ; android . database . Cursor ; android . os . Bundle ; android . provider . ContactsContract ; android . util . Log ; android . view . View ; android . view . Window ; android . widget . ArrayAdapter ; android . widget . ListView ; android . widget . Toast ; 18 19 public class C o n t a c t E x p l o r e r A c t i v i t y extends ListActivity { 20 21 22 private static final int E DIT_CO NTACT_ CALL = 2511; private ArrayAdapter < String > contactAdapter = null ; 23 24 25 26 27 28 29 30 /* * Called when the activity is first created . */ @Override public void onCreate ( Bundle s av ed In st an ce St at e ) { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering onCreate () " ) ; super . onCreate ( sa ve dI ns ta nc eS ta te ) ; // remove Widget - Titlebar this . r e q u e s t W i n d o w F e a t u r e ( Window . FEATURE_NO_TITLE ) ; 31 32 setContentView ( R . layout . contact_overview ) ; 33 34 ArrayList < String > myContacts = new ArrayList < String >() ; 35 36 37 38 // Accessing the contacts and save them into the myContacts - ArryList ContentResolver cr = g et Con te nt Re so lv er () ; Cursor zeiger = cr . query ( ContactsContract . Contacts . CONTENT_URI , null , null , null , null ) ; 39 40 41 42 if ( zeiger . getCount () > 0 ) { while ( zeiger . moveToNext () ) { String contactName = zeiger . getString ( zeiger . getColumnIndex ( ContactsContract . Contacts . C.1. Java source code DISPLAY_NAME ) ) ; if ( contactName != null && ! myContacts . contains ( contactName ) ) { myContacts . add ( contactName ) ; } 43 44 45 } Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Conacts successfull read " ) ; 46 47 } 48 49 contactAdapter = new ArrayAdapter < String >( this , android . R . layout . simple_list_item_1 , myContacts ); // sorting the contacts contactAdapter . sort ( null ) ; // Connect the ListeView - View to the Adapter setListAdapter ( contactAdapter ) ; 50 51 52 53 54 55 56 57 58 } 59 60 61 62 @Override protected void onListItemClick ( ListView l , View v , int position , long id ) { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering onListItemClick () " ) ; 63 64 String item = ( String ) getListAdapter () . getItem ( position ) ; 65 66 67 68 String [] names = item . split ( " " ) ; String forename = names [0]; String surname = " " ; 69 70 71 72 73 74 75 76 77 78 31 if ( names . length >= 2 ) { if ( names . length > 2) for ( int i = 1; i < names . length ; i ++ ) { surname += names [ i ]; if ( i < names . length -1 ) surname += " " ; } else surname = names [1]; } else { Log . w ( MainActivity . MM_WARNING , this . getClass () . getSimpleName () + " : " + " Current contact [ ’ " + item + " ’] has no surname , splitting and accessing the array would cause an Error ! " ) ; } C.1. Java source code 32 79 80 81 Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Starting C o n t a c t I n f o r m a t i o n A c t i v i t y and commit contact information within the Intent " ) ; 82 83 Intent co n t ac t I nf o r ma t i o ns = new Intent ( this , C o n t a c t I n f o r m a t i o n A c t i v i t y . class ) ; c on t a ct I n fo r m a ti o n s . putExtra ( " referenceID " , position ) ; c on t a ct I n fo r m a ti o n s . putExtra ( " vorname " , forename ) ; c on t a ct I n fo r m a ti o n s . putExtra ( " nachname " , surname ) ; 84 85 86 87 88 this . s t a r t A c t i v i t y F o r R e s u l t ( c on t a ct I n fo r m at i o ns , EDIT _CONTA CT_CAL L ) ; 89 90 91 92 93 } 94 95 96 97 98 @Override protected void onActivityResult ( int requestCode , int resultCode , Intent data ) { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering onActivityResult () " ) ; Log . d ( MainActivity . MM_INFORMATION , " requestCode : ’" + requestCode + " ’, resultCode : ’" + resultCode + " ’" ) ; 99 100 101 102 103 104 105 106 107 108 109 110 111 112 if ( requestCode == ED IT_CON TACT_C ALL ) { // Contact was edited if ( resultCode == Activity . RESULT_OK ) { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Activity . RESULT_OK -> saving changes " ) ; // prepare new name String name = data . getStringExtra ( " vorname " ) + " " + data . getStringExtra ( " nachname " ) ; int pos = data . getIntExtra ( " referenceID " , -1) ; if ( pos > 0 && this . contactAdapter != null ) { contactAdapter . remove ( ( String ) getListAdapter () . getItem ( pos ) ) ; contactAdapter . insert ( name , pos ) ; contactAdapter . sort ( null ) ; } else { Log . d ( MainActivity . MM_WARNING , this . getClass () . getSimpleName () + " : " + " referenceID was C.1. Java source code transmitted - contact couldn ’t be saved " ) ; } 113 114 115 Toast . makeText ( this , " Contact saved " , Toast . LENGTH_LONG ) . show () ; 116 } 117 } 118 119 // TODO Auto - generated method stub super . onActivityResult ( requestCode , resultCode , data ) ; 120 121 } 122 123 @Override protected void onResume () { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering onResume () " ) ; // TODO Auto - generated method stub super . onResume () ; 124 125 126 127 128 129 } 130 131 132 133 134 135 } 33 C.1. Java source code 34 Listing C.4: ContactInformationActivity.java 1 package mm . dev . contact ; 2 3 4 5 6 7 8 9 10 import import import import import import import import mm . dev . contact . R ; android . app . Activity ; android . content . Intent ; android . os . Bundle ; android . util . Log ; android . view . View ; android . view . Window ; android . widget . EditText ; 11 12 public class C o n t a c t I n f o r m a t i o n A c t i v i t y extends Activity { 13 14 private int referenceID = 0; 15 16 17 18 19 20 21 22 23 @Override protected void onCreate ( Bundle sa ve dI ns ta nc eS ta te ) { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering onCreate () " ) ; // TODO Auto - generated method stub super . onCreate ( sa ve dI ns ta nc eS ta te ) ; // remove Widget - Titlebar this . r e q u e s t W i n d o w F e a t u r e ( Window . FEATURE_NO_TITLE ) ; setContentView ( R . layout . contact_detail ) ; 24 // reading data committed by partent activty - through the intent . final Bundle data = getIntent () . getExtras () ; 25 26 27 this . referenceID = data . getInt ( " referenceID " ) ; 28 29 // setting value of Fore - and Surname - Field . (( EditText ) this . findViewById ( R . id . editVorname ) ) . setText ( data . getString ( " vorname " ) ) ; (( EditText ) this . findViewById ( R . id . editNachname ) ) . setText ( data . getString ( " nachname " ) ) ; 30 31 32 33 34 } 35 36 37 public void saveAndClose ( final View view ) { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering saveAndClose () "); 38 39 40 41 Intent changes = new Intent () ; // putting data to the result intent changes . putExtra ( " referenceID " , this . referenceID ) ; C.1. Java source code changes . putExtra ( " vorname " , (( EditText ) this . findViewById ( R . id . editVorname ) ) . getText () . toString () ) ; changes . putExtra ( " nachname " , (( EditText ) this . findViewById ( R . id . editNachname ) ) . getText () . toString () ) ; 42 43 44 Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " setting result status : RESULT_OK and committing intent data " ) ; setResult ( RESULT_OK , changes ) ; finish () ; 45 46 47 } 48 49 50 51 @Override public void onBackPressed () { Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " Entering onBackPressed () " ) ; // TODO Auto - generated method stub super . onBackPressed () ; 52 53 54 55 56 57 Log . d ( MainActivity . MM_INFORMATION , this . getClass () . getSimpleName () + " : " + " setting result status : RESULT_CANCELED " ) ; setResult ( RESULT_CANCELED , null ) ; finish () ; 58 59 60 } 61 62 63 35 } C.2. XML (layout) source code C.2 36 XML (layout) source code Listing C.5: AndroidManifestxml 1 2 3 4 5 <? xml version = " 1.0 " encoding = " utf -8 " ? > < manifest xmlns:android = " http: // schemas . android . com / apk / res / android " package = " mm . dev . contact " a nd r o id : v e rs i o nC o d e = " 1 " a nd r o id : v e rs i o nN a m e = " 1.0 " > 6 7 8 9 < uses - sdk a n d r o i d : m i n S d k V e r s i o n = " 11 " / > < uses - permission android:name = " android . permission . READ_CONTACTS " / > < uses - permission android:name = " android . permission . CAMERA " /> 10 11 12 13 14 15 16 < application android:icon = " @drawable / ic_launcher " android:label = " @string / app_name " > < activity android:name = " MainActivity " > < intent - filter > < action android:name = " android . intent . action . MAIN " / > 17 18 19 20 21 22 23 < category android:name = " android . intent . category . LAUNCHER " / > </ intent - filter > </ activity > < activity android:name = " C o n t a c t E x p l o r e r A c t i v i t y " android:label = " @string / app_name " > </ activity > < activity android:name = " C o n t a c t I n f o r m a t i o n A c t i v i t y " > < / activity > < activity android:name = " CameraActivity " > </ activity > 24 25 </ application > 26 27 </ manifest > C.2. XML (layout) source code Listing C.6: main.xml 1 2 3 4 5 6 <? xml version = " 1.0 " encoding = " utf -8 " ? > < LinearLayout xmlns:android = " http: // schemas . android . com / apk / res / android " a n d r o i d : l a y o u t _ w i d t h = " match_parent " a n d r o i d : l a y o u t _ h e i g h t = " match_parent " android:gravity = " cente r_hori zontal | center_vertical " a nd r o id : o r ie n t at i o n = " vertical " > 7 8 9 10 11 12 13 14 15 16 17 18 < Button android:id = " @ + id / contactButton " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " a n d r o i d : l a y o u t _ m a r g i n B o t t o m = " 40 dip " android:onClick = " onChoose " android:text = " @string / bt_init_contact " android:textSize = " 14 pt " android:padding = " 10 dip " an dr oi d: ba ck gr ou nd = " #506495 ED " /> 19 20 21 22 23 24 25 26 27 28 29 30 < Button android:id = " @ + id / cameraButton " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " a n d r o i d : l a y o u t _ m a r g i n T o p = " 40 dip " android:text = " @string / bt_init_camera " android:onClick = " onChoose " android:textSize = " 14 pt " android:padding = " 10 dip " an dr oi d: ba ck gr ou nd = " #506495 ED " /> 31 32 </ LinearLayout > 37 C.2. XML (layout) source code Listing C.7: Camera-View.xml 1 2 3 4 5 <? xml version = " 1.0 " encoding = " utf -8 " ? > < LinearLayout xmlns:android = " http: // schemas . android . com / apk / res / android " a n d r o i d : l a y o u t _ w i d t h = " match_parent " a n d r o i d : l a y o u t _ h e i g h t = " match_parent " android:gravity = " cente r_hori zontal " > 6 7 8 9 < TableLayout a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " match_parent " > 10 11 12 13 14 < TableRow android:id = " @ + id / tableRow2 " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " > 15 16 17 18 19 20 21 22 23 24 25 < Button android:id = " @ + id / button1 " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " a n d r o i d : l a y o u t _ m a r g i n T o p = " 30 dip " a n d r o i d : l a y o u t _ m a r g i n B o t t o m = " 20 dip " android:onClick = " takePicture " android:text = " @string / bt_take_picture " android:padding = " 5 dip " an dr oi d: ba ck gr ou nd = " #506495 ED " / > 26 27 </ TableRow > 28 29 30 31 32 33 < TableRow android:id = " @ + id / tableRow1 " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " android:gravity = " center " > 34 35 36 37 38 39 40 < TextView android:id = " @ + id / pictureHeadline " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " android:text = " @string / tx_no_picture " /> 41 42 </ TableRow > 43 44 45 46 < TableRow android:id = " @ + id / tableRow3 " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " 38 C.2. XML (layout) source code 47 a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " > 48 49 50 51 52 53 < ImageView android:id = " @ + id / cameraImage " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " 300 dip " a n d r o i d : c o n t e n t D e s c r i p t i o n = " @string / ds _p ic _d es cr ip ti on " / > 54 55 </ TableRow > 56 57 </ TableLayout > 58 59 </ LinearLayout > 39 C.2. XML (layout) source code Listing C.8: Contact-Detail.xml 1 2 3 4 5 6 <? xml version = " 1.0 " encoding = " utf -8 " ? > < LinearLayout xmlns:android = " http: // schemas . android . com / apk / res / android " a n d r o i d : l a y o u t _ w i d t h = " match_parent " a n d r o i d : l a y o u t _ h e i g h t = " match_parent " android:gravity = " cente r_hori zontal " a nd r o id : o r ie n t at i o n = " vertical " > 7 8 9 10 11 < TableLayout a n d r o i d : l a y o u t _ w i d t h = " match_parent " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " a n d r o i d : l a y o u t _ m a r g i n T o p = " 10 dip " > 12 13 14 15 16 17 < TableRow android:id = " @ + id / tableRow1 " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " a n d r o i d : l a y o u t _ m a r g i n B o t t o m = " 5 dip " > 18 19 20 21 22 23 < TextView a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " android:text = " @string / tx_vorname " android:padding = " 5 dip " / > 24 25 26 27 28 29 30 31 < EditText android:id = " @ + id / editVorname " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " android:ems = " 10 " and roid:i nputTy pe = " text " > 32 33 34 < requestFocus / > </ EditText > 35 36 </ TableRow > 37 38 39 40 41 < TableRow android:id = " @ + id / tableRow2 " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " > 42 43 44 45 46 < TextView a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " android:text = " @string / tx_nachname " 40 C.2. XML (layout) source code android:padding = " 5 dip " / > 47 48 49 50 51 52 53 54 < EditText android:id = " @ + id / editNachname " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " android:ems = " 10 " and roid:i nputTy pe = " text " / > 55 56 </ TableRow > 57 58 59 60 61 62 < TableRow android:id = " @ + id / tableRow3 " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " > </ TableRow > 63 64 65 66 67 < TableRow android:id = " @ + id / tableRow4 " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " > 68 69 70 71 72 73 < TableRow android:id = " @ + id / tableRow5 " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " > </ TableRow > 74 75 76 </ TableRow > </ TableLayout > 77 78 79 80 81 82 83 84 85 86 < Button android:id = " @ + id / s a v e C o n t a c t I n f o r m a t i o n s " a n d r o i d : l a y o u t _ w i d t h = " wrap_content " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " android:text = " @string / bt_save_contact " android:onClick = " saveAndClose " a n d r o i d : l a y o u t _ m a r g i n T o p = " 50 dip " an dr oi d: ba ck gr ou nd = " #506495 ED " android:padding = " 5 dip " / > 87 88 </ LinearLayout > 41 C.2. XML (layout) source code Listing C.9: Contact-Overview.xml 1 2 3 4 5 6 <? xml version = " 1.0 " encoding = " utf -8 " ? > < LinearLayout xmlns:android = " http: // schemas . android . com / apk / res / android " a n d r o i d : l a y o u t _ w i d t h = " fill_parent " a n d r o i d : l a y o u t _ h e i g h t = " fill_parent " a nd r o id : o r ie n t at i o n = " vertical " android:padding = " 10 dip " > 7 8 9 10 11 12 < ListView android:id = " @ + id / android:list " a n d r o i d : l a y o u t _ w i d t h = " fill_parent " a n d r o i d : l a y o u t _ h e i g h t = " wrap_content " > </ ListView > 13 14 </ LinearLayout > 42 C.2. XML (layout) source code 43 Listing C.10: values.xml 1 2 <? xml version = " 1.0 " encoding = " utf -8 " ? > < resources > 3 4 <! -- MainActivity START -- > 5 6 <! -- Textviews / Descriptions -- > 7 8 9 10 <! -- Buttons -- > < string name = " bt_init_contact " > Contact - Example </ string > < string name = " bt_init_camera " > Camera - Example </ string > 11 12 <! -- Main END -- > 13 14 15 16 17 <! -- C o n t a c t E x p l o r e r A c t i v i t y START -- > 18 19 20 <! -- Textviews / Descriptions -- > < string name = " app_name " > C o n t a c t A n d C a m e r a E x p l o r e r </ string > 21 22 <! -- Buttons -- > 23 24 <! -- C o n t a c t E x p l o r e r A c t i v i t y END -- > 25 26 27 28 29 <! -- C o n t a c t I n f o r m a t i o n A c t i v i t y START -- > 30 31 32 33 <! -- Textviews / Descriptions -- > < string name = " tx_vorname " > Forename: </ string > < string name = " tx_nachname " > Surname: </ string > 34 35 36 <! -- Buttons -- > < string name = " bt_save_contact " > Save contact informations < / string > 37 38 <! -- C o n t a c t I n f o r m a t i o n A c t i v i t y END -- > 39 40 41 <! -- CameraActivity START -- > 42 43 44 45 <! -- Textviews / Descriptions -- > < string name = " tx_taken_picture " > Recently taken picture: </ string > < string name = " tx_no_picture " > No picture taken . </ string > C.2. XML (layout) source code 46 47 <! -- Buttons -- > < string name = " bt_take_picture " > Take a new picture </ string > 48 49 < string name = " ds_ pi c_ de sc ri pt io n " > Picture take via the Camera </ string > 50 51 <! -- CameraActivity 52 53 54 55 44 </ resources > END -- >