『壹』 android調用so(jni)需要在AndroidManifest.xml中聲明許可權嗎,比如通過jni發送簡訊、讀取imei等。
jni通過反調java介面的話,處理方式與JAVA層直接調用介面無異,需要聲明許可權。
jni直接可以讀取設備的cpu、mac等linux kernel中的資料,至於imei是讀不到的。另外,發簡訊也是要調用系統提供的JAVA層的API,如果要直接調用底層介面的話,你估計要重新編譯自己的Android SDK才行。
jni反調java是個很惡心的工作,尤其是在多線程中,最好還是不要嘗試。
有一種不需要聲明許可權的方法是,搞到kernel層的所有API,直接操作硬體吧。當然那是不可能的。
『貳』 Android Studio 之簽名
通過簽名可以確保數據來源的可靠性和數據的不可篡改性
對 Apk 進行簽名,也就是在 Apk 中寫入一個指紋,寫入指紋後,Apk 中有任何修改,都會導致這個指紋無效,Android 系統在安裝 Apk 進行簽名校驗時就會不通過,進而無法安裝該 Apk
如上圖:
通常的簽名驗簽過程中,接收方收到消息後,會先向 CA 機構驗證證書的合法性,再進行簽名校驗。但 Apk 的證書通常由開發者自己製作,沒有向 CA 機構申請,Android 系統在安裝 Apk 時也並沒有校驗證書本身的合法性,只是從證書中提取公鑰和加密演算法,因此,如果對第三方 Apk 重新簽名,也能安裝到沒有安裝過這個 Apk 的系統中
keystore 文件包含私鑰、公鑰和數字證書,分為很多種,Android 使用的是 Java 標准 keystore 格式 JKS(Java Key Storage)
Android App Bundle:用於通過 Google Play 發布的應用,需要升級到AS 3.2 以上版本才支持App Bundle 格式;
APK:用於創建可部署到設備上的簽名 APK
點擊 Finish 就會生成簽名文件與簽名後的 Apk
當我們需要升級 Apk 版本的時候,需要再次對 Apk 文件進行簽名,可以通過配置 build.gradle 讓其自動生成簽名後的 Apk
如果你的項目是開源的,需要把你的簽名信息寫在 local.properties 中,然後在 .gitignore 配置文件中加入 local.properties ,這樣 local.properties 就不會提交到開源項目中,簽名信息也就不會被人獲取
local.properties:
app/build.gradle:
有時候我們的 apk 中某些功能需要系統簽名,例如靜默安裝。測試系統簽名的 apk,需要 root 許可權,而帶 Google APIs 的模擬器不能 root,因此要注意不能選擇帶 Google APIs 的模擬器
下面執行的操作都是在 Linux 中,如果 apk 是 window 中生成的,需要拷貝到 linux 操作,再將生成的系統簽名過得 apk 再拷貝到 window,比較麻煩,可以考慮後面的自動系統簽名,還是需要在 linux 操作一次,不過之後就可以只在 window 操作了
這兩個文件在目錄 aosp/build/target/proct/security 下,如下圖
在目錄 aosp/prebuilts/sdk/tools/lib 下,如下圖
將前面獲取的 platform.pk8 、 platform.x509.pem 和 signapk.jar 文件放到需要簽名的 apk 同一個目錄,執行以下命令
如果出現上面的錯誤:Failed to load any of the given libraries: [conscrypt_openjdk_jni-linux-x86_64, conscrypt_openjdk_jni-linux-x86_64-fedora, conscrypt_openjdk_jni]
解決方法:
到目錄 aosp/prebuilts/sdk/tools/linux/lib64 下,復制 libconscrypt_openjdk_jni.so 文件到需要簽名 apk 的同一個目錄,並將命令改為
自動進行系統簽名的原理是:先生成一個 system.jks 文件,使用 keytool-importkeypair 對 system.jks 文件進行系統簽名,再 build.gradle 和 local.properties 進行配置,直接使用帶有系統簽名的 system.jks 對 apk 進行簽名,這樣編譯生成的apk文件就自帶系統簽名了
按照前面的方法,生成一個 system.jks 文件,此時是在 window 系統中操作的
進入 keytool-importkeypair 目錄,將 system.jks、platform.pk8、platform.x509.pem 文件拷貝進來,拷貝之後的目錄結構為
使用 linux 中修改過的帶有系統簽名的 system.jks 文件將 window 中最開始生成的 system.jks 覆蓋掉,再像前面的自動簽名部分一樣,修改 build.gradle 和 local.properties 的配置,之後生成的 apk 就是系統簽名過的了
測試方法是,在 AndroidManifest.xml 中添加 android:sharedUserId="android.uid.system" 後安裝到 非 Google APIs 的模擬器上 , Google APIs 的模擬器不能 root,無法安裝
會發現只有使用 system.jks 文件簽名後才能安裝,否則安裝失敗,會報以下的錯誤:
『叄』 android怎麼實現後台對按鍵事件的監控
遙控器按鍵事件這個不是在Android源碼的bootable下面ircon.c配置的么。比如:
{ .scancode = 0x0b, .mask = 0xaa0087ee,
.keycode = KEY_UP, .spec = IRCON_KEYCODE_NORMAL | IRCON_KEYCODE_LONGPRESS | IRCON_KEYCODE_MOUSEMD },
遙控器按鍵編號是「 0x0b」,給他的響應是「KEY_UP」,就是方向鍵的下,這個是在源碼里邊配置的。你必須要有遙控器的書名數,知道遙控器每個按鍵的編號,然後對應給他相應的響應才可以。
但是你要操控手機,你的手機必須要能接受遙控器信號,這個也是要硬體支持的,一般的手機貌似都沒有這個。
這個遙控的響應操作是驅動層做的,和應用層沒什麼關系,主要是驅動和硬體的支持。
『肆』 android jni 使用第三方提供的.so庫及所對應的jar包
1.將SO文件直接放到libs/armeabi下,然後代碼中System.loadLibrary("xxx");再public native static int xxx_xxx_xxx();接下來就可以直接調用xxx_xxx_xxx()方法;
2.第二種方案,創建自己的SO文件,在自己的SO文件里調用第三方SO,再在程序中調用自己的SO,這種比較復雜,需要建java類文件,生成.h文件,編寫C源文件include之前生成的.h文件並實現相應方法,最後用android NDK開發包中的ndk-build腳本生成對應的.so共享庫。 http://www.ijiami.cn/newsInfo?id=293&v=3
2. DEX加殼保護,DEX指令動態載入保護和高級源碼混淆保護。其中DEX加殼保護是「愛加密」主推的賣點,該技術通過將DEX文件隱藏,並生成一個類似於虛像的殼文件,阻止黑客利用反編譯工具獲取App源碼。另外,愛加密http://www.ijiami.cn/推出了so庫保護,使得C/C++ 層面的代碼安全也得到防護。加上資源文件保護(圖片、音頻等文件的防查看和防修改)、xml 主配文件保護(對主配文件進行二次簽名)、內存保護等措施,可以基本保證App的動態和靜態安全。
『伍』 如何在Android下使用JNI
1.引言
我們知道,Android系統的底層庫由c/c++編寫,上層Android應用程序通過Java虛擬機調用底層介面,銜接底層c/c++庫與Java應用程序間的介面正是JNI(JavaNative Interface)。本文描述了如何在ubuntu下配置AndroidJNI的開發環境,以及如何編寫一個簡單的c函數庫和JNI介面,並通過編寫Java程序調用這些介面,最終運行在模擬器上的過程。
2.環境配置
2.1.安裝jdk1.6
(1)從jdk官方網站下載jdk-6u29-linux-i586.bin文件。
(2)執行jdk安裝文件
[html] view plainprint?
01.$chmod a+x jdk-6u29-linux-i586.bin
02.$jdk-6u29-linux-i586.bin
$chmod a+x jdk-6u29-linux-i586.bin
$jdk-6u29-linux-i586.bin
(3)配置jdk環境變數
[html] view plainprint?
01.$sudo vim /etc/profile
02.#JAVAEVIRENMENT
03.exportJAVA_HOME=/usr/lib/java/jdk1.6.0_29
04.exportJRE_HOME=$JAVA_HOME/jre
05.exportCLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
06.exportPATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
$sudo vim /etc/profile
#JAVAEVIRENMENT
exportJAVA_HOME=/usr/lib/java/jdk1.6.0_29
exportJRE_HOME=$JAVA_HOME/jre
exportCLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
exportPATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
保存後退出編輯,並重啟系統。
(4)驗證安裝
[html] view plainprint?
01.$java -version
02.javaversion "1.6.0_29"
03.Java(TM)SE Runtime Environment (build 1.6.0_29-b11)
04.JavaHotSpot(TM) Server VM (build 20.4-b02, mixed mode)
05.$javah
06.用法:javah[選項]<類>
07.其中[選項]包括:
08.-help輸出此幫助消息並退出
09.-classpath<路徑>用於裝入類的路徑
10.-bootclasspath<路徑>用於裝入引導類的路徑
11.-d<目錄>輸出目錄
12.-o<文件>輸出文件(只能使用-d或-o中的一個)
13.-jni生成JNI樣式的頭文件(默認)
14.-version輸出版本信息
15.-verbose啟用詳細輸出
16.-force始終寫入輸出文件
17.使用全限定名稱指定<類>(例
18.如,java.lang.Object)。
$java -version
javaversion "1.6.0_29"
Java(TM)SE Runtime Environment (build 1.6.0_29-b11)
JavaHotSpot(TM) Server VM (build 20.4-b02, mixed mode)
$javah
用法:javah[選項]<類>
其中[選項]包括:
-help輸出此幫助消息並退出
-classpath<路徑>用於裝入類的路徑
-bootclasspath<路徑>用於裝入引導類的路徑
-d<目錄>輸出目錄
-o<文件>輸出文件(只能使用-d或-o中的一個)
-jni生成JNI樣式的頭文件(默認)
-version輸出版本信息
-verbose啟用詳細輸出
-force始終寫入輸出文件
使用全限定名稱指定<類>(例
如,java.lang.Object)。2.2.安裝android應用程序開發環境
ubuntu下安裝android應用程序開發環境與windows類似,依次安裝好以下軟體即可:
(1)Eclipse
(2)ADT
(3)AndroidSDK
與windows下安裝唯一不同的一點是,下載這些軟體的時候要下載Linux版本的安裝包。
安裝好以上android應用程序的開發環境後,還可以選擇是否需要配置emulator和adb工具的環境變數,以方便在進行JNI開發的時候使用。配置步驟如下:
把emulator所在目錄android-sdk-linux/tools以及adb所在目錄android-sdk-linux/platform-tools添加到環境變數中,android-sdk-linux指androidsdk安裝包android-sdk_rxx-linux的解壓目錄。
[plain] view plainprint?
01.$sudo vim /etc/profile
02.exportPATH=~/software/android/android-sdk-linux/tools:$PATH
03. exportPATH=~/software/android/android-sdk-linux/platform-tools:$PATH
$sudo vim /etc/profile
exportPATH=~/software/android/android-sdk-linux/tools:$PATH
exportPATH=~/software/android/android-sdk-linux/platform-tools:$PATH
編輯完畢後退出,並重啟生效。
2.3.安裝NDK
NDK是由android提供的編譯android本地代碼的一個工具。
(1)從androidndk官網http://developer.android.com/sdk/ndk/index.html下載ndk,目前最新版本為android-ndk-r6b-linux-x86.tar.bz2.
(2)解壓ndk到工作目錄:
[plain] view plainprint?
01.$tar -xvf android-ndk-r6b-linux-x86.tar.bz2
02.$sudo mv android-ndk-r6b /usr/local/ndk
$tar -xvf android-ndk-r6b-linux-x86.tar.bz2
$sudo mv android-ndk-r6b /usr/local/ndk
(3)設置ndk環境變數
[plain] view plainprint?
01.$sudo vim /etc/profile
02.exportPATH=/usr/local/ndk:$PATH
$sudo vim /etc/profile
exportPATH=/usr/local/ndk:$PATH
編輯完畢後保存退出,並重啟生效
(4)驗證安裝
[plain] view plainprint?
01.$ cd/usr/local/ndk/samples/hello-jni/
02.$ ndk-build
03.Gdbserver : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
04.Gdbsetup : libs/armeabi/gdb.setup
05.Install : libhello-jni.so => libs/armeabi/libhello-jni.so
$ cd/usr/local/ndk/samples/hello-jni/
$ ndk-build
Gdbserver : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
Gdbsetup : libs/armeabi/gdb.setup
Install : libhello-jni.so => libs/armeabi/libhello-jni.so
3.JNI實現
我們需要定義一個符合JNI介面規范的c/c++介面,這個介面不用太復雜,例如輸出一個字元串。接下來,則需要把c/c++介面的代碼文件編譯成共享庫(動態庫).so文件,並放到模擬器的相關目錄下。最後,啟動Java應用程序,就可以看到最終效果了。
3.1.編寫Java應用程序代碼
(1)啟動Eclipse,新建android工程
Project:JNITest
Package:org.tonny.jni
Activity:JNITest
(2)編輯資源文件
編輯res/values/strings.xml文件如下:編輯res/layout/main.xml文件
我們在主界面上添加了一個EditText控制項和一個Button控制項。
(3)編輯JNITest.java文件
static表示在系統第一次載入類的時候,先執行這一段代碼,在這里表示載入動態庫libJNITest.so文件。
再看這一段:
[java] view plainprint?
01.privatenativeString GetReply();
privatenativeString GetReply();
native表示這個方法由本地代碼定義,需要通過jni介面調用本地c/c++代碼。
[java] view plainprint?
01.publicvoidonClick(View arg0) {
02.edtName.setText(reply);
03.}
publicvoidonClick(View arg0) {
edtName.setText(reply);
}
這段代碼表示點擊按鈕後,把native方法的返回的字元串顯示到EditText控制項。
(4)編譯工程,生成.class文件。
3.2.用javah工具生成符合JNI規范的c語言頭文件
在終端中,進入android工程所在的bin目錄
[plain] view plainprint?
01.$cd ~/project/Android/JNITest/bin
$cd ~/project/Android/JNITest/bin
我們用ls命令查看,可以看到bin目錄下有個classes目錄,其目錄結構為classes/org/tonny/jni,即classes的子目錄結構是android工程的包名org.tonny.jni。請注意,下面我們准備執行javah命令的時候,必須進入到org/tonny/jni的上級目錄,即classes目錄,否則javah會提示找不到相關的java類。
下面繼續:
[plain] view plainprint?
01.$cd classes
02.$javah org.tonny.jni.JNITest
03.$ls
04.org org_tonny_jni_JNITest.h
$cd classes
$javah org.tonny.jni.JNITest
$ls
org org_tonny_jni_JNITest.h
執行javahorg.tonny.jni.JNITest命令,在classes目錄下會生成org_tonny_jni_JNITest.h頭文件。如果不進入到classes目錄下的話,也可以這樣:
[plain] view plainprint?
01.$javah -classpath ~/project/Android/JNITest/bin/classesorg.tonny.jni.JNITest
$javah -classpath ~/project/Android/JNITest/bin/classesorg.tonny.jni.JNITest
-classpath 參數表示裝載類的目錄。
3.3.編寫c/c++代碼
生成org_tonny_jni_JNITest.h頭文件後,我們就可以編寫相應的函數代碼了。下面在android工程目錄下新建jni目錄,即~/project/Android/JNITest/jni,把org_tonny_jni_JNITest.h頭文件拷貝到jni目錄下,並在jni目錄下新建org_tonny_jni_JNITest.c文件,編輯代碼如下:
[cpp] view plainprint?
01.#include<jni.h>
02.#include<string.h>
03.#include"org_tonny_jni_JNITest.h"
04.
05.
06.JNIEXPORTjstring JNICALLJava_org_tonny_jni_JNITest_GetReply
07.(JNIEnv *env, jobject obj){
08.return(*env)->NewStringUTF(env,(char*)"Hello,JNITest");
09.}
#include<jni.h>
#include<string.h>
#include"org_tonny_jni_JNITest.h"
JNIEXPORTjstring JNICALLJava_org_tonny_jni_JNITest_GetReply
(JNIEnv *env, jobject obj){
return(*env)->NewStringUTF(env,(char*)"Hello,JNITest");
}
我們可以看到,該函數的實現相當簡單,返回一個字元串為:"Hello,JNITest"
3.4.編寫Android.mk文件
在~/project/Android/JNITest/jni目錄下新建Android.mk文件,android可以根據這個文件的編譯參數編譯模塊。編輯Android.mk文件如下:
[plain] view plainprint?
01.LOCAL_PATH:= $(call my-dir)
02.include$(CLEAR_VARS)
03.LOCAL_MODULE := libJNITest
04.LOCAL_SRC_FILES:= org_tonny_jni_JNITest.c
05.include$(BUILD_SHARED_LIBRARY)
LOCAL_PATH:= $(call my-dir)
include$(CLEAR_VARS)
LOCAL_MODULE := libJNITest
LOCAL_SRC_FILES:= org_tonny_jni_JNITest.c
include$(BUILD_SHARED_LIBRARY)
LOCAL_MODULE表示編譯的動態庫名稱
LOCAL_SRC_FILES 表示源代碼文件
3.5.用ndk工具編譯並生成.so文件
進入到JNITest的工程目錄,執行ndk-build命令即可生成libJNITest.so文件。
[plain] view plainprint?
01.$cd ~/project/Android/JNITest/
02.$ndk-build
03.Invalidattribute name:
04.package
05.Install : libJNITest.so => libs/armeabi/libJNITest.so
$cd ~/project/Android/JNITest/
$ndk-build
Invalidattribute name:
package
Install : libJNITest.so => libs/armeabi/libJNITest.so
可以看到,在工程目錄的libs/armeabi目錄下生成了libJNITest.so文件。
3.6.在模擬器上運行
(1)首先,我們把android模擬器啟動起來。進入到emulator所在目錄,執行emulator命令:
[plain] view plainprint?
01.$cd ~/software/android/android-sdk-linux/tools
02.$./emulator @AVD-2.3.3-V10 -partition-size 512
$cd ~/software/android/android-sdk-linux/tools
$./emulator @AVD-2.3.3-V10 -partition-size 512
AVD-2.3.3-V10表示你的模擬器名稱,與在Eclipse->AVDManager下的AVDName對應,-partition-size表示模擬器的存儲設備容量。
(2)接下來,我們需要把libJNITest.so文件拷貝到模擬器的/system/lib目錄下,執行以下命令:
[plain] view plainprint?
01.$cd ~/project/Android/JNITest/libs/armeabi/
02.$adb remount
03.$adb push libJNITest.so /system/lib
04.80 KB/s (10084 bytes in 0.121s)
$cd ~/project/Android/JNITest/libs/armeabi/
$adb remount
$adb push libJNITest.so /system/lib
80 KB/s (10084 bytes in 0.121s)
當在終端上看到有80 KB/s (10084 bytes in 0.121s)傳輸速度等信息的時候,說明拷貝成功。
(3)在終端上執行JNITest程序,這個我們可以在Eclipse下,右鍵點擊JNITest工程,RunAs->Android Application,即可在模擬器上啟動程序