首页 > 解决方案 > android api-26+ 快捷广播接收器未调用

问题描述

我正在尝试在桌面上为应用程序创建固定快捷方式。CreateShortcut 方法从一个按钮调用并显示 android 创建快捷方式对话框。当调用者选择 ok 时,广播接收器应该被调用并执行完成,以便活动退出。

这是我第一次使用广播接收器,但它看起来很简单。只需创建一个接收器,将其注册到与意图具有相同操作的意图过滤器中,当发送意图时,它应该会调用接收器,对吗?

快捷方式创建得很好,但广播接收器永远不会被调用。我在 logcat 上没有看到任何消息。

private void CreateShortcut(final Context c) {
    if (ShortcutManagerCompat
             .isRequestPinShortcutSupported(c)) {

        Intent shortcutIntent = new Intent(
            c, CreateAppHomeShortcut.class);
        shortcutIntent.setAction(
            Intent.ACTION_CREATE_SHORTCUT);

        ShortcutInfoCompat shortcutInfo 
           = new ShortcutInfoCompat
            .Builder(c, "shortcut")
            .setShortLabel(c.getString(R.string.app_name))
            .setIcon(IconCompat.createWithResource(
                 c, R.drawable.qmark)
            )
            .setIntent(shortcutIntent)
            .build();

        registerReceiver(new BroadcastReceiver() {
                 @Override
                 public void onReceive(
                        Context context, Intent intent) {
                     Log.d(TAG, "msg received");
                     unregisterReceiver(this);
                     finish();
                 }
             }
            , new IntentFilter(
                 Intent.ACTION_CREATE_SHORTCUT
            )
        );
        PendingIntent successCallback = 
            PendingIntent.getBroadcast(
                c, 99
                , shortcutIntent, 0
           );
        ShortcutManagerCompat.requestPinShortcut(c,
             shortcutInfo,
             successCallback.getIntentSender()
        );
    }
}

我已经为此工作了几天,我很困惑。
谢谢

标签: androidandroid-broadcastreceiverdesktop-shortcut

解决方案


我终于得到了我的 BroadcastReceiver 的回调。我的主要问题是我使用错误的意图。我认为只要操作正确,广播接收者意图和快捷方式意图就可以相同。错误的!快捷方式意图必须有一个动作集,但在我所做的测试中,它似乎并不关心那个动作是什么。并且广播接收器被创建为“Intent = new Intent(context, class); setAction(...);”,快捷方式将被创建并且功能正常,但广播接收器从未被调用。我可以让广播接收器工作的唯一方法是使用一个 Intent,只为它设置一个动作集(或可能是额外的)集。我无法让程序使用相同的意图来创建快捷方式并调用广播接收器。

遇到的另一个问题是该界面允许您创建多个固定快捷方式 - 然后将为每个创建的快捷方式调用一次广播接收器。我发现您可以查询所有固定快捷方式的界面并按 id 过滤以查明您的快捷方式是否已经存在并使用该信息来避免在您的主页上创建多个相同的固定快捷方式。

下面的代码似乎可以正常工作 API26+ 用于创建快捷方式,只要用户接受快捷方式,接收器就会被调用。文档声明他们只会在用户接受后才致电您的接收者。这当然使得检测用户交互的结束变得相当困难。由于请求被隐藏在我的实际应用程序中,因此计划将其作为单独活动的一部分打开,但如果用户不想要快捷方式,我无法检测到用户是否已完成。如果有人有建议,我将不胜感激。

// Create a shortcut and exit the activity.  If the shortcut
   // already exists,just exit.
    private void CreateShortcut(final Context c) {
        if (Build.VERSION.SDK_INT >= 26) {
            ShortcutManager sm = 
                getSystemService(ShortcutManager.class);
            if (sm != null && sm.isRequestPinShortcutSupported()) {
                final String shortcutId = "StartApp";
                boolean shortcutExists = false;
                // We create the shortcut multiple times if given the
                // opportunity.  If the shortcut exists, put up
                // a toast message and exit.
                List<ShortcutInfo> shortcuts 
                     = sm.getPinnedShortcuts();
                for (int i = 0;
                      i < shortcuts.size() && !shortcutExists; i++) {
                    shortcutExists 
                       = shortcuts.get(i).getId().equals(shortcutId);
                if (shortcutExists) {
                    Toast.makeText(c , String.format(
                            "Shortcut %s already exists."
                            , shortcutId
                        )
                        , Toast.LENGTH_LONG
                    ).show();
                    finishActivity();
                }
                else {
                    // this is the intent that actually creates the
                    // shortcut.
                    Intent shortcutIntent
                        = new Intent(c, CreateAppHomeShortcut.class);
                    shortcutIntent.setAction(
                            Intent.ACTION_CREATE_SHORTCUT);
                    ShortcutInfo shortcutInfo = new ShortcutInfo
                        .Builder(c, shortcutId)
                        .setShortLabel(
                             c.getString(R.string.app_name))
                        .setIcon(createWithResource(c
                             , R.drawable.qmark))
                        .setIntent(shortcutIntent)
                        .build();
                    // this intent is used to wake up the broadcast
                    // receiver.
                    // I couldn't get createShortcutResultIntent to
                    // work but just a simple intent as used for a
                    // normal broadcast intent works fine.
                    Intent broadcastIntent
                        = new Intent(Intent.ACTION_CREATE_SHORTCUT);
                    // create an anonymous broadcaster.  Unregister
                    // to prevent leaks when done.
                    registerReceiver(new BroadcastReceiver() {
                             @Override
                             public void onReceive(
                                      Context c, Intent intent) {
                                 unregisterReceiver(this);
                                 Log.d(TAG, String.format(
                                     "ShortcutReceiver activity = "
                                        + "\"$1%s\""
                                         , intent.getAction()));
                                 finishActivity();
                             }
                         }
                        , new IntentFilter(
                              Intent.ACTION_CREATE_SHORTCUT)
                    );
                    PendingIntent successCallback 
                        = PendingIntent.getBroadcast(
                            c, 99
                            , broadcastIntent, 0);
                    // Shortcut gets created here.
                    sm.requestPinShortcut(shortcutInfo
                            , successCallback.getIntentSender());
                }
            }
        }
    }

推荐阅读