Android 8.0设备上的JobScheduler API崩溃
为了满足Android target API 26对我的应用程序的要求,我修改了我应用程序中的后台服务,将其与JobScheduler一起启动,而不仅仅作为普通服务。这是我的更新代码 在我的PhoneUtils类中,Android 8.0设备上的JobScheduler API崩溃,android,android-8.0-oreo,android-jobscheduler,android-8.1-oreo,Android,Android 8.0 Oreo,Android Jobscheduler,Android 8.1 Oreo,为了满足Android target API 26对我的应用程序的要求,我修改了我应用程序中的后台服务,将其与JobScheduler一起启动,而不仅仅作为普通服务。这是我的更新代码 在我的PhoneUtils类中, public static void scheduleTTSJob(Context context) { if(isTTSJobServiceOn(context)) { return; } if (android.os.Bui
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;
}
}
TTS服务类的代码:
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>
据我所知,如果我使用的是JobScheduledService ScheduleTSjob()调用,而不是来自代码的普通startService()调用,则不应该发生这种情况。它没有在我测试它的设备(MotoG6)上崩溃,该设备也有安卓8.0.0,但现在在安卓8.0.0及以上的其他设备上崩溃
据我所知,如果我使用的是JobScHeduledService ScheduleTSjob()调用,而不是来自代码的普通startService()调用,则不应该发生这种情况
您肯定在使用来自代码的普通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()
,或startForeground()
- 如果适用,将该
逻辑移动到后台线程中的一些非服务代码中,您可以直接从TTSService
onStartJob()执行这些代码
很难给你更具体的建议,因为我们不知道什么是
TTSService
。谢谢你的及时回复:)我尝试使用StartForegroundsService(),但当ABC是我的应用时,我的设备状态栏上会出现一个永久性通知,说“ABC应用正在运行”。我的一些用户对此并不满意,这就是为什么我想求助于此。基本上,我的TTS服务会启动一个TTS对象,用于在我的应用程序实例可能处于活动状态或不处于活动状态时输出一些语音。在这种情况下如何避免这种情况?我已经更新了TTSService类的代码。请告知。@SoulRayder:JobScheduler
用于将来在半随机时间完成工作,因此我不确定它是否适合TTS场景。但是假设一个半随机的时间是可以的,那么就从你的作业服务中执行TTS工作。从执行TTS-ing的onStartJob()
启动一个后台线程。感谢您的输入。我会试试:)出于好奇,你知道我的测试设备MotoG6也在安卓8.0.0上,它是如何工作的,甚至不会崩溃一次?由于它在这个设备上运行良好,我认为它在Oreo及以上的所有其他设备上运行良好。请阅读-总结是,这不是一种理想的解决志愿者问题的方法,并且可能会对获得答案产生反作用。请不要把这个添加到你的问题中。我不知道这是一件事。对此表示抱歉,请记住:)
@Override
public boolean onStartJob(JobParameters params) {
Intent service = new Intent(getApplicationContext(), TTSService.class);
getApplicationContext().startService(service);
PhoneUtils.scheduleTTSJob(getApplicationContext()); // reschedule the job
return true;
}