推送的內建
常用概念
推送:從伺服器把消息實時發到用戶端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開發筆記的完整目錄