错误描述

今天使用第三方的so库时候,调用JNI方法时出现了错误。报错如下所示:

11-01 16:39:20.979 4669-4669/com.netease.xtc.cloudmusic E/art: No implementation found for void com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils.nativeInit(android.content.Context) (tried Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit and Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit__Landroid_content_Context_2)
11-01 16:39:20.980 4669-4669/com.netease.xtc.cloudmusic D/AndroidRuntime: Shutting down VM
11-01 16:39:20.984 4669-4669/com.netease.xtc.cloudmusic E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.netease.xtc.cloudmusic, PID: 4669
java.lang.UnsatisfiedLinkError: No implementation found for void com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils.nativeInit(android.content.Context) (tried Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit and Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit__Landroid_content_Context_2)
at com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils.nativeInit(Native Method)
at com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils.<clinit>(NeteaseMusicUtils.java:11)
at com.netease.xtc.cloudmusic.MainActivity$1.onClick(MainActivity.java:26)
at android.view.View.performClick(View.java:5277)
at android.view.View$PerformClick.run(View.java:21704)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5905)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749)

在MainActivity中,尝试调用NeteaseMusicUtils类封装好的JNI方法,代码如下所示:

package com.netease.xtc.cloudmusic;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View; import com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils; public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) { String params = NeteaseMusicUtils.getUrlParameters("/search","{\"keyword\":\"周杰伦\",\"limit\":10,\"offset\":0}"); Snackbar.make(view, "params = " + params , Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
} }

而com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils代码如下:

package com.netease.xtc.cloudmusic.utils;

import android.content.Context;

import com.netease.xtc.cloudmusic.app.NeteaseMusicApplication;

public class NeteaseMusicUtils {
static {
//加载库文件
System.loadLibrary("poison");
nativeInit(NeteaseMusicApplication.getContext());
} /**
* 初始化,必须
* @param context
*/
public native static void nativeInit(Context context); /**
* 获取请求中"params"的值
* 例:如果调用搜索接口,搜索keyword=周杰伦 limit=10 offset=0
* params=getUrlParameters("/search","{\"keyword\":\"周杰伦\",\"limit\":10,\"offset\":0}\")
* @param requestUri 接口说明中的uri
* @param paramJson 接口说明中的参数json表达,如果为空请传"{}"
* @return
*/
public native static String getUrlParameters(String requestUri, String paramJson);
}

其中so库位置如下所示:

错误分析

再一次查看下错误日志,如下所示:

11-01 16:47:53.363 11117-11117/com.netease.xtc.cloudmusic E/art: No implementation found for void com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils.nativeInit(android.content.Context) (tried Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit and Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit__Landroid_content_Context_2)
11-01 16:47:53.364 11117-11117/com.netease.xtc.cloudmusic D/AndroidRuntime: Shutting down VM
11-01 16:47:53.365 11117-11131/com.netease.xtc.cloudmusic I/[MALI][Gralloc]: [+]r_hnd(0xf24b3960), client(36), share_fd(44)
11-01 16:47:53.373 11117-11117/com.netease.xtc.cloudmusic E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.netease.xtc.cloudmusic, PID: 11117
java.lang.UnsatisfiedLinkError: No implementation found for void com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils.nativeInit(android.content.Context) (tried Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit and Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit__Landroid_content_Context_2)
at com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils.nativeInit(Native Method)
at com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils.<clinit>(NeteaseMusicUtils.java:11)
at com.netease.xtc.cloudmusic.MainActivity$1.onClick(MainActivity.java:26)
at android.view.View.performClick(View.java:5277)
at android.view.View$PerformClick.run(View.java:21704)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5905)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749)

错误日志提示我们没有 Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit 方法的实现,如下所示:

 java.lang.UnsatisfiedLinkError: No implementation found for void com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils.nativeInit(android.content.Context) (tried Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit and Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit__Landroid_content_Context_2)

