NoSuchFieldError: No static field MapAttrs of type

2019-01-16 12:41发布

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

5条回答
啃猪蹄的小仙女
2楼-- · 2019-01-16 12:59

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')
            }
        }
    }
}
查看更多
我只想做你的唯一
3楼-- · 2019-01-16 13:01

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.

查看更多
啃猪蹄的小仙女
4楼-- · 2019-01-16 13:07

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>
查看更多
神经病院院长
5楼-- · 2019-01-16 13:12

Finally I found out the cause. If you are on a habit of kidnapping the aar files for your own Eclipse benefit (I'm not gonna teach here how because it's not the Android Studio way), you need to move the maps_attrs.xml file on the play-services-base res/values folder. This will align the attributes and the generated R.class file on the class path the maps library is expecting.

Sample use of play-services-base

查看更多
看我几分像从前
6楼-- · 2019-01-16 13:13

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.

查看更多
登录 后发表回答