Android Question [SOLVED] Google Maps example not working

JackKirk

Well-Known Member
Licensed User
Longtime User
I have successfully installed Google Maps on my B4A 5.80 IDE using this tutorial:

https://www.b4x.com/android/forum/threads/google-maps.63930/#post-404386

I have loaded and successfully run the example in this tutorial:

B4X:
#Region  Project Attributes
    #ApplicationLabel: xxx
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
   
    #AdditionalRes: $AndroidSDK$\extras\google\google_play_services\libproject\google-play-services_lib\res, com.google.android.gms
    #ExcludeClasses: .games, .drive, .fitness, .wearable, .measurement, .cast, .auth, .nearby
    #ExcludeClasses: .tagmanager, .analytics, .wallet, .plus, .vision, .gcm
    'Remove the following line if you use AdMob
    #ExcludeClasses: .ads

#End Region

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

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
   Private gmap As GoogleMap
   Private MapFragment1 As MapFragment

End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
   Activity.LoadLayout("1")
   If MapFragment1.IsGooglePlayServicesAvailable = False Then
     ToastMessageShow("Please install Google Play Services.", True)
   End If

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub MapFragment1_Ready
   gmap = MapFragment1.GetMap
   Dim m1 As Marker = gmap.AddMarker(10, 30, "test")
   m1.Snippet = "This is the snippet"
End Sub
using a manifest as suggested by the tutorial:

B4X:
'This code will be applied to the manifest file during compilation.
'You do not need to modify it in most cases.
'See this link for for more information: https://www.b4x.com/forum/showthread.php?p=78136
'minSdkVersion changed from 5 to 14 as per:
'https://www.b4x.com/android/forum/threads/google-maps.63930/#post-404386
AddManifestText(
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19"/>
<supports-screens android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
'End of default text.

'For Google Maps, as per
'https://www.b4x.com/android/forum/threads/google-maps.63930/#post-404386
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="AIza..."/>
   <meta-data android:name="com.google.android.gms.version"
   android:value="@integer/google_play_services_version" />)

(the "AIza...' is the API key which I have blocked out).

There is a non-Designer based example in the documentation at:

https://www.b4x.com/android/help/googlemaps.html#mapfragment

When I develop an example based on this (using exact same manifest):
B4X:
#Region  Project Attributes
    #ApplicationLabel: xxx
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
   
    #AdditionalRes: $AndroidSDK$\extras\google\google_play_services\libproject\google-play-services_lib\res, com.google.android.gms
    #ExcludeClasses: .games, .drive, .fitness, .wearable, .measurement, .cast, .auth, .nearby
    #ExcludeClasses: .tagmanager, .analytics, .wallet, .plus, .vision, .gcm
    'Remove the following line if you use AdMob
    #ExcludeClasses: .ads

#End Region

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

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
  Dim mFragment As MapFragment
  Dim gmap As GoogleMap
  Dim MapPanel As Panel
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
  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
  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

I end up with a red lined log:
B4X:
** Service (starter) Create **
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
java.lang.RuntimeException: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object anywheresoftware.b4a.objects.collections.Map.Get(java.lang.Object)' on a null object reference
    at anywheresoftware.b4a.objects.MapFragmentWrapper$1.onMapReady(MapFragmentWrapper.java:196)
    at com.google.android.gms.maps.MapFragment$zza$1.zza(Unknown Source)
    at com.google.android.gms.maps.internal.zzo$zza.onTransact(Unknown Source)
    at android.os.Binder.transact(Binder.java:380)
    at com.google.android.gms.maps.internal.v$a$a.a(:com.google.android.gms.alldynamite:82)
    at maps.ei.bu$6.run(Unknown Source)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:145)
    at android.app.ActivityThread.main(ActivityThread.java:5832)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object anywheresoftware.b4a.objects.collections.Map.Get(java.lang.Object)' on a null object reference
    at anywheresoftware.b4a.objects.MapFragmentWrapper$1.onMapReady(MapFragmentWrapper.java:181)
    ... 13 more

Which I can not fathom.

Any help would be greatly appreciated...
 

JackKirk

Well-Known Member
Licensed User
Longtime User
Erel,

I did that in the first part of post #1, I would like to know how to set up Google Maps without using the designer.

Thanks...
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
I actually found a way to set up Google Maps v2.00 on B4A 5.80+ without using the Visual Designer:
B4X:
#Region  Project Attributes
    #ApplicationLabel: Pocket Theodolite
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
 
    #AdditionalRes: $AndroidSDK$\extras\google\google_play_services\libproject\google-play-services_lib\res, com.google.android.gms
    #ExcludeClasses: .games, .drive, .fitness, .wearable, .measurement, .cast, .auth, .nearby
    #ExcludeClasses: .tagmanager, .analytics, .wallet, .plus, .vision, .gcm
    'Remove the following line if you use AdMob
    #ExcludeClasses: .ads

