AndroidStudio编译.SO库文件心得一

文本心得通过以下三篇文章习来:
Android Studio开发JNI工程
Android Sutdio开发NDK工程
在Android Studio中直接编译C/C++文件
谢谢三位作者的分享,才能学到这么宝贵的知识。
一直以来都是用的别的SDK提供的so库,编译so库文件跟调用so库的方法都是未曾尝试过。以前看博客了解的是使用Cygwin进行编译so. 现在有了AndroidStudio这个IDE,我们就可以直接使用这个工具就行编译了。
我们先准备好工具,先安装好NDK。然后开始本文的第一步:

编译.so文件

1.在这里我们先简单写一个方法,返回一个字符串(在项目中我们可以将关键的信息,如秘钥打在so库中,虽然也有被反编译的风险,但是还是相比定义在Java层,或者文件中会安全一点),那这里我们就先在Java层中定义一个要调用的本地方法。

public class Math {
    public native static String getStringFromNative();
}

然后我们在点击Build -Make Project进行编译
这里写图片描述
编译完之后,就会在
这里写图片描述
生成Math.class文件

2.我们点击Terminal将路径跳转
进入app_path/app/build/intermediates/classes/debug下,或
app_path/app/src/main/java
在我这里app_path就是F:\demo\JniDemo>
然后输入javah -classpath . com.csf.jnidemo.Math生成对应的.h文件
这个是c或者c++ 的头文件。
这里写图片描述
执行完毕之后就会在对应的路径下生成
com_csf_jnidemo_Math.h。

  1. 编写本地方法。
    我们在main下建立一个jni的文件夹,将上面的.h文件拷贝过来,拷不拷贝都无所谓,我这里就是看着顺眼而已,我们要用到的主要是.h中声明的方法。它生命的方法具有一定的格式,我们接下来需要编写.c或者.cpp文件,函数名就是这个.h中定义的。
    我们在jni下建立Math.c文件
    代码如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <android/log.h>

#ifndef LOG_TAG
#define LOG_TAG "ANDROID_LAB"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#endif

/* Header for class com_csf_jnidemo_Math */

#ifndef _Included_com_csf_jnidemo_Math
#define _Included_com_csf_jnidemo_Math
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class: com_csf_jnidemo_Math
 * Method: getStringFromNative
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_csf_jnidemo_Math_getStringFromNative
  (JNIEnv * env, jobject jObj){
      LOGE("log string from ndk.");
      return (*env)->NewStringUTF(env,"Hello From JNI!");
  }

#ifdef __cplusplus
}
#endif
#endif

其中一些语句我还不太理解,主要是从上面三篇文章拷贝过来的,但是具体内容看懂就OK了,
Java_com_csf_jnidemo_Math_getStringFromNative
在这个方法中我们使用JNI的NewStringUTF生成一个UTF的jstring ,值为”Hello From JNI!”,返回到Java层,同时打下一句Log。

注:
上面的生成.h跟.c方法我们可以使用AndroidStudio来直接生成.c文件,方法如下,直接在native方法上按alt+enter生成c层的方法
这里写图片描述

4.编译.so文件
我们先配置工程的ndk路径,不然就会出现以下错误

Error:Execution failed for task ':app:compileDebugNdk'. 
> NDK not configured. 
Download the NDK from http://developer.android.com/tools/sdk/ndk/.Then add ndk.dir=path/to/ndk in local.properties. 
(On Windows, make sure you escape backslashes, e.g. C:\\ndk rather than C:\ndk)

我们在local.properties文件中配置如下信息指定ndk路径
这里写图片描述

在gradle.properties中加入如下语句

android.useDeprecatedNdk = true

接着修改我们app的gradle文件,在android下增加如下信息
这里写图片描述

ndk{
            moduleName "JniTest"    //lib的名称,对应LOCAL_MODULE
            //stl "stlport_shared"    //对应APP_STL
            ldLibs "log", "z", "m"  //链接时使用到的库,对应LOCAL_LDLIBS
            //cFlags 编译gcc的flag,对应LOCAL_CFLAGS
        }

这样就能编译出各种ABI的so库,如果要指定编译某种CPU架构的so文件,在ndk标签下增加如下语句

abiFilters "armeabi", "armeabi-v7a", "x86"  

