JNI开发时需要注意的一些事项

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;
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值