unity android定时本地推送

游戏中恢复体力,玩法出现等功能都是定时的,需要每天定时推送,提醒玩家,最近遇到这个需求,也是花费了几天,记录一下。

部分代码参照https://www.jianshu.com/p/b9eb60f04f82,基本能实现推送显示功能,但是点击事件,第二篇写了一大堆,感觉用不到,就借鉴其他的。

首先是创建定时任务,写到mainactivity里面,供unity调用。

/**
     * 显示数秒后的通知
     *
     * @param pAppName 应用名
     * @param pTitle 通知标题
     * @param pContent 通知内容
     * @param pDelaySecond 延迟时间
     * @param pIsDailyLoop 是否每日自动推送
     * @throws IllegalArgumentException 错误信息
     * @throws requestCode 推送分类
     */
    public  void ShowNotification(String pAppName, String pTitle, String pContent, int pDelaySecond, boolean pIsDailyLoop,int requestCode) throws IllegalArgumentException {
        if(pDelaySecond < 0)
        {
            throw new IllegalArgumentException("The param: pDelaySecond < 0");
        }
        Intent intent = new Intent(this,AndroidNotificator.class);
        intent.putExtra("appname", pAppName);
        intent.putExtra("title", pTitle);
        intent.putExtra("content", pContent);
        intent.setAction("UNITY_NOTIFICATOR");
        PendingIntent pi =  PendingIntent.getBroadcast(this, requestCode, intent, 0);
        AlarmManager am = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.SECOND, pDelaySecond);
        long alarmTime = calendar.getTimeInMillis();

        if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.M)
        {
            am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,alarmTime,pi);
        }
        else  if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT)
        {
            am.setExact(AlarmManager.RTC_WAKEUP,alarmTime,pi);
        }
        else
        {
            am.set(AlarmManager.RTC_WAKEUP, alarmTime,pi);
        }
    }

参数如注释所述,其中pIsDailyLoop这个参数我没有使用,通过每日都定时一个推送来实现的。解释下代码,首先创建一个intent用来传输数据,构造函数里面第一个参数用的this,第二个参数传的是一个继承BroadcastReceiver的接收通知类。(我觉得这个参数好像并没有什么用,因为下文指定的有action,但是一直没记得去实验一下,就先这样了),在intent里面写入数据,为通知栏中显示的标题和内容。然后指定action,action是自定义的,作用为指定可以接收这个通知的接收器,在manifest文件中配置。然后创建一个pendingintent,携带上面创建的intent的数据,用来传输,之所以用getBroadcast是因为这个是要创建一个广播,第二个参数比较重要,不同类型的推送必须要设置不同的requestCode,相同code的推送,后面的会覆盖掉前面的,比如先创建了推送a,后创建推送b,如果设置相同的code,那么推送a将不会显示,这个比较坑,注意一下。接下来获取系统的定时器,创建定时任务,注意不同的版本创建定时任务要用不同的api,不然会导致android8.0定时不准,或者实时失效的情况,谨记。

接下来创建广播接收器,显示通知,类名即上面创建intent指定的类名,继承BroadcastReceiver。重写onReceive,显示通知。

public class AndroidNotificator extends BroadcastReceiver {

        private static   int m_nLastID = 0;

        @SuppressWarnings("deprecation")
        public void onReceive(Context pContext, Intent pIntent) {
            ApplicationInfo applicationInfo = null;
            PackageManager pm = pContext.getPackageManager();
            try {
                applicationInfo = pm.getApplicationInfo(pContext.getPackageName(), PackageManager.GET_META_DATA);
            } catch (Exception ex) {
                ex.printStackTrace();
                return;
            }
            Intent intent = new Intent(pContext, NotifivationReceiver.class);
            intent.setAction("UNITY_NOTIFRECEIVE");
            PendingIntent contentIntent = PendingIntent.getBroadcast(pContext,0,intent,0);

            Bundle bundle = pIntent.getExtras();
            Notification.Builder builder = new Notification.Builder(pContext)
                    .setContentTitle((String)bundle.get("title"))
                    .setContentText((String)bundle.get("content"))
                    .setSmallIcon(R.drawable.app_icon)
                    .setContentIntent(contentIntent)
                    .setDefaults(Notification.DEFAULT_ALL)
                    .setPriority(Notification.PRIORITY_DEFAULT)
                    .setWhen(System.currentTimeMillis())
                    .setAutoCancel(true)
                    .setOngoing(false);

            Notification  notification=builder.getNotification();
            NotificationManager nm = (NotificationManager)pContext.getSystemService(Context.NOTIFICATION_SERVICE);
            nm.notify(m_nLastID, notification);
            m_nLastID++;
        }
    }

前面那个try catch我不清楚有没有用,就保留下来了。先创建一个intent,传入另一个继承BroadcastReceiver的类,用作接收通知点击事件,action同样是自定义,指向同一个类。然后创建pendingintent,因为点击事件是立即的,不存在覆盖的问题,所以这个requestCode都传0,。接下来就是创建通知Notification,并设置各个属性,这个没什么好说的了,也没有什么坑。然后通知的显示是获取系统的通知管理器,调用api显示即可。这里面功能比较简单,就此略过。

最后创建另一个接收器,接收通知的点击事件,类名如上NotifivationReceiver,同样继承BroadcastReceiver,重写onReceive,响应点击。

public class NotifivationReceiver extends BroadcastReceiver {

    @SuppressWarnings("deprecation")
    public void onReceive(Context context, Intent pIntent) {
        Log.d("NotifivationReceiver","receive");
        Intent mainIntent = new Intent(context, MainActivity.class);     mainIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED|Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(mainIntent);
    }
}

注意一定要设置这样的flags,不然会出问题。这样设置之后,如果游戏正在前台,点击直接进入游戏,如果在后台,点击直接进入游戏,从后台变前台,不会重新启动,游戏已经停止,点击会启动游戏,因为我这个是unity项目,只有mainactivity一个activity。

最后贴一下manifest里面这两个类的配置。可以看到action是相对应的。

      <receiver android:name="****.AndroidNotificator">
          <intent-filter>
              <action android:name="UNITY_NOTIFICATOR" />
          </intent-filter>
      </receiver>

      <receiver android:name="****.NotifivationReceiver">
          <intent-filter>
              <action android:name="UNITY_NOTIFRECEIVE" />
          </intent-filter>
      </receiver>

到这个整个功能就完结了,每天的定时推送是我根据本地的数据来设置的,如果进游戏的时候发现今天已定时,就不会重复定时,如果没有,就定时一下,同时存入本地一个标识符用来判断,个人觉得甚至可以每次进入游戏都创建定时任务,因为相同的requestCode,后面的会覆盖前面的,不会出现重复通知的情况。

总结一下,有几个坑需要注意:

1.创建pendingintent的requestCode,不同的推送要设置不同的值

2.系统定时管理器的api,不同版本要使用不同的api

3.响应通知栏点击,因为也相当于广播,所以创建的intent要指定接收器

4.android4.4经测试,正常退出,强杀程序定时推送正常,android8.0,如果正常退出游戏,在正在运行的程序列表是能看到游戏,这样的话定时任务正常执行,但是如果通过正在运行的程序列表直接强杀程序,定时任务就不会执行,因为8.0杀得太干净了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值