在应用程序仅在生产版本中加载时出现RuntimeException。

9

我正在创建一个应用程序,遇到了问题。基本上,第一次尝试打开应用程序时,它会崩溃,之后就没问题了。令人困惑的是,只有从Google Play下载应用程序时才会出现这种情况。如果我直接从Android Studio将应用程序加载到手机上,则不会出现任何错误。

java.lang.RuntimeException: 
  at android.app.ActivityThread.handleReceiver (ActivityThread.java:3290)
  at android.app.ActivityThread.-wrap20 (ActivityThread.java)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1715)
  at android.os.Handler.dispatchMessage (Handler.java:102)
  at android.os.Looper.loop (Looper.java:154)
  at android.app.ActivityThread.main (ActivityThread.java:6682)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1520)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1410)
Caused by: java.lang.ClassNotFoundException: 
  at dalvik.system.BaseDexClassLoader.findClass (BaseDexClassLoader.java:56)
  at java.lang.ClassLoader.loadClass (ClassLoader.java:380)
  at java.lang.ClassLoader.loadClass (ClassLoader.java:312)
  at android.app.ActivityThread.handleReceiver (ActivityThread.java:3285)

经过调查,我发现人们说要清除设备的缓存。这解决了问题……但这只是清除了应用程序,然后它就可以正常工作。初始安装仍会崩溃。这在多个设备上发生,但我无法在调试时重现它。我唯一的想法是在调用setContentView()之后,在onCreate()中使用了这段代码。

Intent intent = new Intent(this, NotificationListener.class);
startService(intent);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

NotificationListener.class继承了NotificationListenerService类。除了初始启动之外,一切都运作良好。

更新

以下是我在AndroidManifest中设置服务的方式:

<service android:name=".NotificationListener"
  android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
  <intent-filter>
      <action android:name="android.service.notification.NotificationListenerService" />
  </intent-filter>
</service>

这里是我NotificationListenerService的简化版本:
public class NotificationListener extends NotificationListenerService
{
    private IBinder mBinder = new LocalBinder();

    @Override
    public void onNotificationPosted(StatusBarNotification sbn)
    {
        super.onNotificationPosted(sbn);

        // custom code
    }

    @Override
    public void onNotificationRemoved(StatusBarNotification sbn)
    {
        super.onNotificationRemoved(sbn);
    }

    @Override
    public IBinder onBind(Intent intent)
    {
        if (SERVICE_INTERFACE.equals(intent.getAction()))
            return super.onBind(intent);
        else return mBinder;
    }

    public class LocalBinder extends Binder
    {
        public NotificationListener getService()
        {
            return NotificationListener.this;
        }
    }
}

这是用于Binder的ServiceConnection:

private ServiceConnection serviceConnection = new ServiceConnection()
{
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder)
    {
        NotificationListener.LocalBinder localBinder = (NotificationListener.LocalBinder) iBinder;
        notificationListener = localBinder.getService();
        bound = true;

        // code to call custom function in NotificationListener class
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName)
    {
        notificationListener = null;
        bound = false;
    }
};

我知道这一定是服务绑定的问题,因为如果我删除所有绑定代码并只启动服务,一切都会按照预期运行。只有当我添加绑定代码时才会出现此错误。


你能否尝试在不使用Proguard的情况下创建APK文件吗? - kimkevin
1
@KimKevin 这是否只涉及在应用 gradle 的 buildTypes 中删除它的条目?如果是这样,我已经将其删除并上传了我的应用程序的 beta 版本,但仍然在启动时遇到相同的错误。 - sabo
1
@KimKevin 我已经移除了 Proguard,并将 minifyEnabled 设置为 false。是的,作为服务,我把 NotificationListenerService 放在了清单中。 - sabo
1
@KimKevin,请查看我的编辑。我在查看了更多的文档后很好奇,清单中服务的意图过滤器是否可能会成为一个问题。 - sabo
@KimKevin 我在你说的地方找到了。 - sabo
显示剩余4条评论
3个回答

2

看起来您不需要再启动和绑定服务。请在删除以下代码后创建签名apk文件。

Intent intent = new Intent(this, NotificationListener.class);
startService(intent);

我认为这是ProGuard混淆,因此请将以下代码添加到您的ProGuard文件中。
# Base Android exclusions, required for proper function of various components
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.preference.Preference
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment

我扔掉了startService()调用,因为bindService()应该处理它。然而,它仍然崩溃了。我想看看错误是否改变,但出于某种原因,我在beta版中没有得到任何崩溃。 - sabo
当我删除 startService() 后,我仍然会收到相同的错误。 - sabo
我没有处理proguard文件的经验,所以我将其添加到了我的proguard-android.txt-2.3.3文件和我的aapt_rules.txt文件中。但是仍然会崩溃。 - sabo
还有其他想法吗?那个 proguard-android.txt-2.3.3 文件是放置你提到的更改的正确文件吗? - sabo

0

通常这个问题是由于Proguard引起的,如果您将Proguard添加到项目中,它会停止一些功能,比如这个。

只需尝试在proguard-rules.pro文件中添加您的服务模块,方法是添加:

-keep class {package-name}.{service-module-name}.** { *; }

例如:> -keep class com.demo.service.** { *; }

这将在Proguard中添加所有服务权限。


如果使用Proguard会导致问题,我能否直接删除它? - sabo
每件事物都有其优点和缺点,Proguard也是如此。它可以为您提供良好的安全性和许多其他功能。因此,我的建议是将这些文件添加到proguard-rules.pro文件中,而不是完全删除它。 - Vikrant Shah

0
这里的ClassNotFoundException没有消息。查看dalvik.system.BaseDexClassLoader源代码,如果找不到指定的类,则会抛出一个带有该类名称的ClassNotFoundException,因此,在某个地方传递了一个空的类名(即在由ActivityThread::handleReceiver处理的消息中)。如果您能提供完整的堆栈跟踪(即委托此handleReceiver调用的handleMessage分支),那将非常有帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接