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 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 * If set in an Intent passed to {@link Context#startActivity Context.startActivity()}, 178 * this flag will cause a newly launching task to be placed on top of the current 179 * home activity task (if there is one). That is, pressing back from the task 180 * will always return the user to home even if that was not the last activity they 181 * saw. This can only be used in conjunction with 182 * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}. 183 */ 184 public static final int FLAG_ACTIVITY_TASK_ON_HOME = 0x00004000; 185 186 /** 187 * If set in an Intent passed to {@link Context#startActivity Context.startActivity()}, 188 * this flag will cause any existing task that would be associated with the 189 * activity to be cleared before the activity is started. That is, the activity 190 * becomes the new root of an otherwise empty task, and any old activities 191 * are finished. This can only be used in conjunction with 192 * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}. 193 * 194 * <p>This flag will only be obeyed on devices supporting API 11 or higher.</p> 195 */ 196 public static final int FLAG_ACTIVITY_CLEAR_TASK = 0x00008000; 197 198 /** 199 * Create an intent to launch the main (root) activity of a task. This 200 * is the Intent that is started when the application's is launched from 201 * Home. For anything else that wants to launch an application in the 202 * same way, it is important that they use an Intent structured the same 203 * way, and can use this function to ensure this is the case. 204 * 205 * <p>The returned Intent has the given Activity component as its explicit 206 * component, {@link Intent#ACTION_MAIN ACTION_MAIN} as its action, and includes the 207 * category {@link Intent#CATEGORY_LAUNCHER CATEGORY_LAUNCHER}. This does <em>not</em> have 208 * {@link Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} set, 209 * though typically you will want to do that through {@link Intent#addFlags(int) addFlags(int)} 210 * on the returned Intent. 211 * 212 * @param mainActivity The main activity component that this Intent will 213 * launch. 214 * @return Returns a newly created Intent that can be used to launch the 215 * activity as a main application entry. 216 * 217 * @see Intent#setClass 218 * @see Intent#setComponent 219 */ 220 public static Intent makeMainActivity(ComponentName mainActivity) { 221 return IMPL.makeMainActivity(mainActivity); 222 } 223 224 225 /** 226 * Make an Intent for the main activity of an application, without 227 * specifying a specific activity to run but giving a selector to find 228 * the activity. This results in a final Intent that is structured 229 * the same as when the application is launched from 230 * Home. For anything else that wants to launch an application in the 231 * same way, it is important that they use an Intent structured the same 232 * way, and can use this function to ensure this is the case. 233 * 234 * <p>The returned Intent has {@link Intent#ACTION_MAIN} as its action, and includes the 235 * category {@link Intent#CATEGORY_LAUNCHER}. This does <em>not</em> have 236 * {@link Intent#FLAG_ACTIVITY_NEW_TASK} set, though typically you will want 237 * to do that through {@link Intent#addFlags(int)} on the returned Intent. 238 * 239 * @param selectorAction The action name of the Intent's selector. 240 * @param selectorCategory The name of a category to add to the Intent's 241 * selector. 242 * @return Returns a newly created Intent that can be used to launch the 243 * activity as a main application entry. 244 * 245 * @see #setSelector(Intent) 246 */ 247 public static Intent makeMainSelectorActivity(String selectorAction, 248 String selectorCategory) { 249 return IMPL.makeMainSelectorActivity(selectorAction, selectorCategory); 250 } 251 252 /** 253 * Make an Intent that can be used to re-launch an application's task 254 * in its base state. This is like {@link #makeMainActivity(ComponentName)}, 255 * but also sets the flags {@link Intent#FLAG_ACTIVITY_NEW_TASK} and 256 * {@link IntentCompat#FLAG_ACTIVITY_CLEAR_TASK}. 257 * 258 * @param mainActivity The activity component that is the root of the 259 * task; this is the activity that has been published in the application's 260 * manifest as the main launcher icon. 261 * 262 * @return Returns a newly created Intent that can be used to relaunch the 263 * activity's task in its root state. 264 */ 265 public static Intent makeRestartActivityTask(ComponentName mainActivity) { 266 return IMPL.makeRestartActivityTask(mainActivity); 267 } 268} 269