胖蔡说技术
随便扯扯

Makefile 实现一个Android JNI的开发

概述

使用Makefile构建工具完成jni的开发一般会比较繁琐,其实现的基本步骤如下:

  • 编写实现jni的java文件
  • 使用javac 命令编译java文件为class文件(javac Mp3Encoder.java)
  • 使用javah命令编译class文件生成一个jni的头文件(javah -jni cn.enjoytoday.mp3encoder.Mp3Encoder)
  • 将jni头文件复制到jni目录,并建立一个cpp的实现文件实现该JNI头文件的函数
  • 编写Android.mk文件,加入上步的本地代码,利用ndk-build生成动态链接库
  • java代码中加载生成好的动态链接库,并调用native方法

实施过程

本案例结合一个通过JNI来打印“Hello,Mp3 encoder!”的基础工程实现。

  1. 创建工程,编写实现jni的java文件Mp3Encoder,代码如下: public class Mp3Encoder {
    public native void encode();
    }
  2. 完成工程编译生成对应的class文件,或直接通过javac命令生成class文件,这里使用javac命令生成class文件,如下:
hfcai@hfcai-Lenovo-XiaoXin-V4000:~/Mp3Encoder/app/src/main/java$ javac cn/enjoytoday/mp3encoder/Mp3Encoder.java
hfcai@hfcai-Lenovo-XiaoXin-V4000:~/Mp3Encoder/app/src/main/java$ cd cn/enjoytoday/mp3encoder/
hfcai@hfcai-Lenovo-XiaoXin-V4000:~/Mp3Encoder/app/src/main/java/cn/enjoytoday/mp3encoder$ ll
总用量 20
drwxrwxr-x 2 hfcai hfcai 4096 8月 10 06:35 ./
drwxrwxr-x 3 hfcai hfcai 4096 8月 8 20:48 …/
-rw-rw-r-- 1 hfcai hfcai 880 8月 9 08:18 MainActivity.java
-rw-r–r-- 1 hfcai hfcai 236 8月 10 06:35 Mp3Encoder.class
-rw-rw-r-- 1 hfcai hfcai 98 8月 9 22:10 Mp3Encoder.java
hfcai@hfcai-Lenovo-XiaoXin-V4000:~/Mp3Encoder/app/src/main/java/cn/enjoytoday/mp3encoder$
  1. 使用javah命令编译class文件生成一个jni的头文件,Android Studio和Eclipse也可以通过编译的方式生成该头文件,但这里为了更加清楚的了解整个实现过程,采用命令的方式实现.如下:

如上,cn_enjoytoday_mp3encoder_Mp3Encoder.h为生成的jni头文件,文件名定义格式为包名+类名.h。如下为生成的内容:

    /* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cn_enjoytoday_mp3encoder_Mp3Encoder */

#ifndef _Included_cn_enjoytoday_mp3encoder_Mp3Encoder
#define _Included_cn_enjoytoday_mp3encoder_Mp3Encoder
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     cn_enjoytoday_mp3encoder_Mp3Encoder
* Method:    encode
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_cn_enjoytoday_mp3encoder_Mp3Encoder_encode
 (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

该文件不可修改,这里定义了一个方法Java_cn_enjoytoday_mp3encoder_Mp3Encoder_encode,需要在对应的c文件中实现它。

  1. 将jni头文件复制到jni目录,并建立一个cpp的实现文件实现该JNI头文件的函数,创建Mp3Encoder.cpp文件如下:
 #include <jni.h>
#include <android/log.h>
#include <string.h>
#include “cn_enjoytoday_mp3encoder_Mp3Encoder.h”
#define LOG_TAG “mp3encoder”
#define LOGI(…) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, VA_ARGS)
JNIEXPORT void JNICALL Java_cn_enjoytoday_mp3encoder_Mp3Encoder_encode
(JNIEnv *, jobject){
LOGI(“encoder encode!”);
}

在jni下添加Android.mk文件:

    LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS    := -lm -llog
LOCAL_MODULE := audioencoder
LOCAL_LDFLAGS := -Wl,--build-id
LOCAL_SRC_FILES := \
 /home/hfcai/Mp3Encoder/app/src/main/jni/Android.mk \
 /home/hfcai/Mp3Encoder/app/src/main/jni/Mp3encoder.cpp \
LOCAL_C_INCLUDES += /home/hfcai/Mp3Encoder/app/src/main/jni
LOCAL_C_INCLUDES += /home/hfcai/Mp3Encoder/app/src/debug/jni
include $(BUILD_SHARED_LIBRARY)

build.gradle设置ndk编译:

    android {
compileSdkVersion 28
defaultConfig {
    applicationId &quot;cn.enjoytoday.mp3encoder&quot;
    minSdkVersion 19
    targetSdkVersion 28
    versionCode 1
    versionName &quot;1.0&quot;
    testInstrumentationRunner &quot;android.support.test.runner.AndroidJUnitRunner&quot;

    //ndk-build
    ndk{
        moduleName &quot;audioencoder&quot;
    }

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

需要在项目的根目录gradle.properties中添加

    android.deprecatedNdkCompileLease=true

注意 :Android studio 从3.1.4之后将不再支持make方式使用ndk.

  1. 加载调用native方法 Mp3Encoder.java
    package cn.enjoytoday.mp3encoder;
public class Mp3Encoder {
static {
    System.loadLibrary(&quot;audioencoder&quot;);
}
public native void encode();
}
//调用

new Mp3Encoder().encode();

如上,实测可以实现log打印.

赞(0) 打赏
转载请附上原文出处链接:胖蔡说技术 » Makefile 实现一个Android JNI的开发
分享到: 更多 (0)

请小编喝杯咖啡~

支付宝扫一扫打赏

微信扫一扫打赏