天天看點

Android開發筆記(一百零四)消息推送SDK推送的內建極光推送個推

推送的內建

常用概念

推送:從伺服器把消息實時發到用戶端app上,這就是推送,推送可用于發送系統通知、發送推薦資訊、發送聊天消息等等。

别名:用于給移動裝置取個好記的名字,比如電腦有計算機名,可以把别名了解為開發者給移送裝置起的外号。不過,多個移動裝置可以起一樣的别名,這幾個裝置就會同時收到發給該别名的消息。

标記:用于給移動裝置打标簽,可以了解為分類,比如超市裡的泰國大米既可以打上“糧食制品”的标簽,也可以打上“進口商品”的标簽。伺服器可以統一給某個種類的移動裝置發送消息;如果移動裝置打上本裝置手機号碼的标簽,那麼伺服器就能該号碼的手機單獨發消息。

自定義消息:推送的消息内容一般由sdk直接展示在系統的通知欄,不過有時候我們希望由自己控制展示通知的時機,比如說要預先處理某項事務,或者說以對話框形式展現消息等等,在這些時候,自定義消息就派上用場了,app可以先接收伺服器發來的自定義消息,然後自主選擇接下來的處理邏輯。

內建步驟

推送sdk都分為用戶端與服務端兩塊,開發者在用戶端app上內建用戶端sdk,還得在伺服器的程式上內建服務端sdk。不過推送用戶端與服務端sdk并不直接通信,它們之間必須通過推送廠商的推送伺服器來中轉。下面是推送sdk內建時的資料流轉過程:

1、內建了用戶端sdk的app啟動之後,要先進行初始化(注冊)操作,即用戶端sdk向推送伺服器(推送廠商)發送初始化請求(包含appkey、master secret),推送伺服器給該移動裝置配置設定一個唯一辨別。

2、用戶端sdk向推送伺服器發送别名與标記設定,推送伺服器給該移動裝置登記相應的别名與标記。

3、用戶端sdk向推送伺服器發送開啟推送請求,推送伺服器表示知道了,接下來如果有消息就會告訴你。

4、服務端sdk封裝消息推送請求,包括appkey、master secret、别名、标記、推送内容等等資訊。

5、服務端sdk向推送伺服器發送消息推送請求,推送伺服器首先校驗appkey和master secret是否合法;校驗通過,再根據别名和标記挑出需要接收通知的用戶端裝置集合;最後把推送内容分别推送到符合條件的用戶端裝置上。

極光推送

極光推送是使用量較大的一個推送sdk,支援ios、android、winphone等平台。極光推送的用戶端sdk包為jpush-android-2.1.5.jar,服務端sdk包為jpush-client-3.2.9.jar,服務端的sdk還依賴于gson、slf4j、log4j等jar包。

推送調用的接口

在APP上啟用極光推送,用到的是JPushInterface類,下面是JPushInterface的常用方法說明:

init : 初始化。可在MainApplication或者MainActivity中調用。

stopPush : 暫停接收通知。

resumePush : 恢複接收通知。

isPushStopped : 判斷推送是否停止

getRegistrationID : 擷取注冊id。

setAliasAndTags : 設定本裝置的别名與标記。如果伺服器指定向某個手機号碼推送消息,則app調用該方法把手機号碼設定為别名或标記。

setAlias : 設定别名。

setTags : 設定标記。

clearAllNotifications : 清除所有通知。

setPushNotificationBuilder : 設定通知欄樣式。類型為1表示使用基本樣式,為2表示使用自定義樣式。

setPushTime : 設定接收通知的時間段。可設定周一到周日,每天的起始時間與結束時間。

推送事件的廣播

極光推送的各事件都是靠廣播發出來,并不使用監聽器,是以我們要在app中自定義廣播接收器來處理事件。下面是極光推送幾個常用的事件介紹:

1、JPushInterface.ACTION_REGISTRATION_ID

表示注冊SDK的事件,對應的intent-filter是<action android:name="cn.jpush.android.intent.REGISTRATION" />

2、JPushInterface.ACTION_MESSAGE_RECEIVED

表示接收自定義消息的事件,對應的intent-filter是<action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" />

3、JPushInterface.ACTION_NOTIFICATION_RECEIVED

表示接收通知的事件,對應的intent-filter是<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" />

4、JPushInterface.ACTION_NOTIFICATION_OPENED

表示點選通知欄的事件,對應的intent-filter是<action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" />

5、JPushInterface.ACTION_RICHPUSH_CALLBACK

表示接收富文本(如網頁、多媒體等等)回調的事件,對應的intent-filter是<action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" />

