更新到Android Build Tools之后的IncompatibleClassChangeError 25.1.6 GCM / FCM

时间:2016-05-19 01:05:45

标签: android google-cloud-messaging android-gradle firebase-cloud-messaging

自从我更新到Android SDK工具25.1.6和Android支持存储库32.0.0(今天早上)后,我收到以下错误,我没有更改代码中的任何内容,它仍然在我的同事身上工作计算机(Android SDK Tools 25.1.1 + Android Support Repository 30.0.0)。

java.lang.IncompatibleClassChangeError: The method 
     'java.io.File android.support.v4.content.ContextCompat.getNoBackupFilesDir(android.content.Context)' 
     was expected to be of type virtual but instead was found to be of type direct 
     (declaration of 'java.lang.reflect.ArtMethod' appears in /system/framework/core-libart.jar)

     at com.google.android.gms.iid.zzd.zzeb(Unknown Source)
     at com.google.android.gms.iid.zzd.<init>(Unknown Source)
     at com.google.android.gms.iid.zzd.<init>(Unknown Source)
     at com.google.android.gms.iid.InstanceID.zza(Unknown Source)
     at com.google.android.gms.iid.InstanceID.getInstance(Unknown Source)
     at com.xxxxxxx.utils.RegistrationIntentService.onHandleIntent(RegistrationIntentService.java:55)
     at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
     at android.os.Handler.dispatchMessage(Handler.java:102)
     at android.os.Looper.loop(Looper.java:145)
     at android.os.HandlerThread.run(HandlerThread.java:61)

以下是崩溃的代码:

InstanceID instanceID = InstanceID.getInstance(this); // <-- crash here
String instanceIDToken = instanceID.getToken(getString(R.string.google_app_id),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

当我尝试从Google Cloud Messaging获取令牌时。

我在Gradle中使用拆分的播放服务导入GCM:

 compile 'com.google.android.gms:play-services-analytics:9.0.0' 
 compile 'com.google.android.gms:play-services-maps:9.0.0'
 compile 'com.google.android.gms:play-services-location:9.0.0' 
 compile 'com.google.android.gms:play-services-gcm:9.0.0' 
 compile 'com.google.android.gms:play-services-base:9.0.0'

修改 禁用GCM修复了问题,因此我猜我应该迁移到Firebase Cloud Message

EDIT2 我的设备收到Google Play Services 9.0(昨天是8.4.x)。现在它不再崩溃,但抱怨模块描述符

 Failed to load module descriptor class: Didn't find class "com.google.android.gms.dynamite.descriptors.com.google.firebase.auth.ModuleDescriptor"
 Firebase API initialization failure.

有没有人有类似的错误,以及如何修复它?

固定 特别感谢@stegranet。 ./gradlew -q app:dependencies --configuration compile可帮助您确定哪些依赖项包含SDK 24.x

主要问题是某些库使用+符号而不是版本导入最新的支持库。这会导致问题,包括最新的可用版本。

因此,请避免+登录依赖项;)

14 个答案:

答案 0 :(得分:37)

我使用gradle依赖树为我解决了这个错误。

只需运行gradle -q app:dependencies --configuration compile 并检查输出中的条目如下:

+--- com.mcxiaoke.viewpagerindicator:library:2.4.1
|    \--- com.android.support:support-v4:+ -> 24.0.0-beta1 (*)

由于Diego Giorgini表示此版本太高(&gt; = 24)。 因此,请更新build.gradle中的依赖项

compile('com.mcxiaoke.viewpagerindicator:library:2.4.1') {
    exclude module: 'support-v4';
}
compile 'com.android.support:support-v4:23.4.0'

答案 1 :(得分:35)

更新可能27:

我们刚刚发布了一个更新(play-services / firebase sdk v9.0.0)来修复我在第一次编辑中提到的不兼容性 请更新您的依赖项,如果仍有问题,请告诉我们。

谢谢!

原始回答5月20日:

您遇到的问题是由于两者之间不兼容 com.android.support:appcompat-v7 >= 24compile 'com.android.support:appcompat-v7:23.4.0'
(与android-N sdk一起发布的版本)

您应该能够通过定位支持库的早期版本来修复它。像:

#r "Newtonsoft.Json.dll"

答案 2 :(得分:5)

我已在build.gradle

中更新了播放服务依赖项
dependencies {
    compile 'com.google.android.gms:play-services:9.0.0'
}

要通过更新google-services插件的版本修复版本冲突,我必须在项目的根文件夹下的build.gradle更新google-services

dependencies {
    classpath 'com.google.gms:google-services:3.0.0'
}

您可以获取google-services here的最新更新。

虽然它没有避免异常,但它不会使应用程序崩溃在我身边。

<强>更新

