NoSuchFieldError:将MapFragment与Play Services 6.5一起使用时,没有静态字段MapAttrs类型

时间:2014-12-09 11:28:12

标签: android google-play-services google-maps-android-api-2 android-gradle

也许我在这里遗漏了一些东西,但我无法在Play Services 6.5中使用新的仅限地图依赖

我得到以下异常:

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)

清单:

<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文件:

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

布局:

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

这是坏了还是我做错了什么?

完整的捆绑推动了我超过dex限制,我宁愿不使用multidex

5 个答案:

答案 0 :(得分:17)

通过SDK Manager将 Google Repository 更新为版本15,可以解决问题并消除变通方法的需求。需要清理项目。

Android SDK

issue 7432中也提到了这一点。

答案 1 :(得分:5)

临时解决方案

用FrameLayout容器替换xml映射片段

<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"/>-->

在代码中创建片段并替换容器

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);
    }
});

请注意,上述内容是在“创建”中完成的。在没有任何其他片段的活动中,请确保使事务适应您的生命周期和逻辑。

答案 2 :(得分:4)

我找到了一个&#34; hacky&#34;修复以使其适用于您的应用,直到Google决定解决此问题:

将此添加到您的app gradle脚本:

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 :(得分:1)

我认为您在库和模块中都有相同名称或布局的布局 使用重复的资源ID扩充多个xml布局。

在play-services-lib中查找map_attrs并替换为此代码:

<?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>

答案 4 :(得分:0)

最后我发现了原因。如果你习惯于绑架aar文件以获得自己的Eclipse好处(我不会在这里教,因为它不是Android Studio的方式),你需要移动 maps_attrs。 play-services-base res / values 文件夹中的xml 文件。这将使地图库所期望的类路径上的属性和生成的R.class文件保持一致。

Sample use of play-services-base