6、JPushInterface.ACTION_CONNECTION_CHANGE

表示網絡連接配接變化(連上、斷開)的事件,對應的intent-filter是<action android:name="cn.jpush.android.intent.CONNECTION" />

下面是在AndroidManifest.xml注冊極光廣播接收器的xml例子:

<receiver
        android:name=".JpushReceiver"
        android:exported="false"
        android:enabled="true">
        <intent-filter>
            <action android:name="cn.jpush.android.intent.REGISTRATION" />
            <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" />
            <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" />
            <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" />
            <action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" />
            <action android:name="cn.jpush.android.intent.CONNECTION" />
            <category android:name="com.example.exmpushjpush" />
        </intent-filter>
    </receiver>           

複制

伺服器發送通知

APP代碼實作了用戶端接收推送的功能,接下來還得伺服器配合,伺服器的程式發出推送消息,用戶端app接收消息。

下面是伺服器發送消息的具體步驟:

1、構造一個JPushClient對象,該對象包含以下資訊:AppKey、Master Secret、重試次數與逾時時間等參數。

2、按照參數分别生成Platform平台對象、Audience閱聽人對象、Notification通知對象、Message自定義消息對象。

3、根據第二步産生的各對象,建構PushPayload對象。

4、調用JPushClient對象的sendPush方法,把PushPayload對象資訊發送出去。

5、sendPush方法調用失敗則抛出異常,調用成功則傳回PushResult結果對象,裡面包含本次發送的消息編号。

上面步驟三的PushPayload對象是整個發送過程的關鍵,該對象的建構采用建造者模式,由PushPayload.Builder對各參數進行設定,說明如下:

setPlatform : 設定消息接收平台。主要有三種類型,分别是:Platform.ios()、Platform.android()、Platform.winphone()。

setAudience : 設定消息接受群體。主要有三種閱聽人,Audience.all()表示所有使用者,Audience.alias(alias)表示指定别名的使用者,Audience.tag(tag)表示指定标記的使用者。

setNotification : 設定通知内容。根據不同平台有三種設定方法,分别是:Notification.ios、Notification.android、Notification.winphone。

setMessage : 設定自定義消息。注意,隻有android和winphone可以設定自定義消息,ios隻能設定通知。

build : 根據設定内容建構PushPayload對象。

下面是伺服器發送通知的代碼示例:

import cn.jpush.api.JPushClient;
import cn.jpush.api.common.ClientConfig;
import cn.jpush.api.common.resp.APIConnectionException;
import cn.jpush.api.common.resp.APIRequestException;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Message;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.notification.Notification;
import java.util.Map;
import java.util.Set;

public class MessagePush {
	public static long IOS = 0L;
	public static long Android = 1L;

	private String mTitle;
	private String mMessage;
	private long mPlatformType;
	
	private JPushClient mJpushClient;
	private Platform mPlatform;
	private Audience mAudience;
	private Notification mNotify;
	private Message mMsg;
	public long mMsgId;
	public String mStatus;
	public String mErrCode;
	public String mErrMsg;

	public MessagePush(String appKey, String masterSecret, String message) {
		ClientConfig conf = ClientConfig.getInstance();
		conf.setMaxRetryTimes(3);
		mJpushClient = new JPushClient(masterSecret, appKey, null, conf);

		mMessage = message;
		mTitle = "";
		mPlatform = Platform.all();
		mMsg = Message.content(message);
		mAudience = Audience.all();
		setMsg(-1L, 0, 0, "");
	}

	public MessagePush(String appKey, String masterSecret, String message, String title) {
		this(appKey, masterSecret, message);
		mTitle = title;
	}

	public MessagePush(String appKey, String masterSecret, String message,
			String title, Long platformType, Map<String, String> extras) {
		this(appKey, masterSecret, message, title);
		mPlatformType = platformType.longValue();
		System.out.println("MessagePush platformType=" + platformType);
		if (platformType.longValue() == IOS) {
			mPlatform = Platform.ios();
			mNotify = Notification.ios(mMessage, extras);
		} else if (platformType.longValue() == Android) {
			mPlatform = Platform.android();
			mNotify = Notification.android(mMessage, mTitle, extras);
		} else {
			mPlatform = Platform.winphone();
			mNotify = Notification.winphone(mMessage, extras);
		}
	}

	public void setAlias(Set<String> alias) {
		mAudience = Audience.alias(alias);
	}

	public void setTag(String[] tag) {
		mAudience = Audience.tag(tag);
	}

