三分鐘幫你集成極光推送——和那些你可能不知道的事

本文簡介:本文前篇,能夠幫助朋友們快速集成極光推送。本文後篇,是我本身項目實踐的一些總結和心得,應該對讀者們仍是頗有參考價值的,相信讀完這篇文章,你會對極光推送有更加深刻的理解,而不只僅只是會集成而已。總之呢,集成第三方SDK,都不是很難的事情,仔細閱讀文檔,一步步來,遇到Bug,慢慢解決就行,實在解決不了,能夠問問客服小哥哥或者小姐姐,重要的是,你得有着解決它的決心和耐心。html

《一》JPush SDK的集成

簡要介紹: 極光推送(JPush)是一個端到端的推送服務,使得服務器端消息可以及時地推送到終端用戶手機上,讓開發者積極地保持與用戶的鏈接,從而提升用戶活躍度、提升應用的留存率。

開發者集成 JPush Android SDK 到其應用裏,JPush Android SDK 建立到 JPush Cloud 的長鏈接,爲 App 提供永遠在線的能力。 當開發者想要及時地推送消息到達 App 時,只須要調用 JPush API 推送,或者使用其餘方便的智能推送工具,便可輕鬆與用戶交流。 JPush Android SDK 是做爲 Android Service 長期運行在後臺的,從而建立並保持長鏈接,保持永遠在線的能力。前端

假設你已經註冊了極光的帳號,登陸進來了。點擊當即體驗,建立本身的應用。 android

image.png

image.png
App端集成須要用到的AppKey。
image.png

添加集成代碼,此處使用jcenter的方式集成。 1、確認android studio的 Project 根目錄的主 gradle 中配置了jcenter支持。(新建project默認配置就支持)編程

buildscript {
    repositories {
        jcenter()
    }
    ......
}

allprojets {
    repositories {
        jcenter()
    }
}
複製代碼

2、在 module 的 gradle 中添加依賴和AndroidManifest的替換變量。json

android {
    ......
    defaultConfig {
        applicationId "com.xxx.xxx" //JPush上註冊的包名.
        ......

        ndk {
            //選擇要添加的對應cpu類型的.so庫。
            abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a'
            // 還能夠添加 'x86', 'x86_64', 'mips', 'mips64'
        }

        manifestPlaceholders = [
            JPUSH_PKGNAME : applicationId,
            JPUSH_APPKEY : "你的appkey", //JPush上註冊的包名對應的appkey.
            JPUSH_CHANNEL : "developer-default", //暫時填寫默認值便可.
        ]
        ......
    }
    ......
}

dependencies {
    ......

    compile 'cn.jiguang.sdk:jpush:3.1.1'  // 此處以JPush 3.1.1 版本爲例。
    compile 'cn.jiguang.sdk:jcore:1.1.9'  // 此處以JCore 1.1.9 版本爲例。
    ......
}
複製代碼

3、AndroidManifest.xml中添加後端

