2015-12-15 2 views
2

Что я хочу: Чтобы запустить фоновую службу, которая будет взаимодействовать с нашим сервером через RESTful веб-сервиса после очередной интервал 1 мин (его строгое требование проекта Так не может увеличить его.).Длинный ход Фоновый процесс

Что у меня есть: Я пробовал различные подходы, используя простые BroadcastReceivers с простой службы И WakefulBroadcastReceivers используя WakefulIntentService и т.д ..

Основная проблема: 0: Основная проблема заключается в том, когда экран устройства включен, все работает нормально на регулярных/фиксированных интервалах, но когда экран выключается ИЛИ устройства блокируются, тогда диспетчер аварийных сигналов запускает сервис с минимальным интервалом 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

Вы пытались использовать Handler для достижения этой цели? 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 указывает, имея Обработчик объявлен как это выше, будет вызывать обработчик для запуска в главном потоке.Вот некоторые documentation о том, как получить Handler, чтобы работать в фоновом режиме:

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(); 
    } 
} 
+0

Я думаю, что даже с помощью обработчиков он должен будет держать блокировку центрального процессора, чтобы сервисный пробег пока экран выключен. – Than

+0

«Таймеры обычно работают по дружественному батарею ритму, когда это возможно» - OP не использует «Таймер», а «Таймер» не знает о батарее. Кроме того, этот конкретный подход к использованию «Handler» приведет к тому, что работа будет выполнена в основном потоке приложения, что не является хорошей идеей для службы. – CommonsWare

+0

К сожалению, я имел ввиду AlarmManager. Эта часть правильная, правда, верно? Android запускает сигналы тревоги более или менее в нужное время, чтобы продолжать обработку до отрезков времени. В отличие от работы, когда они хотят, что может постоянно поддерживать устройство. – Knossos

4

То, что вы хотите, не поддерживается на Android 6.0 в любом случае. Android 6.0 не будет выдавать тревоги каждую минуту, в любое приложение, благодаря режиму Doze.

Самое близкое, что будет работать это:

  • Есть сервис, который использует ScheduledExecutorService, чтобы контролировать каждую минуту, чтобы сделать вашу работу

  • ли, что служба приобретают WakeLock и держать процессор все время

  • Воспользуйтесь этим сервисом startForeground() и START_STICKY, чтобы свести к минимуму количество времени, в течение которого оно не было, и поэтому inc apable делать эту работу

  • Убедитесь, что приложение будет добавлено в «игнорируемых оптимизаций батареи» белый список в настройках

  • игнорировать крики страдания от пользователей, жалуются, что их срок службы батареи зверским

+0

Хорошо, парень, но я тестировал с вашей точкой № 3, но с теми же результатами. Также я тестирую на 5.0 .. Samsung S4 .. Так что я смущен, почему он не работает в старой версии, если он устарел в версии 6.0, тогда это нормально, я попробую с ScheduledExecutorService, но почему не работает в настоящее время в 5.0 .. Где я пропал? – Noman

+0

@NomanHamid: «Итак, я смущен, почему его не работает в старой версии» - сам «AlarmManager» был изменен в Android 4.4, чтобы игнорировать периоды опроса менее чем за минуту. Однако производители устройств могут и могут изменить ситуацию, поэтому вы можете испытывать некоторые изменения, которые Samsung сделал для экономии энергии, где они подняли самый низкий период опроса до пяти минут. Попытка делать работу каждую минуту считается анти-шаблоном, и все из Google в никуда пытаются ее предотвратить. – CommonsWare

+0

Если это так, то я буду тестировать один и тот же случай на Nexus 5 Android 6.0, тогда .. Я ненавижу samsung btw. Но означает ли это, что ScheduledExecutorService также получит некоторые проблемы с ним, если будет менее 5 минут? – Noman

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 

} 
+0

Пожалуйста, объясните, как это затронет вопрос. – CommonsWare

+0

вы можете установить свой интервал –

+0

Код в вопросе уже устанавливает интервал. – CommonsWare

Смежные вопросы