	public void sendPush() {
		PushPayload payload = build();
		try {
			PushResult result = mJpushClient.sendPush(payload);
			mMsgId = result.msg_id;
			System.out.println("Got result - " + result);
		} catch (APIConnectionException e) {
			System.out.println("Connection error. Should retry later. "
					+ e.getMessage());
			setMsg(-1L, -1, -1, e.getMessage());
		} catch (APIRequestException e) {
			System.out.println("HTTP Status: " + e.getStatus());
			System.out.println("Error Code: " + e.getErrorCode());
			System.out.println("Error Message: " + e.getErrorMessage());
			System.out.println("Msg ID: " + e.getMsgId());
			setMsg(e.getMsgId(), e.getStatus(), e.getErrorCode(),
					e.getErrorMessage());
		}
	}

	private void setMsg(long msgId, int status, int errCode, String errMsg) {
		mMsgId = msgId;
		mStatus = String.valueOf(status);
		mErrCode = String.valueOf(errCode);
		mErrMsg = errMsg;
	}

	private PushPayload build() {
		System.out.println("build platformType=" + mPlatformType);
		PushPayload push;
		if (mPlatformType == IOS) {
			push = PushPayload.newBuilder().setPlatform(mPlatform)
					.setAudience(mAudience).setNotification(mNotify)
					.build();
		} else if (mPlatformType == Android) {
			push = PushPayload.newBuilder().setPlatform(mPlatform)
					.setAudience(mAudience).setMessage(mMsg).build();
					//.setAudience(mAudience).setNotification(mNotify).build();
		} else {
			push = PushPayload.newBuilder().setPlatform(mPlatform)
					.setAudience(mAudience).setMessage(mMsg).build();
		}
		return push;
	}
}           

複制

個推

個推是另一個使用較多的推送sdk,它支援ios和android,但不支援winphone,不過伺服器除了java,還支援PHP、Python、C++、C#等等。個推的用戶端sdk包為GetuiSDK2.8.1.0.jar和GetuiExt-2.0.3.jar,服務端sdk包為gexin-rp-sdk-base-4.0.0.7.jar、gexin-rp-sdk-http-4.0.1.2.jar和gexin-rp-sdk-template-4.0.0.4.jar,服務端的sdk還依賴于commons、jackson、protobuf等jar包。

推送調用的接口

在APP上啟用個推,用到的是PushManager類,下面是PushManager的常用方法說明:

getInstance : 獲得PushManager的單例。

initialize : 初始化。

turnOnPush : 開啟推送。

turnOffPush : 關閉推送。

isPushTurnedOn : 判斷推送是否開啟。

getClientid : 擷取用戶端id。

setTag : 設定标簽。

bindAlias : 綁定别名。

unBindAlias : 解綁别名。

setSilentTime : 設定靜默時間段。即從幾點到幾點不接收通知。

推送事件的廣播

個推也使用廣播來發送事件,不過不像極光那樣細分了許多事件,也需要自定義廣播接收器。下面是個推幾個常用的事件介紹:

事件類型根據bundle.getInt(PushConsts.CMD_ACTION)來區分

1、PushConsts.GET_CLIENTID : 獲得用戶端id。其實就是注冊,相當于極光的JPushInterface.ACTION_REGISTRATION_ID

2、PushConsts.GET_MSG_DATA : 收到自定義消息。相當于極光的JPushInterface.ACTION_MESSAGE_RECEIVED

下面是在AndroidManifest.xml注冊個推廣播接收器的xml例子:

<receiver
            android:name=".GexinReceiver"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.igexin.sdk.action.應用配置設定的AppID值" />
            </intent-filter>
        </receiver>           

複制

伺服器發送通知

下面是伺服器發送消息的具體步驟:

1、構造IGtPush對象,該對象包含以下資訊:個推伺服器位址、AppKey、Master Secret。

2、按照參數分别生成Template模闆對象、AppConditions條件對象、AppID隊列等等。

3、根據第二步産生的各對象,建構AppMessage對象。

4、調用IGtPush對象的pushMessageToApp方法,把AppMessage對象資訊發送出去。

5、pushMessageToApp方法調用失敗則抛出異常,調用成功則傳回IPushResult結果對象,裡面包含本次發送的結果資訊。

上面步驟三的AppMessage對象是整個發送過程的關鍵,該對象的常用方法說明如下:

setAppIdList : 設定AppID隊列。即往綁定哪些AppID的使用者發送消息。

setConditions : 設定條件資訊。包括手機類型、區域、标簽等等。

setData : 設定模闆資料。模闆Template定義了消息的具體樣式,下面是個推包裝好的幾個常用模闆:

--NotificationTemplate : 通知模闆。自動在通知欄裡顯示消息,點選後跳到app首頁。該模闆相當于極光的Notification。

