Android Studio编译并集成SO文件

0x00 本文目标

让Java层代码与Native层代码交互

编译Native代码为SO文件

将SO文件集成到最终的APK文件中

为此你需要Android Studio和NDK套装,百度搜索后直接到官网下载。

0x01 Java层

为了让Java层与JNI层交互,来个简单的测试代码。hello方法用于获取从native返回的字符串,并显示到TextView中,没有TextView的同学自己在布局文件中新建一个就行了。

package com.example.androidtest;

import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.TextView;

public class MainActivity extends AppCompatActivity {    private TextView txt_jni;

    static {        System.loadLibrary("test");    }

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);

        txt_jni = findViewById(R.id.txt_jni);        txt_jni.setText(hello(1, "2"));    }

    private native String hello(int a, String b);}

接下来实现JNI层代码,在Android Studio中新建一个空白工程,File->New->Folder->JNI Folder创建一个JNI源码文件夹,默认路径在/src/main/jni。

博主另一篇文章演示了纯Java生成SO文件:https://www.cnblogs.com/DXCyber409/p/10854415.html

在安卓中同样有这两种方式:Java_固定路径方式,和JNI_OnLoad动态注册方式。

0x02 JNI固定前缀写法

本质就是生成一个固定前缀的函数名称和相关参数,最后在c/cpp文件中实现它。

可以手动生成.h文件,不再演示。本文使用Android Studio提供的External Tools来实现一键生成.h头文件,这将大大提高开发效率。

File->Settings->Tools->Extenal Tools,点个加号创建一个新的项。该命令实际上会执行命令行指令传递相关参数,结合手写的写法:

D:\RTEws\Java\jdk1.8.0_121\bin>javah -d "E:\Workspace\NetBeans\DXCyber409\src\main\java\dxcyber409\jni" -classpath "E:\Workspace\NetBeans\DXCyber409\target\classes" -jni dxcyber409.Test$Cls

Insert Marcros是内置环境变量参考窗口,不要错过:

最终路径参数方案调整如下:

Name:javah
Program:$JDKPath$\bin\javah.exe
Arguments:-d "$ModuleFileDir$\src\main\jni" -classpath "$OutputPath$;$ModuleSdkPath$\platforms\android-28\android.jar;$ModuleSdkPath$\extras\android\android-support-v4.jar;$ModuleSdkPath$\extras\android\android-support-v7.jar" -jni $FileClass$
Working directory:

在Arguments中-classpath选项除了自己代码中已编译的classes目录外,还加入android.jar,android-support-v4.jar,android-support-v7.jar等依赖包,不加会缺少实现类而报错。

写法不止一种,博主在Arguments中已经把所有相关路径都拼接完成了,因此Working directory没啥用留空就行。

Ps.博主的Android SDK貌似不完整的样子,在Android SDK中找不到appcompat相关依赖包。如果你也不想重新安装Android SDK的话这里有个小技巧,到Maven Repository上缺啥下啥,自己动手丰衣足食。下载了丢到目录中引用路径就行,位置没有强硬要求。

随后在/src/main/jni目录中就得到了.h头文件,按惯例新建一个cpp文件包含此文件照着写就行,完整代码如下:

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

