我想要的是什么:运行一个后台服务,它会在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的通知栏中显示声音通知 我将衷心感谢您的帮助。谢谢!
答案 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();
}
}