【问题标题】:Distinct communication from Android Library Project to App using it使用它从 Android 库项目到应用程序的不同通信
【发布时间】:2014-06-29 19:23:13
【问题描述】:

谁能告诉我从 Android 库项目与使用此库的应用程序进行通信的好方法?

一点说明:我的库接收 GCM 通知并使用此库将其中一些转发到应用程序。现在,我通过库发送的 Intent 和在 App 中监听该意图的 BroadcastReceiver 实现了这一点。

问题:当我使用我的应用程序安装 2 个应用程序时,两者都会收到对方的通知。有人出主意吗?

提前致谢!

[编辑]

这是一些代码。我在库中收到 GCM 通知并将其转发给消费应用:

GCMIntentService:

@Override
protected void onHandleIntent(Intent intent) {
   ...
        String notificationString = intent
            .getStringExtra(GCMConstants.NOTIFICATION);

        Intent broadIntent = new Intent(getResources().getString(
                R.string.con_broadcast_gcm_notification));
        broadIntent.putExtra("callback", notification.getCallback());
        context.sendBroadcast(broadIntent);
    ...
    }

我的 BroadcastReceiver 监听 con_broadcast_gcm_notification。它通过 Intent-Filter 在清单中注册。

manifest.xml

    ...
    <receiver android:name=".MyBroadcastReceiver" >
        <intent-filter>
            <action android:name="de.tuberlin.snet.gcm.notification" />
        </intent-filter>
    </receiver>
    ...

【问题讨论】:

    标签: android library-project


    【解决方案1】:

    您可以使用LocalBroadcasts 代替普通广播。它们本质上就像真正的广播,但只对一个应用程序可见。我假设您想从Service 与应用程序通信?那么LocalBroadcasts 应该正是您正在寻找的,但在不知道您是如何实现任何东西的情况下,我无法给您非常具体的建议。

    无论如何,如果您想使用LocalBroadcasts,您首先必须像使用普通广播一样创建BroadcastReceiver

    private static final String SOME_ACTION = "someAction";
    
    private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if(SOME_ACTION.equals(action)) {
                // Do your work
            }
        }
    };
    

    然后您可以像这样注册和注销BroadcastReceiver

    @Override
    public void onResume() {
        super.onResume();
    
        IntentFilter intentFilter = new IntentFilter(SOME_ACTION);
    
        LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
        manager.registerReceiver(broadcastReceiver, intentFilter);
    }
    
    @Override
    public void onPause() {
        super.onPause();
    
        LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
        manager.unregisterReceiver(broadcastReceiver);
    }
    

    最后,您可以从您的Service 或您应用程序中的任何其他位置发送广播,如下所示:

    Intent intent = new Intent(SOME_ACTION);
    
    LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
    manager.sendBroadcast(intent);
    

    【讨论】:

    • 本地广播只能在进程的上下文中工作。如果该库实际上是作为单独的独立安装分发的,则此解决方案不合适。我将编辑我的解决方案以阐明选项。
    • @Phil 是的,这是真的。正如我在回答中所说,如果不知道 OP 如何实现他的库等,很难提供有用的建议。
    • 然而我的解决方案是“错误的”,而您的解决方案是......不太错误?我不会拒绝你的解决方案,尽管它很诱人。
    • 感谢 Phil 和 Xaver 到目前为止的回答。 LocalBroadcastManager 对我来说也很有趣。但是我在该实现中看到的问题是,我的 BroadcastReceiver 必须从任何 Activity 上下文中注册。即使应用程序未处于活动状态并且应用程序仍然需要监听它,GCM 通知也会发生。您是否知道是否也可以在 manifest.xml 中定义 LocalBroadcasts?我自己也会检查的。真的非常感谢你们两个:)
    • 你可以反过来做,使用Intent在你的GCM库中注册一个Service,因为你现在库中的类你不需要广播.从那时起,您可以使用您的Intents 专门针对已注册的Service,而无需诉诸广播。我建议您在客户端应用程序中编写一个管理器/助手类来执行此操作。也许是一个特殊的Service 子类,每个使用你的库的人都必须使用它。他们只需实现这个Service 子类,它就会自动处理向库等注册自己。
    【解决方案2】:

    在 Android 中执行此操作的正确方法取决于您的“库”的安装方式。

    如果您的库本身是作为单独的“应用程序”安装的,则解决方案 是为不同的广播使用不同的意图过滤器。这样,Android 将只向那些宣传他们感兴趣的应用程序发送广播。您需要使用不同的意图过滤器更新您的客户端应用程序,并更改您的库以使用适当客户端的意图过滤器作为其广播的一部分。

    如果您的库与您的两个客户端捆绑在一起,那么使用 LocalBroadcastManager 方法是可以采用的方法。

    【讨论】:

    • 这并不能真正回答 OP 的问题。我认为从他的问题中他很清楚如何使用Intents 以及如何处理不同的操作,但问题是相同的Intent 可以到达多个应用程序,即使只有一个应用程序应该接收它。这只是广播的本质,你对此无能为力。但是您可以使用LocalBroadcasts 来解决这个问题,请参阅我的答案以获取更多信息。
    • 您有权发表自己的意见,但即使您不同意,也很难对技术上正确的答案投反对票。事实上......在你的答案中查看我的 cmets
    • 无需战斗 ;) 我实际上正在考虑使意图不同。我在这个解决方案中看到的问题是,任何人都可以使用该库,并且不应对其进行修改。因此,使用我的库的应用程序必须在它自己的应用程序中定义一些不同的值,而不是在库中使用。这当然是可能的,但我正在寻找一种优雅的方式来最大限度地减少包含库所需的步骤。
    • @Phil 我没有找到任何允许我在 manifest.xml 中注册 LocalBroadcastManager 的来源。但这对于让应用程序一直从我的库中监听 Intents 很重要。因此,我决定采纳您的第一个建议,让使用该库的每个应用程序的意图都不同。不过对我来说仍然看起来像一个肮脏的修复......
    • @Zonic 你不能为库引入一个“初始化”调用吗,这可以获取有关它在其中运行的应用程序的信息并形成一个特定于应用程序的广播名称。应用程序代码可以向库询问它应该监听的广播名称,所以它都被整齐地封装了。
    猜你喜欢
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-20
    • 2020-08-23
    • 2014-03-14
    相关资源
    最近更新 更多