--TransmissionTemplate : 透傳模闆。不會自動展示通知欄,由開發者在廣播接收器的PushConsts.GET_MSG_DATA分支中自行處理。該模闆相當于極光的Message。

--LinkTemplate : 連結模闆。自動在通知欄裡顯示消息,點選後跳轉到指定URL。

--NotyPopLoadTemplate : 下載下傳提示模闆。自動在通知欄裡顯示消息,點選後下載下傳指定安裝包。

下面是伺服器發送通知的代碼示例:

import java.util.ArrayList;
import java.util.List;

import com.gexin.rp.sdk.base.IPushResult;
import com.gexin.rp.sdk.base.impl.AppMessage;
import com.gexin.rp.sdk.base.uitls.AppConditions;
import com.gexin.rp.sdk.http.IGtPush;
import com.gexin.rp.sdk.template.NotificationTemplate;

public class PushtoAppNotify {
    //采用"Java SDK 快速入門", "第二步 擷取通路憑證 "中獲得的應用配置,使用者可以自行替換
	private static String appId = "FJ9uNM6WkS8laiS3C05W9";
    private static String appKey = "cpV7gRK6IlAo26aDZGMtI1";
    private static String masterSecret = "QSvOwGnx0E9jEMpiXtqJ39";
	static String host = "http://sdk.open.api.igexin.com/apiex.htm";

    public static void main(String[] args) throws Exception {

        IGtPush push = new IGtPush(host, appKey, masterSecret);

        NotificationTemplate template = NotificationTemplateDemo();
        AppMessage message = new AppMessage();
        message.setData(template);

        message.setOffline(true);
        //離線有效時間,機關為毫秒,可選
        message.setOfflineExpireTime(24 * 1000 * 3600);
        //推送給App的目标使用者需要滿足的條件
        AppConditions cdt = new AppConditions(); 
        List<String> appIdList = new ArrayList<String>();
        appIdList.add(appId);
        message.setAppIdList(appIdList);
        //手機類型
        List<String> phoneTypeList = new ArrayList<String>();
        //省份
        List<String> provinceList = new ArrayList<String>();
        //自定義tag
        List<String> tagList = new ArrayList<String>();

        cdt.addCondition(AppConditions.PHONE_TYPE, phoneTypeList);
        cdt.addCondition(AppConditions.REGION, provinceList);
        cdt.addCondition(AppConditions.TAG,tagList);
        message.setConditions(cdt); 

        IPushResult ret = push.pushMessageToApp(message,"任務别名_toApp");
        System.out.println(ret.getResponse().toString());
    }

    public static NotificationTemplate NotificationTemplateDemo() throws Exception {
        NotificationTemplate template = new NotificationTemplate();
        template.setAppId(appId);
        template.setAppkey(appKey);
        template.setTitle("PushtoAppNotify标題");
        template.setText("PushtoAppNotify内容");
        template.setLogo("icon.png");
        template.setLogoUrl("");
        template.setIsRing(true);
        template.setIsVibrate(true);
        template.setIsClearable(true);
	    // 透傳消息設定,1為強制啟動應用,用戶端接收到消息後就會立即啟動應用;2為等待應用啟動
	    template.setTransmissionType(1);
	    template.setTransmissionContent("PushtoAppNotify請輸入您要透傳的内容");

        return template;
    }
    
    public static class NotificationTemplateDemo {

    	public static NotificationTemplate notificationTemplateDemo(String appId, String appkey) {
    	    NotificationTemplate template = new NotificationTemplate();
    	    // 設定APPID與APPKEY
    	    template.setAppId(appId);
    	    template.setAppkey(appkey);
    	    // 設定通知欄标題與内容
    	    template.setTitle("請輸入通知欄标題");
    	    template.setText("請輸入通知欄内容");
    	    // 配置通知欄圖示
    	    template.setLogo("icon.png");
    	    // 配置通知欄網絡圖示
    	    template.setLogoUrl("");
    	    // 設定通知是否響鈴,震動,或者可清除
    	    template.setIsRing(true);
    	    template.setIsVibrate(true);
    	    template.setIsClearable(true);
    	    // 透傳消息設定,1為強制啟動應用,用戶端接收到消息後就會立即啟動應用;2為等待應用啟動
    	    template.setTransmissionType(1);
    	    template.setTransmissionContent("請輸入您要透傳的内容");
    	    // 設定定時展示時間
    	    // template.setDuration("2015-01-16 11:40:00", "2015-01-16 12:24:00");
    	    return template;
    	}
    	
    }

}           

複制

點此檢視Android開發筆記的完整目錄