在API 29中在后台接听来电

问题描述

我正在开发一个使用呼叫者姓名的应用程序。问题是我无法在后台启动TTS。也许您可以建议一种更正确的方法来编写此程序,但是现在我创建了2个服务,启动第一个服务后,接收器在后台工作,第二个服务应发出呼叫者的名字。但是我得到了错误

 Process: ua.pkk.voicecalls,PID: 30112
java.lang.RuntimeException: Unable to start receiver ua.pkk.voicecalls.CallReceiver: java.lang.IllegalStateException: Not allowed to start service Intent 
{ 
act=android.intent.action.PHONE_STATE flg=0x1000010 cmp=ua.pkk.voicecalls/.TTS (has extras) 
}: app is in background uid UidRecord{7920cb9 u0a137 RCVR idle change:uncached procs:2 seq(0,0)}

    at android.app.ActivityThread.handleReceiver(ActivityThread.java:3797)
    at android.app.ActivityThread.access$1400(ActivityThread.java:219)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1870)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
 Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { act=android.intent.action.PHONE_STATE flg=0x1000010 cmp=ua.pkk.voicecalls/.TTS (has extras) }: app is in background uid UidRecord{7920cb9 u0a137 RCVR idle change:uncached procs:2 seq(0,0)}
    at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1616)
    at android.app.ContextImpl.startService(ContextImpl.java:1571)
    at android.content.Contextwrapper.startService(Contextwrapper.java:669)
    at android.content.Contextwrapper.startService(Contextwrapper.java:669)
    at ua.pkk.voicecalls.CallReceiver.onIncomingCallReceived(CallReceiver.java:56)
    at ua.pkk.voicecalls.CallReceiver.onCallStateChanged(CallReceiver.java:110)
    at ua.pkk.voicecalls.CallReceiver.onReceive(CallReceiver.java:45)
    at android.app.ActivityThread.handleReceiver(ActivityThread.java:3788)
    at android.app.ActivityThread.access$1400(ActivityThread.java:219) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1870) 
    at android.os.Handler.dispatchMessage(Handler.java:107) 
    at android.os.Looper.loop(Looper.java:214) 
    at android.app.ActivityThread.main(ActivityThread.java:7356) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 

MainActivity:

public class MainActivity extends AppCompatActivity {


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    check_permissions();
}

private void check_permissions() {
    if (ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.SYstem_ALERT_WINDOW) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.READ_CALL_LOG,Manifest.permission.READ_PHONE_STATE,Manifest.permission.READ_CONTACTS,Manifest.permission.FOREGROUND_SERVICE},1);
    }
}

@Override
protected void onPostResume() {
    super.onPostResume();
}

@Override
protected void onPause() {
    super.onPause();
}

public void start_service(View view) {
    getApplicationContext().startService(new Intent(this,myService.class));
}

public void stop_service(View view) {
    getApplicationContext().stopService(new Intent(this,myService.class));
}

}

背景服务:

public class myService extends android.app.Service {

@Override
public void onCreate() {
    Log.d("my_TAG","onCreate");
    super.onCreate();
}

@Override
public int onStartCommand(Intent intent,int flags,int startId) {
    Log.d("my_TAG","onStartCommand");
    return START_STICKY;
}

@Override
public void onDestroy() {
    Log.d("my_TAG","onDestroy");
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

}

语音服务文字

public class TTS extends Service implements TextToSpeech.OnInitListener {
private TextToSpeech tts;
private String spokenText;
private boolean isLoaded;

@Override
public void onCreate() {
    super.onCreate();
    Log.d("my_TAG","onCreate");
    tts = new TextToSpeech(this,this);
}

@Override
public int onStartCommand(Intent intent,"onStartCommand");
    spokenText = intent.getStringExtra("name");
    return START_NOT_STICKY;
}

private void speak() {
    if (tts != null && isLoaded){
        tts.speak(spokenText,TextToSpeech.QUEUE_FLUSH,null,"1");
    }
}

@Override
public void onInit(int status) {
    Log.d("my_TAG","onInit entered " + status);

    if (status == TextToSpeech.SUCCESS) {
        int result = tts.setLanguage(new Locale("en"));

        if (result != TextToSpeech.LANG_MISSING_DATA && result != TextToSpeech.LANG_NOT_SUPPORTED) {
            Log.d("my_TAG","isLoaded = true;");
            isLoaded = true;
            speak();
        } else {
            Log.d("my_TAG","Language has missing data or is not supported");
        }
    } else {
        Log.d("my_TAG","Status unsuccessful");
    }
}

@Override
public void onDestroy() {
    super.onDestroy();
    if (tts != null) {
        tts.stop();
        tts.shutdown();
    }
    Log.d("my_TAG","onDestroy");
}

@Override
public IBinder onBind(Intent arg0) {
    return null;
}

}

在接收器中:

private void onIncomingCallAnswered(Context ctx,String number,Date start) {
    if (number != null) {
        Log.e("my_TAG",number + "answered");
        intent = new Intent("stop_voice");
        intent.putExtra(IS_ENDED_TAG,true);
        ctx.sendbroadcast(intent);
    }
}

;

private void find_name(String number,Context context) {
    ContentResolver contentResolver = context.getContentResolver();
    Uri uri = Uri.withAppendedpath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,Uri.encode(number));
    Cursor cursor = contentResolver.query(uri,new String[]{ContactsContract.PhoneLookup.disPLAY_NAME},null);
    if (cursor == null) {
        return;
    }
    if (cursor.movetoFirst()) {
        contact_name = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.disPLAY_NAME));

    } else {
        contact_name = "UnkNown contact";
    }
    if (!cursor.isClosed()) {
        cursor.close();
    }
}

清单:

<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <receiver
        android:name="ua.pkk.voicecalls.CallReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
        </intent-filter>
    </receiver>

    <service
        android:name="ua.pkk.voicecalls.myService"
        android:enabled="true"
        android:process=":MyServiceProcess" />
    <service android:name="ua.pkk.voicecalls.TTS"
        android:enabled="true"
        android:process=":TTS"/>

</application>

感谢您的关注。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)