<!--Jpush配置 所需權限start-->
    <!-- Required -->
    <permission
        android:name="你的應用包名.permission.JPUSH_MESSAGE"
        android:protectionLevel="signature" />

    <!-- Required  一些系統要求的權限,如訪問網絡等-->
    <uses-permission android:name="你的應用包名.permission.JPUSH_MESSAGE" />
    <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
    <!--<uses-permission android:name="android.permission.INTERNET" />-->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <!--<uses-permission android:name="android.permission.READ_PHONE_STATE" />-->
    <!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />-->
    <!--<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />-->
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <!--<uses-permission android:name="android.permission.VIBRATE" />-->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <!--<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />-->
    <!--<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />-->

    <!-- Optional for location -->
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 用於開啓 debug 版本的應用在6.0 系統上 層疊窗口權限 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!--<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />-->
    <!--<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />-->
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
    <!--<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />-->
    <!--<uses-permission android:name="android.permission.GET_TASKS" />-->
    <!--Jpush配置 所需權限end-->

    <!--Jpush配置 start-->
    <application
        <!-- Rich push 核心功能 since 2.0.6-->
        <activity
            android:name="cn.jpush.android.ui.PopWinActivity"
            android:theme="@style/MyDialogStyle"
            android:exported="false">
        </activity>

        <!-- Required SDK核心功能-->
        <activity
            android:name="cn.jpush.android.ui.PushActivity"
            android:configChanges="orientation|keyboardHidden"
            android:theme="@android:style/Theme.NoTitleBar"
            android:exported="false">
            <intent-filter>
                <action android:name="cn.jpush.android.ui.PushActivity" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="你的應用包名" />
            </intent-filter>
        </activity>

        <!-- Required SDK 核心功能-->
        <!-- 可配置android:process參數將PushService放在其餘進程中 -->
        <service
            android:name="cn.jpush.android.service.PushService"
            android:enabled="true"
            android:exported="false">
            <intent-filter>
                <action android:name="cn.jpush.android.intent.REGISTER" />
                <action android:name="cn.jpush.android.intent.REPORT" />
                <action android:name="cn.jpush.android.intent.PushService" />
                <action android:name="cn.jpush.android.intent.PUSH_TIME" />
            </intent-filter>
        </service>
        <!-- since 3.0.9 Required SDK 核心功能-->
        <provider
            android:authorities="你的應用包名.DataProvider"
            android:name="cn.jpush.android.service.DataProvider"
            android:exported="false"
            />

        <!-- since 1.8.0 option 可選項。用於同一設備中不一樣應用的JPush服務相互拉起的功能。 -->
        <!-- 若不啓用該功能可刪除該組件,將不拉起其餘應用也不能被其餘應用拉起 -->
        <service
            android:name="cn.jpush.android.service.DaemonService"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="cn.jpush.android.intent.DaemonService" />
                <category android:name="你的應用包名" />
            </intent-filter>

        </service>
        <!-- since 3.1.0 Required SDK 核心功能-->
        <provider
            android:authorities="你的應用包名.DownloadProvider"
            android:name="cn.jpush.android.service.DownloadProvider"
            android:exported="true"
            />
        <!-- Required SDK核心功能-->
        <receiver
            android:name="cn.jpush.android.service.PushReceiver"
            android:enabled="true"
            android:exported="false">
            <intent-filter android:priority="1000">
                <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" />   <!--Required  顯示通知欄 -->
                <category android:name="你的應用包名" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.USER_PRESENT" />
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
            <!-- Optional -->
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_ADDED" />
                <action android:name="android.intent.action.PACKAGE_REMOVED" />

                <data android:scheme="package" />
            </intent-filter>
        </receiver>

        <!-- Required SDK核心功能-->
        <receiver android:name="cn.jpush.android.service.AlarmReceiver" android:exported="false"/>

        <!-- User defined.  For test only  MyReceiver爲用戶自定義的廣播接收器-->
        <receiver
            android:name=".util.MyReceiver"
            android:exported="false"
            android:enabled="true">
            <intent-filter>
                <action android:name="cn.jpush.android.intent.REGISTRATION" /> <!--Required  用戶註冊SDK的intent-->
                <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!--Required  用戶接收SDK消息的intent-->
                <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!--Required  用戶接收SDK通知欄信息的intent-->
                <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!--Required  用戶打開自定義通知欄的intent-->
                <action android:name="cn.jpush.android.intent.CONNECTION" /><!-- 接收網絡變化 鏈接/斷開 since 1.6.3 -->
                <category android:name="你的應用包名" />
            </intent-filter>
        </receiver>

        <!-- Required  . Enable it you can get statistics data with channel -->
        <meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/>
        <meta-data android:name="JPUSH_APPKEY" android:value="應用的Appkey" /> <!--  </>值來自開發者平臺取得的AppKey-->
    </application>
        <!--Jpush配置 end-->

