安裝儲存於SDCard的APK包很順利,但如果恰巧手機沒SDCard,將APK包下載到/data/data/<app_package>/下後,再用之前的方式安裝,一直提示"There is a problem parsing the package"。好吧,悲劇的程式員在需求至上的原則下又要解決此問題了。
1.準備
以上次寫過的斷點續傳的代碼
[CSDN]為例,將APK包下載存放路徑改為"/data/data/<app_packages>/apps/":
public static final String RES_LOAD_FOLDER = File.separator + "data" + File.separator + "data"<br /> + File.separator + "lab.sodino.downloadbreak" + File.separator + "apps"<br /> + File.separator;
為方便,將".apk"也改為"file.apk"。
下載後,點擊"安裝",出錯了。
2.找原因
這時進入adb shell,查看apps和file.apk的檔案系統許可權詳情如下:
不可安裝<br /># cd /data/data/lab.sodino.downloadbreak<br />cd /data/data/lab.sodino.downloadbreak<br /># ls -l<br />ls -l<br />drwx------ app_38 app_38 2011-06-16 08:42 apps<br />drwxr-xr-x system system 2011-06-16 08:40 lib<br /># ls -l apps<br />ls -l apps<br />-rw------- app_38 app_38 2708419 2011-06-16 08:42 file.apk
可見檔案夾apps僅對其擁有者app_38開放了讀、寫、執行許可權,file.apk也僅僅是app_38有讀、寫入權限。好了,問題找到了。即系統的應用程式安裝器無法讀取到file.apk導致的。
3.檔案夾、檔案的許可權分配
系統的應用程式安裝器與app_38不同組,所以對apps和file.apk的檔案系統許可權修改應為修改其[other]組許可權。(分為user/group/other三組,詳解請自行google或訪問:http://blog.csdn.net/sodino/archive/2011/03/09/6234713.aspx中的12.chmod詳解(使用者組區分))。
檔案夾的讀許可權是指可以讀取該檔案目錄結構資訊,寫入權限是指可以變更檔目錄結構資訊,位於其[other]組的使用者能否讀取該檔案夾下的檔案與檔案夾是否開放讀許可權無關,只與檔案夾開放的執行許可權有關。原因為檔案夾在不具備執行許可權時,是無法執行"cd"命令進入該檔案夾(也無法執行"ls"命令讀取檔案夾下的檔案詳情)。所以對apps和file.apk最精簡(當然直接設定為rwxrwxrwx是最不需要耗費腦細胞的)的許可權分配詳情如下為:
可安裝<br /># cd /data/data/lab.sodino.downloadbreak<br />cd /data/data/lab.sodino.downloadbreak<br /># ls -l<br />ls -l<br />drwx-----x app_38 app_38 2011-06-16 08:33 apps<br />drwxr-xr-x system system 2011-06-16 08:31 lib<br /># ls -l apps<br />ls -l apps<br />-rw----r-- app_38 app_38 2708419 2011-06-16 08:33 file.apk
4.修改許可權的方法
apps :drwx-----x → (4+2+1) + (0+0+0) + (0+0+1) → 701
files.apk :-rw----r-- → (4+2+0) + (0+0+0) + (4+0+0) → 604
即對apps執行:chmod 705 /data/data/<app_package>/apps
對file.apk執行:chmod 604 /data/data/<app_package>/apps/file.apk
具體代碼為在lab.sodino.downloadbreak.ActDownload類中的installDownload()開頭處新增如下代碼:
// [檔案夾705:drwx---r-x]<br /> String[] args1 = { "chmod", "705", RES_LOAD_FOLDER };<br /> exec(args1);<br /> // [檔案604:-rw----r--]<br /> String[] args2 = { "chmod", "604", RES_LOAD_FOLDER + bean.name };<br /> exec(args2);
執行Linux命令的exec()方法實現如下:
/** 執行Linux命令,並返回執行結果。 */<br /> public static String exec(String[] args) {<br /> String result = "";<br /> ProcessBuilder processBuilder = new ProcessBuilder(args);<br /> Process process = null;<br /> InputStream errIs = null;<br /> InputStream inIs = null;<br /> try {<br /> ByteArrayOutputStream baos = new ByteArrayOutputStream();<br /> int read = -1;<br /> process = processBuilder.start();<br /> errIs = process.getErrorStream();<br /> while ((read = errIs.read()) != -1) {<br /> baos.write(read);<br /> }<br /> baos.write('/n');<br /> inIs = process.getInputStream();<br /> while ((read = inIs.read()) != -1) {<br /> baos.write(read);<br /> }<br /> byte[] data = baos.toByteArray();<br /> result = new String(data);<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> } catch (Exception e) {<br /> e.printStackTrace();<br /> } finally {<br /> try {<br /> if (errIs != null) {<br /> errIs.close();<br /> }<br /> if (inIs != null) {<br /> inIs.close();<br /> }<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> if (process != null) {<br /> process.destroy();<br /> }<br /> }<br /> return result;<br /> }
OK,Sodino Done it.
本文內容歸CSDN部落格博主Sodino 所有
轉載請註明出處:http://blog.csdn.net/sodino/archive/2011/06/16/6549082.aspx