NoSuchFieldError: No static field MapAttrs of type when Using MapFragment with Play Services 6.5

11,259

Solution 1

Updating your Google Repository to version 15 via the SDK Manager should resolve the issues and eliminate the needs for the workarounds. A project clean is required.

Android SDK

This is also mentioned in issue 7432.

Solution 2

Interim solution

replace the xml map fragment with a FrameLayout container

<FrameLayout
    android:id="@+id/map_container"
android:layout_weight="2"
android:layout_width="match_parent"
android:layout_height="0dp"
/>
<!--<fragment android:id="@+id/map"-->
<!--android:layout_weight="2"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="0dp"-->
<!--android:name="com.google.android.gms.maps.SupportMapFragment"/>-->

Create the fragment in code and replace the container

SupportMapFragment supportMapFragment = SupportMapFragment.newInstance();
getSupportFragmentManager().beginTransaction().replace(R.id.map_container,supportMapFragment).commit();

//this you should do anyway
supportMapFragment.getMapAsync(new OnMapReadyCallback() {
    @Override
    public void onMapReady(GoogleMap googleMap) {
        //setup map - optional
        UiSettings settings = googleMap.getUiSettings();
        settings.setCompassEnabled(false);
        settings.setZoomControlsEnabled(false);
        settings.setAllGesturesEnabled(true);
        settings.setMyLocationButtonEnabled(true);
    }
});

Please note that the above was done in 'onCreate' in an activity without any other fragments, so make sure you adapt the transaction to your lifecycle and logic.

Solution 3

I found a "hacky" fix to make it work with your app until Google decides to fix this :

Add this to your app gradle script:

afterEvaluate {
    def pattern = ~/process(.*)Resources/
    tasks.matching { pattern.matcher(it.name).find() }.each {
        def matcher = pattern.matcher(it.name)
        matcher.find()
        def buildType = matcher.group(1)
        buildType = buildType.substring(0, 1).toLowerCase() + buildType.substring(1)
        def rDirectory = "$project.buildDir/generated/source/r/$buildType"
        it << {
            def badFile = file("$rDirectory/com/google/android/gms/R.java")
            def goodFile = file("$rDirectory/com/google/android/gms/maps/R.java")
            if (badFile.exists() && goodFile.exists()) {
                badFile.text = goodFile.text.replaceAll('com.google.android.gms.maps', 'com.google.android.gms')
            }
        }
    }
}

Solution 4

I think you have layout in both library and module with same name or inflating multiple xml layout with duplicate resource id.

Find map_attrs in play-services-lib and replace with this code:

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <declare-styleable name="MapAttrs">
    <attr name="mapType" format="enum">
      <enum name="none" value="0"/>
      <enum name="normal" value="1"/>
      <enum name="satellite" value="2"/>
      <enum name="terrain" value="3"/>
      <enum name="hybrid" value="4"/>



    </attr>
    <attr name="cameraBearing" format="float"/>
    <attr name="cameraTargetLat" format="float"/>
    <attr name="cameraTargetLng" format="float"/>
    <attr name="cameraTilt" format="float"/>
    <attr name="cameraZoom" format="float"/>
    <attr name="liteMode" format="boolean"/>



    <attr name="uiCompass" format="boolean"/>
    <attr name="uiRotateGestures" format="boolean"/>
    <attr name="uiScrollGestures" format="boolean"/>
    <attr name="uiTiltGestures" format="boolean"/>
    <attr name="uiZoomControls" format="boolean"/>
    <attr name="uiZoomGestures" format="boolean"/>
    <attr name="useViewLifecycle" format="boolean"/>
    <attr name="zOrderOnTop" format="boolean"/>
    <attr name="uiMapToolbar" format="boolean"/>
    <attr name="ambientEnabled" format="boolean"/>
  </declare-styleable>

</resources>
Share:
11,259
Philipp E.
Author by

Philipp E.

Updated on June 17, 2022

Comments

  • Philipp E.
    Philipp E. almost 2 years

    Maybe I am missing something here, but I am not able to use the new Maps only dependency in Play Services 6.5

    I get the following exception:

    java.lang.NoSuchFieldError: No static field MapAttrs of type 
        [I in class Lcom/google/android/gms/R$styleable; or its superclasses 
        (declaration of 'com.google.android.gms.R$styleable' appears in 
        /data/app/com.kaching.merchant.dev1-1/base.apk)
            at com.google.android.gms.maps.GoogleMapOptions
                .createFromAttributes(Unknown Source)
            at com.google.android.gms.maps.SupportMapFragment
                .onInflate(Unknown Source)
    

    Manifest:

    <meta-data android:name="com.google.android.gms.version"
      android:value="@integer/google_play_services_version" />
    
    <meta-data
      android:name="com.google.android.maps.v2.API_KEY"
      android:value="my-awesome-key"/>
    
    
    <uses-permission 
      android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
    

    Gradle file:

    compile 'com.google.android.gms:play-services-maps:6.5.+'
    compile 'com.android.support:support-v4:21.0.2'
    

    Layout:

    <fragment
       android:id="@+id/map"
       android:name="com.google.android.gms.maps.MapFragment"
       android:layout_width="match_parent"
       android:layout_height="match_parent"/>
    

    Is this broken or am I doing something wrong?

    The full bundle pushes me over the dex limit and I would prefer not to use multidex