Self updating app
Asked Answered
K

3

24

TL:DR; version ;)

  • my app should run without user interaction (autostart etc works)

  • it should update itself (via apk) without any user interaction

  • rooted devices are possible

.

problem:

  • querying a newer apk from a server works
  • when starting the apk with a (view?) intent, the "install app" prompt pops and needs a user confirmation

How do I solve this without any user interaction?

http://code.google.com/p/auto-update-apk-client/ This seems to be a solution, but there must be better approach.

I already found this: Install Application programmatically on Android

but that doesn't solve my problem.

Karole answered 20/2, 2013 at 14:23 Comment(0)
K
37

Solved it! :D

It just works in rooted devices but works perfectly. Using the unix cmd "pm" (packageManager) allows you to install apks from sdcard, when executing it as root.

Hope this could help some people in the future.

public static void installNewApk()
{
        try
        {
            Runtime.getRuntime().exec(new String[] {"su", "-c", "pm install -r /mnt/internal/Download/fp.apk"});
        }
        catch (IOException e)
        {
            System.out.println(e.toString());
            System.out.println("no root");
        }
}

Required permissions:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Karole answered 26/2, 2013 at 9:31 Comment(8)
it giving me error code 139 i.e Segmentation fault. But my tablet is already rooted. Any idea why?Ietta
Can you tell me what are permissions required to run this code on a rooted tablet?Ietta
Nothing happened. Neither it gave any error nor apk was installed. My device is rooted. Any idea why it did not work?Billionaire
Is this possible with non-rooted phone?Pustule
First sentence: "It just works in rooted devices...", as mentioned ^^Karole
Is there any option available for non-rooted devices to update application without user interaction?Also it is not working in rooted phone.Is there anything else?Should I use signed apk or normal apk would be work?I am just making demo application for nowPustule
Afaik it's not possible for non-rooted devices. Furthermore this code works 1:1 with every apk I tried. Maybe your path is wrong? What's your exception?Karole
What will happen if app is currently playing and you try to run the update? Will it restart, crash or something else? Another question... Is this code in app we are trying to update or in some other app which will update mine?Spathic
A
5

My suggestion is to use plugin mechanism instad of updating the app. You can dynamically load classes from the Web and run them inside your app without any user interaction. There is a lot of resources spread across the Internet:

How to load a Java class dynamically on android/dalvik?

http://android-developers.blogspot.com/2011/07/custom-class-loading-in-dalvik.html

Ardolino answered 20/2, 2013 at 14:33 Comment(2)
Nice idea, I'll give it a try, but anyhow I think updating using an apk would be more robust and less error prone.Karole
Thats right Selvin, maybe I rly should try this: code.google.com/p/auto-update-apk-client ...but what about the rooted device approach? is there a possibility to install an apk on cmd?Karole
U
0

If su -c doesn't work, try su 0 (only rooted devices can do su!)

The full answer looks like this:

private void installNewApk()
    {
        String path = mContext.getFilesDir().getAbsolutePath() + "/" + LOCAL_FILENAME;
        mQuickLog.logD("Install at: " + path);
        ProcessUtils.runProcessNoException(mQuickLog, "su", "0", "pm", "install", "-r", path);
    }

With this class defined:

public class ProcessUtils {
    Process process;
    int errCode;
    public ProcessUtils(String ...command) throws IOException, InterruptedException{
        ProcessBuilder pb = new ProcessBuilder(command);
        this.process = pb.start();
        this.errCode = this.process.waitFor();
    }

    public int getErrCode() {
        return errCode;
    }

    public String getOutput() throws IOException {
        InputStream inputStream = process.getInputStream();
        InputStream errStream = process.getErrorStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line + System.getProperty("line.separator"));
        }

        br = new BufferedReader(new InputStreamReader(errStream));
        while ((line = br.readLine()) != null) {
            sb.append(line + System.getProperty("line.separator"));
        }
        return sb.toString();
    }


    public static String runProcess(String ...command) throws IOException, InterruptedException {
        ProcessUtils p = new ProcessUtils(command);
        if (p.getErrCode() != 0) {
            // err
        }
        return p.getOutput();
    }

    public static void runProcessNoException(String ...command) {
        try {
            runProcess(command);
        } catch (InterruptedException | IOException e) {
            // err
        }
    }
}
Underdrawers answered 4/8, 2018 at 7:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.