博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Studio jni - 入门篇
阅读量:5876 次
发布时间:2019-06-19

本文共 4411 字,大约阅读时间需要 14 分钟。

闲来无事,在研究源码的时候看到一段内存占用的代码,感觉平时测试的时候可能会用到,所以想移植到测试app进行使用。于是开始了这篇jni之旅

一. 环境配置

主要需要配置的就是NDK(Native Development Kit),现在Android Studio很便利,可以一键下载:

Android Studio -> Preferences -> Android SDK -> SDK Tools -> 选择NDK -> 安装

如图:

  • 安装完成以后就可以开撸了

二. jni for memory malloc

  1. 新建一个jni android项目,或者打开一个已经有的android项目
  2. 设置jni支持

  • 打开gradle.properties,添加

           android.useDeprecatedNdk=true

  • 打开local.properties,添加:
ndk.dir=NDK的路径复制代码
  • 最后打开app内build.gradle,在android/defaultConfig下面添加ndk配置
defaultConfig {    applicationId "com.youku.playerproxy"    minSdkVersion 16    targetSdkVersion 19    versionCode getSelfDefinedVersion("code")    versionName getSelfDefinedVersion("name")    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"    multiDexEnabled = true    multiDexKeepFile file('multiDexKeep.txt')    ndk {        moduleName "mem_fill_tool"        abiFilters "armeabi-v7a"    }}复制代码
  • moduleName 表示编译出的so文件的名字

  3. 新建java访问层的C接口类

package com.xxx.utils;public class MemFillTool {    private MemFillTool() {    }    private static MemFillTool instance = null;    public static MemFillTool getInstance() {        if (instance == null) {            System.loadLibrary("mem_fill_tool");            instance = new MemFillTool();        }        return instance;    }    // 填充xxxMB内存    public native int fillMem(int blockNum);    // 释放刚才填充的内存    public native int freeMem();}复制代码

fillMem和freeMem就是与C层交互的jni方法

  4. 生成头文件

  • 先点击make project图标,编译项目,看是否有报错
  • 然后打开终端,运行
cd app/build/intermediates/classes/debug/javah com.xxx.utils.MemFillTool复制代码
运行成功之后打开app/build/intermediates/classes/debug/ 即可找到编译出的头文件"com_lilei_testjni_JniUtils.h",不难发现头文件名是有原报名+类名组成

5.创建jni开发的文件夹

  • 点击app文件夹,New → Folder → JNI Folder, 选择在main文件夹下即可,生成成功后main目录下会出现一个jni的文件夹
  • 找到刚才生成到头文件,复制到jni文件夹下(记得关闭刚才使用的终端,否则无法复制)
  • 头文件有了,现在在jni目录下创建一个C++文件用于开发使用,命名与头文件相同
  • 编写C++文件中定义函数的代码
/* DO NOT EDIT THIS FILE - it is machine generated */#include 
/* Header for class com_xxx_utils_MemFillTool */#ifndef _Included_com_xxx_utils_MemFillTool#define _Included_com_xxx_utils_MemFillTool#ifdef __cplusplusextern "C" {#endif/* * Class: com_xxx_utils_MemFillTool * Method: fillMem * Signature: (I)I */JNIEXPORT jint JNICALL Java_com_xxx_utils_MemFillTool_fillMem (JNIEnv *, jobject, jint);/* * Class: com_xxx_utils_MemFillTool * Method: freeMem * Signature: ()I */JNIEXPORT jint JNICALL Java_com_xxx_utils_MemFillTool_freeMem (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif复制代码

生成的头文件

#include 
#include
#include
#include "com_xxx_utils_MemFillTool.h"int fill(int blockNum);int freeMem();JNIEXPORT jint JNICALL Java_com_xxx_utils_MemFillTool_fillMem(JNIEnv * env, jobject obj, jint blockNum) { return fill((int)blockNum);}JNIEXPORT jint JNICALL Java_com_xxx_utils_MemFillTool_freeMem(JNIEnv * env, jobject obj) { return freeMem();}char *p;const int BASE_SIZE = 1024*1024; // 1Mint fill(int blockNum){ int memSize = blockNum * BASE_SIZE; p = (char *)malloc(memSize); if (!p) { return -1; } int i; for (i = 0; i < memSize; i++) { p[i] = 0; } return 0;}int freeMem(){ if (p) { free(p); } return 0;}复制代码

实现

6.java层加载so

  • 回到JniUtils,加上
public static MemFillTool getInstance() {    if (instance == null) {        System.loadLibrary("mem_fill_tool");   =====> 加载so        instance = new MemFillTool();    }    return instance;}复制代码

至此运行就完全可以了

三、生成so文件

前文介绍如何运行C++程序,但是实际开发中大多是封装编译出so文件后进行开发,就类似java里面的jar包

1.配置NDK环境变量

  • 找到Android Studio安装的NDK包的文件目录(/Users/xxx/Library/Android/sdk/ndk-bundle),添加到系统的环境变量中

2.新建mk文件

  • 在jni目录下新建Android.mk
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := mem_fill_toolLOCAL_SRC_FILES := com_xxx_utils_MemFillToolinclude $(BUILD_SHARED_LIBRARY)复制代码
  • 在jni目录下新建Application.mk文件
APP_STL := gnustl_staticAPP_CPPFLAGS := -frtti -fexceptions -std=c++0xAPP_ABI := armeabi-v7aAPP_PLATFORM := android-18复制代码

3.编译生成so

  • 打开终端cd到jni目录下
  • 调用ndk-build开始编译so
ndk-build复制代码
  • 运行无误的话会如图所示

  • 运行成功之后即会看到main文件夹下多了libs和obj的文件夹,里面就是生成的各种CPU的so文件

libs和obj里面都有so文件,两者的区别google给出的解释是:

As part of the build process, the files in the libs folder have been stripped of symbols and debugging information. So you'll want to keep two copies of each of your .so files: One from the libs folder to install on the Android device, and one from the obj folder to install for GDB to get symbols from.
也就是说,libs目录下生成的库是剥离了符号表与调试信息的,而obj下的库是带有调试信息的。

至此jni的开发入门已完成

转载地址:http://rckix.baihongyu.com/

你可能感兴趣的文章
C#------连接SQLServer和MySQL字符串
查看>>
Arcgis Licensemanager 不能启动的原因之一(转载)
查看>>
(原)Android在子线程用handler发送的消息,主线程是怎么loop到的?
查看>>
$digest already in progress 解决办法——续
查看>>
虚拟机 centos设置代理上网
查看>>
Struts2中Date日期转换的问题
查看>>
mysql 数据类型
查看>>
Ubuntu 设置当前用户sudo免密码
查看>>
设置tomcat远程debug
查看>>
android 电池(一):锂电池基本原理篇【转】
查看>>
Total Command 常用快捷键
查看>>
ionic 调用手机的打电话功能
查看>>
怎么使用阿里云直播服务应用到现在主流直播平台中
查看>>
Xcode全局替换内容,一键Replace
查看>>
1000 加密算法
查看>>
exif_imagetype() 函数在linux下的php中不存在
查看>>
Ruby的case语句
查看>>
Linux的链接文件-ln命令
查看>>
maven的tomcat插件如何进行debug调试
查看>>
table表头固定
查看>>