前言
前兩天因為開發一個app更新的功能,我將從服務器下載的apk文件放在了內部存儲目錄(測試手機為小米,路徑為:data/user/0//files)下面,然后安裝的時候一直安裝不了,提示解析包出錯。后來查詢發現,安裝apk是調用了,沒有相關權限,這個無法獲取內部路徑,所以會安裝不了。借機也復習了一遍Android下面存儲相關的知識點,總結一番。
存儲分類
對于Android存儲目錄,我總結成一張思維導圖。上面這張圖很清楚的展示了Android存儲的目錄,接下來我們詳細分析每一個目錄。
內部存儲位于系統中很特殊的一個位置,對于設備中每一個安裝的 App,系統都會在 data/data//xxx 自動創建與之對應的文件夾。如果你想將文件存儲于內部存儲中,那么文件默認只能被你的應用訪問到,且一個應用所創建的所有文件都在和應用包名相同的目錄下。也就是說應用創建于內部存儲的文件,與這個應用是關聯起來的。當一個應用卸載之后,內部存儲中的這些文件也被刪除。對于這個內部目錄,用戶是無法訪問的,除非獲取root權限。
String fileDir = this.().();
String = this.().();
一般情況下,我們獲取到的路徑為data/data//xxx,小米手機下面打印出來的結果如下:
對于內部存儲路徑,我們一般通過以下兩種方式獲取,內部存儲空間的獲取都需要使用Context:
context.()
對應內部存儲的路徑為: data/data//files,但是對于有的手機如:華為,小米等獲取到的路徑為:data/user/0//files
context.()
對應內部存儲的路徑為: data/data//cache,但是對于有的手機如:華為,小米等獲取到的路徑為:data/user/0//cache應用程序的緩存目錄,該目錄內的文件在設備內存不足時會優先被刪除掉,所以存放在這里的文件是沒有任何保障的,可能會隨時丟掉。
針對于外部存儲比較容易混淆,因為在.4以前,手機機身存儲就叫內部存儲,插入的SD卡就是外部存儲,但是在.4以后的話,就目前而言,現在的手機自帶的存儲就很大,現在.0的話,有的手機能達到256G的存儲,針對于這種情況,手機機身自帶的存儲也是外部存儲,如果再插入SD卡的話也叫外部存儲,因此對于外部存儲分為兩部分:SD卡和擴展卡內存
我們通過一段代碼來獲取手機的外部存儲目錄,我們用的測試手機是三星G4,帶有插入SD卡的:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
File[] files = getExternalFilesDirs(Environment.MEDIA_MOUNTED);
for (File file : files) {
Log.e("file_dir", file.getAbsolutePath());
}
}
對于以上代碼,打印的結果如下:
打印出兩行目錄,第一行目錄是機身自帶的外部存儲目錄,目錄結構為:/storage//0/Android/data//files 第二行是存儲卡的目錄結構,路徑為:/storage//Android/data//files
擴展外部存儲
此目錄路徑需要通過context來獲取,同時在app卸載之后,這些文件也會被刪除。類似于內部存儲。
()
對應外部存儲路徑:/storage//0/Android/data//cache
(String type)
對應外部存儲路徑:/storage//0/Android/data//files
SD卡存儲
SD卡里面的文件是可以被自由訪問,即文件的數據對其他應用或者用戶來說都是可以訪問的,當應用被卸載之后,其卸載前創建的文件仍然保留。
對于SD卡上面的文件路徑需要通過獲取,同時在獲取前需要判斷SD的狀態:
SD卡未知
SD卡移除
SD卡未安裝
SD卡檢查中,剛裝上SD卡時
SD卡為空白或正在使用不受支持的文件系統
SD卡安裝
NLY SD卡安裝但是只讀
SD卡共享
SD卡移除錯誤
存在SD卡但是不能掛載,例如發生在介質損壞
String externalStorageState = Environment.getExternalStorageState();
if (externalStorageState.equals(Environment.MEDIA_MOUNTED)){
//sd卡已經安裝,可以進行相關文件操作
}
rectory()
對應外部存儲路徑:/storage//0
(String type)
獲取外部存儲的共享文件夾路徑如:
音樂目錄
圖片目錄
電影目錄
下載目錄
相機拍照或錄像文件的存儲目錄
文件文檔目錄
String externalStoragePublicDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath();
以上便是獲取相機DCIM目錄,對應獲取的路徑為:/storage//0/DCIM。
()
對應獲取系統分區根路徑:/system
()
對應獲取用戶數據目錄路徑:/data
ctory()
對應獲取用戶緩存目錄路徑:/cache
相關概念區別
這兩個都位于內部存儲目錄/data/data//下面,位于同一級別,前者是file目錄下面,后面是cache目錄下。
前者位于內部存儲目錄/data/data//file下面,后者位于外部存儲目錄/storage//0/Android/data//files下面,它們都存在于應用包名下面,也就是說屬于app應用的,所以當app卸載后,它們也會被刪除的。
對于前面提到的app下載升級功能,我們從服務器端下載的app需要放到外部存儲目錄下面,而不是內部存儲目錄,因為內部存儲目錄的空間很小。另外我也做了相關測試,如果將apk放到內部存儲目錄file下面的話,安裝時會出現問題,提示解析包出錯。
在app中有清除數據和清除緩存這兩個概念,那么這兩者分別清除的是什么目錄下面的數據呢?
清除數據
清除數據清除的是保存在app中所有數據,就是上面提到的位于下面的所有文件,包含內部存儲(/data/data//)和外部存儲(/storage//0/Android/data//)。當然除了SD卡上面的數據,SD卡上面的數據當app卸載之后還會存在的。
清除緩存
緩存是程序運行時的臨時存儲空間,它可以存放從網絡下載的臨時圖片,從用戶的角度出發清除緩存對用戶并沒有太大的影響,但是清除緩存后用戶再次使用該APP時,由于本地緩存已經被清理,所有的數據需要重新從網絡上獲取。為了在清除緩存的時候能夠正常清除與應用相關的緩存,請將緩存文件存放在()或者 ()路徑下。
以上便是Android系統中管存儲目錄的一些知識。
Ubuntu 18.04 AOSP源碼編譯詳盡指南
筆者簡介:
金融行業、互聯網行業信息安全從業劃水10年+;
略懂一點技術;
數據安全治理運營;
1 編譯環境準備
1.1 磁盤空間
預留足夠大的硬盤空間,從實際體驗來看,512g緊張,1T比較合適,所以建議至少配置超過1T的硬盤空間。
1.2操作系統準備
安裝純凈的Ubuntu 18.04虛擬機操作系統,將虛擬機內存設置大一點,筆者PC機物理總內存為32G,分配給了虛擬機24G,內存分配越大,CPU越好,編譯越快。
如果物理內存太小,為了防止編譯過程中因為Ubuntu內存太小報錯,可考慮設置SWAP分區,增加SWAP分區方法如下:
dd if=/dev/zero of=/root/swapfile bs=1G count=16 //創建交換分區的文件,這里設置swap分區為16G:bs為塊大小,每個塊為1G;
mkswap /root/swapfile
swapon /root/swapfile ??????????????????
如果要SWAP在系統開機時自啟動,要在文件/etc/fstab中添加一行
使用free -h或者htop查看配置的SWAP分區是否生效
擴展硬盤,硬盤分配450G;
VMWare上擴展磁盤后,Ubuntu 操作系統還不能識別,需要通過gparted來擴展原來分區,也可以新建一個分區,用來存放AOSP源代碼。
a、采用擴展分區
下面圖例直接是擴展原始分區,拖動橫條,完成硬盤預擴展
執行擴展操作,完成分配
b、采用新建分區
首先要滿足該分區足夠大,另外需要通過mount命令手動掛載分區,比如掛載到桌面的COMPILE目錄下:
1.3虛擬機基礎設置
編譯過程時間長,可能會休眠,所以設置關閉息屏、關閉休眠、時區也設置下
時區設置,選擇Asia-
1.4 安裝編譯工具及相關依賴
更新apt源
root@ubuntu:/etc/apt#cp?sources.list?sources.list.bak??#?備份原始list
root@ubuntu:/etc/apt#vi /etc/apt/sources.list # 新建一個list從(https://www.jianshu.com/p/6dee223ac93e)選擇一種源寫入sources.list文件中
sudo apt-get update # 更新
安裝工具
安裝adb與fastboot
# sudo apt-get -y install adb fastboot
安裝curl
# sudo apt-get -y install curl
git下載和配置
#?sudo?apt-get?install?git
#?git?config?--global?user.email?"郵箱"
#?git?config?--global?user.name?"xxx"
repo下載安裝
# curl https://storage.googleapis.com/git-repo-downloads/repo > /usr/bin/repo
#?chmod?a+x?/usr/bin/repo
將repo訪問的資源修改為清華源,在~/.bashrc文末添加配置,示例如下:
openjdk安裝,編譯不同的版本需要不同的JDK,可在源碼目錄下的/build/core/main.mk文件中查看編譯所依賴的JDK版本
常見的JDK依賴如下:
Android 7.0 (Nougat) 以上:OpenJDK 8
Android 5.x (Lollipop)?– Android 6.0?(Marshmallow):OpenJDK 7
Android 2.3.x (Gingerbread) - Android 4.4.x(KitKat):Java JDK 6
Android 1.5 (Cupcake) - Android 2.2.x (Froyo): Java JDK 5
Ubuntu中安裝JDK,筆者編譯AOSP 版本為,所以選擇
# sudo apt-get install openjdk-8-jdk
安裝AOSP編譯依賴
sudo apt-get install gnupg flex bison gperf build-essential zip gcc-multilib g++-multilib
sudo apt-get install libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev
sudo apt-get install lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4
sudo apt-get install libreadline6-dev:i386 libncurses5-dev:i386
sudo?apt-get?install?zlib1g-dev:i386??zlib1g-dev
sudo apt-get install tofrodos python-markdown
sudo apt-get install dpkg-dev libsdl1.2-dev
sudo apt-get install libx11-dev libx11-dev:i386
sudo?apt-get?install?libssl-dev
sudo apt-get install libesd0-dev //可能需要新的源,如下圖
截至目前,基礎環境配置完成,可以選擇打一個快照,方便后續有問題還原。
2 AOSP源碼下載
本文以編譯源碼為例,下載AOSP源碼方式有2種,根據需求選擇其中一種下載即可。
2.1通過清華鏡像初始化包下載
下載量很大,很慢,但很全,網絡好的情況下,筆者覺得沒必要采用此種方式。
2.1.1通過清華鏡像初始化包下載(檢出)最新版本源代碼
wget?-c?https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar???#?下載初始化包
tar -xvf aosp-latest.tar # 執行解壓操作,解壓后可刪除aosp-latest.tar
cd AOSP # 解壓得到的 AOSP 工程目錄,里面只有一個隱藏的 .repo 目錄,這里面包含了所有版本的倉庫管理腳本及相關工具,所以從這里可以檢出任意版本代碼
repo sync -c -j4 # 在未通過repo init 指定分支時,默認為master分支,即最新版本的Android源碼,同步一遍即可得到最新版本的Android源代碼
2.1.2通過清華鏡像初始化包下載(檢出)指定版本源代碼
首先在 先查詢分支與對應可安裝設備,記錄下Build ID和tag值
wget -c https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar # 下載初始化包
tar?-xvf?aosp-latest.tar???????#?執行解壓操作
cd?aosp??????????????????#?解壓得到的?AOSP?工程目錄
cd .repo/manifests # 進入manifests 目錄
root@ubuntu:~/Desktop/COMPILE/aosp/.repo/manifests
#git branch -a | cut -d / -f 3 # 查看aosp-latest可以下載(檢出)哪些版本代碼
root@ubuntu:~/Desktop/COMPILE/aosp#repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-9.0.0_r9 --depth=1 --platform=auto # 初始化倉庫,指定版本,版本號為前面記錄的Tag值
root@ubuntu:~/Desktop/COMPILE/aosp#repo sync -c -j4 # 下載指定版本代碼到本地
2.2直接下載AOSP源碼
直接下載指定版本的AOSP,家里帶寬比較好的條件下,推薦此種方式,比如1000M帶寬,下載aosp 31G代碼只需要不到15分鐘,如果帶寬小,則下載時間很長,且容易斷,則不推薦該方式
首先在 先查詢分支與對應可安裝設備,記錄下Build ID和tag值
mkdir AOSP
cd AOSP
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-9.0.0_r9 --depth=1 --platform=auto# 初始化倉庫,指定版本,版本號為前面記錄的Tag值
repo sync -c -j4# 只下載當前分支代碼
1000M帶寬下,僅用13分鐘下載完成
3下載驅動
如果編譯好的AOSP要刷真機,則需要驅動,模擬器不需要驅動,aosp提供的僅僅是源碼,要刷真機,還需google的vender和高通的驅動,下載地址:,具體下載項需要根據Build ID、機型判斷
下載完成后,里面是shell腳本,執行shell腳本,兩個腳本產生的文件都會寫入vender目錄,然后將該目錄放到aosp的根目錄下,這個目錄最終會編譯生產vender.img鏡像
4 編譯AOSP源碼
cd到AOSP源碼目錄
root@ubuntu:~/Desktop/COMPILE/aosp# source build/envsetup.sh // 要先執行這步,不然找不到make命令
root@ubuntu:~/Desktop/COMPILE/aosp# lunch
lunch命令后選擇所需要編譯的目標的格式,編譯目標的格式組成為BUILD-,比如-eng的BUILD為,為eng,其中BUILD表示編譯出的鏡像可以運行在什么環境,aosp代表Android開源項目,arm表示系統是運行在arm架構的處理器上,筆者手機是pixel 3XL,,這里以編譯為例,所以選擇14。
root@ubuntu:~/Desktop/COMPILE/aosp#?make?-j4?//編譯命令
第一次編譯,我用的4個線程,耗時4小時,后來升級了PC機,改成16線程,時間縮短到2小時,下圖是第一次編譯,差不多4小時
鏡像位置(/out/target/product/
/)
鏡像說明
4鏡像刷機
將手機連接到虛擬機
設置變量的值
為了避免每次啟動了系統后去設置變量,可以將寫入/etc/profile配置文件中。
以模式啟動手機
# adb reboot bootloader
# fastboot devices
刷入鏡像
只刷system鏡像
# fastboot flash system system.img #只刷系統鏡像刷所有鏡像
完整刷入
# fastboot flashall -w // -w 是雙清(Cache分區和Data分區),fastboot flashall命令會在ANDROID_PRODUCT_OUT目錄中查找所有img文件,將這些img文件燒寫到所有對應的分區中,并重新啟動手機
*請認真填寫需求信息,我們會在24小時內與您取得聯系。