接触安卓有一段时间了,一直没有时间或者说自己没有主动去练习一些jni,今天就来分享一下jni的过程、步骤

我用的环境是studio jdk1.8

1:下载ndk 地址自行百度 安装完成后配置环境变量

Android 单独编译 so 安卓编译so_java

Android 单独编译 so 安卓编译so_android_02


2:AS新建一个项目,然后打开设置 配置一下ndk路径

Android 单独编译 so 安卓编译so_Android 单独编译 so_03


然后配置一下gradle文件 如图

Android 单独编译 so 安卓编译so_jni_04


3: 这时候开始编写代码了,如下图

Android 单独编译 so 安卓编译so_java_05


不擅长文字描述,多用图片,大家别介意,重点来了:

4: 命令行进入刚才编写的NativeTest文件路径 javac 类名.java生成javac文件 如图:

Android 单独编译 so 安卓编译so_java_06


然后开始编译生成.h头文件 javah 包名.类名看下图 注意命令行目录位置:

Android 单独编译 so 安卓编译so_头文件_07


5:有了头文件 接下来要创建jni目录 编写c代码了 步骤 如图:

Android 单独编译 so 安卓编译so_头文件_08

直接点finish就好 然后复制刚才的.h头文件到这个目录里面 如图:

Android 单独编译 so 安卓编译so_Android 单独编译 so_09


这时候创建一个.c文件 开始编写c代码了 如图:

Android 单独编译 so 安卓编译so_java_10


Android 单独编译 so 安卓编译so_头文件_11


好了 开始编写c代码 在刚刚创建的.c文件编写 先引入.h头文件:

#include <com_ndktest_NativeTest.h>`

下一步 重写.h头文件的方法:

//
// Created by Administrator on 2017/9/14 0014.
//
#include <com_ndktest_NativeTest.h>
JNIEXPORT jstring JNICALL Java_com_ndktest_NativeTest_getHint
        (JNIEnv *env, jclass obj){
    return (*env)->NewStringUTF(env,"简单的方法返回值 ,不传参数");
}


JNIEXPORT jstring JNICALL Java_com_ndktest_NativeTest_getToastInfo
        (JNIEnv *env, jclass o, jstring s){
    return  s;
}

配置一下等下要生成的so名字 架构:

Android 单独编译 so 安卓编译so_jni_12


接下来 在刚才的cpp目录 创建 Android.mk文件 用于编写so的一些配置:

Android 单独编译 so 安卓编译so_java_13


还有一个Application.mk文件:

Android 单独编译 so 安卓编译so_Android 单独编译 so_14

重点来了;开始打包so库

7: 命令如下图:

Android 单独编译 so 安卓编译so_头文件_15

大功完成99,还差最后一点点 注释掉刚才build里的这几句话 删除也可以:

ndk {
            moduleName "test"//指定生成的so文件名
            abiFilters "armeabi", "armeabi-v7a", "x86"//cpu的类型
        }

        sourceSets.main {
            jni.srcDirs = ['libs']
        }

然后在项目的main目录新建一个jniLibs目录 拷贝libs里的全部架构进去,删除libs obj jni目录文件 当然,你喜欢 也可以复制到其他地方保存

Android 单独编译 so 安卓编译so_jni_16


最后一步了 我们回到一开始编写的NativeTest.java类里面 初始化一下我们打包的so库:

package com.ndktest;


public class NativeTest {
    static {
        System.loadLibrary("test");
    }

    public static native String getHint();

    public static native String getToastInfo(String values);
}

然后可以去调用这个类的方法了 :

package com.ndktest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toast.makeText(this,
                "jni返回的提示:" + NativeTest.getHint() + " 传过去的参数: "
                        + NativeTest.getToastInfo("sdadasda"),
                Toast.LENGTH_SHORT).show();
        Log.e("jni返回的提示",NativeTest.getHint());
        Log.e("传过去的参数",NativeTest.getToastInfo("sdadasda"));
    }
}

Android 单独编译 so 安卓编译so_Android 单独编译 so_17

Android 单独编译 so 安卓编译so_java_18


好了,本文到这里结束了,希望大家喜欢;

ps:在.c里面返回字符串的时候 使用这个NewStringUTF 请注意,如果你在java里传过去的是字符串 ,请别用NewStringUTF 进行编码 会报错,解决方法两个 1:不使用NewStringUTF ,原样返回值,2 :对传过来的java字符串进行转码,比较麻烦,自行百度。