PendingIntent实现原理和代码

对于Android的Intent相关内容,可能部分初级Android开发者不知道PendingIntent是干什么的? 对于Notification和SmsManager中的sendMessage以及AlarmManager中的set这些方法中均有PendingIntent,到底PendingIntent和Intent有哪些不同呢?

一、Intent

通常Android中的Intent位于 android.content.Intent的实现比较简单,直接从Object类实现,内部主要是保存了一些String或Int、轻量级的数组,提供了一些方法主要是赋值或取值。

二、PendingIntent

这里和Intent的不同分在了android.app.PendingIntent这个包中,属于app层而不是数据存储封装的content层,从首段我们看到了PendingIntent是针对将要发生的事情,比如短信发送时,本对象用于跟踪未来短信的接收情况,主要是短信回执报告和发送成功或失败,因为GSM通讯到RIL再到移动基站的过程很漫长,通过开一个Thread等待对于我们的应用是比较麻烦和耗资源,而Android的框架层的TelephonyManager底层远程服务会跟踪,最终通过PendingIntent来跟踪,有关具体实现原理和代码如下:

public final class PendingIntent implements Parcelable { //实现了Parcelable接口,可以方便的处理二进制数据和用于远程服务的数据交换
private final IIntentSender mTarget;

public static final int FLAG_ONE_SHOT = 1<<30;
public static final int FLAG_NO_CREATE = 1<<29;
public static final int FLAG_CANCEL_CURRENT = 1<<28;
public static final int FLAG_UPDATE_CURRENT = 1<<27;

public static class CanceledException extends AndroidException {
    public CanceledException() {
    }

    public CanceledException(String name) {
        super(name);
    }

    public CanceledException(Exception cause) {
        super(cause);
    }
}

public interface OnFinished {
    void onSendFinished(PendingIntent pendingIntent, Intent intent,
            int resultCode, String resultData, Bundle resultExtras);
}

private static class FinishedDispatcher extends IIntentReceiver.Stub   //这里Android123友情提示如果你掌握了Android的RemoteService或Java RMI这里应该好理解
        implements Runnable {
    private final PendingIntent mPendingIntent;
    private final OnFinished mWho;
    private final Handler mHandler;
    private Intent mIntent;
    private int mResultCode;
    private String mResultData;
    private Bundle mResultExtras;
    FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler) {
        mPendingIntent = pi;
        mWho = who;
        mHandler = handler;
    }
    public void performReceive(Intent intent, int resultCode,
            String data, Bundle extras, boolean serialized, boolean sticky) {
        mIntent = intent;
        mResultCode = resultCode;
        mResultData = data;
        mResultExtras = extras;
        if (mHandler == null) {
            run();
        } else {
            mHandler.post(this);
        }
    }
    public void run() {
        mWho.onSendFinished(mPendingIntent, mIntent, mResultCode,
                mResultData, mResultExtras);
    }
}

public static PendingIntent getActivity(Context context, int requestCode,
        Intent intent, int flags) {
    String packageName = context.getPackageName();
    String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
            context.getContentResolver()) : null;
    try {
        IIntentSender target =
            ActivityManagerNative.getDefault().getIntentSender(
                IActivityManager.INTENT_SENDER_ACTIVITY, packageName,
                null, null, requestCode, intent, resolvedType, flags);
        return target != null ? new PendingIntent(target) : null;
    } catch (RemoteException e) {
    }
    return null;
}

public static PendingIntent getBroadcast(Context context, int requestCode,
        Intent intent, int flags) {
    String packageName = context.getPackageName();
    String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
            context.getContentResolver()) : null;
    try {
        IIntentSender target =
            ActivityManagerNative.getDefault().getIntentSender(
                IActivityManager.INTENT_SENDER_BROADCAST, packageName,
                null, null, requestCode, intent, resolvedType, flags);
        return target != null ? new PendingIntent(target) : null;
    } catch (RemoteException e) {
    }
    return null;
}