複製代碼

4、自定義一個廣播接收器MyReceiver(此處直接使用官方Demo中的MyReceiver)api

/**
 * 自定義接收器
 * 
 * 若是不定義這個 Receiver,則:
 * 1) 默認用戶會打開主界面
 * 2) 接收不到自定義消息
 */
public class MyReceiver extends BroadcastReceiver {
	private static final String TAG = "JIGUANG-Example";

	@Override
	public void onReceive(Context context, Intent intent) {
		try {
			Bundle bundle = intent.getExtras();
			Logger.d(TAG, "[MyReceiver] onReceive - " + intent.getAction() + ", extras: " + printBundle(bundle));

			if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) {
				String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID);
				Logger.d(TAG, "[MyReceiver] 接收Registration Id : " + regId);
				//send the Registration Id to your server...

			} else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
				Logger.d(TAG, "[MyReceiver] 接收到推送下來的自定義消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE));
				processCustomMessage(context, bundle);

			} else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) {
				Logger.d(TAG, "[MyReceiver] 接收到推送下來的通知");
				int notifactionId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID);
				Logger.d(TAG, "[MyReceiver] 接收到推送下來的通知的ID: " + notifactionId);

			} else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {
				Logger.d(TAG, "[MyReceiver] 用戶點擊打開了通知");

				//打開自定義的Activity
				Intent i = new Intent(context, TestActivity.class);
				i.putExtras(bundle);
				//i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP );
				context.startActivity(i);

			} else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(intent.getAction())) {
				Logger.d(TAG, "[MyReceiver] 用戶收到到RICH PUSH CALLBACK: " + bundle.getString(JPushInterface.EXTRA_EXTRA));
				//在這裏根據 JPushInterface.EXTRA_EXTRA 的內容處理代碼,好比打開新的Activity, 打開一個網頁等..

			} else if(JPushInterface.ACTION_CONNECTION_CHANGE.equals(intent.getAction())) {
				boolean connected = intent.getBooleanExtra(JPushInterface.EXTRA_CONNECTION_CHANGE, false);
				Logger.w(TAG, "[MyReceiver]" + intent.getAction() +" connected state change to "+connected);
			} else {
				Logger.d(TAG, "[MyReceiver] Unhandled intent - " + intent.getAction());
			}
		} catch (Exception e){

		}

	}

	// 打印全部的 intent extra 數據
	private static String printBundle(Bundle bundle) {
		StringBuilder sb = new StringBuilder();
		for (String key : bundle.keySet()) {
			if (key.equals(JPushInterface.EXTRA_NOTIFICATION_ID)) {
				sb.append("\nkey:" + key + ", value:" + bundle.getInt(key));
			}else if(key.equals(JPushInterface.EXTRA_CONNECTION_CHANGE)){
				sb.append("\nkey:" + key + ", value:" + bundle.getBoolean(key));
			} else if (key.equals(JPushInterface.EXTRA_EXTRA)) {
				if (TextUtils.isEmpty(bundle.getString(JPushInterface.EXTRA_EXTRA))) {
					Logger.i(TAG, "This message has no Extra data");
					continue;
				}

				try {
					JSONObject json = new JSONObject(bundle.getString(JPushInterface.EXTRA_EXTRA));
					Iterator<String> it =  json.keys();

					while (it.hasNext()) {
						String myKey = it.next();
						sb.append("\nkey:" + key + ", value: [" +
								myKey + " - " +json.optString(myKey) + "]");
					}
				} catch (JSONException e) {
					Logger.e(TAG, "Get message extra JSON error!");
				}

			} else {
				sb.append("\nkey:" + key + ", value:" + bundle.getString(key));
			}
		}
		return sb.toString();
	}
	
	//send msg to MainActivity
	private void processCustomMessage(Context context, Bundle bundle) {
		if (MainActivity.isForeground) {
			String message = bundle.getString(JPushInterface.EXTRA_MESSAGE);
			String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
			Intent msgIntent = new Intent(MainActivity.MESSAGE_RECEIVED_ACTION);
			msgIntent.putExtra(MainActivity.KEY_MESSAGE, message);
			if (!ExampleUtil.isEmpty(extras)) {
				try {
					JSONObject extraJson = new JSONObject(extras);
					if (extraJson.length() > 0) {
						msgIntent.putExtra(MainActivity.KEY_EXTRAS, extras);
					}
				} catch (JSONException e) {

				}

			}
			LocalBroadcastManager.getInstance(context).sendBroadcast(msgIntent);
		}
	}
}

