项目实战:Android Studio与NDK的不期而遇

Android平台从诞生起,就已经支持CC++开发。众所周知,AndroidSDK基于Java实现,这意味着基于AndroidSDK进行开发的第三方应用都必须使用Java语言。但这并不等同于“第三方应用只能使用Java”。

Android SDK首次发布时,Google就宣称其虚拟机Dalvik支持JNI编程方式,也就是第三方应用完全可以通过JNI调用自己的C动态库,即在Android平台上,“Java+C”的编程方式是一直都可以实现的。

不过,Google也表示,使用原生SDK编程相比Dalvik虚拟机也有一些劣势,Android SDK文档里,找不到任何JNI方面的帮助。即使第三方应用开发者使用JNI完成了自己的C动态链接库(so)开发,但是so如何和应用程序一起打包成apk并发布?

这里面也存在技术障碍。比如程序更加复杂,兼容性难以保障,无法访问Framework APIDebug难度更大等。开发者需要自行斟酌使用。于是NDK就应运而生了。NDK全称是Native Development KitNDK的发布,使“Java+C”的开发方式终于转正,成为官方支持的开发方式。NDK将是Android平台支持C开发的开端。

我们为什么使用NDK?

1.代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。

2.可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。

3.提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。

4.便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。


下面正式开始AS与NDK的邂逅。


温馨提示:从Android Studio 1.3 Beta1开始,就支持了NDK。在进行配置前请先将Android Studio更新至最新版本,不低于1.3。

这里写图片描述

然后使用Android Studio内置的SDK管理器下载NDK。

这里写图片描述

或者在项目上右键打开Project Structure,切到的SDK Location页进行安装

这里写图片描述


咱们先建一个NdkJniDemo的工程,再新建JniUtils类实现native方法

public class JniUtils {
    public static native String getStringFormC();

    static {
        //System.loadLibrary("NdkJniDemo");//之前在build.gradle里面设置的so名字,必须一致
    }
}

Build-Clean Project-Rebuild Project生成class文件,

这时候打开如下图的文件夹看是否生成了classes文件夹,没有生成请重新来过。



再打开Terminal输入指令
cd app/build/intermediates/classes/debug
然后再输入指令
javah -jni 包名.JniUtils
注意 这里javah -jni后面跟的是JniUtils类的全路径,如果javah报不存在之类的,是你的java环境没有配置好。


这时候打开classes/debug下面的文件发现多了一个文件
包名_JniUtils.h
然后在src/main下新建文件夹jni,把生成的.h文件复制或者剪切到jni文件夹下面去,新建一个c类随便取一个名字如jniutils,添加代码如下:

#include "com_ndkjnidemo_quan_ndkjnidemo_JniUtils.h"
/*
* Class:     Java_com_ndkjnidemo_quan_ndkjnidemo_JniUtils
* Method:    getStringFormC
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ndkjnidemo_quan_ndkjnidemo_JniUtils_getStringFormC
        (JNIEnv *env, jobject obj){
    return (*env)->NewStringUTF(env, "权兴权意-这里是来自C的string");
}

这里发现头文件#include <jni.h>报红色,是因为咱们还没有配置ndk环境,按照开头配置即可。



设置好了之后,发现头文件还是红色的,然后再build一下工程,就会有提示,按着提示做就行了 在gradle.properties文件末尾添加android.useDeprecatedNdk=true就ok啦。

然后在app文件下得build.gradle ->defaultConfig括号内添加如下代码

        ndk{
            moduleName "NdkJniDemo"			//生成的so名字
            ldLibs "log", "z", "m"	//添加依赖库文件,因为有log打印等
            abiFilters "armeabi", "armeabi-v7a", "x86"	//输出指定三种abi体系结构下的so库。目前可有可无。
        }

到了这一步重新build项目,发现已经没有变红了。接下来就是运用了,在JniUtils类里面添加如下代码(同前):

static {    
   System.loadLibrary("NdkJniDemo");//之前在build.gradle里面设置的so名字,必须一致
}

然后简单调用就行了,MainActivity代码如下:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView ndk_text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ndk_text = (TextView) findViewById(R.id.ndk_text);
        ndk_text.setText(JniUtils.getStringFormC());
    }
}


运行结果如图:




小贴士:

1.如果build工程时遇到Error:Executionfailed for task':app:clean'. > Unable to delete file: xxx.file问题,不要慌。

说明这个文件被其他文件占用,可以把AS关掉,直接去对应的文件夹下面手动删除对应的文件,再重新打开AS就ok了。

 

2.遇到error: 'JNIEXPORT'does not name a type的问题,不要慌。

有#include <jni.h>即可。

 

 

小伙伴推荐了一篇文章,可以试试。

用Android Studio 运行ndk 程序

http://blog.csdn.net/cuiran/article/details/50755767

 

参考:

文/兔子吃过窝边草(简书作者)

Android Studio ndk-Jni开发详细入门,Aes加密demo

http://www.jianshu.com/p/d8cde65cb4f7







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值