İan Boddison
İan Boddison

Reputation: 367

Parse error when programmatically installing an APK

I am trying to create a mechanism for an app to update itself by downloading and installing a later APK from within the app.

I have an APK located on a server which installs fine if I simply navigate to the URI then open the .apk file. The problem comes when I try to install it programmatically. I get "Parse Error - There was a problem while parsing the package"

The target phone allows install from unknown sources and within AndroidManifest.xml I request these permissions:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.REQUEST_WRITE_PERMISSION"/>

The code to perform the update has been taken from another thread here on StackOverflow and changed slightly to suit my particular situation.

public class UpdateApp extends AsyncTask<String,Void,Void> {
    private Context context;
    public void setContext(Context contextf){
        context = contextf;
    }

    @Override
    protected Void doInBackground(String... arg0) {
        try {
            URL url = new URL(arg0[0]);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setDoOutput(true);
            conn.connect();

            File file = context.getCacheDir();
            file.mkdirs();
            File outputFile = new File(file, "update.apk");
            if(outputFile.exists()){
                outputFile.delete();
            }
            FileOutputStream fos = new FileOutputStream(outputFile);

            InputStream is = conn.getInputStream();

            byte[] buffer = new byte[1024];
            int len1 = 0;
            while ((len1 = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len1);
            }
            fos.close();
            is.close();

            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(outputFile), "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);


        } catch (Throwable ex) {
            Toast.makeText(context, ex.toString(), Toast.LENGTH_LONG).show();
        }
        return null;
    }
}

What can I try in order to understand why the APK is generating an error when installed from within the code but installs without issue when downloaded from the server?

The app is being built for API 23 although it will be required to work with API 24 once complete.

Upvotes: 8

Views: 4086

Answers (2)

Vlad
Vlad

Reputation: 8552

This works for me on Android 8

startActivity(Intent(Intent.ACTION_VIEW).apply {
    type = "application/vnd.android.package-archive"
    data = FileProvider.getUriForFile(applicationContext, "$packageName.fileprovider", file)
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
})

Upvotes: 1

Rahul
Rahul

Reputation: 5049

You will have to make your cached apk file world-readable.

After is.close();

put

outputFile.setReadable(true, false);

Upvotes: 6

Related Questions