Location Based Services on Android – Part 1/3 – MyLocationOverlay

A juicy feature of Android is its capability for location based services. The combination of the integrated GPS-Device with the easy use of Google Maps allows powerful location based applications.

Anyway, the first use of these technologies contains some hazards. Therefore, I decided to write some blog entries explaining the first steps with Android and Google Maps.

The first part of this series describes the integration of the google map view and the use of the MyLocationOverlay. In the second part I demonstrate how to use an ItemizedOverlay on a google map. Third and last part of this series describes how to build a custom Overlay and show it on the map.

Part 1 – Enable Google Maps and use a MyLocationOverlay

The first part of this series contains a short description how to integrate Google Maps in an Android application and show the current location using the MyLocationOverlay.

In order to follow these steps, you should already have installed the android sdk Eclipse as IDE and created a new Android project. If you have not done this so far, look at the Android Documentation.

Integrate Google Maps in your application
We start by editing the layout definition file of the application. The following snippet shows the content of the /res/layout/main.xml file. Its contents are described below.

<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <com.google.android.maps.MapView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:clickable="true"
    android:enabled="true"
    android:id="@+id/mymap"
    android:apiKey="@string/mapskey" />
  <LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/myzoom"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
  />
</RelativeLayout>

This layout definition contains a little we trick we use to position the zoom-controls at the bottom of the map. We use a RelativeLayout, which uses the whole viewport as container. This contains the Google Maps View (com.google.android.maps.MapView) and a LinearLayout. The LinearLayout will contain the Zoom-Controls of the map. Inside a RelativeLayout, Views can be positioned in relation to each other or in relation to its parent (the RelativeLayout). The map simply uses the complete viewport. For the LinearLayout (with the zoom controls) we use the abilities of the RelativeLayout and position it centered at the bottom of the RelativeLayout, above the map.

NOTE: For sdk 1.5 it is not needed anymore to work with this trick. But it still works.

The IDs of the LinearLayout and the map are used to make the Views accessible inside the Activity.

To use the Google Maps View an API key is needed, this will be stored as string ressource referenced by the key @string/mapskey.

Get an Google Maps API key

Android only allows the installation of signed applications. Before installing an application on the emulator, Eclipse will automatically sign the application, using a debug certificate which comes along with the Android sdk. The google maps api key is based on the certificate used to sign the application. Detailed descriptions about signing an application can be found in the online documentation.

To obtain a google maps api key (using the debug certificate) you have to do the following steps:

  1. Create a md5 checksum of the debug certificate
    Find the debug.keystore

    • Windows Vista: C:\Users\’user’\.android\debug.keystore
    • Windows XP: C:\Documents and Settings\’user’\.android\debug.keystore
    • Mac OS X und Linux: ~/.android/debug.keystore

    and call the command
    keytool -list -alias androiddebugkey -keystore .keystore -storepass android -keypass android
    The md5 checksum is generated and printed to the screen.

  2. Register the md5 checksum
    Register the generated checksum at Maps API key. A google account is required to do so.
  3. Edit ressources
    Paste the Maps API key to the resources.

The /res/strings.xml with the Maps key of my debug certificate

<?xml version="1.0" encoding="utf-8"?>
<resources>
	<string name="app_name">LocationBasedServicesV1</string>
	<string name="mapskey">0zHDFEa6rhx5Je8xqLmDaH6kEym5ga9nxV49H5w</string>
</resources>

A detailed description how to generate the Google Maps API key for Android can be found in the reference.

Add required permissions and libraries to the manifest

The application requires 2 permissions.

  1. Google maps requires access to the internet (android.permission.INTERNET)
  2. MyLocationOverlay requires access to the GPS (android.permission.ACCESS_FINE_LOCATION)

In addition, the library Google Maps API (com.google.android.maps) must be included to the project.

The AndroidManifest.xml containing all necessary changes:

<?xml version="1.0" encoding="utf-8"?>
<manifest
	xmlns:android="http://schemas.android.com/apk/res/android"
	package="de.itemis.frey.blog.lbsv1"
	android:versionCode="100"
	android:versionName="1.0.0">
	<application
		android:icon="@drawable/icon"
		android:label="@string/app_name">
		<activity
			android:name=".LocationBasedServicesV1"
			android:label="@string/app_name">
			<intent-filter>
				<action android:name="android.intent.action.MAIN" />
				<category android:name="android.intent.category.LAUNCHER" />
			</intent-filter>
		</activity>
		<uses-library android:name="com.google.android.maps" />
	</application>
	<uses-permission android:name="android.permission.INTERNET" />
	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

Add MyLocationOverlay to the map and init the zoomcontrols

