Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapbox Inflate View on Fragment

I am having issues inflating a Mapbox MapView on an Android Fragment. When I use the same code on an Activity (other than standard differences between an Activity and a Fragment), I can get the MapView to load correctly, but not on the Fragment.

Mapbox also has a MapFragment class here, but I am unsure how to use this properly in a Fragment (the example is still in an Activity); with the Google Maps API I am able to use a MapView on a Fragment without a problem.

The below logcat line of:

at com.example.exampleapp.FragmentMap.onCreateView(FragmentMap.java:133)

is referring to the Java line:

fragmentLayout = inflater.inflate(R.layout.fragment_map, container, false);

Here is the relevant code for this issue along with the log:

fragment_map.xml:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:mapbox="http://schemas.android.com/apk/res-auto"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <com.mapbox.mapboxsdk.views.MapView
        android:id="@+id/mapview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        mapbox:access_token="@string/access_token"/>

    <android.support.v7.widget.CardView
        android:id="@+id/map_card"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="5dp">
        <com.mapbox.mapboxsdk.views.MapView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:id="@+id/mini_map"
            android:layout_centerVertical="true"
            android:layout_centerHorizontal="true"
            mapbox:access_token="@string/access_token"/>
    </android.support.v7.widget.CardView>

FragmentMap.java:

public class FragmentMap extends Fragment {
    private MapView mv, miniMap;
        View fragmentLayout;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        fragmentLayout = inflater.inflate(R.layout.fragment_map, container, false);

    mv = (MapView) fragmentLayout.findViewById(R.id.mapview);
    mv.onCreate(savedInstanceState);

    miniMap = (MapView) fragmentLayout.findViewById(R.id.mini_map);
    miniMap.onCreate(savedInstanceState);

    return fragmentLayout;
}


@Override
public void onStart() {
    super.onStart();
    mv.onStart();
    miniMap.onStart();
}
@Override
public void onStop() {
    super.onStop();
    mv.onStop();
    miniMap.onStop();
}


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

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

@Override
public void onPause() {
    super.onPause();
    mv.onPause();
    miniMap.onPause();
}
@Override
public void onLowMemory() {
    super.onLowMemory();
    mv.onLowMemory();
    miniMap.onLowMemory();
}

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

logcat:

01-07 08:07:00.548 710-710/com.example.exampleapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.exampleapp, PID: 710
android.view.InflateException: Binary XML file line #13: Error inflating class com.mapbox.mapboxsdk.views.MapView
at android.view.LayoutInflater.createView(LayoutInflater.java:633)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:743)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at com.example.exampleapp.FragmentMap.onCreateView(FragmentMap.java:133)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1106)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:552)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:514)
at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:495)
at android.support.design.widget.TabLayout$ViewPagerOnTabSelectedListener.onTabSelected(TabLayout.java:1778)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:871)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:841)
at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1115)
at android.support.design.widget.TabLayout$1.onClick(TabLayout.java:665)
at android.view.View.performClick(View.java:4785)
at android.view.View$PerformClick.run(View.java:19884)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5343)
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:905)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
at android.view.LayoutInflater.createView(LayoutInflater.java:607)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:743)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at com.example.exampleapp.FragmentMap.onCreateView(FragmentMap.java:133)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1106)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:552)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:514)
at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:495)
at android.support.design.widget.TabLayout$ViewPagerOnTabSelectedListener.onTabSelected(TabLayout.java:1778)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:871)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:841)
at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1115)
at android.support.design.widget.TabLayout$1.onClick(TabLayout.java:665)
at android.view.View.performClick(View.java:4785)
at android.view.View$PerformClick.run(View.java:19884)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5343)
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:905)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
Caused by: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.exampleapp-2/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libmapbox-gl.so"
at java.lang.Runtime.loadLibrary(Runtime.java:366)
at java.lang.System.loadLibrary(System.java:988)
at com.mapbox.mapboxsdk.views.NativeMapView.<clinit>(NativeMapView.java:42)
at com.mapbox.mapboxsdk.views.MapView.initialize(MapView.java:680)
at com.mapbox.mapboxsdk.views.MapView.<init>(MapView.java:621)
at java.lang.reflect.Constructor.newInstance(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
at android.view.LayoutInflater.createView(LayoutInflater.java:607)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:743)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at com.example.exampleapp.FragmentMap.onCreateView(FragmentMap.java:133)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1106)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:552)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:514)
at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:495)
at android.support.design.widget.TabLayout$ViewPagerOnTabSelectedListener.onTabSelected(TabLayout.java:1778)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:871)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:841)
at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1115)
at android.support.design.widget.TabLayout$1.onClick(TabLayout.java:665)
at android.view.View.performClick(View.java:4785)
at android.view.View$PerformClick.run(View.java:19884)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5343)
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:905)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)

app gradle:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0'
    }
}

apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'