然后我去咨询了一下第三方提供so库的工作人员,回复说NeteaseMusicUtils类的包名一定要是com.netease.cloudmusic.utils。原因是JNI接口Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit中,com.netease.xtc.cloudmusic.utils代表的是package nameNeteaseMusicUtils则是class name

而第三方提供so库的工作人员的c文件的定义JNI接口为Java_com_netease_cloudmusic_utils_NeteaseMusicUtils_nativeInit,即:package name必须为:com.netease.cloudmusic.utils,而class name必须为 NeteaseMusicUtils

也就是说,我们.so中函数声明涉及到的package name和class name与调用它的package name和class name不符。因此我们要改变我们工程中的package name和class name。使其与.so文件中函数签名提示的一致,在这个类中加入native方法的声明。

错误解决方法

好吧,我新建一个包名为com.netease.cloudmusic.utils,并把NeteaseMusicUtils类移到该包名地下。

未移动NeteaseMusicUtils到com.netease.cloudmusic.utils包之前

移动NeteaseMusicUtils到com.netease.cloudmusic.utils包之后

然后重新编译,成功运行。

JNI的命名规则

这里顺便说一下JNI的命名规则,对于传统的JNI编程来说,JNI方法跟Java类方法的名称之间有一定的对应关系,要遵循一定的命名规则,如下所示:

  1. 前缀: Java_
  2. 类的全限定名,用下划线进行分隔(_):com_oyp_jni_JniTest
  3. 方法名:getTestString
  4. JNI函数指定第一个参数: JNIEnv *
  5. JNI函数指定第二个参数: jobject
  6. 实际Java参数: jstring, jint ….

所以对于在Java类 com.oyp.jni.JniTest类的一个方法:

public native String getTestString (String oyp);

其对应的jni层的方法如下:

jstring Java_com_oyp_jni_JniTest_getTestString(JNIEnv * e, jobject clazz, jstring oyp);

如果不这样命名,当把动态库加载进DVM的时候,通过JNIEnv *指针去查找Java Native方法对应的JNI方法的时候,就会找不到了。

注意,我们也可以利用函数注册的方法,将Java层的方法名跟JNI层的方法名的对应关系保存起来,注册到DVM中,就不需要这样的命名规范了。

JNI 数据类型

我们知道Java的数据类型是跟C/C++的数据类型是不一样的,而JNI是处于Java和Native本地库(大部分是用C/C++写的)中间的一层,JNI对于两种不同的数据类型之间必须做一种转换,所以在JNI跟Java之间就会有数据类型的对应关系。 在JNI中,提供了以下各种数据类型,可以分为原生类型和引用类型: 对于原生类型有:jchar, jbyte, jshort, jint, jlong, jfloat, jdouble, jboolean,其与java端的数据类型对应如下表:

java jni
char jchar
byte jbyte
short jshort
int jint
long jlong
float jfloat
double jdouble
boolean jboolean

对于引用类型则有:jobject, jstring, jthrowable, jclass, jarray, 以及继承于jarray,对应于其原生类型的8种jarray和jobjectarray。


作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!

转载请保留原文地址:http://blog.csdn.net/ouyang_peng/article/details/52973274

