項目介紹:cocos2dx跨平臺遊戲android
項目需求:實現本地消息推送,需求①:定點推送;需求②:根據遊戲內邏輯實現推送(好比玩家體力滿時,須要計算後到點推送);需求③:清理後臺程序或重啓後依然可以實現本地推送。數據庫
功能實現:因爲IOS有一套比較成熟的UILocalNotification推送機制,這裏主要說明Android下本地推送的實現。另外你們感興趣能夠看下第三方的推送:個推、極光、騰訊信鴿、百度雲推送等,第三方可能是要接入服務端,不然只能本身在第三方申請的應用的後臺手動推送,另外第三方也不保證能100%全部客戶端都能接收到推送。本身遊戲裏接入了信鴿,親試,開啓遊戲能夠收到推送,關閉遊戲未能收到而是在再次啓動遊戲時收到。看來接收也有待優化。併發
1.全局定時器AlarmManager,可參考鬧鐘app,AlarmManager爲系統級別,因此通常不會被清理掉,並把設定的提醒保存到本地(這裏使用的SharedPreference,也可以使用SQLite數據庫存儲),開機重啓時從新設置定時提醒。app
/** * 消息推送 * 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。開機從新設置提醒。ide
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註冊及權限ui
<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" />this
android:targetSdkVersion="18"spa
注意:code
1.手機必須開啓容許開啓自啓動權限定時推送才能在重啓後依然生效。有些手機管理軟件,如360會推薦關閉一些應用的開機自啓動選項。
2.targetSdkVersion19之前是準時推送,貌似19以後爲非準時推送,須要注意一下。
3.有些手機類型,好比小米,可能有5分鐘之內的偏差,多是基於省電的考慮。