69

AndroidStudio 3.0 NDK开发1——环境搭建与编译

 5 years ago
source link: http://www.koffuxu.com/uncategorized/781.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前提

JNI开发主要有两种方式,一种是在Android源码中编译,另外一种是使用AndroidStuido工具开发。主要是看自己的业务场景。

如果你们公司是平台型开发方式,很容易或者当前就是在Android源码中做项目,推荐使用第一种方式,有Swig工具的加持也是效率很高;

如果公司是偏APP开发,得要适配不同平台,建议使用AndroidStudio工具来开发。本文讲这种方式。

使用AndroidStudio编译C/C++主要有两种方式:CMake和ndk-build

CMake:需要自己编写cmake.txt规则,使用CMake工具来编译;

ndk-build:需要自己编译Android.mk文件,使用ndk-build工具来编译。

因为Android源码是使用Android.mk来编译,所以我更习惯使用ndk-build这种方式。西方是讲这种方式。

Prepare

源码Android SDK快速迭代,JNI在AndroidStudio不同版本上使用有较大的区别,我这贴出我使用AndroidStudio相关版本的情况

OS Windows 10 10.0 NDK 17.2 JDK JRE: 1.8.0_152-release-915-b01 amd64 AndroidStudio IDE Android Studio 3.0
Build #AI-171.4408382, built on October 21, 2017 gradlewrap 版本 gradle-4.4-all.zip AS gradle插件 com.android.tools.build:gradle:3.0.0

Starting

1,安装NDK,CMake,LLDB

aAFvqir.png!web

2,编写并编译JAVA代码

第一步,在自己的项目中新建Java Class: MyJniTest.java

package com.aispeech.aistools.jni;

/**
 * @Author: Gangfeng Xu([email protected])
 * @Date: 9/14/2018
 */

public class MyJniTest {
    static {
        System.loadLibrary("hello-jni");
    }
    public native String getJniVersionName();

}

14

14

1

package com.aispeech.aistools.jni;

2

3

/**

4

 * @Author: Gangfeng Xu([email protected])

5

 * @Date: 9/14/2018

6

 */

7

8

public class MyJniTest {

9

    static {

10

        System.loadLibrary("hello-jni");

11

    }

12

    public native String getJniVersionName();

13

14

}

第二步,Ctrl + F9 make项目

b2qQjuF.png!web

第三步,在app/build目录找到这个类的class文件

rYNvMrF.png!web

第四步,生成头文件

第一种:进到debug目录,执行命令生成头文件

C:\Users\koffuxu\02-sulab\aispeech-tools\app\build\intermediates\classes\debug>javah -jni com.aispeech.aistools.jni.MyJniTest

C:\Users\koffuxu\02-sulab\aispeech-tools\app\build\intermediates\classes\debug>dir
 Volume in drive C has no label.
 Volume Serial Number is 09C1-B27D

 Directory of C:\Users\koffuxu\02-sulab\aispeech-tools\app\build\intermediates\classes\debug

09/14/2018  05:05 PM    <DIR>          .
09/14/2018  05:05 PM    <DIR>          ..
09/14/2018  04:58 PM    <DIR>          android
09/14/2018  04:58 PM    <DIR>          androidx
09/14/2018  04:58 PM    <DIR>          com
09/14/2018  05:05 PM               567 com_aispeech_aistools_jni_MyJniTest.h
               1 File(s)            567 bytes
               5 Dir(s)  173,480,382,464 bytes free

16

16

1

C:\Users\koffuxu\02-sulab\aispeech-tools\app\build\intermediates\classes\debug>javah -jni com.aispeech.aistools.jni.MyJniTest

2

3

C:\Users\koffuxu\02-sulab\aispeech-tools\app\build\intermediates\classes\debug>dir

4

 Volume in drive C has no label.

5

 Volume Serial Number is 09C1-B27D

6

7

 Directory of C:\Users\koffuxu\02-sulab\aispeech-tools\app\build\intermediates\classes\debug

