Android install .apk file programmatically

11,698

Solution 1

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

Solution 2

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));
Share:
11,698
r2b2s
Author by

r2b2s

Updated on June 04, 2022

Comments

  • r2b2s
    r2b2s about 2 years

    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

  • aminography
    aminography over 5 years
    @r2b2s: Have you tested it?
  • r2b2s
    r2b2s over 5 years
    thanks, but i've already tested this solution, and it's not wotking for me the apk installer windows is launched but immediatly closed... I've scrapped the idea and tried something new, use google play store with tested version
  • roghayeh hosseini
    roghayeh hosseini about 5 years
    are u test it in android >Oreo?
  • aminography
    aminography about 5 years
    @roghayehhosseini: I've tested it on Android N, as the problem comes from N and later, I think it is OK on O.
  • Sagar
    Sagar almost 5 years
    @aminography For me it showing dialog There was a problem while parsing the package and security exception for androidx.core.content.FileProvider I have added FLAG_GRANT_READ_URI_PERMISSION flag also