Android本地消息推送


項目介紹:cocos2dx跨平台游戲

項目需求:實現本地消息推送,需求①:定點推送;需求②:根據游戲內邏輯實現推送(比如玩家體力滿時,需要計算后到點推送);需求③:清理后台程序或重啟后依然能夠實現本地推送。

功能實現:由於IOS有一套比較成熟的UILocalNotification推送機制,這里主要說明Android下本地推送的實現。另外大家感興趣可以看下第三方的推送:個推、極光、騰訊信鴿、百度雲推送等,第三方多是要接入服務端,否則只能自己在第三方申請的應用的后台手動推送,另外第三方也不保證能100%所有客戶端都能接收到推送。自己游戲里接入了信鴿,親試,開啟游戲可以收到推送,關閉游戲未能收到而是在再次啟動游戲時收到。看來接收也有待優化。

1.全局定時器AlarmManager,可參考鬧鍾app,AlarmManager為系統級別,所以一般不會被清理掉,並把設定的提醒保存到本地(這里使用的SharedPreference,也可使用SQLite數據庫存儲),開機重啟時重新設置定時提醒。

/**
     * 消息推送
     * noticeStr:通知內容
     * tiemstamp:通知的啟動的時間戳,單位為秒,定時器單位為毫秒
     */
    public int noticeCount = 0;
    public void pushMessage(String noticeStr, long timestamp) {
        //System.currentTimeMillis() 等於 Calendar.getInstance().getTimeInMillis()
      long longTime = timestamp*1000;if (longTime > System.currentTimeMillis()) { Intent intent = new Intent(this, PushReceiver.class); //設置參數 intent.putExtra("noticeId", noticeCount); intent.putExtra("noticeStr", noticeStr); //timestamp參數 區別要注冊的PendingIntent //receiver獲取參數需要flag設置為PendingIntent.FLAG_UPDATE_CURRENT PendingIntent pi = PendingIntent.getBroadcast(FunmAndroid.this, noticeCount, intent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager am = (AlarmManager) getSystemService(Activity.ALARM_SERVICE);; am.set(AlarmManager.RTC_WAKEUP, longTime, pi); //本地存儲,手機重啟,需要重新設置 SharedPreferences sharedPreferences = getSharedPreferences("funm_push", Context.MODE_PRIVATE); Editor editor = sharedPreferences.edit(); editor.putLong("tiemstamp_"+noticeCount, longTime); editor.putString("noticeStr_"+noticeCount, noticeStr); editor.putInt("noticeCount", noticeCount); Log.v("and_log", "put noticeCount: "+noticeCount); editor.commit(); noticeCount++; } }

2.接收廣播:BroadCastReceiver,注意這里使用BroadCastReceiver,不要使用service。開機重新設置提醒。

package com.funcity.funm.push;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;

import com.funcity.funm.FunmAndroid;

public class BootReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent1) {
        // TODO Auto-generated method stub
        String action = intent1.getAction();
        if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
            resetPush(context);
        }
    }
    
    private void resetPush(Context context) {
        SharedPreferences sharedPreferences = context.getSharedPreferences("funm_push", Context.MODE_PRIVATE);
        int count = sharedPreferences.getInt("noticeCount", 0);
        int noticeCount = 0;
        for (int i=0; i<count; i++) {
            long timestamp = sharedPreferences.getLong("tiemstamp_"+noticeCount, 0);
            String noticeStr = sharedPreferences.getString("noticeStr_"+noticeCount, "");
            if (timestamp !=0 && !noticeStr.equals("")) {
                Intent playerIntent = new Intent(context, PushReceiver.class);
                playerIntent.putExtra("noticeId", noticeCount);
                playerIntent.putExtra("noticeStr", noticeStr);
                PendingIntent pi = PendingIntent.getBroadcast(context, noticeCount, playerIntent, PendingIntent.FLAG_UPDATE_CURRENT);
                AlarmManager am = (AlarmManager) context.getSystemService(Activity.ALARM_SERVICE);
                am.set(AlarmManager.RTC_WAKEUP, timestamp, pi);
            }
            noticeCount++;
        }
    }
}

3.接收提醒並發起推送:

package com.funcity.funm.push;

import com.fun.funm.R;
import com.funcity.funm.FunmAndroid;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

public class PushReceiver  extends BroadcastReceiver {  
  
    private NotificationManager manager;
    @Override  
    public void onReceive(Context context, Intent intent) {  
        // TODO Auto-generated method stub 
        manager = (NotificationManager)context.getSystemService(android.content.Context.NOTIFICATION_SERVICE);
        int noticeId = intent.getIntExtra("noticeId", 0);
        String noticeStr = intent.getStringExtra("noticeStr");
        Intent playIntent = new Intent(context, FunmAndroid.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, playIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
        builder.setContentTitle(FunmAndroid.getAppName()).setContentText(noticeStr).setSmallIcon(R.drawable.icon).setDefaults(Notification.DEFAULT_ALL).setContentIntent(pendingIntent).setAutoCancel(true);
        manager.notify(noticeId, builder.build());
        Log.v("and_log","收到推送:onReceive: "+ noticeStr);
    }  
}

4.Receiver注冊及權限

<receiver android:name="com.funcity.funm.push.PushReceiver">
            <intent-filter>
                 <action android:name="com.funcity.funm.push.PushReceiver"/>
            </intent-filter>
        </receiver>
        <receiver android:name="com.funcity.funm.push.BootReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
         </receiver>

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

android:targetSdkVersion="18"

注意:

1.手機必須開啟允許開啟自啟動權限定時推送才能在重啟后依然生效。有些手機管理軟件,如360會推薦關閉一些應用的開機自啟動選項。

2.targetSdkVersion19以前是准時推送,貌似19之后為非准時推送,需要注意一下。

3.有些手機類型,比如小米,可能有5分鍾以內的誤差,可能是基於省電的考慮。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM