Download Week #

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
Mobile Application Development
Department of Information Technology
Faculty of Computing and Information Technology
King Abdulaziz University
CPIT490
Lab# 10: Embedded Applications and Location Tracking Applications
Objectives:
The objective of this lab is to develop embedded android applications and location tracking
applications.
Outline of this lab:
1. Embedded Applications
2. Location Management Application
Activity Outcomes
At the end of this lab, the student will be able to develop an embedded Android Applications and
location management applications.
Task 1: Steps to develop an embedded android application:
Step 1. Embedding PDFViewer in the Android Project:
 Create a new Android Project. Download the PDFViewer.jar file from Internet or from Moodle.
Add this file in the Project’s build path (this could be done by adding the jar file into the libs folder
of the Android application).
 Copy
the
following
drawable
resources
from
PdfViewer/res/drawable
into
YourProject/res/drawable folder: left_arrow.png right_arrow.png, zoom_in.png, zoom_out.png
 Copy the following two layout resources from PdfViewer/res/layout into YourProject/res/layout
folder: dialog_pagenumber.xml, pdf_file_password.xml
Step 2. Developing the Java code:
In addition to the Main Activity java class, create an additional activity class called
MyPDFViewerActivity.java by extending PdfViewerActivity. This program is given below.
import net.sf.andpdf.pdfviewer.PdfViewerActivity;
public class MyPdfViewerActivity extends PdfViewerActivity {
public int getPreviousPageImageResource() {return R.drawable.left_arrow;}
public int getNextPageImageResource() { return R.drawable.right_arrow;}
public int getZoomInImageResource() {return R.drawable.zoom_in;}
public int getZoomOutImageResource() {return R.drawable.zoom_out;}
public int getPdfPasswordLayoutResource() {return R.layout.pdf_file_password;}
public int getPdfPageNumberResource() { return R.layout.dialog_pagenumber;}
public int getPdfPasswordEditField() {return R.id.etPassword;}
public int getPdfPasswordOkButton() {return R.id.btOK;}
public int getPdfPasswordExitButton() { return R.id.btExit;}
public int getPdfPageNumberEditField() {return R.id.pagenum_edit;}
}
Create the Main Activity class as below.
import
import
import
import
net.sf.andpdf.pdfviewer.PdfViewerActivity;
android.app.Activity;
android.content.Intent;
android.os.Bundle;
1
import android.view.Menu;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// CODE FOR FILE ACCESS COMES HERE – refer to step 4
}
}
Step 3. Updating the manifest file:
a. You need to modify the Manifest file to include both activities.
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="MyPdfViewerActivity"></activity>
</application>
b. If you want to access the local SD Card to play some video or audio, you need to provide
READ_EXTERNAL_STORAGE permission.
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE">
</uses-permission>
Step 4. Different methods to access PDF files present at different locations
1. In order to access the internal and external storage present in the mobile device or emulator,
various methods could be used. The problem with these methods is that they could perform
differently on different emulators and devices. Using the following methods in the onCreate()
method of MainActivity class, please identify the directory which is accessed on your mobile
device.
Log.d("TESTING", Environment.getExternalStorageDirectory().toString());
// returns /storage/emulated/legacy which is the internal storage
Log.d("TESTING", System.getenv("EXTERNAL_STORAGE").toString());
// returns /storage/extSdCard which is the external storage
Log.d("TESTING", System.getenv("SECONDARY_STORAGE").toString());
2. Based on the above, modify the code to access the file present in your internal and external
storage. You need only one of these entries.
File file = new File(Environment.getExternalStorageDirectory().getPath()
+"/test.pdf");
File file = new File("/storage/extSdCard/test.pdf");
3. Opening the PDF from the default PDF Viewer.
Intent target = new Intent(Intent.ACTION_VIEW);
2
target.setDataAndType(Uri.fromFile(file),"application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
// Intent intent = Intent.createChooser(target, "Open File");
startActivity(intent);
4. Opening the PDF from the embedded PDF Viewer.
Intent intent = new Intent(this, MyPdfViewerActivity.class);
// accessing a file present in the SD card
// Change the file path and file name according to your file details
intent.putExtra(PdfViewerActivity.EXTRA_PDFFILENAME,"/storage/sdCard/test.pdf");
startActivity(intent);
Task 2: Developing an android application for location Tracking:
In order to develop Google API based android applications, make sure the following are available:
 Go to SDK Manager in Eclipse:
o Select the respective Google Maps API that matches the android version and install it; if
you want to upgrade your Android API level, you need to use help  Install New
Software
o Under Extras, select Google Play Services and install it
a. Obtain the SHA1 key:
i. To obtain the SHA1 key, use the following:
C:\<jdk-folder>\bin>keytool.exe
-list
-alias
androiddebugkey
-keystore
C:\<yourHomeFolder>\.android\debug.keystore -storepass android -keypass android –v
OR
ii. You could use the Eclipse to obtain the SHA1 key. This is possible using Window
 Preferences  Android  Build
b. Obtain the API key:
i. Register
your
client
ID
and
obtain
Google
API
key
at
https://code.google.com/apis/console/
ii. You will need to use your gmail login
iii. Under services, enable Google Maps Android API v2. You could click on Create
New Android key to generate the key. You need your SHA1 key and the package
name for this. Enter the values of SHA1 key and package name, separated with a
semi-colon.
iv. Your new API key will be a 40 character string


Note the API key obtain from the previous step. Also, note its validity period.
Add the Google Play Services project into your Eclipse workspace.
o Click File  Import, select Android  Existing Android Code into Workspace
o Browse to and select
o <android-sdk-folder>/extras/google/google_play_services/libproject/google-playservices_lib
o You don’t need to enable the option to copy the library into your workspace
In your new project file:

To add the dependency to Google Play Services into your project


Update MainActivity.java to extend FragmentActivity instead of Activity
Note: If there is an error with regard to a missing library, you need to right click on the project
and go to Build Path and configure Build Path. In the libraries tab, remove the wrongly added
libraries.
Add the following tag into your AndroidManifest.xml just before the closing </application> tag
3
o

Project  Properties  Android  Library, Add  google-play-services_lib
o

Your application now also needs the following permissions in the AndroidManifest.xml
o
o
o
o
o

<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
The layout file is like this:
o
o
o
o
o
o
o
o

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Maps v2 uses OpenGl so the following uses-feature is also required
o

<permission android:name="your_package_name.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/>
<uses-permission android:name="your_package_name.permission.MAPS_RECEIVE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission
android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
Optionally you can include one or both of these permissions to enable auto-location
o
o

<meta-data android:name="com.google.android.maps.v2.API_KEY"
android:value="your_api_key"/>
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="@+id/the_map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.MapFragment"
map:cameraTilt="45" map:cameraZoom="14" />
In order to run the application on an Android device, whose android version is less that android
version 12, use
<fragment … android:name="com.google.android.gms.maps.SupportMapFragment" />
Instead of
<fragment … android:name="com.google.android.gms.maps.MapFragment" />

Make sure Target build is Google API. You could check that on Right-click on
Project 
Preferences  Android  Project Build Target

You need to check whether your project has google-play-services_lib as a library. Doing this
process includes the google-play-services_lib.jar file into Android Dependencies for the
current project. This is possible only after importing the google-play-services_lib into Eclipse.
Example program for location management:
public class MyMapActivity extends FragmentActivity {
LocationClient locationclient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_map);
GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// Get a handle to the Map Fragment
GoogleMap
map
=
getSupportFragmentManager().findFragmentById(R.id.the_map)).getMap();
// Map settings
// Other supported types include: MAP_TYPE_NORMAL,
// MAP_TYPE_TERRAIN, MAP_TYPE_HYBRID and MAP_TYPE_NONE
//map.setMapType(map.MAP_TYPE_SATELLITE);
map.setMapType(map.MAP_TYPE_NORMAL);
map.getUiSettings().setZoomControlsEnabled(false);
// showFixedLocation(map);
showCurrentLocation(map);
4
((SupportMapFragment)
}
private void showFixedLocation(GoogleMap map) {
LatLng kau = new LatLng(21.4939, 39.2503);
map.setMyLocationEnabled(true);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(kau, 13));
map.addMarker(new MarkerOptions()
.title("KAU")
.snippet("Our university in Jeddah.")
// .icon(BitmapDescriptorFactory.fromResource(R.drawable.house_flag))
// Flat markers will rotate when the map is rotated,
// and change perspective when the map is tilted.
// .flat(true)
.position(kau));
// for flat(true)
CameraPosition cameraPosition = CameraPosition.builder()
.target(kau)
.zoom(13)
.bearing(90)
.build();
// Animate the change in camera view over 2 seconds
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition),
2000, null);
// Polylines are useful for marking paths and routes on the map.
map.addPolyline(new PolylineOptions().geodesic(true)
.add(new LatLng(21.4333, 40.35)) // Taif
.add(new LatLng(24.4667, 39.6)) // Madinah
.add(new LatLng(21.4167, 39.8167)) // Makkah
.add(new LatLng(21.4939, 39.2503)) // KAU
);
}
private void showCurrentLocation(GoogleMap map) {
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean enabledGPS = service.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean enabledWiFi = service.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
// Check if enabled and if not send user to the GPS settings
// Better solution would be to display a dialog and suggesting to
// go to the settings
if (!enabledGPS) {
Toast.makeText(this, "GPS signal not found", Toast.LENGTH_LONG).show();
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
if (enabledGPS) {
// service.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
//
locationManager.requestLocationUpdates(
//
LocationManager.GPS_PROVIDER,
//
MIN_TIME_BW_UPDATES,
//
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (service != null) {
Location location = service.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
double latitude = location.getLatitude();
double longitude = location.getLongitude();
Toast.makeText(this,
"Selected
Provider
"
+
location.getLatitude()
+
","
+
location.getLongitude(),
Toast.LENGTH_SHORT).show();
}
}
LocationManager
locationManager
=
(LocationManager)
getSystemService(Context.LOCATION_SERVICE);
// Define the criteria how to select the locatoin provider -> use default
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {
Toast.makeText(this, "Selected Provider " + provider, Toast.LENGTH_SHORT).show();
5
// onLocationChanged(location);
LatLng current = new LatLng(location.getLatitude(), location.getLongitude());
map.moveCamera(CameraUpdateFactory.newLatLngZoom(current, 13));
map.addMarker(new MarkerOptions()
.position(current)
.title("Current Location"));
// .icon(BitmapDescriptorFactory
// .fromResource(R.drawable.ic_launcher)));
} else {
Toast.makeText(this, "GPS Signal is not available", Toast.LENGTH_SHORT).show();
} }
}
}

