吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3156|回复: 9
收起左侧

[其他转载] Android Studio 3.6 SO文件生成(CMake)

[复制链接]
西班牙三棵树 发表于 2021-5-27 09:58

希望记录一下在学习过程中遇到的最新的问题,过于浅薄,希望各位大佬尽量多的提出问题熬。

  • 安装NDK:

    现有的NDK最新的版本是NDK22.1,但是NDK22.1并不能成功地兼容。(具体原因我忘了,大概一个月前的时候,有大佬知道可以提点我一下)于是安装的是NDK21,但是下面创建项目时,会提示最优的版本是NDK20,但是好在NDK21没有出现大的兼容问题,没有安装的伙伴可以在创建项目后首次进行Sync(小象图标)根据那个NDK缺失情况进行安装。

image-20210505151510910.png

在Android Studio 2.2 之后,工具中增加了 CMake 的支持,所以在 Android Studio 2.2 之后有2种选择来编译 c/c++ 代码。

  • 一种是 ndk-build + Android.mk + Application.mk 的方式

  • 另一种是 CMake + CMakeLists.txt 的方式

    实现NDK的完整步骤如下:

    1. 创建Android ndk project,使用Native关键字定义Java方法(即需要调用的native方法)
    2. 使用javac编译上述 Java源文件 (即 .java文件)最终得到 .class文件
    3. 通过 javah 命令编译.class文件,最终导出JNI的头文件(.h文件)
    4. C++实现在 Java中声明的Native方法
    5. Activity加载so库,使用native方法
    6. 生成.so库文件
    7. 执行代码

    我初步是跟随大佬帖子里,使用ndk-build进行so库生成,主要有几个问题:

  • javah的指令已经过期,已经嵌入到了javac -h里面

  • 在全部配置完后,rebuild Project并不能生成对应so库

  • 在搜寻过一堆ndk-build的so库解决方案并且对应改完之后,我生成了so库。但是对应的apk会闪退。。。

接下来我会继续研究关于ndk-build生成so文件的方案,以及问题的解决方案

今天要介绍的是通过Cmake方式进行So文件生成。

如果是新的工程,可以在新建工程时选择,进去直接就能找到对应的jni库和c++写好的helloworld函数,进行修改,或者再加入新的代码就可以。

image-20210526172307642.png

如果是在原有工程下进行so库的添加操作,可以按照以下的方式进行:

(其实这种方式可以先生成一个空的Native C++项目看一下文件夹结构和内容,新添加多数情况下可以直接拷贝模板过来,但是用C++和C写的so文件的语法和格式也是有一些出入的)

  • 先在src->main下构建cpp文件夹,以及文件夹下的main.c, CmakeLists.txt,空置

  • apk文件夹右键:link c++ project with gradle,路径选择刚刚新建的那个CmakeList.txt。
  • image-20210526173536775.png

image-20210526173345772.png

  • 添加如下代码至Cmake文件
cmake_minimum_required(VERSION 3.4.1)

add_library( 
        # Specifies the name of the library.
        native-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        main.c)
  • 点击右上角小象:
    image-20210526174015766.png

  • 然后就可以书写main.c的代码了

#include <jni.h>

JNIEXPORT jstring JNICALL Java_com_example_myapplication_MainActivity_stringFromJNI(JNIEnv *env, jobject thiz) {
    return (*env)->NewStringUTF(env, "hello from c++ language");
}

JNIEXPORT jint JNICALL Java_com_example_myapplication_MainActivity_sum(JNIEnv *env, jobject thiz, jint num1, jint num2){
    return num1+num2;
}

在MainActivity中进行native-lib的调用就可以完成了

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("native-lib");
    }

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

        Log.i("from native-lib", stringFromJNI());
        Log.i("from native-lib", "sum result: " + sum(10, 15));

    }
    public native String stringFromJNI();
    public native int sum(int num1, int num2);

}

本文的主要来源:

https://www.52pojie.cn/thread-706568-1-1.html

https://blog.csdn.net/qycc3391/article/details/114241225

下面是我在研究ndk-build的时候成功生成so文件但是闪退的过程,希望有大佬帮我看看哪里出了什么问题:

  • 配置NDK:

File->Project Structure

image-20210505152225469.png

  • 加环境变量,确保ndk-build可以运行

image-20210505153018258.png

  • 在对应的要编译为so文件的java文件夹下使用javah,将java文件生成为.h,即c语言头文件

    注意新版本的指令,不能用javah了:

image-20210429155435928.png

  • 按照生成的.h文件书写自己的c语言文件,命名为java调用的library的名字。然后在java同级目录下创建一个jni文件夹。将c和h文件放进去

    image-20210505155345694.png
    image-20210505155358121.png

  • Android.mk文件书写:

    大家都知道在Linux下编辑经常要写一个Makefile文件, 可以把这个Makefile文件理解成一个编译配置文件,它保存着如何编译的配置信息,即指导编译器如何来编译程序,并决定编译的结果是什么。而在Android下的Android.mk文件也是类型的功能,顾名思义,从名字上就可以猜测得到,Android.mk文件是针对Android的Makefile文件.具体来说:该文件是GNU Makefile的一小部分,会被编译系统解析一次或多次。你可以在每一个Android.mk file中定义一个或多个模块,你也可以在几个模块中使用同一个源代码文件。编译系统为你处理许多细节问题。

image-20210505160614781.png

  • 在在控制台中,进入到工程的jni目录下,然后输入ndk-build(如下所示),不出问题即可编译成功(但是在在入口调用会闪退,问题来源暂不明朗)。
    image-20210505162256124.png
image-20210526173721632.png

免费评分

参与人数 3吾爱币 +2 热心值 +3 收起 理由
lgc81034 + 1 谢谢@Thanks!
抱薪风雪雾 + 1 + 1 谢谢@Thanks!
笙若 + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

余生余你余于余 发表于 2021-5-27 13:28
学习了,以后可能也会用到
ZLJ13697750126 发表于 2021-5-27 15:21
8204118 发表于 2021-5-28 11:27
debug_cat 发表于 2021-5-28 13:43
cmake简单一点吧,至于闪退问题,要有奔溃的时候的log才能定位。
feihu72 发表于 2021-5-28 15:38
感谢楼主分享~
烟花非易冷 发表于 2021-5-28 22:52
就这些图文来说,楼主辛苦了
goda 发表于 2021-5-28 23:08
崩溃直接看日志啊
sornian 发表于 2021-5-29 01:36
想的很详细
ZLJ13697750126 发表于 2021-5-29 15:21
赞一个,感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 15:27

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表