Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

MapView in fragment not working and the app freezes after calling recreate() in the host activity #11121

Closed
minthura opened this issue Feb 6, 2018 · 11 comments
Assignees
Labels
Android Mapbox Maps SDK for Android

Comments

@minthura
Copy link

minthura commented Feb 6, 2018

Platform:
Android

Mapbox SDK version:
mapbox-android-sdk:5.4.0

Steps to trigger behavior

  1. I use MapView in a fragment. All lifecycle functions are also implemented properly.
  2. I call recreate() function in the host activity for language change purpose.
  3. The app freezes and the MapView goes black.

I've provided some codes for your reference.
MapFragment.java

public class MapFragment extends Fragment {

    private MapView mapView;
    private HomeListener mListener = null;

    public MapFragment() {
        // Required empty public constructor
    }

    public static MapFragment newInstance() {
        MapFragment fragment = new MapFragment();
        return fragment;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof HomeListener) {
            mListener = (HomeListener) context;
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_map, container, false);
        mapView = view.findViewById(R.id.mapView);
        view.findViewById(R.id.btnChangeLanguage).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mListener.onLanguageChange(null);
            }
        });
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mapView.onCreate(savedInstanceState);
    }

    @Override
    public void onStart() {
        super.onStart();
        mapView.onStart();
    }

    @Override
    public void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mapView.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
        mapView.onStop();
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mapView.onLowMemory();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapView.onSaveInstanceState(outState);
    }

}

MainActivity.java

public class MainActivity extends AppCompatActivity implements HomeListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Mapbox.getInstance(this, "my-key");
        setContentView(R.layout.activity_main);
        getSupportFragmentManager().beginTransaction().replace(R.id.home_container, MapFragment.newInstance()).commit();
    }

    @Override
    public void onLanguageChange(View view) {
        recreate();
    }
}

Screenshot
device-2018-02-06-154914

@tobrun
Copy link
Member

tobrun commented Feb 6, 2018

Thank you for reaching out and using our products, as noted in the javadoc, you need to call onDestroy as part of Fragment#OnDestroyView instead of Fragment#onDestroy. Hooking into the correct lifecycle will resolve your issue.

@tobrun tobrun closed this as completed Feb 6, 2018
@tobrun tobrun added the Android Mapbox Maps SDK for Android label Feb 6, 2018
@minthura
Copy link
Author

minthura commented Feb 6, 2018

@tobrun I already tried with Fragment#OnDestroyView instead of Fragment#onDestroy but this time the app crashes with the following stack trace.

java.lang.IllegalStateException: setRenderer has already been called for this instance.
                      at android.opengl.GLSurfaceView.checkRenderThreadState(GLSurfaceView.java:1893)
                      at android.opengl.GLSurfaceView.setEGLContextClientVersion(GLSurfaceView.java:473)
                      at com.mapbox.mapboxsdk.maps.renderer.glsurfaceview.GLSurfaceViewMapRenderer.<init>(GLSurfaceViewMapRenderer.java:27)
                      at com.mapbox.mapboxsdk.maps.MapView$6.<init>(MapView.java:309)
                      at com.mapbox.mapboxsdk.maps.MapView.initialiseDrawingSurface(MapView.java:309)
                      at com.mapbox.mapboxsdk.maps.MapView.access$100(MapView.java:70)
                      at com.mapbox.mapboxsdk.maps.MapView$1.onGlobalLayout(MapView.java:144)
                      at android.view.ViewTreeObserver.dispatchOnGlobalLayout(ViewTreeObserver.java:945)
                      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2237)
                      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1385)
                      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6722)
                      at android.view.Choreographer$CallbackRecord.run(Choreographer.java:886)
                      at android.view.Choreographer.doCallbacks(Choreographer.java:698)
                      at android.view.Choreographer.doFrame(Choreographer.java:633)
                      at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:872)
                      at android.os.Handler.handleCallback(Handler.java:769)
                      at android.os.Handler.dispatchMessage(Handler.java:98)
                      at android.os.Looper.loop(Looper.java:164)
                      at android.app.ActivityThread.main(ActivityThread.java:6540)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

Is there anything I'm missing ?

@minthura
Copy link
Author

minthura commented Feb 6, 2018

I also tested with the SupportMapFragment from the MapBox sdk instead, still facing the same issue. Any idea on this ? Thank you.

@tobrun
Copy link
Member

tobrun commented Feb 6, 2018

@minthura was able to reproduce:

adding the following solves your issue:

    if (savedInstanceState == null) {
      getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MapFragment()).commit();
    }

The activity itself manages fragment recreation on its own. I will work on hardening this integration.

