现在很多android应用的注册码配置的时候,为了保证本身应用的安全,将获取机器唯一标识的字段放在jni中执行。


手机或者pad的机器唯一标识主要有

imei 手机设备号

imsi 手机串口

macaddr 手机上的物理地址


一般都是

jint Java_com_example_jnicalltest_Jnihelper_testobj(JNIEnv* env, jobject thiz, jobject obj)

比如这个是一个c语言写的jni函数


java应用层调用的时候一般是使用

Jnihelper.testobj(MainActivity.this);

这个方法,注意传入的这个类继承于 android.app.Activity,再网上继承是 android.app.Context,而不管怎样,这个类传入以后,在c语言中的这个函数的实现部分,就可以使用


jmethodID systemService = (*env)->GetMethodID(env,clazz,"getSystemService","(Ljava/lang/String;)Ljava/lang/Object;");


这类的接口找到这个类是否存在这样的接口了.

找到有这样的接口,肯定有,因为你可以查看android api的文档,也不会写一个不存在的接口

然后就调用


jobject tm = (*env)->CallObjectMethod(env, obj, systemService,jstrMSG);

这样的接口,来调用了 传入的obj的 getSystemService 这个成员方法,获取jobject的返回值,然后再进行相关的操作,最终用这样的方法取得了想要的手机唯一码值


原理大概就这些,基本搞清楚了


然后就是想有没有神马方法能够让jni中的so库调用我们的class,而不是android系统的Context的class,如果能够调用我们的class,那样我们写神马返回值不都能够回传到jni中,从而破坏掉其业务逻辑。


是有方法的:


1 com_example_jnicalltest_Jnihelper 编写这样的包在自己的工程中,以为直接修改so中的调用函数名比较麻烦,所以还是在自己的工程中老老实实的建立一样的package方便,像上面的函数,基本上就是建立 com.example.jnicalltest.Jnihelper 这样的类就行了


package com.example.jnicalltest;


public class Jnihelper {

static {

System.loadLibrary("screenshot");

}

public static native int testobj(Object testobj);

public static native int testsystem(Object testsystem);

}

比如这样的写法...