Android 第三方推送整合文檔

一、集成開發文檔

官方文檔已經非常詳細,而且更新及時,這裏直接給出地址了。集成過程中可能會遇到一點小坑,在網上找找還是有的。

1,小米推送

配置文檔地址:https://dev.mi.com/doc/?p=544

注:開發中遇到推送多條消息只顯示最後一條的問題。原因是服務器在構建消息時 notifyId 使用了默認值,當 notifyId 相同時會覆蓋之前的消息。詳見《小米推送服務 Server 端 SDK 》

2,激光推送

配置文檔地址:http://docs.jiguang.cn/jpush/client/Android/android_sdk/

3,阿里雲推送

配置文檔地址:https://help.aliyun.com/document_detail/51056.html?spm=5176.doc30066.6.641.pXaihr

控制檯地址:https://push.console.aliyun.com/

注:阿里雲在創建應用時只需要有一個名字,待審覈通過後會出現“配置”按鈕,此時一定要進入配置對應的包名應用才能正常。

二、點擊推送消息後的處理(參考)

點擊推送消息後,如果需要打開一連串的 Fragment 頁面,還得考慮應用是否啓動,邏輯就變得繁瑣起來。

首先有這麼幾條信息先整理一下:

  • 將 Activity 的啓動模式設置爲 singleTask 後,調用開啓,此時如果 Activity 已經啓動會執行生命週期的 onNewIntent(Intent intent) 方法,如果未啓動纔會執行 onCreate(Bundle savedInstanceState) 方法。

  • 在 Fragment 基礎上嵌套再開啓另外一個 Fragment 時,只有在第一個 Fragment 執行了 onResume() 方法後纔可以正常的開啓第二個 Fragment,否者會替換失敗。(測試得出)

有如下一條邏輯鏈:點擊通知條 —》 開啓 Activity —》 加載 FragmentA —》 FragmentA onResume() —》 加載 FragmentB —》 FragmentB onResume() —》 加載 FragmentC,可以參照如下方式實現:

在廣播接收者中,接收用戶點擊通知條的事件:

// 小米推送的實現方式
public class MiPushMusicReceiver extends PushMessageReceiver {

    @Override
    public void onNotificationMessageClicked(Context context, MiPushMessage miPushMessage) {
        String pushContent = miPushMessage.getContent();
        if (!TextUtils.isEmpty(pushContent)) {
            PushMusic pushMusic = GsonHelper.fromJson(pushContent, PushMusic.class);
            if (pushMusic != null) {
                startMusic(context, pushMusic);
            }
        }
    }

    public static final String EXTRA_PUSH_MUSIC = "extraPushMusic";

    private void startMusic(Context context, PushMusic pushMusic) {
        if (isAppAlive(context, context.getPackageName())) {
            Intent intent = new Intent(context, MainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.putExtra(EXTRA_PUSH_MUSIC, pushMusic);
            context.startActivity(intent);
        } else {
            Intent launchIntent = context.getPackageManager().
                    getLaunchIntentForPackage("com.ionesmile.pushdemo");
            launchIntent.setFlags(
                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
            launchIntent.putExtra(EXTRA_PUSH_MUSIC, pushMusic);
            context.startActivity(launchIntent);
        }
    }

    /**
     * 判斷應用是否已經啓動
     *
     * @param context     一個context
     * @param packageName 要判斷應用的包名
     * @return boolean
     */
    public static boolean isAppAlive(Context context, String packageName) {
        Log.v("NotificationLaunch", "isAppAlive() packageName = " + 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)) {
                Log.i("NotificationLaunch", String.format("the %s is running, isAppAlive return true", packageName));
                return true;
            }
        }
        Log.i("NotificationLaunch", String.format("the %s is not running, isAppAlive return false", packageName));
        return false;
    }
}

在 Activity 中,處理如下,並給 Activity 添加 SingleTask 啓動模式:

public class MainActivity extends Activity implements ContinuousEventCallback {

    private Map<Class, Runnable> classRunnableMap = new HashMap<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        startPushMusic(getIntent(), false);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        startPushMusic(intent, true);
    }

    @Override
    public void onWindowResumeReady(Object window) {
        Runnable runnable = classRunnableMap.remove(fragment.getClass());
        if (runnable != null) {
            runnable.run();
        }
    }

    // 執行一連串的事情,當窗體在 onResume() 時做什麼操作
    private void startPushMusic(Intent intent, boolean isNewIntent) {
        if (intent != null && intent.getExtras() != null) {
            final MiPushMusicReceiver.PushMusic pushMusic = (MiPushMusicReceiver.PushMusic) intent.getExtras().getSerializable(MiPushMusicReceiver.EXTRA_PUSH_MUSIC);
            if (pushMusic != null) {
                classRunnableMap.put(FragmentA.class, new Runnable() {
                    @Override
                    public void run() {
                        // TODO FragmentA something 
                    }
                });
                classRunnableMap.put(FragmentB.class, new Runnable() {
                    @Override
                    public void run() {
                        // TODO FragmentB something 
                    }
                });
                ...
                // 如果當前 Activity 已經存在,說明部分子 Fragment 已經執行了 onResume(),可以直接執行子操作
                if (isNewIntent) {
                    classRunnableMap.remove(FragmentA.class).run();
                    classRunnableMap.remove(FragmentB.class).run();
                }
            }
        }
    }
}

public interface ContinuousEventCallback {

    void onWindowResumeReady(Object window);
}

另外,在 Fragment(BaseFragment 或是需要監聽的 Fragment) 的 onResume() 方法中調用添加如下代碼:

@Override
public void onResume() {
    super.onResume();
    if (getActivity() instanceof ContinuousEventCallback) {
        ((ContinuousEventCallback) getActivity()).onWindowResumeReady(this);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章