Possible errors and solutions:
o NOTE: Google Android API codes work only on Android device and not on the
emulator. In the emulator, you get only the grids and no maps.
o ClassNotFoundException: This error indicates that respective class is not found in the
apk file. To solve this, you need to include the google-play-services_lib as a library to
your project.
o Program opens and closes immediately:
 Happens in the emulator:
 There might be problems with the target SDK version or there is a
mistake in the manifest file
 You need to have your network connection enabled
 Happens in the device: Check the minimum and Target SDK version provided in
the Manifest file along with that of the mobile device itself. A mismatch in this
will cause the program to crash
o Crashing of eclipse is possible with .metadata/.log indicating as below:
 Plug-in
com.android.ide.eclipse.adt
was
unable
to
load
class

com.android.ide.eclipse.adt.internal.welcome
Go to .metadata/.plugins folder and rename
.metadata/.plugins/org.eclipse.e4.workbench
.workbench.temp
to.metadata/.plugins/org.eclipse.e4
and restart eclipse

android.view.InflateException: Binary XML file line #2: Error inflating class fragment
o Make sure this entry is present in layout file
o android:name="com.google.android.gms.maps.SupportMapFragment”

Make sure to add the below in manifest file under <application> tag
o
o
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data android:name="com.google.android.maps.v2.API_KEY"
android:value="API-key" />

