最近一直在作公司的一個安卓開發框架,含so庫,接近尾聲了,領導提出一個需求,要求使用這個框架的開發者必須有咱們的受權才能夠,可是對方發佈的應用後又不能被此受權限制——要否則全部的應用都來要受權那就麻煩了。java
分析:app
既然是限制開發者,那麼就必需要區分debug版本和release版本,也就是框架的受權限制功能只對debug版本有效,而對release版本無效;而後就是須要一個調試設備的一個惟一ID,這樣受權碼是綁定在固定的設備的,只要有新的調試設備就須要新的受權碼,通常公司裏也就是十幾個設備吧,這個申請量級徹底能夠接受。框架
思路:jvm
由於正好這個框架須要so庫的支持,這樣在so庫加載時的int JNI_OnLoad(JavaVM* jvm, void* reserved)方法中能夠完成驗證。this
關於debug和release版本的區分,安卓系統提供了一個debugable屬性能夠實現,只要是從Eclipse或者ADT的集成環境裏直接運行或者調試,均可以判斷出是不是debug版本;加密
關於安卓設備的ID,安卓自己提供好幾種ID的獲取,我最終使用的是security類的ID, Settings.Secure.getString(ContentResolver,Settings.Secure.ANDROID_ID),這個ID是在安卓設備第一次啓動的時候自動生成的,若是刷機的話則可能會改變。spa
受權碼的存放位置就放在AndroidManifest中的application結點下,增長一個meta結點,並能夠自定義信息的名稱,那麼如今就是準備工做就全了.debug
實現:調試
1. JNI層的int JNI_OnLoad(JavaVM* jvm, void* reserved)完成驗證code
2.JNI層判斷程序是否爲debug版本,爲防止java代碼被反編譯,因此獲取debug屬性和判斷都在JNI層進行,能夠參考java層的以下代碼,即將一下代碼改編爲C++代碼:
public boolean isDebugMode(){ ApplicationInfo info = this.getApplicationInfo(); return (0!=((info.flags) & ApplicationInfo.FLAG_DEBUGGABLE)); }
3.JNI層獲取安卓設備的惟一ID,能夠參考java代碼,即將一下代碼改編爲C++代碼:
String id = Settings.Secure.getString(this.mainActivity.getContentResolver(), Settings.Secure.ANDROID_ID);
4.獲取Manifest中的meta中的受權碼,這個就不必非得在JNI層實現了,能夠在java層獲取,而後傳遞給JNI層,參考是以下的java代碼:
ApplicationInfo info=context.getPackageManager().getApplicationInfo(con.getPackageName(),PackageManager.GET_META_DATA); String key=info.metadata.getString("permissionKey");
5.接下來就是加密解密以及最後的適當加花加殼的取捨了,就再也不細說了。