Android Tutorial (old) Google Maps Android v2 tutorial

Status
Not open for further replies.
If you are using B4A v5.80+ then please follow this tutorial: https://www.b4x.com/android/forum/threads/google-maps.63930/#post-404386

GoogleMaps library requires v2.50 or above.

GoogleMaps library allows you to add Google maps to your application. This library requires Android 3+ and will only work on devices with Google Play service.

This tutorial will cover the configuration steps required for showing a map.

1. Download Google Play services - From the IDE choose Run AVD Manager and then choose Tools - SDK Manager. Select Google Play services under the Extras node and install it:

SS-2012-12-18_18.28.04.png


2. Copy google-play-services.jar to the libraries folder - This file is available under:
C:\<android sdk>\extras\google\google_play_services\libproject\google-play-services_lib\libs (ignore the extra space that the forum script insists on adding)
You should copy it to the libraries folder.

2.5. Download the attached library, unzip it and copy to the libraries folder.

3. Find the key signature - Your application must be signed with a private key other than the debug key. After you select a new or existing key file (Tools - Private Sign Key) you should reopen the private key dialog. The signature information will be displayed (increase the dialog size as needed).
The value after SHA1 is required for the next step:

SS-2012-12-18_18.11.34.png


4. Create an API project - Follow these steps and create an API project.
You should follow the steps under "Creating an API Project" and "Obtaining an API key".

Tips:
- Make sure to select "Google Maps Android API v2" in the services list and not one of the other similar services.
- Under "Simple API Access" you should select "Key for Android apps (with certificates".

5. Add the following code to the manifest editor:
B4X:
AddManifestText( <permission
          android:name="$PACKAGE$.permission.MAPS_RECEIVE"
          android:protectionLevel="signature"/>
      <uses-feature android:glEsVersion="0x00020000" android:required="true"/>)

AddApplicationText(<meta-data
    android:name="com.google.android.maps.v2.API_KEY"
    android:value="AIzaSyCzspmxxxxxxxxxxxxx"/>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"
    />)
AddPermission(android.permission.ACCESS_NETWORK_STATE)
You should replace the value after android:value with the key you received in the previous step.

6. Add an #AdditionalRes attribute to the main activity:

You should add a reference to Google play resources by adding the following line:
B4X:
#AdditionalRes: <google-play-services res folder>, com.google.android.gms
For example:

#AdditionalRes: C:\android-sdk-windows\extras\google\google_play_services\libproject\google-play-services_lib\res, com.google.android.gms

Run the following code:
B4X:
'Activity module
Sub Process_Globals

End Sub

Sub Globals
   Dim mFragment As MapFragment
   Dim gmap As GoogleMap
   Dim MapPanel As Panel
End Sub

Sub Activity_Create(FirstTime As Boolean)
   MapPanel.Initialize("")
   Activity.AddView(MapPanel, 0, 0, 100%x, 100%y)
   If mFragment.IsGooglePlayServicesAvailable = False Then
      ToastMessageShow("Google Play services not available.", True)
   Else
      mFragment.Initialize("Map", MapPanel)
   End If
End Sub
Sub Map_Ready
   Log("map ready")
   gmap = mFragment.GetMap
   If gmap.IsInitialized = False Then
      ToastMessageShow("Error initializing map.", True)
   Else
      gmap.AddMarker(36, 15, "Hello!!!")
      Dim cp As CameraPosition
      cp.Initialize(36, 15, gmap.CameraPosition.Zoom)
      gmap.AnimateCamera(cp)
   End If
End Sub

You should see:

SS-2012-12-18_18.25.14.png


If you see a "white map" then there is most probably a mismatch between the: package name, sign key and the API key (from the manifest editor).

Google documentation: https://developers.google.com/maps/documentation/android/intro
Note that there is a required attribution which you must include in your app (see above link). You can get the string by calling MapFragment.GetOpenSourceSoftwareLicenseInfo.

V1.01: Fixes a bug in AddMarker2.
 

