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