by tony蔣
最近有客戶投訴,有一款app store在Android 4.2中不能更新版本, 更新版本安裝會失敗,具體錯誤消息如下:
[html]
10-23 10:57:56.663: I/ActivityManager(391): START u0 {dat=file:///storage/emulated/0/Download/xxxmarket/1382493454155.tmp cmp=com.android.packageinstaller/.InstallAppProgress (has extras)} from pid 30530
10-23 10:57:56.764: W/InstallAppProgress(30530): Replacing package:com.xxx.market.sys.xxx.apl
10-23 10:57:56.827: W/ActivityManager(391): No content provider found for permission revoke: file:///storage/emulated/0/Download/xxxmarket/1382493454155.tmp
10-23 10:57:56.827: W/PackageManager(391): Can't install update of com.xxx.market.sys.xxx.apl update version 0 is older than installed version 116/pre>
奇怪的是,這種現象只出現在Android 4.2中。
我們版本更新的邏輯是, 啟動一個AsynTask,下載最新的apk到內存裡, 然後發intent給Android PackInstaller, 執行安裝。
一開始調查懷疑是因為, 我們在內存裡寫文件用了以下代碼,
[java]
tempFileStream = context.openFileOutput(LOCAL_TEMPFILENAME, Context.MODE_WORLD_READABLE);
writeResponse(response, tempFileStream);
Android 4.2中Context.MODE_WORLD_READABLE已經被廢止了, 因此會出現文件讀寫無權限?!
後來我們強制把文件寫到SD卡中, 發現一樣無法讀取安裝。
這就奇怪了。
我注意到app中AndroidMainfest.xml配置versioncode的地方如下
@CopyRight 歸於蔣彪, from 南湖邊上的小木屋
[html]
android:versionName="@string/app_version_name" android:versionCode="@integer/app_version_code"
是交叉引用了其他配置文件中的信息,而不是直接寫死。 會不會跟這個有關?
我嘗試修改成直接寫死,結果就成了。。。。。。。。。。。
對於原因, 我懷疑是, Android 4.2開始為了對應多用戶機制, 加強了app直接文件訪問的權限配置。
所有的app之間的數據共享都要基於ContentProvider, PackageInstaller作為Android的原生態app, 也沒有權限去讀取除AndroidManifest.xml以外的app信息。
本著嚴謹的學術作風, 我又調查了一下Android的源代碼, 在Android專用來解析AndroidMainifest.xml的[android.content.res.Resources] , 看到了如下代碼
[java]
// XXX note that for now we only work with compiled XML files.
// To support generic XML files we will need to manually parse
// out the attributes from the XML file (applying type information
// contained in the resources and such).
XmlBlock.Parser parser = (XmlBlock.Parser)set;
mAssets.retrieveAttributes(parser.mParseState, attrs,
array.mData, array.mIndices);
這塊的注釋,想必已經能說明問題了。