Google Maps Android API v2 only supports devices with OpenGL ES 2.0 and above
o This error is possible if your emulator selected does not support OpenGL ES 2.0 and
also if the device does not support OpenGL ES 2.0.

Library is missing while compiling the program. Also,
import android.support.v4.app.FragmentActivity; has an error
o Right click on the project and choose properties. Then in Java Build Path, add
support-v4.jar (ADT-Folder\sdk\extra\android\support\v4)as an external jar

https://developers.google.com/maps/documentation/android/
6
android-
Exercises:
1. Using the inbuilt PDF Viewer do the following:
a. Open a PDF file present in a Web Server
(http://www.kau.edu.sa/files/130002/files/6785_aas.pdf).
b. Open a PDF file present in the assets or raw folder of the apk file.
i. Direct access of the files present in the assets or raw folder might not work properly on all
mobile phones or emulators. Thus, you need to copy the files into a separate location in
the SD card and then access it.
ii. Accessing the files present in the raw or assets folder.
copyFile(this.getResources().openRawResource(R.raw.test), new FileOutputStream(new
File("/storage/extSdCard/", "test1.pdf"))); // for file in raw folder
copyFile(this.getAssets().open("test.pdf"), new FileOutputStream(new
File("/storage/extSdCard/", "test1.pdf"))); // for file in assets folder
// returns /data/data/com.pdftesting.pdftesting/files folder
Log.d("TESTING",getFilesDir().toString());
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
c. The following code is used to list only the pdf files in a folder and when clicked open, the
respective file will be opened.
File images = Environment.getExternalStorageDirectory();
imagelist = images.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return ((name.endsWith(".pdf")));
}
});
pdflist = new String[imagelist.length];
for (int i = 0; i < imagelist.length; i++) {
pdflist[i] = imagelist[i].getName();
}
this.setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
pdflist));
}
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
String path = imagelist[(int) id].getAbsolutePath();
openPdfIntent(path);
}
private void openPdfIntent(String path) {
try {
final Intent intent = new Intent(this, PdfActivity.class);
intent.putExtra(PdfViewerActivity.EXTRA_PDFFILENAME, path);
startActivity(intent);
} catch (Exception e) { e.printStackTrace(); }
}
References:
 http://andhradroid.wordpress.com/2012/07/21/how-to-display-the-pdf-in-android/
 http://androidcodeexamples.blogspot.com/2013_03_01_archive.html
7