漫游后台进程

时间:2015-12-15 13:59:41

标签: android service alarmmanager

我想要的是什么:运行一个后台服务,它会在1分钟的固定间隔后通过RESTFUL webservice与我们的服务器通信(这是一个严格的项目要求。所以无法增加它。)

我有什么:我尝试了各种方法,使用简单的 BroadcastReceivers ,使用简单的服务 AND WakefulBroadcastReceivers strong> WakefulIntentService 等..

主要问题:主要问题是当设备屏幕亮起时,一切都在正常/固定的时间间隔内正常工作,但是当屏幕关闭或设备被锁定时,警报管理器会触发服务最小间隔 5分钟 ..这正是我不想要的。设备锁定/屏幕关闭时我想要相同的1分钟间隔。

以下是我的代码:

Manifest.xml

  <uses-permission android:name="android.permission.WAKE_LOCK" />   
  <receiver android:name=".MyScheduledReceiver" />
  <service android:name=".BackgroundService" />  

Activity.java

 MyScheduledReceiver.scheduleAlarms(MainActivity.this);  

gradle

// Background long running process
compile 'com.commonsware.cwac:wakeful:1.0.+'  


repositories {
maven {
    url "https://s3.amazonaws.com/repo.commonsware.com"
}

}

BroadcastReceiver

public class MyScheduledReceiver extends WakefulBroadcastReceiver {


private static final int PERIOD = 60 * 1000;
private static final int INITIAL_DELAY = 2000; // 5 seconds

@Override
public void onReceive(Context context, Intent i) {

    try {

        if (i.getAction() == null) {
            WakefulIntentService.sendWakefulWork(context, BackgroundService.class);

        } else {
            scheduleAlarms(context);

        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}


static void scheduleAlarms(Context ctxt) {

    AlarmManager mgr = (AlarmManager) ctxt.getSystemService(Context.ALARM_SERVICE);
    Intent i = new Intent(ctxt, MyScheduledReceiver.class);
    PendingIntent pi = PendingIntent.getBroadcast(ctxt, 0, i, 0);

    mgr.setRepeating(AlarmManager.RTC_WAKEUP, INITIAL_DELAY, PERIOD, pi);

}

}

BackgroundService

public class BackgroundService extends WakefulIntentService {


public BackgroundService() {
    super("BackgroundService");
}

@Override
protected void doWakefulWork(Intent intent) {

    sendNotification("HELLOO");

    stopSelf();
}

@Override
public void onTaskRemoved(Intent rootIntent) {

    MyScheduledReceiver.scheduleAlarms(BackgroundService.this);

    super.onTaskRemoved(rootIntent);
}

private void sendNotification(String message) {


    try {
        Intent intent = intent = new Intent(this, MainActivity.class);

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        Notification notification;
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("test")
                .setContentText(message)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        notification = notificationBuilder.build();
        notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());

    } catch (Exception e) {
        e.printStackTrace();
    }

}

}

目前我只是在我的BackgroundService的通知栏中显示声音通知 我将衷心感谢您的帮助。谢谢!

3 个答案:

答案 0 :(得分:4)

无论如何,Android 6.0不支持您想要的内容。由于Doze模式,Android 6.0不会每分钟向任何应用程序发出警报。

最接近的是:

  • 让服务使用ScheduledExecutorService来控制每一分钟来完成工作

  • 让该服务获得WakeLock并始终保持CPU开启

  • 让该服务使用startForeground()START_STICKY来最大限度地缩短它不在的时间,从而无法完成这项工作

  • 确保将应用程序添加到“设置

  • 中的”忽略电池优化“白名单
  • 忽略用户的痛苦哭泣,抱怨他们的电池寿命很恶劣

答案 1 :(得分:1)

尝试使用像这样的

public static void scheduleAlarms(Context ctxt) {
    AlarmManager mgr = (AlarmManager)ctxt.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(ctxt, MyScheduledReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(ctxt,REQUEST_CODE, i, 0);

// We want the alarm to go off 3 seconds from now.
long firstTime = SystemClock.elapsedRealtime();
firstTime += 3 * 1000;//start 3 seconds after first register.

mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime,
        600000, sender);//10min interval

}

答案 2 :(得分:0)

您是否尝试使用处理程序来实现此目标? AlarmManager通常会在可能的情况下以电池友好的节奏工作。而处理程序更准确。

例如,您可以在Service

中运行此代码
// Store this as a member variable
private Handler mHandler = new Handler();

// This can be a member variable or local
private Runnable runnable = new Runnable() {
   @Override
   public void run() {
      // Do stuff

      // Tell the Handler to call itself again
      mHandler.postDelayed(this, 60000);
   }
};

// Put this at the start of `Service`
mHandler.postDelayed(runnable, 60000);

正如Commonsware所指出的那样,将Handler声明为如上所述会导致Handler在主线程上运行。以下是关于如何让Handler在后台运行的一些documentation

class LooperThread extends Thread {
    public Handler mHandler;

    public void run() {
        Looper.prepare();

        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                // process incoming messages here
            }
        };

        Looper.loop();
    }
}