Attachments

  • GoogleMaps.zip
    17.8 KB · Views: 11,430
Last edited:

Carlos Bernardino

New Member
Licensed User
Longtime User
Yes, Martin. I already use OSM and I think it's a better alternative for mobile apps than Google Maps. However, I have now to find a way of adding a Google Maps satellite view to my application. As I've noticed, I have to use a WebView for that. ;)
 

ValDog

Active Member
Licensed User
Longtime User
GoogleMapsExtras has been updated to version 1.35

The new Snapshot method takes a snapshot of the current map.
The event SnapshotReady is raised when the snapshot has been created, the snapshot passed to your event handling Sub as a Bitmap.

B4X:
Sub Process_Globals
   '   i'll use a Process_Global to enable me to pass the snapshot Bitmap from this Activity to the SnapshotViewer Activity
   Dim LastSnapshot As Bitmap
End Sub

Sub Globals
  Dim MapFragment1 As MapFragment
  Dim GoogleMap1 As GoogleMap
   Dim GoogleMapsExtras1 As GoogleMapsExtras
  Dim MapPanel As Panel
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("Main")
  If MapFragment1.IsGooglePlayServicesAvailable = False Then
  ToastMessageShow("Google Play services not available.", True)
  Else
  MapFragment1.Initialize("MapFragment1", MapPanel)
  End If
End Sub

Sub GoogleMapsExtras1_SnapshotReady(Bitmap1 As Bitmap)
   Log("GoogleMapsExtras1_SnapshotReady")
   LastSnapshot=Bitmap1
   StartActivity(SnapshotViewer)
End Sub

Sub MapFragment1_LongClick (Point As LatLng)
   '   a long click on the map will add a new Marker
   GoogleMap1.AddMarker(Point.Latitude, Point.Longitude, "("&Point.Latitude&", "&Point.Longitude&")")
End Sub

Sub MapFragment1_Ready
  Log("MapFragment1_Ready")
  GoogleMap1 = MapFragment1.GetMap
  If GoogleMap1.IsInitialized = False Then
  ToastMessageShow("Error initializing map.", True)
  Else
     GoogleMap1.AddMarker(52.75619, 0.3980, "Home Sweet Home")
   
  Dim CameraPosition1 As CameraPosition
  CameraPosition1.Initialize(52.75619, 0.3980, 6)
  GoogleMap1.AnimateCamera(CameraPosition1)
  End If
End Sub

Sub SnapshotButton_Click
   Log("SnapshotButton_Click")
   GoogleMapsExtras1.Snapshot(GoogleMap1, "GoogleMapsExtras1")
End Sub

This is the Main Activity, it shows a basic map with a single Marker.
A long click on the map adds a new Marker.

A click on the 'Take snapshot' button calls the new Snapshot method.
When the 'SnapshotReady' event is raised, the snapshot (a Bitmap) is saved as a ProcessGlobal and a new Actvitiy started.
The new Activity contains just an ImageView and displays the snapshot Bitmap centered in the ImageView.

IMPORTANT: In order to use the new Snapshot method you must ensure that your b4a additional libraries folder contains the latest version of google-play-services.jar.
Run the Android SDK Manager utility and check whether or not you have the latest version, i have tested with version 10 of the Google Play servcies library
.

Your attention is drawn to the notes from the GoogleMap API reference:



Martin.



Martin,

When I go click Snapshot I crash with the following error:


GoogleMapsExtras1.Snapshot(gmap, "GoogleMapsExtras1")
java.lang.NoClassDefFoundError: uk.co.martinpearman.b4a.googlemapsextras.GoogleMapsExtras$1
at uk.co.martinpearman.b4a.googlemapsextras.GoogleMapsExtras.Snapshot(GoogleMapsExtras.java:238)
at b4a.GoogleMaps.main._snapshotbutton_click(main.java:474)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:170)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:158)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:154)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:64)
at android.view.View.performClick(View.java:4424)
at android.view.View$PerformClick.run(View.java:18383)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4998)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
at dalvik.system.NativeStart.main(Native Method)