我可以通过从Beta频道更新Android工作室来避免崩溃。然后在SDK中更新您的platform/build-tools

enter image description here

答案 3 :(得分:5)

我的工作人员如下:

app level gradle

dependencies {
 compile 'com.android.support:appcompat-v7:23.4.0'
 compile 'com.android.support:design:23.4.0'
 compile 'com.google.android.gms:play-services:9.0.0'
}

root level gradle

dependencies {
    classpath 'com.google.gms:google-services:3.0.0'
}

答案 4 :(得分:4)

更新到最新的Google Play服务版本为我解决了这个问题。

申请插件:&#39; com.google.gms.google-services&#39; 在底部     ...

{{1}}

https://developers.google.com/android/guides/setup#add_google_play_services_to_your_project

答案 5 :(得分:3)

因为facebook更新了sdk而我发生了

compile 'com.facebook.android:facebook-android-sdk:4.+'

将其替换为

compile 'com.facebook.android:facebook-android-sdk:4.15.0'

解决了我的问题。

参考:https://developers.facebook.com/docs/android/change-log-4.x

答案 6 :(得分:1)

包括所有游戏服务&#39;封装

dependencies {
  compile 'com.google.android.gms:play-services:9.0.0'
}

你压制错误,但最终的结果是,GCM令牌检索不起作用,我们也无法获得GCM的实例。所以这不是我书中的解决方案。如果有人知道发生了什么,请启发我们。

编辑:

我用firebase替换GCM,将android studio从2.1更新到2.2以修复firebase分析的即时运行问题,更新24-rc4的构建工具和24-rc3的平台工具,并保留我的支持库&#39;版本为23.4.0。现在一切似乎都很好。

答案 7 :(得分:1)

我遇到了同样的问题,并从Android支持存储库32.0.0恢复到Android支持存储库31.0.0解决了它。

答案 8 :(得分:1)

使用GCM 2016进行Android推送通知:

1)在Android SDK中 - &gt; SDK工具检查Google Play服务

2)在gradle中添加依赖项只需一行:

compile 'com.google.android.gms:play-services-gcm:9.4.0'

(没有特定的类路径,它适用于我)

3)你必须创建3个类(GCMPushReceiverService,GCMRegistrationIntentService,GCMTokenRefreshListenerService)

4.1)GCMTokenRefreshListenerService的代码:

package com.myapp.android;

/**
 * Created by skygirl on 02/08/2016.
 */
import android.content.Intent;
import com.google.android.gms.iid.InstanceIDListenerService;

public class GCMTokenRefreshListenerService extends InstanceIDListenerService {

    //If the token is changed registering the device again
    @Override
    public void onTokenRefresh() {
        Intent intent = new Intent(this, GCMRegistrationIntentService.class);
        startService(intent);
    }
}

4.2)GCMRegistrationIntentService的代码(将authorizedEntity更改为您的项目编号):

package com.myapp.android;

/**
 * Created by Skygirl on 02/08/2016.
 */
import android.app.IntentService;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.google.android.gms.iid.InstanceID;

public class GCMRegistrationIntentService extends IntentService {
    //Constants for success and errors
    public static final String REGISTRATION_SUCCESS = "RegistrationSuccess";
    public static final String REGISTRATION_ERROR = "RegistrationError";

    //Class constructor
    public GCMRegistrationIntentService() {
        super("");
    }


    @Override
    protected void onHandleIntent(Intent intent) {
        //Registering gcm to the device
        registerGCM();
    }

    private void registerGCM() {
        //Registration complete intent initially null
        Intent registrationComplete = null;

        //Register token is also null
        //we will get the token on successfull registration
        String token = null;
        try {
            //Creating an instanceid
            InstanceID instanceID = InstanceID.getInstance(this);
            String authorizedEntity = "XXXXXXXXXX"; //  your project number

            //Getting the token from the instance id
            token = instanceID.getToken(authorizedEntity, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

            //Displaying the token in the log so that we can copy it to send push notification
            //You can also extend the app by storing the token in to your server
            Log.w("GCMRegIntentService", "token:" + token);

            //on registration complete creating intent with success
            registrationComplete = new Intent(REGISTRATION_SUCCESS);

            //Putting the token to the intent
            registrationComplete.putExtra("token", token);
        } catch (Exception e) {
            //If any error occurred
            Log.w("GCMRegIntentService", "Registration error");
            registrationComplete = new Intent(REGISTRATION_ERROR);
        }

        //Sending the broadcast that registration is completed
        LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
    }
}

4.3)GCMPushReceiverService的代码:

package com.myapp.android;

/**
 * Created by Skygirl on 02/08/2016.
 */
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;

import com.google.android.gms.gcm.GcmListenerService;

