【问题标题】:IBM Mobile First 7.1 - Push on Hybrid Android App - Dex Class not FoundIBM Mobile First 7.1 - 推送混合 Android 应用程序 - 未找到 Dex 类
【发布时间】:2016-03-14 13:27:49
【问题描述】:

我最近为我们的一位客户实施了一个基于混合 Cordova 的应用程序,并根据 MFP 文档为其添加了推送通知。

几乎一切正常,注册广播推送事件,通过 MFP 服务器发送和接收它们,并在 Javascript 中处理它们。如果应用程序未处于活动状态,则推送通知会显示在通知栏上,这没关系。

但是,点击它不会启动应用程序,因此我的 javascript 代码永远不会收到通知。

相反,Logcat 显示此异常:

03-10 15:47:37.489: E/Parcel(3190): Class not found when unmarshalling: com.worklight.wlclient.push.GCMIntentService$Message
03-10 15:47:37.489: E/Parcel(3190): java.lang.ClassNotFoundException: com.worklight.wlclient.push.GCMIntentService$Message
03-10 15:47:37.489: E/Parcel(3190):     at java.lang.Class.classForName(Native Method)
03-10 15:47:37.489: E/Parcel(3190):     at java.lang.Class.forName(Class.java:308)
03-10 15:47:37.489: E/Parcel(3190):     at java.lang.Class.forName(Class.java:272)
03-10 15:47:37.489: E/Parcel(3190):     at android.os.Parcel.readParcelableCreator(Parcel.java:2275)
03-10 15:47:37.489: E/Parcel(3190):     at android.os.Parcel.readParcelable(Parcel.java:2239)
03-10 15:47:37.489: E/Parcel(3190):     at android.os.Parcel.readValue(Parcel.java:2146)
03-10 15:47:37.489: E/Parcel(3190):     at android.os.Parcel.readArrayMapInternal(Parcel.java:2479)
03-10 15:47:37.489: E/Parcel(3190):     at android.os.BaseBundle.unparcel(BaseBundle.java:221)
03-10 15:47:37.489: E/Parcel(3190):     at android.os.BaseBundle.getString(BaseBundle.java:918)
03-10 15:47:37.489: E/Parcel(3190):     at android.content.Intent.getStringExtra(Intent.java:5440)
03-10 15:47:37.489: E/Parcel(3190):     at com.android.server.am.ActivityStackSupervisor.startActivityLocked(ActivityStackSupervisor.java:1871)
03-10 15:47:37.489: E/Parcel(3190):     at com.android.server.am.ActivityStackSupervisor.startActivityMayWait(ActivityStackSupervisor.java:1409)
03-10 15:47:37.489: E/Parcel(3190):     at com.android.server.am.ActivityManagerService.startActivityInPackage(ActivityManagerService.java:5565)
03-10 15:47:37.489: E/Parcel(3190):     at com.android.server.am.PendingIntentRecord.sendInner(PendingIntentRecord.java:257)
03-10 15:47:37.489: E/Parcel(3190):     at com.android.server.am.PendingIntentRecord.send(PendingIntentRecord.java:197)
03-10 15:47:37.489: E/Parcel(3190):     at android.content.IIntentSender$Stub.onTransact(IIntentSender.java:64)
03-10 15:47:37.489: E/Parcel(3190):     at android.os.Binder.execTransact(Binder.java:446)
03-10 15:47:37.489: E/Parcel(3190): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.worklight.wlclient.push.GCMIntentService$Message" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
03-10 15:47:37.489: E/Parcel(3190):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
03-10 15:47:37.489: E/Parcel(3190):     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
03-10 15:47:37.489: E/Parcel(3190):     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
03-10 15:47:37.489: E/Parcel(3190):     ... 17 more
03-10 15:47:37.489: E/Parcel(3190):     Suppressed: java.lang.ClassNotFoundException: com.worklight.wlclient.push.GCMIntentService$Message
03-10 15:47:37.489: E/Parcel(3190):         at java.lang.Class.classForName(Native Method)
03-10 15:47:37.489: E/Parcel(3190):         at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
03-10 15:47:37.489: E/Parcel(3190):         at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
03-10 15:47:37.489: E/Parcel(3190):         at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
03-10 15:47:37.489: E/Parcel(3190):         ... 18 more
03-10 15:47:37.489: E/Parcel(3190):     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

我检查了索引类和内部类。尽管如此,dex 类加载器拒绝找到/加载它们。我还仔细检查了活动名称、权限以及我在 Stack Overflow 等上挖掘的所有其他内容,但无济于事。由于 dex 类加载器上缺少该内部类,因此无法处理它的应用程序可以正常接收 Intent。

这是没有 ProGuard 的调试版本。我还将项目从 Eclipse/ADT/ANT 迁移到 Android Studio/Gradle 只是为了面临同样的问题,所以我认为这与 GCM 库或构建过程本身无关。这可能与 dex 路径有关,但我不知道如何分析或解决此问题。

由于所涉及库的大小(Google Play 和移动优先),我不得不在 project.properties 中设置 dex.force.jumbo=true。

这是我的 AndroidManifest:

