Display install errors as notify/dialog
This commit is contained in:
parent
de1d310499
commit
4e8e148029
@ -562,55 +562,28 @@ public class AppDetails extends AppCompatActivity {
|
||||
}
|
||||
case Installer.ACTION_INSTALL_COMPLETE: {
|
||||
headerFragment.removeProgress();
|
||||
|
||||
localBroadcastManager.unregisterReceiver(this);
|
||||
|
||||
PackageManagerCompat.setInstaller(packageManager, app.packageName);
|
||||
|
||||
onAppChanged();
|
||||
break;
|
||||
}
|
||||
case Installer.ACTION_INSTALL_INTERRUPTED: {
|
||||
headerFragment.removeProgress();
|
||||
onAppChanged();
|
||||
|
||||
String errorMessage =
|
||||
intent.getStringExtra(Installer.EXTRA_ERROR_MESSAGE);
|
||||
|
||||
if (!TextUtils.isEmpty(errorMessage)) {
|
||||
Log.e(TAG, "Installer aborted with errorMessage: " + errorMessage);
|
||||
|
||||
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(AppDetails.this);
|
||||
alertBuilder.setTitle(R.string.install_error_notify_title);
|
||||
alertBuilder.setMessage(errorMessage);
|
||||
alertBuilder.setNeutralButton(android.R.string.ok, null);
|
||||
alertBuilder.create().show();
|
||||
}
|
||||
|
||||
localBroadcastManager.unregisterReceiver(this);
|
||||
|
||||
|
||||
// TODO: old error handling code:
|
||||
// if (errorCode == InstallerCallback.ERROR_CODE_CANCELED) {
|
||||
// return;
|
||||
// }
|
||||
// final int title, body;
|
||||
// if (operation == InstallerCallback.OPERATION_INSTALL) {
|
||||
// title = R.string.install_error_title;
|
||||
// switch (errorCode) {
|
||||
// case ERROR_CODE_CANNOT_PARSE:
|
||||
// body = R.string.install_error_cannot_parse;
|
||||
// break;
|
||||
// default: // ERROR_CODE_OTHER
|
||||
// body = R.string.install_error_unknown;
|
||||
// break;
|
||||
// }
|
||||
// } else { // InstallerCallback.OPERATION_DELETE
|
||||
// title = R.string.uninstall_error_title;
|
||||
// switch (errorCode) {
|
||||
// default: // ERROR_CODE_OTHER
|
||||
// body = R.string.uninstall_error_unknown;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// runOnUiThread(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// onAppChanged();
|
||||
//
|
||||
// Log.e(TAG, "Installer aborted with errorCode: " + errorCode);
|
||||
//
|
||||
// AlertDialog.Builder alertBuilder = new AlertDialog.Builder(AppDetails.this);
|
||||
// alertBuilder.setTitle(title);
|
||||
// alertBuilder.setMessage(body);
|
||||
// alertBuilder.setNeutralButton(android.R.string.ok, null);
|
||||
// alertBuilder.create().show();
|
||||
// }
|
||||
// });
|
||||
break;
|
||||
}
|
||||
case Installer.ACTION_INSTALL_USER_INTERACTION: {
|
||||
@ -643,52 +616,28 @@ public class AppDetails extends AppCompatActivity {
|
||||
}
|
||||
case Installer.ACTION_UNINSTALL_COMPLETE: {
|
||||
headerFragment.removeProgress();
|
||||
localBroadcastManager.unregisterReceiver(this);
|
||||
|
||||
onAppChanged();
|
||||
|
||||
localBroadcastManager.unregisterReceiver(this);
|
||||
break;
|
||||
}
|
||||
case Installer.ACTION_UNINSTALL_INTERRUPTED: {
|
||||
headerFragment.removeProgress();
|
||||
localBroadcastManager.unregisterReceiver(this);
|
||||
|
||||
// TODO: old error handling code:
|
||||
// if (errorCode == InstallerCallback.ERROR_CODE_CANCELED) {
|
||||
// return;
|
||||
// }
|
||||
// final int title, body;
|
||||
// if (operation == InstallerCallback.OPERATION_INSTALL) {
|
||||
// title = R.string.install_error_title;
|
||||
// switch (errorCode) {
|
||||
// case ERROR_CODE_CANNOT_PARSE:
|
||||
// body = R.string.install_error_cannot_parse;
|
||||
// break;
|
||||
// default: // ERROR_CODE_OTHER
|
||||
// body = R.string.install_error_unknown;
|
||||
// break;
|
||||
// }
|
||||
// } else { // InstallerCallback.OPERATION_DELETE
|
||||
// title = R.string.uninstall_error_title;
|
||||
// switch (errorCode) {
|
||||
// default: // ERROR_CODE_OTHER
|
||||
// body = R.string.uninstall_error_unknown;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// runOnUiThread(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// onAppChanged();
|
||||
//
|
||||
// Log.e(TAG, "Installer aborted with errorCode: " + errorCode);
|
||||
//
|
||||
// AlertDialog.Builder alertBuilder = new AlertDialog.Builder(AppDetails.this);
|
||||
// alertBuilder.setTitle(title);
|
||||
// alertBuilder.setMessage(body);
|
||||
// alertBuilder.setNeutralButton(android.R.string.ok, null);
|
||||
// alertBuilder.create().show();
|
||||
// }
|
||||
// });
|
||||
String errorMessage =
|
||||
intent.getStringExtra(Installer.EXTRA_ERROR_MESSAGE);
|
||||
|
||||
if (!TextUtils.isEmpty(errorMessage)) {
|
||||
Log.e(TAG, "Installer aborted with errorMessage: " + errorMessage);
|
||||
|
||||
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(AppDetails.this);
|
||||
alertBuilder.setTitle(R.string.uninstall_error_notify_title);
|
||||
alertBuilder.setMessage(errorMessage);
|
||||
alertBuilder.setNeutralButton(android.R.string.ok, null);
|
||||
alertBuilder.create().show();
|
||||
}
|
||||
|
||||
localBroadcastManager.unregisterReceiver(this);
|
||||
break;
|
||||
}
|
||||
case Installer.ACTION_UNINSTALL_USER_INTERACTION: {
|
||||
|
@ -25,9 +25,7 @@ import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.BuildConfig;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.privileged.install.InstallExtensionDialogActivity;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@ -43,36 +41,22 @@ public class DefaultInstaller extends Installer {
|
||||
protected void installPackage(Uri uri, Uri originatingUri, String packageName) {
|
||||
sendBroadcastInstall(uri, originatingUri, Installer.ACTION_INSTALL_STARTED);
|
||||
|
||||
Utils.debugLog(TAG, "ACTION_INSTALL uri: " + uri + " file: " + new File(uri.getPath()));
|
||||
Utils.debugLog(TAG, "DefaultInstaller uri: " + uri + " file: " + new File(uri.getPath()));
|
||||
|
||||
Uri sanitizedUri;
|
||||
try {
|
||||
sanitizedUri = Installer.prepareApkFile(mContext, uri, packageName);
|
||||
} catch (Installer.InstallFailedException e) {
|
||||
Log.e(TAG, "prepareApkFile failed", e);
|
||||
sendBroadcastInstall(uri, originatingUri, Installer.ACTION_INSTALL_INTERRUPTED,
|
||||
e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
Intent installIntent;
|
||||
// special case: F-Droid Privileged Extension
|
||||
if (packageName != null && packageName.equals(PrivilegedInstaller.PRIVILEGED_EXTENSION_PACKAGE_NAME)) {
|
||||
|
||||
// extension must be signed with the same public key as main F-Droid
|
||||
// NOTE: Disabled for debug builds to be able to use official extension from repo
|
||||
ApkSignatureVerifier signatureVerifier = new ApkSignatureVerifier(mContext);
|
||||
if (!BuildConfig.DEBUG && !signatureVerifier.hasFDroidSignature(new File(sanitizedUri.getPath()))) {
|
||||
throw new RuntimeException("APK signature of extension not correct!");
|
||||
}
|
||||
|
||||
installIntent = new Intent(mContext, InstallExtensionDialogActivity.class);
|
||||
installIntent.setAction(InstallExtensionDialogActivity.ACTION_INSTALL);
|
||||
installIntent.setData(sanitizedUri);
|
||||
} else {
|
||||
installIntent = new Intent(mContext, DefaultInstallerActivity.class);
|
||||
installIntent.setAction(DefaultInstallerActivity.ACTION_INSTALL_PACKAGE);
|
||||
installIntent.putExtra(DefaultInstallerActivity.EXTRA_ORIGINATING_URI, originatingUri);
|
||||
installIntent.setData(sanitizedUri);
|
||||
}
|
||||
Intent installIntent = new Intent(mContext, DefaultInstallerActivity.class);
|
||||
installIntent.setAction(DefaultInstallerActivity.ACTION_INSTALL_PACKAGE);
|
||||
installIntent.putExtra(DefaultInstallerActivity.EXTRA_ORIGINATING_URI, originatingUri);
|
||||
installIntent.setData(sanitizedUri);
|
||||
|
||||
PendingIntent installPendingIntent = PendingIntent.getActivity(
|
||||
mContext.getApplicationContext(),
|
||||
@ -88,17 +72,10 @@ public class DefaultInstaller extends Installer {
|
||||
protected void uninstallPackage(String packageName) {
|
||||
sendBroadcastUninstall(packageName, Installer.ACTION_UNINSTALL_STARTED);
|
||||
|
||||
Intent uninstallIntent;
|
||||
// special case: F-Droid Privileged Extension
|
||||
if (packageName != null && packageName.equals(PrivilegedInstaller.PRIVILEGED_EXTENSION_PACKAGE_NAME)) {
|
||||
uninstallIntent = new Intent(mContext, InstallExtensionDialogActivity.class);
|
||||
uninstallIntent.setAction(InstallExtensionDialogActivity.ACTION_UNINSTALL);
|
||||
} else {
|
||||
uninstallIntent = new Intent(mContext, DefaultInstallerActivity.class);
|
||||
uninstallIntent.setAction(DefaultInstallerActivity.ACTION_UNINSTALL_PACKAGE);
|
||||
uninstallIntent.putExtra(
|
||||
DefaultInstallerActivity.EXTRA_UNINSTALL_PACKAGE_NAME, packageName);
|
||||
}
|
||||
Intent uninstallIntent = new Intent(mContext, DefaultInstallerActivity.class);
|
||||
uninstallIntent.setAction(DefaultInstallerActivity.ACTION_UNINSTALL_PACKAGE);
|
||||
uninstallIntent.putExtra(
|
||||
DefaultInstallerActivity.EXTRA_UNINSTALL_PACKAGE_NAME, packageName);
|
||||
PendingIntent uninstallPendingIntent = PendingIntent.getActivity(
|
||||
mContext.getApplicationContext(),
|
||||
packageName.hashCode(),
|
||||
|
@ -30,6 +30,7 @@ import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
|
||||
/**
|
||||
@ -207,9 +208,10 @@ public class DefaultInstallerActivity extends FragmentActivity {
|
||||
}
|
||||
default:
|
||||
case Activity.RESULT_FIRST_USER: {
|
||||
// AOSP actually returns Activity.RESULT_FIRST_USER if something breaks
|
||||
// AOSP returns Activity.RESULT_FIRST_USER on error
|
||||
installer.sendBroadcastInstall(mInstallUri, mInstallOriginatingUri,
|
||||
Installer.ACTION_INSTALL_INTERRUPTED, "error");
|
||||
Installer.ACTION_INSTALL_INTERRUPTED,
|
||||
getString(R.string.install_error_unknown));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -237,11 +239,10 @@ public class DefaultInstallerActivity extends FragmentActivity {
|
||||
}
|
||||
default:
|
||||
case Activity.RESULT_FIRST_USER: {
|
||||
// AOSP UninstallAppProgress actually returns
|
||||
// Activity.RESULT_FIRST_USER if something breaks
|
||||
// AOSP UninstallAppProgress returns RESULT_FIRST_USER on error
|
||||
installer.sendBroadcastUninstall(mUninstallPackageName,
|
||||
Installer.ACTION_UNINSTALL_INTERRUPTED,
|
||||
"error");
|
||||
getString(R.string.uninstall_error_unknown));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -43,13 +43,13 @@ public class ExtensionInstaller extends Installer {
|
||||
|
||||
@Override
|
||||
protected void installPackage(Uri uri, Uri originatingUri, String packageName) {
|
||||
sendBroadcastInstall(uri, originatingUri, Installer.ACTION_INSTALL_STARTED);
|
||||
|
||||
Uri sanitizedUri;
|
||||
try {
|
||||
sanitizedUri = Installer.prepareApkFile(mContext, uri, packageName);
|
||||
} catch (InstallFailedException e) {
|
||||
Log.e(TAG, "prepareApkFile failed", e);
|
||||
sendBroadcastInstall(uri, originatingUri, Installer.ACTION_INSTALL_INTERRUPTED,
|
||||
e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -57,10 +57,10 @@ public class ExtensionInstaller extends Installer {
|
||||
// NOTE: Disabled for debug builds to be able to use official extension from repo
|
||||
ApkSignatureVerifier signatureVerifier = new ApkSignatureVerifier(mContext);
|
||||
if (!BuildConfig.DEBUG && !signatureVerifier.hasFDroidSignature(new File(sanitizedUri.getPath()))) {
|
||||
throw new RuntimeException("APK signature of extension not correct!");
|
||||
sendBroadcastInstall(uri, originatingUri, Installer.ACTION_INSTALL_INTERRUPTED,
|
||||
"APK signature of extension not correct!");
|
||||
}
|
||||
Intent installIntent;
|
||||
installIntent = new Intent(mContext, InstallExtensionDialogActivity.class);
|
||||
Intent installIntent = new Intent(mContext, InstallExtensionDialogActivity.class);
|
||||
installIntent.setAction(InstallExtensionDialogActivity.ACTION_INSTALL);
|
||||
installIntent.setData(sanitizedUri);
|
||||
|
||||
@ -72,14 +72,16 @@ public class ExtensionInstaller extends Installer {
|
||||
|
||||
sendBroadcastInstall(uri, originatingUri,
|
||||
Installer.ACTION_INSTALL_USER_INTERACTION, installPendingIntent);
|
||||
|
||||
// don't use broadcasts for the rest of this special installer
|
||||
sendBroadcastInstall(uri, originatingUri, Installer.ACTION_INSTALL_COMPLETE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallPackage(String packageName) {
|
||||
sendBroadcastUninstall(packageName, Installer.ACTION_UNINSTALL_STARTED);
|
||||
|
||||
Intent uninstallIntent;
|
||||
uninstallIntent = new Intent(mContext, InstallExtensionDialogActivity.class);
|
||||
Intent uninstallIntent = new Intent(mContext, InstallExtensionDialogActivity.class);
|
||||
uninstallIntent.setAction(InstallExtensionDialogActivity.ACTION_UNINSTALL);
|
||||
|
||||
PendingIntent uninstallPendingIntent = PendingIntent.getActivity(
|
||||
@ -90,5 +92,8 @@ public class ExtensionInstaller extends Installer {
|
||||
|
||||
sendBroadcastUninstall(packageName,
|
||||
Installer.ACTION_UNINSTALL_USER_INTERACTION, uninstallPendingIntent);
|
||||
|
||||
// don't use broadcasts for the rest of this special installer
|
||||
sendBroadcastUninstall(packageName, Installer.ACTION_UNINSTALL_COMPLETE);
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import android.text.TextUtils;
|
||||
import org.fdroid.fdroid.AppDetails;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.compat.PackageManagerCompat;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.App;
|
||||
import org.fdroid.fdroid.net.Downloader;
|
||||
@ -274,15 +275,26 @@ public class InstallManagerService extends Service {
|
||||
Uri originatingUri =
|
||||
intent.getParcelableExtra(Installer.EXTRA_ORIGINATING_URI);
|
||||
String urlString = originatingUri.toString();
|
||||
removeFromActive(urlString);
|
||||
Apk apk = removeFromActive(urlString);
|
||||
|
||||
PackageManagerCompat.setInstaller(getPackageManager(), apk.packageName);
|
||||
|
||||
localBroadcastManager.unregisterReceiver(this);
|
||||
|
||||
break;
|
||||
}
|
||||
case Installer.ACTION_INSTALL_INTERRUPTED: {
|
||||
localBroadcastManager.unregisterReceiver(this);
|
||||
Uri originatingUri =
|
||||
intent.getParcelableExtra(Installer.EXTRA_ORIGINATING_URI);
|
||||
String urlString = originatingUri.toString();
|
||||
String errorMessage =
|
||||
intent.getStringExtra(Installer.EXTRA_ERROR_MESSAGE);
|
||||
|
||||
if (!TextUtils.isEmpty(errorMessage)) {
|
||||
App app = getAppFromActive(urlString);
|
||||
notifyError(app, urlString, errorMessage, false);
|
||||
}
|
||||
|
||||
localBroadcastManager.unregisterReceiver(this);
|
||||
break;
|
||||
}
|
||||
case Installer.ACTION_INSTALL_USER_INTERACTION: {
|
||||
@ -292,7 +304,7 @@ public class InstallManagerService extends Service {
|
||||
intent.getParcelableExtra(Installer.EXTRA_USER_INTERACTION_PI);
|
||||
Utils.debugLog(TAG, "originatingUri: " + originatingUri);
|
||||
|
||||
Apk apk = getFromActive(originatingUri.toString());
|
||||
Apk apk = getApkFromActive(originatingUri.toString());
|
||||
// show notification if app details is not visible
|
||||
if (AppDetails.isAppVisible(apk.packageName)) {
|
||||
cancelNotification(originatingUri.toString());
|
||||
@ -379,6 +391,25 @@ public class InstallManagerService extends Service {
|
||||
notificationManager.notify(downloadUrlId, notification);
|
||||
}
|
||||
|
||||
private void notifyError(App app, String urlString, String text, boolean uninstall) {
|
||||
String title;
|
||||
if (uninstall) {
|
||||
title = String.format(getString(R.string.uninstall_error_notify_title), app.name);
|
||||
} else {
|
||||
title = String.format(getString(R.string.install_error_notify_title), app.name);
|
||||
}
|
||||
|
||||
int downloadUrlId = urlString.hashCode();
|
||||
NotificationCompat.Builder builder =
|
||||
new NotificationCompat.Builder(this)
|
||||
.setAutoCancel(true)
|
||||
.setContentTitle(title)
|
||||
.setSmallIcon(R.drawable.ic_issues)
|
||||
.setContentText(text);
|
||||
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
nm.notify(downloadUrlId, builder.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the {@link Notification} tied to {@code urlString}, which is the
|
||||
* unique ID used to represent a given APK file. {@link String#hashCode()}
|
||||
@ -393,7 +424,7 @@ public class InstallManagerService extends Service {
|
||||
ACTIVE_APPS.put(app.packageName, app);
|
||||
}
|
||||
|
||||
private static Apk getFromActive(String urlString) {
|
||||
private static Apk getApkFromActive(String urlString) {
|
||||
return ACTIVE_APKS.get(urlString);
|
||||
}
|
||||
|
||||
@ -404,6 +435,10 @@ public class InstallManagerService extends Service {
|
||||
* {@link BroadcastReceiver}s, in which case {@code urlString} would not
|
||||
* find anything in the active maps.
|
||||
*/
|
||||
private static App getAppFromActive(String urlString) {
|
||||
return ACTIVE_APPS.get(getApkFromActive(urlString).packageName);
|
||||
}
|
||||
|
||||
private static Apk removeFromActive(String urlString) {
|
||||
Apk apk = ACTIVE_APKS.remove(urlString);
|
||||
if (apk != null) {
|
||||
|
@ -160,6 +160,9 @@ public abstract class Installer {
|
||||
// if (count < 0) {
|
||||
// mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
||||
// InstallerCallback.ERROR_CODE_CANNOT_PARSE);
|
||||
|
||||
// install_error_cannot_parse
|
||||
|
||||
// return;
|
||||
// }
|
||||
// if (count > 0) {
|
||||
|
@ -151,6 +151,8 @@ public class PrivilegedInstaller extends Installer {
|
||||
sanitizedUri = Installer.prepareApkFile(mContext, uri, packageName);
|
||||
} catch (Installer.InstallFailedException e) {
|
||||
Log.e(TAG, "prepareApkFile failed", e);
|
||||
sendBroadcastInstall(uri, originatingUri, Installer.ACTION_INSTALL_INTERRUPTED,
|
||||
e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -299,6 +301,9 @@ public class PrivilegedInstaller extends Installer {
|
||||
// } else if (resultCode == InstallConfirmActivity.RESULT_CANNOT_PARSE) {
|
||||
// mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
||||
// InstallerCallback.ERROR_CODE_CANNOT_PARSE);
|
||||
|
||||
// install_error_cannot_parse
|
||||
|
||||
// } else { // Activity.RESULT_CANCELED
|
||||
// mCallback.onError(InstallerCallback.OPERATION_INSTALL,
|
||||
// InstallerCallback.ERROR_CODE_CANCELED);
|
||||
|
@ -267,10 +267,8 @@
|
||||
<string name="requesting_root_access_body">Requesting root access…</string>
|
||||
<string name="root_access_denied_title">Root access denied</string>
|
||||
<string name="root_access_denied_body">Either your Android device is not rooted or you have denied root access for F-Droid.</string>
|
||||
<string name="install_error_title">Install error</string>
|
||||
<string name="install_error_unknown">Failed to install due to an unknown error</string>
|
||||
<string name="install_error_cannot_parse">An error occurred while parsing the package</string>
|
||||
<string name="uninstall_error_title">Uninstall error</string>
|
||||
<string name="uninstall_error_unknown">Failed to uninstall due to an unknown error</string>
|
||||
<string name="system_install_denied_title">F-Droid Privileged Extension is not available</string>
|
||||
<string name="system_install_denied_body">This option is only available when F-Droid Privileged Extension is installed.</string>
|
||||
@ -365,6 +363,9 @@
|
||||
<string name="tap_to_install">Download completed, tap to install</string>
|
||||
<string name="download_error">Download unsuccessful</string>
|
||||
<string name="download_pending">Waiting to start download…</string>
|
||||
<string name="install_error_notify_title">Error installing %s</string>
|
||||
<string name="uninstall_error_notify_title">Error uninstalling %s</string>
|
||||
|
||||
|
||||
<string name="perms_new_perm_prefix">New: </string>
|
||||
<string name="perms_description_app">Provided by %1$s.</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user