2012-01-09 69 views
3

向所有同行程序員致以問候和新年快樂。從內部存儲器下載並安裝應用程序(apk) - 無SD卡

我的代碼從遠程服務器下載apk文件。我需要通過代碼啓動安裝過程,而無需用戶明確安裝它。問題是我無法使用SD卡下載apk文件。

我可以導航到數據/數據/文件夾,可以看到我的文件下載。唯一的問題是我無法安裝它。這就是我得到的

'/data/data/org.obs.testinstall.main/files/app.apk': Permission denied 

我知道Android不授予訪問數據目錄的權限。 我的問題是我如何不使用SD卡下載和安裝應用程序(apk)。此應用程序不打算在市場上發佈。我一直在使用

FileOutputStream fos = openFileOutput("app.apk", Context.MODE_PRIVATE); 

和緩存目錄

File file = getCacheDir(); 
File outputFile = new File(file, "app.apk"); 

都給予同樣的結果同時使用內部存儲嘗試。「權限被拒絕」

當我改變代碼中摻入SD卡的應用程序完美工作,但使用SD卡不是一種選擇。

當然必須有辦法做到這一點。很難相信在Android操作系統中存在這樣的障礙。

有沒有人這樣做?任何解決方法?任何指針都會有幫助。

回答

10

它,它由Android應用程序引起的,如果是使用私有模式寫入不能從 讀取其他應用程序文件。

你可以這樣做:

String fileName = "tmp.apk"; 
FileOutputStream fos = openFileOutput(fileName, 
     MODE_WORLD_READABLE | MODE_WORLD_WRITEABLE); 

// write the .apk content here ... flush() and close() 

// Now start the standard instalation window 
File fileLocation = new File(context.getFilesDir(), fileName); 
Intent intent = new Intent(Intent.ACTION_VIEW); 
intent.setDataAndType(Uri.fromFile(fileLocation), 
         "application/vnd.android.package-archive"); 
context.startActivity(intent); 

不過要小心,因爲該文件現在是世界上可見, 並且可以通過在同一個設備的應用程序中可以看出, 如果他們知道該文件的位置。

+1

謝謝。我不知道我是怎麼錯過的。安全性在這裏不是問題,因爲它意味着在封閉的環境中運行。再次感謝。 – Umesh 2012-01-09 07:10:34

+0

不客氣,很高興我能幫到:) – hanung 2012-01-09 07:26:17

+0

這是否需要額外的權限? – 2013-02-22 10:04:01

0

嘗試生根您的設備,然後從設備運行的程序,而不是使用模擬器。

+0

生根不是一個選項。我需要爲擁有多個設備的客戶端執行此操作。 – Umesh 2012-01-09 06:51:10

2

不需要root。 你可以使用linux命令chmod來完成它。

public static String exec(String[] args) { 
    String result = ""; 
    ProcessBuilder processBuilder = new ProcessBuilder(args); 
    Process process = null; 
    InputStream errIs = null; 
    InputStream inIs = null; 
    try { 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     int read = -1; 
     process = processBuilder.start(); 
     errIs = process.getErrorStream(); 
     while ((read = errIs.read()) != -1) { 
      baos.write(read); 
     } 
     baos.write('\n'); 
     inIs = process.getInputStream(); 
     while ((read = inIs.read()) != -1) { 
      baos.write(read); 
     } 
     byte[] data = baos.toByteArray(); 
     result = new String(data); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      if (errIs != null) { 
       errIs.close(); 
      } 
      if (inIs != null) { 
       inIs.close(); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     if (process != null) { 
      process.destroy(); 
     } 
    } 
    return result; 
} 

在你的程序,它可以調用這樣的:

String[] args1 = { "chmod", "705", "/data/data/org.obs.testinstall.main/files/" }; 
    exec(args1); 
    String[] args2 = { "chmod", "604", "/data/data/org.obs.testinstall.main/files/app.apk" }; 
    exec(args2); 

然後你就可以安裝app.apk的希望。

+0

謝謝。我正在下載的是一個apk文件。我需要使用意圖啓動安裝過程。閱讀文件不是我想要的。 – Umesh 2012-01-09 06:55:10

+0

感謝您的幫助。我很感激。 – Umesh 2012-01-09 07:11:24

0

對我來說,我刪除apk文件的startActivity之後,這是異步的。

太糟糕了,有解析錯誤的沒有更好的說明(未找到文件,訪問被拒絕,損壞的文件包中,...)

0

當您發送意圖安裝apk時,您可以使用此功能更改apk目錄的模式。

private static boolean changeMode(String filePath, String prefixPath) { 
    if (TextUtils.isEmpty(prefixPath) || !filePath.startsWith(prefixPath)) { 
     return true; 
    } 

    try { 
     String[] args1 = { "chmod", "705", prefixPath}; 
     Runtime.getRuntime().exec(args1); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return false; 
    } 

    String subPath = filePath.split(prefixPath)[1]; 
    String[] subArr = subPath.split(File.separator); 
    for (String path : subArr) { 
     if (!TextUtils.isEmpty(path)) { 
      prefixPath = prefixPath + File.separator + path; 
      try { 
       if (!prefixPath.endsWith(".apk")) { 
        String[] progArray1 = {"chmod", "705", prefixPath}; 
        Runtime.getRuntime().exec(progArray1); 
       } else { 
        String[] progArray2 = {"chmod", "604", prefixPath}; 
        Runtime.getRuntime().exec(progArray2); 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
       return false; 
      } 
     } 
    } 
    return true; 
} 

而在您發送意圖之前,請檢查chmod是否成功。

boolean chmodRes = changeMode(filePath, context.getCacheDir().getAbsolutePath()) 
      && changeMode(filePath, context.getFilesDir().getAbsolutePath()); 
    if (!chmodRes) { 
     return false; 
    }