平板实现app2sd功能
平臺:android4.0
場景:平板上都默認(rèn)不插入SD卡,所以會將mnt/sdcard指向flash上分出來的某個塊,即使默認(rèn)的app2sd功能存在,也是一個假象。
時間:2012.5.25
android在2.2后開始支持,專門在vold里面添加了const char *Volume::SEC_STGDIR = “/mnt/secure/staging”。
單獨(dú)討論手機(jī)的情況,手機(jī)的SD卡對應(yīng)的就是mnt/sdcard.因此在sd卡進(jìn)行掛載的時候,首先會把sd設(shè)備掛載到/mnt/secure/staging下,然后將sd設(shè)備上的android_secure文件改成.android_secure文件,同時映射到/mnt/secure/asec下。掛載的最后,將sd卡掛載到mnt/sdcard上,同時移除/mnt/secure/staging,即umount掉。
此時/mnt/secure/asec依然映射到sd卡設(shè)備的.android_secure文件。
當(dāng)進(jìn)行app2sd操作的時候,會將app移動到.android_secure文件中,同時將.android_secure文件中的apk文件改名為xxxx.asec,并映射到mnt/asec下。(此時.android_secure文件中的apk名字并未變化,mnt/asec下只是改了名字的一個映射,此路徑被uri使用)。
上述實(shí)現(xiàn)的關(guān)鍵函數(shù)是createBindMounts()函數(shù)。同時關(guān)于asec的操作定義在VolumeManager.cpp中。
其提供給CommandListener::AsecCmd::runCommand()使用。此處為socket調(diào)用,client端位于框架的MountService,使得上層可以根據(jù)情況進(jìn)行調(diào)用。
關(guān)于平板,基本上將flash(即真實(shí)flash的一個block區(qū)域)掛載到了mnt/sdcard路徑,從而上述的相關(guān)操作,都在flash上面進(jìn)行了。因此在平板上的app2sd其實(shí)是一個假象。而關(guān)于還原其真實(shí)情況,需要做的事情比較簡單:在vold進(jìn)行mountVol()的時候,我們可以根據(jù)不同的設(shè)備(flash,真實(shí)sdcard)的label進(jìn)行區(qū)分處理。當(dāng)是真實(shí)的sdcard的時候,我們才使用mnt/secure/staging的相關(guān)操作,而關(guān)于flash的掛載,我們僅僅直接mount,即使用Fat::doMount(devicePath, getMountpoint()。這樣,app2sd功能在平板上就是真實(shí)實(shí)現(xiàn)了,同時僅僅在平板插入sdcard的時候起作用。當(dāng)然,還需要記得清理asce相關(guān)的操作上進(jìn)行一次判斷。
解決方法:
1、把staging的創(chuàng)建和move的代碼都移到sdcard那個if分支里
2、修改清理asec為在sdcard卸載的時候
關(guān)于app2sd的框架中的流程,大致如下:
PKMS::movePackage()====>PKMS::copyAPK()====>DefaultContainerService::copyResourceInner()====>FileUtils::copyFile()
在copyResourceInner()中調(diào)用FileUtils::copyFile()的關(guān)鍵,是path參數(shù),即newCachePath。而newCachePath的獲取,來自于:
PackageHelper::createSdDir()====>MountService::getSecureContainerPath()====>CommandListener::AsecCmd::runCommand()。
看吧,繞回到AsecCmd中了,從而各種調(diào)用VolumeManager.cpp中定義的asec相關(guān)的函數(shù)。
修改后存在的問題:
當(dāng)一個apk在其AndroidManifest.xml中申明的安裝位置為External時,此apk將無法安裝。提示報錯:INSTALL_FAILED_CONTAINER_ERROR。
報錯原因,在安裝的過程中獲取到的推薦安裝位置為External,而此時框架中Environment.java中的External的定義依然是路徑“mnt/sdcard”—即為小機(jī)器上的falsh。而安裝在外部的apk是需要放入到.android_secure文件中的!
因?yàn)槲覀円呀?jīng)把真實(shí)的app2sd實(shí)現(xiàn)了,此文件已經(jīng)被建立到真實(shí)的SD卡上去了,因此在安裝的過程中執(zhí)行copyAPK()的時候,URI中包含的.android_secure路徑在flash上是找不到的。
關(guān)鍵點(diǎn):我們已經(jīng)將真實(shí)app2sd實(shí)現(xiàn),即.android_secure在真實(shí)的SD卡上,而此apk本身是推薦自己安裝在外部—在框架中依然還是指向mnt/sdcard對應(yīng)的flash!
推薦安裝到外部,此時的外部應(yīng)該對應(yīng)的是sdcard,在沒有插入SD卡的情況下,不是應(yīng)該不推薦外部安裝么!?其實(shí)系統(tǒng)本身就是這么實(shí)現(xiàn)的,而關(guān)鍵點(diǎn)就是系統(tǒng)在判斷SD卡的掛載情況時,依然判斷的是mnt/sdcard這個flash對應(yīng)的路徑的掛載情況!
—其實(shí)這里應(yīng)該判斷SD卡對應(yīng)的mnt/sdcard2的掛載情況!(按照系統(tǒng)的處理,若SD卡沒有掛載,則將推薦到內(nèi)部安裝,此時情況就正常了)
—-在DefaultContainerService.java中修改isUnderExternalThreshold()函數(shù)中的if判斷,此處應(yīng)該是判斷真實(shí)的SD卡是否掛載上!
總結(jié)
以上是生活随笔為你收集整理的平板实现app2sd功能的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 探索Kubernetes HPA
- 下一篇: Springboot+vue项目体用用品