IntentSender.java revision 7f2054392e9957d3ba8579ef08c29cfb27df564e
1/* 2 * Copyright (C) 2006 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.content; 18 19import android.content.Context; 20import android.content.Intent; 21import android.content.IIntentSender; 22import android.content.IIntentReceiver; 23import android.os.Bundle; 24import android.os.RemoteException; 25import android.os.Handler; 26import android.os.IBinder; 27import android.os.Parcel; 28import android.os.Parcelable; 29import android.util.AndroidException; 30 31 32/** 33 * A description of an Intent and target action to perform with it. 34 * The returned object can be 35 * handed to other applications so that they can perform the action you 36 * described on your behalf at a later time. 37 * 38 * <p>By giving a IntentSender to another application, 39 * you are granting it the right to perform the operation you have specified 40 * as if the other application was yourself (with the same permissions and 41 * identity). As such, you should be careful about how you build the IntentSender: 42 * often, for example, the base Intent you supply will have the component 43 * name explicitly set to one of your own components, to ensure it is ultimately 44 * sent there and nowhere else. 45 * 46 * <p>A IntentSender itself is simply a reference to a token maintained by 47 * the system describing the original data used to retrieve it. This means 48 * that, even if its owning application's process is killed, the 49 * IntentSender itself will remain usable from other processes that 50 * have been given it. If the creating application later re-retrieves the 51 * same kind of IntentSender (same operation, same Intent action, data, 52 * categories, and components, and same flags), it will receive a IntentSender 53 * representing the same token if that is still valid. 54 * 55 * <p>Instances of this class can not be made directly, but rather must be 56 * created from an existing {@link android.app.PendingIntent} with 57 * {@link android.app.PendingIntent#getIntentSender() PendingIntent.getIntentSender()}. 58 */ 59public class IntentSender implements Parcelable { 60 private final IIntentSender mTarget; 61 62 /** 63 * Exception thrown when trying to send through a PendingIntent that 64 * has been canceled or is otherwise no longer able to execute the request. 65 */ 66 public static class SendIntentException extends AndroidException { 67 public SendIntentException() { 68 } 69 70 public SendIntentException(String name) { 71 super(name); 72 } 73 74 public SendIntentException(Exception cause) { 75 super(cause); 76 } 77 } 78 79 /** 80 * Callback interface for discovering when a send operation has 81 * completed. Primarily for use with a IntentSender that is 82 * performing a broadcast, this provides the same information as 83 * calling {@link Context#sendOrderedBroadcast(Intent, String, 84 * android.content.BroadcastReceiver, Handler, int, String, Bundle) 85 * Context.sendBroadcast()} with a final BroadcastReceiver. 86 */ 87 public interface OnFinished { 88 /** 89 * Called when a send operation as completed. 90 * 91 * @param IntentSender The IntentSender this operation was sent through. 92 * @param intent The original Intent that was sent. 93 * @param resultCode The final result code determined by the send. 94 * @param resultData The final data collected by a broadcast. 95 * @param resultExtras The final extras collected by a broadcast. 96 */ 97 void onSendFinished(IntentSender IntentSender, Intent intent, 98 int resultCode, String resultData, Bundle resultExtras); 99 } 100 101 private static class FinishedDispatcher extends IIntentReceiver.Stub 102 implements Runnable { 103 private final IntentSender mIntentSender; 104 private final OnFinished mWho; 105 private final Handler mHandler; 106 private Intent mIntent; 107 private int mResultCode; 108 private String mResultData; 109 private Bundle mResultExtras; 110 FinishedDispatcher(IntentSender pi, OnFinished who, Handler handler) { 111 mIntentSender = pi; 112 mWho = who; 113 mHandler = handler; 114 } 115 public void performReceive(Intent intent, int resultCode, 116 String data, Bundle extras, boolean serialized) { 117 mIntent = intent; 118 mResultCode = resultCode; 119 mResultData = data; 120 mResultExtras = extras; 121 if (mHandler == null) { 122 run(); 123 } else { 124 mHandler.post(this); 125 } 126 } 127 public void run() { 128 mWho.onSendFinished(mIntentSender, mIntent, mResultCode, 129 mResultData, mResultExtras); 130 } 131 } 132 133 /** 134 * Perform the operation associated with this IntentSender, allowing the 135 * caller to specify information about the Intent to use and be notified 136 * when the send has completed. 137 * 138 * @param context The Context of the caller. This may be null if 139 * <var>intent</var> is also null. 140 * @param code Result code to supply back to the IntentSender's target. 141 * @param intent Additional Intent data. See {@link Intent#fillIn 142 * Intent.fillIn()} for information on how this is applied to the 143 * original Intent. Use null to not modify the original Intent. 144 * @param onFinished The object to call back on when the send has 145 * completed, or null for no callback. 146 * @param handler Handler identifying the thread on which the callback 147 * should happen. If null, the callback will happen from the thread 148 * pool of the process. 149 * 150 * 151 * @throws SendIntentException Throws CanceledIntentException if the IntentSender 152 * is no longer allowing more intents to be sent through it. 153 */ 154 public void sendIntent(Context context, int code, Intent intent, 155 OnFinished onFinished, Handler handler) throws SendIntentException { 156 try { 157 String resolvedType = intent != null ? 158 intent.resolveTypeIfNeeded(context.getContentResolver()) 159 : null; 160 int res = mTarget.send(code, intent, resolvedType, 161 onFinished != null 162 ? new FinishedDispatcher(this, onFinished, handler) 163 : null); 164 if (res < 0) { 165 throw new SendIntentException(); 166 } 167 } catch (RemoteException e) { 168 throw new SendIntentException(); 169 } 170 } 171 172 /** 173 * Comparison operator on two IntentSender objects, such that true 174 * is returned then they both represent the same operation from the 175 * same package. 176 */ 177 @Override 178 public boolean equals(Object otherObj) { 179 if (otherObj instanceof IntentSender) { 180 return mTarget.asBinder().equals(((IntentSender)otherObj) 181 .mTarget.asBinder()); 182 } 183 return false; 184 } 185 186 @Override 187 public int hashCode() { 188 return mTarget.asBinder().hashCode(); 189 } 190 191 @Override 192 public String toString() { 193 StringBuilder sb = new StringBuilder(128); 194 sb.append("IntentSender{"); 195 sb.append(Integer.toHexString(System.identityHashCode(this))); 196 sb.append(": "); 197 sb.append(mTarget != null ? mTarget.asBinder() : null); 198 sb.append('}'); 199 return sb.toString(); 200 } 201 202 public int describeContents() { 203 return 0; 204 } 205 206 public void writeToParcel(Parcel out, int flags) { 207 out.writeStrongBinder(mTarget.asBinder()); 208 } 209 210 public static final Parcelable.Creator<IntentSender> CREATOR 211 = new Parcelable.Creator<IntentSender>() { 212 public IntentSender createFromParcel(Parcel in) { 213 IBinder target = in.readStrongBinder(); 214 return target != null ? new IntentSender(target) : null; 215 } 216 217 public IntentSender[] newArray(int size) { 218 return new IntentSender[size]; 219 } 220 }; 221 222 /** 223 * Convenience function for writing either a IntentSender or null pointer to 224 * a Parcel. You must use this with {@link #readIntentSenderOrNullFromParcel} 225 * for later reading it. 226 * 227 * @param sender The IntentSender to write, or null. 228 * @param out Where to write the IntentSender. 229 */ 230 public static void writeIntentSenderOrNullToParcel(IntentSender sender, 231 Parcel out) { 232 out.writeStrongBinder(sender != null ? sender.mTarget.asBinder() 233 : null); 234 } 235 236 /** 237 * Convenience function for reading either a Messenger or null pointer from 238 * a Parcel. You must have previously written the Messenger with 239 * {@link #writeIntentSenderOrNullToParcel}. 240 * 241 * @param in The Parcel containing the written Messenger. 242 * 243 * @return Returns the Messenger read from the Parcel, or null if null had 244 * been written. 245 */ 246 public static IntentSender readIntentSenderOrNullFromParcel(Parcel in) { 247 IBinder b = in.readStrongBinder(); 248 return b != null ? new IntentSender(b) : null; 249 } 250 251 /** @hide */ 252 public IntentSender(IIntentSender target) { 253 mTarget = target; 254 } 255 256 /** @hide */ 257 public IntentSender(IBinder target) { 258 mTarget = IIntentSender.Stub.asInterface(target); 259 } 260} 261