【我的Android进阶之旅】Android调用JNI出错 java.lang.UnsatisfiedLinkError: No implementation found for的解决方法的更多相关文章

  1. 我的Android进阶之旅------>关于调用Webservice查询火车票时刻表的几个接口介绍

    今天发现一个可以提供火车票时刻表查询的WebService,先记录下来以后如果写一个火车票时刻表查询的Android App的话就用的着.首先该WebService的的名字是TrainTimeWebS ...

  2. 我的Android进阶之旅------> Android为TextView组件中显示的文本添加背景色

    通过上一篇文章 我的Android进阶之旅------> Android在TextView中显示图片方法 (地址:http://blog.csdn.net/ouyang_peng/article ...

  3. 我的Android进阶之旅------>Android疯狂连连看游戏的实现之实现游戏逻辑(五)

    在上一篇<我的Android进阶之旅------>Android疯狂连连看游戏的实现之加载界面图片和实现游戏Activity(四)>中提到的两个类: GameConf:负责管理游戏的 ...

  4. 我的Android进阶之旅------>Android疯狂连连看游戏的实现之加载界面图片和实现游戏Activity(四)

    正如在<我的Android进阶之旅------>Android疯狂连连看游戏的实现之状态数据模型(三)>一文中看到的,在AbstractBoard的代码中,当程序需要创建N个Piec ...

  5. 我的Android进阶之旅------>Android中AsyncTask源码分析

    在我的<我的Android进阶之旅------>android异步加载图片显示,并且对图片进行缓存实例>文章中,先后使用了Handler和AsyncTask两种方式实现异步任务机制. ...

  6. 我的Android进阶之旅------> Android为TextView组件中显示的文本加入背景色

    通过上一篇文章 我的Android进阶之旅------> Android在TextView中显示图片方法 (地址:http://blog.csdn.net/ouyang_peng/article ...

  7. 我的Android进阶之旅------>Android颜色值(#AARRGGBB)透明度百分比和十六进制对应关系以及计算方法

    我的Android进阶之旅-->Android颜色值(RGB)所支持的四种常见形式 透明度百分比和十六进制对应关系表格 透明度 十六进制 100% FF 99% FC 98% FA 97% F7 ...

  8. 我的Android进阶之旅------>Android中查看应用签名信息

    一.查看自己的证书签名信息 如上一篇文章<我的Android进阶之旅------>Android中制作和查看自定义的Debug版本Android签名证书>地址:http://blog ...

  9. 我的Android进阶之旅------>Android利用温度传感器实现带动画效果的电子温度计

    要想实现带动画效果的电子温度计,需要以下几个知识点: 1.温度传感器相关知识. 2.ScaleAnimation动画相关知识,来进行水印刻度的缩放效果. 3.android:layout_weight ...

随机推荐

  1. Java创建多线程的三种方法

    Java多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式线程执行完后都没 ...

  2. 5.14日学习内容1:jquery表单相关知识

    <script> $comment.animate({height:'+=50'},400);//在原来的基础上加50: $('.smaller').click(function(){ i ...

  3. django的html模板中获取字典的值

    在django的html模板中获取字典中的值应当直接使用 字典.[key] 的方式 {% for i in lists %} <li id="{{i.id}}" class ...

  4. jQuery 实战读书笔记之第三章:操作 jQuery 集合

    创建新 HTML 元素 $('<div>Hello</div>'); /* 创建等价的空 div 元素 */ $('<div>'); $('<div /> ...

  5. 名词解释 ssl、tls、key、crt、cer、x509

    1. SSL:安全套接字层 Secure Socket Layer的缩写 2. TLS:传输层安全协议 Transport Layer Security的缩写  ,SSL的继任者 3. KEY:通常指 ...

  6. Android控件——7种形式的Android Dialog使用举例(转载)

    在Android开发中,我们经常会需要在Android界面上弹出一些对话框,比如询问用户或者让用户选择.这些功能我们叫它Android Dialog对话框,在我们使用Android的过程中,我归纳了一 ...

  7. mean 快速开发和现有技术的对比分析

    最近无聊的时候,网上看了下全栈开发的相关资料,发现了mean这个好玩的东西.可能我是一个比较传统的开发,接触.net 已经将近快8年了,一直在传统的后端多层架构的模式下开发,一时对这个新的东西就喜欢研 ...

  8. C++ STL标准模板库(queue)

    //queue的使用 #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<queue> using name ...

  9. Android开发人员必须掌握的10 个开发工具+应该深入学习的10个开源应用项目

    一.Android开发人员必须掌握的10 个开发工具 Android SDK 本身包含很多帮助开发人员设计.开发.测试和发布 Android 应用的工具,在本文中,我们将讨论 10 个最常用的工具. ...

  10. Cross compile perl

    Alex Suykov had do some work for this purpose, and my compile script is based on her patch. Steps St ...