Как смоделировать JobService как липкий сервис? - PullRequest
0 голосов
/ 08 октября 2018

В соответствии с целевыми требованиями к Android O, мне пришлось повторно реализовать сервис для инициализации объекта преобразования текста в речь как запланированный на работу сервис .

Мой первоначальный сервис реализован следующим образом: TTSService.java

Код для класса TTSService:

package services;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.speech.tts.TextToSpeech;
import android.support.annotation.Nullable;

public class TTSService extends Service {

private static TextToSpeech voice =null;

public static TextToSpeech getVoice() {
return voice;
}

@Nullable
@Override

public IBinder onBind(Intent intent) {
// not supporting binding
return null;
}

public TTSService() {
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

try{

        voice = new TextToSpeech(TTSService.this, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(final int status) {

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


  return Service.START_STICKY;
}

@Override
public void onDestroy() {
 clearTtsEngine();
 super.onDestroy();

}

public static void clearTtsEngine()
{
if(voice!=null)
{
    voice.stop();
    voice.shutdown();
    voice = null;
  }
 }
}

Чтобы повторно реализовать этот сервис какСлужба запланированного задания, в своем классе PhoneUtils я использовал следующие методы:

public static void scheduleTTSJob(Context context) {

if(isTTSJobServiceOn(context))
{
    return;
}

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {

    ComponentName serviceComponent = new ComponentName(context, TTSJobScheduledService.class);
    JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, serviceComponent);

    builder.setMinimumLatency(1 * 1000); // wait at least
    builder.setOverrideDeadline(3 * 1000); // maximum delay
    JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
    jobScheduler.schedule(builder.build());
}
}

public static boolean isTTSJobServiceOn( Context context ) {

boolean hasBeenScheduled = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

    JobScheduler scheduler = (JobScheduler) context.getSystemService( Context.JOB_SCHEDULER_SERVICE );

    for ( JobInfo jobInfo : scheduler.getAllPendingJobs() ) {
        if ( jobInfo.getId() == JOB_ID ) {
            hasBeenScheduled = true;
            break;
        }
    }
}

return hasBeenScheduled;
}

public static void stopTTSJob(Context context)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    JobScheduler scheduler = (JobScheduler) context.getSystemService( Context.JOB_SCHEDULER_SERVICE );

    for ( JobInfo jobInfo : scheduler.getAllPendingJobs() ) {
        if ( jobInfo.getId() == JOB_ID ) {

            scheduler.cancel(JOB_ID);
            break;
        }
    }
}
}

, и служба была реализована следующим образом: TTSJobScheduledService class

package services;

import android.annotation.TargetApi;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Intent;
import android.os.Build;
import android.speech.tts.TextToSpeech;

import com.crashlytics.android.Crashlytics;

import utilities.PhoneUtils;

/**
* Created by Admin on 30-Sep-18.
*/

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class TTSJobScheduledService extends JobService {

private static TextToSpeech voice =null;

public static TextToSpeech getVoice() {
    return voice;
}

@Override
public boolean onStartJob(JobParameters params) {
    startTTSEngine();
    PhoneUtils.scheduleTTSJob(getApplicationContext()); // reschedule the job
    return true;
}

@Override
public boolean onStopJob(JobParameters params) {
    clearTtsEngine();
    return true;
}

private void startTTSEngine()
{
    try{
        voice = new TextToSpeech(TTSJobScheduledService.this, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(final int status) {

            }
        });
    }
    catch(Exception e){
        Crashlytics.log("TTS initialization issue");
        Crashlytics.logException(e);
    }
}

private static void clearTtsEngine()
{
    if(voice!=null)
    {
        voice.stop();
        try {
            voice.shutdown();
        }
        catch (Exception e){
            Crashlytics.log("ClearTTSEngine shutdown issue");
            Crashlytics.logException(e);
        }
        voice = null;
    }
 }
}

Казалось, что это хорошо работает на устройствах с Android O, пока я не заметил, что служба прекратила работу через некоторое время и не перезапускалась сама по себе.Чтобы перезапустить его вручную, мне пришлось либо открыть приложение, либо перезапустить устройство.

По сути, я хочу смоделировать свой TTSService как sticky, jobservice (в основном этодолжна быть перезапущена ОС после ее завершения) .Для этого можно ли просто перезапустить службу в методе onStopJob () службы TTSJobScheduledService?Или есть лучший способ сделать это?

1 Ответ

0 голосов
/ 12 октября 2018
 @Override
    public boolean onStartJob(JobParameters params) {
        return true;
    }

Вызов метода выше будет зависеть от доступности системных ресурсов.Кроме того, нет необходимости, чтобы jobcheduler запускал задание в течение заданного срока, который вы упомянули в вашем jobscheduler.

например: builder.setOverrideDeadline (3 * 1000);

Через некоторое время, если планировщик заданий не используется, система сама останавливает службу.

Вы также можете начать работу в методе onStopJob () , но это всегда зависит от того, как часто вы его используете.

В соответствии с последним ограничением фона Android, ваши изменения будут работать.Если вы хотите какого-либо взаимодействия с пользователем, используйте startForegroundService () .

Пожалуйста, обратитесь к блогу для более подробной информации: https://medium.com/exploring-android/exploring-background-execution-limits-on-android-oreo-ab384762a66c

...