最近想调用FFmepg库来做编解码的东西,首先就得学会使用JNI(JAVA Native Interface)调用。
下面做个简单的JNI调用实例,中间遇到的问题及解决过程省略一万字,查找到的资料也都是东一句西一句的,整理一下完整的实现过程,希望对初学JNI的朋友有所帮助:
1、创建一个Android工程,名为SimpleJni;
2、在com.example.simplejni包下新建一个Jni接口类SimpleInterface,这个类不需要继承java的接口类;
package com.example.simplejni; public class SimpleInterface { public static native String sayName(); }3、编译这个接口类,为c端调用的头文件。
工程目录:
命令窗口:Win+R运行cmd,cd进入到eclipse工作空间中SimpleJni工程目录,
输入javah -classpath bin/classes -d jni com.example.simplejni.SimpleInterface编译接口类
编译完成后,刷新工程,就可以看到工程中自动创建了jni文件夹,其中包含编译好的.h头文件
4、事先安装好NDT插件,右键SimpleJni工程选择Android tools下Add Native Support选项,library name使用默认的工程名;
完成后,会在jni文件夹中添加一个Android.mk文件和SimpleJni.cpp文件;
打开头文件,是不是发现JNICALL报错了,不着急,下面有解决方法。
5、然后给工程新建并配置一个Builder,能够自动生成so库在Android端代码进行调用。
①右键工程-Properties-Builders-New,在弹出对话框中点击Program。
②在Edit Configuration对话框中的Main选项卡中,添加路径;
Location中选择到NDK安装目录下的ndk-build.cmd;
WorkingDirectory中选择到SimpleJni工程目录。
③选择Refresh选项卡,在其中勾选如下
④在Build Options选项卡中勾选如下
其中Specify Resource中配置到SimpleJni工程的jni目录即可。
到此点击ok,配置完成了,相比通过命令行编译的方法,至少方便很多。
完成后,会在SimpleJni工程libs文件下自动创建armeabi文件夹并包含编译好的libSimpleJni.so库文件,当工程有所改变的时候,就会自动编译so文件;
目前的工程目录结构:
6、下面来填充SimpleJni.cpp,相信学过C++的朋友会觉得很熟悉,在这个cpp文件里面写接口的具体实现。
这里会出现JNICALL等类型无法识别等报错,需要导入一个NDK的include头文件库:
①右键工程,选择Properties -> C/C++ General -> Path and Symbols 中点击include选项卡,添加NDK安装目录下的include文件夹D:\AndroidNDK\android-ndk-r10d\platforms\android-14\arch-arm\usr\include
导入完毕之后就不会报错了
7、首先将头文件Include进来,但是要遵循方法的命名规则:Java_(固定开头)com_example_hellojni(用"_"连接的包名)_HelloJni(类名)_stringFromJNI(函数名) 再从接口.h头文件中把sayName方法复制过来,并修改参数,简单的返回一个字符串。
#include <jni.h> #include <com_example_simplejni_SimpleInterface.h> JNIEXPORT jstring JNICALL Java_com_example_simplejni_SimpleInterface_sayName (JNIEnv *env, jclass){ return env->NewStringUTF("I'm Eric!"); }8、然后修改MainActivity.java代码,添加一个TextView并设置其文本为SayName()方法的返回值;添加static代码块,载入so库,之前右键工程add native Support的library名称就是在这里调用:
package com.example.simplejni; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; public class MainActivity extends Activity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textview_id); textView.setText(SimpleInterface.sayName()); } static { System.loadLibrary("SimpleJni"); } }运行SimpleJni工程,运行结果如下:
可以参考的文章:
NDK生成SO文件:http://blog.csdn.net/laczff21/article/details/7542236
Android调用JNI方法:http://www.2cto.com/kf/201409/330892.html
Android移植ffmpeg后so库的使用:http://tq09931.iteye.com/blog/1011895
还参考了很多资料,就不一一贴上来了,主要对我有帮助的就这些,另外其中遇到了很多问题,通过论坛等大牛获得解决办法。
附上Demo地址:http://download.csdn.net/detail/ericfantastic/9199871