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:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With