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
Høgskolen i Telemark Telemark University College Department of Electrical Engineering, Information Technology and Cybernetics Android Programming Android App Cuong Nguyen, 2013.06.19 Faculty of Technology, Postboks 203, Kjølnes ring 56, N-3901 Porsgrunn, Norway. Tel: +47 35 57 50 00 Fax: +47 35 57 54 01 Table of Contents Introduction............................................................................................................................................. 3 1 Technical Implementation .............................................................................................................. 4 1.1 CreateAndroid WebService client ........................................................................................... 4 1.2 Android programming ............................................................................................................. 6 1.3 Execute and run the app ....................................................................................................... 14 1.4 Comments & explainations ................................................................................................... 15 2 1 Introduction This tutorial will focus on how to create a Web Service Client to exchange data with a Web Service. The Web Service which was created earlier to broad cast temperature data, here we will create an Android “Native” application to present the published data in an appropriate manner on Android device. In able to complete this tutorial you should already have a deployed Web Service running to test the creating Android Web Service client. If you do not have a Web Service yet, it is recommended to go through the “WebService” tutorial to create a Web Service on your system. Additionally, in able to develop an Android application you must first of all set-up the Android development environment. Kindly study “Android_Startup” tutorial to set-up an Android system. Objective: Create “Native” Android client to present data from a Web Service. Figure 1-1: WS data displayed by web browser. Android WS client: Type WS address → Start new screen → Pull data & present Figure 1-2: Android Web Service client. 3 2 Technical Implementation 2.1 CreateAndroid WebService Client Make sure the Android developing interface (JAVA-ADT) is set-up on your computer, If not go through the “Android_Startup” tutorial. Create a new Android application project and give a name (WebService) to the project . File → New → Android Application Project → give name to the project and basically just click on NEXT until finish. INFO: More details on how to create a new project is described in “Android_Startup”. The Android development environment should be as shown in Figure 2-1. We will modify this application (Hello world!) into a Web Service client. Figure 2-1: Development environment with project (WebService). We would like to create additional xml and java files as seen in Figure 2-2. Package Explorer → WebService → src → SensorValue.java 4 5 Technical Implementation Package Explorer → WebService → layout → activity_sensort_value.xml Figure 2-2: Additional needed files. To create additional java files. File → New → Class Name: XXX (in this case Name: SensorValue) NOTE!! The SensorValue.java file should be under “src” folder as shown in Figure 2-2. To create additional xml files. ClicK: icon (Left top corner) → Android → Android XML File → Next Resource Type: Layout → File: activity_sensor_value.xml → Root Element: TableLayout → Finish. (See details in Figure 2-3) INFO: an activity_sensor_value.xml file should appear under layout. Web Service Client 6 Technical Implementation Figure 2-3: Creating "activity_sensor_value.xml" file 2.2 Android Programming Now we would like to modify and fill in xml and java files with codes. We will first of all focus on to filling android codes to the correct files. Once we finish with this process then we will execute and run the application on an Android Virtual Device and also on a real Android device. Comments on all the codes and programming structures are listed at the end of this tutorial. The following files will be modified or/and filled in with codes: MainActivity.java, SensorValue.java, activity_sensor_value.xml, strings.xml, AndroidManifest.xml, main.xml. Note!! main.xml in your case is activity_main.xml Fill in files with codes We will start to fill in codes in strings.xml. Double click: strings.xml → Fill in codes in the strings.xml file Web Service Client 7 Technical Implementation Figure 2-4: Opening a file for editing. Strings.xml codes: <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Web Service</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <string name="get_button">Get</string> <string name="enter_address">Enter Web Service address</string> <string name="text_view">TextView</string> <string name="hint_text"></string> <string name="start_button">Start</string> <string name="title_activity_sensor_value">Sensor Value</string> <string name="value_textview"></string> <string name="tvRow1Column1"></string> <string name="name_textview"></string> </resources> Activity_main.xml codes: <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tableLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:stretchColumns="*" android:background="#FFF" android:padding="5dp"> <!-- tableRow0 --> <TableRow android:id="@+id/tableRow0" Web Service Client 8 Technical Implementation android:layout_height="wrap_content" android:layout_width="match_parent" > <EditText android:id="@+id/edit_message" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/enter_address" android:layout_span="4" /> </TableRow> <!-- tableRow1 --> <TableRow android:id="@+id/tableRow1" android:layout_height="wrap_content" android:layout_width="match_parent" > <TextView android:id="@+id/tvRow1Column1" android:layout_gravity="center_vertical" android:layout_height="wrap_content" android:layout_span="3" android:text="@string/tvRow1Column1" /> <Button android:id="@+id/get_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/get_button" android:layout_gravity="center_vertical" android:onClick="sendMessage" /> </TableRow> </TableLayout> Activity_sensor_value.xml codes: <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/tableLayout2" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="5dp" android:stretchColumns="*" android:background="@android:color/white" tools:context=".SensorValue"> <!-- tableRow0 --> <TableRow android:id="@+id/tableRow0" android:layout_height="wrap_content" android:layout_width="match_parent">" <Button android:id="@+id/start_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/start_button" /> </TableRow> Web Service Client 9 Technical Implementation <!-- tableRow1 --> <TableRow android:id="@+id/tableRow1" android:layout_height="wrap_content" android:layout_width="match_parent" > <TextView android:id="@+id/nameTextview" android:layout_gravity="center_horizontal" android:textSize="46dp" android:text="@string/name_textview" android:padding="5dp"/> </TableRow> <!-- tableRow2 --> <TableRow android:id="@+id/tableRow2" android:layout_height="wrap_content" android:layout_width="match_parent" android:layout_weight="1" > <TextView android:id="@+id/valueTextview" android:layout_gravity="center_horizontal" android:textSize="36dp" android:text="@string/value_textview" android:padding="5dp"/> </TableRow> </TableLayout> SensorValue.java codes: package no.hit.webservice; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import import import import import import import import org.apache.http.HttpEntity; org.apache.http.HttpResponse; org.apache.http.client.HttpClient; org.apache.http.client.methods.HttpGet; org.apache.http.impl.client.DefaultHttpClient; org.apache.http.protocol.BasicHttpContext; org.apache.http.protocol.HttpContext; org.w3c.dom.Document; Web Service Client 10 Technical Implementation import import import import org.w3c.dom.Element; org.w3c.dom.Node; org.w3c.dom.NodeList; org.xml.sax.InputSource; import import import import import import import import import import import import import import android.annotation.SuppressLint; android.app.Activity; android.content.Intent; android.graphics.Color; android.os.AsyncTask; android.os.Bundle; android.os.Handler; android.support.v4.app.NavUtils; android.view.Menu; android.view.MenuItem; android.view.View; android.view.View.OnClickListener; android.widget.Button; android.widget.TextView; public class SensorValue extends Activity implements OnClickListener { private Handler h = new Handler(); private Runnable myRunnable = new Runnable() { public void run() { //do stuff new LongRunningGetIO().execute(); //run again in one second h.postDelayed(myRunnable, 1000); } }; @SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sensor_value); findViewById(R.id.start_button).setOnClickListener(this); } @Override public void onClick(View arg0) { Button b = (Button)findViewById(R.id.start_button); b.setClickable(false); new LongRunningGetIO().execute(); h.postDelayed(myRunnable, 1000); } private class LongRunningGetIO extends AsyncTask <Void, Void, String> { Web Service Client 11 Technical Implementation protected String getASCIIContentFromEntity(HttpEntity entity) throws IllegalStateException, IOException { InputStream in = entity.getContent(); StringBuffer out = new StringBuffer(); int n = 1; while (n>0) { byte[] b = new byte[4096]; n = in.read(b); if (n>0) out.append(new String(b, 0, n)); } return out.toString(); } @Override protected String doInBackground(Void... params) { // Get the message from the intent Intent intent = getIntent(); String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE); HttpClient httpClient = new DefaultHttpClient(); HttpContext localContext = new BasicHttpContext(); HttpGet httpGet = new HttpGet("http://"+ message); String webServiceXML = null; try { HttpResponse response = httpClient.execute(httpGet, localContext); HttpEntity entity = response.getEntity(); webServiceXML = getASCIIContentFromEntity(entity); } catch (Exception e) { return e.getLocalizedMessage(); } return webServiceXML; } protected void onPostExecute(String webServiceXML) { String nameData=""; String valueData=""; if (webServiceXML!=null) { // parse try { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); InputSource s = new InputSource(new StringReader(webServiceXML)); Web Service Client 12 Technical Implementation Document doc = dBuilder.parse(s); doc.getDocumentElement().normalize(); NodeList nList = doc.getElementsByTagName("Terminal"); for (int temp = 0; temp < nList.getLength(); temp++) { Node nNode = nList.item(temp); if (nNode.getNodeType() == Node.ELEMENT_NODE) { Element eElement = (Element) nNode; nameData = eElement.getElementsByTagName("Name").item(0).getTextContent(); valueData = eElement.getElementsByTagName("Value").item(0).getTextContent(); } } } catch (Exception e) { e.printStackTrace(); } TextView name = (TextView) findViewById(R.id.nameTextview); name.setTextColor(Color.parseColor("#0147FA")); name.setText(nameData); TextView value = (TextView) findViewById(R.id.valueTextview); value.setTextColor(Color.parseColor("#0147FA")); value.setText(valueData + " " +(char) 0x00B0 + "C"); } Button button = (Button)findViewById(R.id.start_button); button.setClickable(true); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.sensor_value, menu); return true; } } MainActivity.java codes: package no.hit.webservice; import import import import android.app.Activity; android.content.Intent; android.os.Bundle; android.view.View; Web Service Client 13 Technical Implementation import android.widget.EditText; public class MainActivity extends Activity { public final static String EXTRA_MESSAGE = "no.hit.webservice.MESSAGE"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } /** Called when the user clicks the Send button */ public void sendMessage(View view) { Intent intent = new Intent(this, SensorValue.class); EditText editText = (EditText) findViewById(R.id.edit_message); String message = editText.getText().toString(); intent.putExtra(EXTRA_MESSAGE, message); startActivity(intent); } } AndroidManifest.xml codes: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="no.hit.webservice" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="no.hit.webservice.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="no.hit.webservice.SensorValue" android:label="@string/title_activity_sensor_value" android:parentActivityName="no.hit.webservice.MainActivity" > <meta-data android:name="android.support.PARENT_ACTIVITY" Web Service Client 14 Technical Implementation android:value="no.hit.webservice.MainActivity" /> </activity> </application> </manifest> 2.3 Execute and Run the App We are now finishing with Android programming phase (All the files are loaded with codes). Next we will execute and run the Android WebService client. Run on Android Virtual Device (AVD) Simulate an application in a Virtual Device File → Save to save all the changes Click: “WebService” → Project → Clean… Click: “WebService” → Run → Run as → 1 Android Application Recommend: Repeat all the three steps above every time you run your app. NOTE!! Important to click on “WebService”. Wait approximately a few minutes for your computer to load the Virtual Device (AVD). In case a window is pop-up as seen in Figure 2-5, just click Yes → OK to continue. INFO: unlike other programming languages, to compile and run codes on Android is a very slow process, due to the reason the required time to launch AVD. Once AVD appears → unlock → Wait. Figure 2-5: Enable logcat service. Your new created “WebService” is running on Android Virtual Device by the given name MyDevice. Enter: address of the WebService → Get → Start Data extracted from the Web Service should display on AVD. Web Service Client 15 Technical Implementation Figure 2-6: Android "WebService" application. Run on a real Android Device All the written codes are compressed in a “apk” file, in this case the file name is WebService.apk. This specific file has to be downloaded (transferred) and installed on the real device. The file can be passed to the android device throug Bluetooth technology or simply by using a cable. Location of apk file: workspace → WebService → bin folder → WebService.apk INFO: In my case the whole path to the WebService.apk is located in C:/User/levo/workspace/ WebService /bin/ WebService.apk Note!! Levo is my user name, so it is different name in your computer. 2.4 Comments & Explainations This section will focus on functionalities of different files (java and xml) and comments on all the codes containing in these files. Furthermore, src, values and layout folders are folders that developers mostly interact with, will also be given discussions. Layout XML code all the codes written in the xml files within layout folder specifies the layout of the screen. In this case we have two different xml files, activity_sensor_value.xml and activity_main.xml, these are located in the layout folder. Since the Web Service client (application) consists of two different screens and each separate screen needs their own xml file to control the layout. Activity_main. xml or main.xml controls the layout of the first screen. Here we refer the first screen as the first page appears on the device when the application starts up. In these case we enter the address of the Web Service on the first screen. activity_sensor_value.xml controls the layout of the second screen. In this case we display data published from the Web Service on the second screen. Web Service Client 16 Technical Implementation Figure 2-7: App consists of two screens. Java source code The Java code is what drives everything, where the main duty is to deliver the job given based on input from the screen, in other words commands given by the user. Java code executes and runs the application. MainActivity.java and SensorValue.java are the two files that contain Java codes. Each java files controls, executes and delivers the job based on the command given as input from layout screen. Java code can be considered as unseen engine spinning behind the current screen, always listening for a command from the user, where its mission is to deliver the job once a command is detected. MainActivity.java file deliver the job based on input from the first screen, while SensorValue.java file also has the same function but listens to the input from the second screen instead. The Java file operation in our case can be simplified as below: First screen → Get (Input ,Command) → MainActivity.java → Result (copy the WS address, send to the second activity (SensorValue.java) and open the second screen. Second screen → Start (Input ,Command) → SensorValue.java → Result (get the WS address from the first activity, get and update data from WS every second, display data on second screen). The whole process is illustrated in Figure 2-8. Web Service Client 17 Technical Implementation Figure 2-8: Chart flow of WebService app. Values folder This folder contains xml files as resources (dimensions, strings, styles), from which other files can pull data resources to fulfill various functions. All the text strings are stored in the strings.xml as text resource from which other files, methods, activity are able to utilize. A word string is stored in an xml file as seen below. <?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello_world">Hello world!</string> </resources> AndroidManifest.xml The manifest file glues everything together, this specific file describes what the application consists of, what all its main building blocks are, what permissions it requires and etc. A Manifest file fills automatically codes by it selves while we are developing the app. The code of line below has to be written by the developer him selves to allow the application to access to the internet. <uses-permission android:name=”android.permission.INTERNET”/> Activity_main.xml or main.xml Since this file is located in the layout folder so the codes containing in the main.xml file are mostly EditText, TextView and buttons of various type. The codes in this file control where on the screen these features should be placed and their characteristics. Main.xml file controls the layout of the first screen in the created WS client, from which there are two features; EditText and a “Get” button. EditText: is needed for users to be able to type input to the system, here the input is referred to a WebService address. Web Service Client 18 Technical Implementation “Get” button: when user press this button, a command is detected by codes written in a java and process until the result is delivered. Layout of first screen We set the screen as TableLayout type, we split the table up to two rows of which the first row (Android define first row as row 0) is reserved for TextEdit while the second row (row 1) is occupied by the “Get” button. Additionally the table is split in to three columns where one of the columns is reserved by “Get” button. A thickness of “5dp” is surrounding along the whole table to the outer edge. The rest of the codes in the activity_main.xml are logical and easy to understand. Figure 2-9: Layout design of first screen. Layout of second screen We set the second screen also as TableLayout type, we split the table up to three rows of which the first row (Android define first row as row 0) is reserved for a “Start” button while the second and third rows (row 1 and row 2) are occupied by two TextViews with different properties. Additionally, a thickness of “5dp” is surrounding along the whole table to the outer edge. The rest of the codes in the activity_main.xml are logical and easy to understand. Hence, “Temperature” and “26,7 °C” are dynamic TextViews, meaning they are displayed corresponding to changes in data broad casted from the WebService. Web Service Client 19 Technical Implementation Figure 2-10: Layout design of second screen. Java files The actual hardcore programming taken place in the java files, the java code is what drives everything. This Web Service client application consists of two java files; MainActivity.java reacts to the input from the first screen (main.xml) while SensorValue.java deliver the work based on the command from the second screen (activity_sensor_value.xml). MainActivity.java The method “sendMessage” will reacts based on the users interaction to the “Get” button in main_xml file. Once the button is pressed the method will start to process and the final result to the work is totally depending on what code is specified for this method. In this case the missions of the “sendMessage” method are; First of all create a new intent object by the name “intent”. Intent is a service in Android which mostly used to start a new activity. Since we are currently in MainActivity.java, intent will start SensorValue.java as new activity. Define the EditText (id: edit_message) as editText in this java file copy the entered address in the EditText to the “message”. Example, if you have typed in <<128.39.35.239:8080/WebService/Temp_value>> the ”message” contains the whole string that was just typed in. message = 128.39.35.239:8080/WebService/Temp_value When intent is activated and start another activity, the content of the message will also be sent to the new started activity, which in our case is SensorValue.java. public void sendMessage(View view) { Web Service Client 20 Technical Implementation Intent intent = new Intent(this, SensorValue.class); EditText editText = (EditText) findViewById(R.id.edit_message); String message = editText.getText().toString(); intent.putExtra(EXTRA_MESSAGE, message); startActivity(intent); } SensorValue.java “myRunnable” method will put the system into sleep for a certain time period, in this case it is set one second. We use this method to get data from the WebService once in a second. private Runnable myRunnable = new Runnable() { public void run() { new LongRunningGetIO().execute(); //run again in one second h.postDelayed(myRunnable, 1000); } }; “onClick” method calls for other method to perform a certain task. public void onClick(View arg0) { Button b = (Button)findViewById(R.id.start_button); b.setClickable(false); new LongRunningGetIO().execute(); h.postDelayed(myRunnable, 1000); } This part of code runs in the background of the system, its tasks are to; get the message (Entered in the EditText) passed over from the first activity then start internet connection with the WebService, where the address is contained in the “message”. protected String doInBackground(Void... params) { // Get the message from the intent Intent intent = getIntent(); String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE); Web Service Client 21 Technical Implementation HttpClient httpClient = new DefaultHttpClient(); HttpContext localContext = new BasicHttpContext(); HttpGet httpGet = new HttpGet("http://"+ message); String webServiceXML = null; try { HttpResponse response = httpClient.execute(httpGet, localContext); HttpEntity entity = response.getEntity(); webServiceXML = getASCIIContentFromEntity(entity); } catch (Exception e) { return e.getLocalizedMessage(); } return webServiceXML; } With this code we only extract (parse data from WS to Android) the data of interest from the WebService (Temperature and 26,7 °C) then we give properties to these data. All the mentioned actions will be activated once the “Start_button” is pressed. protected void onPostExecute(String webServiceXML) { String nameData=""; String valueData=""; if (webServiceXML!=null) { // parse try { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder=dbFactory.newDocumentBuilder(); InputSource s = new InputSource(new StringReader(webServiceXML)); Document doc = dBuilder.parse(s); doc.getDocumentElement().normalize(); NodeList nList = doc.getElementsByTagName("Terminal"); for (int temp = 0; temp < nList.getLength(); temp++) { Node nNode = nList.item(temp); if (nNode.getNodeType() == Node.ELEMENT_NODE) { Element eElement = (Element) nNode; nameData = eElement.getElementsByTagName("Name").item(0).getTextContent(); valueData = eElement.getElementsByTagName("Value").item(0).getTextContent(); } } Web Service Client 22 Technical Implementation } catch (Exception e) { e.printStackTrace(); } // Temperature TextView properties TextView name = (TextView) findViewById(R.id.nameTextview); name.setTextColor(Color.parseColor("#0147FA")); name.setText(nameData); // Temperature value TextView properties TextView value = (TextView) findViewById(R.id.valueTextview); value.setTextColor(Color.parseColor("#0147FA")); value.setText(valueData + " " +(char) 0x00B0 + "C"); } Button button = (Button)findViewById(R.id.start_button); button.setClickable(true); } } Note!! When programming in java files we need to import many different libraries to support the code. In Android we do not need to put much focused on this problem. While you are programming every now and then just click: “Ctrl + Shift + O” Android will import all necessary libraries to support the written codes. As the second options is to right click texts with underlines, then choose import. At this moment you should be able to execute and run the Web Service client on an emulator (AVD) and also on the real physical Android device. But most important of it all is that you understand the programming structure in Android and have an idea over the functional of the codes in different xml and java files. Web Service Client Høgskolen i Telemark Telemark University College Department of Electrical Engineering, Information Technology and Cybernetics Telemark University College Faculty of Technology Kjølnes Ring 56 N-3918 Porsgrunn, Norway www.hit.no Faculty of Technology, Postboks 203, Kjølnes ring 56, N-3901 Porsgrunn, Norway. Tel: +47 35 57 50 00 Fax: +47 35 57 54 01