//Class is extending GcmListenerService
public class GCMPushReceiverService extends GcmListenerService {

    //This method will be called on every new message received
    @Override
    public void onMessageReceived(String from, Bundle data) {
        //Getting the message from the bundle
        String message = data.getString("message");
        //Displaying a notiffication with the message
        sendNotification(message);
    }

    //This method is generating a notification and displaying the notification
    private void sendNotification(String message) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        int requestCode = 0;
        PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
        NotificationCompat.Builder noBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.your_logo)
                .setContentTitle("Your Amazing Title")
                .setContentText(message)
                .setPriority(Notification.PRIORITY_MAX)
                .setContentIntent(pendingIntent);
        noBuilder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));

        NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, noBuilder.build()); //0 = ID of notification
    }
}

5)不要忘记更改包名

6)在mainActivity中粘贴此代码:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Setup view
        setContentView(R.layout.main);
    mRegistrationBroadcastReceiver = new BroadcastReceiver() {

        //When the broadcast received
        //We are sending the broadcast from GCMRegistrationIntentService

        public void onReceive(Context context, Intent intent) {
            //If the broadcast has received with success
            //that means device is registered successfully
            if(intent.getAction().equals(GCMRegistrationIntentService.REGISTRATION_SUCCESS)){
                //Getting the registration token from the intent
                String token = intent.getStringExtra("token");
                //Displaying the token as toast
                Toast.makeText(getApplicationContext(), "Registration token:" + token, Toast.LENGTH_LONG).show();

                //if the intent is not with success then displaying error messages
            } else if(intent.getAction().equals(GCMRegistrationIntentService.REGISTRATION_ERROR)){
                Toast.makeText(getApplicationContext(), "GCM registration error!", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(getApplicationContext(), "Error occurred", Toast.LENGTH_LONG).show();
            }
        }
    };

    //Checking play service is available or not
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());

    //if play service is not available
    if(ConnectionResult.SUCCESS != resultCode) {
        //If play service is supported but not installed
        if(GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
            //Displaying message that play service is not installed
            Toast.makeText(getApplicationContext(), "Google Play Service is not install/enabled in this device!", Toast.LENGTH_LONG).show();
            GooglePlayServicesUtil.showErrorNotification(resultCode, getApplicationContext());

            //If play service is not supported
            //Displaying an error message
        } else {
            Toast.makeText(getApplicationContext(), "This device does not support for Google Play Service!", Toast.LENGTH_LONG).show();
        }

        //If play service is available
    } else {
        //Starting intent to register device
        Intent itent = new Intent(this, GCMRegistrationIntentService.class);
        startService(itent);
    }
}

//Unregistering receiver on activity paused
@Override
public void onPause() {
    super.onPause();
    Log.w("MainActivity", "onPause");
    LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
}



    @Override
    public void onResume() {
 super.onResume();
        Log.w("MainActivity", "onResume");
        LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
                new IntentFilter(GCMRegistrationIntentService.REGISTRATION_SUCCESS));
        LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
                new IntentFilter(GCMRegistrationIntentService.REGISTRATION_ERROR));
    }

7)在AndroidManifest.xml中添加以下行:

<uses-permission android:name="android.permission.INTERNET" />

8)在您的控制台logcat中复制您的令牌并粘贴到此site 添加项目编号,令牌和消息。它对我来说很好用:))

答案 9 :(得分:0)

在这一整天之后,我可以100%确认Optimizely库也在某种程度上发生冲突并导致此错误。具体来说,我通过Fabric使用Optimizely。在以这种方式使用Optimizely时可能无法使Firebase初始化(可能在所有方面?)。

我已经在他们的github上发布了它并将直接与他们联系......

https://github.com/optimizely/Optimizely-Android-SDK/issues/11

答案 10 :(得分:0)

我遇到了同样的问题。 我将SDK工具更新到25.1.7 rc1,然后问题就消失了。

答案 11 :(得分:0)

将SDK工具更新到25.1.7并修复了此问题。

答案 12 :(得分:0)

我遇到了这个问题,我的app gradle版本从1.5.0更改为2.0.0。

变化 classpath

com.android.tools.build:gradle:1.5.0

classpath 'com.android.tools.build:gradle:2.0.0

答案 13 :(得分:0)

解决方案1:

dependencies {
 compile `com.android.support:appcompat-v7:23.4.0`
 compile `com.android.support:support-v4:23.4.0`
 compile `com.android.support:design:23.4.0`
 compile `com.google.android.gms:play-services:9.0.0`
}

解决方案2:检测文件夹上的不兼容.idie / libraries /       。有时你宣布play-services-ads:8.4.0与play-services-gcm:9.0.0并发       。你必须覆盖你检测到的build.grade不兼容的库