1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.core.app; 18 19 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 20 21 import android.annotation.SuppressLint; 22 import android.app.PendingIntent; 23 import android.app.RemoteAction; 24 import android.graphics.drawable.Icon; 25 import android.os.Build; 26 27 import androidx.annotation.RequiresApi; 28 import androidx.annotation.RestrictTo; 29 import androidx.core.graphics.drawable.IconCompat; 30 import androidx.core.util.Preconditions; 31 import androidx.versionedparcelable.ParcelField; 32 import androidx.versionedparcelable.VersionedParcelable; 33 import androidx.versionedparcelable.VersionedParcelize; 34 35 import org.jspecify.annotations.NonNull; 36 37 /** 38 * Represents a remote action that can be called from another process. The action can have an 39 * associated visualization including metadata like an icon or title. 40 * <p> 41 * This is a backward-compatible version of {@link RemoteAction}. 42 */ 43 @VersionedParcelize(jetifyAs = "android.support.v4.app.RemoteActionCompat") 44 public final class RemoteActionCompat implements VersionedParcelable { 45 /** 46 */ 47 @SuppressWarnings("NotNullFieldNotInitialized") // VersionedParceleble inits this field. 48 @RestrictTo(LIBRARY_GROUP) 49 @ParcelField(1) 50 public @NonNull IconCompat mIcon; 51 /** 52 */ 53 @SuppressWarnings("NotNullFieldNotInitialized") // VersionedParceleble inits this field. 54 @RestrictTo(LIBRARY_GROUP) 55 @ParcelField(2) 56 public @NonNull CharSequence mTitle; 57 /** 58 */ 59 @SuppressWarnings("NotNullFieldNotInitialized") // VersionedParceleble inits this field. 60 @RestrictTo(LIBRARY_GROUP) 61 @ParcelField(3) 62 public @NonNull CharSequence mContentDescription; 63 /** 64 */ 65 @SuppressWarnings("NotNullFieldNotInitialized") // VersionedParceleble inits this field. 66 @RestrictTo(LIBRARY_GROUP) 67 @ParcelField(4) 68 public @NonNull PendingIntent mActionIntent; 69 /** 70 */ 71 @RestrictTo(LIBRARY_GROUP) 72 @ParcelField(5) 73 public boolean mEnabled; 74 /** 75 */ 76 @RestrictTo(LIBRARY_GROUP) 77 @ParcelField(6) 78 public boolean mShouldShowIcon; 79 RemoteActionCompat(@onNull IconCompat icon, @NonNull CharSequence title, @NonNull CharSequence contentDescription, @NonNull PendingIntent intent)80 public RemoteActionCompat(@NonNull IconCompat icon, @NonNull CharSequence title, 81 @NonNull CharSequence contentDescription, @NonNull PendingIntent intent) { 82 mIcon = Preconditions.checkNotNull(icon); 83 mTitle = Preconditions.checkNotNull(title); 84 mContentDescription = Preconditions.checkNotNull(contentDescription); 85 mActionIntent = Preconditions.checkNotNull(intent); 86 mEnabled = true; 87 mShouldShowIcon = true; 88 } 89 90 /** 91 * Used for VersionedParcelable. 92 */ 93 @RestrictTo(LIBRARY_GROUP) RemoteActionCompat()94 public RemoteActionCompat() {} 95 96 /** 97 * Constructs a {@link RemoteActionCompat} using data from {@code other}. 98 */ RemoteActionCompat(@onNull RemoteActionCompat other)99 public RemoteActionCompat(@NonNull RemoteActionCompat other) { 100 Preconditions.checkNotNull(other); 101 mIcon = other.mIcon; 102 mTitle = other.mTitle; 103 mContentDescription = other.mContentDescription; 104 mActionIntent = other.mActionIntent; 105 mEnabled = other.mEnabled; 106 mShouldShowIcon = other.mShouldShowIcon; 107 } 108 109 /** 110 * Creates an RemoteActionCompat from a RemoteAction. 111 */ 112 @RequiresApi(26) createFromRemoteAction( @onNull RemoteAction remoteAction)113 public static @NonNull RemoteActionCompat createFromRemoteAction( 114 @NonNull RemoteAction remoteAction) { 115 Preconditions.checkNotNull(remoteAction); 116 RemoteActionCompat action = new RemoteActionCompat(IconCompat.createFromIcon( 117 Api26Impl.getIcon(remoteAction)), 118 Api26Impl.getTitle(remoteAction), 119 Api26Impl.getContentDescription(remoteAction), 120 Api26Impl.getActionIntent(remoteAction)); 121 action.setEnabled(Api26Impl.isEnabled(remoteAction)); 122 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 123 action.setShouldShowIcon(Api28Impl.shouldShowIcon(remoteAction)); 124 } 125 return action; 126 } 127 128 /** 129 * Sets whether this action is enabled. 130 */ setEnabled(boolean enabled)131 public void setEnabled(boolean enabled) { 132 mEnabled = enabled; 133 } 134 135 /** 136 * Return whether this action is enabled. 137 */ isEnabled()138 public boolean isEnabled() { 139 return mEnabled; 140 } 141 142 /** 143 * Sets whether the icon should be shown. 144 */ setShouldShowIcon(boolean shouldShowIcon)145 public void setShouldShowIcon(boolean shouldShowIcon) { 146 mShouldShowIcon = shouldShowIcon; 147 } 148 149 /** 150 * Return whether the icon should be shown. 151 */ 152 @SuppressLint("KotlinPropertyAccess") shouldShowIcon()153 public boolean shouldShowIcon() { 154 return mShouldShowIcon; 155 } 156 157 /** 158 * Return an icon representing the action. 159 */ getIcon()160 public @NonNull IconCompat getIcon() { 161 return mIcon; 162 } 163 164 /** 165 * Return an title representing the action. 166 */ getTitle()167 public @NonNull CharSequence getTitle() { 168 return mTitle; 169 } 170 171 /** 172 * Return a content description representing the action. 173 */ getContentDescription()174 public @NonNull CharSequence getContentDescription() { 175 return mContentDescription; 176 } 177 178 /** 179 * Return the action intent. 180 */ getActionIntent()181 public @NonNull PendingIntent getActionIntent() { 182 return mActionIntent; 183 } 184 185 /** 186 * Convert this compat object to {@link RemoteAction} object. 187 * 188 * @return {@link RemoteAction} object 189 */ 190 @SuppressWarnings("deprecation") 191 @RequiresApi(26) toRemoteAction()192 public @NonNull RemoteAction toRemoteAction() { 193 RemoteAction action = Api26Impl.createRemoteAction(mIcon.toIcon(), mTitle, 194 mContentDescription, mActionIntent); 195 Api26Impl.setEnabled(action, isEnabled()); 196 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 197 Api28Impl.setShouldShowIcon(action, shouldShowIcon()); 198 } 199 return action; 200 } 201 202 @RequiresApi(28) 203 static class Api28Impl { Api28Impl()204 private Api28Impl() { 205 // This class is not instantiable. 206 } 207 shouldShowIcon(RemoteAction remoteAction)208 static boolean shouldShowIcon(RemoteAction remoteAction) { 209 return remoteAction.shouldShowIcon(); 210 } 211 setShouldShowIcon(RemoteAction remoteAction, boolean shouldShowIcon)212 static void setShouldShowIcon(RemoteAction remoteAction, boolean shouldShowIcon) { 213 remoteAction.setShouldShowIcon(shouldShowIcon); 214 } 215 } 216 217 @RequiresApi(26) 218 static class Api26Impl { Api26Impl()219 private Api26Impl() { 220 // This class is not instantiable. 221 } 222 getContentDescription(RemoteAction remoteAction)223 static CharSequence getContentDescription(RemoteAction remoteAction) { 224 return remoteAction.getContentDescription(); 225 } 226 getActionIntent(RemoteAction remoteAction)227 static PendingIntent getActionIntent(RemoteAction remoteAction) { 228 return remoteAction.getActionIntent(); 229 } 230 getTitle(RemoteAction remoteAction)231 static CharSequence getTitle(RemoteAction remoteAction) { 232 return remoteAction.getTitle(); 233 } 234 getIcon(RemoteAction remoteAction)235 static Icon getIcon(RemoteAction remoteAction) { 236 return remoteAction.getIcon(); 237 } 238 isEnabled(RemoteAction remoteAction)239 static boolean isEnabled(RemoteAction remoteAction) { 240 return remoteAction.isEnabled(); 241 } 242 createRemoteAction(Icon icon, CharSequence title, CharSequence contentDescription, PendingIntent intent)243 static RemoteAction createRemoteAction(Icon icon, CharSequence title, 244 CharSequence contentDescription, PendingIntent intent) { 245 return new RemoteAction(icon, title, contentDescription, intent); 246 } 247 setEnabled(RemoteAction remoteAction, boolean enabled)248 static void setEnabled(RemoteAction remoteAction, boolean enabled) { 249 remoteAction.setEnabled(enabled); 250 } 251 } 252 } 253