Download The Android SDK - Data Management and Data Exploration

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
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 -- >