You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何修复Firebase中出现的java.lang.NoClassDefFoundError异常?

问题分析与解决方案

这个错误看起来很误导人——堆栈日志指向了waterDataClear方法,但这个方法本身完全没用到NotificationChannel类。真正的问题是你的代码在API 26以下的Android设备上,尝试调用了仅在Android O(API 26)及以上才存在的NotificationChannel相关逻辑,加上版本兼容处理缺失,最终触发了NoClassDefFoundError

1. 修复NotificationChannel的版本判断逻辑

你的createNotification方法里直接创建了NotificationChannel,但这个类是API 26才引入的,必须先判断系统版本再执行创建操作,否则低版本设备会找不到这个类。修改后的方法如下:

@RequiresApi(api = Build.VERSION_CODES.O)
public void createNotification(Context context, String title, String text, String bigtext, int icon, int i, String channelID, int color,int[] saatler,int[] dklar) {
    Intent myintent = new Intent(context, SplashActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, myintent, PendingIntent.FLAG_UPDATE_CURRENT);
    NotificationCompat.Builder mbuilder = new NotificationCompat.Builder(context.getApplicationContext(), channelID);
    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

    // 仅在API 26及以上设备创建NotificationChannel
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(channelID, channelID, NotificationManager.IMPORTANCE_HIGH);
        channel.setDescription(channelID);
        Objects.requireNonNull(notificationManager).createNotificationChannel(channel);
    }

    mbuilder
            .setSmallIcon(icon)
            .setChannelId(channelID)
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
            .setColor(color)
            .setDefaults(Notification.DEFAULT_ALL)
            .setWhen(System.currentTimeMillis())
            .setContentTitle(title)
            .setContentText(text)
            .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND)
            .setContentInfo("Info")
            .setStyle(new NotificationCompat.BigTextStyle()
                    .bigText(bigtext));
    Objects.requireNonNull(notificationManager).notify(i, mbuilder.build());
    AlarmHelper alarmHelper=new AlarmHelper();
    alarmHelper.helper(context,saatler,dklar);
}

2. 为低版本设备添加兼容的通知创建逻辑

你的onReceive方法调用createNotification时,虽然方法标注了@RequiresApi,但如果低版本设备触发了notificationID=6的广播,还是会直接调用这个方法导致崩溃。需要在调用前也做版本判断,同时为低版本设备编写不带Channel的通知逻辑:

@Override
public void onReceive(Context context, Intent intent) {
    sharedPreferences = context.getSharedPreferences(MAIN_DATA, Context.MODE_PRIVATE);
    Bundle extras = intent.getExtras();
    notificationID = Objects.requireNonNull(extras).getInt("NotificationID");
    if (notificationID == 6) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // API26+使用带Channel的通知方法
            createNotification(context, context.getString(R.string.tracker_title), trackertxt, trackertxt, R.mipmap.ic_launcher, 6, context.getString(R.string.weight_channel), context.getResources().getColor(R.color.colorhedef), saatler, dklar);
        } else {
            // API26以下使用兼容版通知创建逻辑
            Intent myintent = new Intent(context, SplashActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, myintent, PendingIntent.FLAG_UPDATE_CURRENT);
            NotificationCompat.Builder mbuilder = new NotificationCompat.Builder(context.getApplicationContext());
            NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            
            mbuilder
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentIntent(pendingIntent)
                    .setAutoCancel(true)
                    .setColor(context.getResources().getColor(R.color.colorhedef))
                    .setDefaults(Notification.DEFAULT_ALL)
                    .setWhen(System.currentTimeMillis())
                    .setContentTitle(context.getString(R.string.tracker_title))
                    .setContentText(trackertxt)
                    .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND)
                    .setContentInfo("Info")
                    .setStyle(new NotificationCompat.BigTextStyle()
                            .bigText(trackertxt));
            Objects.requireNonNull(notificationManager).notify(6, mbuilder.build());
            AlarmHelper alarmHelper=new AlarmHelper();
            alarmHelper.helper(context,saatler,dklar);
        }
        notificationID = 0;
    }
    if (notificationID == 10) {
        waterDataClear(context);
        notificationID = 0;
    }
}

3. 修复ProGuard混淆问题

检查你的proguard-rules.pro文件,确保AndroidX通知相关类没有被混淆,添加以下规则:

-keep class androidx.core.app.** { *; }
-keep class android.app.NotificationChannel { *; }
-keep class android.app.NotificationManager { *; }

为什么错误堆栈指向waterDataClear?

这是类加载异常导致的“误导性堆栈”:当低版本设备运行时,NotificationCompat.Builder的内部实现可能尝试加载NotificationChannel类(即使你没显式调用),类加载失败会中断广播接收器的执行,堆栈会指向当前正在执行的方法,也就是waterDataClear,但问题根源其实在通知的版本兼容逻辑上。

内容的提问来源于stack exchange,提问作者user13434299

火山引擎 最新活动