8

9

09/14/2018  05:05 PM    <DIR>          .

10

09/14/2018  05:05 PM    <DIR>          ..

11

09/14/2018  04:58 PM    <DIR>          android

12

09/14/2018  04:58 PM    <DIR>          androidx

13

09/14/2018  04:58 PM    <DIR>          com

14

09/14/2018  05:05 PM               567 com_aispeech_aistools_jni_MyJniTest.h

15

               1 File(s)            567 bytes

16

               5 Dir(s)  173,480,382,464 bytes free

第二种方法:进入需要创建的模块main下面,其实是一样的,只是这种方法看起来更合规,并且省掉了第五步

C:\Users\koffuxu\02-sulab\aispeech-tools\usbrcvoicelib\src\main>javah -d jni -classpath C:\Users\koffuxu\02-sulab\aispeech-tools\usbrcvoicelib\build\intermediates\classes\debug com.aispeech.usbrcvoicelib.nativeutils.UsbVoiceManager
x

1

C:\Users\koffuxu\02-sulab\aispeech-tools\usbrcvoicelib\src\main>javah -d jni -classpath C:\Users\koffuxu\02-sulab\aispeech-tools\usbrcvoicelib\build\intermediates\classes\debug com.aispeech.usbrcvoicelib.nativeutils.UsbVoiceManager

第五步,创建JNI文件夹,位于java的同级目录

FfqAVbI.png!web

第六步,把第四步生成的.h文件copy到这个文件夹,同时创建my_jni_test.c文件和Android文件

内容如下:

Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := hello-jni   #指定了生成的动态链接库的名字
LOCAL_SRC_FILES := my_jni_test.c #指定了C的源文件叫什么名字

include $(BUILD_SHARED_LIBRARY)  # 制定要生成动态链接库

6

1

LOCAL_PATH := $(call my-dir)

2

include $(CLEAR_VARS)

3

LOCAL_MODULE    := hello-jni   #指定了生成的动态链接库的名字

4

LOCAL_SRC_FILES := my_jni_test.c #指定了C的源文件叫什么名字

5

6

include $(BUILD_SHARED_LIBRARY)  # 制定要生成动态链接库

my_jni_test.c

#include "com_aispeech_aistools_jni_MyJniTest.h"
JNIEXPORT jstring JNICALL Java_com_aispeech_aistools_jni_MyJniTest_getJniVersionName
  (JNIEnv * env, jobject obj) {
        return (*env)->NewStringUTF(env, "Hello , I'm from JNI");
  }

5

5

1

#include "com_aispeech_aistools_jni_MyJniTest.h"

2

JNIEXPORT jstring JNICALL Java_com_aispeech_aistools_jni_MyJniTest_getJniVersionName

3

  (JNIEnv * env, jobject obj) {

4

        return (*env)->NewStringUTF(env, "Hello , I'm from JNI");

5

  }

第七步,添加编译项目

在app下面的build.gradule添加

buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        ndkBuild {
            path 'src/main/jni/Android.mk'
        }
    }

11

11

1

    buildTypes {

2

        release {

3

            minifyEnabled false

4

            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

5

        }

6

    }

7

    externalNativeBuild {

8

        ndkBuild {

9

            path 'src/main/jni/Android.mk'

10

        }

11

    }

或者通过IDE添加

juYnQzZ.png!web

第八步,编译完成,将看到不同平台的so文件

miQZvyV.png!web

第九步,验证

在MainActivity.java里面调MyJniTest的方法,编译,安装验证

Log.e(TAG, "initDate: Jni version="+new MyJniTest().getJniVersionName());

1

1

Log.e(TAG, "initDate: Jni version="+new MyJniTest().getJniVersionName());

打印查看

nuENvyV.png!web

多平台支持

如果需要支持更多平台,比如Mips,需要在jni的目录添加Application.mk添加相差参数


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK