寫這文章之前妄痪,先介紹一下Android與IOS推送的區(qū)別
Android
APP未運(yùn)行,不可以接收到通知。
APP已運(yùn)行,放置在后臺(tái)欣簇,可以接收到通知。
APP已運(yùn)行安吁,正在前臺(tái)使用醉蚁,可以接收到通知。
結(jié)束APP進(jìn)程鬼店,不可以接收到通知网棍。
IOS
APP未運(yùn)行,可以接收到通知妇智。
APP已運(yùn)行滥玷,放置在后臺(tái)氏身,可以接收到通知。
APP已運(yùn)行惑畴,正在前臺(tái)使用蛋欣,不可以接收到通知。
通過上面的對比我們很明顯看到IOS的推送做得比較好如贷,尤其在安卓6.0+各種權(quán)限下陷虎,經(jīng)常出現(xiàn)推送不到或者推送延遲的情況。有一些公司使用自己平臺(tái)的推送框架杠袱,如果是做自己公司的推送框架选泻,需要注意一下以下幾點(diǎn):
1.采用什么協(xié)議森缠?目前常用就是XMPP以及MQTT或者自定義的二進(jìn)制協(xié)議吓坚。
2.推送的內(nèi)容瞧栗?(單純的存文本還是圖文或者是包含語言?)
3.長連接的蔽坪活問題庄萎。
4.數(shù)據(jù)的加密解密
5.傳輸過程數(shù)據(jù)是否會(huì)丟失?或者客戶端網(wǎng)絡(luò)請求不穩(wěn)定如何處理塘安?
常用的一些第三方推送平臺(tái)
融云
小米推送(MiPush)
華為推送(華為Push)
友盟推送(U-Push)
個(gè)推
極光推送
阿里云移動(dòng)推送(Alibaba Cloud Channel Service)
騰訊信鴿推送
百度云推送
Bmob云推送
平臺(tái)那么多我們該選哪家糠涛?
上面的推送,大致分為手機(jī)廠商推送耙旦、平臺(tái)推送脱羡、第三方推送。
手機(jī)廠商推送:
他們的推送服務(wù)在他們自己生產(chǎn)的手機(jī)上屬于系統(tǒng)級(jí)別的服務(wù)免都,手機(jī)系統(tǒng)對他們自家的推送限制最小。如小米手機(jī)上帆竹,不在系統(tǒng)自啟動(dòng)名單里的App绕娘,在手機(jī)重啟后,App聲明的后臺(tái)Service并不會(huì)自動(dòng)運(yùn)行栽连。但是险领,小米推送作為手機(jī)系統(tǒng)級(jí)服務(wù),仍然是可以收到推送的秒紧。又如華為绢陌,內(nèi)部團(tuán)隊(duì)放話:華為Push,在華為手機(jī)上是系統(tǒng)級(jí)別的服務(wù)熔恢,穩(wěn)定性等各方面肯定都會(huì)好些脐湾。
第三方平臺(tái)推送:
第三方平臺(tái)推送主要看平臺(tái)的規(guī)模,例如百度推送叙淌,用百度推送的公司多了秤掌,就算你APP在后臺(tái)愁铺,依然可以收到推送。至于用哪種推送好闻鉴,就看你們自己了茵乱,小編我就只用過兩種推送:百度推送和極光推送,感覺也能滿足公司的要求了孟岛。寫這篇文章的時(shí)候用的是:Baidu-Push-SDK-Android-L2-5.6.0.30瓶竭。
幾個(gè)新聞端的推送
2016.12.31的版本。
友盟推送(今日頭條渠羞、央視新聞在验、一點(diǎn)資訊、ZAKER新聞)
個(gè)推推送(新浪新聞堵未、網(wǎng)易新聞)
百度推送 (百度新聞)
信鴿推送的(掌上英雄聯(lián)盟腋舌、歡樂斗地主 )
關(guān)于推送的一些細(xì)節(jié)問題
1、如果主應(yīng)用已經(jīng)被殺死并且不存在任何Activity后就無法跳到用戶指定面板渗蟹;
2块饺、只有在主應(yīng)用未被殺死的情況下可以跳到用戶上次依然打開的面板;
3雌芽、如果主應(yīng)用被殺死后點(diǎn)擊通知欄依然可以重新啟動(dòng)主應(yīng)用效果授艰;
4、從推送平臺(tái)的Service外部進(jìn)程打開Activity必須指定FLAG_ACTIVITY_NEW_TASK標(biāo)記世落;
1.百度推送收到推送后點(diǎn)開通知欄會(huì)重新打開APP
勾選自定義行為淮腾,并添加<action android:name="com.baidu.android.pushservice.action.notification.CLICK" />
2.百度云推送點(diǎn)擊通知后進(jìn)入不了想要的頁面
此問題跟上一個(gè)問題一樣,是因?yàn)闆]有配置好百度推送的高級(jí)設(shè)置屉佳。
相關(guān)DEMO代碼
1.AndroidManifest.xml的主線程需要添加android:launchMode="singleTask"
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
>
2.判斷APP進(jìn)程是否存在
/**
* 判斷應(yīng)用是否已經(jīng)啟動(dòng)
* @param context 一個(gè)context
* @param packageName 要判斷應(yīng)用的包名
* @return boolean
*/
public static boolean isAppAlive(Context context, String packageName){
ActivityManager activityManager =
(ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> processInfos
= activityManager.getRunningAppProcesses();
for(int i = 0; i < processInfos.size(); i++){
if(processInfos.get(i).processName.equals(packageName)){
//app進(jìn)程存在
return true;
}
}
//app還沒啟動(dòng)
return false;
}
3.啟動(dòng)頁
public class SplashActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
if(getIntent().getBundleExtra(Constants.EXTRA_BUNDLE) != null){
//判斷是否推送進(jìn)來的
intent.putExtra(Constants.EXTRA_BUNDLE,
getIntent().getBundleExtra(Constants.EXTRA_BUNDLE));
}
startActivity(intent);
finish();
}
}, 2000);
}
}
4.主頁
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Bundle bundle = getIntent().getBundleExtra(Constants.EXTRA_BUNDLE);
if(bundle != null){
//推送進(jìn)來 打開詳情頁
String goodsId= bundle.getString("goodsId");
Intent detialIntent = new Intent(MainActivity.this,Detial.class);
detialIntent.putExtra("goodsId",goodsId);
startActivity(detialIntent);
}
}
}
5.百度的MyPushMessageReceiver
@Override
public void onNotificationClicked(Context context, String title,
String description, String customContentString) {
// 通知點(diǎn)擊
// 自定義內(nèi)容獲取方式谷朝,mykey和myvalue對應(yīng)通知推送時(shí)自定義內(nèi)容中設(shè)置的鍵和值
if (!TextUtils.isEmpty(customContentString)) {
JSONObject customJson = null;
try {
customJson = new JSONObject(customContentString);
String goodsId = null;
//校驗(yàn)傳過來的值
if (!customJson.isNull("goodsId")) {
goodsId = customJson.getString("goodsId");
//判斷app進(jìn)程是否存活
if(UiUtils.isAppAlive(context)){
//如果存活的話,就直接啟動(dòng)DetailActivity武花,但要考慮一種情況圆凰,就是app的進(jìn)程雖然仍然在
//但Task棧已經(jīng)空了,比如用戶點(diǎn)擊Back鍵退出應(yīng)用体箕,但進(jìn)程還沒有被系統(tǒng)回收专钉,如果直接啟動(dòng)
//DetailActivity,再按Back鍵就不會(huì)返回MainActivity了。所以在啟動(dòng)
//DetailActivity前累铅,要先啟動(dòng)MainActivity跃须。
Intent mainIntent = new Intent(context, GuideActivity.class);
//將MainAtivity的launchMode設(shè)置成SingleTask, 或者在下面flag中加上Intent.FLAG_CLEAR_TOP,
//如果Task棧中有MainActivity的實(shí)例,就會(huì)把它移到棧頂娃兽,把在它之上的Activity都清理出棧菇民,
//如果Task棧不存在MainActivity實(shí)例,則在棧頂創(chuàng)建
//清除MainActivity上所有界面
//mainIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
mainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent detailIntent = new Intent(context, DetialActivity.class);
detailIntent.putExtra("goodsId", "goodsId");
Intent[] intents = {mainIntent, detailIntent};
context.startActivities(intents);
}else{
//如果app進(jìn)程已經(jīng)被殺死,先重新啟動(dòng)app玉雾,將DetailActivity的啟動(dòng)參數(shù)傳入Intent中翔试,參數(shù)經(jīng)過
//SplashActivity傳入MainActivity,此時(shí)app的初始化已經(jīng)完成复旬,在MainActivity中就可以根據(jù)傳入 //參數(shù)跳轉(zhuǎn)到DetailActivity中去了
Intent launchIntent = context.getPackageManager().
getLaunchIntentForPackage("包名");
launchIntent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Bundle args = new Bundle();
args.putString("goodsId", "goodsId");
launchIntent.putExtra(Constants.EXTRA_BUNDLE, args);
context.startActivity(launchIntent);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
另外垦缅,小米華為手機(jī)可能要另外配置:要去小米華為官網(wǎng)搞配置問題。建議是用融云推送驹碍。