複製代碼

5、在Application中的onCreate()方法中初始化極光推送bash

// 初始化 JPush
        JPushInterface.init(this);
        //發佈時關閉日誌
        JPushInterface.setDebugMode(false);
複製代碼

6、最後不要忘了添加混淆代碼哦!服務器

請在工程的混淆文件proguard-rules.pro中添加如下配置:
-dontoptimize
-dontpreverify

-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
-keep class * extends cn.jpush.android.helpers.JPushMessageReceiver { *; }

-dontwarn cn.jiguang.**
-keep class cn.jiguang.** { *; }
複製代碼

7、經過極光官網控制檯推送,測試推送結果。 網絡

image.png

《二》推送方式分析

使用場景分析:推送消息,無疑就是兩種情形,一種是所有推送,這種方式簡單,羣發就好了,Portal與API都支持向指定的 appKey 羣發消息。可是通常實際的業務需求,都不只僅是羣發,還須要針對某一我的或者某一羣人進行推送。例如:給會員推送一些新的內容,此時就須要針對會員這一羣特定的人,來進行推送。簡單的說,就是須要把JPush的註冊用戶與開發者App用戶綁定起來,以達到精準推送的目的。

1.RegistrationID方式實現點對點的精準推送(把綁定關係保存到開發者應用服務器中)

集成了 JPush SDK 的應用程序在第一次成功註冊到 JPush 服務器時,JPush 服務器會以廣播的形式發送RegistrationID到應用程序,給客戶端返回一個惟一的該設備的標識 - RegistrationID。首次註冊成功,自定義的MyReceiver中會收到一條廣播。

以下圖,會在MyReceiver中收到RegistrationID的值。只要極光推送第一次註冊成功了,後期不會再發 RegistrationID 的廣播了。RegistrationID 就會被保留在手機內,下次即便你是無網狀態進入APP,你也能夠獲取到這個RegistrationID。有了這個標識,App 編程能夠把這個 RegistrationID 保存到本身的應用服務器上,而後就能夠根據 RegistrationID 來向設備推送消息或者通知。因此建議能夠在你的Application和MyReceiver中都對這個RegistrationID進行賦值。而後根據項目的業務須要,將RegistrationID和用戶標識的對應關係,上傳本身的服務端。

image.png

public class MyApplication extends Application{
    public static String registrationID;
     @Override
    public void onCreate() {
        // 初始化 JPush
        JPushInterface.init(this);
        registrationID = JPushInterface.getRegistrationID(this);
        Log.d("TAG", "接收Registration Id : " + registrationID);
    }
}
複製代碼

【注意】: 若是 App 不卸載,是直接覆蓋安裝,Android, iOS 上 RegistrationID 的值都不會變化。 若是 App 是卸載以後再次安裝:Android 上 RegistrationID 基本不會變; iOS 上若是啓用了 IDFA 變化可能性不大,若是未啓用 IDFA 則每次安裝 RegistrationID 都會變; 參考:極光推送的設備惟一性標識 RegistrationID

若是使用此種推送方式,你可能會遇到的問題:假設在一個設備中登陸不一樣的帳號,那此時上傳給服務器的都是同一個RegistrationID,由於設備沒有變化。那麼可能出現:原本服務器是根據A用戶找到它的RegistrationID進行推送,可是B用戶也是在A用戶登陸的設備登陸的,RegistrationID跟A的同樣,這樣就致使B用戶收到了推送給A用戶的推送內容。

