Download and install an application (apk) from internal memory - no SD card

后端 未结 6 1898
庸人自扰
庸人自扰 2021-01-06 19:35

Greetings and a happy new year to all my fellow programmers.

My code downloads an apk file from a remote server. I need to initiate the installation procedure throug

相关标签:
6条回答
  • 2021-01-06 20:12

    No need to root. You can just use linux command chmod to do it.

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

    in your program,it can be invoked like this:

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

    Then you can install the app.apk as wished.

    0 讨论(0)
  • 2021-01-06 20:16

    It it caused by android application can not read from another application file if it is written using PRIVATE mode.

    You can do this:

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

    Be careful though, because that file is now world-visible, and can be seen by any application in the same device, if they know the file location.

    0 讨论(0)
  • 2021-01-06 20:17

    Try rooting your device and then running the program from the device, instead of using an emulator.

    0 讨论(0)
  • 2021-01-06 20:18

    Also you can use

    downloadedFile.setReadable(true, false);

    with

    fileOutputStream = openFileOutput(fileName, Context.MODE_PRIVATE);

    There are two setReadable method. The first has one parameter and the second one has two parameters.

    setReadable(boolean readable)
    setReadable(boolean readable, boolean ownerOnly)
    
    0 讨论(0)
  • 2021-01-06 20:24

    when you send intent to install apk, you can use this function to change mode for apk directory.

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

    And before you send intent, check chmod is it alreay success.

        boolean chmodRes = changeMode(filePath, context.getCacheDir().getAbsolutePath())
                && changeMode(filePath, context.getFilesDir().getAbsolutePath());
        if (!chmodRes) {
            return false;
        }
    
    0 讨论(0)
  • 2021-01-06 20:29

    For me I deleted the apk file right after the startActivity, which is asynchronous.

    Too bad there is no better description of the parsing error (file not found, access denied, corrupted file in package,...)

    0 讨论(0)
提交回复
热议问题