[32→100] 找不到集成进来的库文件,为什么?

问题描述

集成JPush出现一个神奇的bug,只要集成好JPush,环信就崩溃,打印如下错误

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.uztek.fh, PID: 31868 java.lang.UnsatisfiedLinkError: 
com.android.tools.fd.runtime.IncrementalClassLoader$DelegateClassLoader 
……中间省略无效log…………
nativeLibraryDirectories=[/data/app/com.uztek.fh-1/lib/arm, /data/app/com.uztek.fh-1/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/lib]]] 
couldn't find "libhyphenate_av.so"

问题排查

一开始,以为是集成步骤出错了,反复注销相关代码来排查问题,发现把设置jniLibs的代码注销即可。

android {
    sourceSets {
        main {
//            jniLibs.srcDirs = ['libs-jpush']
        }
    }
}

问题原因

为什么呢?反复观察文件,发现JPush的so目录和环信不是一致的


JPush lib库结构.png
环信 lib库结构.png

回看bug信息,里面nativeLibraryDirectories=[/data/app/com.uztek.fh-1/lib/arm, /data/app/com.uztek.fh-1/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/lib]]],这几个文件夹下都没有环信的库,而只有JPush的库。所以整个流程是这样的:

  • 集成JPush之前,系统发现armeabi是最匹配的,所以在这个里面发现了环信的库,正常使用。
  • 集成JPush之后,系统发现armeabi-v7a是最匹配的,在这里找到JPush的库,但是没有环信的库,所以产生异常,抛出崩溃。

问题解决

删除掉只含有JPush库的几个文件夹即可。

附赠:JPush集成清单

  1. jPush控制台新建相关的app,获取相应的key值。
  2. 按照Android集成指南集成 jar、so、AndroidManifest.xml、res
  1. 通常吧so和jar放到一个单独的目录,比如libs-jpush,然后在build.gradle添加
android {
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs-jpush']
        }
    }
}
dependencies {
    compile fileTree(dir: 'libs-jpush', include: ['*.jar'])
}
  1. 实现IPushInterface接口,比如
iPushInterface = new IPushInterface() {
    @Override
    public void setDebugMode(boolean b) {
        JPushInterface.setDebugMode(b);
    }
    @Override
    public void initPush(Context context) {
        JPushInterface.init(context);
    }
    @Override
    public void setAlias(Context context, String alias) {
        JPushInterface.setAlias(context, alias, new TagAliasCallback() {
            @Override
            public void gotResult(int i, String s, Set<String> set) {}});
    }
    @Override
    public void resumePush(Context context) {
        JPushInterface.resumePush(context);
    }
    @Override
    public void stopPush(Context context) {
        JPushInterface.stopPush(context);
    }
};
  1. 配置消息接收器,比如:
<receiver
    android:name="panda.android.lib.commonapp.push.PushReceiver"
    android:exported="false"
    android:enabled="true">
    <intent-filter>
        <action android:name="cn.jpush.android.intent.REGISTRATION" /> <!--Required  用户注册SDK的intent-->
        <action android:name="cn.jpush.android.intent.UNREGISTRATION" />
        <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!--Required  用户接收SDK消息的intent-->
        <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!--Required  用户接收SDK通知栏信息的intent-->
        <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!--Required  用户打开自定义通知栏的intent-->
        <action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" /> <!--Optional 用户接受Rich Push Javascript 回调函数的intent-->
        <action android:name="cn.jpush.android.intent.CONNECTION" /><!-- 接收网络变化 连接/断开 since 1.6.3 -->
        <category android:name="${applicationId}" />
    </intent-filter>
</receiver>
  1. 在app初始化的位置初始化引擎
iPushInterface.setDebugMode(true);
iPushInterface.initPush(getActivity());
iPushInterface.setAlias(getActivity(), "alias_mi4");
  1. AndroidManifest.xmlbuild.gradlegradle.properties配置相关的key值
<meta-data android:name="JPUSH_APPKEY" android:value="${jpushAppkey}" /> <!--  </>值来自开发者平台取得的AppKey-->
manifestPlaceholders = [jpushAppkey: "project.jPUSH_APP_KEY"]
jPUSH_APP_KEY=<jPush控制台提供的key值>
  1. 在后台推送通知和消息,进行测试。

Panda
2016-05-25

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容