服务正在重新创建者AlarmManager(Service being re-Created by

2019-07-21 17:15发布

我有一个相当标准的服务,我想通过报警来触发。 下面是服务的开始部分:

class MyService extends Service {
    private Context context;
    private AlarmManager  alarmManager = null;

    private final String startReason = "com.stuff.myreason";
    private final int REASON_NO_INTENT = 0;
    private final int REASON_ALARM     = 1;
    private final int REASON_X         = 2; // and so on.

    @Override
    void onCreate() {
        super.onCreate();
        context = getApplicationContext();
        alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
        // do onCreate stuff
    }

    @Override
    int onStartCommand (Intent intent, int flags, int startId) {
        int reason = REASON_NO_INTENT;
        if (intent != null) {
            reason = intent.getExtra(startReason, REASON_NO_INTENT);
        }

        switch(reason) {
            // handle the different reasons we may have been "started"
        }

        return START_STICKY;
    }
}

当我使用触发它context.startService从一个活动,它开始正常绝。 特别是,如果它已经运行它不(再)从头开始,而只是通过进入现有的实例onStartCommand() 这是预期的行为。 然而,当我触发它使用AlarmManager:

Intent intent = new Intent(context, MyService.class);
intent.putExtra(purposeOfStartCode, REASON_ALARM);

PendingIntent pi = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

alarmManager.set(AlarmManager.RTC_WAKEUP, /* A time in the future */, pi);

当报警是由于它似乎重新从头服务:它启动一个新实例,调用onCreate()然后onStartCommand()而不是仅仅调用onStartCommand()在已经运行的实例。

我已经试图改变PendingIntent标志FLAG_ONE_SHOT和更换contextMyService.this没有改善。

我宁愿这个困惑 - 任何人都可以解释这种行为,并建议如何得到它像预期的那样?

编辑 - 那所得溶液中的行为的收集是我的回答如下。

Answer 1:

经过一番调查和工作,我发现了一些东西。 做完所有的人,这个问题看起来像它的消失:

  1. 如果您在服务覆盖在onStart和onStartCommand(允许旧设备),你把super.onStartCommand在后者,它会调用在onStart,这意味着你会得到每一个意图来两次!

  2. 按照其他答案(和它的意见),该AlarmManager设计和指定提供广播意图,而不是其他类型之一。 然而,在实践中,这是不挑剔,似乎兑现等形式。 我认为这是解决问题的关键之一。

  3. 如果该服务是在同一进程中其他activites等服务有时似乎“一下就重新启动”。 这可能是在这个问题上注意到问题的实际原因。 见的Android服务的onCreate被多次调用,而不调用的onDestroy 。

  4. 事情似乎仅仅使用意图时与服务,而不是绑定和使用Messenger或结合和访问方式进行沟通更加稳定。 虽然两者都是正确的,他们是有相当复杂的管理(虽然你可以使用这种方法: 什么是调用一个Android活动从服务线程回来的首选方式 ,并使用Android应用程序类持久化数据 )。 虽然我完全明白了android文档不同意我,以我的观察移动广播意图仅通信显得关键。 如果你去的独立过程方法你无论如何都要做到这一点。

  5. 它支付是如何声明一致,并解决您的类。 这是一个有点乱,但是,因为有时似乎要使用全名(“com.company.superapp.CleverService”),而不是短期(“CleverService”或“.CleverService”)。 因此,它可能会更好始终使用全名。

  6. 拇指漂浮在那里大约上下文(“使用getApplicationContext”)的规则是不是真的这样做的正确方法。 见当调用活动上下文或应用程序上下文? ; 在本质上利用这一点,除非你真的需要使用一个更广阔的背景和管理您的变量好。

  7. 这是可能的垃圾收集器,如果它是一个活动,服务,主题,的AsyncTask等已不再围绕创建仍在使用清理的东西。 如果应用程序是基于一个服务,它可能是明智的类拷贝进来,使他们没有得到后清理。

  8. 启动比通常建议进行服务的更合适的方法是给服务的IntentFilter的与它的全名作为动作。 然后,您可以创建的意图,只类的字符串名字启动它。 这意味着你不必担心环境。 参见问题的呼叫服务 。



Answer 2:

嗯,我确实惊讶的是,它在您的Service了! 该PendingIntent ,你传递给AlarmManager需要一个广播Intent 。 所以,你需要重新构建你的代码位。 该AlarmManager将触发BroadcastReceiverBroadcastReciever然后可以调用startService()

看到的描述AlarmManager.set()



Answer 3:

我得到这个使用下面的代码工作:

AlarmManager almgr = (AlarmManager)MyContext.getSystemService(Context.ALARM_SERVICE);
Intent timerIntent = new Intent(MyUniqueLabel);
timerIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
PendingIntent pendingOffLoadIntent = PendingIntent.getBroadcast(MyContext, 1, timerIntent, 0);

你必须做这些事情为它工作。
1)呼叫addFlags和意图,并传递它FLAG_RECEIVER_FORGROUND
2.)使用在PendingIntent.getBroadcast非零请求码

如果你留下任何的这些步骤进行,它不会工作。



文章来源: Service being re-Created by AlarmManager