AndroidはJNIでMACアドレスを取得する(Android 6.0以上に適合)
17208 ワード
最近のプロジェクトでは、C++レイヤで暗号化し、soにコンパイルする必要があると遭遇しました.MACアドレスはデバイスの一意性を識別できることを知っている.だから、C++層でMACアドレスを取得する必要があります.ここではJNIを使ってプログラミングする必要があります.あまり言わないで、どのように取得するかを見てみましょう.
その前に、権限の追加を忘れないでください.
まず、javaでどのように取得されたかを見てみましょう.Android6.0以前のメソッドは6.0以降では成功しませんでした.最新の取得方法を直接使用しますコードは簡単で、静的メソッドgetByNameでNetworkInterfaceインスタンスを取得し、getHardwareAddress()でbyte[]配列を取得します.ここで取得したのは16進数配列で、変換が必要です.
ここでBYTEはマクロ定義でcppファイルに加算
主な難点は、データの変換方法です.JNIはjava反射法のような一連の方法でjavaのしたことを完成させ、javaの呼び出しを行う.具体的なパラメータ変換はネット上にたくさんありますが、ここではリストしません.これにより、デバイスのMACアドレスが取得されます.もちろん、一般的にはjavaレイヤに戻る必要はありません(javaは取得できますが、なぜcレイヤで取得するのが面倒なのか、私が病気でない限り戻ります.)20は、暗号化などのMACアドレスをJNIレイヤで直接操作します.
文章はここまでで、みんなはjavaの多くの方法に対してJNI呼び出しを行うことができて、システムのクラスのほかに、私达もクラスをカスタマイズすることができて、もしコードに対して暗号化する必要があるならば、他の人に简単な反コンパイルをさせたくなくて、この技を使うことができて、结局soはやはりとても安全です.
その前に、権限の追加を忘れないでください.
android:name="android.permission.INTERNET" />
android:name="android.permission.READ_PHONE_STATE" />
android:name="android.permission.ACCESS_WIFI_STATE" />
まず、javaでどのように取得されたかを見てみましょう.Android6.0以前のメソッドは6.0以降では成功しませんでした.最新の取得方法を直接使用しますコードは簡単で、静的メソッドgetByNameでNetworkInterfaceインスタンスを取得し、getHardwareAddress()でbyte[]配列を取得します.ここで取得したのは16進数配列で、変換が必要です.
/**
* MAC
* */
public static String getMacAddress() {
/* mac android 6.0 , , "02:00:00:00:00:00" mac , googel getSYstemService(Context.WIFI_SERVICE) mac 。*/
// String macAddress= "";
// WifiManager wifiManager = (WifiManager) MyApp.getContext().getSystemService(Context.WIFI_SERVICE);
// WifiInfo wifiInfo = wifiManager.getConnectionInfo();
// macAddress = wifiInfo.getMacAddress();
// return macAddress;
String macAddress = null;
StringBuffer buf = new StringBuffer();
NetworkInterface networkInterface = null;
try {
networkInterface = NetworkInterface.getByName("eth1");
if (networkInterface == null) {
networkInterface = NetworkInterface.getByName("wlan0");
}
if (networkInterface == null) {
return "02:00:00:00:00:02";
}
byte[] addr = networkInterface.getHardwareAddress();
for (byte b : addr) {
buf.append(String.format("%02X:", b));
}
if (buf.length() > 0) {
buf.deleteCharAt(buf.length() - 1);
}
macAddress = buf.toString();
} catch (SocketException e) {
e.printStackTrace();
return "02:00:00:00:00:02";
}
return macAddress;
}
そしてこの方法に従ってJNIで実現する// JNI java NetworkInterface
jclass cls_networkInterface = env->FindClass("java/net/NetworkInterface");
if (cls_networkInterface == 0) {
return env->NewStringUTF("");
}
// getByName
jmethodID jmethodID1 = env->GetStaticMethodID(cls_networkInterface, "getByName", "(Ljava/lang/String;)Ljava/net/NetworkInterface;");
if (jmethodID1 == 0)
return env->NewStringUTF("");
std::string ss = "wlan0";
jstring jss2 = env->NewStringUTF(ss.c_str());
// getByname NetworkInterface
jobject jobject1 = env->CallStaticObjectMethod(cls_networkInterface, jmethodID1, jss2);
// getHardAddress
jmethodID getHardwareAddress = env->GetMethodID(cls_networkInterface, "getHardwareAddress", "()[B");
if (getHardwareAddress == 0)
return env->NewStringUTF("");
// getHardAddress MAC byte[]
jbyteArray jbyte1 = (jbyteArray)env->CallObjectMethod(jobject1, getHardwareAddress);
// byte[] char
jbyte * olddata = (jbyte*)env->GetByteArrayElements(jbyte1, 0);
jsize oldsize = env->GetArrayLength(jbyte1);
// BYTE #define BYTE unsigned char
BYTE* bytearr = (BYTE*)olddata;
int len = (int)oldsize;
char* data = (char*)env->GetByteArrayElements(jbyte1, 0);
char *temp = new char[len*2 + 1];
memset(temp,0,len*2 +1);
for (int i = 0; i < len; i++) {
char * buffer = new char[2];
memset(buffer,2,0);
sprintf(buffer, "%02X", data[i]);
memcpy(temp+i*2, buffer, 2);
delete[] (buffer);
}
jstring jMac = charTojstring(env, temp);
delete[] temp;
return jMac;
ここでBYTEはマクロ定義でcppファイルに加算
#define BYTE unsigned char
charTojstringメソッドは次のとおりです.jstring charTojstring(JNIEnv* env, const char* pat) {
// java String strClass
jclass strClass = (env)->FindClass("java/lang/String");
// String(byte[],String) , byte[] String
jmethodID ctorID = (env)->GetMethodID(strClass, "" , "([BLjava/lang/String;)V");
// byte
jbyteArray bytes = (env)->NewByteArray(strlen(pat));
// char* byte
(env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*) pat);
// String, , byte String
jstring encoding = (env)->NewStringUTF("GB2312");
// byte java String,
return (jstring) (env)->NewObject(strClass, ctorID, bytes, encoding);
}
主な難点は、データの変換方法です.JNIはjava反射法のような一連の方法でjavaのしたことを完成させ、javaの呼び出しを行う.具体的なパラメータ変換はネット上にたくさんありますが、ここではリストしません.これにより、デバイスのMACアドレスが取得されます.もちろん、一般的にはjavaレイヤに戻る必要はありません(javaは取得できますが、なぜcレイヤで取得するのが面倒なのか、私が病気でない限り戻ります.)20は、暗号化などのMACアドレスをJNIレイヤで直接操作します.
文章はここまでで、みんなはjavaの多くの方法に対してJNI呼び出しを行うことができて、システムのクラスのほかに、私达もクラスをカスタマイズすることができて、もしコードに対して暗号化する必要があるならば、他の人に简単な反コンパイルをさせたくなくて、この技を使うことができて、结局soはやはりとても安全です.