Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android install .apk file programmatically

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

like image 245
r2b2s Avatar asked Mar 04 '23 17:03

r2b2s


2 Answers

I have wrote a code in java with respect to Uri access exposure for targetSdkVersion >= 24, please try it in xamarin 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);
like image 160
aminography Avatar answered Mar 27 '23 10:03

aminography


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));
like image 39
Manasranjan Avatar answered Mar 27 '23 11:03

Manasranjan