public static PendingIntent getService(Context context, int requestCode,
        Intent intent, int flags) {
    String packageName = context.getPackageName();
    String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
            context.getContentResolver()) : null;
    try {
        IIntentSender target =
            ActivityManagerNative.getDefault().getIntentSender(
                IActivityManager.INTENT_SENDER_SERVICE, packageName,
                null, null, requestCode, intent, resolvedType, flags);
        return target != null ? new PendingIntent(target) : null;
    } catch (RemoteException e) {
    }
    return null;
}

public IntentSender getIntentSender() {
    return new IntentSender(mTarget);
}

public void cancel() {
    try {
        ActivityManagerNative.getDefault().cancelIntentSender(mTarget);
    } catch (RemoteException e) {
    }
}

public void send() throws CanceledException {
    send(null, 0, null, null, null);
}

public void send(int code) throws CanceledException {
    send(null, code, null, null, null);
}

public void send(Context context, int code, Intent intent)
        throws CanceledException {
    send(context, code, intent, null, null);
}

public void send(int code, OnFinished onFinished, Handler handler)
        throws CanceledException {
    send(null, code, null, onFinished, handler);
}

public void send(Context context, int code, Intent intent,
        OnFinished onFinished, Handler handler) throws CanceledException {
    try {
        String resolvedType = intent != null ?
                intent.resolveTypeIfNeeded(context.getContentResolver())
                : null;
        int res = mTarget.send(code, intent, resolvedType,
                onFinished != null
                ? new FinishedDispatcher(this, onFinished, handler)
                : null);
        if (res < 0) {
            throw new CanceledException();
        }
    } catch (RemoteException e) {
        throw new CanceledException(e);
    }
}

public String getTargetPackage() {
    try {
        return ActivityManagerNative.getDefault()
            .getPackageForIntentSender(mTarget);
    } catch (RemoteException e) {
        // Should never happen.
        return null;
    }
}

@Override
public boolean equals(Object otherObj) {
    if (otherObj instanceof PendingIntent) {
        return mTarget.asBinder().equals(((PendingIntent)otherObj)
                .mTarget.asBinder());
    }
    return false;
}

@Override
public int hashCode() {
    return mTarget.asBinder().hashCode();
}

@Override
public String toString() {
    StringBuilder sb = new StringBuilder(128);
    sb.append("PendingIntent{");
    sb.append(Integer.toHexString(System.identityHashCode(this)));
    sb.append(": ");
    sb.append(mTarget != null ? mTarget.asBinder() : null);
    sb.append('}');
    return sb.toString();
}

public int describeContents() {
    return 0;
}

public void writeToParcel(Parcel out, int flags) {
    out.writeStrongBinder(mTarget.asBinder());
}

public static final Parcelable.Creator<PendingIntent> CREATOR
        = new Parcelable.Creator<PendingIntent>() {
    public PendingIntent createFromParcel(Parcel in) {
        IBinder target = in.readStrongBinder();
        return target != null ? new PendingIntent(target) : null;
    }

    public PendingIntent[] newArray(int size) {
        return new PendingIntent[size];
    }
};

public static void writePendingIntentOrNullToParcel(PendingIntent sender,
        Parcel out) {
    out.writeStrongBinder(sender != null ? sender.mTarget.asBinder()
            : null);
}

public static PendingIntent readPendingIntentOrNullFromParcel(Parcel in) {
    IBinder b = in.readStrongBinder();
    return b != null ? new PendingIntent(b) : null;
}

/*package*/ PendingIntent(IIntentSender target) {
    mTarget = target;
}

/*package*/ PendingIntent(IBinder target) {
    mTarget = IIntentSender.Stub.asInterface(target);
}

/** @hide */
public IIntentSender getTarget() {
    return mTarget;
}

}

整体来说PendingIntent的实现比较简单,主要和Android特定的的远程服务打交道(短信、通知、闹铃等),通常的应用无需使用。