【发布时间】: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