3

I have been using Action_View to install apk using following code

Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
    intent.setDataAndType(Uri.fromFile(new File(location + "myAPK.apk")),
            "application/vnd.android.package-archive");
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);

It opens the Install Prompt window in device. Now user can install or cancel the installation process.

I am only interested when user click the install package but installation failed due to some reason may be corrupt apk or mismatched signed apk etc.

How can i capture the event when installation failed.. Can i get the result from ACTION_INSTALL_PACKAGE

I have gone through reading System Broadcast Messages but all are used for either Pacakge added or replaced.

Any Clue ?

Rajeev Kumar
  • 4,901
  • 8
  • 48
  • 83
  • Have you tried to launch the process with `startActivityForResult` and then analyse the callback in case it fails on `onActivityResult`? – nano May 11 '17 at 11:00
  • @nano it triggers the `OnActivityResult` immediately after opening install prompt window and does not wait for user response. – Rajeev Kumar May 11 '17 at 11:07
  • Try again removing `intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);` – nano May 11 '17 at 11:09
  • Possible duplicate of [ACTION\_INSTALL\_PACKAGE](http://stackoverflow.com/questions/19825636/action-install-package) – Yazan May 11 '17 at 11:23

3 Answers3

6

Quoting the documentation for ACTION_INSTALL_PACKAGE:

Output: If EXTRA_RETURN_RESULT, returns whether the install succeeded.

Quoting the documentation for EXTRA_RETURN_RESULT:

Used as a boolean extra field with ACTION_INSTALL_PACKAGE or ACTION_UNINSTALL_PACKAGE. Specifies that the installer UI should return to the application the result code of the install/uninstall. The returned result code will be RESULT_OK on success or RESULT_FIRST_USER on failure.

So, add EXTRA_RETURN_RESULT to your Intent, with a value of true, and use startActivityForResult().

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
4

Launch the Intent with startActivityForResult:

Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setDataAndType(Uri.fromFile(new File(location + "myAPK.apk")),
        "application/vnd.android.package-archive");
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
startActivityForResult(intent, MY_CONSTANT);

Then analyse the result

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case ...
    }
}
nano
  • 2,511
  • 4
  • 25
  • 42
0

I only want to add my own considerations and experiences. I had encountered the same problem. If you want to get the result the best way is that suggested by Nano and CommonsWare.

I want to highlight that if your apk is internally located you may face the problem "parsing the package error". I want remember you that you need the right permission in the manifest <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />.

But I noticed that is also needed add Intent.FLAG_GRANT_READ_URI_PERMISSION. So the complete example code could be like this mine:

Uri fileUri = FileProvider.getUriForFile(getApplicationContext(),  BuildConfig.APPLICATION_ID + ".provider", currentFile);
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setDataAndType(fileUri,"application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
startActivityForResult(intent, APK_INSTALL_CODE);

Then I would also remember you that this mechanism is all asynchronous, so if you need to know the result to move on, you need to wait it. I don't know if this is the best way to do but it works:

Uri fileUri = FileProvider.getUriForFile(getApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", currentFile);
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setDataAndType(fileUri,"application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
startActivityForResult(intent, APK_INSTALL_CODE);
while (WAIT_APK_INSTALL) {
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == APK_INSTALL_CODE) {
        if (resultCode == 1) {
            WAIT_APK_INSTALL = false;
            //SUCCESS
        }
        else {
            //FAILED 
            //maybe it's needed crash the app like me. In my case the installation was necessary
            Intent intent = new Intent(getBaseContext(), ErrorActivity.class);
            intent.putExtra(GlobalStrings.INTENT_EXTRA_MESSAGE, getString(R.string.apk_installation_failed));
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); // required when starting from Application
            startActivity(intent);
            System.exit(1); // kill off the crashed app
        }
    }
}
NonnoAndre
  • 51
  • 2