repositories {
    mavenCentral()
    jcenter()
}

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.example.exampleapp"
        minSdkVersion 19
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }
    useLibrary 'org.apache.http.legacy'

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:cardview-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
    compile 'com.google.android.exoplayer:exoplayer:r1.5.2'
    compile 'com.google.android.gms:play-services-auth:8.3.0'
    compile 'com.google.android.gms:play-services-maps:8.3.0'
    compile('com.mapbox.mapboxsdk:mapbox-android-sdk:2.3.0@aar') {
        transitive = true
    }
    compile files('libs/commons-lang3-3.3.2.jar')
}

Project Structure:

enter image description here

like image 474
sean Avatar asked Jan 07 '16 22:01

sean


Video Answer


1 Answers

You are telling about inflation but look at stack trace:

Caused by: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.exampleapp-2/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libmapbox-gl.so" at java.lang.Runtime.loadLibrary(Runtime.java:366) at java.lang.System.loadLibrary(System.java:988) at com.mapbox.mapboxsdk.views.NativeMapView.(NativeMapView.java:42) at com.mapbox.mapboxsdk.views.MapView.initialize(MapView.java:680) at com.mapbox.mapboxsdk.views.MapView.(MapView.java:621)

BTW:

first

u need to decide if u inflate view every time {local variable) or u reuse it (global one)

example:

if(_view==null) 
   _view = inflater.inflate(..);
return _view;

second:

do not call activities or fragment methods like onCreate onPause manually (those used by os to maintain life cycle)

third:

if u use viewpager and nested fragments u need create adapter with child fragment manager

more & more:

keep in mind that to set some data and properties in child fragment viewpager fragment need to laid out

"First: I am inflating it every time, which is usually not a problem (my tabs work with any other fragment I have created, including Google Maps, just not Mapbox) Second: Yes, you do call activity lifecycle methods manually. You have to use onCreate to inflate a view. Third: I have an adapter, I just did not include it here. That is not the issue, my tabs work fine with any other fragment I have created. Lastly: I'm not sure what you're saying, but my fragments work fine in my other tabs.

Please focus on the problem at hand... putting a Mapbox view in a fragment, > regardless of where that fragment is (tab pageviewer or not).. – TangoJLabs"

/**
 * Called to do initial creation of a fragment.  This is called after
 * {@link #onAttach(Activity)} and before
 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
 *
 * <p>Note that this can be called while the fragment's activity is
 * still in the process of being created.  As such, you can not rely
 * on things like the activity's content view hierarchy being initialized
 * at this point.  If you want to do work once the activity itself is
 * created, see {@link #onActivityCreated(Bundle)}.
 *
 * @param savedInstanceState If the fragment is being re-created from
 * a previous saved state, this is the state.
 */
public void onCreate(@Nullable Bundle savedInstanceState) {
    mCalled = true;
}

move this from onCreate of fragment to onViewCreated(View,Bundle)

mv = (MapView) fragmentLayout.findViewById(R.id.mapview);
mv.onCreate(savedInstanceState);

miniMap = (MapView) fragmentLayout.findViewById(R.id.mini_map);
miniMap.onCreate(savedInstanceState);


/**
 * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}
 * has returned, but before any saved state has been restored in to the view.
 * This gives subclasses a chance to initialize themselves once
 * they know their view hierarchy has been completely created.  The fragment's
 * view hierarchy is not however attached to its parent at this point.
 * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
 * @param savedInstanceState If non-null, this fragment is being re-constructed
 * from a previous saved state as given here.
 */
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
}

last word: gradle files

i dont know if your file content contains both gradle files or only app file but those lines shouldnt be in app gradle file - those are top level gradle :

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0'
    }
}

repositories {
    mavenCentral()
    jcenter()
}

and u should consider to move to newest android app plugin - but i see you are using gms services - so u top gradle file is containing other plugin and those above is omitted

I'm having trouble following the logic of your edits. I don't have an onCreate from which I can move anything

/** inflate fragment  - this will create view */
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_map, container, false);
}

/** after view is created - set map view */
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    if(view!=null) {
       MapView mv = (MapView) view.findViewById(R.id.mapview);
       mv.onCreate(savedInstanceState);
    }
}

btw i have more concerns on rest of lifecycle methods - fragment could or not retain state so simple putting activity lifecycle methods in fragment method could produce more problems :)

i don't use & know the source implementation of MapView so i cant tell u how to implement this but i can give u a hint to check if fragment is attached to activity before u call any mapview method

@ceph3us -1 everything mentioned in this is wrong, and your grammar can be improved. I don't have an answer to this, I am here with the same question. 1st root view should not be a field, it should be inflated on each call to onCreateView, 2nd those are proper calls, 3rd and the rest are off topic and not helpful to the subject. – HaydenKai

@HaydenKai

  1. first of all pleas specify the SOURCES for you deliberations
  2. why u want to recreate view ? purpose ? to waste resources (like your time to code and user CPU and MEM)? - there where u can afford it or need a fresh one then its ok but in other cases REUSE !!!
  3. the view does not need to be inflated at all, it can be normally created eg by return new LinearLayout(Context) or FrameLayout or any other complex view - this is a developer choice to use xml or java - i prefer not to use xml - i like pure JAVA :)
  4. so at the very end i can say your -1 is empty one for me her

enter image description here

like image 67
ceph3us Avatar answered Sep 23 '22 23:09

ceph3us