More work on device admins:
- You can now show a dynamic message to the user when asking to
have your DeviceAdmin added.
- A DeviceAdmin can now provide a warning message that is displayed
before a user disables it.
- Better ordering (and text) of the policy warnings.
- New API to set the maximum failed password attempts before the device
wipes itself.
- We now store the number of failed unlock attempts in persistent
storage.
- New managed dialog APIs that will be used by the settings app.
Also a little bit of cleanup as I was working on this - removed the
long unused MailboxNotAvailableException, fixed a java doc in Messenger.
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index ca15a99..95142e3 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -609,8 +609,13 @@
private static final String SAVED_DIALOG_IDS_KEY = "android:savedDialogIds";
private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";
private static final String SAVED_DIALOG_KEY_PREFIX = "android:dialog_";
+ private static final String SAVED_DIALOG_ARGS_KEY_PREFIX = "android:dialog_args_";
- private SparseArray<Dialog> mManagedDialogs;
+ private static class ManagedDialog {
+ Dialog mDialog;
+ Bundle mArgs;
+ }
+ private SparseArray<ManagedDialog> mManagedDialogs;
// set by the thread after the constructor and before onCreate(Bundle savedInstanceState) is called.
private Instrumentation mInstrumentation;
@@ -851,35 +856,41 @@
final int[] ids = b.getIntArray(SAVED_DIALOG_IDS_KEY);
final int numDialogs = ids.length;
- mManagedDialogs = new SparseArray<Dialog>(numDialogs);
+ mManagedDialogs = new SparseArray<ManagedDialog>(numDialogs);
for (int i = 0; i < numDialogs; i++) {
final Integer dialogId = ids[i];
Bundle dialogState = b.getBundle(savedDialogKeyFor(dialogId));
if (dialogState != null) {
// Calling onRestoreInstanceState() below will invoke dispatchOnCreate
// so tell createDialog() not to do it, otherwise we get an exception
- final Dialog dialog = createDialog(dialogId, dialogState);
- mManagedDialogs.put(dialogId, dialog);
- onPrepareDialog(dialogId, dialog);
- dialog.onRestoreInstanceState(dialogState);
+ final ManagedDialog md = new ManagedDialog();
+ md.mArgs = b.getBundle(savedDialogArgsKeyFor(dialogId));
+ md.mDialog = createDialog(dialogId, dialogState, md.mArgs);
+ if (md.mDialog != null) {
+ mManagedDialogs.put(dialogId, md);
+ onPrepareDialog(dialogId, md.mDialog, md.mArgs);
+ md.mDialog.onRestoreInstanceState(dialogState);
+ }
}
}
}
- private Dialog createDialog(Integer dialogId, Bundle state) {
- final Dialog dialog = onCreateDialog(dialogId);
+ private Dialog createDialog(Integer dialogId, Bundle state, Bundle args) {
+ final Dialog dialog = onCreateDialog(dialogId, args);
if (dialog == null) {
- throw new IllegalArgumentException("Activity#onCreateDialog did "
- + "not create a dialog for id " + dialogId);
+ return null;
}
dialog.dispatchOnCreate(state);
return dialog;
}
- private String savedDialogKeyFor(int key) {
+ private static String savedDialogKeyFor(int key) {
return SAVED_DIALOG_KEY_PREFIX + key;
}
+ private static String savedDialogArgsKeyFor(int key) {
+ return SAVED_DIALOG_ARGS_KEY_PREFIX + key;
+ }
/**
* Called when activity start-up is complete (after {@link #onStart}
@@ -1096,8 +1107,11 @@
for (int i = 0; i < numDialogs; i++) {
final int key = mManagedDialogs.keyAt(i);
ids[i] = key;
- final Dialog dialog = mManagedDialogs.valueAt(i);
- dialogState.putBundle(savedDialogKeyFor(key), dialog.onSaveInstanceState());
+ final ManagedDialog md = mManagedDialogs.valueAt(i);
+ dialogState.putBundle(savedDialogKeyFor(key), md.mDialog.onSaveInstanceState());
+ if (md.mArgs != null) {
+ dialogState.putBundle(savedDialogArgsKeyFor(key), md.mArgs);
+ }
}
dialogState.putIntArray(SAVED_DIALOG_IDS_KEY, ids);
@@ -1283,14 +1297,14 @@
// dismiss any dialogs we are managing.
if (mManagedDialogs != null) {
-
final int numDialogs = mManagedDialogs.size();
for (int i = 0; i < numDialogs; i++) {
- final Dialog dialog = mManagedDialogs.valueAt(i);
- if (dialog.isShowing()) {
- dialog.dismiss();
+ final ManagedDialog md = mManagedDialogs.valueAt(i);
+ if (md.mDialog.isShowing()) {
+ md.mDialog.dismiss();
}
}
+ mManagedDialogs = null;
}
// close any cursors we are managing.
@@ -1301,6 +1315,7 @@
c.mCursor.close();
}
}
+ mManagedCursors.clear();
}
/**
@@ -2411,36 +2426,57 @@
}
/**
- * Callback for creating dialogs that are managed (saved and restored) for you
- * by the activity.
- *
- * If you use {@link #showDialog(int)}, the activity will call through to
- * this method the first time, and hang onto it thereafter. Any dialog
- * that is created by this method will automatically be saved and restored
- * for you, including whether it is showing.
- *
- * If you would like the activity to manage the saving and restoring dialogs
- * for you, you should override this method and handle any ids that are
- * passed to {@link #showDialog}.
- *
- * If you would like an opportunity to prepare your dialog before it is shown,
- * override {@link #onPrepareDialog(int, Dialog)}.
- *
- * @param id The id of the dialog.
- * @return The dialog
- *
- * @see #onPrepareDialog(int, Dialog)
- * @see #showDialog(int)
- * @see #dismissDialog(int)
- * @see #removeDialog(int)
+ * @deprecated Old no-arguments version of {@link #onCreateDialog(int, Bundle)}.
*/
+ @Deprecated
protected Dialog onCreateDialog(int id) {
return null;
}
/**
+ * Callback for creating dialogs that are managed (saved and restored) for you
+ * by the activity. The default implementation calls through to
+ * {@link #onCreateDialog(int)} for compatibility.
+ *
+ * <p>If you use {@link #showDialog(int)}, the activity will call through to
+ * this method the first time, and hang onto it thereafter. Any dialog
+ * that is created by this method will automatically be saved and restored
+ * for you, including whether it is showing.
+ *
+ * <p>If you would like the activity to manage saving and restoring dialogs
+ * for you, you should override this method and handle any ids that are
+ * passed to {@link #showDialog}.
+ *
+ * <p>If you would like an opportunity to prepare your dialog before it is shown,
+ * override {@link #onPrepareDialog(int, Dialog, Bundle)}.
+ *
+ * @param id The id of the dialog.
+ * @param args The dialog arguments provided to {@link #showDialog(int, Bundle)}.
+ * @return The dialog. If you return null, the dialog will not be created.
+ *
+ * @see #onPrepareDialog(int, Dialog, Bundle)
+ * @see #showDialog(int, Bundle)
+ * @see #dismissDialog(int)
+ * @see #removeDialog(int)
+ */
+ protected Dialog onCreateDialog(int id, Bundle args) {
+ return onCreateDialog(id);
+ }
+
+ /**
+ * @deprecated Old no-arguments version of
+ * {@link #onPrepareDialog(int, Dialog, Bundle)}.
+ */
+ @Deprecated
+ protected void onPrepareDialog(int id, Dialog dialog) {
+ dialog.setOwnerActivity(this);
+ }
+
+ /**
* Provides an opportunity to prepare a managed dialog before it is being
- * shown.
+ * shown. The default implementation calls through to
+ * {@link #onPrepareDialog(int, Dialog)} for compatibility.
+ *
* <p>
* Override this if you need to update a managed dialog based on the state
* of the application each time it is shown. For example, a time picker
@@ -2450,43 +2486,66 @@
*
* @param id The id of the managed dialog.
* @param dialog The dialog.
- * @see #onCreateDialog(int)
+ * @param args The dialog arguments provided to {@link #showDialog(int, Bundle)}.
+ * @see #onCreateDialog(int, Bundle)
* @see #showDialog(int)
* @see #dismissDialog(int)
* @see #removeDialog(int)
*/
- protected void onPrepareDialog(int id, Dialog dialog) {
- dialog.setOwnerActivity(this);
+ protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
+ onPrepareDialog(id, dialog);
}
/**
- * Show a dialog managed by this activity. A call to {@link #onCreateDialog(int)}
+ * Simple version of {@link #showDialog(int, Bundle)} that does not
+ * take any arguments. Simply calls {@link #showDialog(int, Bundle)}
+ * with null arguments.
+ */
+ public final void showDialog(int id) {
+ showDialog(id, null);
+ }
+
+ /**
+ * Show a dialog managed by this activity. A call to {@link #onCreateDialog(int, Bundle)}
* will be made with the same id the first time this is called for a given
* id. From thereafter, the dialog will be automatically saved and restored.
*
- * Each time a dialog is shown, {@link #onPrepareDialog(int, Dialog)} will
+ * <p>Each time a dialog is shown, {@link #onPrepareDialog(int, Dialog, Bundle)} will
* be made to provide an opportunity to do any timely preparation.
*
* @param id The id of the managed dialog.
- *
+ * @param args Arguments to pass through to the dialog. These will be saved
+ * and restored for you. Note that if the dialog is already created,
+ * {@link #onCreateDialog(int, Bundle)} will not be called with the new
+ * arguments but {@link #onPrepareDialog(int, Dialog, Bundle)} will be.
+ * If you need to rebuild the dialog, call {@link #removeDialog(int)}Êfirst.
+ * @return Returns true if the Dialog was created; false is returned if
+ * it is not created because {@link #onCreateDialog(int, Bundle)} returns false.
+ *
* @see Dialog
- * @see #onCreateDialog(int)
- * @see #onPrepareDialog(int, Dialog)
+ * @see #onCreateDialog(int, Bundle)
+ * @see #onPrepareDialog(int, Dialog, Bundle)
* @see #dismissDialog(int)
* @see #removeDialog(int)
*/
- public final void showDialog(int id) {
+ public final boolean showDialog(int id, Bundle args) {
if (mManagedDialogs == null) {
- mManagedDialogs = new SparseArray<Dialog>();
+ mManagedDialogs = new SparseArray<ManagedDialog>();
}
- Dialog dialog = mManagedDialogs.get(id);
- if (dialog == null) {
- dialog = createDialog(id, null);
- mManagedDialogs.put(id, dialog);
+ ManagedDialog md = mManagedDialogs.get(id);
+ if (md == null) {
+ md = new ManagedDialog();
+ md.mDialog = createDialog(id, null, args);
+ if (md.mDialog == null) {
+ return false;
+ }
+ mManagedDialogs.put(id, md);
}
- onPrepareDialog(id, dialog);
- dialog.show();
+ md.mArgs = args;
+ onPrepareDialog(id, md.mDialog, args);
+ md.mDialog.show();
+ return true;
}
/**
@@ -2497,21 +2556,21 @@
* @throws IllegalArgumentException if the id was not previously shown via
* {@link #showDialog(int)}.
*
- * @see #onCreateDialog(int)
- * @see #onPrepareDialog(int, Dialog)
+ * @see #onCreateDialog(int, Bundle)
+ * @see #onPrepareDialog(int, Dialog, Bundle)
* @see #showDialog(int)
* @see #removeDialog(int)
*/
public final void dismissDialog(int id) {
if (mManagedDialogs == null) {
throw missingDialog(id);
-
}
- final Dialog dialog = mManagedDialogs.get(id);
- if (dialog == null) {
+
+ final ManagedDialog md = mManagedDialogs.get(id);
+ if (md == null) {
throw missingDialog(id);
}
- dialog.dismiss();
+ md.mDialog.dismiss();
}
/**
@@ -2527,28 +2586,27 @@
* Removes any internal references to a dialog managed by this Activity.
* If the dialog is showing, it will dismiss it as part of the clean up.
*
- * This can be useful if you know that you will never show a dialog again and
+ * <p>This can be useful if you know that you will never show a dialog again and
* want to avoid the overhead of saving and restoring it in the future.
*
* @param id The id of the managed dialog.
*
- * @see #onCreateDialog(int)
- * @see #onPrepareDialog(int, Dialog)
+ * @see #onCreateDialog(int, Bundle)
+ * @see #onPrepareDialog(int, Dialog, Bundle)
* @see #showDialog(int)
* @see #dismissDialog(int)
*/
public final void removeDialog(int id) {
-
if (mManagedDialogs == null) {
return;
}
- final Dialog dialog = mManagedDialogs.get(id);
- if (dialog == null) {
+ final ManagedDialog md = mManagedDialogs.get(id);
+ if (md == null) {
return;
}
- dialog.dismiss();
+ md.mDialog.dismiss();
mManagedDialogs.remove(id);
}