APK(Android package,wiki chs):android安裝包,由aapt(Android Assert Packaging Tool,已集成到build-tools工具集中)把AndroidManifest.xml、資源文件、lib動態鏈接庫、dex(Dalvik二進制字節碼)等歸檔成的zip壓縮包。
assets:對應項目工程asset目錄下的文件,可以使用AssetManager獲取 注:其下的main.obb.png為一個壓縮方式為僅存儲的標准zip文件
lib:包含適用於不同處理器的第三方動態鏈接庫,這里邊可以有多個子目錄。如:armeabi、armeabi-v7a、 arm64-v8a,、x86,、x86_64以及mips
METE-INF:存放簽名證書等信息;其中包含兩個簽名文件(CERT.SF和CERT.RSA)和一個manifest文件(MANIFEST.MF)
jdk1.8.0_77\bin\keytool.exe -printcert -file %apkdir%\CERT.RSA // 查看當前apk的簽名信息
res:包含那些沒有被編譯到resources.arsc的資源(如:應用圖標、字符串表等)
AndroidManifest.xml:二進制格式的manifest文件
classes*.dex:Dalvik EXcutable file,Dalvik虛擬機執行程序,java文件先編譯為class文件,然后打包成dex二進制字節碼文件。一個APK中有多個dex文件。
resources.arsc:存儲編譯好的資源,包括項目工程中的res/values目錄里的xml文件,它們都被編譯成二進制格式,也包括一些路徑,指向那些沒有被編譯的資源,比如layout文件和圖片
Android系統目錄結構
- /init 系統啟動文件
- /bin 常用的系統本地命令(二進制) 如:du、ls、mv等
- /system
- build.prop 系統設置和變更屬性
- app 安裝的系統應用所在的目錄
- bin 常用的系統本地命令(二進制) 如:ps、cp、rm等
- etc 系統配置文件
- hosts 用於配置IP或域名的重定向文件
- hosts 用於配置IP或域名的重定向文件
- font 字體目錄
- framework Java平台架構核心庫,jar包和odex優化的文件
- lib 32位系統底層共享庫,.so庫文件
- lib64 64位系統底層共享庫,.so庫文件
- egl
- libGLES_android.so
- libart-compiler.so
- libart-dexlayout.so
- libart.so
- libc++.so
- libc.so
- libstdc++.so
- lib_malloc_debug.so
- lib_malloc_hooks.so
- libEGL.so
- libGLESv1_CM.so
- libGLESv2.so
- libGLESv3.so
- ... ...
- egl
- xbin 不常用的系統管理工具,相當於linux的/sbin
- media
- audio 鈴聲,提示音等音頻文件, .ogg
- notifications 通知
- ui 界面
- alarms 警告
- ringtones 鈴聲
- audio 鈴聲,提示音等音頻文件, .ogg
- usr 用戶文件夾,包含共享、鍵盤布局、時間區域
- keychars
- keylayout
- share
- srec 配置
- ......
- vendor 廠商文件
- build.prop
- app 廠商自帶應用所在目錄
- bin 廠商自帶命令工具
- etc
- lib
- lib64
- egl
- eglSubDriverAndroid.so
- libGL_adreno.so
- libGLESv1_CM_adreno.so
- libGLESv2_adreno.so
- libq3dtools_adreno.so
- libq3dtools_esx.so
- libQTapGLES.so
- libjson.so
- ... ...
- egl
- /etc --> 軟鏈接指向 /system/etc
- /vendor --> 軟鏈接指向 /system/vendor
- /dev 存放設備節點文件
- /proc 全局系統信息
- /data 用戶軟件和各種數據
- local/tmp 臨時目錄,無權限要求
- app 普通程序安裝目錄
- data
- <package_name>
- files Context.getFilesDir() ,Context.openFileOutput() 獲取的目錄,應用安裝目錄下
- cache Context.getCacheDir() 獲取的目錄,應用安裝目錄下,系統會自動在內存不足或目錄大小達到特定數值時自動清理。
- shared_pref Context.getSharedPreferences() 建立的preferences文件(xml)存放目錄
- <package_name>
- anr 應用發生ANR(Applicaiton is Not Responding)時,Android將問題點的堆棧寫入到traces.txt文件中
- property 其中persist.sys.timezone記錄系統時區
- /sdcard --> 軟鏈接 SD卡的FAT32文件系統掛載到此目錄
- Android
- data
- <package_name> 應用的額外數據,應用卸載時自動刪除。
- files Context.getExternalFilesDir()獲取的目錄。設置->應用->具體應用詳情-> 清除數據 操作對象就是這個目錄。
- cache Context.getExternalCacheDir()獲取的緩存目錄。設置->應用->具體應用詳情-> 清除緩存 操作對象就是這個目錄。
- <package_name> 應用的額外數據,應用卸載時自動刪除。
- data
- Android
可在Android Studio的View菜單 -- Tool Windows -- Device File Explorer面板中查看手機上整個文件目錄(手機無需root 更多信息詳見這里)
注:文件夾圖標的右上角帶箭頭為一個軟鏈接,右下角帶問號的為一個文件
內部存儲(Internal Storage) // 在手機內部,屬於手機自帶存儲空間的一部分
/data/app // 應用程序安裝的目錄。安裝時,系統的PackageManagerService(PMS)進程會把apk文件復制到該目錄
1. com.tencent.mf.test1-S72Tv4IGEow5LtbwxPQHpQ== // 字符串S72Tv4IGEow5LtbwxPQHpQ是隨機字符串,每次安裝都會變化
2. base.apk為原始的Android安裝包。app運行時的資源從該文件中讀取。
3. 在安裝apk時,PMS會將apk中的so動態鏈接庫釋放到/data/app/com.tencent.mf.test1-S72Tv4IGEow5LtbwxPQHpQ==/lib/arm64中
游戲so動態鏈接庫的路徑搜索路徑依次為:/data/app/com.tencent.mf.test1-S72Tv4IGEow5LtbwxPQHpQ==/lib/arm64, /data/app/com.tencent.mf.test1-S72Tv4IGEow5LtbwxPQHpQ==/base.apk!/lib/arm64-v8a, /system/lib64, /vendor/lib64, /product/lib64
4. 首次運行app時,會將apk中的classes*.dex編譯釋放到/data/app/com.tencent.mf.test1-S72Tv4IGEow5LtbwxPQHpQ==/oat/arm64中,會生成出3個文件:base.vdex、base.odex、base.art
.vdex:未壓縮DEX 代碼,以及一些旨在加快驗證速度的元數據(省去重新校驗apk中dex文件合法性的過程 )。Android 8引入。
.odex:對於dalvik虛擬機,存放的是JIT后的優化后的字節碼(Optimized Dalvik EXcutable file);對於AOT Runtime,存放的是經過AOT(Ahead Of Time)編譯后的本地機器碼(即:oat文件,一種私有的ELF文件格式)。
注1:為了保證安裝速度,在安裝時並沒有AOT;而是當app啟動運行一小段時間,收集了足夠多的jit 熱點方法信息時,
Android會在后台重新進行dex2oat(該文件在/system/bin/dex2oat,是Android Art Runtime的重要模塊), 將熱點函數(Hot Code)編譯成odex本地機器碼
注2:odex + vdex = 全部java源碼。隨着更多的vdex的java代碼被AOT成odex,其size會逐漸變小
.art (可選):包含APK中列出的某些字符串和類的 ART 內部表示,記錄app啟動熱點函數相關地址,用於加快app啟動速度。
/data/data // 該目錄存放應用程序的私有數據
對於設備中每一個安裝的 App,系統都會在內部存儲空間的 data/data 目錄下以應用包名為名字自動創建與之對應的文件夾。
用戶卸載 App 時,系統自動刪除 data/data 目錄下對應包名的文件夾及其內容。
data/data/包名/cache: 存放的 APP 的緩存信息
context.getCacheDir(); // 返回/data/data/包名/cache目錄路徑
data/data/包名/databases: 存放 APP 的數據庫信息
context.getDataDir(); // 返回/data/data/包名/databases目錄路徑 context.getDatabasePath(name); // 獲取指定數據庫對象 context.deleteDatabase(name); // 刪除指定數據庫對象
data/data/包名/files: 存放 APP 的文件信息
context.getFilesDir(); // 返回/data/data/包名/files目錄路徑 context.deleteFile(name); // 刪除指定文件對象 context.fileList(); // 查詢所有文件對象
data/data/包名/shared_prefs: 存放 APP 內的 SharedPreferences
context.getSharedPreferences(name,mode) //返回指定的SharedPreferences對象 context.deleteSharedPreferences(name) // 刪除指定的SharedPreferences
一些內部存儲的根目錄
Environment.getDataDirectory(); // 返回/data目錄 Environment.getDownloadCacheDirectory(); // 返回/cache目錄 Environment.getRootDirectory(); // 返回/system目錄
外部存儲(External Storage) // 非root下,只要是能看得到,都是外部存儲
該存儲可能是可移除的存儲介質(如:SD 卡)或內部(不可移除)存儲。 保存到外部存儲的文件是全局可讀取文件。當用USB連接到計算機並以傳輸文件后,可由用戶修改這些文件。
外部存儲在Android 文件系統中是/sdcard目錄(只是一個快捷方式),真正的目錄是 /storage/emulated/0 文件夾
/sdcard -> /storage/self/primary -> /mnt/user/0/primary -> /storage/emulated/0
注1:對於不同版本的Android系統,/sdcard指向的真正目錄有一些不同。
注2:Android設備一般都有內置 SD 卡,有一些設備同時也提供外置 SD 卡接口(用於插入的外置內存卡,其對應的路徑形如:/storage/AFE0-2E94)
Environment.getExternalStorageDirectory(); // 返回/storage/emulated/0目錄 Environment.getExternalStoragePublicDirectory(DIRECTORY_ALARMS); // 返回/storage/emulated/0/Alarms目錄 Environment.getExternalStoragePublicDirectory(DIRECTORY_DCIM); // 返回/storage/emulated/0/DCIM目錄 Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS); // 返回/storage/emulated/0/Download目錄 Environment.getExternalStoragePublicDirectory(DIRECTORY_MOVIES); // 返回/storage/emulated/0/Movies目錄 Environment.getExternalStoragePublicDirectory(DIRECTORY_MUSIC); // 返回/storage/emulated/0/Music目錄 Environment.getExternalStoragePublicDirectory(DIRECTORY_NOTIFICATIONS); // 返回/storage/emulated/0/Notifications目錄 Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES); // 返回/storage/emulated/0/Pictures目錄 Environment.getExternalStoragePublicDirectory(DIRECTORY_PODCASTS); // 返回/storage/emulated/0/Podcasts目錄 Environment.getExternalStoragePublicDirectory(DIRECTORY_RINGTONES); // 返回/storage/emulated/0/Ringtones目錄
/sdcard/Android/data/包名 // App外部存儲私有目錄
context.getExternalFilesDir(); //外部存儲私有目錄/sdcard/Android/data/包名/files UE4的FString GExternalFilePath全局變量即為該目錄 一般存儲長時間保存的數據 對應“設置”->“應用”-> “應用詳情”里面的“清除數據”選項 context.getExternalCacheDir(); //外部存儲私有目錄/sdcard/Android/data/包名/cache 一般存儲臨時緩存數據 對應“設置”->“應用”-> “應用詳情”里面的“清除緩存”選項
默認情況下,系統並不會自動創建外部存儲空間的應用私有目錄。開發人員需在需要時,通過 SDK 提供的 API 創建該目錄文件夾和操作文件夾內容
當用戶卸載 App 時,系統也會自動刪除外部存儲空間下的對應 App 私有目錄文件夾及其內容,不會留下垃圾。
/sdcard/Android/obb/包名 // App外部存儲obb目錄
context.getObbDir(); // 返回App的外部存儲obb目錄
/sdcard/UE4Game // UE4Game外部存儲目錄
在UE4Game外部存儲目錄中,Test1項目的目錄結構如下:
APK安裝的4種方式
① 系統應用安裝:開機時加載系統的APK和應用,沒有安裝界面
② 網絡下載應用安裝:通過各種market應用完成,沒有安裝界面
③ ADB工具安裝:即通過Android的SDK開發tools里面的adb.exe程序安裝,沒有安裝界面
注1:對應的window為:com.miui.securitycenter/com.miui.permcenter.install.AdbInstallActivity
注2:需要在【開發者選項】中打開【USB安裝】
注3:小米10手機可通過如下設置來關閉“USB安裝提示”的確認 -- step1:【開發者選項】中【關閉MIUI 優化】 step2:重啟手機 step3:【應用設置】--【授權管理】,右上角設置里面,關閉【USB安裝管理】
④ 通過第三方應用來安裝:通過SD卡里的APK文件安裝(比如雙擊APK文件觸發),有安裝界面,系統默認已經安裝了一個安裝卸載應用的程序(packageinstaller.apk)
APK安裝過程
1. 拷貝apk文件到指定目錄
在Android系統中,apk安裝文件是會被保存起來的,默認情況下,用戶安裝的apk首先會被拷貝到 /data/app 目錄下。/data/app目錄是用戶有權限訪問的目錄,在安裝apk的時候會自動選擇該目錄存放用戶安裝的文件。
而系統出廠的apk文件則被放到了 /system 分區下,包括 /system/app,/system/vendor/app,以及 /system/priv-app 等等,該分區只有Root權限的用戶才能訪問,這也就是為什么在沒有Root手機之前,我們無法刪除系統出廠的app的原因了。
2. 解壓apk,拷貝文件,創建應用的數據目錄
apk在安裝的時候,會將app的依賴的第三方動態鏈接庫拷貝到/data/app/包名-XXXXXXXXXXXXXX==/lib/平台名的目錄中。
然后,在/data/data/目錄下創建應用程序的數據目錄(以應用的包名命名),存放應用的相關數據,如數據庫、xml文件、cache、二進制的so動態庫等等。
3. 解析apk的AndroidManifinest.xml文件並寫入/data/system/packages.xml中
/data/system/packages.xml類似於Windows的注冊表,這個文件是在解析apk時由writeLP()創建的,里面記錄了系統的permissions,以及每個apk的name,codePath,flags,ts,version,uesrid等信息。
這些信息主要通apk的AndroidManifest.xml解析獲取,解析完apk后將更新信息寫入這個文件並保存,下次開機直接從里面讀取相關信息添加到內存相關列表中。當有apk升級,安裝或刪除時會更新這個文件。
<package name="com.tencent.mf.test1" codePath="/data/app/com.tencent.mf.test1-S72Tv4IGEow5LtbwxPQHpQ==" nativeLibraryPath="/data/app/com.tencent.mf.test1-S72Tv4IGEow5LtbwxPQHpQ==/lib" primaryCpuAbi="arm64-v8a" publicFlags="940097094" privateFlags="0" ft="173e7953470" it="173e795b2e4" ut="173e795b2e4" version="1" userId="10815" installer="com.miui.packageinstaller"> <sigs count="1" schemeVersion="2"> <cert index="34" key="3082033d30820225a003020102020425c2be86300d06092a864886f70d01010b0500304e310b300906035504061302636e310b3009060355040813026764310b300906035504071302737a310b3009060355040a13026d66310b3009060355040b13026d66310b3009060355040313026d663020170d3230303130363037343934385a180f32323933313032313037343934385a304e310b300906035504061302636e310b3009060355040813026764310b300906035504071302737a310b3009060355040a13026d66310b3009060355040b13026d66310b3009060355040313026d6630820122300d06092a864886f70d01010105000382010f003082010a0282010100b4455215e09e7cdb7830cebe51c0d79e6f5cb22e96d7ce11f3d1f40e1ef43be245f49fbabb1af8efeddb823dc7ca1273724421c478a315e01b57f69a3d642c062bd879e096904fb379692c6d62cb032b14d6ed687a53b620dcf6ddb925fea65bdad3eff2244786d3b22dbfb2e7cc77424336048c852b7e85bdf41d5a05da231528ae3bfebb6752a92cf895073b38c3b43e1f9f6d217d24bab868575b36d7efd29739ad5b34b4d7f53a9c2cbe2b8db349f730b0cda090b91e57a54cdc5803577ac84159f7144a69902f12bd8da4986a85aab9020bab076f5f2254fd57c75c3c8aaeb4b4eda6ba9c9369e08e77f4f99c801e8819c341743de17dce558470e5b19f0203010001a321301f301d0603551d0e0416041491e0d5be16fcfcfa80e39b370a70ec05236828ff300d06092a864886f70d01010b05000382010100919b40fc021831a196726201e528c4a3ceefce44890ec9c07e543b757e0a0fde0c1230c34e3883104ff7e3cac4d0fcf42dbb4cefaaf97853e04313d1a611b5198b8d969c00b041bb2de8484b4140c5d80a7bdcbe66bd03fbb37c78b794078fc5d512b0298144864691d01cbd12d3f052548c83cc6d76c62379ce1fe7b48c24af4f1cf0ddf35faa4f833ab556c60d1793a432cfb64e475fe01dad59417d1b6a3f97f24de881dc65842e361e2074edf23d80228ce5f242bd485dc60b43999c2328e11608376a60eacc9a0228356aa008a1d95c57d3526591dbd352aa46b06f9c21f90e1967a65ccd70859d9a420ee5b0cb62ca7ef18c4fa0da8534577e7677f7b8" /> </sigs> <perms> <item name="android.permission.MODIFY_AUDIO_SETTINGS" granted="true" flags="0" /> <item name="android.permission.BLUETOOTH" granted="true" flags="0" /> <item name="android.permission.INTERNET" granted="true" flags="0" /> <item name="com.android.vending.CHECK_LICENSE" granted="true" flags="0" /> <item name="android.permission.BLUETOOTH_ADMIN" granted="true" flags="0" /> <item name="android.permission.CHANGE_WIFI_STATE" granted="true" flags="0" /> <item name="android.permission.ACCESS_NETWORK_STATE" granted="true" flags="0" /> <item name="android.permission.VIBRATE" granted="true" flags="0" /> <item name="android.permission.ACCESS_WIFI_STATE" granted="true" flags="0" /> <item name="android.permission.WAKE_LOCK" granted="true" flags="0" /> </perms> <proper-signing-keyset identifier="577" /> </package>
4. 顯示icon圖標
Launcher應用程序負責從PackageManagerService服務中把這些安裝好的App取出來,並以快捷圖標的方式在桌面上展現出來。
如小米10上的Launcher window為:com.miui.home/.launcher.Launcher
SIM卡
SIM卡即電話芯片卡,對應某個手機號,上面也能存放一些個人隱私數據:如聯系人、短信等。
第三方App必須申請相應的權限才能訪問SIM卡上數據。
參考