1/* 2 * Copyright (C) 2011 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 17package android.support.v4.content; 18 19import android.content.ComponentName; 20import android.content.Context; 21import android.content.Intent; 22import android.os.Build; 23 24/** 25 * Helper for accessing features in {@link android.content.Intent} 26 * introduced after API level 4 in a backwards compatible fashion. 27 */ 28public final class IntentCompat { 29 30 interface IntentCompatImpl { 31 Intent makeMainActivity(ComponentName componentName); 32 Intent makeMainSelectorActivity(String selectorAction, String selectorCategory); 33 Intent makeRestartActivityTask(ComponentName mainActivity); 34 } 35 36 static class IntentCompatImplBase implements IntentCompatImpl { 37 @Override 38 public Intent makeMainActivity(ComponentName componentName) { 39 Intent intent = new Intent(Intent.ACTION_MAIN); 40 intent.setComponent(componentName); 41 intent.addCategory(Intent.CATEGORY_LAUNCHER); 42 return intent; 43 } 44 45 @Override 46 public Intent makeMainSelectorActivity(String selectorAction, 47 String selectorCategory) { 48 // Before api 15 you couldn't set a selector intent. 49 // Fall back and just return an intent with the requested action/category, 50 // even though it won't be a proper "main" intent. 51 Intent intent = new Intent(selectorAction); 52 intent.addCategory(selectorCategory); 53 return intent; 54 } 55 56 @Override 57 public Intent makeRestartActivityTask(ComponentName mainActivity) { 58 Intent intent = makeMainActivity(mainActivity); 59 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 60 | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK); 61 return intent; 62 } 63 } 64 65 static class IntentCompatImplHC extends IntentCompatImplBase { 66 @Override 67 public Intent makeMainActivity(ComponentName componentName) { 68 return IntentCompatHoneycomb.makeMainActivity(componentName); 69 } 70 @Override 71 public Intent makeRestartActivityTask(ComponentName componentName) { 72 return IntentCompatHoneycomb.makeRestartActivityTask(componentName); 73 } 74 } 75 76 static class IntentCompatImplIcsMr1 extends IntentCompatImplHC { 77 @Override 78 public Intent makeMainSelectorActivity(String selectorAction, String selectorCategory) { 79 return IntentCompatIcsMr1.makeMainSelectorActivity(selectorAction, selectorCategory); 80 } 81 } 82 83 private static final IntentCompatImpl IMPL; 84 static { 85 final int version = Build.VERSION.SDK_INT; 86 if (version >= 15) { 87 IMPL = new IntentCompatImplIcsMr1(); 88 } else if (version >= 11) { 89 IMPL = new IntentCompatImplHC(); 90 } else { 91 IMPL = new IntentCompatImplBase(); 92 } 93 } 94 95 private IntentCompat() { 96 /* Hide constructor */ 97 } 98 99 /** 100 * Broadcast Action: Resources for a set of packages (which were 101 * previously unavailable) are currently 102 * available since the media on which they exist is available. 103 * The extra data {@link #EXTRA_CHANGED_PACKAGE_LIST} contains a 104 * list of packages whose availability changed. 105 * The extra data {@link #EXTRA_CHANGED_UID_LIST} contains a 106 * list of uids of packages whose availability changed. 107 * Note that the 108 * packages in this list do <em>not</em> receive this broadcast. 109 * The specified set of packages are now available on the system. 110 * <p>Includes the following extras: 111 * <ul> 112 * <li> {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages 113 * whose resources(were previously unavailable) are currently available. 114 * {@link #EXTRA_CHANGED_UID_LIST} is the set of uids of the 115 * packages whose resources(were previously unavailable) 116 * are currently available. 117 * </ul> 118 * 119 * <p class="note">This is a protected intent that can only be sent 120 * by the system. 121 */ 122 public static final String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = 123 "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE"; 124 125 /** 126 * Broadcast Action: Resources for a set of packages are currently 127 * unavailable since the media on which they exist is unavailable. 128 * The extra data {@link #EXTRA_CHANGED_PACKAGE_LIST} contains a 129 * list of packages whose availability changed. 130 * The extra data {@link #EXTRA_CHANGED_UID_LIST} contains a 131 * list of uids of packages whose availability changed. 132 * The specified set of packages can no longer be 133 * launched and are practically unavailable on the system. 134 * <p>Inclues the following extras: 135 * <ul> 136 * <li> {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages 137 * whose resources are no longer available. 138 * {@link #EXTRA_CHANGED_UID_LIST} is the set of packages 139 * whose resources are no longer available. 140 * </ul> 141 * 142 * <p class="note">This is a protected intent that can only be sent 143 * by the system. 144 */ 145 public static final String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = 146 "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE"; 147 148 /** 149 * This field is part of 150 * {@link android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE}, 151 * {@link android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE} 152 * and contains a string array of all of the components that have changed. 153 */ 154 public static final String EXTRA_CHANGED_PACKAGE_LIST = 155 "android.intent.extra.changed_package_list"; 156 157 /** 158 * This field is part of 159 * {@link android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE}, 160 * {@link android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE} 161 * and contains an integer array of uids of all of the components 162 * that have changed. 163 */ 164 public static final String EXTRA_CHANGED_UID_LIST = 165 "android.intent.extra.changed_uid_list"; 166 167 /** 168 * A constant String that is associated with the Intent, used with 169 * {@link android.content.Intent#ACTION_SEND} to supply an alternative to 170 * {@link android.content.Intent#EXTRA_TEXT} 171 * as HTML formatted text. Note that you <em>must</em> also supply 172 * {@link android.content.Intent#EXTRA_TEXT}. 173 */ 174 public static final String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT"; 175 176 /** 177 * Indicates an activity optimized for Leanback mode, and that should 178 * be displayed in the Leanback launcher. 179 */ 180 public static final String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER"; 181 182 /** 183 * If set in an Intent passed to {@link Context#startActivity Context.startActivity()}, 184 * this flag will cause a newly launching task to be placed on top of the current 185 * home activity task (if there is one). That is, pressing back from the task 186 * will always return the user to home even if that was not the last activity they 187 * saw. This can only be used in conjunction with 188 * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}. 189 */ 190 public static final int FLAG_ACTIVITY_TASK_ON_HOME = 0x00004000; 191 192 /** 193 * If set in an Intent passed to {@link Context#startActivity Context.startActivity()}, 194 * this flag will cause any existing task that would be associated with the 195 * activity to be cleared before the activity is started. That is, the activity 196 * becomes the new root of an otherwise empty task, and any old activities 197 * are finished. This can only be used in conjunction with 198 * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}. 199 * 200 * <p>This flag will only be obeyed on devices supporting API 11 or higher.</p> 201 */ 202 public static final int FLAG_ACTIVITY_CLEAR_TASK = 0x00008000; 203 204 /** 205 * Create an intent to launch the main (root) activity of a task. This 206 * is the Intent that is started when the application's is launched from 207 * Home. For anything else that wants to launch an application in the 208 * same way, it is important that they use an Intent structured the same 209 * way, and can use this function to ensure this is the case. 210 * 211 * <p>The returned Intent has the given Activity component as its explicit 212 * component, {@link Intent#ACTION_MAIN ACTION_MAIN} as its action, and includes the 213 * category {@link Intent#CATEGORY_LAUNCHER CATEGORY_LAUNCHER}. This does <em>not</em> have 214 * {@link Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} set, 215 * though typically you will want to do that through {@link Intent#addFlags(int) addFlags(int)} 216 * on the returned Intent. 217 * 218 * @param mainActivity The main activity component that this Intent will 219 * launch. 220 * @return Returns a newly created Intent that can be used to launch the 221 * activity as a main application entry. 222 * 223 * @see Intent#setClass 224 * @see Intent#setComponent 225 */ 226 public static Intent makeMainActivity(ComponentName mainActivity) { 227 return IMPL.makeMainActivity(mainActivity); 228 } 229 230 231 /** 232 * Make an Intent for the main activity of an application, without 233 * specifying a specific activity to run but giving a selector to find 234 * the activity. This results in a final Intent that is structured 235 * the same as when the application is launched from 236 * Home. For anything else that wants to launch an application in the 237 * same way, it is important that they use an Intent structured the same 238 * way, and can use this function to ensure this is the case. 239 * 240 * <p>The returned Intent has {@link Intent#ACTION_MAIN} as its action, and includes the 241 * category {@link Intent#CATEGORY_LAUNCHER}. This does <em>not</em> have 242 * {@link Intent#FLAG_ACTIVITY_NEW_TASK} set, though typically you will want 243 * to do that through {@link Intent#addFlags(int)} on the returned Intent. 244 * 245 * @param selectorAction The action name of the Intent's selector. 246 * @param selectorCategory The name of a category to add to the Intent's 247 * selector. 248 * @return Returns a newly created Intent that can be used to launch the 249 * activity as a main application entry. 250 */ 251 public static Intent makeMainSelectorActivity(String selectorAction, 252 String selectorCategory) { 253 return IMPL.makeMainSelectorActivity(selectorAction, selectorCategory); 254 } 255 256 /** 257 * Make an Intent that can be used to re-launch an application's task 258 * in its base state. This is like {@link #makeMainActivity(ComponentName)}, 259 * but also sets the flags {@link Intent#FLAG_ACTIVITY_NEW_TASK} and 260 * {@link IntentCompat#FLAG_ACTIVITY_CLEAR_TASK}. 261 * 262 * @param mainActivity The activity component that is the root of the 263 * task; this is the activity that has been published in the application's 264 * manifest as the main launcher icon. 265 * 266 * @return Returns a newly created Intent that can be used to relaunch the 267 * activity's task in its root state. 268 */ 269 public static Intent makeRestartActivityTask(ComponentName mainActivity) { 270 return IMPL.makeRestartActivityTask(mainActivity); 271 } 272} 273