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

家住魔仙堡 提交于 2019-12-12 08:56:09

问题


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 through code, without user having to explicitly install it. The catch is that i cannot use an SD card download the apk file.

I can navigate to the data/data/files folder and can see my file downloaded. The only problem is that i cannot get it installed. This is what i get

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

I understand that Android does not give permission to access the data directory. My question is how can i download and install an application(apk) without using a SD card. This application is not intended to be published in the market. I have tried using both the Internal Storage using

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

and the cache directory

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

Both give the same result .. "Permission denied"

When i change the code to incorporate an SD card the application works perfectly, but using an SD card is not an option.

Surely there must be a way to do this. It is hard to believe that such a handicap exist in the Android O/S.

Has anybody done this? Any workarounds? Any pointers would be helpful.


回答1:


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.




回答2:


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.




回答3:


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)



回答4:


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




回答5:


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,...)




回答6:


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


来源:https://stackoverflow.com/questions/8784404/download-and-install-an-application-apk-from-internal-memory-no-sd-card

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!