【问题标题】:Download and install an application (apk) from internal memory - no SD card从内部存储器下载并安装应用程序 (apk) - 无 SD 卡
【发布时间】:2018-11-01 13:44:11
【问题描述】:

向我所有的程序员伙伴们问好,新年快乐。

我的代码从远程服务器下载了一个 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 操作系统中存在这样的障碍。

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

【问题讨论】:

    标签: android apk


    【解决方案1】:

    它是由android应用程序无法读取引起的 另一个应用程序文件,如果它是使用 PRIVATE 模式编写的。

    你可以这样做:

    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);
    

    不过要小心,因为该文件现在是全世界可见的, 并且可以被同一设备中的任何应用程序看到, 如果他们知道文件位置。

    【讨论】:

    • 非常感谢。我不知道我是怎么错过的。安全性在这里不是问题,因为它旨在在封闭的环境中运行。再次感谢。
    • 这需要额外的权限吗?
    【解决方案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。

    【讨论】:

    • 谢谢。我下载的是一个apk文件。我需要使用意图启动安装过程。读取文件不是我想要的。
    • 感谢您的帮助。我很感激。
    【解决方案3】:

    你也可以使用

    downloadedFile.setReadable(true, false);

    fileOutputStream = openFileOutput(fileName, Context.MODE_PRIVATE);

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

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

    【讨论】:

      【解决方案4】:

      尝试将您的设备植根,然后从设备上运行程序,而不是使用模拟器。

      【讨论】:

      • 生根不是一个选项。我需要为拥有多个设备的客户执行此操作。
      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

        当您发送安装 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;
            }
        

        【讨论】:

          猜你喜欢
          • 2013-01-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-07
          • 1970-01-01
          • 2011-12-12
          • 2016-01-24
          相关资源
          最近更新 更多