几个小时后android警报管理器停止 [英] android alarm manager stops after few hours

查看:66
本文介绍了几个小时后android警报管理器停止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个警报管理器,该警报管理器每5秒钟启动一次服务,该应用程序运行良好,但是几个小时后,警报管理器停止运行。请注意,用户未使用该应用程序,这意味着它在没有用户交互的情况下在后台运行。是否有人知道如何每隔一秒钟启动一次服务而不停止?

I have create an alarm manager that start a service every 5 second, the app is running well but after few hours the alarm manager stop running. Note that the application is not used by the user which mean that it is running on background without user interaction. Does any one knows how to start a service every some second without stopping ?

AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
intent.putExtra(ONE_TIME, Boolean.TRUE); 
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi); 


推荐答案

请勿在警报管理器中执行此类操作。警报管理器更多是
a概念,用于应该在几个小时内完成的任务(在最佳情况下)。

Don't do such things with the alarm manager. The alarm manager is more a concept for tasks that should be done for a period of hours (in best cases).

如果您需要精确处理任务,请在服务的
中使用处理程序,该处理程序将执行您的runnable。
在您的可运行对象内部,调用该方法以再次执行该可运行对象。

If you need a precise processing of your tasks, use a handler inside of a service, that post executes your runnable. Inside of your runnable, call the method to post execute the runnable again.

将可运行对象和处理程序另存为服务的成员变量,然后使
流程粘滞。如果要停止服务和处理程序(如果仅调用stopService(Context)或Service.stopSelf(),处理程序将不会
停止,则需要
来调用removeCallbacks(runnable)并将runnable置于

Save the runnable and handler as member variables of the service and make the process sticky. If you want to stop the service and handler (handler won't stop if you just call stopService(Context) or Service.stopSelf(), you need to call removeCallbacks(runnable) with your runnable on the handler.

干杯。

顺便说一句:考虑一下您是否真的想要每5秒启动一次服务。
也许只是在我刚才描述的服务
的可运行内部执行服务。

Btw: Think about if you really really want to start a service every 5 seconds. Maybe just do the Service work inside of the runnable of the service I just described.

Edit2 :如果您需要该服务可靠,请添加用于启动操作的BroadcastReceiver,它将在启动时接收广播并重新启动您的服务。

Edit2: If you need the Service to be reliable, add a BroadcastReceiver for Boot Actions, that will receive the Broadcast at boot and restart your service.

Edit3 :检查服务是否正在运行而不启动的代码:

Edit3: Code to check if your service is running, without starting it:

    public static boolean isRunning(Context context) {
    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (YourService.class.getName().equals(service.service.getClassName())){
            return true;
        }
    }
    return false;
}

但是,请在onStartCommand中检查您的成员 handler不是null
,如果是这样,则忽略启动请求,因为这可能会导致您遇到具有多个可运行处理的情况。

BUT, nevertheless, check in onStartCommand that your member 'handler' isn't null and ignore a start request if so, because this could lead you to a situation with multiple runnable processing.

Edit4:

服务代码段:

public class LoopingServiceSnipped extends Service{

public static final long STANDARD_FREQUENCY = 1000;
private static       long         loopingFrequency         = STANDARD_FREQUENCY;
private Handler  serviceHandler; 
private Runnable loop; 

//EXTRAS

private static final String       INTENT_EXTRA_STOP_SERVICE  = LoopingServiceSnipped.class.getSimpleName() + "_INTENT_EXTRA_STOP_SERVICE";
private static final String       INTENT_EXTRA_FREQUENCY     = LoopingServiceSnipped.class.getSimpleName() + "_INTENT_EXTRA_FREQUENCY";

/**
 * Determines if the service is running (reliably) without starting it.
 *
 * @param context
 *         needed for SystemServices
 *
 * @return true if the service is running
 */
public static boolean isRunning(Context context) {
    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (LoadingScreenAppDetectionService.class.getName().equals(service.service.getClassName())){
            return true;
        }
    }
    return false;
}

public static void stopService(Context c) {
    Intent i = new Intent(c, LoopingServiceSnipped 
    i.putExtra(INTENT_EXTRA_STOP_SERVICE, true);
    c.startService(i);
 }

public static synchronized void setFrequency(Context c, long frequency) {
    Intent i = new Intent(c, LoadingScreenAppDetectionService.class);
    i.putExtra(INTENT_EXTRA_FREQUENCY, frequency);
    c.startService(i);
}

@Override
public void onCreate() {
    super.onCreate();
    init();
}

private void init() {
    //do your initialization here
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if (shouldStopService(intent)){
        LOG.d("Going to stop service!");
        tryStopService();
        return Service.START_NOT_STICKY;
    } else {
        return startOrContinueService(intent);
    }
}

private void tryStopService() {
    stopLooping();
    stopSelf();
}

private void stopLooping() {
    if (serviceHandler != null){
        serviceHandler.removeCallbacks(getLoop());
        serviceHandler = null;
    }
}

private int startOrContinueService(Intent intent) {
    if (hasNewFrequency(intent)){
        setFrequency(intent);
        stopLooping();
    }
    if (!isServiceRunning()){
     startLooping();
        }
    } else {
        LOG.d("Going to continue with service!");
    }
    return Service.START_STICKY;
}


private boolean hasNewFrequency(Intent intent) {
    return intent.hasExtra(INTENT_EXTRA_FREQUENCY);
}

private void setFrequency(Intent intent) {
    if (intent.hasExtra(INTENT_EXTRA_FREQUENCY)){
        loopingFrequency = intent.getLongExtra(INTENT_EXTRA_FREQUENCY, STANDARD_FREQUENCY);
    }
}

private boolean isServiceRunning() {
    return serviceHandler != null;
}

private boolean shouldStopService(Intent i) {
    if (i.hasExtra(INTENT_EXTRA_STOP_SERVICE)){
        return i.getBooleanExtra(INTENT_EXTRA_STOP_SERVICE, false);
    } else {
        return false;
    }
}

private void startLooping() {
    if (serviceHandler == null){
        serviceHandler = new Handler();
    }
    serviceHandler.postDelayed(getAppDetectionLoop(), getFrequency());
}

private Runnable getLoop() {
    if (loop == null){
        loop = new Runnable() {
            @Override
            public void run() {
                //do your looping work here
                startLooping();
            }
        };
    }
    return loop;
}

另外添加Boot Receiver和Screen TurnOn Receiver。

Additionally add Boot Receiver and Screen TurnOn Receiver.

这篇关于几个小时后android警报管理器停止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