9

I can't get the map ! all I can get is null.

here is the code.

       public class MainActivity extends FragmentActivity {

     @Override
     protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        SupportMapFragment fragment = new SupportMapFragment();
        getSupportFragmentManager().beginTransaction()
                .add(android.R.id.content, fragment).commit();


       GoogleMap map;
        map = fragment.getMap();
             //here i cant access this snippet because map = null 
        if(map!=null){
        UiSettings mm = map.getUiSettings();
        map.setMyLocationEnabled(true);
          } }
           }

The manifest:

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.anywhere_reminder"
android:versionCode="1"
android:versionName="1.0" >

    <uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="17" />
    <uses-feature
    android:glEsVersion="0x00020000"
     android:required="true"/>

   <permission
    android:name="com.example.anywhere_reminder.permission.MAPS_RECEIVE"
    android:protectionLevel="signature" />

 <uses-permission android:name="com.example.anywhere_reminder.permission.MAPS_RECEIVE" />
 <uses-permission android:name="android.permission.INTERNET" />
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
 <uses-permission   android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"     />

    <application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity android:name="com.google.android.gms.BuildConfig" />
    <activity
        android:name="com.example.anywhere_reminder.MainActivity"
        android:label="@string/app_name" >

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        </activity>

    <meta-data
     android:name="com.google.android.maps.v2.API_KEY"
   android:value=" my key "/> 

    </application>
    </manifest>

here is the xml:

  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 tools:context=".MainActivity" >


 <fragment xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/map"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 class="com.google.android.gms.maps.MapFragment"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:text="@string/hello_world" />

  </RelativeLayout>

I tried to solve it like this solution Google Maps Android API v2 throws GooglePlayServicesNotAvailableException, out of date, SupportMapFragment.getMap() returns null .. but still did not work

UPDATE:

I got my map working now .. here is the edited working version

   public class MainActivity extends FragmentActivity {
 private GoogleMap myMap;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);

          android.support.v4.app.FragmentManager myFragmentManager = getSupportFragmentManager();
          SupportMapFragment mySupportMapFragment 
           = (SupportMapFragment)myFragmentManager.findFragmentById(R.id.map);


             myMap = mySupportMapFragment.getMap();
             if(myMap!=null)
            myMap.setMyLocationEnabled(true);


        }
Community
  • 1
  • 1
proG
  • 111
  • 1
  • 5
  • 12

5 Answers5

17

You are creating a dynamic fragment, via a FragmentTransaction. When you call commit(), the fragment has not yet been added to the screen, because the FragmentTransaction has only been scheduled to occur -- it has not occurred yet. Hence, the SupportMapFragment has not been called with onCreateView() yet, so there is no GoogleMap.

Either switch to static fragments (<fragment> tag in a layout), or delay your use of the GoogleMap until after the transaction has been processed.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Sorry :$ but how could i delay the use of GoogleMap i tried to call it in onResume() and did not work .. not sure if that what you mean – proG Feb 16 '13 at 12:03
  • @proG: After calling `commit()` on the transaction, call `post()` on some `View` (or a `Handler` if you have one). By the time the `Runnable` you schedule is invoked, the `GoogleMap` should exist. Or, again, switch to static fragments. – CommonsWare Feb 16 '13 at 13:18
  • I use a static fragment via the xml layout, but some phones still have this problem. One tester's GS2 works while another tester's GS2 does not. Could this have anything to do with Google Play Services not being available on the device? – JMRboosties May 21 '13 at 19:23
  • @JMRboosties: No, insofar as you should have figured out that was the problem long before trying to actually do anything with Maps V2. – CommonsWare May 21 '13 at 20:36
6

executePendingTransactions() in FragmentManager class was designed to fix this delay. From documantstion : After a FragmentTransaction is committed with FragmentTransaction.commit(), it is scheduled to be executed asynchronously on the process's main thread. If you want to immediately executing any such pending operations, you can call this function (only from the main thread) to do so. Note that all callbacks and other related behavior will be done from within this call, so be careful about where this is called from.

darias
  • 91
  • 4
6

I have extended the MapFragment class and added a listener. The doc about getMap() say:

... Null if the view of the fragment is not yet ready. This can happen if the fragment lifecyle have not gone through onCreateView(LayoutInflater, ViewGroup, Bundle) yet....

Then I call the listener after onCreateView. I add the class

public class MySupportMapFragment extends SupportMapFragment{

private MySupportMapFragmentListener listener;

public interface MySupportMapFragmentListener{
    public void onMapCreated(GoogleMap googleMap);
}

// value taken from source code
private static final String MAP_OPTIONS = "MapOptions";

public static MySupportMapFragment newInstance() {
        MySupportMapFragment f = new MySupportMapFragment();
        return f;
}

public static MySupportMapFragment newInstance(GoogleMapOptions options) {
        MySupportMapFragment f = new MySupportMapFragment();
        Bundle args = new Bundle();
        args.putParcelable(MAP_OPTIONS, options);
        f.setArguments(args);
        return f;
}

// other newInstance methods ...


/* (non-Javadoc)
 * @see android.support.v4.app.Fragment#onViewCreated(android.view.View, android.os.Bundle)
 */
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onViewCreated(view, savedInstanceState);
    // here, as doc say, the map can be initialized, or the service is not available
    if(listener!=null){
        listener.onMapCreated(getMap());
    }

}
/**
 * @return the listener
 */
public MySupportMapFragmentListener getListener() {
    return listener;
}
/**
 * @param listener the listener to set
 */
public void setListener(MySupportMapFragmentListener listener) {
    this.listener = listener;
}

}

After in the calling activity or fragment ...

    mapFragment = MySupportMapFragment.newInstance();
    mapFragment.setListener(new MySupportMapFragmentListener() {
        @Override
        public void onMapCreated(GoogleMap googleMap) {
            // TODO Auto-generated method stub          
            if(googleMap!=null){
                  // service is unaviable
            }               
        }
Davide
  • 3,407
  • 1
  • 20
  • 22
3

Move the code snippet:

GoogleMap map; map = fragment.getMap();

//here map is not null

if(map!=null){

UiSettings mm = map.getUiSettings();
map.setMyLocationEnabled(true);

}

to onResume() method, this will solve your issue.

Lei Zhang
  • 634
  • 4
  • 6
1

Another way to solve it. Implemet an interface in the MapFragment to communicate to the activity when it is ready for GoogleMap creation.

    @Override
public void onActivityCreated(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onActivityCreated(savedInstanceState);
    listener.onGoogleMapCreattion();


}

Then you just need to implement the listener in the activtiy:

    @Override
public void onGoogleMapCreation() {
    setUpMapIfNeeded();

}

    private void setUpMapIfNeeded() {
    // Do a null check to confirm that we have not already instantiated the map.
    if (mMap == null) {
         mMap = mMapFragment.getMap();
        // Check if we were successful in obtaining the map.
        if (mMap != null) {
          // The Map is verified. It is now safe to manipulate the map.
            setUpMap();

        }
    }
  }
  • Best answer. Handling the async nature of the creation process is the right way to go IMO. Anything else and your just guessing that right about now is the right time to access the object. – Brill Pappin Aug 13 '14 at 06:11