@tobrun tobrun reopened this Feb 6, 2018
@tobrun
Copy link
Member

tobrun commented Feb 6, 2018

Debugging shows very strange behavior, when you recreate the activity, I'm seeing 2 fragments being recreated and both share the same SurfaceView which results in the setRenderer has already been called for this instance. This should not happen as they both do layout inflation on their own. Creating the SurfaceView programmatically resolves the issue though can't really explain this behavior atm

@tobrun tobrun added this to the android-v5.4.1 milestone Feb 6, 2018
@minthura
Copy link
Author

minthura commented Feb 6, 2018

Hmm yeah that's strange. Anyway I could fix the issue with the way you suggested for now. Thanks @tobrun.

@prcGit
Copy link

prcGit commented Oct 15, 2018

Hi,
I can't add MapView into a Fragment.

My Fragment layout:

`

<ImageView
    android:id="@+id/image_header"
    android:layout_width="match_parent"
    android:layout_height="120dp"
     />

<TextView
    android:id="@+id/text_day"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginTop="32dp"
    android:layout_marginEnd="8dp"
    android:text="20"
    android:textSize="38dp"
    android:fontFamily="@font/roboto_light"
    android:textColor="@color/colorPrimaryDark"/>

<TextView
    android:id="@+id/text_month"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginTop="16dp"
    android:layout_marginEnd="8dp"
    android:text="october"
    android:textSize="26dp"
    android:fontFamily="@font/roboto_light"
    android:textColor="@color/colorPrimaryDark"/>

<TextView
    android:id="@+id/text_header_name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

<TextView
    android:id="@+id/text_body_about"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

<TextView
    android:id="@+id/text_place"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

<com.google.android.gms.maps.MapView
    android:id="@+id/mapView"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:layout_marginTop="32dp" />

`

My Fragment:
`package com.app.wtmzaragoza.ui

import android.arch.lifecycle.Observer
import android.arch.lifecycle.ViewModelProviders
import android.os.Bundle
import android.support.v4.app.Fragment
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.app.wtmzaragoza.R
import com.app.wtmzaragoza.data.LocalResourcesReader
import com.app.wtmzaragoza.data.db.FavDatabase
import com.bumptech.glide.Glide
import com.google.android.gms.maps.*
import kotlinx.android.synthetic.main.fragment_event_details.*
import com.google.android.gms.maps.model.MarkerOptions
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.CameraUpdate
import com.google.android.gms.common.GooglePlayServicesNotAvailableException
import com.google.android.gms.maps.MapsInitializer
import kotlinx.android.synthetic.main.fragment_event_details.view.*

class EvantDetailsFragment : Fragment() {

// override fun onMapReady(googleMap: GoogleMap?) {
// val sydney = LatLng(-33.852, 151.211)
// googleMap?.addMarker(MarkerOptions().position(sydney)
// .title("Marker in Sydney"))
// googleMap?.moveCamera(CameraUpdateFactory.newLatLng(sydney))
// }

private lateinit var dataViewModel: DataViewModel
private lateinit var map : GoogleMap


override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(R.layout.fragment_event_details, container, false)

    mapView?.onCreate(savedInstanceState)


    return view
}


override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)


    dataViewModel = ViewModelProviders.of(this).get(DataViewModel::class.java)
    dataViewModel.init(LocalResourcesReader(context!!), FavDatabase.getInstance(context!!))

    Glide.with(context!!).load("http://empretsinf.blogs.upv.es/files/2016/04/WT_logo_horizontal.png").into(image_header)

    dataViewModel.getEventInfo().observe(this, Observer {
        text_day.text = it?.day
        text_month.text = it?.month
    })

}

override fun onStart() {
    super.onStart()
    mapView?.let{
        it.onStart()
    }
}

override fun onResume() {
    super.onResume()
    mapView?.let{
        it.onResume()
    }
}

override fun onPause() {
    super.onPause()
    mapView?.let{
        it.onPause()
    }
}

override fun onStop() {
    super.onStop()
    mapView?.let{
        it.onStop()
    }
}

override fun onDestroyView() {
    super.onDestroyView()
    mapView?.let{
        it.onDestroy()
    }
}

override fun onLowMemory() {
    super.onLowMemory()
    mapView?.let{
        it.onLowMemory()
    }
}

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    mapView?.let {
        it.onSaveInstanceState(outState)
    }
}

companion object {

    var TAG = "event"

    fun newInstance() = EvantDetailsFragment()
}

}`