須要謹記:

使用 RegistrationID 推送的關鍵於,App 開發者須要在開發 App 時,獲取到這個 RegistrationID,保存到 App 業務服務器上去,而且與本身的用戶標識對應起來。建議 App 開發者儘量作這個保存動做。由於這是最精確地定位到設備的。(RegistrationID 的方式,相對而言比較麻煩一點,由於須要本身的App服務端維護RegistrationID和用戶的對應關係。暫時我尚未使用這種方式,真正投入到線上的項目,只是測試環境下調試過。) 值得一讀:[推送人羣的選擇 – 推送方式-技術篇](http://blog.jiguang.cn/push_audience_tech-2/)

2.別名與標籤推送(把綁定關係保存到 JPush 服務器端)

別名推送也是一種實現點對點推送的方式,用於給某特定用戶推送消息。 功能介紹: ①爲安裝了應用程序的用戶,取個別名來標識。之後給該用戶 Push 消息時,就能夠用此別名來指定。 ②每一個用戶只能指定一個別名。 ③同一個應用程序內,對不一樣的用戶,建議取不一樣的別名。這樣,儘量根據別名來惟一肯定用戶。 ④系統不限定一個別名只能指定一個用戶。若是一個別名被指定到了多個用戶,當給指定這個別名發消息時,服務器端API會同時給這多個用戶發送消息。

舉例:在一個用戶要登陸的遊戲中,可能設置別名爲 userid。遊戲運營時,發現該用戶 3 天沒有玩遊戲了,則根據 userid 調用服務器端API發通知到客戶端提醒用戶。

別名設置:

須要和本身的服務端協商好別名的規則,例以下面的代碼中,是將用戶ID經過MD5加密,做爲別名,設置保存到JPush服務器。固然你也可使用其餘的拼接規則,具體根據每一個公司的項目須要設置便可,只要知足別名的命名限制就行: 命名長度限制爲 40 字節。(判斷長度需採用UTF-8編碼)

深刻理解各類推送方式能夠參考:推送人羣的選擇 – 推送方式-技術篇

下面是一個JPush設置別名和標籤的輔助類。

public class JPushHelper {
    private String TAG = "JPushHelper";

    /**
     * 設置別名與標籤
     *
     * @param UUID
     */
    private void setAlias(String UUID) {
        if (null != UUID) {
            //恢復接收推送
            JPushInterface.resumePush(MyApplication.getInstance());
            JPushInterface.setAliasAndTags(MyApplication.getInstance(), UUID, null, mAliasCallback);
        }
    }

    public void setAlias() {
        if (MyApplication.isLogin) { //必須登陸
            UserInfo userBean = ACT_Login.getLoginUser();
            if (null != userBean) {
                 //根據具體業務需求,能夠再拼接上其餘相關字段
                //String alias = "";
                //StringBuilder stringBuffer = new StringBuilder();
                // stringBuffer.append(StringUtil.getString(userBean.user_id));
                Log.e(TAG, stringBuffer.toString());
                alias = MD5Util.string2MD5(userBean.user_id);
                //限制:alias 命名長度限制爲 40 字節。(判斷長度需採用UTF-8編碼)
                Log.e(TAG, alias);
                //setAlias("");
                setAlias(alias);
            }
        }
    }

    /**
     * 中止接收推送
     */
    public void removeAlias() {
        JPushInterface.clearAllNotifications(MyApplication.getInstance());
        //setAlias("");//該句打開的話,若是退出登陸後,用戶就收不到離線的消息了。
        JPushInterface.stopPush(MyApplication.getInstance());
    }

    private final TagAliasCallback mAliasCallback = new TagAliasCallback() {

        @Override
        public void gotResult(int code, String alias, Set<String> tags) {
            String logs;
            switch (code) {
                case 0:
    // 建議這裏往 SharePreference 裏寫一個成功設置的狀態。成功設置一次後,之後沒必要再次設置了。
                    logs = "Set tag and alias success";
                    Log.e(TAG, logs);
                    break;
                case 6002:
                    logs = "Failed to set alias and tags due to timeout. Try again after 60s.";
                    // 延遲 60 秒來調用 Handler 設置別名
                    mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SET_ALIAS, alias), 1000 * 6);
                    Log.e(TAG, logs + AppDateUtil.getTimeStamp(System.currentTimeMillis(), AppDateUtil.MM_DD_HH_MM_SS));
                    break;
                default:
                    logs = "Failed with errorCode = " + code;
                    Log.e(TAG, logs);
            }

        }

    };

    private static final int MSG_SET_ALIAS = 1001;
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(android.os.Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MSG_SET_ALIAS:
                    Log.e(TAG, "Set alias in handler." + ((String) msg.obj));
                    // 調用 JPush 接口來設置別名。
                    JPushInterface.setAliasAndTags(MyApplication.getInstance(),
                            (String) msg.obj,
                            null,
                            mAliasCallback);
                    break;
                default:
                    Log.e(TAG, "Unhandled msg - " + msg.what);
            }
        }
    };

    // 校驗Tag Alias 只能是數字,英文字母和中文
    public static boolean isValidTagAndAlias(String s) {
        Pattern p = Pattern.compile("^[\u4E00-\u9FA50-9a-zA-Z_!@#$&*+=.|]+$");
        Matcher m = p.matcher(s);
        return m.matches();
    }
}
複製代碼

