極光推送能實現(xiàn);所謂的消息推送就是服務(wù)器和移動端保持連接,通過定期傳送一定的信息。比如一些關(guān)于新聞客戶端,每隔一段時間就會收到一條或者多條的信息通知,這就是從服務(wù)器推送過來的消息。
為湞江等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及湞江網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都網(wǎng)站設(shè)計、網(wǎng)站制作、湞江網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!
消息推送的好處
1、提高用戶的活躍度;消息推送是獲得用戶的關(guān)注,打開App激活使用的絕佳途徑。
2、提高用戶的留存率;就是喚醒沉睡用戶,挽留流失用戶,對于提高用戶留存率都是有重要意義。
3、帶動功能模塊使用率;用戶對新功能的點擊、發(fā)現(xiàn)率低,而消息推送正是一個引導(dǎo)用 戶關(guān)注及使用體驗的途徑。
使用消息推送系統(tǒng)推薦使用深圳極光家的系統(tǒng)。是中國領(lǐng)先的開發(fā)者服務(wù)提供商,專注于為開發(fā)者提供穩(wěn)定高效的消息推送、一鍵認(rèn)證以及流量變現(xiàn)等服務(wù),助力開發(fā)者的運營、增長與變現(xiàn)。
目前極光推送的船新版本是3.0.3,具體的集成步驟就不多說了,按照官網(wǎng)的步驟來就可以了.
之前用自定義的消息去寫,那么自己就要寫通知,當(dāng)時的思路是在自定義的消息里面去寫,這樣拓展程度高.自己定義的receiver如下:
結(jié)果到最后,感覺還是用極光的推送好一些,我在小米4的測試機(jī)上面測試自定義的消息,當(dāng)自定義的推送消息推送過來的時候,不需要點擊就執(zhí)行了這個自定義消息的點擊意圖,不知道為什么,在別的模擬器上面沒有發(fā)現(xiàn)這個問題,然后自己寫的Notification也有缺陷,懸浮式通知不能自己隱藏,而且自己寫的通知只能顯示一條,新推送的消息會覆蓋掉上一條,應(yīng)該是 mNotifyMgr.notify(buiderID,notify);的時候沒有指定不同的buiderID,可以將buiderID每次都指定不同的,這樣應(yīng)該就不會覆蓋了,但是沒有去驗證.
極光推送技術(shù)挺不錯。極光推送具有以下優(yōu)勢:
1、便捷的使用體驗
快速集成SDK,簡單易用的控制臺和API
2、靈活的目標(biāo)篩選
提供用戶自定義的標(biāo)簽和別名系統(tǒng),以及極光自己根據(jù)數(shù)據(jù)分析出的分類目標(biāo)
3、高效穩(wěn)定的系統(tǒng)
支持10億級的高并發(fā)訪問,多點備份保證系統(tǒng)穩(wěn)定
4、專業(yè)的支持
有專業(yè)的技術(shù)支持團(tuán)隊,及時響應(yīng)客戶的需求和問題
極光可定制的私有云:對于安全性要求更高,希望推送數(shù)據(jù)和系統(tǒng)存儲在自己服務(wù)器的客戶,及個性化需求需要定制開發(fā)的,性能更高要求的,或者想擁有自己推送平臺的甚至要求源碼授權(quán)二次開發(fā)的開發(fā)者,極光提供全功能的私有云解決方案。
極光推送安全包:為金融、新聞、政務(wù)及其他對推送安全要求極高的客戶提供安全嚴(yán)謹(jǐn)、穩(wěn)定可靠的信息推送解決方案。
應(yīng)用場景:在我們的項目中我們用的是創(chuàng)建視頻會議和預(yù)警消息通知推送這兩種情況,首先創(chuàng)建視頻會議和中途邀請人參加會議我采用的是自定義推送消息,因為此應(yīng)用場景傳遞的參數(shù)比較多,在推送過去之后android和ios可以很方便的將參數(shù)傳遞過去,但是我們考慮到邀請的所有人都在登錄狀態(tài)的時候才可以創(chuàng)建會議房間,我們采用的是騰訊視頻會議的sdk,因為我們采用的是別名推送,當(dāng)用戶在登錄的時候安卓端將用戶uuid設(shè)置為別名,退出時取消別名,我在服務(wù)端根據(jù)傳遞過來的uuid利用別名查詢registration_ids的數(shù)組大小是否為空判斷當(dāng)前用戶是否設(shè)置別名,當(dāng)邀請的所有人都設(shè)置了別名之后我才調(diào)用創(chuàng)建會議房間的接口。而預(yù)警消息推送我采用的是通知推送,當(dāng)氣象預(yù)警觸發(fā)的時候我會采用通知推送的方式推送給app,這種方式比較簡單。
極光推送是給app推送消息的,我們首先需要在服務(wù)端集成maven依賴
!-- 極光推送 --
groupIdcn.jpush.api
artifactIdjpush-client
version3.2.3
/dependency
接著我們需要了解極光推送有哪些推送方式,對于安卓和ios都適用的情況,我在項目中使用的是別名推送alias,(還有標(biāo)簽推送tag),推送方式又分為通知推送和自定義推送,通知推送能夠顯示在手機(jī)提示框中,而自定義推送卻不能,我看安卓他們做的能跟微信視頻一樣的彈出一個會話框,看著挺不錯的,這跟微信不同的是可以邀請多個,之前用阿里云的好像只能一對一,所以才換成騰訊視頻會議的,好了,廢話不多說,上我寫的一個工具類,
package com.jpxx.homepage.homePage.service.utils;
import cn.jpush.api.JPushClient;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Options;
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 cn.jpush.api.push.model.Message;
import cn.jpush.api.push.model.PushPayload.Builder;
public class SendMessageUtils {
private static StringAppKey="8a7880c6fb81ad494b224078";
/**
* JPush MasterSecret 極光推送平臺生成的密鑰
*/
private static StringMasterSecret="c0fc675c4c48f9bf35269cf4";
//兩個參數(shù)分別填寫你申請的masterSecret和appKey
private static JPushClientjPushClient=new JPushClient(MasterSecret,AppKey);
/**
* 通知推送
* 備注:推送方式不為空時,推送的值也不能為空;推送方式為空時,推送值不做要求
* @param type 推送方式:1、“tag”標(biāo)簽推送,2、“alias”別名推送
* @param value 推送的標(biāo)簽或別名值
* @param alert 推送的內(nèi)容
*/
public static StringpushNotice(String type,String title,String value,String alert,int roomId,String MessageType,String name,String promoterAdavter,String meetingTitle,String sig){
Builder builder= PushPayload.newBuilder();
? ? builder.setPlatform(Platform.all());//設(shè)置接受的平臺,all為所有平臺,包括安卓、ios、和微軟的
? ? //設(shè)置如果用戶不在線、離線消息保存的時間
? ? Options options=Options.sendno();
? ? options.setTimeToLive(86400l);? ? //設(shè)置為86400為保存一天,如果不設(shè)置默認(rèn)也是保存一天
? ? builder.setOptions(options);
? ? builder.setMessage(Message.newBuilder()
.setMsgContent(value)
.setTitle(title)
.addExtra("roomId",roomId)
.addExtra("MessageType",MessageType)
.addExtra("name",name)
.addExtra("promoterAdavter",promoterAdavter)
.addExtra("meetingTitle",meetingTitle)
.addExtra("userSig",sig)
.build());
? ? //設(shè)置推送方式
? ? if(type.equals("alias")){
builder.setAudience(Audience.alias(value));//根據(jù)別名推送
? ? }else if(type.equals("tag")){
builder.setAudience(Audience.tag(value));//根據(jù)標(biāo)簽推送
? ? }else{
builder.setAudience(Audience.all());//Audience設(shè)置為all,說明采用廣播方式推送,所有用戶都可以接收到
? ? }
//設(shè)置為采用通知的方式發(fā)送消息
? ? builder.setNotification(Notification.alert(alert));
? ? PushPayload pushPayload=builder.build();
? ? System.out.println("ggggggg"+pushPayload);
? ? try{
//進(jìn)行推送,實際推送就在這一步
? ? ? ? //System.out.println("zzzzzzzzz "+jPushClient.sendPush(pushPayload));
? ? ? ? PushResult pushResult=jPushClient.sendPush(pushPayload);
? ? ? ? return "success";
? ? }catch(Exception e){
System.out.println("異常 "+e);
? ? ? ? e.printStackTrace();
? ? ? ? return "fail";
? ? }
}
/**
* 自定義消息推送
* 備注:推送方式不為空時,推送的值也不能為空;推送方式為空時,推送值不做要求
* @param type 推送方式:1、“tag”標(biāo)簽推送,2、“alias”別名推送
* @param value 推送的標(biāo)簽或別名值
* @param alert 推送的內(nèi)容
*/
public static StringpushMsg(String type,String title,String value,String alert,int roomId,String MessageType,String name,String promoterAdavter,String meetingTitle,String sig){
Builder builder= PushPayload.newBuilder();
? ? builder.setPlatform(Platform.all());//設(shè)置接受的平臺
? ? if(type.equals("alias")){
builder.setAudience(Audience.alias(value));//別名推送
? ? }else if(type.equals("tag")){
builder.setAudience(Audience.tag(value));//標(biāo)簽推送
? ? }else{
builder.setAudience(Audience.all());//Audience設(shè)置為all,說明采用廣播方式推送,所有用戶都可以接收到
? ? }
Message.Builder newBuilder=Message.newBuilder();
? ? newBuilder.setMsgContent(alert);//消息內(nèi)容
? ? newBuilder.setTitle(title);
? ? newBuilder.addExtra("roomId",roomId);
? ? newBuilder.addExtra("MessageType",MessageType);
? ? newBuilder.addExtra("name",name);
? ? newBuilder.addExtra("promoterAdavter",promoterAdavter);
? ? newBuilder.addExtra("meetingTitle",meetingTitle);
? ? newBuilder.addExtra("userSig",sig);
? ? Message message=newBuilder.build();
? ? builder.setMessage(message);
? ? PushPayload pushPayload=builder.build();
? ? try{
PushResult pushResult=jPushClient.sendPush(pushPayload);
? ? ? ? System.out.println(pushResult.isResultOK());
? ? ? ? return "success";
? ? }catch(Exception e){
e.printStackTrace();
? ? ? ? return "fail";
? ? }
}
public static void main(String[] args) {
//給標(biāo)簽為kefu的用戶進(jìn)行消息推送
? ? //SendMessageUtils.pushMsg("alias","標(biāo)題","5b9022746e284ea0992e3baa983035dc","你有新的任務(wù),請及時處理",111,"meetingType","name","avater","meetingTitle","");
//sendNotificationWirhAlias_Ios("zzzzzzzzzzzz","uuid");
? ? //String result = SendMessageUtils.pushNotice("alias","標(biāo)題","5b9022746e284ea0992e3baa983035dc","你有新的任務(wù),請及時處理",111,"meetingType","name","avater","meetingTitle","");
? ? //System.out.println("返回結(jié)果"+result);
? ? /*String result = SendMessageUtils.pushNotice("alias","預(yù)警標(biāo)題","5b9022746e284ea0992e3baa983035dc","dddd",0,"warnType","","","","");? //userDto.getUuId()
System.out.println("result "+result);*/
? ? //根據(jù)uuid查詢別名信息是否存在
? ? String result = HttpRequestUtil.JGUtil("", "8a7880c6fb81ad494b224078","c0fc675c4c48f9bf35269cf4");//get請求
? ? //String result = HttpRequestUtil.interfaceUtil("", "","ydswtapp","eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJjbGllbnRJZFwiOlwieWRzd3RhcHBcIixcImxvZ2luVGltZVwiOjE1NTYwMDY1NDU4MzksXCJ1c0lkXCI6MjM5OSxcInVzZXJSb2xlXCI6XCJBRE1JTlwiLFwidXVJZFwiOlwiNDAyODgxZTUzYzdmMGRkZTAxM2M3ZjI5ZWQ4ZTAwMTZcIn0iLCJpc3MiOiJhdXRoMCIsImV4cCI6MTg3MTM2NjU0NSwiaWF0IjoxNTU2MDA2NTQ1fQ.Cy3-eDD4OEYhJlldvtJsymALRVGwP466TmBrSQJQGUo");//get請求
? ? System.out.println("result? "+result);
}
}
因為我要根據(jù)前端傳來的uuid判斷當(dāng)前用戶是否登錄,所以我對http方法進(jìn)行了稍微改裝,根據(jù)極光的api文檔(文檔寫的不是很好找),以下是我改裝的
/**
*
* 極光專用
*/
public static StringJGUtil(String path,String appKey,String masterSecret) {
String str ="";
try {
URL url =new URL(path);
? ? //打開和url之間的連接
? ? HttpURLConnection conn = (HttpURLConnection) url.openConnection();
? ? PrintWriter out =null;
? ? /**設(shè)置URLConnection的參數(shù)和普通的請求屬性****start***/
? ? String base64String=appKey+":"+masterSecret;
? ? System.out.println("拼接的 "+base64String);
? ? String str2=base64String;
? ? String encode =new BASE64Encoder().encode(str2.getBytes());
? ? System.out.println("編碼過后:"+encode);
? ? String auth ="Basic "+encode;
? ? System.out.println("最終的 "+auth);
? ? conn.setRequestProperty("Authorization", auth);
? ? conn.setRequestProperty("Content-Type", "application/json");
? ? //conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
? ? conn.setRequestProperty("accept", "*/*");
? ? conn.setRequestProperty("connection", "Keep-Alive");
? ? conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
? ? /**設(shè)置URLConnection的參數(shù)和普通的請求屬性****end***/
? ? //設(shè)置是否向httpUrlConnection輸出,設(shè)置是否從httpUrlConnection讀入,此外發(fā)送post請求必須設(shè)置這兩個
? ? //最常用的Http請求無非是get和post,get請求可以獲取靜態(tài)頁面,也可以把參數(shù)放在URL字串后面,傳遞給servlet,
? ? //post與get的 不同之處在于post的參數(shù)不是放在URL字串里面,而是放在http請求的正文內(nèi)。
? ? conn.setDoOutput(true);
? ? conn.setDoInput(true);
? ? conn.setRequestMethod("GET");//GET和POST必須全大寫
? ? /**GET方法請求*****start*/
/**
? ? * 如果只是發(fā)送GET方式請求,使用connet方法建立和遠(yuǎn)程資源之間的實際連接即可;
? ? * 如果發(fā)送POST方式的請求,需要獲取URLConnection實例對應(yīng)的輸出流來發(fā)送請求參數(shù)。
? ? * */
? ? conn.connect();
? ? /**GET方法請求*****end*/
? ? /***POST方法請求****start*/
? ? /*out = new PrintWriter(conn.getOutputStream());//獲取URLConnection對象對應(yīng)的輸出流? ? ? ? out.print(data);//發(fā)送請求參數(shù)即數(shù)據(jù)? ? ? ? out.flush();//緩沖數(shù)據(jù)*/
? ? /***POST方法請求****end*/
? ? //獲取URLConnection對象對應(yīng)的輸入流
? ? InputStream is = conn.getInputStream();
? ? //構(gòu)造一個字符流緩存
? ? BufferedReader br =new BufferedReader(new InputStreamReader(is));
? ? while ((str = br.readLine()) !=null) {
str =new String(str.getBytes(), "UTF-8");//解決中文亂碼問題
? ? ? ? System.out.println("wwwww"+str);
? ? ? ? return str;
? ? }
//關(guān)閉流
? ? is.close();
? ? //斷開連接,最好寫上,disconnect是在底層tcp socket鏈接空閑時才切斷。如果正在被其他線程使用就不切斷。
? ? //固定多線程的話,如果不disconnect,鏈接會增多,直到收發(fā)不出信息。寫上disconnect后正常一些。
? ? conn.disconnect();
? ? System.out.println("完整結(jié)束");
}catch (Exception e) {
e.printStackTrace();
}
return "success";
}
好了,以后再寫類似的就會寫了,這里附上極光文檔的鏈接
2.選擇推送服務(wù)
廠商通道在 onCreate() 中獲取 String json = getIntent().getExtras().getString("JMessageExtra");
極光通道在 receiver 中的方法 onNotifyMessageOpened() 獲取 String json = notificationMessage.notificationExtras;
1、首先在極光后臺用你的app包名創(chuàng)建應(yīng)用獲取極光的appkey和appid,然后點擊推送配置,
2、在小米開放平臺通過你的包名創(chuàng)建你app的應(yīng)用 獲取小米這里的appkey和appid
3、在極光后臺找到推送配置,把小米創(chuàng)建的appid和appkey 還有一個App Secret 填進(jìn)去然后啟用
4、在你應(yīng)用的app路徑的build.grile將極光和小米開放平臺的appid和appkey都配置進(jìn)去
我本來以為這樣就完成了,然后興沖沖的去測試推送,然后就遇到以下錯誤
xiaomi sdk appkey or appid was empty,please check your manifest config
如果你遇到這個錯誤的話,就一定記住你的appid和appkey前面一定要加上
MI-你的設(shè)備
然后我我跑起來發(fā)現(xiàn),又報了如下錯誤
register fail 22022
5、? 登錄小米開放平臺,點擊應(yīng)用服務(wù),立即體驗,然后找你的應(yīng)用,把推送服務(wù)給我開啟
然后我又運行,發(fā)現(xiàn)又報錯了
xiao mi push register failed - errorCode:66108,reason:appid does not match packagename!
最后排查發(fā)現(xiàn)小米開放平臺和極光后臺的包名不一致? 然后? 就不報錯了