Android install .apk file programmatically

Viewed 13448

I'm trying to do an autoupdate function, after a lot of search I've found solution for download .apk file from my server to my device But i'can't launch this file, window to prompt user for install open but close direct.

this is my code

Java.IO.File file = new Java.IO.File(destination);

Android.Net.Uri apkURI = Android.Support.V4.Content.FileProvider.GetUriForFile(
                                  _context,
                                  _context.ApplicationContext.PackageName + ".provider", file);

 Intent promptInstall = new Intent(Intent.ActionView);
 //promptInstall.SetDataAndType(apkURI, "application/vnd.android.package-archive");
 promptInstall.SetData(apkURI);

 promptInstall.AddFlags(ActivityFlags.NewTask);
 promptInstall.AddFlags(ActivityFlags.GrantReadUriPermission);
         _context.GrantUriPermission(_context.ApplicationContext.PackageName, apkURI, ActivityFlags.GrantReadUriPermission);
_context.StartActivity(promptInstall);

I've tryed with a lot of combinaison of flags and Ident.Action like ActionInstallPackage

android version is 8.1

thanks

2 Answers

I have wrote a code in with respect to Uri access exposure for targetSdkVersion >= 24, please try it in yourself.

ApkInstaller.java

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.support.v4.content.FileProvider;
import android.util.Log;

import java.io.File;

public class ApkInstaller {

    public static void installApplication(Context context, String filePath) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(uriFromFile(context, new File(filePath)), "application/vnd.android.package-archive");
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        try {
            context.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            e.printStackTrace();
            Log.e("TAG", "Error in opening the file!");
        }
    }

    private static Uri uriFromFile(Context context, File file) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file);
        } else {
            return Uri.fromFile(file);
        }
    }

}

manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="package.identifier">

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application ... >

        ...

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>

    </application>

</manifest>

res/xml/provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="external_files"
        path="." />
</paths>

Usage:

ApkInstaller.installApplication(context, filePath);

STEP-1

First Create xml file inside your res/xml/provider_paths.xml and then

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="files_root"
        path="Android/data/${applicationId}" />
    <external-path
        name="external_files"
        path="." />
</paths>

STEP-2

Add this in AndroidManifest.xml file

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

<application>
 <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>
    </application>

STEP-3 Final step

Add this in your Activity class

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                            Uri uri = FileProvider.getUriForFile(context,
                                    context.getApplicationContext().getPackageName() + ".provider", new File(apkFilePath));
                            Intent intent = new Intent(Intent.ACTION_VIEW);
                            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            intent.setDataAndType(uri, "application/vnd.android.package-archive");
                            startActivity(intent);

                        } else {
                            Intent intent = new Intent(Intent.ACTION_VIEW);
                            intent.setDataAndType(FileUtils.getFileToUri(BaseActivity.this, new File(apkFilePath)),
                                    "application/vnd.android.package-archive");
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                        }

Note: FileProvider only for Android >= Nougat

Using FileProvider you can get other .extension file like capture image uri

Uri uri = FileProvider.getUriForFile(context,
context.getApplicationContext().getPackageName() + ".provider", new File(imageFilePath));
Related