下面前期准备工作就做的差不错了,不过还有一个问题,我没有去验证,
上面几篇博客都有提到的在执行”Build->Rebuild Project”,编译so文件
的时候,在Windows平台下会出现下面这个问题

Error:Execution failed for task ':app:compileDebugNdk'.
> com.android.ide.common.internal.LoggedErrorException: Failed to run command:
 D:\Mission\adt-bundle-windows\ndk-r10b\ndk-build.cmd NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\Android.mk APP_PLATFORM=android-21 NDK_OUT=C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\obj NDK_LIBS_OUT=C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\lib APP_ABI=armeabi,armeabi-v7a,x86
Error Code:
 2
Output:
 make.exe: *** No rule to make target `C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\obj/local/armeabi/objs/JniTest/C_\Users\sodinochen\AndroidstudioProjects\JniTest2\app\src\main\jni', needed by `C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\obj/local/armeabi/objs/JniTest/C_\Users\sodinochen\AndroidstudioProjects\JniTest2\app\src\main\jni\main.o'. Stop.

解决方法是在jni下面建立一个空的.c文件。
最后编译后的so就存在以下目录下
这里写图片描述

文件编译出来是不是很高兴,可是应该怎么使用呢

6.调用so库文件
我们创建一个Android module(Test,下文简称T工程),将上面lib下的文件拷贝到到这个新工程下lib文件夹下
这里写图片描述
之后我们要编辑一下T工程的的gradle脚本,在android标签下增加以下脚本

sourceSets {
        main {
            jniLibs.srcDir(['libs'])
        }
    }

那前期的准备工作就完成了,下面就是调用的了

我们在T工程下的Activity中编写如下代码
这里写图片描述

这个时候我们会发现编译器根本就找不到com.csf.jnidemo.Math.getStringFromNative这个包名下的这个方法。
这是因为我们没有编写对应的Java层声明代码(以前都是直接用的别人的jar包跟so文件,别人的Java层声明代码就是写在jar包上),那应该怎么声明方法呢。这个是有一定的要求的,Java层申明getStringFromNative方法,他的类名,包名要跟.so中的想对应。我们这里采用最简单的方法,因为so是我们自己编译的,我们其实已经有Java层声明代码了,看下图
这里写图片描述
我们直接将上面编译so工程的Math类及其包名目录拷贝到我们的T工程上就OK 了,其实我们可以将这个代码打出Jar包在T工程中引用,这样才是比较稳妥的。

那就运行T工程吧。结果就出来了。
这里写图片描述

这里写图片描述

好了,本文到此就完结了,上面只是用到的最简单的从so库取出一个字符串,以后我们再学习探讨下传参进native方法中处理后return到Java层的方法以及调用其他现成so库的方法。大家一起学习进步吧。
本文如果有存在什么错误的话,请指明下,谢谢!

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要将libzbarjni.so下载到Android Studio中,您可以按照以下步骤进行操作: 1. 首先,您需要找到libzbarjni.so的可用源。通常,您可以在开源项目的官方网站或代码托管平台上找到这些。您可以使用搜索引擎来查找相关的信息。 2. 找到合适的之后,您可以在下载页面或页面中找到相应的下载链接。点击链接,将下载文件保存到您的本地计算机上。 3. 确保您已经启动了Android Studio,并打开您想要添加libzbarjni.so的项目。 4. 在项目视图中,找到您的项目文件夹中的"jniLibs"文件夹。如果没有该文件夹,请手动创建一个。 5. 将下载的libzbarjni.so文件移动到您刚创建的"jniLibs"文件夹中。请注意,根据您的项目架构,您可能需要将文件放在不同的子文件夹中,例如"armeabi-v7a"或"x86"。 6. 在将文件添加到项目之后,您需要更新您的项目配置文件以引用这个。打开您的项目中的"build.gradle"文件。 7. 在"build.gradle"文件中,找到android部分并添加以下代码: ``` sourceSets { main { jniLibs.srcDirs = ['jniLibs'] } } ``` 这将告诉Android Studio编译和构建项目时将"jniLibs"文件夹中的文件包含在内。 8. 最后,保存并关闭"build.gradle"文件。重新编译和构建您的项目,Android Studio将自动将libzbarjni.so添加到您的应用程序中。 这样,您就成功地将libzbarjni.so下载到Android Studio中,并将其添加到您的项目中。您现在可以使用这个进行开发和测试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值