Can you give me a clue as to what the problem may be?
 

warwound

Expert
Licensed User
Longtime User
I'd guess that you're running your app in rapid debug mode - there's been a few reports that GoogleMapsExtras fails when run in rapid debug mode.
Solution is to use Release or Legacy debug mode.

If that's not the problem then maybe your version of Google Play Services library is not up to date.
Run your Android SDK Manager and ensure you have the latest version - and also be sure that once the latest version has been downloaded to the Android SDK folder that you copy the latest version to your b4a additional libraries folder.

Martin.
 

abceasyas123

Member
Licensed User
Longtime User
Help for complete Newbie please.

When I try this tutorial I get "Google Play Services Not Available". I can see why the code displays this message, I just don't understand why the services are not available to me?

I have spent over 3 hours now trying to figure out what's going on, but as there are no other error messages on screen or in the logs, I don't know where to turn.

My app compiles without any errors or warnings
I have tried to follow the extra instructions regarding issues with the latest version of the SDK and have downloaded the suggested new jar file

I think the problem might be with my API key. I have successfully created a Google API project and activated the "Google Maps Android API v2" service. I have created an API key using the SHA1 key I created within B4A and have added the key provided back by Google to the manifest as instructed. However, when I was creating the key, I wasn't really sure what to put after the semi colon. I put ";b4a.example" as this is the text in my Project Package name. Can I just put anything after the semi-colon?

Does it matter if I compile in Debug mode or Release mode

I am currently running the app on an emulator, if I try to run on my actual handset the app actually crashes and doesn't even display the "Google Play Services Are Not available" message.

If I go to the Google API service console, it shows ZERO requests having being received

I believe I have inserted the sample code correctly, but have copied below for reference

Thanks in Advance for any help - I really am struggling to make any progress

B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
End Sub

Sub Globals
    Dim mFragment As MapFragment
      Dim gmap As GoogleMap
      Dim MapPanel As Panel
End Sub

Sub Activity_Create(FirstTime As Boolean)
    MapPanel.Initialize("")
  Activity.AddView(MapPanel, 0, 0, 100%x, 100%y)
  If mFragment.IsGooglePlayServicesAvailable = False Then
      ToastMessageShow("Google Play services not available.", True)
  Else
      mFragment.Initialize("Map", MapPanel)
  End If
  End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub Map_Ready
  Log("map ready")
  gmap = mFragment.GetMap
  If gmap.IsInitialized = False Then
      ToastMessageShow("Error initializing map.", True)
  Else
      gmap.AddMarker(36, 15, "Hello!!!")
      Dim cp As CameraPosition
      cp.Initialize(36, 15, gmap.CameraPosition.Zoom)
      gmap.AnimateCamera(cp)
  End If
End Sub
 

ValDog

Active Member
Licensed User
Longtime User
The way that Erel created the b4a GoogleMaps library did not expose the MarkerOptions object and this is the object you'd need to use to create a Marker that is initially not visible.

So i've now partly wrapped the MarkerOptions object and added a new method to GoogleMapsExtras AddMarker(MarkerOptions1 As MarkerOptions) As Marker.

Have a look at this example code:

B4X:
Sub Process_Globals

End Sub

Sub Globals
    Dim MapFragment1 As MapFragment
    Dim GoogleMap1 As GoogleMap
   Dim GoogleMapsExtras1 As GoogleMapsExtras
    Dim MapPanel As Panel
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("Main")
    If MapFragment1.IsGooglePlayServicesAvailable = False Then
        ToastMessageShow("Google Play services not available.", True)
    Else
        MapFragment1.Initialize("MapFragment1", MapPanel)
    End If
End Sub

