java.lang.Object
↳Activity
↳androidx.wear.watchface.ComplicationHelperActivity
Gradle dependencies
compile group: 'androidx.wear.watchface', name: 'watchface', version: '1.1.0-rc01'
- groupId: androidx.wear.watchface
- artifactId: watchface
- version: 1.1.0-rc01
Artifact androidx.wear.watchface:watchface:1.1.0-rc01 it located at Google repository (https://maven.google.com/)
Overview
Activity to handle permission requests for complications.
This can be used to start the complication data source chooser, making a permission request
if necessary, or to just make a permission request, and update all active complications if the
permission is granted.
To use, add this activity to your app, and also add the com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA permission.
Then, to start the complication data source chooser chooser, use
ComplicationHelperActivity.createComplicationDataSourceChooserHelperIntent(Context, ComponentName, int, Collection, String) to obtain an intent. If the
permission has not yet been granted, the permission will be requested and the complication
data source chooser chooser will only be started if the request is accepted by the user.
Or, to request the permission, for instance if android.support.wearable.complications.ComplicationData
of TYPE_NO_PERMISSION
has been received and tapped on, use
ComplicationHelperActivity.createPermissionRequestHelperIntent(Context, ComponentName).
Summary
Methods |
---|
public static Intent | createComplicationDataSourceChooserHelperIntent(Context context, ComponentName watchFace, int watchFaceComplicationId, java.util.Collection<ComplicationType> supportedTypes, java.lang.String watchFaceInstanceId)
Returns an intent that may be used to start the complication data source chooser activity via
the ComplicationHelperActivity. |
public static Intent | createPermissionRequestHelperIntent(Context context, ComponentName watchFace)
Returns an intent that may be used to start this activity in order to request the permission
required to receive complication data. |
protected void | onActivityResult(int requestCode, int resultCode, Intent data)
|
protected void | onCreate(Bundle savedInstanceState)
|
public void | onRequestPermissionsResult(int requestCode, java.lang.String permissions[], int[] grantResults[])
|
from java.lang.Object | clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Fields
public static boolean
useTestComplicationDataSourceChooserActivityWhether to invoke a specified activity instead of the system's complication data source
chooser.
To be used in tests.
public static boolean
skipPermissionCheckWhether to skip th permission check and directly attempt to invoke the complication data
source chooser.
To be used in tests.
public static final java.lang.String
ACTION_REQUEST_UPDATE_ALL_ACTIVEpublic static final java.lang.String
EXTRA_WATCH_FACE_COMPONENTpublic static final java.lang.String
ACTION_START_PROVIDER_CHOOSERpublic static final java.lang.String
ACTION_PERMISSION_REQUEST_ONLYConstructors
public
ComplicationHelperActivity()
Methods
protected void
onCreate(Bundle savedInstanceState)
public void
onRequestPermissionsResult(int requestCode, java.lang.String permissions[], int[] grantResults[])
protected void
onActivityResult(int requestCode, int resultCode, Intent data)
public static Intent
createComplicationDataSourceChooserHelperIntent(Context context, ComponentName watchFace, int watchFaceComplicationId, java.util.Collection<ComplicationType> supportedTypes, java.lang.String watchFaceInstanceId)
Returns an intent that may be used to start the complication data source chooser activity via
the ComplicationHelperActivity. This allows the required permission to be checked before the
complication data source chooser is displayed.
To use this, the ComplicationHelperActivity must be added to your app, and your app must
include the com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA
permission in its manifest.
The complication data source chooser activity will show a list of all complication data
sources that can supply data of at least one of the supportedTypes.
When the user chooses a complication data source, the configuration will be set up in the
complications system - the watch face does not need to do anything else.
The activity may be started using . The result
delivered back to your activity will have a result code of if a complication data source was successfully set, or a result code of if no complication data source was set. In the case
where a complication data source was set, android.support.wearable.complications.ComplicationProviderInfo
for the chosen
complication data source will be included in the data intent of the result, as an extra
with the key android.support.wearable.complications.EXTRA_PROVIDER_INFO.
The package of the calling app must match the package of the watch face, or this will not
work.
From android R onwards this API can only be called during an editing session.
Parameters:
context: context for the current app, that must contain a
ComplicationHelperActivity
watchFace: the ComponentName of the WatchFaceService being configured.
watchFaceComplicationId: the watch face's id for the complication being configured.
This must match the id passed in when the watch face calls
WatchFaceService.Engine#setActiveComplications.
supportedTypes: the types supported by the complication, in decreasing
order of
preference. If a complication data source can supply data for
more than one of these types, the type chosen will be
whichever was specified first.
watchFaceInstanceId: The ID of the watchface being edited.
public static Intent
createPermissionRequestHelperIntent(Context context, ComponentName watchFace)
Returns an intent that may be used to start this activity in order to request the permission
required to receive complication data.
To use this, the ComplicationHelperActivity must be added to your app, and your app must
include the com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA
permission in its manifest.
If the current app has already been granted this permission, the activity will finish
immediately.
If the current app has not been granted this permission, a permission request will be
made. If the permission is granted by the user, an update of all complications on the current
watch face will be triggered. The provided watchFace must match the current watch
face for this to occur.
Parameters:
context: context for the current app, that must contain a ComplicationHelperActivity
watchFace: the ComponentName of the WatchFaceService for the current watch face
Source
/*
* Copyright 2020 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.watchface;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.wearable.complications.ComplicationData;
import android.support.wearable.complications.ComplicationProviderInfo;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.core.app.ActivityCompat;
import androidx.wear.complications.ComplicationDataSourceUpdateRequesterConstants;
import androidx.wear.complications.data.ComplicationType;
import java.util.Collection;
import java.util.Objects;
/**
* Activity to handle permission requests for complications.
*
* <p>This can be used to start the complication data source chooser, making a permission request
* if necessary, or to just make a permission request, and update all active complications if the
* permission is granted.
*
* <p>To use, add this activity to your app, and also add the {@code
* com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA} permission.
*
* <p>Then, to start the complication data source chooser chooser, use
* {@link #createComplicationDataSourceChooserHelperIntent} to obtain an intent. If the
* permission has not yet been granted, the permission will be requested and the complication
* data source chooser chooser will only be started if the request is accepted by the user.
*
* <p>Or, to request the permission, for instance if {@link ComplicationData} of {@link
* ComplicationData#TYPE_NO_PERMISSION TYPE_NO_PERMISSION} has been received and tapped on, use
* {@link #createPermissionRequestHelperIntent}.
*
* @hide
*/
@RequiresApi(Build.VERSION_CODES.N)
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@SuppressWarnings("ForbiddenSuperClass")
public final class ComplicationHelperActivity extends Activity
implements ActivityCompat.OnRequestPermissionsResultCallback {
/**
* Whether to invoke a specified activity instead of the system's complication data source
* chooser.
*
* To be used in tests.
*/
public static boolean useTestComplicationDataSourceChooserActivity = false;
/**
* Whether to skip th permission check and directly attempt to invoke the complication data
* source chooser.
*
* To be used in tests.
*/
public static boolean skipPermissionCheck = false;
/** @hide */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public static final String ACTION_REQUEST_UPDATE_ALL_ACTIVE =
"android.support.wearable.complications.ACTION_REQUEST_UPDATE_ALL_ACTIVE";
/** @hide */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public static final String EXTRA_WATCH_FACE_COMPONENT =
"android.support.wearable.complications.EXTRA_WATCH_FACE_COMPONENT";
/** @hide */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public static final String ACTION_START_PROVIDER_CHOOSER =
"android.support.wearable.complications.ACTION_START_PROVIDER_CHOOSER";
/** @hide */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public static final String ACTION_PERMISSION_REQUEST_ONLY =
"android.support.wearable.complications.ACTION_PERMISSION_REQUEST_ONLY";
/** The package of the service that accepts complication data source requests. */
private static final String UPDATE_REQUEST_RECEIVER_PACKAGE = "com.google.android.wearable.app";
private static final int START_REQUEST_CODE_PROVIDER_CHOOSER = 1;
private static final int PERMISSION_REQUEST_CODE_PROVIDER_CHOOSER = 1;
private static final int PERMISSION_REQUEST_CODE_REQUEST_ONLY = 2;
private static final String COMPLICATIONS_PERMISSION =
"com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA";
private static final String COMPLICATIONS_PERMISSION_PRIVILEGED =
"com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA_PRIVILEGED";
@Nullable
private ComponentName mWatchFace;
private int mWfComplicationId;
@Nullable
private Bundle mAdditionalExtras;
@Nullable
@ComplicationData.ComplicationType
private int[] mTypes;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
switch (Objects.requireNonNull(intent.getAction())) {
case ACTION_START_PROVIDER_CHOOSER:
mWatchFace = intent.getParcelableExtra(
ComplicationDataSourceChooserIntent.EXTRA_WATCH_FACE_COMPONENT_NAME);
mWfComplicationId =
intent.getIntExtra(
ComplicationDataSourceChooserIntent.EXTRA_COMPLICATION_ID, 0);
mTypes = intent.getIntArrayExtra(
ComplicationDataSourceChooserIntent.EXTRA_SUPPORTED_TYPES);
mAdditionalExtras = getAdditionalExtras(intent);
if (checkPermission()) {
startComplicationDataSourceChooser();
} else {
ActivityCompat.requestPermissions(
this,
new String[]{COMPLICATIONS_PERMISSION},
PERMISSION_REQUEST_CODE_PROVIDER_CHOOSER);
}
break;
case ACTION_PERMISSION_REQUEST_ONLY:
mWatchFace = intent.getParcelableExtra(
ComplicationDataSourceChooserIntent.EXTRA_WATCH_FACE_COMPONENT_NAME);
if (checkPermission()) {
finish();
} else {
ActivityCompat.requestPermissions(
this,
new String[]{COMPLICATIONS_PERMISSION},
PERMISSION_REQUEST_CODE_REQUEST_ONLY);
}
break;
default:
throw new IllegalStateException("Unrecognised intent action.");
}
}
@Override
public void onRequestPermissionsResult(
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (grantResults.length == 0) {
// Request was cancelled.
finish();
return;
}
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestCode == PERMISSION_REQUEST_CODE_PROVIDER_CHOOSER) {
startComplicationDataSourceChooser();
} else {
finish();
}
requestUpdateAll(mWatchFace);
} else {
finish();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == START_REQUEST_CODE_PROVIDER_CHOOSER) {
setResult(resultCode, data);
finish();
}
}
private boolean checkPermission() {
return ActivityCompat.checkSelfPermission(this, COMPLICATIONS_PERMISSION_PRIVILEGED)
== PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(this, COMPLICATIONS_PERMISSION)
== PackageManager.PERMISSION_GRANTED
|| skipPermissionCheck;
}
/**
* Returns an intent that may be used to start the complication data source chooser activity via
* the ComplicationHelperActivity. This allows the required permission to be checked before the
* complication data source chooser is displayed.
*
* <p>To use this, the ComplicationHelperActivity must be added to your app, and your app must
* include the {@code com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA}
* permission in its manifest.
*
* <p>The complication data source chooser activity will show a list of all complication data
* sources that can supply data of at least one of the {@code supportedTypes}.
*
* <p>When the user chooses a complication data source, the configuration will be set up in the
* complications system - the watch face does not need to do anything else.
*
* <p>The activity may be started using {@link Activity#startActivityForResult}. The result
* delivered back to your activity will have a result code of {@link Activity#RESULT_OK
* RESULT_OK} if a complication data source was successfully set, or a result code of {@link
* Activity#RESULT_CANCELED RESULT_CANCELED} if no complication data source was set. In the case
* where a complication data source was set, {@link ComplicationProviderInfo} for the chosen
* complication data source will be included in the data intent of the result, as an extra
* with the key android.support.wearable.complications.EXTRA_PROVIDER_INFO.
*
* <p>The package of the calling app must match the package of the watch face, or this will not
* work.
*
* <p>From android R onwards this API can only be called during an editing session.
*
* @param context context for the current app, that must contain a
* ComplicationHelperActivity
* @param watchFace the ComponentName of the WatchFaceService being configured.
* @param watchFaceComplicationId the watch face's id for the complication being configured.
* This must match the id passed in when the watch face calls
* WatchFaceService.Engine#setActiveComplications.
* @param supportedTypes the types supported by the complication, in decreasing
* order of
* preference. If a complication data source can supply data for
* more than one of these types, the type chosen will be
* whichever was specified first.
* @param watchFaceInstanceId The ID of the watchface being edited.
*/
@NonNull
public static Intent createComplicationDataSourceChooserHelperIntent(
@NonNull Context context,
@NonNull ComponentName watchFace,
int watchFaceComplicationId,
@NonNull Collection<ComplicationType> supportedTypes,
@Nullable String watchFaceInstanceId) {
Intent intent = new Intent(context, ComplicationHelperActivity.class);
intent.setAction(ACTION_START_PROVIDER_CHOOSER);
intent.putExtra(
ComplicationDataSourceChooserIntent.EXTRA_WATCH_FACE_COMPONENT_NAME, watchFace);
intent.putExtra(
ComplicationDataSourceChooserIntent.EXTRA_COMPLICATION_ID, watchFaceComplicationId);
if (watchFaceInstanceId != null) {
intent.putExtra(ComplicationDataSourceChooserIntent.EXTRA_WATCHFACE_INSTANCE_ID,
watchFaceInstanceId);
}
int[] wireSupportedTypes = new int[supportedTypes.size()];
int i = 0;
for (ComplicationType supportedType : supportedTypes) {
wireSupportedTypes[i++] = supportedType.toWireComplicationType();
}
intent.putExtra(ComplicationDataSourceChooserIntent.EXTRA_SUPPORTED_TYPES,
wireSupportedTypes);
return intent;
}
/**
* Returns an intent that may be used to start this activity in order to request the permission
* required to receive complication data.
*
* <p>To use this, the ComplicationHelperActivity must be added to your app, and your app must
* include the {@code com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA}
* permission in its manifest.
*
* <p>If the current app has already been granted this permission, the activity will finish
* immediately.
*
* <p>If the current app has not been granted this permission, a permission request will be
* made. If the permission is granted by the user, an update of all complications on the current
* watch face will be triggered. The provided {@code watchFace} must match the current watch
* face for this to occur.
*
* @param context context for the current app, that must contain a ComplicationHelperActivity
* @param watchFace the ComponentName of the WatchFaceService for the current watch face
*/
@NonNull
public static Intent createPermissionRequestHelperIntent(
@NonNull Context context, @NonNull ComponentName watchFace) {
Intent intent = new Intent(context, ComplicationHelperActivity.class);
intent.setAction(ACTION_PERMISSION_REQUEST_ONLY);
intent.putExtra(ComplicationDataSourceChooserIntent.EXTRA_WATCH_FACE_COMPONENT_NAME,
watchFace);
return intent;
}
private void startComplicationDataSourceChooser() {
Intent intent =
ComplicationDataSourceChooserIntent.createComplicationDataSourceChooserIntent(
mWatchFace, mWfComplicationId, mTypes);
// Add the extras that were provided to the ComplicationHelperActivity. This is done by
// first taking the additional extras and adding to that anything that was set in the
// chooser intent, and setting them back on the intent itself to avoid the additional
// extras being able to override anything that was set by the chooser intent.
Bundle extras = new Bundle(mAdditionalExtras);
extras.putAll(intent.getExtras());
intent.replaceExtras(extras);
if (useTestComplicationDataSourceChooserActivity) {
intent.setComponent(new ComponentName(
"androidx.wear.watchface.editor.test",
"androidx.wear.watchface.editor.TestComplicationDataSourceChooserActivity"));
}
startActivityForResult(intent, START_REQUEST_CODE_PROVIDER_CHOOSER);
}
/** Requests that the system update all active complications on the watch face. */
private void requestUpdateAll(ComponentName watchFaceComponent) {
Intent intent = new Intent(ACTION_REQUEST_UPDATE_ALL_ACTIVE);
intent.setPackage(UPDATE_REQUEST_RECEIVER_PACKAGE);
intent.putExtra(EXTRA_WATCH_FACE_COMPONENT, watchFaceComponent);
// Add a placeholder PendingIntent to allow the UID to be checked.
intent.putExtra(
ComplicationDataSourceUpdateRequesterConstants.EXTRA_PENDING_INTENT,
PendingIntent.getActivity(this, 0, new Intent(""), 0));
sendBroadcast(intent);
}
/**
* Returns any extras that were not handled by the activity itself.
*
* <p>These will be forwarded to the chooser activity.
*/
private Bundle getAdditionalExtras(Intent intent) {
Bundle extras = intent.getExtras();
extras.remove(ComplicationDataSourceChooserIntent.EXTRA_WATCH_FACE_COMPONENT_NAME);
extras.remove(ComplicationDataSourceChooserIntent.EXTRA_COMPLICATION_ID);
extras.remove(ComplicationDataSourceChooserIntent.EXTRA_SUPPORTED_TYPES);
return extras;
}
}