1、你可以直接写一个JNI的头文件或者用javah生成一个JNI的头文件。
先说第二种吧:
我们要用一个类调用native方法
package com.venom.ftp.jni;
import android.content.Context;
public class JNIgetNamePass {
static{
System.loadLibrary("checkkey");
}
public native boolean isSignnatureLegal(Context context);
public native String getUserName();
public native String getPassword();
}
a、第一步 配置
JAVA_HOME
C:\Program Files\Java\jdk1.7.0_80
b、第二步 配置
CLASSPATH
.;D:\work\android_sdk\sdk\platforms\android-17\android.jar
CLASSPATH 中的andorid.jar的目录前一定要加
.;
c、第三步 javah
D:\administer\workspace\工程名称\bin\classes>javah -jni com.venom.ftp.jni.JNIgetNa
mePass
d、生成的文件:
文件名称:com_venom_ftp_jni_JNIgetNamePass.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_venom_ftp_jni_JNIgetNamePass */
#ifndef _Included_com_venom_ftp_jni_JNIgetNamePass
#define _Included_com_venom_ftp_jni_JNIgetNamePass
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_venom_ftp_jni_JNIgetNamePass
* Method: isSignnatureLegal
* Signature: (Landroid/content/Context;)Z
*/
JNIEXPORT jboolean JNICALL Java_com_venom_ftp_jni_JNIgetNamePass_isSignnatureLegal
(JNIEnv *, jobject, jobject);
/*
* Class: com_venom_ftp_jni_JNIgetNamePass
* Method: getUserName
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_venom_ftp_jni_JNIgetNamePass_getUserName
(JNIEnv *, jobject);
/*
* Class: com_venom_ftp_jni_JNIgetNamePass
* Method: getPassword
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_venom_ftp_jni_JNIgetNamePass_getPassword
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
注意 第二步一定要有如果你的c文件中有andorid的类的话,如果不设置会找不到类:由于本文中用到的是Contenxt类会报:找不到类android.content.Context。
2、如果 是手动直接写JNI .h头文件的话,有几点要注意
a、 extern "C" {}
如果是C++文件(.cpp或者.cc),要使用extern "C" { } 把本地方法括进去。
b、要用jni的语法来编写程序
c、方法名命名:Java 开头,后面是对应java类的包名,包名中间用“_”隔开,包名最后是类名,类名后面是方法名。
d、.h文件中的方法声明,在cpp文件中实现的时候一定要保持一致
3、校验签名是否一致,一致的时候才返回你的token,这样才能更加安全的确保你的so文件的安全性,防止别人盗用
#include <jni.h>
#include <string.h>
#include <stdio.h>
#include <com_android_jni_JNI.h>
#include<android/log.h>
/**
* http api 授权 key ,由服务端提供
*/
const char* USER_NAME = "chanmao";
const char* PASS_WORD = "chanmao";
/**
* 发布的app 签名,只有和本签名一致的app 才会返回合法的 授权 key
*/
const char* RELEASE_SIGN ="308201dd30820146020101300d06092a864886f70d010105050030373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b3009060355040613025553301e170d3136303533303035343230325a170d3436303532333035343230325a30373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b300906035504061302555330819f300d06092a864886f70d010101050003818d0030818902818100b057029943e21659b6da7b8ccfba183210eac516893681dec14720ffd7c81296be073e00316a366a1b6f9e2b95c19f088482d3bae38e0a03074369b338ed6e1874143b509800074d11370ac0c7cd851cae4d95e8dc15fb2c65b19c0ea8381bd85c4fcc3b482ee83558ceba21b3723b8e36de7ffd4ff5c0df6dc42d8d6439a5f70203010001300d06092a864886f70d010105050003818100708e272ae1f8e565deaec01d42abcd91b8c001b68647795866b1f83a97d314709e37d7a472c24c65368584d5e8a3c72614e422f2130b45b20c94f0b6fbbececca610f30c87ad5ef8d7f22d4c0a6dda5cfc3416ea200e5892b1db08aea05a4fbf1aae3c379f1e47b3d59e1691d0cc7216df5177b6b202a392b11bc9a6a986b0fb";
/**
* 拿到传入的app 的 签名信息,对比合法的app 签名,防止so文件被未知应用盗用
*/
static jclass contextClass;
static jclass signatureClass;
static jclass packageNameClass;
static jclass packageInfoClass;
jboolean isSignnatureLegal = false;
JNIEXPORT void JNICALL Java_com_venom_ftp_jni_JNIgetNamePass_isSignnatureLegal(
JNIEnv * env, jobject obj, jobject contextObject) {
jmethodID getPackageManagerId = (env)->GetMethodID(contextClass, "getPackageManager","()Landroid/content/pm/PackageManager;");
jmethodID getPackageNameId = (env)->GetMethodID(contextClass, "getPackageName","()Ljava/lang/String;");
jmethodID signToStringId = (env)->GetMethodID(signatureClass, "toCharsString","()Ljava/lang/String;");
jmethodID getPackageInfoId = (env)->GetMethodID(packageNameClass, "getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
jobject packageManagerObject = (env)->CallObjectMethod(contextObject, getPackageManagerId);
jstring packNameString = (jstring)(env)->CallObjectMethod(contextObject, getPackageNameId);
jobject packageInfoObject = (env)->CallObjectMethod(packageManagerObject, getPackageInfoId,packNameString, 64);
jfieldID signaturefieldID =(env)->GetFieldID(packageInfoClass,"signatures", "[Landroid/content/pm/Signature;");
jobjectArray signatureArray = (jobjectArray)(env)->GetObjectField(packageInfoObject, signaturefieldID);
jobject signatureObject = (env)->GetObjectArrayElement(signatureArray,0);
const char* signStrng = (env)->GetStringUTFChars((jstring)(env)->CallObjectMethod(signatureObject, signToStringId),0);
__android_log_print(ANDROID_LOG_INFO, "JNITag","-------:%s",signStrng);
if(strcmp(signStrng,RELEASE_SIGN)==0)//签名一致 返回合法的 api key,否则返回错误
{
isSignnatureLegal = true;
}else
{
isSignnatureLegal = false;
}
//return (env)->NewStringUTF(AUTH_KEY);
}
JNIEXPORT jstring JNICALL Java_com_venom_ftp_jni_JNIgetNamePass_getUserName(
JNIEnv * env, jobject obj) {
if(isSignnatureLegal){
return (env)->NewStringUTF(PASS_WORD);
}else{
return (env)->NewStringUTF("error");
}
}
JNIEXPORT jstring JNICALL Java_com_venom_ftp_jni_JNIgetNamePass_getPassword(
JNIEnv * env, jobject obj) {
if(isSignnatureLegal){
return (env)->NewStringUTF(PASS_WORD);
}else{
return (env)->NewStringUTF("error");
}
}
JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM* vm,void* reserved){
JNIEnv* env = NULL;
jint result=-1;
if(vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK)
return result;
contextClass = (jclass)env->NewGlobalRef((env)->FindClass("android/content/Context"));
signatureClass = (jclass)env->NewGlobalRef((env)->FindClass("android/content/pm/Signature"));
packageNameClass = (jclass)env->NewGlobalRef((env)->FindClass("android/content/pm/PackageManager"));
packageInfoClass = (jclass)env->NewGlobalRef((env)->FindClass("android/content/pm/PackageInfo"));
return JNI_VERSION_1_4;
}
android获取签名:
public static String getSignature(Context context)
{
try {
/** 通过包管理器获得指定包名包含签名的包信息 **/
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
/******* 通过返回的包信息获得签名数组 *******/
Signature[] signatures = packageInfo.signatures;
/******* 循环遍历签名数组拼接应用签名 *******/
return signatures[0].toCharsString();
/************** 得到应用签名 **************/
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return null;
}