最新版Android Studio 创建JNI教程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最新版Android Studio 创建JNI教程相关的知识,希望对你有一定的参考价值。

本文主要目的如题所示,并针对一些创建过程中可能会遇到的问题提供解决方案。

本文主要参考:http://ph0b.com/android-studio-gradle-and-ndk-integration/,里面有视频讲解,嫌看文档麻烦

的可以直戳进去。。。

主要思路:在一个类中创建native方法,编译生成该类的class文件,再去生成该类的头文件,有了头文件之后在c文件中编写代码的具体实现,配置sdk、ndk路径、给ndk模块起名,最后就是对该方法的调用。

详细步骤如下:

1、本地创建native方法

新建一个空的android工程,在类中声明native方法

建议:不在activity中声明native方法,一是为了设计上的简洁并功能分离,二是创建头文件时避免不要的麻烦。

public class JniUtil {
    public native String getStringFromNative();
}

 

2、编译

如图,主要是为了得到带有native方法类的.class文件

技术分享

编译通过之后如下图所示

技术分享

在此目录下会出现JniUtil.class文件。

3、制作JniUtil.class的头文件

3.1打开terminal终端,主要有两种方法:

3.1.1.菜单栏View视图下,选择tool windows,再点击terminal即可进入

3.1.2.快捷键进入

技术分享

3.2 jni生成头文件

终端进入app\\src\\main文件下,再输入以下指令(javah及以后),如图

技术分享

主要格式为 javah –d –jni –classpath,

不熟悉javah指令的朋友可以输入javah -help帮助下。

-o <file>                输出文件 (只能使用 -d 或 -o 之一)                                         
-d <dir>                 输出目录                                                                  
-v  -verbose             启用详细输出                                                              
-h  --help  -?           输出此消息                                                                
-version                 输出版本信息                                                              
-jni                     生成 JNI 样式的标头文件 (默认值)                                          
-force                   始终写入输文 件                                                                                                               
-classpath <path>        从中加载类的路径
                  

路径介绍:  e:\\android-sdks\\platforms\\android-23\\android.jar  为此android工程所依赖的sdk版本,最终锁定到android.jar文件; ..\\..\\build\\intermediates\\classes\\debug com.example.hitman.final.JniUtil代表生成头文件所依据的.class文件.两个路径中间要用英文分号隔开

成功之后会看到main文件夹下多出一个-jni文件(有的可能直接生成jni文件夹)。里面有编译好的头文件

技术分享

可能遇到的问题

1)、某些类文件找不到  更多情况下是在activity中直接声明native方法导致的,由于AS工程依赖的android版本比较高,这就导致e:\\android-sdks\\platforms\\android-23\\android.jar 中没有所需的类,即javah –d找不到所需路径。以下文为例

技术分享
import android.support.v7.app.AppCompatActivity; 
public class MainActivity extends AppCompatActivity {

}
View Code

 

这种情况会导致appCompatActivity找不到,因为e:\\android-sdks\\platforms\\android-23\\android.jar 路径中没有这个类,appCompatActivity的实际路径是 E:\\android-sdks\\extras\\android\\m2repository\\com\\android\\support \\appcompat-v7\\23.1.1(本人路径)

技术分享

解决方案:将native方法迁出activity中,此方法笔者编译一次通过或者将public class MainActivity extends AppCompatActivity 改为public class MainActivity extends Activity

3.3创建.c文件,一定要在jni文件夹中

这时我们要注意,将-jni文件夹改名为jni,否则编译时build文件下不能生成ndk库(笔者遇到过这个问题),改名后再jni文件夹下新建.c文件,任意取名为main.c。内容下图所示:

技术分享
#include <com_example_hitman_finaljni_JniUtil.h>
 
JNIEXPORT jstring JNICALL Java_com_example_hitman_finaljni_JniUtil_getStringFromNative
        (JNIEnv *env, jobject obj){
    return (*env)->NewStringUTF(env,"HELLO FROM NATIVEJNI");
};
View Code

 

注意事项:一定要添加新建的头文件,如蓝色文字所示。

可能遇到问题:有些AS的bug必须要创建两个.c文件才能编译成功。

关于.c文件的语法问题可参考http://blog.chinaunix.net/uid-26000296-id-5296362.html

4、配置sdk、ndk路径,并编译

4.1打开local.propertiesZ文件

技术分享

ndk.dir=E\\:\\\\android-sdks\\\\ndk-bundle
sdk.dir=E\\:\\\\android-sdks

4.2设置好路径之后编译一下就能看到build问价下的ndk中的库了

技术分享

可能遇到的问题

Error:Execution failed for task ‘:app:compileDebugNdk‘.
> Error: NDK integration is deprecated in the current plugin.  Consider trying the new experimental plugin.  For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental.  Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.

这个可以在在gradle.properties 文件里面添加 android.useDeprecatedNdk=true 后重新编译即可

技术分享

5、给自己的库取名字并在activity中调用native方法

5.1在app目录选的build.gradle中添加ndk

技术分享

5.2加载本地库,并调用native方法

只需在activity中调用TextView.setText()方法就可以了。代码如下

public class MainActivity extends AppCompatActivity { 
    static{ 
        System.loadLibrary("MyLib"); 
    } 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.content_main); 
        TextView txt=(TextView)findViewById(R.id.txt); 
        JniUtil util=new JniUtil(this); 
        txt.setText(util.getStringFromNative()); 
            } 
        }); 
    } 
}

 

至此,确保编译通过就能能正常运行,模拟器效果图如下:

技术分享

如有问题、意见或者建议的欢迎留言交流。

以上是关于最新版Android Studio 创建JNI教程的主要内容,如果未能解决你的问题,请参考以下文章

JNI拒绝各种坑!Android Studio 下创建JNI项目

Android Studio NDK 入门教程--JNI签名验证防止恶意调用

Android Studio NDK 入门教程--JNI动态注册本地方法

Android Studio NDK 入门教程--JNI签名验证防止恶意调用

Android Studio NDK 入门教程--JNI签名验证防止恶意调用

Android Studio中的Gstreamer示例