I am trying to incorporate the new Google Maps Android API v2 into an application using the Android Support Library. I've gone through many iteration to try to get somewhere to work and now I have given up and thought I should ask here.
I went to the API Console, created a project, enabled Google Maps API v2 for Android, created a debug KEY as required and pasted it on the manifest. No authentication problems or anything like that. Pretty sure I did this right.
In my project's libs
folder I put android-support-v4.jar
(via project right-click->Android->Add Support Library...). In Eclipse I did File->Import->Android->Existing Android Code Into Workspace and imported the latest (rev 3) of android-sdk/google/google_play_services/libproject/google-play-services_lib. Then I added it as a dependency library to my project (project right-click->Properties->Android->Add it as a library dependency on the bottom.
In my manifest I have:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<permission
android:name="myapp.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/>
<All the uses-permission required like INTERNET, ACCESS_NETWORK_STATE, WRITE_EXTERNAL_STORAGE, FINE AND COARSE LOCATION, etc>
<uses-permission android:name="myapp.permission.MAPS_RECEIVE"/>
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
<application ...>
...
<uses-library android:name="com.google.android.maps" />
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AI..."/>
</application>
In my mainview.xml I have:
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
class="com.google.android.gms.maps.SupportMapFragment" />
Now on MainView.java I have:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
public class MainView extends FragmentActivity ... {
private GoogleMap mMap;
@Override
protected void onResume() {
...
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.map);
SupportMapFragment mapFragment = (SupportMapFragment)fragment;
mMap = mapFragment.getMap();
//PROBLEM: mMap is null here even though mapFragment is not
}
}
Then I thought I probably need to initialize the fragments so I added in my onCreate
after setting the content view:
//Fragments
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.map, SupportMapFragment.newInstance());
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.commit();
Then I said, maybe it's not SupportMapFragment
but I actually should refer to the actual fragment, and in my onResume
I did:
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.map);
SupportMapFragment mapFragment = (SupportMapFragment)fragment;
//Fragments
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.map, mapFragment);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.commit();
mMap = mapFragment.getMap();
mMap
is again null after this.
Then I saw there is a MapsInitializer
class, so I thought maybe I should call that first.
So I added the code before getting the fragment in the above code:
try {
MapsInitializer.initialize(this);
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
With this Logcat reported the warning (line 313 is the MapsInitializer.initialize(this)
):
com.google.android.gms.common.GooglePlayServicesNotAvailableException
at com.google.android.gms.internal.n.c(Unknown Source)
at com.google.android.gms.internal.n.a(Unknown Source)
at com.google.android.gms.maps.MapsInitializer.initialize(Unknown Source)
at myapp.activities.MainView.inflateSelectedViewAndSetData(MainView.java:313)
at myapp.activities.MainView.onClick(MainView.java:642)
at android.view.View.performClick(View.java:3153)
at android.view.View$PerformClick.run(View.java:12148)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:152)
at android.app.ActivityThread.main(ActivityThread.java:4615)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
Throughout my attempts Logcat would report the following warning:
Google Play services out of date. Requires 2010100 but found 1013
This could be a/the culprit but I found no solution.
At this point I am out of ideas. I read several threads here, here, here but none of the suggestions resolved the problem. On the latter they suggest not including the project dependency and just including the jar file. Well, that did not work either using either google-play-services.jar
from the google-play-services_lib/libs
folder or exporting my own jar from that project.
By the way I am running on an actual device (2.3.5 and a tablet with 3.2), not the emulator.
Any help wholeheartedly appreciated. :)
UPDATE:
The solution is below by qubit.
As far exporting the library dependency, a neat way to not have to deal with it (which is a pain when dealing with repositories) is to use FatJar and export the google_play_services_lib
project (which I DID NOT create a local copy from because when it updates I don't want to re-import), and include tha output fat jar file in your project as another jar file.
NOTE: When choosing which jar files to include in the fat jar, I had to exclude the annotations.jar
file as it was already pre-included and was causing errors for duplication.
Now all I have to do is include the google_play_services_rev_3.jar
in my project's libs
folder and I am good to go.
Download and install the latest
Google Play services
from the Play Store. For some reason, I couldn't find it by searching. By running the sample app from the SDK in the folder/extras/google/google_play_services/samples/maps
I was prompted to install the upgrade and was taken to the Play Store to do that.I had the same problem in my project. The solution is very simple just handle the possibility that
((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
can returnnull
. If you will handlenull
the buid-inSupportMapFragment
will handleGoogle Play services out of date.
error and will show you insted of map localized message and button for updating the Google Play Service just like this that @qubz is telling about in sample project.Code from sample:
And result:
As documentation sad
as described at the bottom of that link; http://developer.android.com/google/play-services/setup.html
and here comes sample code to handle this properly;