3.關於後端服務器設置別名仍是前端設置別名:

說實在的,之前沒有遇到過這個選擇題,由於以前作的極光推送都是在咱們客戶端設置,不過最近調試JPush的時候後臺說他設置別名,我忽然就有點蒙了?不是通常都是前端設置嗎??? 因而有個疑問:若是是服務端設置別名,那服務端也沒有通過客戶端,那極光服務器咋經過別名來匹配用戶進行點對點推送呀???我一會兒有點想不通了。而後查了一下文檔和相關博客,確實極光服務器也給後端服務提供設置別名的API,又問了一下後端開發,他是否是隻是單單設置了別名,仍是在設備ID上也有作了處理,由於沒有映射關係,極光服務器也不可能找到對應的用戶進行推送呀。果不其然,他是在RegistrationID上設置的別名,這下我就明白了。 不過大部分的狀況,應該仍是前端設置別名吧,畢竟那些登入登出的操做在前端控制會比較方便。

小提醒:

實際應用場景,客戶端通常都須要在登陸到App成功後,設置別名,恢復接收推送。退出登陸後,中止接收推送。 恢復接收推送: ``` JPushInterface.resumePush(MyApplication.getInstance()); ``` 中止接收推送: ``` JPushInterface.stopPush(MyApplication.getInstance()); ```

4.App殺死後還想要收到推送

有的公司因爲業務需求,可能會要求你,App殺死後還想要收到推送。若是知道JPush Android SDK 是做爲 Android Service 長期運行在後臺的,從而建立並保持長鏈接,保持永遠在線的能力...的童鞋們,那麼必需要清楚一點的是:若是APP真的被殺死了,是不可能收到推送的,若是殺死了還能收到,那說明多是如下幾種狀況: ①應用自啓動了 ②要麼是其餘方式將App拉起來了。 ③你壓根就沒有殺死App,Service還在運行着。(有的手機清理App,並無徹底殺死進程的)

關於這個問題能夠看看這位小姐姐的總結:
Android 關於App被殺死後,如何接收極光推送
極光推送相關閱讀參考:
官網集成
極光推送Android端API
詳解極光推送的 4 種消息形式 —— Android 篇
常見問題 - JPush 合集(持續更新)

相關文章
相關標籤/搜索