The activity calls in its onCreate Method the two methods initMap and initMylocation.

  1. initMap
    This method initialises the zoom controls of the map and adds them to the LinearLayout.
  2. initMyLocation
    • Instantiate a new MyLocationOverlay
    • Enable the MyLocationOverlay
    • Add the overlay to the list of overlays of the map

The LocationBasedServicesV1.java

package de.itemis.frey.blog.lbsv1;
 
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
 
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
 
/**
 * This application demonstrates the use of the google maps view in combination
 * with a MyLocationOverlay.
 * 
 * @author frey
 */
public class LocationBasedServicesV1 extends MapActivity {
 
	private MapView myMap;
	private MyLocationOverlay myLocOverlay;
 
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
 
		initMap();
		initMyLocation();
	}
 
	/**
	 * Initialise the map and adds the zoomcontrols to the LinearLayout.
	 */
	private void initMap() {
		myMap = (MapView) findViewById(R.id.mymap);
 
		View zoomView = myMap.getZoomControls();
		LinearLayout myzoom = (LinearLayout) findViewById(R.id.myzoom);
		myzoom.addView(zoomView);
		myMap.displayZoomControls(true);
 
	}
 
	/**
	 * Initialises the MyLocationOverlay and adds it to the overlays of the map
	 */
	private void initMyLocation() {
		myLocOverlay = new MyLocationOverlay(this, myMap);
		myLocOverlay.enableMyLocation();
		myMap.getOverlays().add(myLocOverlay);
 
	}
 
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
}

The application is now ready to receive gps signals and show them using a MyLocationOverlay.

Trigger the “GPS” of the emulator

It is possible to test the application and the gps device using the emulator. First, start the application (run as android applicaition). The easiest way to emulate incoming gps signals, is by using the “DDMS” Perspective in Eclipse. There you can send Locations via the Emulator control.

However this is not possible with a german operating system. Due to a bug in android concerning the different localised date format. But you can use telnet to connect to the emulator console and send a new position to the emulator.

  1. open a terminal
  2. type “telnet localhost 5554″ – you should now be connected to the emulator
  3. send the geo fix command, for example “geo fix 9 49

The application should now show a pin at the given location. Whenever you change the position, the maps should center to this new coordinate. (This only works, when the pin was already visible before).

So that’s it. In the next part of this series, i will explain how to use a Google Map with ItemizedOverlays.

You are welcome to post comments or suggestions for improvement.

The complete series:

Autor: Andreas Frey
Datum: Saturday, 4. April 2009 12:09
Trackback: Trackback-URL Themengebiet: Google Maps API, Google Android, Location Based Services, Tutorial

Feed zum Beitrag: RSS 2.0 Diesen Artikel kommentieren