#End Region

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

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim mFragment As MapFragment
    Dim gmap As GoogleMap
 
    Dim Map_Panel As Panel
    Dim Map_Props As Map
    Dim Map_Label As Label
 
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    Map_Panel.Initialize("")
    Activity.AddView(Map_Panel, 0, 0, 100%x, 100%y)

    Map_Props.Initialize

    'Keys for Map_Props come from <designerProperty> entries in ...\Additional Libraries\GoogleMaps.xml
    '  <designerProperty>key:MapType, displayname:Map Type, fieldtype:String, defaultvalue:NORMAL, list:NORMAL|SATELLITE|TERRAIN</designerProperty>
    '  <designerProperty>key:MyLocationEnabled, displayname:My Location Enabled, fieldtype:Boolean, defaultvalue:True, description:Whether to show the user location on the map.</designerProperty>
    '  <designerProperty>key:TrafficEnabled, displayname:Traffic Enabled, fieldtype:Boolean, defaultvalue:False, description:Whether to show the traffic layer.</designerProperty>
    '  <designerProperty>key:BuildingsEnabled, displayname:Building Enabled, fieldtype:Boolean, defaultvalue:False, description:Whether to show the buildings layer.</designerProperty>
    '  <designerProperty>key:auto1CompassEnabled, displayname:Compass Enabled, fieldtype:Boolean, defaultvalue:True</designerProperty>
    '  <designerProperty>key:auto1MyLocationButtonEnabled, displayname:MyLocation Button Enabled, fieldtype:Boolean, defaultvalue:True</designerProperty>
    '  <designerProperty>key:auto1RotateGesturesEnabled, displayname:Rotate Gestures Enabled, fieldtype:Boolean, defaultvalue:True</designerProperty>
    '  <designerProperty>key:auto1ScrollGesturesEnabled, displayname:Scroll Gestures Enabled, fieldtype:Boolean, defaultvalue:True</designerProperty>
    '  <designerProperty>key:auto1TiltGesturesEnabled, displayname:Tilt Gestures Enabled, fieldtype:Boolean, defaultvalue:True</designerProperty>
    '  <designerProperty>key:auto1ZoomControlsEnabled, displayname:Zoom Controls Enabled, fieldtype:Boolean, defaultvalue:True</designerProperty>
    '  <designerProperty>key:auto1ZoomGesturesEnabled, displayname:Zoom Gestures Enabled, fieldtype:Boolean, defaultvalue:True</designerProperty>
    '[display name] defines property name as seen in Designer

    'By pure experimentation, these properties must be explicitly set
    Map_Props.Put("MapType","NORMAL")                        'Map Type
    Map_Props.Put("MyLocationEnabled", True)                'My Location Enabled
    Map_Props.Put("TrafficEnabled", False)                    'Traffic Enabled
    Map_Props.Put("BuildingsEnabled", False)                'Building Enabled

    'These properties do not have to be explicitly set and presumably drop to their respective defaults if not
    'Map_Props.Put("auto1CompassEnabled", True)                'Compass Enabled
    'Map_Props.Put("auto1MyLocationButtonEnabled", True)    'MyLocation Button Enabled
    'Map_Props.Put("auto1RotateGesturesEnabled", True)        'Rotate Gestures Enabled
    'Map_Props.Put("auto1ScrollGesturesEnabled", True)        'Scroll Gestures Enabled
    'Map_Props.Put("auto1TiltGesturesEnabled", True)        'Tilt Gestures Enabled
    'Map_Props.Put("auto1ZoomControlsEnabled", True)        'Zoom Controls Enabled
    'Map_Props.Put("auto1ZoomGesturesEnabled", True)        'Zoom Gestures Enabled

    Map_Label.Initialize("")

    If mFragment.IsGooglePlayServicesAvailable = False Then
        ToastMessageShow("Google Play services not available.", True)
    Else
        mFragment.Initialize("Map", Activity)
        mFragment.DesignerCreateView(Map_Panel, Map_Label, Map_Props)
     
        'Map_Label does not appear to be needed, last statement can also be:
        'mFragment.DesignerCreateView(Map_Panel, Null, Map_Props)
     
    End If
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Map_Ready
 
    'This is essential
    Map_Panel.BringToFront
 
    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 * 2)
        gmap.AnimateCamera(cp)
    End If
End Sub
I can't say I am super impressed, there seem to be a couple of issues:

  1. A version of the map appears on the Activity, as well as the Map_Panel.
  2. Map_Panel has to be brought to front (I would have thought this was default).
  3. The mFragment.Initialize method doesn't appear to follow the same syntax as required to set up other custom views:
mFragment.Initialize(EventName as String, Parent as android.view.ViewGroup)

-vs-

xxx.Initialize(TargetModule As Object, EventName As String) (from custom views tutorial)

If nothing else I would be interested in knowing what this is about.
===================================================

Another (better) option is to create a layout with only the map and add it one or more times by loading the layout file to a panel.
I have also already done this - works OK but I have to agree with the sentiments expressed here:

https://www.b4x.com/android/forum/threads/iui8-create-views-in-the-code.64071/#post-405521

In a lot of circumstances using the Designer is akin to using the proverbial sledgehammer to crack the proverbial (pea)nut - and it does not help with code clarity and documentation.
 
Upvote 0
Top