Android JNI模板与读取系统属性笔记
2018-01-02 16:17
399 查看
一、编写目的
本文主要提供一个简单可用的 jni 模板,便于在APK中编写native代码。通过记录,希望能对jni学习有一个更深的认识。
二、APP中的jni模板
1、jni文件在项目中的截图
2、详细步骤
1)、在src/main/ 层,创建jni目录用于存放,native代码2)、增加Android.mk
# Android.mk for check is rightful board LOCAL_PATH := $(call my-dir) # Program include $(CLEAR_VARS) LOCAL_MODULE := nativeXXXX LOCAL_SRC_FILES := nativeXXXX.c LOCAL_C_INCLUDES += $(LOCAL_PATH) // 配置头文件目录,根据实际修改 LOCAL_LDLIBS := -llog -lz // 添加静态依赖库,编译需要 LOCAL_SHARED_LIBRARIES := libcutils // 添加动态依赖库,读取系统属性需要 include $(BUILD_SHARED_LIBRARY)
3)、增加Application.mk
APP_ABI :=armeabi-v7a // 指定编译哪些CPU架构
4)、增加nativeXXXX.c
// // Created by LinChengChun on 2018/1/2. // #include "nativeXXXX.h" static const char *ClassName = "com/example/XXXX"; // 包名 jint test(JNIEnv *env, jobject jobj){ char *key = "ro.build.id"; char value[PROP_VALUE_MAX] = {0}; int ret = __system_property_get(key, value); if(ret <= 0 ){ return -1; } ret = strcmp(value, "XXXX"); if(ret != 0){ return -1; } return 0; } static JNINativeMethod METHODS[]={ {"test","()I",(void *)test} }; JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { int retVal = -1; JNIEnv *env; if ( (*vm)->GetEnv(vm,(void **) &env, JNI_VERSION_1_4) == JNI_OK ) { jclass clazz = (*env)->FindClass(env,ClassName); if (clazz != NULL) { if ((*env)->RegisterNatives(env,clazz, METHODS,sizeof(METHODS) / sizeof(METHODS[0])) >= 0) { retVal = JNI_VERSION_1_4; }else{ LOGI("RegisterNatives Subprocess.create method failed!"); } (*env)->DeleteLocalRef(env,clazz); }else{ LOGI("className not found!"); } } return retVal; } JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) { }
5)、增加nativeXXXX.h
// // Created by LinChengChun on 2018/1/2. // #ifndef XXXX_ANDROID_NATIVEXXXX_H #define XXXX_ANDROID_NATIVEXXXX_H #include <jni.h> #include <assert.h> #include <string.h> #include <sys/types.h> #include <android/log.h> #include <sys/system_properties.h> #define LOG_TAG "NativeXXXX" #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) #endif //XXXX_ANDROID_NATIVEXXXX_H
6)、在JAVA层增加native接口类
package com.example; /** * Created by LinChengChun on 2018/1/2. */ public class XXXX{ public native static int test(); // 在外部可以通过 XXXX.test() 方法调用 static { System.loadLibrary("nativeXXXX"); // 优先加载动态库 } }
3、添加NDK编译工具,AndroidStudio中添加 外部编译命令 的方法
在Settings > Tools > External Tools中添加命令行工具(NDK)如下: ndk-build、ndk build clean、javah如果顺利完成以上步骤,就可以在工程任意位置 右键->NDK->ndk-build 编译生成 so库了
三、在JNI读取系统属性方法
用 objdump 看了一下 libc.so ,找到了其中的函数。如下:000095f0 g F .text 00000014 __system_properties_init 00009604 g F .text 00000014 __system_property_find 00009618 g F .text 00000014 __system_property_find_nth 0000962c g F .text 00000014 __system_property_get 00009640 g F .text 00000014 __system_property_read 00009654 g F .text 00000014 __system_property_wait
头文件是 system_properties.h ,在 usr/include/sys目录下面。
__system_property_get 可以用来获取一个属性值,函数原型如下:
/* Look up a system property by name, copying its value and a ** \0 terminator to the provided pointer. The total bytes ** copied will be no greater than PROP_VALUE_MAX. Returns ** the string length of the value. A property that is not ** defined is identical to a property with a length 0 value. */ int __system_property_get(const char *name, char *value);
读写ro.build.id的方法
char *key = "ro.build.id"; char value[PROP_VALUE_MAX] = {0}; int ret = __system_property_get(key, value); if(ret <= 0 ){ return -1; }
四、在JAVA中读取系统属性方法
private static String getSystemProperty(String key, String defaultValue) { try { Class<?> clz = Class.forName("android.os.SystemProperties"); // 通过反射实现 Method get = clz.getMethod("get", String.class, String.class); return (String)get.invoke(clz, key, defaultValue); } catch (Exception e) { } return defaultValue; } public static boolean test(){ String value =CurrentClass.getSystemProperty("ro.build.id", null); if (TextUtils.isEmpty(value)){ return false; } if(!"XXXX".equals(value)){ return false; } return true; }
五、把编译生成的so库打包到apk里面去
android { compileSdkVersion 23 buildToolsVersion '25.0.0' defaultConfig { 。。。。。。 ndk { abiFilters 'armeabi-v7a', 'x86' } //加载so库目录 sourceSets { main { // Tell Android Gradle that no jni code need to compile, so we can avoid Ndk compile task, // then we will to compile use ndk-build in command-line. jni.srcDirs = [] // 不依赖 gradle来编译 jni,根据我们的ndk-build来编译 jniLibs.srcDir "src/main/libs" } } } 。。。。。。
六、以上是APP 添加 jni 代码的全部记录,注意下包名,一般可以启动运行正常,jni基础知识会在另外文章介绍。^-^
相关文章推荐
- 读取android系统属性,比如驱动写些驱动设备型号等到手机prop,上层用APK读出来,省去用JNI读取
- Android 中系统组件GridView属性笔记
- jni 获得 android 系统属性
- Android C 语言读取系统属性
- android基础笔记——模板代码:SharedPreferences保存、读取数据
- android开发笔记之系统属性(ro.com.google.clientidbase.ms)随卡适配
- Android 笔记 读取style文件的属性
- jni 获得 android 系统属性
- Android C 语言读取系统属性
- Android读取系统控件的自定义属性
- android 学习笔记 读取系统联系人
- Android系统setting中读取apk的属性
- android通过读取系统属性设置字体缩放的默认值
- android JNI 学习笔记
- JNI学习笔记3——本地方法取得Java属性/调用java方法
- Android 的系统属性(SystemProperties)设置分析
- Android 属性系统
- Android 的系统属性(SystemProperties)设置分析
- 识别你的手机 Android的属性系统
- android JNI 学习笔记