5

Can anyone tell me a good approach to communicate from an Android Library Project to the App which uses this Library?

A little description: my library receives GCM notifications and forwards some of them to the App using this library. Right now I realized this with Intents send by the library and a BroadcastReceiver listening for that intent in the App.

The problem: when I install 2 Apps with my application, both receive each others notifications. Anybody an idea?

Thanks in advance!

[Edit]

Here is some Code. I receive a GCM Notification in the library and forward it to the consuming App:

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);
    ...
    }

and my BroadcastReceiver listens for con_broadcast_gcm_notification. It is registered in the manifest via Intent-Filter.

manifest.xml

    ...
    <receiver android:name=".MyBroadcastReceiver" >
        <intent-filter>
            <action android:name="de.tuberlin.snet.gcm.notification" />
        </intent-filter>
    </receiver>
    ...
Stefan Medack
  • 2,731
  • 26
  • 32

2 Answers2

3

You can use LocalBroadcasts instead of normal broadcasts. They essentially are like real broadcasts, but only visible to one application. I assume you want to communicate from a Service to the app? Then LocalBroadcasts should be exactly what you are looking for, but without knowing exactly how you implemented anything I cannot give you very specific advice.

Anyway if you want to use LocalBroadcasts you first have to create a BroadcastReceiver like you would with a normal broadcast:

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
        }
    }
};

You can then register and unregister the BroadcastReceiver like this:

@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);
}

And finally you can send a broadcast from your Service or anywhere else in your application like this:

Intent intent = new Intent(SOME_ACTION);

LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
manager.sendBroadcast(intent);
Xaver Kapeller
  • 49,491
  • 11
  • 98
  • 86
  • 1
    A local broadcast only works in the context of a process. If the library is in fact distributed as a separate standalone installation, this solution is not appropriate. I will edit my solution to clarify the options. – Phil Haigh May 12 '14 at 12:52
  • @Phil Yes that is true. As I said in my answer it is difficult to give helpful advice without knowing how the OP implemented his library etc. – Xaver Kapeller May 12 '14 at 12:55
  • And yet my solution is 'wrong' while yours is... less wrong? I'm not going to downvote your solution, tempting though it is. – Phil Haigh May 12 '14 at 12:58
  • 1
    Thanks for your answers so far Phil and Xaver. LocalBroadcastManager looks interesting to me too. But the problem I see with that implementation would be, that my BroadcastReceiver has to be registered out of any Activity context. GCM notifications can occur even though the App is not active and the App still has to listen for it. Do you know by any chance, if LocalBroadcasts can also be defined in the manifest.xml? I'll check it myself too. Really a big thank you to both of you :) – Stefan Medack May 12 '14 at 13:14
  • 1
    You could do it the other way around, use an `Intent` to register a `Service` in your GCM library, since you now the classes in your library you don't need a broadcast for that. From then on you can target the registered `Service` specifically with your `Intents` and don't need to resort to broadcasts. I would suggest you write a manager/helper class to do this in the client application. Maybe a special `Service` subclass which everyone using your library has to use. They would just implement this `Service` subclass and it automatically takes care of registering itself with the library etc. – Xaver Kapeller May 12 '14 at 13:18
  • Can a Local Broadcast be sent from a PendingIntent? Like PendingIntent.getBroadcast... – IgorGanapolsky Feb 05 '15 at 13:41
1

The correct way to do this in Android depends on how your 'library' is installed.

If your library is installed as a separate 'application' in its own right, the solution is to use different intent filters for distinct broadcasts. In that way Android will deliver a broadcast only to those apps which have advertised their interest. You'll need to update your client apps with distinct intent filters, and change your library to use the intent filter for the appropriate client as part of its broadcast.

If your library is bundled with both of your clients, then using a LocalBroadcastManager approach is the route to take.

Phil Haigh
  • 4,522
  • 1
  • 25
  • 29
  • 1
    That does not really answer the OPs question. I think from his question he is well aware how to use `Intents` and how to handle different actions, but the problem is that the same `Intent` reaches multiple apps even though only one should receive it. That is simply the nature of broadcasts and you cannot do anything about that. But you can use `LocalBroadcasts` to get around that, see my answer for more information. – Xaver Kapeller May 12 '14 at 12:47
  • You're entitled to your opinion but its harsh to downvote an answer that is technically correct, even if you disagree with it. In fact... see my comments on your answer – Phil Haigh May 12 '14 at 12:50
  • I don't disagree with it, and I know that it is technically correct. But it is just not what the OP asked for. You could never implement it the way OP wants with normal broadcasts as they just don't work that way. Broadcasts are always visible to all applications and you cannot and should not try to target specific apps with broadcasts. The OP's question is not about how to use broadcasts or anything like that, his problem is just that the broadcasts are visible to all applications. – Xaver Kapeller May 12 '14 at 12:59
  • 1
    No need to fight ;) I was actually thinking about making the intents distinct. The problem I see with this solution is, that the library can be used by anybody and should not be modified. So an App which uses my library has to define some distinct values in it's own App, which I than use in the library. This is of course possible, but I'm looking for an elegant way to minimize the steps needed to include the library. – Stefan Medack May 12 '14 at 13:04
  • You're assuming that the broadcast is _never_ going to be applicable to other applications. We don't know that. After all, it is difficult to give helpful advice without knowing how the OP implemented his library etc, isn't it? – Phil Haigh May 12 '14 at 13:07
  • @Zonic then if the library is packaged with the app, LocalBroadcastManager is the way to go. – Phil Haigh May 12 '14 at 13:15
  • 1
    @Phil I haven't found any source allowing me to register a LocalBroadcastManager in manifest.xml. But this is important to have the App listening to Intents from my library all the time. So I decided to take your first advice to make the Intents distinct for each App using the library. Still looks like a dirty fix to me though... – Stefan Medack May 13 '14 at 16:43
  • 1
    @Zonic couldn't you introduce an 'initialisation' call for the library, this could obtain information about the app it is running inside and form an application-specific broadcast name. The application code can ask the library what broadcast name it should be listening for, so it is all neatly encapsulated. – Phil Haigh May 14 '14 at 10:17