31 Kommentare

  1. 1

    Hi,

    great tutorial, thanks!

    Do you know how to add the zoom controls to an image view, do you always have to have a mapview present to obtain them from?

    Thanks

  2. 2

    Hi Paul,

    no, you dont need to use the built-in zoomcontrols. You can also use image-buttons oder image-views to control the zooming of the map.

    To do so, simply use 2 ImageButtons, one for “+”, one for “-” zoom

    
    <RelativeLayout
      ...
      >
      <com.google.android.maps.MapView
        ...
        android:id="@+id/map"
      />
       <ImageButton
        android:id="@+id/buttonPlus"
        android:src="@drawable/plus"
        android:layout_alignTop="@id/map"
        android:layout_alignLeft="@id/map"
        ...
       />
       <ImageButton
        android:id="@+id/buttonMinus"
        android:src="@drawable/minus"
        android:layout_alignTop="@id/map"
        android:layout_toRightOf="@id/buttonPlus"
        ...
       />
    </RelativeLayout>
    

    When initialising your buttons, simply use the Methods:

    theMap.getController().zoomIn();
    theMap.getController().zoomOut();
    

    to zoom the map by yourself

  3. 3

    Hi, thank you for a speedy response!

    I think I did not explain myself well.

    What I mean is how do you get to the zoom controls as they appear in the Pictures application?

    I have an image displayed which I need to zoom but I do not understand how to get the zoom controls to work with images.

    Your code showed me how to place them within a relative layout but I do not know how attach the controls?

    Thanks

  4. 4

    Hi Paul,

    Do you want to zoom a google map, or do you want to zoom an image?

  5. 5

    Hi,

    I want to zoom an image. I see the Android G1 has a Pictures application that allows the user to zoom an image using the zoom controls.

  6. 6

    Hi,

    sorry I did not try this yet. When I do i will post about it in this blog.

    Unfortunately my next steps are to continue this series.

  7. 7

    Hi,
    Thanks for your fabulous tutorial examples!
    I re-do your example in my Eclipse step by step, and it can be compled properly. However, I could not run it on Android Emulator, the error message shows that the application has stopped unexpectedly.
    I do not know how to fix it and I appreciate your response in advance.

  8. 8

    Hi,

    I have got the problem. That is due to my stupid miss “android” between “google” and “maps” in “com.google.android.maps.MapView” in main.xml.
    Thank you anyway and hope your more wonderful tutorial about android development.

  9. 9

    Hi,

    I am able to run the above sample application and get the google map, but when i send the latitude,longitude values from telnet, it doesn’t show the pin at he given location.

    Can you help me what might be the problem?

    Regards, Edwin

  10. 10

    Hi Edwin,

    sometimes the map is not positioned automatically to the new position. Try to search it on the map and then resend long/lat values.

    In addition check the following things.
    - Do you add the overlay to the map?
    - Is the permission “android.permission.ACCESS_FINE_LOCATION” set?
    - Is there an error in the logcat view?

  11. 11

    I am not able to add the overlay to map.I get the message application stopped unexpectedly.I get this message when i include these lines :
    myLocOverlay.enableMyLocation();
    myLocOverlay.enableCompass();

    can you please help me fix it?

  12. 12

    Hi Ann,

    I suppose you did not set all needed permissions. You need to set the permission “android.permission.ACCESS_FINE_LOCATION” to access the LocationManager.

    Try to verify all permissions, you also should check the LogCat view (Eclipse) and have a lookt at the stacktrace of the thrown exception.

    Hope that helps,
    Andreas

  13. 13

    Hi Andreas,

    Thanks for the guidance after adding all the permissions i get these errors:
    05-24 13:02:47.547: ERROR/vold(538): Error opening switch name path ‘/sys/class/switch/test2′ (No such file or directory)
    05-24 13:02:47.547: ERROR/vold(538): Error bootstrapping switch ‘/sys/class/switch/test2′ (m)
    05-24 13:02:47.547: ERROR/vold(538): Error opening switch name path ‘/sys/class/switch/test’ (No such file or directory)
    05-24 13:02:47.547: ERROR/vold(538): Error bootstrapping switch ‘/sys/class/switch/test’ (m)
    05-24 13:02:47.648: ERROR/flash_image(544): can’t find recovery partition
    05-24 13:02:57.269: ERROR/MemoryHeapBase(568): error opening /dev/pmem: No such file or directory
    05-24 13:02:57.269: ERROR/SurfaceFlinger(568): Couldn’t open /sys/power/wait_for_fb_sleep or /sys/power/wait_for_fb_wake
    05-24 13:02:57.298: ERROR/GLLogger(568): couldn’t load library (Cannot find library)
    05-24 13:02:57.378: ERROR/GLLogger(568): couldn’t load library (Cannot find library)
    05-24 13:02:59.498: ERROR/BatteryService(568): Could not open ‘/sys/class/power_supply/usb/online’
    05-24 13:02:59.498: ERROR/BatteryService(568): Could not open ‘/sys/class/power_supply/battery/batt_vol’
    05-24 13:02:59.498: ERROR/BatteryService(568): Could not open ‘/sys/class/power_supply/battery/batt_temp’
    05-24 13:02:59.758: ERROR/EventHub(568): could not get driver version for /dev/input/mouse0, Not a typewriter
    05-24 13:02:59.787: ERROR/System(568): Failure starting core service
    05-24 13:02:59.787: ERROR/System(568): java.lang.SecurityException
    05-24 13:02:59.787: ERROR/System(568): at android.os.BinderProxy.transact(Native Method)
    05-24 13:02:59.787: ERROR/System(568): at android.os.ServiceManagerProxy.addService(ServiceManagerNative.java:146)
    05-24 13:02:59.787: ERROR/System(568): at android.os.ServiceManager.addService(ServiceManager.java:72)
    05-24 13:02:59.787: ERROR/System(568): at com.android.server.ServerThread.run(SystemServer.java:163)
    05-24 13:02:59.787: ERROR/AndroidRuntime(568): Crash logging skipped, no checkin service
    05-24 13:02:59.799: ERROR/EventHub(568): could not get driver version for /dev/input/mice, Not a typewriter
    05-24 13:03:00.478: ERROR/LockPatternKeyguardView(568): Failed to bind to GLS while checking for account
    05-24 13:03:03.307: ERROR/ApplicationContext(568): Couldn’t create directory for SharedPreferences file shared_prefs/wallpaper-hints.xml
    05-24 13:03:08.418: ERROR/MediaPlayerService(542): Couldn’t open fd for content://settings/system/notification_sound
    05-24 13:03:08.418: ERROR/MediaPlayer(568): Unable to to create media player
    05-24 13:03:03.273: ERROR/ActivityThread(608): Failed to find provider info for android.server.checkin
    05-24 13:03:04.462: ERROR/ActivityThread(608): Failed to find provider info for android.server.checkin
    05-24 13:03:04.542: ERROR/ActivityThread(608): Failed to find provider info for android.server.checkin
    05-24 13:03:12.902: ERROR/ActivityThread(728): Failed to find provider info for com.google.settings
    05-24 13:03:14.092: ERROR/MapActivity(728): Couldn’t get connection factory client

    can you please guide me how to overcome these errors?

  14. 14

    Finally a tutorial which is up to date with the latest SDK! I am getting exactly the same error like Ann.

    Also, do you know where to find the Google Android Maps API? The link

    http://developer.android.com/reference/com/google/android/maps/package-summary.html

    which is Google’s first hit is broken!

  15. 15

    Hello Ann, Hello Lex,

    i adjusted this tutorial for sdk 1.5 now. There was a small issue regarding the zoom-Controls (This works much easier in sdk 1.5 now). I also updated the Paths to the debug.keystores.

    You can now simply activate the zoom controls of the google map by using the method:
    “theMap.setBuiltInZoomControls(true);”

    Feel free to retry the new version of the java file. I would be glad about a response.

  16. 16

    hi Andreas,

    Thanks.I was able to get expected results.
    When i went through google apis on android sdk1.5 many packages have been removed especially navigation(overlay controller,DrivingDirections etc) classes.How can we implement them on android 1.5?

  17. 17

    Looks like I had a black screen coz I was using myLocOverlay.enableCompass(). I presume I will need it eventually for my navigation application, but that’s out of the scope of this post ;)

  18. 18

    hey…ven i run thid appln i m gettin de error mess,”Could not find MapView.apk!”
    how do i solve dis….plz help

  19. 19

    Hello Sany,

    you provide not enough information to solve this problem. Seems you have some problems with your SDK itself. Try to reselect the Android Virtual Device (AVD) inside Eclipse and try again.

    If this will not work … try to search in the Google Groups …
    http://groups.google.com/group/android-beginners/browse_thread/thread/0621da80d4b23f08

    Many Greetings,
    Andreas

  20. 20

    Hi Andreas Frey,

    this is tutorial is superb,it is do step by step,
    am seeing these 3 versions,how i can approach your
    other tutorials..means further tutorail..if u see this comment..please give some suggestion..how i can follow your tutorial..

  21. 21

    Ok, as so often trying is the best way to learn. :-)

    I found a solution for my question:

    GeoPoint myLoc = new GeoPoint(myLocOverlay.getMyLocation().getLatitudeE6(),
    myLocOverlay.getMyLocation().getLongitudeE6());
    mapController.animateTo(myLoc);

    Thanks again!

    Rudi

  22. 22

    However this is not possible with a german operating system. Due to a bug in android concerning the different localised date format. But you can use telnet to connect to the emulator console and send a new position to the emulator.

    1. open a terminal
    2. type “telnet localhost 5554″ – you should now be connected to the emulator
    3. send the geo fix command, for example “geo fix 9 49“

    ====>>>>> I don’t know how to run it, someone please helps

  23. 23

    Hi, Thanks for the tutorial but I have got a problem.
    I have followed each step precisely but eclipse does not recagnize the google imports. e.g:

    import com.google.android.maps.MapActivity;

    how can I solve this problem? thanks in advance

  24. 24

    Please be sure to set the Android Build Target to the version with Google API, not only Android. (->Project properties -> Android)

  25. 25

    Thank you so much , problem solved .

  26. 26

    Hi,
    another question , I have typed
    telnet localhost 5554
    and I got a connection refused error,
    I either looked through nmap localhost but there wasn’t such an open port and I have tried other open ports but they worked neither?

  27. 27

    When you start the emulator, the port number it uses should be visible at the title of the emulator-window. Use the telnet command with that port.

  28. 28

    I have done as u directed. I am getting the grids of the google maps but not getting the maps on my android emulator.I donno if it is Internet problem. But i have set the internet permissions also.I am struggling to solve this problem from past three days.I have project demo on saturday. Could anyone help me on this issue as early as possible

  29. 29

    An empty grid indicates, you have no valid Google maps API key. Have a look at this: http://code.google.com/intl/de-DE/android/add-ons/google-apis/mapkey.html

  30. 30

    Thx very much!

    I had a lot of trouble getting the tutorials on internet running (DMMS didn’t work and I couldn’t find out why) but finally it all comes together by reading your blog. Part 3 also helps to get my first Android application up and running.

    Thx again!
    Tschüss,
    Rob (NL)

  31. 31

    Good tutorial, wish I’d found it sooner, however on mine there is nothing showing for my location (no pin nor blue dot), also is it possible to change the marker with my own image?

    Thanks,
    Dez (UK)

Kommentar abgeben