Error Logcat:
2018-10-15 21:45:16.548 1288-1288/com.app.wtmzaragoza E/AndroidRuntime: FATAL EXCEPTION: main Process: com.app.wtmzaragoza, PID: 1288 java.lang.NullPointerException: Attempt to invoke interface method 'void com.google.maps.api.android.lib6.impl.bt.v()' on a null object reference at com.google.maps.api.android.lib6.impl.db.h(:com.google.android.gms.dynamite_mapsdynamite@14366051@14.3.66 (040408-213742215):13) at com.google.android.gms.maps.internal.w.a(:com.google.android.gms.dynamite_mapsdynamite@14366051@14.3.66 (040408-213742215):8) at fq.onTransact(:com.google.android.gms.dynamite_mapsdynamite@14366051@14.3.66 (040408-213742215):4) at android.os.Binder.transact(Binder.java:612) at com.google.android.gms.internal.maps.zza.transactAndReadExceptionReturnVoid(Unknown Source:7) at com.google.android.gms.maps.internal.zzk.onStart(Unknown Source:6) at com.google.android.gms.maps.MapView$zza.onStart(Unknown Source:2) at com.google.android.gms.dynamic.zaf.zaa(Unknown Source:3) at com.google.android.gms.dynamic.zaa.onDelegateCreated(Unknown Source:4) at com.google.android.gms.maps.MapView$zzb.createDelegate(Unknown Source:47) at com.google.android.gms.dynamic.DeferredLifecycleHelper.zaa(Unknown Source:18) at com.google.android.gms.dynamic.DeferredLifecycleHelper.onStart(Unknown Source:54) at com.google.android.gms.maps.MapView.onStart(Unknown Source:2) at com.app.wtmzaragoza.ui.EvantDetailsFragment.onStart(EvantDetailsFragment.kt:68) at android.support.v4.app.Fragment.performStart(Fragment.java:2361) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1462) at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1754) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1822) at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:797) at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2591) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2378) at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2333) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2240) at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:703) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6938) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

Any idea? Thanks!

@tobrun
Copy link
Member

tobrun commented Oct 16, 2018

You are using a Google Map in your xml and not a Mapbox one:

<com.google.android.gms.maps.MapView 
   ....
   .>

@paulhristea
Copy link

@prcGit I am getting the same error when using Google MapView - have you been able to solve it?

(sorry for this post)

@VadlamudiNaveen
Copy link

VadlamudiNaveen commented Mar 1, 2019

@hi everyone i dont know why it is getting this problem... please check this out ... and i am following the instructions of the official website of mapbox...

package com.example.vibloc;

import android.app.Dialog;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;

import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;

public class MainActivity extends AppCompatActivity {
private MapView mapview;
public MainActivity() {

}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Mapbox.getInstance(this, "pk.eyJ1IjoibmF2ZWVudmFkbGFtdWRpIiwiYSI6ImNqc3BzZ3VyNjBwa2czeW8wa2tncWN5a3QifQ.gTS6ApXhA1H9_l2FK0p7-w");
    setContentView(R.layout.activity_main);
    mapview =findViewById(R.id.mapView);
    mapview.onCreate(savedInstanceState);
    mapview.getMapAsync(new OnMapReadyCallback() {
        @Override
        public void onMapReady(@NonNull MapboxMap mapboxMap) {
            mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
                @Override
                public void onStyleLoaded(@NonNull Style style) {


                }
            });
        }
    });
}

@Override
public void onStart() {
    super.onStart();
    mapview.onStart();
}

@Override
public void onResume() {
    super.onResume();
    mapview.onResume();
}

@Override
public void onPause() {
    super.onPause();
    mapview.onPause();
}

@Override
public void onStop() {
    super.onStop();
    mapview.onStop();
}

@Override
public void onLowMemory() {
    super.onLowMemory();
    mapview.onLowMemory();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    mapview.onDestroy();
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    mapview.onSaveInstanceState(outState);
}

}

error is:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.vibloc/com.example.vibloc.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.mapbox.mapboxsdk.maps.MapView.onCreate(android.os.Bundle)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.mapbox.mapboxsdk.maps.MapView.onCreate(android.os.Bundle)' on a null object reference
at com.example.vibloc.MainActivity.onCreate(MainActivity.java:41)
at android.app.Activity.performCreate(Activity.java:7009)
at android.app.Activity.performCreate(Activity.java:7000)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856) 
at android.app.ActivityThread.-wrap11(Unknown Source:0) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:164) 
at android.app.ActivityThread.main(ActivityThread.java:6494) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 
Application terminated.

please give me a solution for this ...asap thanks ...

@tobrun
Copy link
Member

tobrun commented Mar 4, 2019

@VadlamudiNaveen a NullPointerException like that means that you haven't added a MapView decleration to your Xml layout file.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Android Mapbox Maps SDK for Android
Projects
None yet
Development

No branches or pull requests

5 participants