为了满足我的应用程序的Android target API 26要求,我修改了应用程序中的后台服务,以使用JobScheduler而不是将其作为普通服务启动。这是我更新的代码。
在我的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类
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 utilities.PhoneUtils;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class TTSJobScheduledService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
Intent service = new Intent(getApplicationContext(), TTSService.class);
getApplicationContext().startService(service);
PhoneUtils.scheduleTTSJob(getApplicationContext()); // reschedule the job
return true;
}
@Override
public boolean onStopJob(JobParameters params) {
return true;
}
}
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;
}
}
}
此外,我在清单文件中添加了这项新服务:
<service
android:name="services.TTSJobScheduledService"
android:label="TTS service"
android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
当用户打开我的应用程序(如果尚未计划),设备重新启动或应用程序在Google Play上升级时,我正在计划此服务。
但是,发布此应用程序更新后不久,对于使用Android 8.0.0及更高版本的设备,此堆栈跟踪就开始崩溃:
Caused by java.lang.IllegalStateException: Not allowed to start service Intent { cmp=abc.fgh.com.abc/services.TTSService }: app is in background uid UidRecord{6dafcbe u0a250 TRNB idle procs:1 seq(0,0,0)}
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1505)
at android.app.ContextImpl.startService(ContextImpl.java:1461)
at android.content.ContextWrapper.startService(ContextWrapper.java:644)
at services.TTSJobScheduledService.onStartJob(Unknown Source:15)
at android.app.job.JobService$1.onStartJob(JobService.java:71)
at android.app.job.JobServiceEngine$JobHandler.handleMessage(JobServiceEngine.java:108)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:180)
at android.app.ActivityThread.main(ActivityThread.java:6950)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:835)
据我了解,鉴于我使用的是JobScheduledService scheduleTTSJob()调用,而不是代码中的普通startService()调用,因此不应发生这种情况。在我测试的设备(Moto G6)上,它也没有崩溃,该设备也具有Android 8.0.0,但现在在装有Android 8.0.0及更高版本的其他设备上也崩溃了。
答案 0 :(得分:1)
据我了解,鉴于我使用的是JobScHeduledService scheduleTTSJob()调用,而不是代码中的普通startService()调用,所以这应该不会发生
您肯定在代码中使用普通的Image Crop
调用。它在您的startService()
方法中:
onStartJob()
这就是堆栈跟踪显示您崩溃的地方。
请让我知道我的代码中要进行的修复
要么:
删除该@Override
public boolean onStartJob(JobParameters params) {
Intent service = new Intent(getApplicationContext(), TTSService.class);
getApplicationContext().startService(service);
PhoneUtils.scheduleTTSJob(getApplicationContext()); // reschedule the job
return true;
}
呼叫,或
使用startService()
并在启动时让ContextCompat.startForegroundService()
呼叫TTSService
,或者
如果适用,将startForeground()
逻辑移到直接从TTSService
执行的后台线程中的一些非服务代码中
鉴于我们不知道onStartJob()
是什么,因此很难给您更具体的建议。