Sub MapFragment1_Ready
    Log("MapFragment1_Ready")
    GoogleMap1 = MapFragment1.GetMap
    If GoogleMap1.IsInitialized = False Then
        ToastMessageShow("Error initializing map.", True)
    Else
      '   use the new MarkerOptions method to create and add a Marker to the map
     
      Dim MarkerOptions1 As MarkerOptions
      MarkerOptions1.Initialize
     
      MarkerOptions1.Position2(52.75619, 0.3980).Snippet("Home is where the heart is").Title("Home Sweet Home").Visible(True)
      Dim Marker1 As Marker=GoogleMapsExtras1.AddMarker(GoogleMap1, MarkerOptions1)
     
        Dim CameraPosition1 As CameraPosition
        CameraPosition1.Initialize(52.75619, 0.3980, 6)
        GoogleMap1.AnimateCamera(CameraPosition1)
    End If
End Sub

MarkerOptions
Methods:

  • Anchor (U As Float, V As Float) As MarkerOptions
  • Draggable (Draggable As Boolean) As MarkerOptions
  • Initialize
  • IsInitialized As Boolean
  • Position (LatLng1 As LatLng) As MarkerOptions
  • Position2 (Latitude As Double, Longitude As Double) As MarkerOptions
  • Snippet (Snippet As String) As MarkerOptions
  • Title (Title As String) As MarkerOptions
  • Visible (Visible As Boolean) As MarkerOptions

I've not fully wrapped the MarkerOptions object, there are various other methods that can also be wrapped, take a look: https://developers.google.com/maps/...m/google/android/gms/maps/model/MarkerOptions.

Code and beta library files attached - i'll complete the MarkerOptions object hopefully tomorrow and get it uploaded to the GoogleMapsExtras thread.

When the device orientation changes you have no way to tell the activity not to destroy all of it's objects and variables - that's the way android works.

You could keep references as process global objects - not sure about a sticky service but i guess that's another way to keep a reference to objects you create but don't want destroyed when the orientation changes.

Note that you should not keep a reference to a Marker - a Marker is an Activity object and should be destroyed when the activity is destroyed.
Don't try to keep a process global reference to a Marker - there's no point, you can't add a Marker to the map, BUT you can keep a process global reference to a MarkerOptions object.

So create a MarkerOptions object for each of your many markers, and keep each MarkerOptions object as a process global (or try and use a service), then on orientation change you can re-create new Markers from the (already created) MarkerOptions objects.

Martin.


Martin, great job! I am able to compile and run this demo just fine, but when I try to integrate it into my main program as a separate activity I see the following error upon compile:


Parsing code. 0.20
Compiling code. 0.27
Compiling layouts code. 0.03
Generating R file. 0.07
Compiling generated Java code. Error
B4A line: 50
MarkerG = GoogleMapsExtras1.AddMarker(gmap, MarkerOptions1)
javac 1.7.0_45
src\b4a\gsight\mapg.java:417: error: inconvertible types
_markerg.setObject((uk.co.martinpearman.b4a.osmdroid.views.overlays.MyOverlayItem)(mostCurrent._googlemapsextras1.AddMarker((com.google.android.gms.maps.GoogleMap)(mostCurrent._gmap.getObject()),(com.google.android.gms.maps.model.MarkerOptions)(_markeroptions1.getObject())).getObject()));
^
required: MyOverlayItem
found: Marker


I've been pulling my hair out trying to figure out why I'm seeing this. Can you shed any light on it?

Thanks, Val
 

warwound

Expert
Licensed User
Longtime User
@ValDog Looks like you have checked both OSMDroid and GoogleMaps libraries in the IDE.
They both contain a Marker object and that's confusing the compiler.

Uncheck OSMDroid and try again.

Martin.
 

warwound

Expert
Licensed User
Longtime User

In the B4A IDE (Tools > Configure Paths) which version of the android.jar file (from the Android SDK) are you using?
You need to set the path in the IDE to use a version of android.jar for Android 3+, if it is set to a version lower than 3 then that might explain the issue.

Martin.
 

ValDog

