【问题标题】:Android notification not fired when app killed应用程序终止时未触发Android通知
【发布时间】:2019-01-16 21:16:37
【问题描述】:

我正在使用警报管理器来设置时间并在该特定时间发出通知。当应用程序是前台或后台时工作正常。我正在 Android 8 上进行测试。但是我的问题是当应用程序从任务管理器中被杀死时,通知不会被触发,因为广播不起作用。这是因为我在 MainActivity 的 onCreate() 中注册了接收器,并在 onDestroy() 中取消了接收器的注册。如果我在清单中注册我的广播接收器,也许它会起作用,但从 Android 8 开始就不允许这样做。如何解决这个问题,即使应用被杀死,我也收到广播?

【问题讨论】:

  • 您应该创建一个服务并在手机启动或您的应用程序启动时启动它,即使您的应用程序已被杀死,您也可以保持该服务处于活动状态。查看广播接收器的工作原理。
  • 谢谢,能否给我一个伪代码或如何实现它的示例或一些链接。这会很有帮助
  • 如果我没记错的话,我有一个带有工作广​​播接收器的旧项目,它会在您的本地化靠近某个地点时通知您。今晚晚些时候我会试着找到它,如果我找到它会告诉你的。
  • 那太好了:) 谢谢
  • 你应该检查的快速的事情,我看到你的最后一个问题,如果你想在用户已经收到警报时销毁它,你为什么要停止你的广播接收器 onDestroy 应用程序,你应该停止发送通知时的服务。

标签: android


【解决方案1】:

BroadCastREceiver 示例

public class SchedulerMailBroadcastReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            Log.i("scheduler: " + new DateWrapper().getLocaleString());
            PowerManager pm = (PowerManager) context.getApplicationContext().getSystemService(Context.POWER_SERVICE);
            PowerManager.WakeLock wl = null;
            if (pm != null) {
                Log.d("aquire wakelog");
                wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ics:mailScheduler");
                wl.acquire(10000);
            }
            startInNewThread(context.getApplicationContext(),wl);
        }catch(Exception e){
            Log.e(e);
        }
    }
    public void startInNewThread(final Context context, PowerManager.WakeLock wl){
        new ThreadWrapper(() -> {
            try {
               //Do Stuff
            }catch(Exception e){
                Log.e(e);
            }finally {
                Log.d("releasing wakelog");
                try {
                    wl.release();
                    Log.i("released wakelog");
                }catch(Exception e){
                    Log.e("wakelog release","exception on releasing wawkelog");
                }
            }
        }).start();
    }

    public static boolean registerScheduler(Context context){

        final int requestCode=1234;

        Intent intent = new Intent(context, SchedulerMailBroadcastReceiver.class);
        intent.setAction("startScheduler");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        AlarmManager alarmManager =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        if (alarmManager != null) {
           // alarmManager.cancel(previousPendingIntent);
            alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 1000 * 60*15, pendingIntent);
            Log.i("registered repeating");
        }
        return  true;
    }


}

虽然你可能不想要 setRepeating

JobService 示例

public class SchedulerMailJobManager extends JobService{

    @Override
    public boolean onStartJob(JobParameters params) {
        try {
            Log.i("SchedulerMailJobManager","scheduler run at "+ new DateWrapper().getLocaleString());
            startInNewThread(getApplicationContext(),params);
            return true;
        }catch(Exception e){
            Log.e("SchedulerMailJobManager","errpr in starting new thread",e);
            return false;
        }
    }

    @Override
    public void onDestroy(){
        Intent intent = new Intent(this,ServiceRestarter.class);
        intent.setAction("restartService");
        intent.putExtra("service","mailScheduler");
        sendBroadcast(intent);
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        Log.w("stoppedJob","stopped");
        return true;
    }

    public void startInNewThread(final Context context,final JobParameters params){
        new ThreadWrapper(() -> {
            try {
                //Do Stuff
            }catch(Exception e){
                Log.e("JobScheduler2ndThread","Exception",e);
            }finally {
                if(params!=null) {
                    this.jobFinished(params,false);
                }else{
                    Log.e("JobScheduler2ndThread","no params for jobFinished");
                }
            }
        }).start();
    }


    static JobInfo createScheduledJob(Context context){
        ComponentName serviceComponent = new ComponentName(context,SchedulerMailJobManager.class );
        JobInfo.Builder builder=new JobInfo.Builder(1234,serviceComponent);
        int waitMin=30;
        builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
        builder.setPersisted(true);
        builder.setPeriodic(1000*60*waitMin,1000);
        return builder.build();
    }
    public static boolean registerScheduler(Context context){
        JobScheduler scheduler=context.getSystemService(JobScheduler.class);
        if(scheduler==null){
            Log.e("registerScheduler","scheduler is null");
            return false;
        }
        if(scheduler.getPendingJob(1234)!=null) {
            scheduler.cancel(1234);
            Log.i("registerScheduler","cancelled previous");
        }
        int resultCode=scheduler.schedule(createScheduledJob(context));
        if(resultCode==JobScheduler.RESULT_SUCCESS){
            Log.i("JobManagerScheduler","registered new scheduler");
            return true;
        }else{
            Log.e("registerScheduler","failed registering");
            return false;
        }

    }

}

由于您只有一个通知,您可能不需要在新线程中启动任何内容,这意味着在此解决方案中您应该在 OnStartJob 中返回 false

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-06
    • 2017-07-30
    • 2016-03-25
    • 2018-08-08
    • 2017-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多