/** * Return information about who launched this activity. If the launching Intent * contains an {@link android.content.Intent#EXTRA_REFERRER Intent.EXTRA_REFERRER}, * that will be returned as-is; otherwise, if known, an * {@link Intent#URI_ANDROID_APP_SCHEME android-app:} referrer URI containing the * package name that started the Intent will be returned. This may return null if no * referrer can be identified -- it is neither explicitly specified, nor is it known which * application package was involved. * * <p>If called while inside the handling of {@link #onNewIntent}, this function will * return the referrer that submitted that new intent to the activity. Otherwise, it * always returns the referrer of the original Intent.</p> * * <p>Note that this is <em>not</em> a security feature -- you can not trust the * referrer information, applications can spoof it.</p> */ @Nullable public Uri getReferrer() { Intent intent = getIntent(); try { Uri referrer = intent.getParcelableExtra(Intent.EXTRA_REFERRER); if (referrer != null) { return referrer; } String referrerName = intent.getStringExtra(Intent.EXTRA_REFERRER_NAME); if (referrerName != null) { return Uri.parse(referrerName); } } catch (BadParcelableException e) { Log.w(TAG, "Cannot read referrer from intent;" + " intent extras contain unknown custom Parcelable objects"); } if (mReferrer != null) { return new Uri.Builder().scheme("android-app").authority(mReferrer).build(); } return null; }
/** * A special variation to launch an activity only if a new activity * instance is needed to handle the given Intent. In other words, this is * just like {@link #startActivityForResult(Intent, int)} except: if you are * using the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP} flag, or * singleTask or singleTop * {@link android.R.styleable#AndroidManifestActivity_launchMode launchMode}, * and the activity * that handles <var>intent</var> is the same as your currently running * activity, then a new instance is not needed. In this case, instead of * the normal behavior of calling {@link #onNewIntent} this function will * return and you can handle the Intent yourself. * * <p>This function can only be called from a top-level activity; if it is * called from a child activity, a runtime exception will be thrown. * * @param intent The intent to start. * @param requestCode If >= 0, this code will be returned in * onActivityResult() when the activity exits, as described in * {@link #startActivityForResult}. * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. * * @return If a new activity was launched then true is returned; otherwise * false is returned and you must handle the Intent yourself. * * @see #startActivity * @see #startActivityForResult */ public boolean startActivityIfNeeded(@RequiresPermission @NonNull Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { int result = ActivityManager.START_RETURN_INTENT_TO_CALLER; try { Uri referrer = onProvideReferrer(); if (referrer != null) { intent.putExtra(Intent.EXTRA_REFERRER, referrer); } intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(this); result = ActivityManagerNative.getDefault() .startActivity(mMainThread.getApplicationThread(), getBasePackageName(), intent, intent.resolveTypeIfNeeded(getContentResolver()), mToken, mEmbeddedID, requestCode, ActivityManager.START_FLAG_ONLY_IF_NEEDED, null, options); } catch (RemoteException e) { // Empty } Instrumentation.checkStartActivityResult(result, intent); if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } return result != ActivityManager.START_RETURN_INTENT_TO_CALLER; } throw new UnsupportedOperationException( "startActivityIfNeeded can only be called from a top-level activity"); }
/** * @hide */ @Override public void startActivityForResult( String who, Intent intent, int requestCode, @Nullable Bundle options) { Uri referrer = onProvideReferrer(); if (referrer != null) { intent.putExtra(Intent.EXTRA_REFERRER, referrer); } options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, who, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, who, requestCode, ar.getResultCode(), ar.getResultData()); } cancelInputsAndStartExitTransition(options); }
/** * Start a new activity as if it was started by the activity that started our * current activity. This is for the resolver and chooser activities, which operate * as intermediaries that dispatch their intent to the target the user selects -- to * do this, they must perform all security checks including permission grants as if * their launch had come from the original activity. * @param intent The Intent to start. * @param options ActivityOptions or null. * @param ignoreTargetSecurity If true, the activity manager will not check whether the * caller it is doing the start is, is actually allowed to start the target activity. * If you set this to true, you must set an explicit component in the Intent and do any * appropriate security checks yourself. * @param userId The user the new activity should run as. * @hide */ public void startActivityAsCaller(Intent intent, @Nullable Bundle options, boolean ignoreTargetSecurity, int userId) { if (mParent != null) { throw new RuntimeException("Can't be called from a child"); } options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivityAsCaller( this, mMainThread.getApplicationThread(), mToken, this, intent, -1, options, ignoreTargetSecurity, userId); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, -1, ar.getResultCode(), ar.getResultData()); } cancelInputsAndStartExitTransition(options); }
/** * Obtain an {@link Intent} that will launch an explicit target activity specified by * this activity's logical parent. The logical parent is named in the application's manifest * by the {@link android.R.attr#parentActivityName parentActivityName} attribute. * Activity subclasses may override this method to modify the Intent returned by * super.getParentActivityIntent() or to implement a different mechanism of retrieving * the parent intent entirely. * * @return a new Intent targeting the defined parent of this activity or null if * there is no valid parent. */ @Nullable public Intent getParentActivityIntent() { final String parentName = mActivityInfo.parentActivityName; if (TextUtils.isEmpty(parentName)) { return null; } // If the parent itself has no parent, generate a main activity intent. final ComponentName target = new ComponentName(this, parentName); try { final ActivityInfo parentInfo = getPackageManager().getActivityInfo(target, 0); final String parentActivity = parentInfo.parentActivityName; final Intent parentIntent = parentActivity == null ? Intent.makeMainActivity(target) : new Intent().setComponent(target); return parentIntent; } catch (NameNotFoundException e) { Log.e(TAG, "getParentActivityIntent: bad parentActivityName '" + parentName + "' in manifest"); return null; } }
/** * Called when the activity is starting. This is where most initialization * should go: calling {@link #setContentView(int)} to inflate the * activity's UI, using {@link #findViewById} to programmatically interact * with widgets in the UI, calling * {@link #managedQuery(android.net.Uri , String[], String, String[], String)} to retrieve * cursors for data being displayed, etc. * * <p>You can call {@link #finish} from within this function, in * which case onDestroy() will be immediately called without any of the rest * of the activity lifecycle ({@link #onStart}, {@link #onResume}, * {@link #onPause}, etc) executing. * * <p><em>Derived classes must call through to the super class's * implementation of this method. If they do not, an exception will be * thrown.</em></p> * * @param savedInstanceState If the activity is being re-initialized after * previously being shut down then this Bundle contains the data it most * recently supplied in {@link #onSaveInstanceState}. <b><i>Note: Otherwise it is null.</i></b> * * @see #onStart * @see #onSaveInstanceState * @see #onRestoreInstanceState * @see #onPostCreate */ @MainThread @CallSuper protected void onCreate(@Nullable Bundle savedInstanceState) { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState); if (mLastNonConfigurationInstances != null) { mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders); } if (mActivityInfo.parentActivityName != null) { if (mActionBar == null) { mEnableDefaultActionBarUp = true; } else { mActionBar.setDefaultDisplayHomeAsUpEnabled(true); } } if (savedInstanceState != null) { Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG); mFragments.restoreAllState(p, mLastNonConfigurationInstances != null ? mLastNonConfigurationInstances.fragments : null); } mFragments.dispatchCreate(); getApplication().dispatchActivityCreated(this, savedInstanceState); if (mVoiceInteractor != null) { mVoiceInteractor.attachActivity(this); } mCalled = true; }
/** * Set a {@link android.widget.Toolbar Toolbar} to act as the {@link ActionBar} for this * Activity window. * * <p>When set to a non-null value the {@link #getActionBar()} method will return * an {@link ActionBar} object that can be used to control the given toolbar as if it were * a traditional window decor action bar. The toolbar's menu will be populated with the * Activity's options menu and the navigation button will be wired through the standard * {@link android.R.id#home home} menu select action.</p> * * <p>In order to use a Toolbar within the Activity's window content the application * must not request the window feature {@link Window#FEATURE_ACTION_BAR FEATURE_ACTION_BAR}.</p> * * @param toolbar Toolbar to set as the Activity's action bar, or {@code null} to clear it */ public void setActionBar(@Nullable Toolbar toolbar) { final ActionBar ab = getActionBar(); if (ab instanceof WindowDecorActionBar) { throw new IllegalStateException("This Activity already has an action bar supplied " + "by the window decor. Do not request Window.FEATURE_ACTION_BAR and set " + "android:windowActionBar to false in your theme to use a Toolbar instead."); } // If we reach here then we're setting a new action bar // First clear out the MenuInflater to make sure that it is valid for the new Action Bar mMenuInflater = null; // If we have an action bar currently, destroy it if (ab != null) { ab.onDestroy(); } if (toolbar != null) { final ToolbarActionBar tbab = new ToolbarActionBar(toolbar, getTitle(), this); mActionBar = tbab; mWindow.setCallback(tbab.getWrappedWindowCallback()); } else { mActionBar = null; // Re-set the original window callback since we may have already set a Toolbar wrapper mWindow.setCallback(this); } invalidateOptionsMenu(); }
/** * Like {@link #startIntentSenderFromChild}, but taking a Fragment; see * {@link #startIntentSenderForResult(IntentSender, int, Intent, int, int, int)} * for more information. * * @hide */ public void startIntentSenderFromChildFragment(Fragment child, IntentSender intent, int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, @Nullable Bundle options) throws IntentSender.SendIntentException { startIntentSenderForResultInner(intent, child.mWho, requestCode, fillInIntent, flagsMask, flagsValues, options); }
/** * Launch an activity for which you would like a result when it finished. * When this activity exits, your * onActivityResult() method will be called with the given requestCode. * Using a negative requestCode is the same as calling * {@link #startActivity} (the activity is not launched as a sub-activity). * * <p>Note that this method should only be used with Intent protocols * that are defined to return a result. In other protocols (such as * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may * not get the result when you expect. For example, if the activity you * are launching uses the singleTask launch mode, it will not run in your * task and thus you will immediately receive a cancel result. * * <p>As a special case, if you call startActivityForResult() with a requestCode * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your * activity, then your window will not be displayed until a result is * returned back from the started activity. This is to avoid visible * flickering when redirecting to another activity. * * <p>This method throws {@link android.content.ActivityNotFoundException} * if there was no Activity found to run the given Intent. * * @param intent The intent to start. * @param requestCode If >= 0, this code will be returned in * onActivityResult() when the activity exits. * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. * * @throws android.content.ActivityNotFoundException * * @see #startActivity */ public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } cancelInputsAndStartExitTransition(options); // TODO Consider clearing/flushing other event sources and events for child windows. } else { if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this, intent, requestCode); } } }
/** * {@inheritDoc} */ @Nullable @Override public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) { try { mActionModeTypeStarting = type; return onWindowStartingActionMode(callback); } finally { mActionModeTypeStarting = ActionMode.TYPE_PRIMARY; } }
/** * Like {@link #startActivityFromChild(Activity, Intent, int)}, but * taking a IntentSender; see * {@link #startIntentSenderForResult(IntentSender, int, Intent, int, int, int)} * for more information. */ public void startIntentSenderFromChild(Activity child, IntentSender intent, int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, @Nullable Bundle options) throws IntentSender.SendIntentException { startIntentSenderForResultInner(intent, child.mEmbeddedID, requestCode, fillInIntent, flagsMask, flagsValues, options); }
/** * @hide Implement to provide correct calling token. */ public void startActivityForResultAsUser(Intent intent, int requestCode, @Nullable Bundle options, UserHandle user) { if (mParent != null) { throw new RuntimeException("Can't be called from a child"); } options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options, user); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } cancelInputsAndStartExitTransition(options); }
/** * Give the Activity a chance to control the UI for an action mode requested * by the system. * * <p>Note: If you are looking for a notification callback that an action mode * has been started for this activity, see {@link #onActionModeStarted(ActionMode)}.</p> * * @param callback The callback that should control the new action mode * @return The new action mode, or <code>null</code> if the activity does not want to * provide special handling for this action mode. (It will be handled by the system.) */ @Nullable @Override public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) { // Only Primary ActionModes are represented in the ActionBar. if (mActionModeTypeStarting == ActionMode.TYPE_PRIMARY) { initWindowDecorActionBar(); if (mActionBar != null) { return mActionBar.startActionMode(callback); } } return null; }
/** * Special version of starting an activity, for use when you are replacing * other activity components. You can use this to hand the Intent off * to the next Activity that can handle it. You typically call this in * {@link #onCreate} with the Intent returned by {@link #getIntent}. * * @param intent The intent to dispatch to the next activity. For * correct behavior, this must be the same as the Intent that started * your own activity; the only changes you can make are to the extras * inside of it. * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. * * @return Returns a boolean indicating whether there was another Activity * to start: true if there was a next activity to start, false if there * wasn't. In general, if true is returned you will then want to call * finish() on yourself. */ public boolean startNextMatchingActivity(@RequiresPermission @NonNull Intent intent, @Nullable Bundle options) { if (mParent == null) { try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(this); return ActivityManagerNative.getDefault() .startNextMatchingActivity(mToken, intent, options); } catch (RemoteException e) { // Empty } return false; } throw new UnsupportedOperationException( "startNextMatchingActivity can only be called from a top-level activity"); }
@Nullable @Override public View onFindViewById(int id) { return Activity.this.findViewById(id); }
/** * Retrieve a reference to this activity's ActionBar. * * @return The Activity's ActionBar, or null if it does not have one. */ @Nullable public ActionBar getActionBar() { initWindowDecorActionBar(); return mActionBar; }
/** * 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. * * <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB} * or later, consider instead using a {@link DialogFragment} instead.</em> * * <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, Bundle) * @see #onPrepareDialog(int, Dialog, Bundle) * @see #dismissDialog(int) * @see #removeDialog(int) * * @deprecated Use the new {@link DialogFragment} class with * {@link FragmentManager} instead; this is also * available on older platforms through the Android compatibility package. */ @Nullable @Deprecated public final boolean showDialog(int id, Bundle args) { if (mManagedDialogs == null) { mManagedDialogs = new SparseArray<ManagedDialog>(); } 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); } md.mArgs = args; onPrepareDialog(id, md.mDialog, args); md.mDialog.show(); return true; }
/** * Like {@link #startActivityForResult(Intent, int)}, but allowing you * to use a IntentSender to describe the activity to be started. If * the IntentSender is for an activity, that activity will be started * as if you had called the regular {@link #startActivityForResult(Intent, int)} * here; otherwise, its associated action will be executed (such as * sending a broadcast) as if you had called * {@link IntentSender#sendIntent IntentSender.sendIntent} on it. * * @param intent The IntentSender to launch. * @param requestCode If >= 0, this code will be returned in * onActivityResult() when the activity exits. * @param fillInIntent If non-null, this will be provided as the * intent parameter to {@link IntentSender#sendIntent}. * @param flagsMask Intent flags in the original IntentSender that you * would like to change. * @param flagsValues Desired values for any bits set in * <var>flagsMask</var> * @param extraFlags Always set to 0. * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. If options * have also been supplied by the IntentSender, options given here will * override any that conflict with those given by the IntentSender. */ public void startIntentSenderForResult(IntentSender intent, int requestCode, @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options) throws IntentSender.SendIntentException { if (mParent == null) { startIntentSenderForResultInner(intent, mEmbeddedID, requestCode, fillInIntent, flagsMask, flagsValues, options); } else if (options != null) { mParent.startIntentSenderFromChild(this, intent, requestCode, fillInIntent, flagsMask, flagsValues, extraFlags, options); } else { // Note we want to go through this call for compatibility with // existing applications that may have overridden the method. mParent.startIntentSenderFromChild(this, intent, requestCode, fillInIntent, flagsMask, flagsValues, extraFlags); } }
/** * Launch a new activity. You will not receive any information about when * the activity exits. This implementation overrides the base version, * providing information about * the activity performing the launch. Because of this additional * information, the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag is not * required; if not specified, the new activity will be added to the * task of the caller. * * <p>This method throws {@link android.content.ActivityNotFoundException} * if there was no Activity found to run the given Intent. * * @param intent The intent to start. * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. * * @throws android.content.ActivityNotFoundException * * @see #startActivity(Intent) * @see #startActivityForResult */ @Override public void startActivity(Intent intent, @Nullable Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { // Note we want to go through this call for compatibility with // applications that may have overridden the method. startActivityForResult(intent, -1); } }
/** * This hook is called to launch the search UI. * * <p>It is typically called from onSearchRequested(), either directly from * Activity.onSearchRequested() or from an overridden version in any given * Activity. If your goal is simply to activate search, it is preferred to call * onSearchRequested(), which may have been overridden elsewhere in your Activity. If your goal * is to inject specific data such as context data, it is preferred to <i>override</i> * onSearchRequested(), so that any callers to it will benefit from the override. * * @param initialQuery Any non-null non-empty string will be inserted as * pre-entered text in the search query box. * @param selectInitialQuery If true, the initial query will be preselected, which means that * any further typing will replace it. This is useful for cases where an entire pre-formed * query is being inserted. If false, the selection point will be placed at the end of the * inserted query. This is useful when the inserted query is text that the user entered, * and the user would expect to be able to keep typing. <i>This parameter is only meaningful * if initialQuery is a non-empty string.</i> * @param appSearchData An application can insert application-specific * context here, in order to improve quality or specificity of its own * searches. This data will be returned with SEARCH intent(s). Null if * no extra data is required. * @param globalSearch If false, this will only launch the search that has been specifically * defined by the application (which is usually defined as a local search). If no default * search is defined in the current application or activity, global search will be launched. * If true, this will always launch a platform-global (e.g. web-based) search instead. * * @see android.app.SearchManager * @see #onSearchRequested */ public void startSearch(@Nullable String initialQuery, boolean selectInitialQuery, @Nullable Bundle appSearchData, boolean globalSearch) { ensureSearchManager(); mSearchManager.startSearch(initialQuery, selectInitialQuery, getComponentName(), appSearchData, globalSearch); }
/** * This hook is called when the user signals the desire to start a search. * * <p>You can use this function as a simple way to launch the search UI, in response to a * menu item, search button, or other widgets within your activity. Unless overidden, * calling this function is the same as calling * {@link #startSearch startSearch(null, false, null, false)}, which launches * search for the current activity as specified in its manifest, see {@link SearchManager}. * * <p>You can override this function to force global search, e.g. in response to a dedicated * search key, or to block search entirely (by simply returning false). * * <p>Note: when running in a {@link Configuration#UI_MODE_TYPE_TELEVISION}, the default * implementation changes to simply return false and you must supply your own custom * implementation if you want to support search.</p> * * @param searchEvent The {@link SearchEvent} that signaled this search. * @return Returns {@code true} if search launched, and {@code false} if the activity does * not respond to search. The default implementation always returns {@code true}, except * when in {@link Configuration#UI_MODE_TYPE_TELEVISION} mode where it returns false. * * @see android.app.SearchManager */ public boolean onSearchRequested(@Nullable SearchEvent searchEvent) { mSearchEvent = searchEvent; boolean result = onSearchRequested(); mSearchEvent = null; return result; }