Loading packages/PackageInstaller/AndroidManifest.xml +12 −0 Original line number Diff line number Diff line Loading @@ -210,6 +210,18 @@ <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <activity android:name=".UnarchiveErrorActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:theme="@style/Theme.AlertDialogActivity.NoActionBar" android:excludeFromRecents="true" android:noHistory="true" android:exported="true"> <intent-filter android:priority="1"> <action android:name="com.android.intent.action.UNARCHIVE_ERROR_DIALOG" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application> </manifest> packages/PackageInstaller/res/values/strings.xml +82 −0 Original line number Diff line number Diff line Loading @@ -267,4 +267,86 @@ <!-- The action to restore (i.e. re-install, re-download) an app after parts of the app have been previously moved into the cloud for temporary storage. [CHAR LIMIT=15] --> <string name="restore">Restore</string> <!-- Dialog title shown when the user is trying to restore an app but the associated download cannot happen immediately because the device is offline (has no internet connection. [CHAR LIMIT=50] --> <string name="unarchive_error_offline_title">You\'re offline</string> <!-- Dialog body test shown when the user is trying to restore an app but the associated download cannot happen immediately because the device is offline (has no internet connection. [CHAR LIMIT=none] --> <string name="unarchive_error_offline_body"> This app will automatically restore when you\'re connected to the internet </string> <!-- Dialog title shown when the user is trying to restore an app but a generic error happened. [CHAR LIMIT=50] --> <string name="unarchive_error_generic_title">Something went wrong</string> <!-- Dialog body shown when the user is trying to restore an app but a generic error happened. [CHAR LIMIT=none] --> <string name="unarchive_error_generic_body"> There was a problem trying to restore this app </string> <!-- Dialog title shown when the user is trying to restore an app but the device is out of storage. [CHAR LIMIT=50] --> <string name="unarchive_error_storage_title">Not enough storage</string> <!-- Dialog body shown when the user is trying to restore an app but the device is out of storage. [CHAR LIMIT=none] --> <string name="unarchive_error_storage_body"> To restore this app, you can free up space on this device. Storage required: <xliff:g id="bytes" example="100 MB">%1$s</xliff:g> </string> <!-- Dialog title shown when the user is trying to restore an app but the installer needs to perform an additional action. [CHAR LIMIT=50] --> <string name="unarchive_action_required_title">Action required</string> <!-- Dialog body shown when the user is trying to restore an app but the installer needs to perform an additional action. [CHAR LIMIT=none] --> <string name="unarchive_action_required_body"> Follow the next steps to restore this app </string> <!-- Dialog title shown when the user is trying to restore an app but the installer responsible for the action is in a disabled state. [CHAR LIMIT=50] --> <string name="unarchive_error_installer_disabled_title"> <xliff:g id="installername" example="App Store">%1$s</xliff:g> is disabled </string> <!-- Dialog body shown when the user is trying to restore an app but the installer responsible for the action is in a disabled state. [CHAR LIMIT=none] --> <string name="unarchive_error_installer_disabled_body"> To restore this app, enable the <xliff:g id="installername" example="App Store">%1$s</xliff:g> in Settings </string> <!-- Dialog title shown when the user is trying to restore an app but the installer responsible for the action is uninstalled. [CHAR LIMIT=50] --> <string name="unarchive_error_installer_uninstalled_title"> <xliff:g id="installername" example="App Store">%1$s</xliff:g> is uninstalled </string> <!-- Dialog body shown when the user is trying to restore an app but the installer responsible for the action is uninstalled. [CHAR LIMIT=none] --> <string name="unarchive_error_installer_uninstalled_body"> To restore this app, you\'ll need to install <xliff:g id="installername" example="App Store">%1$s</xliff:g> </string> <!-- Dialog action to continue with the next action. [CHAR LIMIT=30] --> <string name="unarchive_action_required_continue">Continue</string> <!-- Dialog action to clear device storage, as in deleting some apps or photos to free up bytes [CHAR LIMIT=30] --> <string name="unarchive_clear_storage_button">Clear storage</string> <!-- Dialog action to open the Settings app. [CHAR LIMIT=30] --> <string name="unarchive_settings_button">Settings</string> <!-- Dialog action to close a dialog. [CHAR LIMIT=30] --> <string name="close">Close</string> </resources> packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorActivity.java 0 → 100644 +79 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.packageinstaller; import android.app.Activity; import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentTransaction; import android.app.PendingIntent; import android.content.Intent; import android.content.pm.PackageInstaller; import android.os.Bundle; import java.util.Objects; public class UnarchiveErrorActivity extends Activity { static final String EXTRA_REQUIRED_BYTES = "com.android.content.pm.extra.UNARCHIVE_EXTRA_REQUIRED_BYTES"; static final String EXTRA_INSTALLER_PACKAGE_NAME = "com.android.content.pm.extra.UNARCHIVE_INSTALLER_PACKAGE_NAME"; static final String EXTRA_INSTALLER_TITLE = "com.android.content.pm.extra.UNARCHIVE_INSTALLER_TITLE"; @Override public void onCreate(Bundle icicle) { super.onCreate(null); Bundle extras = getIntent().getExtras(); int unarchivalStatus = extras.getInt(PackageInstaller.EXTRA_UNARCHIVE_STATUS); long requiredBytes = extras.getLong(EXTRA_REQUIRED_BYTES); PendingIntent intent = extras.getParcelable(Intent.EXTRA_INTENT, PendingIntent.class); String installerPackageName = extras.getString(EXTRA_INSTALLER_PACKAGE_NAME); // We cannot derive this from the package name because the installer might not be installed // anymore. String installerAppTitle = extras.getString(EXTRA_INSTALLER_TITLE); if (unarchivalStatus == PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED) { Objects.requireNonNull(intent); } FragmentTransaction ft = getFragmentManager().beginTransaction(); Fragment prev = getFragmentManager().findFragmentByTag("dialog"); if (prev != null) { ft.remove(prev); } Bundle args = new Bundle(); args.putInt(PackageInstaller.EXTRA_UNARCHIVE_STATUS, unarchivalStatus); args.putLong(EXTRA_REQUIRED_BYTES, requiredBytes); if (intent != null) { args.putParcelable(Intent.EXTRA_INTENT, intent); } if (installerPackageName != null) { args.putString(EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName); } if (installerAppTitle != null) { args.putString(EXTRA_INSTALLER_TITLE, installerAppTitle); } DialogFragment fragment = new UnarchiveErrorFragment(); fragment.setArguments(args); fragment.show(ft, "dialog"); } } packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java 0 → 100644 +196 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.packageinstaller; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.app.PendingIntent; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender; import android.content.pm.PackageInstaller; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.text.format.Formatter; import android.util.Log; import androidx.annotation.Nullable; public class UnarchiveErrorFragment extends DialogFragment implements DialogInterface.OnClickListener { private static final String TAG = "UnarchiveErrorFragment"; private int mStatus; @Nullable private PendingIntent mExtraIntent; @Nullable private String mInstallerPackageName; @Override public Dialog onCreateDialog(Bundle savedInstanceState) { Bundle args = getArguments(); mStatus = args.getInt(PackageInstaller.EXTRA_UNARCHIVE_STATUS, -1); mExtraIntent = args.getParcelable(Intent.EXTRA_INTENT, PendingIntent.class); long requiredBytes = args.getLong(UnarchiveErrorActivity.EXTRA_REQUIRED_BYTES); mInstallerPackageName = args.getString( UnarchiveErrorActivity.EXTRA_INSTALLER_PACKAGE_NAME); String installerAppTitle = args.getString(UnarchiveErrorActivity.EXTRA_INSTALLER_TITLE); AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity()); dialogBuilder.setTitle(getDialogTitle(mStatus, installerAppTitle)); dialogBuilder.setMessage(getBodyText(mStatus, installerAppTitle, requiredBytes)); addButtons(dialogBuilder, mStatus); return dialogBuilder.create(); } private void addButtons(AlertDialog.Builder dialogBuilder, int status) { switch (status) { case PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED: dialogBuilder.setPositiveButton(R.string.unarchive_action_required_continue, this); dialogBuilder.setNegativeButton(R.string.close, this); break; case PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE: dialogBuilder.setPositiveButton(R.string.unarchive_clear_storage_button, this); dialogBuilder.setNegativeButton(R.string.close, this); break; case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED: dialogBuilder.setPositiveButton(R.string.external_sources_settings, this); dialogBuilder.setNegativeButton(R.string.close, this); break; case PackageInstaller.UNARCHIVAL_ERROR_NO_CONNECTIVITY: case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED: case PackageInstaller.UNARCHIVAL_GENERIC_ERROR: dialogBuilder.setPositiveButton(android.R.string.ok, this); break; default: // This should never happen through normal API usage. throw new IllegalArgumentException("Invalid unarchive status " + status); } } private String getBodyText(int status, String installerAppTitle, long requiredBytes) { switch (status) { case PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED: return getString(R.string.unarchive_action_required_body); case PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE: return String.format(getString(R.string.unarchive_error_storage_body), Formatter.formatShortFileSize(getActivity(), requiredBytes)); case PackageInstaller.UNARCHIVAL_ERROR_NO_CONNECTIVITY: return getString(R.string.unarchive_error_offline_body); case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED: return String.format(getString(R.string.unarchive_error_installer_disabled_body), installerAppTitle); case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED: return String.format( getString(R.string.unarchive_error_installer_uninstalled_body), installerAppTitle); case PackageInstaller.UNARCHIVAL_GENERIC_ERROR: return getString(R.string.unarchive_error_generic_body); default: // This should never happen through normal API usage. throw new IllegalArgumentException("Invalid unarchive status " + status); } } private String getDialogTitle(int status, String installerAppTitle) { switch (status) { case PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED: return getString(R.string.unarchive_action_required_title); case PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE: return getString(R.string.unarchive_error_storage_title); case PackageInstaller.UNARCHIVAL_ERROR_NO_CONNECTIVITY: return getString(R.string.unarchive_error_offline_title); case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED: return String.format(getString(R.string.unarchive_error_installer_disabled_title), installerAppTitle); case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED: return String.format( getString(R.string.unarchive_error_installer_uninstalled_title), installerAppTitle); case PackageInstaller.UNARCHIVAL_GENERIC_ERROR: return getString(R.string.unarchive_error_generic_title); default: // This should never happen through normal API usage. throw new IllegalArgumentException("Invalid unarchive status " + status); } } @Override public void onClick(DialogInterface dialog, int which) { if (which != Dialog.BUTTON_POSITIVE) { return; } try { onClickInternal(); } catch (IntentSender.SendIntentException e) { Log.e(TAG, "Failed to start intent after onClick.", e); } } private void onClickInternal() throws IntentSender.SendIntentException { Activity activity = getActivity(); if (activity == null) { // This probably shouldn't happen in practice. Log.i(TAG, "Lost reference to activity, cannot act onClick."); return; } switch (mStatus) { case PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED: activity.startIntentSender(mExtraIntent.getIntentSender(), /* fillInIntent= */ null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0); break; case PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE: if (mExtraIntent != null) { activity.startIntentSender(mExtraIntent.getIntentSender(), /* fillInIntent= */ null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0); } else { Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE"); startActivity(intent); } break; case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED: Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", mInstallerPackageName, null); intent.setData(uri); startActivity(intent); break; default: // Do nothing. The rest of the dialogs are purely informational. } } @Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); if (isAdded()) { getActivity().finish(); } } } Loading
packages/PackageInstaller/AndroidManifest.xml +12 −0 Original line number Diff line number Diff line Loading @@ -210,6 +210,18 @@ <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <activity android:name=".UnarchiveErrorActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:theme="@style/Theme.AlertDialogActivity.NoActionBar" android:excludeFromRecents="true" android:noHistory="true" android:exported="true"> <intent-filter android:priority="1"> <action android:name="com.android.intent.action.UNARCHIVE_ERROR_DIALOG" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application> </manifest>
packages/PackageInstaller/res/values/strings.xml +82 −0 Original line number Diff line number Diff line Loading @@ -267,4 +267,86 @@ <!-- The action to restore (i.e. re-install, re-download) an app after parts of the app have been previously moved into the cloud for temporary storage. [CHAR LIMIT=15] --> <string name="restore">Restore</string> <!-- Dialog title shown when the user is trying to restore an app but the associated download cannot happen immediately because the device is offline (has no internet connection. [CHAR LIMIT=50] --> <string name="unarchive_error_offline_title">You\'re offline</string> <!-- Dialog body test shown when the user is trying to restore an app but the associated download cannot happen immediately because the device is offline (has no internet connection. [CHAR LIMIT=none] --> <string name="unarchive_error_offline_body"> This app will automatically restore when you\'re connected to the internet </string> <!-- Dialog title shown when the user is trying to restore an app but a generic error happened. [CHAR LIMIT=50] --> <string name="unarchive_error_generic_title">Something went wrong</string> <!-- Dialog body shown when the user is trying to restore an app but a generic error happened. [CHAR LIMIT=none] --> <string name="unarchive_error_generic_body"> There was a problem trying to restore this app </string> <!-- Dialog title shown when the user is trying to restore an app but the device is out of storage. [CHAR LIMIT=50] --> <string name="unarchive_error_storage_title">Not enough storage</string> <!-- Dialog body shown when the user is trying to restore an app but the device is out of storage. [CHAR LIMIT=none] --> <string name="unarchive_error_storage_body"> To restore this app, you can free up space on this device. Storage required: <xliff:g id="bytes" example="100 MB">%1$s</xliff:g> </string> <!-- Dialog title shown when the user is trying to restore an app but the installer needs to perform an additional action. [CHAR LIMIT=50] --> <string name="unarchive_action_required_title">Action required</string> <!-- Dialog body shown when the user is trying to restore an app but the installer needs to perform an additional action. [CHAR LIMIT=none] --> <string name="unarchive_action_required_body"> Follow the next steps to restore this app </string> <!-- Dialog title shown when the user is trying to restore an app but the installer responsible for the action is in a disabled state. [CHAR LIMIT=50] --> <string name="unarchive_error_installer_disabled_title"> <xliff:g id="installername" example="App Store">%1$s</xliff:g> is disabled </string> <!-- Dialog body shown when the user is trying to restore an app but the installer responsible for the action is in a disabled state. [CHAR LIMIT=none] --> <string name="unarchive_error_installer_disabled_body"> To restore this app, enable the <xliff:g id="installername" example="App Store">%1$s</xliff:g> in Settings </string> <!-- Dialog title shown when the user is trying to restore an app but the installer responsible for the action is uninstalled. [CHAR LIMIT=50] --> <string name="unarchive_error_installer_uninstalled_title"> <xliff:g id="installername" example="App Store">%1$s</xliff:g> is uninstalled </string> <!-- Dialog body shown when the user is trying to restore an app but the installer responsible for the action is uninstalled. [CHAR LIMIT=none] --> <string name="unarchive_error_installer_uninstalled_body"> To restore this app, you\'ll need to install <xliff:g id="installername" example="App Store">%1$s</xliff:g> </string> <!-- Dialog action to continue with the next action. [CHAR LIMIT=30] --> <string name="unarchive_action_required_continue">Continue</string> <!-- Dialog action to clear device storage, as in deleting some apps or photos to free up bytes [CHAR LIMIT=30] --> <string name="unarchive_clear_storage_button">Clear storage</string> <!-- Dialog action to open the Settings app. [CHAR LIMIT=30] --> <string name="unarchive_settings_button">Settings</string> <!-- Dialog action to close a dialog. [CHAR LIMIT=30] --> <string name="close">Close</string> </resources>
packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorActivity.java 0 → 100644 +79 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.packageinstaller; import android.app.Activity; import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentTransaction; import android.app.PendingIntent; import android.content.Intent; import android.content.pm.PackageInstaller; import android.os.Bundle; import java.util.Objects; public class UnarchiveErrorActivity extends Activity { static final String EXTRA_REQUIRED_BYTES = "com.android.content.pm.extra.UNARCHIVE_EXTRA_REQUIRED_BYTES"; static final String EXTRA_INSTALLER_PACKAGE_NAME = "com.android.content.pm.extra.UNARCHIVE_INSTALLER_PACKAGE_NAME"; static final String EXTRA_INSTALLER_TITLE = "com.android.content.pm.extra.UNARCHIVE_INSTALLER_TITLE"; @Override public void onCreate(Bundle icicle) { super.onCreate(null); Bundle extras = getIntent().getExtras(); int unarchivalStatus = extras.getInt(PackageInstaller.EXTRA_UNARCHIVE_STATUS); long requiredBytes = extras.getLong(EXTRA_REQUIRED_BYTES); PendingIntent intent = extras.getParcelable(Intent.EXTRA_INTENT, PendingIntent.class); String installerPackageName = extras.getString(EXTRA_INSTALLER_PACKAGE_NAME); // We cannot derive this from the package name because the installer might not be installed // anymore. String installerAppTitle = extras.getString(EXTRA_INSTALLER_TITLE); if (unarchivalStatus == PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED) { Objects.requireNonNull(intent); } FragmentTransaction ft = getFragmentManager().beginTransaction(); Fragment prev = getFragmentManager().findFragmentByTag("dialog"); if (prev != null) { ft.remove(prev); } Bundle args = new Bundle(); args.putInt(PackageInstaller.EXTRA_UNARCHIVE_STATUS, unarchivalStatus); args.putLong(EXTRA_REQUIRED_BYTES, requiredBytes); if (intent != null) { args.putParcelable(Intent.EXTRA_INTENT, intent); } if (installerPackageName != null) { args.putString(EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName); } if (installerAppTitle != null) { args.putString(EXTRA_INSTALLER_TITLE, installerAppTitle); } DialogFragment fragment = new UnarchiveErrorFragment(); fragment.setArguments(args); fragment.show(ft, "dialog"); } }
packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java 0 → 100644 +196 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.packageinstaller; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.app.PendingIntent; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender; import android.content.pm.PackageInstaller; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.text.format.Formatter; import android.util.Log; import androidx.annotation.Nullable; public class UnarchiveErrorFragment extends DialogFragment implements DialogInterface.OnClickListener { private static final String TAG = "UnarchiveErrorFragment"; private int mStatus; @Nullable private PendingIntent mExtraIntent; @Nullable private String mInstallerPackageName; @Override public Dialog onCreateDialog(Bundle savedInstanceState) { Bundle args = getArguments(); mStatus = args.getInt(PackageInstaller.EXTRA_UNARCHIVE_STATUS, -1); mExtraIntent = args.getParcelable(Intent.EXTRA_INTENT, PendingIntent.class); long requiredBytes = args.getLong(UnarchiveErrorActivity.EXTRA_REQUIRED_BYTES); mInstallerPackageName = args.getString( UnarchiveErrorActivity.EXTRA_INSTALLER_PACKAGE_NAME); String installerAppTitle = args.getString(UnarchiveErrorActivity.EXTRA_INSTALLER_TITLE); AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity()); dialogBuilder.setTitle(getDialogTitle(mStatus, installerAppTitle)); dialogBuilder.setMessage(getBodyText(mStatus, installerAppTitle, requiredBytes)); addButtons(dialogBuilder, mStatus); return dialogBuilder.create(); } private void addButtons(AlertDialog.Builder dialogBuilder, int status) { switch (status) { case PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED: dialogBuilder.setPositiveButton(R.string.unarchive_action_required_continue, this); dialogBuilder.setNegativeButton(R.string.close, this); break; case PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE: dialogBuilder.setPositiveButton(R.string.unarchive_clear_storage_button, this); dialogBuilder.setNegativeButton(R.string.close, this); break; case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED: dialogBuilder.setPositiveButton(R.string.external_sources_settings, this); dialogBuilder.setNegativeButton(R.string.close, this); break; case PackageInstaller.UNARCHIVAL_ERROR_NO_CONNECTIVITY: case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED: case PackageInstaller.UNARCHIVAL_GENERIC_ERROR: dialogBuilder.setPositiveButton(android.R.string.ok, this); break; default: // This should never happen through normal API usage. throw new IllegalArgumentException("Invalid unarchive status " + status); } } private String getBodyText(int status, String installerAppTitle, long requiredBytes) { switch (status) { case PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED: return getString(R.string.unarchive_action_required_body); case PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE: return String.format(getString(R.string.unarchive_error_storage_body), Formatter.formatShortFileSize(getActivity(), requiredBytes)); case PackageInstaller.UNARCHIVAL_ERROR_NO_CONNECTIVITY: return getString(R.string.unarchive_error_offline_body); case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED: return String.format(getString(R.string.unarchive_error_installer_disabled_body), installerAppTitle); case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED: return String.format( getString(R.string.unarchive_error_installer_uninstalled_body), installerAppTitle); case PackageInstaller.UNARCHIVAL_GENERIC_ERROR: return getString(R.string.unarchive_error_generic_body); default: // This should never happen through normal API usage. throw new IllegalArgumentException("Invalid unarchive status " + status); } } private String getDialogTitle(int status, String installerAppTitle) { switch (status) { case PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED: return getString(R.string.unarchive_action_required_title); case PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE: return getString(R.string.unarchive_error_storage_title); case PackageInstaller.UNARCHIVAL_ERROR_NO_CONNECTIVITY: return getString(R.string.unarchive_error_offline_title); case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED: return String.format(getString(R.string.unarchive_error_installer_disabled_title), installerAppTitle); case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED: return String.format( getString(R.string.unarchive_error_installer_uninstalled_title), installerAppTitle); case PackageInstaller.UNARCHIVAL_GENERIC_ERROR: return getString(R.string.unarchive_error_generic_title); default: // This should never happen through normal API usage. throw new IllegalArgumentException("Invalid unarchive status " + status); } } @Override public void onClick(DialogInterface dialog, int which) { if (which != Dialog.BUTTON_POSITIVE) { return; } try { onClickInternal(); } catch (IntentSender.SendIntentException e) { Log.e(TAG, "Failed to start intent after onClick.", e); } } private void onClickInternal() throws IntentSender.SendIntentException { Activity activity = getActivity(); if (activity == null) { // This probably shouldn't happen in practice. Log.i(TAG, "Lost reference to activity, cannot act onClick."); return; } switch (mStatus) { case PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED: activity.startIntentSender(mExtraIntent.getIntentSender(), /* fillInIntent= */ null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0); break; case PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE: if (mExtraIntent != null) { activity.startIntentSender(mExtraIntent.getIntentSender(), /* fillInIntent= */ null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0); } else { Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE"); startActivity(intent); } break; case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED: Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", mInstallerPackageName, null); intent.setData(uri); startActivity(intent); break; default: // Do nothing. The rest of the dialogs are purely informational. } } @Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); if (isAdded()) { getActivity().finish(); } } }