<?xml version="1.0" encoding="UTF-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ag.entega.enetz.promt" android:versionCode="15" android:versionName="1.12">  
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22"/>  
<supports-screens android:smallScreens="false" android:normalScreens="true" android:largeScreens="true"/>  
<uses-permission android:name="android.permission.INTERNET"/>  
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>  
<permission android:name="ag.entega.enetz.promt.permission.C2D_MESSAGE" android:protectionLevel="signature"/>  
<uses-permission android:name="ag.entega.enetz.promt.permission.C2D_MESSAGE"/>  
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>  
<uses-permission android:name="android.permission.WAKE_LOCK"/>  
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>  
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
<uses-permission android:name="android.permission.CAMERA"/>  
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>  
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>  
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>  
<uses-feature android:name="android.hardware.wifi"/>  
<application android:label="@string/app_label" android:icon="@drawable/icon" android:allowBackup="false" android:largeHeap="true"> 
    <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/>  
    <activity android:name="promt" android:label="@string/app_label" android:configChanges="orientation|keyboardHidden|screenSize" android:launchMode="singleTask" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:screenOrientation="sensor"> 
        <intent-filter> 
            <action android:name="android.intent.action.MAIN"/>  
            <category android:name="android.intent.category.LAUNCHER"/> 
        </intent-filter>  
        <intent-filter> 
            <action android:name="ag.entega.enetz.promt.NOTIFICATION"/>  
            <category android:name="android.intent.category.DEFAULT"/> 
        </intent-filter> 
    </activity>  
    <!-- Preference Activity  -->  
    <activity android:name="com.worklight.common.WLSettingActivity" android:label="Worklight Settings"/>  
    <!-- UI Activity for displaying native dialogs  -->  
    <activity android:name="com.worklight.wlclient.ui.UIActivity"/>  
    <!-- Push service  -->  
    <!-- In order to use the c2dm library, an application must declare a class with the name C2DMReceiver, in its own package, extending com.google.android.c2dm.C2DMBaseReceiver
        It must also include this section in the manifest, replacing "com.google.android.apps.chrometophone" with its package name. -->  
    <service android:name="GCMIntentService"/>  
    <service android:name="ForegroundService"/>  
    <!-- Only google service can send data messages for the app. If permission is not set - any other app can generate it -->  
    <receiver android:name="com.worklight.androidgap.push.WLBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND"> 
        <!-- Receive the actual message -->  
        <intent-filter> 
            <action android:name="com.google.android.c2dm.intent.RECEIVE"/>  
            <category android:name="ag.entega.enetz.promt"/> 
        </intent-filter>  
        <!-- Receive the registration id -->  
        <intent-filter> 
            <action android:name="com.google.android.c2dm.intent.REGISTRATION"/>  
            <category android:name="ag.entega.enetz.promt"/> 
        </intent-filter> 
    </receiver>  
    <activity android:name="com.google.zxing.client.android.CaptureActivity" android:screenOrientation="landscape" android:configChanges="orientation|keyboardHidden" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:windowSoftInputMode="stateAlwaysHidden"> 
        <intent-filter> 
            <action android:name="com.phonegap.plugins.barcodescanner.SCAN"/>  
            <category android:name="android.intent.category.DEFAULT"/> 
        </intent-filter> 
    </activity>  
    <activity android:name="com.google.zxing.client.android.encode.EncodeActivity" android:label="@string/share_name"> 
        <intent-filter> 
            <action android:name="com.phonegap.plugins.barcodescanner.ENCODE"/>  
            <category android:name="android.intent.category.DEFAULT"/> 
        </intent-filter> 
    </activity> 
</application> 

我的问题是:如何解决这个内部类未找到异常?非常感谢任何帮助。

【问题讨论】:

  • 您需要提供您的 AndroidManifest.xml。我认为这与任何 dex 都没有关系。
  • 您是否修改了生成的 AndroidManifest.xml 中的任何内容?如果您要删除环境并重新添加它,是否可以解决问题?
  • @VivinK 没有尝试过这个......我添加/更改的内容涉及 GCM 的权限,并且我引入了 app_label 作为资源来断开显示名称与应用程序/活动名称的连接。会检查一下,谢谢你的想法。
  • 已知断开显示名称会产生无法通过点击推送通知启动应用程序的副作用
  • @VivinK 是的,但仅限于意图动作定义不正确的效果。这将导致 Logcat 消息,例如“无法使用动作 xyz 启动意图”,因为实际上没有应用程序提供该动作。这里的不同之处在于无法加载重要的类。我认为显示名称与 dex 加载器中缺少的类没有任何关系。但我可能错了。

标签: android cordova push ibm-mobilefirst hybrid


【解决方案1】:

好的,我明白了。感谢您的所有建议!

首先,我不必要地将 google play 库包含到我的项目中。它由 Google 推荐并且通常需要,但不适用于 MFP。移动优先平台为游戏带来了一切,以使用 GCM 推送通知。但是删除lib后仍然出现错误。

所以我查看了 IBM 的示例项目,设置并运行它,瞧,当点击通知时应用程序打开。所以我仔细检查了AndroidManifest,发现了两个不同之处:

首先,我在应用名称“promt”前面缺少了一个点。所以正确的是“.promt”。

通知的第二个意图过滤器缺少活动名称:

<intent-filter> 
    <action android:name="ag.entega.enetz.promt.NOTIFICATION"/>  
    <category android:name="android.intent.category.DEFAULT"/> 
</intent-filter> 

必须

<intent-filter> 
    <action android:name="ag.entega.enetz.promt.promt.NOTIFICATION"/>  
    <category android:name="android.intent.category.DEFAULT"/> 
</intent-filter>

修复此问题后不再出现错误,点击通知即可打开应用。

因此@IdanAdar 和@Vikin K 指向AndroidManifest.xml 是正确的。再次感谢各位!

这让我很不解为什么这个异常并没有指出手头的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多