Active Member
Licensed User
Longtime User
@ValDog Looks like you have checked both OSMDroid and GoogleMaps libraries in the IDE.
They both contain a Marker object and that's confusing the compiler.

Uncheck OSMDroid and try again.

Martin.


Martin, I believe you are correct -I do have OSMDroid lib in the IDE. So, apparently I can't use both - which poses a problem for me w/r to using offline maps. Is there a way I can to that with Google Maps?
 

warwound

Expert
Licensed User
Longtime User
Take a look here: http://www.b4x.com/android/forum/threads/osmdroid-mapview-for-b4a-tutorial.16310/page-12#post-184125

I have already recompiled OSMDroid with it's 'Marker' object renamed to 'OSMDroid_Marker' so that will fix this issue for you.
But note that as and when i update OSMDroid, any updates will not include the renamed Marker object.

So for now try the recompiled version of OSMDroid with it's renamed Marker.
If i update OSMDroid and you want to use the update then contact me and i'll recompile the update with the renamed Marker object for you.

Martin.
 

abceasyas123

Member
Licensed User
Longtime User
Hi

IDE is pointing to android-sdk\platforms\android-19\android.jar, I think that -19 relates to Android 4.4.2? (although my understanding of what the SDK Manager is telling me is poor)

I have also tried given my project a more unique name "com.fivelathams.daniel.mapdisplayer", generating a private key for this app and using the combination to create a new Google APIcode that I have added to the manifest.

I have also made sure that the suggested google-play-services.jar is copied to C:\Program Files (x86)\Anywhere Software\Basic4android\Libraries

Still no luck

Regards

D
 

ValDog

Active Member
Licensed User
Longtime User
Martin,

Using OSMDroid I am able to create a module which displays OSM maps, adds location markers real time as I move my android device, and draw a path line connecting my location markers. OSMDroid of course uses a MapView object. I would like to be able to do the same thing using Google Maps. The closest I've seen in the forum is Klaus' GoogleMapsPlus demo where he uses a WebView object. Is there a way to do this with the GoogleMap object?

You may have already discussed this previously and I just missed it - if so, I apologize in advance.
 

warwound

Expert
Licensed User
Longtime User
@abceasyas123

I'm not sure what to suggest next.
I am pretty sure that you cannot use an emulator to run an app that contains a GoogleMap, so make sure you always use a real device (a real device running android 3 or later).

What device are you getting these errors with?
And what android version is that device running?

@ValDog

Yes that is all possible with GoogleMaps and GoogleMapsExtras.

GoogleMaps has the AddMarker and AddPolyline methods.

GoogleMapsExtras has an AddMarker method which exposes more of the available MarkerOptions, and an AddPolygon method if you need to create Polygons.
GoogleMapsExtras also has an AddCircle method if you need to create Circles.

You might not even require GoogleMapsExtras if basic Marker and Polyline objects are all that you require.

Martin.
 

ValDog

Active Member
Licensed User
Longtime User
@abceasyas123

I'm not sure what to suggest next.
I am pretty sure that you cannot use an emulator to run an app that contains a GoogleMap, so make sure you always use a real device (a real device running android 3 or later).

What device are you getting these errors with?
And what android version is that device running?

@ValDog

Yes that is all possible with GoogleMaps and GoogleMapsExtras.

GoogleMaps has the AddMarker and AddPolyline methods.

GoogleMapsExtras has an AddMarker method which exposes more of the available MarkerOptions, and an AddPolygon method if you need to create Polygons.
GoogleMapsExtras also has an AddCircle method if you need to create Circles.

You might not even require GoogleMapsExtras if basic Marker and Polyline objects are all that you require.

Martin.


Martin,

OSMDroid library methodology has a number of developer-friendly overlays (MyLocationOverlay, PathOverlay, ScaleBarOverlay,MarkersBalloonOverlay, to name a few). Have you (or would you) considered adding this kind of functionality to the GoogleMaps library methodology?
 
Status
Not open for further replies.
Top