奥利奥系统、默认短信应用和ACTION_RESPOND_VIA_MESSAGE

4

针对 Android O 的应用程序在使用服务时有一些新规则,其中之一是我们不能在应用程序处于后台时启动服务。

成为默认短信应用程序的要求之一是:(来自 Telephony.java javadoc)

* <li>In a service, include an intent filter for {@link
* android.telephony.TelephonyManager#ACTION_RESPOND_VIA_MESSAGE}
* (<code>"android.intent.action.RESPOND_VIA_MESSAGE"</code>) with schemas,
* <code>sms:</code>, <code>smsto:</code>, <code>mms:</code>, and <code>mmsto:</code>.
* This service must also require the {@link
* android.Manifest.permission#SEND_RESPOND_VIA_MESSAGE} permission.
* <p>This allows users to respond to incoming phone calls with an immediate text message
* using your app.</p></li>
* </ul>

你可以看到我的问题...因为如果我们在应用程序后台接收到电话并且用户通过短信拒绝接听电话,则 ACTION_RESPOND_VIA_MESSAGE 需要具有 SEND_RESPOND_VIA_MESSAGE 权限的服务将无法启动。

1237-6018 W/Binder: Binder call failed.
                    java.lang.IllegalStateException: Not allowed to start service Intent { act=android.intent.action.RESPOND_VIA_MESSAGE dat=smsto:xxxxxxxxx cmp=APP_PACKAGE_NAME (has extras) }: app is in background uid null

有什么办法可以解决这个问题吗?

1
正如文档所述,您现在应该启动一个前台服务。 - M. Prokhorov
我不是启动服务的人,而是本机电话应用程序。你是说本机电话应用程序应该调用startForegroundService吗?那确实有道理。在这种情况下,我无需做任何事情,只需等待电话应用程序更新其代码以符合最新的Android Oreo指南即可。 - duffyduck
我最初的印象是你的应用程序试图启动服务。原生电话应用程序不是你所谈论的更改的主题,因为当用户选择用短信回答时,电话应用程序应该在前台。此时,你的应用程序也应被视为前台应用程序,因为它属于“另一个前台应用程序连接到应用程序,通过绑定其服务之一或利用其内容提供程序之一”。那么,实际发生了什么? - M. Prokhorov
再次说明,你说的很有道理。 完整的使用案例是,我是默认的短信应用程序,我的应用程序在后台运行(没有服务/任务运行),我接收到本机呼叫并回复消息。查看日志,我可以看到系统正在尝试启动我的服务,但它失败了,出现java.lang.IllegalStateException:Not allowed to start service Intent { ... }:app is in background uid null(请注意,我的应用程序不会崩溃)。我开始认为这可能是设备问题,我正在使用OnePlus 3。 - duffyduck
你可以用另一台设备或模拟器进行测试吗?你可以从测试应用程序中发送相同的意图。 - M. Prokhorov
观察到 Microsoft SMS Organizer 即使在此限制下也能正常工作,而其他一些应用则不能。 - Rahul Tiwari
1个回答

1
这在原生Android中不应该是这样的,因为默认实现不会调用短信应用程序来拒绝带有消息的呼叫,而是使用SmsManager。

参考自AOSP Oreo中的RespondViaSmsManager.java

/**
 * Reject the call with the specified message. If message is null this call is ignored.
 */
private void rejectCallWithMessage(Context context, String phoneNumber, String textMessage,
                                   int subId, String contactName) {
    if (TextUtils.isEmpty(textMessage)) {
        Log.w(RespondViaSmsManager.this, "Couldn't send SMS message: empty text message. ");
        return;
    }
    if (!SubscriptionManager.isValidSubscriptionId(subId)) {
        Log.w(RespondViaSmsManager.this, "Couldn't send SMS message: Invalid SubId: " +
                subId);
        return;
    }

    SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
    try {
        smsManager.sendTextMessage(phoneNumber, null, textMessage, null /*sentIntent*/,
                null /*deliveryIntent*/);

        SomeArgs args = SomeArgs.obtain();
        args.arg1 = !TextUtils.isEmpty(contactName) ? contactName : phoneNumber;
        args.arg2 = context;
        mHandler.obtainMessage(MSG_SHOW_SENT_TOAST, args).sendToTarget();
    } catch (IllegalArgumentException e) {
        Log.w(RespondViaSmsManager.this, "Couldn't send SMS message: " +
                e.getMessage());
    }
}
似乎一些OEM(我在OnePlus上经历过这种情况)定制了它们的短信应用程序,并保留了旧的行为,需要启动SMS应用程序的服务,而没有考虑到在Oreo中存在关于后台服务的限制。
以下是一些投诉:
  1. https://www.reddit.com/r/oneplus/comments/8n9w37/cant_send_text_message_when_rejecting_phone_call/
  2. https://forums.oneplus.com/threads/reject-call-with-sms-is-not-working-after-oreo-update-oxygen-5-0-1-3t.817578/
我已经在大多数短信应用程序上遇到了这种行为,包括谷歌的Messages,在一加5上使用Android 8.1版本。
这仍然无法解释如何在同一设备上使用OEM提供的短信应用程序或来自微软的SMS Organizer适用于此用例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接