Subclasses:
CarAppPermissionActivity, CarAppActivity, LauncherActivity, BaseCarAppActivity, AppSearchDebugActivity, SlicePermissionActivity, ComplicationHelperActivity, FragmentActivity, FragmentScenario.EmptyFragmentActivity, DeviceCredentialHandlerActivity, AppCompatActivity
Overview
Base class for activities that enables composition of higher level components.
Rather than all functionality being built directly into this class, only the minimal set of
lower level building blocks are included. Higher level components can then be used as needed
without enforcing a deep Activity class hierarchy or strong coupling between components.
Summary
Constructors |
---|
public | ComponentActivity()
Default constructor for ComponentActivity. |
public | ComponentActivity(int contentLayoutId)
Alternate constructor that can be used to provide a default layout
that will be inflated as part of super.onCreate(savedInstanceState) . |
Methods |
---|
public void | addContentView(View view, ViewGroup.LayoutParams params)
|
public void | addMenuProvider(MenuProvider provider)
|
public void | addMenuProvider(MenuProvider provider, LifecycleOwner owner)
|
public void | addMenuProvider(MenuProvider provider, LifecycleOwner owner, Lifecycle.State state)
|
public final void | addOnConfigurationChangedListener(Consumer<Configuration> listener)
|
public final void | addOnContextAvailableListener(OnContextAvailableListener listener)
Any listener added here will receive a callback as part of
super.onCreate() , but importantly before any other
logic is done (including calling through to the framework
with the exception of restoring the state
of the SavedStateRegistry for use in your listener. |
public final void | addOnMultiWindowModeChangedListener(Consumer<MultiWindowModeChangedInfo> listener)
|
public final void | addOnNewIntentListener(Consumer<Intent> listener)
|
public final void | addOnPictureInPictureModeChangedListener(Consumer<PictureInPictureModeChangedInfo> listener)
|
public final void | addOnTrimMemoryListener(Consumer<java.lang.Integer> listener)
|
public final ActivityResultRegistry | getActivityResultRegistry()
Get the ActivityResultRegistry associated with this activity. |
public CreationExtras | getDefaultViewModelCreationExtras()
|
public ViewModelProvider.Factory | getDefaultViewModelProviderFactory()
|
public java.lang.Object | getLastCustomNonConfigurationInstance()
Return the value previously returned from
ComponentActivity.onRetainCustomNonConfigurationInstance(). |
public Lifecycle | getLifecycle()
|
public final OnBackPressedDispatcher | getOnBackPressedDispatcher()
Retrieve the OnBackPressedDispatcher that will be triggered when
ComponentActivity.onBackPressed() is called. |
public final SavedStateRegistry | getSavedStateRegistry()
|
public ViewModelStore | getViewModelStore()
Returns the ViewModelStore associated with this activity |
public void | invalidateMenu()
|
protected void | onActivityResult(int requestCode, int resultCode, Intent data)
|
public void | onBackPressed()
Called when the activity has detected the user's press of the back
key. |
public void | onConfigurationChanged(Configuration newConfig)
Dispatches this call to all listeners added via
ComponentActivity.addOnConfigurationChangedListener(Consumer). |
protected void | onCreate(Bundle savedInstanceState)
If your ComponentActivity is annotated with ContentView, this will
call ComponentActivity.setContentView(int) for you. |
public boolean | onCreateOptionsMenu(Menu menu)
|
public void | onMultiWindowModeChanged(boolean isInMultiWindowMode)
Dispatches this call to all listeners added via
ComponentActivity.addOnMultiWindowModeChangedListener(Consumer). |
public void | onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig)
Dispatches this call to all listeners added via
ComponentActivity.addOnMultiWindowModeChangedListener(Consumer). |
protected void | onNewIntent(Intent intent)
Dispatches this call to all listeners added via
ComponentActivity.addOnNewIntentListener(Consumer). |
public boolean | onOptionsItemSelected(MenuItem item)
|
public void | onPanelClosed(int featureId, Menu menu)
|
public void | onPictureInPictureModeChanged(boolean isInPictureInPictureMode)
Dispatches this call to all listeners added via
ComponentActivity.addOnPictureInPictureModeChangedListener(Consumer). |
public void | onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig)
Dispatches this call to all listeners added via
ComponentActivity.addOnPictureInPictureModeChangedListener(Consumer). |
public boolean | onPrepareOptionsMenu(Menu menu)
|
public void | onRequestPermissionsResult(int requestCode, java.lang.String permissions[], int[] grantResults[])
|
public java.lang.Object | onRetainCustomNonConfigurationInstance()
Use this instead of ComponentActivity.onRetainNonConfigurationInstance(). |
public final java.lang.Object | onRetainNonConfigurationInstance()
Retain all appropriate non-config state. |
protected void | onSaveInstanceState(Bundle outState)
|
public void | onTrimMemory(int level)
Dispatches this call to all listeners added via ComponentActivity.addOnTrimMemoryListener(Consumer). |
public Context | peekAvailableContext()
|
public final ActivityResultLauncher<java.lang.Object> | registerForActivityResult(ActivityResultContract<java.lang.Object, java.lang.Object> contract, ActivityResultCallback<java.lang.Object> callback)
|
public final ActivityResultLauncher<java.lang.Object> | registerForActivityResult(ActivityResultContract<java.lang.Object, java.lang.Object> contract, ActivityResultRegistry registry, ActivityResultCallback<java.lang.Object> callback)
|
public void | removeMenuProvider(MenuProvider provider)
|
public final void | removeOnConfigurationChangedListener(Consumer<Configuration> listener)
|
public final void | removeOnContextAvailableListener(OnContextAvailableListener listener)
|
public final void | removeOnMultiWindowModeChangedListener(Consumer<MultiWindowModeChangedInfo> listener)
|
public final void | removeOnNewIntentListener(Consumer<Intent> listener)
|
public final void | removeOnPictureInPictureModeChangedListener(Consumer<PictureInPictureModeChangedInfo> listener)
|
public final void | removeOnTrimMemoryListener(Consumer<java.lang.Integer> listener)
|
public void | reportFullyDrawn()
|
public void | setContentView(int layoutResID)
|
public void | setContentView(View view)
|
public void | setContentView(View view, ViewGroup.LayoutParams params)
|
public void | startActivityForResult(Intent intent, int requestCode)
|
public void | startActivityForResult(Intent intent, int requestCode, Bundle options)
|
public void | startIntentSenderForResult(IntentSender intent, int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
|
public void | startIntentSenderForResult(IntentSender intent, int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options)
|
from ComponentActivity | dispatchKeyEvent, dispatchKeyShortcutEvent, getExtraData, putExtraData, shouldDumpInternalState, superDispatchKeyEvent |
from java.lang.Object | clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructors
public
ComponentActivity()
Default constructor for ComponentActivity. All Activities must have a default constructor
for API 27 and lower devices or when using the default
.
public
ComponentActivity(int contentLayoutId)
Alternate constructor that can be used to provide a default layout
that will be inflated as part of super.onCreate(savedInstanceState)
.
This should generally be called from your constructor that takes no parameters,
as is required for API 27 and lower or when using the default
.
See also: ComponentActivity.ComponentActivity()
Methods
protected void
onCreate(Bundle savedInstanceState)
If your ComponentActivity is annotated with ContentView, this will
call ComponentActivity.setContentView(int) for you.
protected void
onSaveInstanceState(Bundle outState)
public final java.lang.Object
onRetainNonConfigurationInstance()
Retain all appropriate non-config state. You can NOT
override this yourself! Use a ViewModel if you want to
retain your own non config state.
public java.lang.Object
onRetainCustomNonConfigurationInstance()
Deprecated: Use a ViewModel to store non config state.
Use this instead of ComponentActivity.onRetainNonConfigurationInstance().
Retrieve later with ComponentActivity.getLastCustomNonConfigurationInstance().
public java.lang.Object
getLastCustomNonConfigurationInstance()
Deprecated: Use a ViewModel to store non config state.
Return the value previously returned from
ComponentActivity.onRetainCustomNonConfigurationInstance().
public void
setContentView(int layoutResID)
public void
setContentView(View view)
public void
setContentView(View view, ViewGroup.LayoutParams params)
public void
addContentView(View view, ViewGroup.LayoutParams params)
public Context
peekAvailableContext()
Any listener added here will receive a callback as part of
super.onCreate()
, but importantly before any other
logic is done (including calling through to the framework
with the exception of restoring the state
of the SavedStateRegistry for use in your listener.
public boolean
onPrepareOptionsMenu(Menu menu)
public boolean
onCreateOptionsMenu(Menu menu)
public boolean
onOptionsItemSelected(MenuItem item)
public void
onPanelClosed(int featureId, Menu menu)
public void
invalidateMenu()
Overriding this method is no longer supported and this method will be made
final
in a future version of ComponentActivity. If you do override
this method, you must
:
- Return an instance of LifecycleRegistry
- Lazily initialize your LifecycleRegistry object when this is first called.
Note that this method will be called in the super classes' constructor, before any
field initialization or object state creation is complete.
Returns the ViewModelStore associated with this activity
Overriding this method is no longer supported and this method will be made
final
in a future version of ComponentActivity.
Returns:
a ViewModelStore
public CreationExtras
getDefaultViewModelCreationExtras()
The extras of ComponentActivity when this is first called will be used as
the defaults to any SavedStateHandle passed to a view model
created using this extra.
public void
onBackPressed()
Called when the activity has detected the user's press of the back
key. The OnBackPressedDispatcher will be given a
chance to handle the back button before the default behavior of
is invoked.
See also: ComponentActivity.getOnBackPressedDispatcher()
Retrieve the OnBackPressedDispatcher that will be triggered when
ComponentActivity.onBackPressed() is called.
Returns:
The OnBackPressedDispatcher associated with this ComponentActivity.
public void
startActivityForResult(Intent intent, int requestCode)
Deprecated: This method has been deprecated in favor of using the Activity Result API
which brings increased type safety via an ActivityResultContract and the prebuilt
contracts for common intents available in
ActivityResultContracts, provides hooks for
testing, and allow receiving results in separate, testable classes independent from your
activity. Use
ComponentActivity.registerForActivityResult(ActivityResultContract, ActivityResultCallback)
passing in a ActivityResultContracts.StartActivityForResult object for the ActivityResultContract.
public void
startActivityForResult(Intent intent, int requestCode, Bundle options)
Deprecated: This method has been deprecated in favor of using the Activity Result API
which brings increased type safety via an ActivityResultContract and the prebuilt
contracts for common intents available in
ActivityResultContracts, provides hooks for
testing, and allow receiving results in separate, testable classes independent from your
activity. Use
ComponentActivity.registerForActivityResult(ActivityResultContract, ActivityResultCallback)
passing in a ActivityResultContracts.StartActivityForResult object for the ActivityResultContract.
public void
startIntentSenderForResult(IntentSender intent, int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
Deprecated: This method has been deprecated in favor of using the Activity Result API
which brings increased type safety via an ActivityResultContract and the prebuilt
contracts for common intents available in
ActivityResultContracts, provides hooks for
testing, and allow receiving results in separate, testable classes independent from your
activity. Use
ComponentActivity.registerForActivityResult(ActivityResultContract, ActivityResultCallback)
passing in a ActivityResultContracts.StartIntentSenderForResult object for the
ActivityResultContract.
public void
startIntentSenderForResult(IntentSender intent, int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options)
Deprecated: This method has been deprecated in favor of using the Activity Result API
which brings increased type safety via an ActivityResultContract and the prebuilt
contracts for common intents available in
ActivityResultContracts, provides hooks for
testing, and allow receiving results in separate, testable classes independent from your
activity. Use
ComponentActivity.registerForActivityResult(ActivityResultContract, ActivityResultCallback)
passing in a ActivityResultContracts.StartIntentSenderForResult object for the
ActivityResultContract.
protected void
onActivityResult(int requestCode, int resultCode, Intent data)
Deprecated: This method has been deprecated in favor of using the Activity Result API
which brings increased type safety via an ActivityResultContract and the prebuilt
contracts for common intents available in
ActivityResultContracts, provides hooks for
testing, and allow receiving results in separate, testable classes independent from your
activity. Use
ComponentActivity.registerForActivityResult(ActivityResultContract, ActivityResultCallback)
with the appropriate ActivityResultContract and handling the result in the
callback.
public void
onRequestPermissionsResult(int requestCode, java.lang.String permissions[], int[] grantResults[])
Deprecated: This method has been deprecated in favor of using the Activity Result API
which brings increased type safety via an ActivityResultContract and the prebuilt
contracts for common intents available in
ActivityResultContracts, provides hooks for
testing, and allow receiving results in separate, testable classes independent from your
activity. Use
ComponentActivity.registerForActivityResult(ActivityResultContract, ActivityResultCallback) passing
in a ActivityResultContracts.RequestMultiplePermissions object for the ActivityResultContract and
handling the result in the callback.
Get the ActivityResultRegistry associated with this activity.
Returns:
the ActivityResultRegistry
public void
onConfigurationChanged(Configuration newConfig)
Dispatches this call to all listeners added via
ComponentActivity.addOnConfigurationChangedListener(Consumer).
public final void
addOnConfigurationChangedListener(
Consumer<Configuration> listener)
public final void
removeOnConfigurationChangedListener(
Consumer<Configuration> listener)
public void
onTrimMemory(int level)
Dispatches this call to all listeners added via ComponentActivity.addOnTrimMemoryListener(Consumer).
public final void
addOnTrimMemoryListener(
Consumer<java.lang.Integer> listener)
public final void
removeOnTrimMemoryListener(
Consumer<java.lang.Integer> listener)
protected void
onNewIntent(Intent intent)
Dispatches this call to all listeners added via
ComponentActivity.addOnNewIntentListener(Consumer).
public final void
addOnNewIntentListener(
Consumer<Intent> listener)
public final void
removeOnNewIntentListener(
Consumer<Intent> listener)
public void
onMultiWindowModeChanged(boolean isInMultiWindowMode)
Dispatches this call to all listeners added via
ComponentActivity.addOnMultiWindowModeChangedListener(Consumer).
public void
onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig)
Dispatches this call to all listeners added via
ComponentActivity.addOnMultiWindowModeChangedListener(Consumer).
public final void
addOnMultiWindowModeChangedListener(
Consumer<MultiWindowModeChangedInfo> listener)
public final void
removeOnMultiWindowModeChangedListener(
Consumer<MultiWindowModeChangedInfo> listener)
public void
onPictureInPictureModeChanged(boolean isInPictureInPictureMode)
Dispatches this call to all listeners added via
ComponentActivity.addOnPictureInPictureModeChangedListener(Consumer).
public void
onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig)
Dispatches this call to all listeners added via
ComponentActivity.addOnPictureInPictureModeChangedListener(Consumer).
public final void
addOnPictureInPictureModeChangedListener(
Consumer<PictureInPictureModeChangedInfo> listener)
public final void
removeOnPictureInPictureModeChangedListener(
Consumer<PictureInPictureModeChangedInfo> listener)
public void
reportFullyDrawn()
Source
/*
* Copyright 2018 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 androidx.activity;
import static android.os.Build.VERSION.SDK_INT;
import static androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions;
import static androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions.ACTION_REQUEST_PERMISSIONS;
import static androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions.EXTRA_PERMISSIONS;
import static androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions.EXTRA_PERMISSION_GRANT_RESULTS;
import static androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
import static androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult.EXTRA_ACTIVITY_OPTIONS_BUNDLE;
import static androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult;
import static androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult.ACTION_INTENT_SENDER_REQUEST;
import static androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult.EXTRA_INTENT_SENDER_REQUEST;
import static androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult.EXTRA_SEND_INTENT_EXCEPTION;
import static androidx.lifecycle.SavedStateHandleSupport.enableSavedStateHandles;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import androidx.activity.contextaware.ContextAware;
import androidx.activity.contextaware.ContextAwareHelper;
import androidx.activity.contextaware.OnContextAvailableListener;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultCaller;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.ActivityResultRegistry;
import androidx.activity.result.ActivityResultRegistryOwner;
import androidx.activity.result.IntentSenderRequest;
import androidx.activity.result.contract.ActivityResultContract;
import androidx.annotation.CallSuper;
import androidx.annotation.ContentView;
import androidx.annotation.LayoutRes;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.app.MultiWindowModeChangedInfo;
import androidx.core.app.OnMultiWindowModeChangedProvider;
import androidx.core.app.OnNewIntentProvider;
import androidx.core.app.OnPictureInPictureModeChangedProvider;
import androidx.core.app.PictureInPictureModeChangedInfo;
import androidx.core.content.ContextCompat;
import androidx.core.content.OnConfigurationChangedProvider;
import androidx.core.content.OnTrimMemoryProvider;
import androidx.core.os.BuildCompat;
import androidx.core.util.Consumer;
import androidx.core.view.MenuHost;
import androidx.core.view.MenuHostHelper;
import androidx.core.view.MenuProvider;
import androidx.lifecycle.HasDefaultViewModelProviderFactory;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
import androidx.lifecycle.ReportFragment;
import androidx.lifecycle.SavedStateHandleSupport;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStore;
import androidx.lifecycle.ViewModelStoreOwner;
import androidx.lifecycle.ViewTreeLifecycleOwner;
import androidx.lifecycle.ViewTreeViewModelStoreOwner;
import androidx.lifecycle.viewmodel.CreationExtras;
import androidx.lifecycle.viewmodel.MutableCreationExtras;
import androidx.savedstate.SavedStateRegistry;
import androidx.savedstate.SavedStateRegistryController;
import androidx.savedstate.SavedStateRegistryOwner;
import androidx.savedstate.ViewTreeSavedStateRegistryOwner;
import androidx.tracing.Trace;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Base class for activities that enables composition of higher level components.
* <p>
* Rather than all functionality being built directly into this class, only the minimal set of
* lower level building blocks are included. Higher level components can then be used as needed
* without enforcing a deep Activity class hierarchy or strong coupling between components.
*/
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
ContextAware,
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner,
ActivityResultRegistryOwner,
ActivityResultCaller,
OnConfigurationChangedProvider,
OnTrimMemoryProvider,
OnNewIntentProvider,
OnMultiWindowModeChangedProvider,
OnPictureInPictureModeChangedProvider,
MenuHost {
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
private static final String ACTIVITY_RESULT_TAG = "android:support:activity-result";
final ContextAwareHelper mContextAwareHelper = new ContextAwareHelper();
private final MenuHostHelper mMenuHostHelper = new MenuHostHelper(this::invalidateMenu);
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@SuppressWarnings("WeakerAccess") /* synthetic access */
final SavedStateRegistryController mSavedStateRegistryController =
SavedStateRegistryController.create(this);
// Lazily recreated from NonConfigurationInstances by getViewModelStore()
private ViewModelStore mViewModelStore;
private ViewModelProvider.Factory mDefaultFactory;
private final OnBackPressedDispatcher mOnBackPressedDispatcher =
new OnBackPressedDispatcher(new Runnable() {
@SuppressWarnings("deprecation")
@Override
public void run() {
// Calling onBackPressed() on an Activity with its state saved can cause an
// error on devices on API levels before 26. We catch that specific error
// and throw all others.
try {
ComponentActivity.super.onBackPressed();
} catch (IllegalStateException e) {
if (!TextUtils.equals(e.getMessage(),
"Can not perform this action after onSaveInstanceState")) {
throw e;
}
}
}
});
@LayoutRes
private int mContentLayoutId;
private final AtomicInteger mNextLocalRequestCode = new AtomicInteger();
private final ActivityResultRegistry mActivityResultRegistry = new ActivityResultRegistry() {
@SuppressWarnings("deprecation")
@Override
public <I, O> void onLaunch(
final int requestCode,
@NonNull ActivityResultContract<I, O> contract,
I input,
@Nullable ActivityOptionsCompat options) {
ComponentActivity activity = ComponentActivity.this;
// Immediate result path
final ActivityResultContract.SynchronousResult<O> synchronousResult =
contract.getSynchronousResult(activity, input);
if (synchronousResult != null) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
dispatchResult(requestCode, synchronousResult.getValue());
}
});
return;
}
// Start activity path
Intent intent = contract.createIntent(activity, input);
Bundle optionsBundle = null;
// If there are any extras, we should defensively set the classLoader
if (intent.getExtras() != null && intent.getExtras().getClassLoader() == null) {
intent.setExtrasClassLoader(activity.getClassLoader());
}
if (intent.hasExtra(EXTRA_ACTIVITY_OPTIONS_BUNDLE)) {
optionsBundle = intent.getBundleExtra(EXTRA_ACTIVITY_OPTIONS_BUNDLE);
intent.removeExtra(EXTRA_ACTIVITY_OPTIONS_BUNDLE);
} else if (options != null) {
optionsBundle = options.toBundle();
}
if (ACTION_REQUEST_PERMISSIONS.equals(intent.getAction())) {
// requestPermissions path
String[] permissions = intent.getStringArrayExtra(EXTRA_PERMISSIONS);
if (permissions == null) {
permissions = new String[0];
}
ActivityCompat.requestPermissions(activity, permissions, requestCode);
} else if (ACTION_INTENT_SENDER_REQUEST.equals(intent.getAction())) {
IntentSenderRequest request =
intent.getParcelableExtra(EXTRA_INTENT_SENDER_REQUEST);
try {
// startIntentSenderForResult path
ActivityCompat.startIntentSenderForResult(activity, request.getIntentSender(),
requestCode, request.getFillInIntent(), request.getFlagsMask(),
request.getFlagsValues(), 0, optionsBundle);
} catch (final IntentSender.SendIntentException e) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
dispatchResult(requestCode, RESULT_CANCELED,
new Intent().setAction(ACTION_INTENT_SENDER_REQUEST)
.putExtra(EXTRA_SEND_INTENT_EXCEPTION, e));
}
});
}
} else {
// startActivityForResult path
ActivityCompat.startActivityForResult(activity, intent, requestCode, optionsBundle);
}
}
};
private final CopyOnWriteArrayList<Consumer<Configuration>> mOnConfigurationChangedListeners =
new CopyOnWriteArrayList<>();
private final CopyOnWriteArrayList<Consumer<Integer>> mOnTrimMemoryListeners =
new CopyOnWriteArrayList<>();
private final CopyOnWriteArrayList<Consumer<Intent>> mOnNewIntentListeners =
new CopyOnWriteArrayList<>();
private final CopyOnWriteArrayList<Consumer<MultiWindowModeChangedInfo>>
mOnMultiWindowModeChangedListeners = new CopyOnWriteArrayList<>();
private final CopyOnWriteArrayList<Consumer<PictureInPictureModeChangedInfo>>
mOnPictureInPictureModeChangedListeners = new CopyOnWriteArrayList<>();
/**
* Default constructor for ComponentActivity. All Activities must have a default constructor
* for API 27 and lower devices or when using the default
* {@link android.app.AppComponentFactory}.
*/
public ComponentActivity() {
Lifecycle lifecycle = getLifecycle();
//noinspection ConstantConditions
if (lifecycle == null) {
throw new IllegalStateException("getLifecycle() returned null in ComponentActivity's "
+ "constructor. Please make sure you are lazily constructing your Lifecycle "
+ "in the first call to getLifecycle() rather than relying on field "
+ "initialization.");
}
if (Build.VERSION.SDK_INT >= 19) {
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_STOP) {
Window window = getWindow();
final View decor = window != null ? window.peekDecorView() : null;
if (decor != null) {
Api19Impl.cancelPendingInputEvents(decor);
}
}
}
});
}
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
// Clear out the available context
mContextAwareHelper.clearAvailableContext();
// And clear the ViewModelStore
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
ensureViewModelStore();
getLifecycle().removeObserver(this);
}
});
mSavedStateRegistryController.performAttach();
enableSavedStateHandles(this);
if (19 <= SDK_INT && SDK_INT <= 23) {
getLifecycle().addObserver(new ImmLeaksCleaner(this));
}
getSavedStateRegistry().registerSavedStateProvider(ACTIVITY_RESULT_TAG,
() -> {
Bundle outState = new Bundle();
mActivityResultRegistry.onSaveInstanceState(outState);
return outState;
});
addOnContextAvailableListener(context -> {
Bundle savedInstanceState = getSavedStateRegistry()
.consumeRestoredStateForKey(ACTIVITY_RESULT_TAG);
if (savedInstanceState != null) {
mActivityResultRegistry.onRestoreInstanceState(savedInstanceState);
}
});
}
/**
* Alternate constructor that can be used to provide a default layout
* that will be inflated as part of <code>super.onCreate(savedInstanceState)</code>.
*
* <p>This should generally be called from your constructor that takes no parameters,
* as is required for API 27 and lower or when using the default
* {@link android.app.AppComponentFactory}.
*
* @see #ComponentActivity()
*/
@ContentView
public ComponentActivity(@LayoutRes int contentLayoutId) {
this();
mContentLayoutId = contentLayoutId;
}
/**
* {@inheritDoc}
*
* If your ComponentActivity is annotated with {@link ContentView}, this will
* call {@link #setContentView(int)} for you.
*/
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
// Restore the Saved State first so that it is available to
// OnContextAvailableListener instances
mSavedStateRegistryController.performRestore(savedInstanceState);
mContextAwareHelper.dispatchOnContextAvailable(this);
super.onCreate(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
if (BuildCompat.isAtLeastT()) {
mOnBackPressedDispatcher.setOnBackInvokedDispatcher(getOnBackInvokedDispatcher());
}
if (mContentLayoutId != 0) {
setContentView(mContentLayoutId);
}
}
@CallSuper
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
Lifecycle lifecycle = getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);
}
super.onSaveInstanceState(outState);
mSavedStateRegistryController.performSave(outState);
}
/**
* Retain all appropriate non-config state. You can NOT
* override this yourself! Use a {@link androidx.lifecycle.ViewModel} if you want to
* retain your own non config state.
*/
@Override
@Nullable
@SuppressWarnings("deprecation")
public final Object onRetainNonConfigurationInstance() {
// Maintain backward compatibility.
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
// No one called getViewModelStore(), so see if there was an existing
// ViewModelStore from our last NonConfigurationInstance
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
viewModelStore = nc.viewModelStore;
}
}
if (viewModelStore == null && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
return nci;
}
/**
* Use this instead of {@link #onRetainNonConfigurationInstance()}.
* Retrieve later with {@link #getLastCustomNonConfigurationInstance()}.
*
* @deprecated Use a {@link androidx.lifecycle.ViewModel} to store non config state.
*/
@Deprecated
@Nullable
public Object onRetainCustomNonConfigurationInstance() {
return null;
}
/**
* Return the value previously returned from
* {@link #onRetainCustomNonConfigurationInstance()}.
*
* @deprecated Use a {@link androidx.lifecycle.ViewModel} to store non config state.
*/
@Deprecated
@Nullable
public Object getLastCustomNonConfigurationInstance() {
NonConfigurationInstances nc = (NonConfigurationInstances)
getLastNonConfigurationInstance();
return nc != null ? nc.custom : null;
}
@Override
public void setContentView(@LayoutRes int layoutResID) {
initViewTreeOwners();
super.setContentView(layoutResID);
}
@Override
public void setContentView(@SuppressLint({"UnknownNullness", "MissingNullability"}) View view) {
initViewTreeOwners();
super.setContentView(view);
}
@Override
public void setContentView(@SuppressLint({"UnknownNullness", "MissingNullability"}) View view,
@SuppressLint({"UnknownNullness", "MissingNullability"})
ViewGroup.LayoutParams params) {
initViewTreeOwners();
super.setContentView(view, params);
}
@Override
public void addContentView(@SuppressLint({"UnknownNullness", "MissingNullability"}) View view,
@SuppressLint({"UnknownNullness", "MissingNullability"})
ViewGroup.LayoutParams params) {
initViewTreeOwners();
super.addContentView(view, params);
}
private void initViewTreeOwners() {
// Set the view tree owners before setting the content view so that the inflation process
// and attach listeners will see them already present
ViewTreeLifecycleOwner.set(getWindow().getDecorView(), this);
ViewTreeViewModelStoreOwner.set(getWindow().getDecorView(), this);
ViewTreeSavedStateRegistryOwner.set(getWindow().getDecorView(), this);
ViewTreeOnBackPressedDispatcherOwner.set(getWindow().getDecorView(), this);
}
@Nullable
@Override
public Context peekAvailableContext() {
return mContextAwareHelper.peekAvailableContext();
}
/**
* {@inheritDoc}
*
* Any listener added here will receive a callback as part of
* <code>super.onCreate()</code>, but importantly <strong>before</strong> any other
* logic is done (including calling through to the framework
* {@link Activity#onCreate(Bundle)} with the exception of restoring the state
* of the {@link #getSavedStateRegistry() SavedStateRegistry} for use in your listener.
*/
@Override
public final void addOnContextAvailableListener(
@NonNull OnContextAvailableListener listener) {
mContextAwareHelper.addOnContextAvailableListener(listener);
}
@Override
public final void removeOnContextAvailableListener(
@NonNull OnContextAvailableListener listener) {
mContextAwareHelper.removeOnContextAvailableListener(listener);
}
@Override
public boolean onPrepareOptionsMenu(@NonNull Menu menu) {
super.onPrepareOptionsMenu(menu);
mMenuHostHelper.onPrepareMenu(menu);
return true;
}
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
super.onCreateOptionsMenu(menu);
mMenuHostHelper.onCreateMenu(menu, getMenuInflater());
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (super.onOptionsItemSelected(item)) {
return true;
}
return mMenuHostHelper.onMenuItemSelected(item);
}
@Override
public void onPanelClosed(int featureId, @NonNull Menu menu) {
mMenuHostHelper.onMenuClosed(menu);
super.onPanelClosed(featureId, menu);
}
@Override
public void addMenuProvider(@NonNull MenuProvider provider) {
mMenuHostHelper.addMenuProvider(provider);
}
@Override
public void addMenuProvider(@NonNull MenuProvider provider, @NonNull LifecycleOwner owner) {
mMenuHostHelper.addMenuProvider(provider, owner);
}
@Override
@SuppressLint("LambdaLast")
public void addMenuProvider(@NonNull MenuProvider provider, @NonNull LifecycleOwner owner,
@NonNull Lifecycle.State state) {
mMenuHostHelper.addMenuProvider(provider, owner, state);
}
@Override
public void removeMenuProvider(@NonNull MenuProvider provider) {
mMenuHostHelper.removeMenuProvider(provider);
}
@Override
public void invalidateMenu() {
invalidateOptionsMenu();
}
/**
* {@inheritDoc}
* <p>
* Overriding this method is no longer supported and this method will be made
* <code>final</code> in a future version of ComponentActivity. If you do override
* this method, you <code>must</code>:
* <ol>
* <li>Return an instance of {@link LifecycleRegistry}</li>
* <li>Lazily initialize your LifecycleRegistry object when this is first called.
* Note that this method will be called in the super classes' constructor, before any
* field initialization or object state creation is complete.</li>
* </ol>
*/
@NonNull
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
/**
* Returns the {@link ViewModelStore} associated with this activity
* <p>
* Overriding this method is no longer supported and this method will be made
* <code>final</code> in a future version of ComponentActivity.
*
* @return a {@code ViewModelStore}
* @throws IllegalStateException if called before the Activity is attached to the Application
* instance i.e., before onCreate()
*/
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the "
+ "Application instance. You can't request ViewModel before onCreate call.");
}
ensureViewModelStore();
return mViewModelStore;
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
void ensureViewModelStore() {
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
}
@NonNull
@Override
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
if (mDefaultFactory == null) {
mDefaultFactory = new SavedStateViewModelFactory(
getApplication(),
this,
getIntent() != null ? getIntent().getExtras() : null);
}
return mDefaultFactory;
}
/**
* {@inheritDoc}
*
* <p>The extras of {@link #getIntent()} when this is first called will be used as
* the defaults to any {@link androidx.lifecycle.SavedStateHandle} passed to a view model
* created using this extra.</p>
*/
@NonNull
@Override
@CallSuper
public CreationExtras getDefaultViewModelCreationExtras() {
MutableCreationExtras extras = new MutableCreationExtras();
if (getApplication() != null) {
extras.set(ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY, getApplication());
}
extras.set(SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY, this);
extras.set(SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY, this);
if (getIntent() != null && getIntent().getExtras() != null) {
extras.set(SavedStateHandleSupport.DEFAULT_ARGS_KEY, getIntent().getExtras());
}
return extras;
}
/**
* Called when the activity has detected the user's press of the back
* key. The {@link #getOnBackPressedDispatcher() OnBackPressedDispatcher} will be given a
* chance to handle the back button before the default behavior of
* {@link android.app.Activity#onBackPressed()} is invoked.
*
* @see #getOnBackPressedDispatcher()
*/
@SuppressWarnings("deprecation")
@Override
@MainThread
public void onBackPressed() {
mOnBackPressedDispatcher.onBackPressed();
}
/**
* Retrieve the {@link OnBackPressedDispatcher} that will be triggered when
* {@link #onBackPressed()} is called.
* @return The {@link OnBackPressedDispatcher} associated with this ComponentActivity.
*/
@NonNull
@Override
public final OnBackPressedDispatcher getOnBackPressedDispatcher() {
return mOnBackPressedDispatcher;
}
@NonNull
@Override
public final SavedStateRegistry getSavedStateRegistry() {
return mSavedStateRegistryController.getSavedStateRegistry();
}
/**
* {@inheritDoc}
*
* @deprecated This method has been deprecated in favor of using the Activity Result API
* which brings increased type safety via an {@link ActivityResultContract} and the prebuilt
* contracts for common intents available in
* {@link androidx.activity.result.contract.ActivityResultContracts}, provides hooks for
* testing, and allow receiving results in separate, testable classes independent from your
* activity. Use
* {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
* passing in a {@link StartActivityForResult} object for the {@link ActivityResultContract}.
*/
@Override
@Deprecated
public void startActivityForResult(@SuppressLint("UnknownNullness") Intent intent,
int requestCode) {
super.startActivityForResult(intent, requestCode);
}
/**
* {@inheritDoc}
*
* @deprecated This method has been deprecated in favor of using the Activity Result API
* which brings increased type safety via an {@link ActivityResultContract} and the prebuilt
* contracts for common intents available in
* {@link androidx.activity.result.contract.ActivityResultContracts}, provides hooks for
* testing, and allow receiving results in separate, testable classes independent from your
* activity. Use
* {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
* passing in a {@link StartActivityForResult} object for the {@link ActivityResultContract}.
*/
@Override
@Deprecated
public void startActivityForResult(@SuppressLint("UnknownNullness") Intent intent,
int requestCode, @Nullable Bundle options) {
super.startActivityForResult(intent, requestCode, options);
}
/**
* {@inheritDoc}
*
* @deprecated This method has been deprecated in favor of using the Activity Result API
* which brings increased type safety via an {@link ActivityResultContract} and the prebuilt
* contracts for common intents available in
* {@link androidx.activity.result.contract.ActivityResultContracts}, provides hooks for
* testing, and allow receiving results in separate, testable classes independent from your
* activity. Use
* {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
* passing in a {@link StartIntentSenderForResult} object for the
* {@link ActivityResultContract}.
*/
@Override
@Deprecated
public void startIntentSenderForResult(@SuppressLint("UnknownNullness") IntentSender intent,
int requestCode, @Nullable Intent fillInIntent, int flagsMask, int flagsValues,
int extraFlags)
throws IntentSender.SendIntentException {
super.startIntentSenderForResult(intent, requestCode, fillInIntent, flagsMask, flagsValues,
extraFlags);
}
/**
* {@inheritDoc}
*
* @deprecated This method has been deprecated in favor of using the Activity Result API
* which brings increased type safety via an {@link ActivityResultContract} and the prebuilt
* contracts for common intents available in
* {@link androidx.activity.result.contract.ActivityResultContracts}, provides hooks for
* testing, and allow receiving results in separate, testable classes independent from your
* activity. Use
* {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
* passing in a {@link StartIntentSenderForResult} object for the
* {@link ActivityResultContract}.
*/
@Override
@Deprecated
public void startIntentSenderForResult(@SuppressLint("UnknownNullness") IntentSender intent,
int requestCode, @Nullable Intent fillInIntent, int flagsMask, int flagsValues,
int extraFlags, @Nullable Bundle options) throws IntentSender.SendIntentException {
super.startIntentSenderForResult(intent, requestCode, fillInIntent, flagsMask, flagsValues,
extraFlags, options);
}
/**
* {@inheritDoc}
*
* @deprecated This method has been deprecated in favor of using the Activity Result API
* which brings increased type safety via an {@link ActivityResultContract} and the prebuilt
* contracts for common intents available in
* {@link androidx.activity.result.contract.ActivityResultContracts}, provides hooks for
* testing, and allow receiving results in separate, testable classes independent from your
* activity. Use
* {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
* with the appropriate {@link ActivityResultContract} and handling the result in the
* {@link ActivityResultCallback#onActivityResult(Object) callback}.
*/
@CallSuper
@Override
@Deprecated
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (!mActivityResultRegistry.dispatchResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
/**
* {@inheritDoc}
*
* @deprecated This method has been deprecated in favor of using the Activity Result API
* which brings increased type safety via an {@link ActivityResultContract} and the prebuilt
* contracts for common intents available in
* {@link androidx.activity.result.contract.ActivityResultContracts}, provides hooks for
* testing, and allow receiving results in separate, testable classes independent from your
* activity. Use
* {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)} passing
* in a {@link RequestMultiplePermissions} object for the {@link ActivityResultContract} and
* handling the result in the {@link ActivityResultCallback#onActivityResult(Object) callback}.
*/
@CallSuper
@Override
@Deprecated
public void onRequestPermissionsResult(
int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults) {
if (!mActivityResultRegistry.dispatchResult(requestCode, Activity.RESULT_OK, new Intent()
.putExtra(EXTRA_PERMISSIONS, permissions)
.putExtra(EXTRA_PERMISSION_GRANT_RESULTS, grantResults))) {
if (Build.VERSION.SDK_INT >= 23) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
@NonNull
@Override
public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
@NonNull final ActivityResultContract<I, O> contract,
@NonNull final ActivityResultRegistry registry,
@NonNull final ActivityResultCallback<O> callback) {
return registry.register(
"activity_rq#" + mNextLocalRequestCode.getAndIncrement(), this, contract, callback);
}
@NonNull
@Override
public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
@NonNull ActivityResultContract<I, O> contract,
@NonNull ActivityResultCallback<O> callback) {
return registerForActivityResult(contract, mActivityResultRegistry, callback);
}
/**
* Get the {@link ActivityResultRegistry} associated with this activity.
*
* @return the {@link ActivityResultRegistry}
*/
@NonNull
@Override
public final ActivityResultRegistry getActivityResultRegistry() {
return mActivityResultRegistry;
}
/**
* {@inheritDoc}
*
* Dispatches this call to all listeners added via
* {@link #addOnConfigurationChangedListener(Consumer)}.
*/
@CallSuper
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
for (Consumer<Configuration> listener : mOnConfigurationChangedListeners) {
listener.accept(newConfig);
}
}
@Override
public final void addOnConfigurationChangedListener(
@NonNull Consumer<Configuration> listener
) {
mOnConfigurationChangedListeners.add(listener);
}
@Override
public final void removeOnConfigurationChangedListener(
@NonNull Consumer<Configuration> listener
) {
mOnConfigurationChangedListeners.remove(listener);
}
/**
* {@inheritDoc}
*
* Dispatches this call to all listeners added via {@link #addOnTrimMemoryListener(Consumer)}.
*/
@CallSuper
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
for (Consumer<Integer> listener : mOnTrimMemoryListeners) {
listener.accept(level);
}
}
@Override
public final void addOnTrimMemoryListener(@NonNull Consumer<Integer> listener) {
mOnTrimMemoryListeners.add(listener);
}
@Override
public final void removeOnTrimMemoryListener(@NonNull Consumer<Integer> listener) {
mOnTrimMemoryListeners.remove(listener);
}
/**
* {@inheritDoc}
*
* Dispatches this call to all listeners added via
* {@link #addOnNewIntentListener(Consumer)}.
*/
@CallSuper
@Override
protected void onNewIntent(
@SuppressLint({"UnknownNullness", "MissingNullability"}) Intent intent
) {
super.onNewIntent(intent);
for (Consumer<Intent> listener : mOnNewIntentListeners) {
listener.accept(intent);
}
}
@Override
public final void addOnNewIntentListener(
@NonNull Consumer<Intent> listener
) {
mOnNewIntentListeners.add(listener);
}
@Override
public final void removeOnNewIntentListener(
@NonNull Consumer<Intent> listener
) {
mOnNewIntentListeners.remove(listener);
}
/**
* {@inheritDoc}
*
* Dispatches this call to all listeners added via
* {@link #addOnMultiWindowModeChangedListener(Consumer)}.
*/
@CallSuper
@Override
@SuppressWarnings("deprecation")
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
// We specifically do not call super.onMultiWindowModeChanged() to avoid
// crashing when this method is manually called prior to API 24 (which is
// when this method was added to the framework)
for (Consumer<MultiWindowModeChangedInfo> listener : mOnMultiWindowModeChangedListeners) {
listener.accept(new MultiWindowModeChangedInfo(isInMultiWindowMode));
}
}
/**
* {@inheritDoc}
*
* Dispatches this call to all listeners added via
* {@link #addOnMultiWindowModeChangedListener(Consumer)}.
*/
@RequiresApi(api = Build.VERSION_CODES.O)
@CallSuper
@Override
public void onMultiWindowModeChanged(boolean isInMultiWindowMode,
@NonNull Configuration newConfig) {
// We specifically do not call super.onMultiWindowModeChanged() to avoid
// triggering the call to onMultiWindowModeChanged(boolean) which would
// send a second callback to listeners without the newConfig
for (Consumer<MultiWindowModeChangedInfo> listener : mOnMultiWindowModeChangedListeners) {
listener.accept(new MultiWindowModeChangedInfo(isInMultiWindowMode, newConfig));
}
}
@Override
public final void addOnMultiWindowModeChangedListener(
@NonNull Consumer<MultiWindowModeChangedInfo> listener
) {
mOnMultiWindowModeChangedListeners.add(listener);
}
@Override
public final void removeOnMultiWindowModeChangedListener(
@NonNull Consumer<MultiWindowModeChangedInfo> listener
) {
mOnMultiWindowModeChangedListeners.remove(listener);
}
/**
* {@inheritDoc}
*
* Dispatches this call to all listeners added via
* {@link #addOnPictureInPictureModeChangedListener(Consumer)}.
*/
@CallSuper
@Override
@SuppressWarnings("deprecation")
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
// We specifically do not call super.onPictureInPictureModeChanged() to avoid
// crashing when this method is manually called prior to API 24 (which is
// when this method was added to the framework)
for (Consumer<PictureInPictureModeChangedInfo> listener :
mOnPictureInPictureModeChangedListeners) {
listener.accept(new PictureInPictureModeChangedInfo(isInPictureInPictureMode));
}
}
/**
* {@inheritDoc}
*
* Dispatches this call to all listeners added via
* {@link #addOnPictureInPictureModeChangedListener(Consumer)}.
*/
@RequiresApi(api = Build.VERSION_CODES.O)
@CallSuper
@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode,
@NonNull Configuration newConfig) {
// We specifically do not call super.onPictureInPictureModeChanged() to avoid
// triggering the call to onPictureInPictureModeChanged(boolean) which would
// send a second callback to listeners without the newConfig
for (Consumer<PictureInPictureModeChangedInfo> listener :
mOnPictureInPictureModeChangedListeners) {
listener.accept(new PictureInPictureModeChangedInfo(
isInPictureInPictureMode, newConfig));
}
}
@Override
public final void addOnPictureInPictureModeChangedListener(
@NonNull Consumer<PictureInPictureModeChangedInfo> listener
) {
mOnPictureInPictureModeChangedListeners.add(listener);
}
@Override
public final void removeOnPictureInPictureModeChangedListener(
@NonNull Consumer<PictureInPictureModeChangedInfo> listener
) {
mOnPictureInPictureModeChangedListeners.remove(listener);
}
@Override
public void reportFullyDrawn() {
try {
if (Trace.isEnabled()) {
// TODO: Ideally we'd include getComponentName() (as later versions of platform
// do), but b/175345114 needs to be addressed.
Trace.beginSection("reportFullyDrawn() for ComponentActivity");
}
if (Build.VERSION.SDK_INT > 19) {
super.reportFullyDrawn();
} else if (Build.VERSION.SDK_INT == 19 && ContextCompat.checkSelfPermission(this,
Manifest.permission.UPDATE_DEVICE_STATS) == PackageManager.PERMISSION_GRANTED) {
// On API 19, the Activity.reportFullyDrawn() method requires the
// UPDATE_DEVICE_STATS permission, otherwise it throws an exception. Instead of
// throwing, we fall back to a no-op call.
super.reportFullyDrawn();
}
// The Activity.reportFullyDrawn() got added in API 19, fall back to a no-op call if
// this method gets called on devices with an earlier version.
} finally {
Trace.endSection();
}
}
@RequiresApi(19)
static class Api19Impl {
private Api19Impl() { }
static void cancelPendingInputEvents(View view) {
view.cancelPendingInputEvents();
}
}
}