#ifndef _Included_com_example_androidtest_MainActivity
#define _Included_com_example_androidtest_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
#undef com_example_androidtest_MainActivity_BIND_ABOVE_CLIENT
#define com_example_androidtest_MainActivity_BIND_ABOVE_CLIENT 8L
#undef com_example_androidtest_MainActivity_BIND_ADJUST_WITH_ACTIVITY
#define com_example_androidtest_MainActivity_BIND_ADJUST_WITH_ACTIVITY 128L
#undef com_example_androidtest_MainActivity_BIND_ALLOW_OOM_MANAGEMENT
#define com_example_androidtest_MainActivity_BIND_ALLOW_OOM_MANAGEMENT 16L
#undef com_example_androidtest_MainActivity_BIND_AUTO_CREATE
#define com_example_androidtest_MainActivity_BIND_AUTO_CREATE 1L
#undef com_example_androidtest_MainActivity_BIND_DEBUG_UNBIND
#define com_example_androidtest_MainActivity_BIND_DEBUG_UNBIND 2L
#undef com_example_androidtest_MainActivity_BIND_EXTERNAL_SERVICE
#define com_example_androidtest_MainActivity_BIND_EXTERNAL_SERVICE -2147483648L
#undef com_example_androidtest_MainActivity_BIND_IMPORTANT
#define com_example_androidtest_MainActivity_BIND_IMPORTANT 64L
#undef com_example_androidtest_MainActivity_BIND_NOT_FOREGROUND
#define com_example_androidtest_MainActivity_BIND_NOT_FOREGROUND 4L
#undef com_example_androidtest_MainActivity_BIND_WAIVE_PRIORITY
#define com_example_androidtest_MainActivity_BIND_WAIVE_PRIORITY 32L
#undef com_example_androidtest_MainActivity_CONTEXT_IGNORE_SECURITY
#define com_example_androidtest_MainActivity_CONTEXT_IGNORE_SECURITY 2L
#undef com_example_androidtest_MainActivity_CONTEXT_INCLUDE_CODE
#define com_example_androidtest_MainActivity_CONTEXT_INCLUDE_CODE 1L
#undef com_example_androidtest_MainActivity_CONTEXT_RESTRICTED
#define com_example_androidtest_MainActivity_CONTEXT_RESTRICTED 4L
#undef com_example_androidtest_MainActivity_MODE_APPEND
#define com_example_androidtest_MainActivity_MODE_APPEND 32768L
#undef com_example_androidtest_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING
#define com_example_androidtest_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L
#undef com_example_androidtest_MainActivity_MODE_MULTI_PROCESS
#define com_example_androidtest_MainActivity_MODE_MULTI_PROCESS 4L
#undef com_example_androidtest_MainActivity_MODE_NO_LOCALIZED_COLLATORS
#define com_example_androidtest_MainActivity_MODE_NO_LOCALIZED_COLLATORS 16L
#undef com_example_androidtest_MainActivity_MODE_PRIVATE
#define com_example_androidtest_MainActivity_MODE_PRIVATE 0L
#undef com_example_androidtest_MainActivity_MODE_WORLD_READABLE
#define com_example_androidtest_MainActivity_MODE_WORLD_READABLE 1L
#undef com_example_androidtest_MainActivity_MODE_WORLD_WRITEABLE
#define com_example_androidtest_MainActivity_MODE_WORLD_WRITEABLE 2L
#undef com_example_androidtest_MainActivity_RECEIVER_VISIBLE_TO_INSTANT_APPS
#define com_example_androidtest_MainActivity_RECEIVER_VISIBLE_TO_INSTANT_APPS 1L
#undef com_example_androidtest_MainActivity_DEFAULT_KEYS_DIALER
#define com_example_androidtest_MainActivity_DEFAULT_KEYS_DIALER 1L
#undef com_example_androidtest_MainActivity_DEFAULT_KEYS_DISABLE
#define com_example_androidtest_MainActivity_DEFAULT_KEYS_DISABLE 0L
#undef com_example_androidtest_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL
#define com_example_androidtest_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L
#undef com_example_androidtest_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL
#define com_example_androidtest_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L
#undef com_example_androidtest_MainActivity_DEFAULT_KEYS_SHORTCUT
#define com_example_androidtest_MainActivity_DEFAULT_KEYS_SHORTCUT 2L
#undef com_example_androidtest_MainActivity_RESULT_CANCELED
#define com_example_androidtest_MainActivity_RESULT_CANCELED 0L
#undef com_example_androidtest_MainActivity_RESULT_FIRST_USER
#define com_example_androidtest_MainActivity_RESULT_FIRST_USER 1L
#undef com_example_androidtest_MainActivity_RESULT_OK
#define com_example_androidtest_MainActivity_RESULT_OK -1L
#undef com_example_androidtest_MainActivity_HONEYCOMB
#define com_example_androidtest_MainActivity_HONEYCOMB 11L
#undef com_example_androidtest_MainActivity_MSG_REALLY_STOPPED
#define com_example_androidtest_MainActivity_MSG_REALLY_STOPPED 1L
#undef com_example_androidtest_MainActivity_MSG_RESUME_PENDING
#define com_example_androidtest_MainActivity_MSG_RESUME_PENDING 2L
/*
 * Class:     com_example_androidtest_MainActivity
 * Method:    hello
 * Signature: (ILjava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_androidtest_MainActivity_hello
  (JNIEnv *, jobject, jint, jstring);

#ifdef __cplusplus
}
#endif
#endif

0x03 JNI动态注册写法

本质是向RegisterNatives

0x04 编译SO文件

0x05 集成SO文件

0x06 测试结果

NDK官方指定使用Makefile来进行SO文件编译,那么新建一个文件重命名Android.mk。

目前最重要的是编译出一个SO成品来,一切配置最简单化。后续有详细需要各个编译选项的可以参考官方文档:https://developer.android.com/ndk/guides/android_mk.html?hl=zh-cn

参考源

https://www.jianshu.com/p/faa3eebbd401

原文地址:https://www.cnblogs.com/DXCyber409/p/10992309.html

时间: 2024-11-06 10:43:44

Android Studio编译并集成SO文件的相关文章

android studio 编译C生成.so文件

一.前言 前段时间有个同事离职了,用C编译的.SO文件需要更改,结果C文件是他写的,无赖啊,自己又是一个小白,不会啊,所以自己又好好钻研了一天,不会,看什么都难啊,痛苦啊,网上找了好多,才找到的,而且感觉都不怎么详细,步骤说的不是很清楚,所以自己整理了一下,谁便记录一下,好了,废话不多说,开始正题. 二.编译过程 1.编译环境的搭建 正所谓:"工欲善其事必先利其器"嘛,所以先把改准备工具准备一下,因为是在studio下编译的,所以啊,什么studio.什么sdk.什么jdk,这些都自己

我的Android进阶之旅------&gt;解决Android Studio编译后安装apk报错:The APK file does not exist on disk

1.错误描述 今天用Android Studio编译应用后安装APK的时候,报错了,错误如下所示: The APK file build\outputs\apk\OYP_2.3.4_I2Base_6476_official_debug.apk does not exist on disk. Error while Installing APK 如下图所示 2.解决方法 1.尝试了Build -> Clean Project再编译,还是无效 2.尝试重启Android Studio无效 然后我去打

Android Studio编译好的apk放在哪里?

Eclipse中编译好的apk文件时在bin文件里面的,但是在Android Studio有一个比较大的改动了,编译好的apk在android studio里面是直接看不到了,而且apk文件所在目录也变了,那apk文件放在哪呢,你要在硬盘中找到对应的工程目录: E:\StudioDemo\MyApplication\app\build\outputs\apk 其中app是你的module,记得一定要在对应的module下找对应的编译好的apk文件. Android Studio编译好的apk放在

Android Studio 项目中集成百度地图SDK报Native method not found: com.baidu.platform.comjni.map.commonmemcache.JNICommonMemCache.Create:()I错误

Android Studio 项目中集成百度地图SDK报以下错误: 1 java.lang.UnsatisfiedLinkError: Native method not found: com.baidu.platform.comjni.map.commonmemcache.JNICommonMemCache.Create)I 2 at com.baidu.platform.comjni.map.commonmemcache.JNICommonMemCache.Create(Native Met

Android studio 编译失败Error:Could not read entry &amp;#39;:app:processDebugManifest&amp;#39; from cache taskArtifacts.b

Android studio 编译失败 Error:Could not read entry ':app:processDebugManifest' from cache taskArtifacts.bin 升级了Android studio 2.0 版本号后 编译之前的项目失败 出现了以下提示: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/

Error:Execution failed for task &#39;:app:compileDebugAidl&#39;. &gt; aidl is missing(Android Studio编译错误)

今天下载了一个1.2.1.1版本的Android Studio,使用VPN更新好SDK之后就新建了一个hello world工程测试一下环境,然后就出现以下错误: Error:Execution failed for task ':app:compileDebugAidl'. > aidl is missing 什么情况?全新安装的环境也有错误?Google发布这个工具时没有测试好吗? 没搞过这个工具,一阵搜索得到以下方案: 1.右键工程->Open Module Settings 2.将Bu

Cocos2d-x移植到Android平台编译的两个文件Android.mk和Application.mk

背景 首先,说说文章的背景.最近手中的一个项目,由于需求中要求提供Web界面的打印功能,当然如果没有打印机,还可以提供保存到本地.项目组长把这个"小任务"分给了我.本着努力为组长分忧解难的思想,领了任务之后,就马上开始了工作. 问题 刚开始的时候,组长给了一个工具(jatoolsprinter)让我研究,我用了一个多小时的时间,做出了一个简单的Demo,然后就是各种的测试,由于 web 打印需要浏览器安装 ActiveX 组件,在随后的测试中,我用了几款浏览器,甚至把安全级别都调到了最

Ubuntu下android studio 编译报错A problem occurred starting process &#39;command &#39;/Android/Sdk/build-tools/21.1.2/aapt&#39;&#39;

此问题在stack  over flow 上找到答案. 原链接地址:http://stackoverflow.com/questions/27589844/android-studio-1-0-2-not-building-appmergedebugresources-error 解决方法: //在终端分别运行下面两条指令,安装lib32stdc++6 和lib32z1 sudo apt-get install lib32stdc++6 sudo apt-get install lib32z1

Android Studio编译运行Fresco Sample。Android缓存新境界。 (a problem occurred start process &#39;command &#39;ndk-build&#39;&#39;)

今天闲逛知乎,偶遇一篇“Android应用开发难点”,作为安卓程序猿,本能点进去,想看看究竟能有什么难点自己不知道的(夜郎自大..面壁中). 插件化,H5容器优化,网络.图片缓存..感觉都还好.直到看到“Fresco出来之前,你是不是觉得图片缓存已经到头了?” Fresco究竟是何方神圣!! 询问度娘得知,2015.3.27日之前就已经发布了(度娘的结果最早是3.27).通过查看GitHub: Version 0.1.0  tyronen released this 16 days ago ·