Gradle dependencies
compile group: 'androidx.wear', name: 'wear', version: '1.3.0-alpha02'
- groupId: androidx.wear
- artifactId: wear
- version: 1.3.0-alpha02
Artifact androidx.wear:wear:1.3.0-alpha02 it located at Google repository (https://maven.google.com/)
Androidx artifact mapping:
androidx.wear:wear com.android.support:wear
Androidx class mapping:
androidx.wear.ambient.AmbientModeSupport android.support.wear.ambient.AmbientModeSupport
Overview
Use this as a headless Fragment to add ambient support to an Activity on Wearable devices.
The application that uses this should add the
permission to its manifest.
The following describes the general use of this class:
Create a subclass of one of the FragmentActivity classes and implement the
AmbientModeSupport.AmbientCallbackProvider interface. Override the
AmbientModeSupport.AmbientCallbackProvider.getAmbientCallback() method to provide the callbacks required
for reacting to the ambient events from the Android system. If a valid
AmbientModeSupport.AmbientCallback is not provided (either no implementation of the
AmbientModeSupport.AmbientCallbackProvider interface, or returning null from
AmbientModeSupport.AmbientCallbackProvider.getAmbientCallback()), then ambient mode will NOT be enabled.
The primary entry point for this code is the AmbientModeSupport.attach(T) method.
It should be called with an FragmentActivity as an argument and that
FragmentActivity will then be able to receive ambient lifecycle events through
an AmbientModeSupport.AmbientCallback. The FragmentActivity will also receive a
AmbientModeSupport.AmbientController object from the attachment which can be used to query the current
status of the ambient mode.
An example of how to implement the AmbientModeSupport.AmbientCallbackProvider interface, attach
AmbientModeSupport to your FragmentActivity and use the
AmbientModeSupport.AmbientController can be found below:
public class MyActivity extends FragmentActivity
implements AmbientModeSupport.AmbientCallbackProvider {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
...
AmbientModeSupport.AmbientController controller = AmbientModeSupport.attach(this);
boolean isAmbient = controller.isAmbient();
}
@Override
AmbientModeSupport.AmbientCallback getAmbientCallback() {
return new AmbientModeSupport.AmbientCallback() {
public void onEnterAmbient(Bundle ambientDetails) {...}
public void onExitAmbient(Bundle ambientDetails) {...}
}
}
}
Summary
Methods |
---|
public static AmbientModeSupport.AmbientController | attach(FragmentActivity activity)
Attach ambient support to the given activity. |
public void | dump(java.lang.String prefix, java.io.FileDescriptor fd, java.io.PrintWriter writer, java.lang.String args[])
Print the Fragments's state into the given stream. |
public void | onAttach(Activity activity)
Called when a fragment is first attached to its activity. |
public void | onCreate(Bundle savedInstanceState)
Called to do initial creation of a fragment. |
public void | onDestroy()
Called when the fragment is no longer in use. |
public void | onDetach()
Called when the fragment is no longer attached to its activity. |
public void | onPause()
Called when the Fragment is no longer resumed. |
public void | onResume()
Called when the fragment is visible to the user and actively running. |
public void | onStop()
Called when the Fragment is no longer started. |
from Fragment | equals, getActivity, getAllowEnterTransitionOverlap, getAllowReturnTransitionOverlap, getArguments, getChildFragmentManager, getContext, getDefaultViewModelCreationExtras, getDefaultViewModelProviderFactory, getEnterTransition, getExitTransition, getFragmentManager, getHost, getId, getLayoutInflater, getLayoutInflater, getLifecycle, getLoaderManager, getParentFragment, getParentFragmentManager, getReenterTransition, getResources, getRetainInstance, getReturnTransition, getSavedStateRegistry, getSharedElementEnterTransition, getSharedElementReturnTransition, getString, getString, getTag, getTargetFragment, getTargetRequestCode, getText, getUserVisibleHint, getView, getViewLifecycleOwner, getViewLifecycleOwnerLiveData, getViewModelStore, hashCode, hasOptionsMenu, instantiate, instantiate, isAdded, isDetached, isHidden, isInLayout, isMenuVisible, isRemoving, isResumed, isStateSaved, isVisible, onActivityCreated, onActivityResult, onAttach, onAttachFragment, onConfigurationChanged, onContextItemSelected, onCreateAnimation, onCreateAnimator, onCreateContextMenu, onCreateOptionsMenu, onCreateView, onDestroyOptionsMenu, onDestroyView, onGetLayoutInflater, onHiddenChanged, onInflate, onInflate, onLowMemory, onMultiWindowModeChanged, onOptionsItemSelected, onOptionsMenuClosed, onPictureInPictureModeChanged, onPrepareOptionsMenu, onPrimaryNavigationFragmentChanged, onRequestPermissionsResult, onSaveInstanceState, onStart, onViewCreated, onViewStateRestored, postponeEnterTransition, postponeEnterTransition, registerForActivityResult, registerForActivityResult, registerForContextMenu, requestPermissions, requireActivity, requireArguments, requireContext, requireFragmentManager, requireHost, requireParentFragment, requireView, setAllowEnterTransitionOverlap, setAllowReturnTransitionOverlap, setArguments, setEnterSharedElementCallback, setEnterTransition, setExitSharedElementCallback, setExitTransition, setHasOptionsMenu, setInitialSavedState, setMenuVisibility, setReenterTransition, setRetainInstance, setReturnTransition, setSharedElementEnterTransition, setSharedElementReturnTransition, setTargetFragment, setUserVisibleHint, shouldShowRequestPermissionRationale, startActivity, startActivity, startActivityForResult, startActivityForResult, startIntentSenderForResult, startPostponedEnterTransition, toString, unregisterForContextMenu |
from java.lang.Object | clone, finalize, getClass, notify, notifyAll, wait, wait, wait |
Fields
public static final java.lang.String
EXTRA_BURN_IN_PROTECTIONProperty in bundle passed to AmbientCallback#onEnterAmbient(Bundle) to indicate
whether burn-in protection is required. When this property is set to true, views must be
shifted around periodically in ambient mode. To ensure that content isn't shifted off
the screen, avoid placing content within 10 pixels of the edge of the screen. Activities
should also avoid solid white areas to prevent pixel burn-in. Both of these requirements
only apply in ambient mode, and only when this property is set to true.
public static final java.lang.String
EXTRA_LOWBIT_AMBIENTProperty in bundle passed to AmbientCallback#onEnterAmbient(Bundle) to indicate
whether the device has low-bit ambient mode. When this property is set to true, the screen
supports fewer bits for each color in ambient mode. In this case, activities should disable
anti-aliasing in ambient mode.
public static final java.lang.String
FRAGMENT_TAGFragment tag used by default when adding AmbientModeSupport to add ambient support to
a FragmentActivity.
Constructors
public
AmbientModeSupport()
Constructor
Methods
public void
onAttach(Activity activity)
Deprecated: See Fragment.onAttach(Context).
Called when a fragment is first attached to its activity.
Fragment.onCreate(Bundle) will be called after this.
public void
onCreate(Bundle savedInstanceState)
Called to do initial creation of a fragment. This is called after
Fragment.onAttach(Activity) and before
Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle).
Note that this can be called while the fragment's activity is
still in the process of being created. As such, you can not rely
on things like the activity's content view hierarchy being initialized
at this point. If you want to do work once the activity itself is
created, add a LifecycleObserver on the
activity's Lifecycle, removing it when it receives the
callback.
Any restored child fragments will be created before the base
Fragment.onCreate
method returns.
Parameters:
savedInstanceState: If the fragment is being re-created from
a previous saved state, this is the state.
Called when the fragment is visible to the user and actively running.
This is generally
tied to of the containing
Activity's lifecycle.
Called when the Fragment is no longer resumed. This is generally
tied to of the containing
Activity's lifecycle.
Called when the Fragment is no longer started. This is generally
tied to of the containing
Activity's lifecycle.
Called when the fragment is no longer in use. This is called
after Fragment.onStop() and before Fragment.onDetach().
Called when the fragment is no longer attached to its activity. This
is called after Fragment.onDestroy().
Attach ambient support to the given activity. Calling this method with an Activity
implementing the AmbientModeSupport.AmbientCallbackProvider interface will provide you with an
opportunity to react to ambient events such as onEnterAmbient. Alternatively,
you can call this method with an Activity which does not implement
the AmbientModeSupport.AmbientCallbackProvider interface and that will only enable the auto-resume
functionality. This is equivalent to providing (@code null} from
the AmbientModeSupport.AmbientCallbackProvider.
Parameters:
activity: the activity to attach ambient support to.
Returns:
the associated AmbientModeSupport.AmbientController which can be used to query the state of
ambient mode.
public void
dump(java.lang.String prefix, java.io.FileDescriptor fd, java.io.PrintWriter writer, java.lang.String args[])
Print the Fragments's state into the given stream.
Parameters:
prefix: Text to print at the front of each line.
fd: The raw file descriptor that the dump is being sent to.
writer: The PrintWriter to which you should dump your state. This will be
closed for you after you return.
args: additional arguments to the dump request.
Source
/*
* Copyright (C) 2017 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.wear.ambient;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import com.google.android.wearable.compat.WearableActivityController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* Use this as a headless Fragment to add ambient support to an Activity on Wearable devices.
* <p>
* The application that uses this should add the {@link android.Manifest.permission#WAKE_LOCK}
* permission to its manifest.
* <p>
* The following describes the general use of this class:
* <p>
* Create a subclass of one of the {@link FragmentActivity} classes and implement the
* {@link AmbientCallbackProvider} interface. Override the
* {@link AmbientCallbackProvider#getAmbientCallback()} method to provide the callbacks required
* for reacting to the ambient events from the Android system. If a valid
* {@link AmbientCallback} is not provided (either no implementation of the
* {@link AmbientCallbackProvider} interface, or returning null from
* {@link AmbientCallbackProvider#getAmbientCallback()}), then ambient mode will NOT be enabled.
* <p>
* The primary entry point for this code is the {@link #attach(FragmentActivity)} method.
* It should be called with an {@link FragmentActivity} as an argument and that
* {@link FragmentActivity} will then be able to receive ambient lifecycle events through
* an {@link AmbientCallback}. The {@link FragmentActivity} will also receive a
* {@link AmbientController} object from the attachment which can be used to query the current
* status of the ambient mode.
* <p>
* An example of how to implement the {@link AmbientCallbackProvider} interface, attach
* {@link AmbientModeSupport} to your {@link FragmentActivity} and use the
* {@link AmbientController} can be found below:
*
* <pre class="prettyprint">
* public class MyActivity extends FragmentActivity
* implements AmbientModeSupport.AmbientCallbackProvider {
* {@literal @}Override
* public void onCreate(Bundle savedInstanceState) {
* super.onCreate(savedInstanceState)
* ...
* AmbientModeSupport.AmbientController controller = AmbientModeSupport.attach(this);
* boolean isAmbient = controller.isAmbient();
* }
* {@literal @}Override
* AmbientModeSupport.AmbientCallback getAmbientCallback() {
* return new AmbientModeSupport.AmbientCallback() {
* public void onEnterAmbient(Bundle ambientDetails) {...}
* public void onExitAmbient(Bundle ambientDetails) {...}
* }
* }
* }</pre>
*/
public final class AmbientModeSupport extends Fragment {
private static final String TAG = "AmbientModeSupport";
/**
* Property in bundle passed to {@code AmbientCallback#onEnterAmbient(Bundle)} to indicate
* whether burn-in protection is required. When this property is set to true, views must be
* shifted around periodically in ambient mode. To ensure that content isn't shifted off
* the screen, avoid placing content within 10 pixels of the edge of the screen. Activities
* should also avoid solid white areas to prevent pixel burn-in. Both of these requirements
* only apply in ambient mode, and only when this property is set to true.
*/
public static final String EXTRA_BURN_IN_PROTECTION =
WearableActivityController.EXTRA_BURN_IN_PROTECTION;
/**
* Property in bundle passed to {@code AmbientCallback#onEnterAmbient(Bundle)} to indicate
* whether the device has low-bit ambient mode. When this property is set to true, the screen
* supports fewer bits for each color in ambient mode. In this case, activities should disable
* anti-aliasing in ambient mode.
*/
public static final String EXTRA_LOWBIT_AMBIENT =
WearableActivityController.EXTRA_LOWBIT_AMBIENT;
/**
* Fragment tag used by default when adding {@link AmbientModeSupport} to add ambient support to
* a {@link FragmentActivity}.
*/
public static final String FRAGMENT_TAG = "android.support.wearable.ambient.AmbientMode";
/**
* Interface for any {@link Activity} that wishes to implement Ambient Mode. Use the
* {@link #getAmbientCallback()} method to return an {@link AmbientCallback} which can be used
* to bind the {@link AmbientModeSupport} to the instantiation of this interface.
* <p>
* <pre class="prettyprint">{@code
* return new AmbientModeSupport.AmbientCallback() {
* public void onEnterAmbient(Bundle ambientDetails) {...}
* public void onExitAmbient(Bundle ambientDetails) {...}
* }
* }</pre>
*/
public interface AmbientCallbackProvider {
/**
* @return the {@link AmbientCallback} to be used by this class to communicate with the
* entity interested in ambient events.
*/
AmbientCallback getAmbientCallback();
}
/**
* Callback to receive ambient mode state changes. It must be used by all users of
* AmbientModeSupport.
*/
public abstract static class AmbientCallback {
/**
* Called when an activity is entering ambient mode. This event is sent while an activity is
* running (after onResume, before onPause). All drawing should complete by the conclusion
* of this method. Note that {@code invalidate()} calls will be executed before resuming
* lower-power mode.
*
* @param ambientDetails bundle containing information about the display being used.
* It includes information about low-bit color and burn-in protection.
*/
public void onEnterAmbient(Bundle ambientDetails) {}
/**
* Called when the system is updating the display for ambient mode. Activities may use this
* opportunity to update or invalidate views.
*/
public void onUpdateAmbient() {}
/**
* Called when an activity should exit ambient mode. This event is sent while an activity is
* running (after onResume, before onPause).
*/
public void onExitAmbient() {}
/**
* Called to inform an activity that whatever decomposition it has sent to Sidekick is no
* longer valid and should be re-sent before enabling ambient offload.
*/
public void onAmbientOffloadInvalidated() {}
}
private final AmbientDelegate.AmbientCallback mCallback =
new AmbientDelegate.AmbientCallback() {
@Override
public void onEnterAmbient(Bundle ambientDetails) {
if (mSuppliedCallback != null) {
mSuppliedCallback.onEnterAmbient(ambientDetails);
}
}
@Override
public void onExitAmbient() {
if (mSuppliedCallback != null) {
mSuppliedCallback.onExitAmbient();
}
}
@Override
public void onUpdateAmbient() {
if (mSuppliedCallback != null) {
mSuppliedCallback.onUpdateAmbient();
}
}
@Override
public void onAmbientOffloadInvalidated() {
if (mSuppliedCallback != null) {
mSuppliedCallback.onAmbientOffloadInvalidated();
}
}
};
@SuppressWarnings("WeakerAccess") /* synthetic access */
AmbientDelegate mDelegate;
@Nullable
@SuppressWarnings("WeakerAccess") /* synthetic access */
AmbientCallback mSuppliedCallback;
private AmbientController mController;
/**
* Constructor
*/
public AmbientModeSupport() {
mController = new AmbientController();
}
@Override
@CallSuper
public void onAttach(Context context) {
super.onAttach(context);
mDelegate = new AmbientDelegate(getActivity(), new WearableControllerProvider(), mCallback);
if (context instanceof AmbientCallbackProvider) {
mSuppliedCallback = ((AmbientCallbackProvider) context).getAmbientCallback();
} else {
Log.w(TAG, "No callback provided - enabling only smart resume");
}
}
@Override
@CallSuper
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDelegate.onCreate();
if (mSuppliedCallback != null) {
mDelegate.setAmbientEnabled();
}
}
@Override
@CallSuper
public void onResume() {
super.onResume();
mDelegate.onResume();
}
@Override
@CallSuper
public void onPause() {
mDelegate.onPause();
super.onPause();
}
@Override
@CallSuper
public void onStop() {
mDelegate.onStop();
super.onStop();
}
@Override
@CallSuper
public void onDestroy() {
mDelegate.onDestroy();
super.onDestroy();
}
@Override
@CallSuper
public void onDetach() {
mDelegate = null;
super.onDetach();
}
/**
* Attach ambient support to the given activity. Calling this method with an Activity
* implementing the {@link AmbientCallbackProvider} interface will provide you with an
* opportunity to react to ambient events such as {@code onEnterAmbient}. Alternatively,
* you can call this method with an Activity which does not implement
* the {@link AmbientCallbackProvider} interface and that will only enable the auto-resume
* functionality. This is equivalent to providing (@code null} from
* the {@link AmbientCallbackProvider}.
*
* @param activity the activity to attach ambient support to.
* @return the associated {@link AmbientController} which can be used to query the state of
* ambient mode.
*/
public static <T extends FragmentActivity> AmbientController attach(T activity) {
FragmentManager fragmentManager = activity.getSupportFragmentManager();
AmbientModeSupport ambientFragment =
(AmbientModeSupport) fragmentManager.findFragmentByTag(FRAGMENT_TAG);
if (ambientFragment == null) {
AmbientModeSupport fragment = new AmbientModeSupport();
fragmentManager
.beginTransaction()
.add(fragment, FRAGMENT_TAG)
.commit();
ambientFragment = fragment;
}
return ambientFragment.mController;
}
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
if (mDelegate != null) {
mDelegate.dump(prefix, fd, writer, args);
}
}
@VisibleForTesting
void setAmbientDelegate(AmbientDelegate delegate) {
mDelegate = delegate;
}
/**
* A class for interacting with the ambient mode on a wearable device. This class can be used to
* query the current state of ambient mode. An instance of this class is returned to the user
* when they attach their {@link Activity} to {@link AmbientModeSupport}.
*/
public final class AmbientController {
private static final String TAG = "AmbientController";
// Do not initialize outside of this class.
AmbientController() {}
/**
* @return {@code true} if the activity is currently in ambient.
*/
public boolean isAmbient() {
return mDelegate == null ? false : mDelegate.isAmbient();
}
/**
* Sets whether this activity is currently in a state that supports ambient offload mode.
*/
public void setAmbientOffloadEnabled(boolean enabled) {
if (mDelegate != null) {
mDelegate.setAmbientOffloadEnabled(enabled);
}
}
/**
* Sets whether this activity's task should be moved to the front when the system exits
* ambient mode. If true, the activity's task may be moved to the front if it was the
* last activity to be running when ambient started, depending on how much time the
* system spent in ambient mode.
*/
public void setAutoResumeEnabled(boolean enabled) {
if (mDelegate != null) {
mDelegate.setAutoResumeEnabled(enabled);
}
}
}
}