android jni abifilters为什么没产生文件
发布网友
发布时间:2022-04-22 21:48
我来回答
共1个回答
热心网友
时间:2023-09-28 14:59
android studio 中简单的jni开发
Let’s Go!!!
准备工作不再需要什么cgwin来编译ndk(太特么操蛋了),现在只需要你下载一下NDK的库就ok了,然后你也可以去离线下载http://www.androiddevtools.cn最新版,这里吐槽一下android studio对NDK的支持还有待提高。
效果
看下今天的效果:(安卓jni获取 apk的包名及签名信息)
必须的步骤
1.配置你的ndk路径(local.properties)
ndk.dir=E:\Android\sdk\android-ndk-r11b-windows-x86_64\android-ndk-r11b
2.grale配置使用ndk(gradle.properties)
android.useDeprecatedNdk=true
3.在mole下的build.gradle添加ndk以及jni生成目录
ndk{
moleName “JNI_ANDROID”
abiFilters “armeabi”, “armeabi-v7a”, “x86” //输出指定三种abi体系结构下的so库,目前可有可无。
}
sourceSets.main{
jniLibs.srcDirs = [‘libs’]
}
准备工作做好了开始写代码:(jni实现获取应用的包名和签名信息)
步骤1:先写要实现本地方法的类,及加载库(JNI_ANDROID也就是ndk 里面配的moleName)
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<code class="hljs java">package com.losileeya.getapkinfo;
/**
* User: Losileeya (847457332@qq.com)
* Date: 2016-07-16
* Time: 11:09
* 类描述:
*
* @version :
*/
public class JNIUtils {
/**
* 获取应用的签名
* @param o
* @return
*/
public static native String getSignature(Object o);
/**
* 获取应用的包名
* @param o
* @return
*/
public static native String getPackname(Object o);
/**
* 加载so库或jni库
*/
static {
System.loadLibrary("JNI_ANDROID");
}
}</code>
注意我们 的加载c方法都加了native关键字,然后要使用jni下的c/c++文件就必须使用System.loadLibrary()。
步骤2:使用javah命令生成.h(头文件)
javah -jni com.losileeya.getapkinfo.JNIUtils
执行完之后你可以在mole下文件夹app\build\intermediates\classes\debug下看见生成的 .h头文件为:
com_losileeya_getapkinfo_JNIUtils.h
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<code class="hljs vala">/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_losileeya_getapkinfo_JNIUtils */
#ifndef _Included_com_losileeya_getapkinfo_JNIUtils
#define _Included_com_losileeya_getapkinfo_JNIUtils
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jstring JNICALL Java_com_losileeya_getapkinfo_JNIUtils_getPackname(JNIEnv *, jobject, jobject);
JNIEXPORT jstring JNICALL Java_com_losileeya_getapkinfo_JNIUtils_getSignature(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif</jni.h></code>
在工程的main目录下新建一个名字为jni的目录,然后将刚才的.h文件剪切过来,当然文件名字是可以修改的
步骤3:根据.h文件生成相应的c/cpp文件
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<code class="hljs scala">//
// Created by Administrator on 2016/7/16.
//
#include <stdio.h>
#include <jni.h>
#include <stdlib.h>
#include "appinfo.h"
JNIEXPORT jstring JNICALL Java_com_losileeya_getapkinfo_JNIUtils_getPackname(JNIEnv *env, jobject clazz, jobject obj)
{
jclass native_class = env->GetObjectClass(obj);
jmethodID mId = env->GetMethodID(native_class, "getPackageName", "()Ljava/lang/String;");
jstring packName = static_cast<jstring>(env->CallObjectMethod(obj, mId));
return packName;
}
JNIEXPORT jstring JNICALL Java_com_losileeya_getapkinfo_JNIUtils_getSignature(JNIEnv *env, jobject clazz, jobject obj)
{
jclass native_class = env->GetObjectClass(obj);
jmethodID pm_id = env->GetMethodID(native_class, "getPackageManager", "()Landroid/content/pm/PackageManager;");
jobject pm_obj = env->CallObjectMethod(obj, pm_id);
jclass pm_clazz = env->GetObjectClass(pm_obj);
// 得到 getPackageInfo 方法的 ID
jmethodID package_info_id = env->GetMethodID(pm_clazz, "getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
jstring pkg_str = Java_com_losileeya_getapkinfo_JNIUtils_getPackname(env, clazz, obj);
// 获得应用包的信息
jobject pi_obj = env->CallObjectMethod(pm_obj, package_info_id, pkg_str, 64);
// 获得 PackageInfo 类
jclass pi_clazz = env->GetObjectClass(pi_obj);
// 获得签名数组属性的 ID
jfieldID signatures_fieldId = env->GetFieldID(pi_clazz, "signatures", "[Landroid/content/pm/Signature;");
jobject signatures_obj = env->GetObjectField(pi_obj, signatures_fieldId);
jobjectArray signaturesArray = (jobjectArray)signatures_obj;
jsize size = env->GetArrayLength(signaturesArray);
jobject signature_obj = env->GetObjectArrayElement(signaturesArray, 0);
jclass signature_clazz = env->GetObjectClass(signature_obj);
jmethodID string_id = env->GetMethodID(signature_clazz, "toCharsString", "()Ljava/lang/String;");
jstring str = static_cast<jstring>(env->CallObjectMethod(signature_obj, string_id));
char *c_msg = (char*)env->GetStringUTFChars(str,0);
return str;
}</jstring></jstring></stdlib.h></jni.h></stdio.h></code>
注意:要使用前得先声明,方法名直接从h文件考过来就好了,studio目前还是很操蛋的,对于jni的支持还是不很好。
步骤4:给项目添加Android.mk和Application.mk
此步骤显然也是不必要的,如果你需要生成so库添加一下也好,为什么不呢考过去改一下就好了,如果你不写这2文件也是没有问题的,因为debug下也是有这些so库的。
好吧,勉强看一下这2货:
Android.mk
?
1
2
3
4
5
<code class="hljs ruby">LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JNI_ANDROID
LOCAL_SRC_FILES =: appinfo.cpp
include $(BUILD_SHARED_LIBRARY)</code>
Application.mk
?
1
2
<code class="hljs makefile">APP_MODULES := JNI_ANDROID
APP_ABI := all</code>
android studio下External Tools的高级配置NDK一键javah,ndk生成so库
eclipse开发ndk的时候你可能就配置过javah,所以android studio也可以配置,是不是很兴奋:
Settings—>Tools—->External Tools就可以配置我们的终端命令了,别急一个一个来:
javah -jni 命令的配置(一键生成h文件)
我们先来看参数的配置:
1.Program:JDKPath\bin\javah.exe 这里配置的是javah.exe的路径(基本一致)
2.Parametes: -classpath . -jni -d MoleFileDir/src/main/jni FileClass这里指的是定位在Mole的jni文件你指定的文件执行jni指令<喎�"/kf/ware/vc/" target="_blank" class="keylink">vcD4NCgk8cD4zLldvcmtpbmc6PG5vYnI+TW9kdWxlRmlsZURpcjwvbm9icj5cc3JjXG1haW5camF2YTwvcD4NCjwvYmxvY2txdW90ZT4NCm5kay1idWlsZCjSu7z8yfqzyXNvv+IpDQo8cD48aW1nIGFsdD0="" src="/uploadfile/Collfiles/20160718/201607181017581505.png" title="\" />
我们同样来看参数的配置:
1.Program:E:\Android\sdk\android-ndk-r11b-windows-x86_64\android-ndk-r11b\ndk-build.cmd 这里配置的是ndk下的ndk-build.cmd的路径(自己去找下)
2.Working:MoleFileDir\src\main\
javap-s(此命令用于c掉java方法时方法的签名)
我们同样来看参数的配置:
1.Program:JDKPath\bin\javap.exe 这里配置的是javap.exe的路径(基本一致)
2.Parametes: -classpathMoleFileDir/build/intermediates/classes/debug -s FileClass 这里指的是定位到build的debug目录下执行 javap -s class文件
3.Working:MoleFileDir
这里介绍最常用的3个命令,对你的帮助应该还是很大的来看一下怎么使用:
javah -jni的使用:选中native文件—>右键—>External Tools—>javah -jni
效果如下:
是不是自动生成了包名.类名的.h文件。
ndk-build的使用:选中jni文件—>右键—>External Tools—>ndk-build
效果如下:
是不是一键生成了7种so库,你还想去debug目录下面去找吗
javap-s的使用:选中native文件—>右键—>External Tools—>javap-s
效果如下:
看见了每个方法下的descriptor属性的值就是你所要的方法签名。
3种一键生成的命令讲完了,以后你用到了什么命令都可以这样设置,是不是很给力。