targetSdkVersion 26在崩溃报告中给出了例外情况

时间:2018-08-04 15:33:09

标签: android google-text-to-speech

根据在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(这是我应用程序中的当前状态)?任何其他解决方案将不胜感激。

4 个答案:

答案 0 :(得分:1)

Android 8.0+不允许启动后台服务。请参阅this,以更好地了解引起问题的原因。您可以根据自己的minSdkVersion迁移到FirebaseJobDispatcherJobScheduler。另外,如果您使用 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);
    }
}

希望有帮助