从内部存储器下载并安装应用程序(apk) - 没有SD卡

时间:2012-01-09 05:49:44

标签: android apk

向所有同事们致以问候和新年快乐。

我的代码从远程服务器下载apk文件。我需要通过代码启动安装过程,而无需用户明确安装它。问题是,我无法使用SD卡下载apk文件。

我可以导航到data / data / files文件夹,可以看到我的文件已下载。唯一的问题是我无法安装它。这就是我得到的

 '/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 O / S存在这样的障碍。

有人这样做过吗?任何解决方法?任何指针都会有所帮助。

6 个答案:

答案 0 :(得分:12)

它引起的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 :(得分: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。

答案 2 :(得分:1)

还可以使用

downloadedFile.setReadable(true, false);

fileOutputStream = openFileOutput(fileName, Context.MODE_PRIVATE);

有两个setReadable方法。第一个具有一个参数,第二个具有两个参数。

setReadable(boolean readable)
setReadable(boolean readable, boolean ownerOnly)

答案 3 :(得分:0)

尝试生根设备,然后从设备运行程序,而不是使用模拟器。

答案 4 :(得分:0)

对我来说,我在startActivity之后删除了apk文件,这是异步的。

太糟糕了,没有更好的解析错误描述(文件未找到,访问被拒绝,包中的文件损坏,......)

答案 5 :(得分: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;
    }