根据在2018年11月之前将目标SDK版本更新为26的要求,我尝试在几个月前更新gradle文件,并在更新目标sdk和编译sdk版本后发布了新版本的应用程序到26(从23)。一天之内,我开始在Firebase控制台上观察我的应用程序中的崩溃。原因是我在我的应用程序中使用了TTS服务,并且当定位到版本26时,由于致命的运行时异常,它似乎需要TTS服务的新实现。因此,我将目标SDK版本还原为23,并将sdk版本还原为23。
Caused by java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.a.b.c/services.TTSService }: app is in background
对于Android OS 8.0和8.1上的设备,此异常仅显示为 。
所以一个月前,我买了一个新的设备,该设备在Android 8.0(Motorola G6 Plus)上,希望能够始终如一地重现此错误。 即使我的应用定位为26版,即使我通过我的应用强行触发了TTS服务,该设备也从未发生过。因此,我对如何进行感到困惑。
here说明了此异常的解决方案。
我当前用于实现和调用TTS服务的代码如下:
MainActivity oncreate方法:
if(!isMyServiceRunning(TTSService.class))//Start a service instance only if service is currently not running
startService(new Intent(MainActivity.this, TTSService.class));
TTSService.java:
package services;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Environment;
import android.os.IBinder;
import android.speech.tts.TextToSpeech;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.Toast;
import com.google.firebase.crash.FirebaseCrash;
import constants.ConstantParams;
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();
FirebaseCrash.report(new Exception("Error in initializing TTS object"));
FirebaseCrash.log("Error in initializing TTS object");
}
return Service.START_STICKY;
}
@Override
public void onDestroy() {
clearTtsEngine();
super.onDestroy();
}
public static void clearTtsEngine()
{
if(voice!=null)
{
voice.stop();
voice.shutdown();
voice = null;
}
}
}
是否必须按照上述解决方案重新实现此功能?还是我可以采用一种更简单的方法来定位版本26 SDK,但将编译SDK版本保留为23(这是我应用程序中的当前状态)?任何其他解决方案将不胜感激。
答案 0 :(得分:1)
Android 8.0+不允许启动后台服务。请参阅this,以更好地了解引起问题的原因。您可以根据自己的minSdkVersion迁移到FirebaseJobDispatcher或JobScheduler。另外,如果您使用 androidx -WorkManager。
P.S。请注意,将目标SDK设置为26后,通知将无法正常工作。
答案 1 :(得分:1)
在android 8(api 26)+上,您无法在后台运行服务。您可以做的就是通过在清单中添加权限服务前台并调用startServiceForeground()
来在前台运行服务。
答案 2 :(得分:0)
可以请您试试
`startForegroundService()` in place of `startService()`.
答案 3 :(得分:0)
我更改您的服务代码。看一下这个 (///添加此评论)
为您的服务添加关注功能
//ADD THIS
private IBinder mBinder = new LocalBinder();
//ADD THIS
@Override
public IBinder onBind(Intent intent) {
// Called when a client (MainActivity in case of this sample) comes to the foreground
// and binds with this service. The service should cease to be a foreground service
// when that happens.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
stopForeground(true);
}
return mBinder;
}
//ADD THIS
@Override
public void onRebind(Intent intent) {
// Called when a client (MainActivity in case of this sample) returns to the foreground
// and binds once again with this service. The service should cease to be a foreground
// service when that happens.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
stopForeground(true);
}
super.onRebind(intent);
}
//ADD THIS
@Override
public boolean onUnbind(Intent intent) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(13, new Notification());
return true; // Ensures onRebind() is called when a client re-binds.
}
return false;
}
//ADD THIS
public class LocalBinder extends Binder {
public TTSService getServerInstance() {
return TTSService.this;
}
}
然后在您的MainActivity
的onCreate()上方添加此变量
// A reference to the service used to get location updates.
private TTSService mService = null;
// Tracks the bound state of the service.
private boolean mBound = false;
// Monitors the state of the connection to the service.
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
TTSService.LocalBinder binder = (TTSService.LocalBinder) service;
mService = binder.getServerInstance();
mBound = true;
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mService = null;
mBound = false;
}
}
};
并在onStop()
和onStart()
中添加以下行
@Override
protected void onStop() {
super.onStop();
//add for android O
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (mBound) {
// Unbind from the service. This signals to the service that this activity is no longer
// in the foreground, and the service can respond by promoting itself to a foreground
// service.
unbindService(mServiceConnection);
mBound = false;
}
}
}
@Override
protected void onStart() {
super.onStart();
//add for android O
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
bindService(new Intent(this, TTSService.class), mServiceConnection, Context.BIND_AUTO_CREATE);
}
}
希望有帮助