android使用C/C++调用SO库
有时候,我们反编译apk得到一个so库,如果直接使用这个so库的话,必须使用原来so库同样的package名字,才能用。
这样人家反编译你的apk,就知道你侵犯了人家的版权。为了达到混淆的目的,我们可以再写一个so库调用人家的so库,即把人家的so库放到root的某个路径下,用c/c++语言调用这个so库。比如说,我得到一个APK,反编译这个APK看到下面的代码:
- static {
- try {
- System.loadLibrary("NativeExampleActivity");
- } catch (Throwable t) {
- }
- }
- public native int addFunction(int a, int b);
- public native String getString(String name);
很明显,这个so库是libNativeExampleActivity.so, 库里面有两个native函数addFunction和getString。
虽然知道了这两个native函数,但是我们还不能直接使用,因为这两个native函数在so库里面的真实函数名不是addFunction和getString,
它在native函数名之前还有包名,所以必须使用nm命令,查看so库里面的函数名。
显示so库函数的命令:
nm -A libNativeExampleActivity.so
或者
nm -D libNativeExampleActivity.so
这样我们看到so库里的主要信息:
Java_org_natives_example_NativeExampleActivity_addFunction
Java_org_natives_example_NativeExampleActivity_getString
看到没有,在addFunction函数前面还有包名,这就是为什么直接使用人家的so库的时候,一定要使用原来的package名字!
好了,现在是怎么调用这两个函数了,4个步骤完成。
1.用Eclipse创建一个项目
- package so.hello;
- import android.app.Activity;
- import android.os.Bundle;
- public class SoHelloActivity extends Activity {
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
- static {
- try {
- System.loadLibrary("soHello");
- } catch (Throwable t) {
- }
- }
- public native int addFunction1(int a, int b);
- public native String getString1(String name);
- }
2.在终端进入到项目的路径soHello/bin/classes,执行命令:
guo@guo-desktop:~/workspace/soHello/bin/classes$ javah -jni so.hello.SoHelloActivity
在soHello/bin/classes目录下会生成一个文件so_hello_SoHelloActivity.h
- /* DO NOT EDIT THIS FILE - it is machine generated */
- #include <jni.h>
- /* Header for class so_hello_SoHelloActivity */
- #ifndef _Included_so_hello_SoHelloActivity
- #define _Included_so_hello_SoHelloActivity
- #ifdef __cplusplus
- extern "C" {
- #endif
- /*
- * Class: so_hello_SoHelloActivity
- * Method: addFunction1
- * Signature: (II)I
- */
- JNIEXPORT jint JNICALL Java_so_hello_SoHelloActivity_addFunction1
- (JNIEnv *, jobject, jint, jint);
- /*
- * Class: so_hello_SoHelloActivity
- * Method: getString1
- * Signature: (Ljava/lang/String;)Ljava/lang/String;
- */
- JNIEXPORT jstring JNICALL Java_so_hello_SoHelloActivity_getString1
- (JNIEnv *, jobject, jstring);
- #ifdef __cplusplus
- }
- #endif
- #endif
3.写一个so_hello_SoHelloActivity.cpp文件
- #include "so_hello_SoHelloActivity.h"
- #include <stdlib.h>
- #include <fcntl.h>
- #include <android/log.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <dlfcn.h>
- void *filehandle = NULL;
- jint (*addFunc)(JNIEnv *,jobject,jint,jint) = NULL;
- jstring (*getStringFunc)(JNIEnv *, jobject, jstring) = NULL;
- JNIEXPORT jint JNICALL Java_so_hello_SoHelloActivity_addFunction1
- (JNIEnv *env, jobject obj, jint a, jint b);
- {
- jint mun = 0;
- //事先把libNativeExampleActivity放到root/system/lib/目录下
- filehandle = dlopen("/system/lib/libNativeExampleActivity.so", RTLD_LAZY);
- if(filehandle)
- {
- addFunc = (jint (*)(JNIEnv *,jobject,jint,jint))dlsym(filehandle, "Java_org_natives_example_NativeExampleActivity_addFunction");
- if(addFunc)
- mun = addFunc(env, obj, a, b);
- dlclose(filehandle);
- filehandle = NULL;
- }
- return mun;
- }
- /*
- * Class: so_hello_SoHelloActivity
- * Method: getString1
- * Signature: (Ljava/lang/String;)Ljava/lang/String;
- */
- JNIEXPORT jstring JNICALL Java_so_hello_SoHelloActivity_getString1
- (JNIEnv *, jobject, jstring name)
- {
- jstring mun = 0;
- //事先把libNativeExampleActivity放到root/system/lib/目录下
- filehandle = dlopen("/system/lib/libNativeExampleActivity.so", RTLD_LAZY);
- if(filehandle)
- {
- getStringFunc = (jstring (*)(JNIEnv *,jobject,jstring))dlsym(filehandle, "Java_org_natives_example_NativeExampleActivity_getString");
- if(getStringFunc)
- {
- mun = getStringFunc(env, obj, name);
- }
- dlclose(filehandle);
- filehandle = NULL;
- }
- return env->NewStringUTF(mun);
- }
4.编写Android.mk
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_LDLIBS := -llog
- LOCAL_C_INCLUDES += system/core/include/cutils
- LOCAL_SHARED_LIBRARIES := \
- libdl \
- libcutils
- LOCAL_PRELINK_MODULE := false
- LOCAL_MODULE := libsoHello
- LOCAL_MODULE_TAGS := optional
- LOCAL_SRC_FILES := so_hello_SoHelloActivity.cpp
- LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
- include $(BUILD_SHARED_LIBRARY)
使用mm命令编译so_hello_SoHelloActivity.cpp,便可以生成libsoHello.so库。
然后这个so库就可以用啦!
综述:
这里主要使用了dlopen、dlsym、dlclose三个函数来加载so库:
void *filehandle = NULL;
jint (*addFunc)(JNIEnv *,jobject,jint,jint) = NULL;
jint mun = 0
//事先把libNativeExampleActivity放到root/system/lib/目录下
filehandle = dlopen("/system/lib/libNativeExampleActivity.so", RTLD_LAZY);
if(filehandle)
{
addFunc = (jint (*)(JNIEnv *,jobject,jint,jint))dlsym(filehandle, "Java_org_natives_example_NativeExampleActivity_addFunction");
if(addFunc)
mun = addFunc(env, obj, a, b);
dlclose(filehandle);
filehandle = NULL;
}
android使用C/C++调用SO库的更多相关文章
- android开发-c++代码调用so库
Android项目的CMakeLists.txt代码如下,so文件放在项目的$Project/app/src/main/jniLibs/$arch下,$arch替换为arm64-v8a armv7a等 ...
- 【走过巨坑】android studio对于jni调用及运行闪退无法加载库的问题解决方案
相信很多小伙伴都在android开发中遇到调用jni的各种巨坑,因为我们不得不在很多地方用到第三方库so文件,然而第三方官方通常都只会给出ADT环境下的集成方式,而谷歌亲儿子android studi ...
- Android JNI如何调用第三方库
http://www.2cto.com/kf/201504/388764.html Android JNI找不到第三方库的解决方案 cannot load library 最近做一个jni项目,拿到的 ...
- [置顶] android利用jni调用第三方库——第三篇——编写库android程序整合第三方库libhello.so到自己的库libhelloword.so
0:前言: 在第二篇中,我们主要介绍了丙方android公司利用乙方C++公司给的动态库,直接调用库中的方法,但是这样方式受限于: 乙方C++公司开发的动态库是否符合jni的规范,如果不规范,则不能直 ...
- [置顶] android利用jni调用第三方库——第二篇——编写库android程序直接调用第三方库libhello.so
0:前言 1:本文主要作为丙方android公司的身份来写 2:作者有不对的地方,请指出,谢谢 [第一篇:android利用jni调用第三方库——编写库libhello.so] [第二篇:androi ...
- [置顶] android调用第三方库——第四篇——调用多个第三方库
0:前言: 在前面三篇中我们介绍了android调用第三方库的形式,在这一篇中我们介绍调用多个第三方库的Android.mk的写法,由于其他三篇介绍的很详细,这里只给出Android.mk的内容. [ ...
- Android NDK开发及调用标准linux动态库.so文件
源:Android NDK开发及调用标准linux动态库.so文件 预备知识及环境搭建 1.NDK(native development Kit)原生开发工具包,用来快速开发C.C++动态库,并能自动 ...
- 简单的调用OpenCV库的Android NDK开发 工具Android Studio
前言 本博客写于2017/08/11, 博主非专业搞安卓开发, 只是工作的需要倒腾了下Android NDK相关的开发, 博文中有什么不正确.不严格的地方欢迎指正哈 本文后续也许还会有删改, 就 ...
- android调用第三方库——第二篇——编写库android程序直接调用第三方库libhello.so (转载)
转自:http://blog.csdn.net/jiuyueguang/article/details/9449737 版权声明:本文为博主原创文章,未经博主允许不得转载. 0:前言 1:本文主要作为 ...
随机推荐
- 阿里云ftp连接遇到的错误,entering passive mode失败(一个并不成熟的产品?)
####禁止自行转载 ####违者必究 ####需要转载请联系我 因为最近用python写了一个自动上传的脚本,想通过FTP把数据上传到我的服务器. 于是, 兴高采烈地打开我一直信任的阿里云,yum ...
- 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记6——四大变换&光照与材质
第13章 四大变换 在Direct3D中,如果为进行任何空间坐标变换而直接绘图的话,图形将始终处于应用程序窗口的中心位置,默认这个位置就成为世界坐标系的原点(0,0,0).而且我们也不能改变观察图形的 ...
- hdu 1243(LCS变形)
反恐训练营 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- jmeter+Jenkins 持续集成中发送邮件报错:MessagingException message: Exception reading response
已经配置好了发送邮件的相关信息,但是执行完脚本出现报错:MessagingException message: Exception reading response 1.查看Jenkins本次构建的控 ...
- 在class中获取web资源
背景介绍 项目中用jasperreport做报表,模板文件为web资源,不在classpath之中.class又需要获取模板文件,结合数据源,生成pdf格式的报表. 之前的做法是定义一个public ...
- NIO使用Reactor模式遇到的问题
关于Reactor模式,不再多做介绍,推荐Doug Lea大神的教程:Java 可扩展的IO 本来在Reactor的构造方法中完成一系列操作是没有问题的: public class Reactor i ...
- 解决Linux用户模板文件被删除后显示不正常问题
缺失用户模板文件(用户骨架文件)会导致shell提示符不完整,可以到/etc/skel/目录下复制相关文件来恢复 (1).创建测试环境,删除模板文件 [root@xuexi ~]# useradd t ...
- gwy常识
其实公务员考试是一门艺术,七分靠水平,三分凭发挥,充分而又细致的准备则是取得优秀成绩的前提.考生若想在笔试中成功上岸,还需苦练内功,凭技巧和真才实学在考场上一较高下.那么针对历年上海公务员考试笔试考情 ...
- python搜索引擎(转)
用python如何实现一个站内搜索引擎? 先想想搜索引擎的工作流程: 1.网页搜集.用深度或者广度优先的方法搜索某个网站,保存下所有的网页,对于网页的维护采用定期搜集和增量搜集的方式. 2.建立索引库 ...
- HDU 6060 RXD and dividing(LCA)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6060 [题目大意] 给一个n个节点的树,要求将2-n号节点分成k部分, 然后将每一部分加上节点1, ...