sendOrderedBroadcast setPackage requirement in Oreo

非 Y 不嫁゛ 提交于 2019-12-22 11:14:10

问题


Why would the following Ordered Broadcast fail in Android Oreo, unless I specifically set the package name?

final Intent vrIntent = new Intent(RecognizerIntent.ACTION_GET_LANGUAGE_DETAILS);

// Setting the package it will work. Omitting, it will fail
// vrIntent.setPackage("com.google.android.googlequicksearchbox");

getContext().sendOrderedBroadcast(vrIntent, null, new BroadcastReceiver() {

    @Override
    public void onReceive(final Context context, final Intent intent) {

                // final Bundle bundle = intent.getExtras();
                final Bundle bundle = getResultExtras(true);

                if (bundle != null) {

                    if (bundle.containsKey(RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES)) {
                        Log.i("TAG", "onReceive: EXTRA_SUPPORTED_LANGUAGES present");

                        final ArrayList<String> vrStringLocales = bundle.getStringArrayList(
                                RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES);

                        Log.i("TAG", "onReceive: EXTRA_SUPPORTED_LANGUAGES size: " + vrStringLocales.size());

                    } else {
                        Log.w("TAG", "onReceive: missing EXTRA_SUPPORTED_LANGUAGES");
                    }

                } else {
                    Log.w("TAG", "onReceive: Bundle null");
                }

}, null, 1234, null, null);

If the package name is not set, EXTRA_SUPPORTED_LANGUAGES will be missing.

I recently asked a bounty question where my 'legacy code', which didn't set the package name, was failing in Oreo, but worked successfully on previous Android versions.

Having checked all of the behavioural changes in API 26 I can see nothing that would explain this.

Can anyone shed some light on the possible cause please?

Note: The sample code and issue assumes the device has Google's 'Now' application installed to provide the RecognitionService


回答1:


OK, I reproduced the problem. The 1234 result code was a red herring — it looks like the process behind RecognizerIntent does not set a result code, so you get the initial code.

However, you do get this error message on Android 8.1 (and, presumably, 8.0):

W/BroadcastQueue: Background execution not allowed: receiving Intent { act=android.speech.action.GET_LANGUAGE_DETAILS flg=0x10 } to com.google.android.googlequicksearchbox/com.google.android.voicesearch.intentapi.IntentApiReceiver

That's the "you registered a receiver in the manifest, and we're not going to give you the broadcast, because you are in the background" error.

This lightly-tested sendImplicitOrderedBroadcast() method works around the problem, while in principle maintaining the order of receivers (descending by priority):

  private void sendImplicitOrderedBroadcast(Intent i, String receiverPermission,
                                            BroadcastReceiver resultReceiver,
                                            Handler scheduler, int initialCode,
                                            String initialData,
                                            Bundle initialExtras) {
    PackageManager pm=getPackageManager();
    List<ResolveInfo> matches=pm.queryBroadcastReceivers(i, 0);

    Collections.sort(matches,
      (left, right) -> right.filter.getPriority()-left.filter.getPriority());

    for (ResolveInfo resolveInfo : matches) {
      Intent explicit=new Intent(i);
      ComponentName cn=
        new ComponentName(resolveInfo.activityInfo.applicationInfo.packageName,
          resolveInfo.activityInfo.name);

      explicit.setComponent(cn);
      sendOrderedBroadcast(explicit, receiverPermission, resultReceiver,
        scheduler, initialCode, initialData, initialExtras);
    }
  }

I took the liberty of filing an issue.



来源:https://stackoverflow.com/questions/48653654/sendorderedbroadcast-setpackage-requirement-in-oreo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!