user15603244
user15603244

Reputation:

How to install an apk from inside my app?

I've been stuck on this for 2 days.

All I want is for the app to install an apk. I placed the apk inside the raw resource directory.

Update: Thanks to @MarcosVasconcelos below code is now working.

Manifest:

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

<application>

    <provider
        android:enabled="true"
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.goodweathercorp.boost.fileProvider"
        android:grantUriPermissions="true"
        android:exported="false">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/paths" />
    </provider>

</application>

paths.xml in res>xml:

<paths>
    <cache-path name="cache" path="/"/>

</paths>

In Activity:

if (getPackageManager().canRequestPackageInstalls()) {
    
    File file = new File(getCacheDir()+"/longer.apk");
    if (!file.exists())
        try {

            InputStream inputStream = getAssets().open("longer.apk");
            FileOutputStream fos = new FileOutputStream(file);

            int size = inputStream.available();
            byte[] buffer = new byte[size];
            inputStream.read(buffer);

            fos.write(buffer);


            inputStream.close();
            fos.close();
        } catch (FileNotFoundException e) {
            Log.e(TAG, e.getMessage());
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
        }
    else Log.e(TAG, "File already exists");

    Uri apkUri = FileProvider.getUriForFile(this, getPackageName() + ".fileProvider", file);

    Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
    intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    try {
        getApplicationContext().startActivity(intent);
    } catch (ActivityNotFoundException e) {
        Log.e(TAG, e.getMessage());
    }
}

I tried all variants of the String path, including using the Resource Id and adding the ".apk" file extension. I always get the ActivityNotFoundException error. Perhaps an apk shouldn't be placed in the raw folder? If so where would it be placed to get a working Uri?

Upvotes: -1

Views: 160

Answers (1)

Marcos Vasconcelos
Marcos Vasconcelos

Reputation: 18276

The only way to share a file from within your application is providing a ContentProvider in your Android manifest, from your code you create a URI from getContentResolver() and share the Uri trough the intent. developer.android.com/reference/android/content/ContentProvider

Good implementation example: https://developer.android.com/training/secure-file-sharing/setup-sharing

EDIT: theres a better approach to read a stream, the idea of the size is buffering chunks, so use a size of 1024 and a loop:

   int count = 0;
   while (true) {
       count = inputStream.read(buffer);
       if (count <= 0) break;
         fos.write(buffer, 0, count);
   }

Upvotes: 0

Related Questions