Четкая связь между проектом библиотеки Android и приложением, использующим его

Может ли кто-нибудь сказать мне хороший подход для связи из проекта библиотеки Android с приложением, которое использует эту библиотеку?

Небольшое описание: моя библиотека получает уведомления GCM и пересылает некоторые из них в приложение с помощью этой библиотеки. Прямо сейчас я понял это с намерениями, отправленными библиотекой, и 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.

манифест.xml

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

person Stefan Medack    schedule 12.05.2014    source источник


Ответы (2)


Правильный способ сделать это в Android зависит от того, как установлена ​​ваша «библиотека».

Если ваша библиотека установлена ​​как отдельное «приложение», решение состоит в том, чтобы использовать разные фильтры намерений для разных трансляций. Таким образом, Android будет доставлять трансляцию только тем приложениям, которые заявили о своем интересе. Вам потребуется обновить свои клиентские приложения с помощью отдельных фильтров намерений и изменить свою библиотеку, чтобы использовать фильтр намерений для соответствующего клиента как часть его трансляции.

Если ваша библиотека связана с обоими вашими клиентами, то лучше всего использовать подход LocalBroadcastManager.

person Phil Haigh    schedule 12.05.2014
comment
Это на самом деле не отвечает на вопрос ОП. Я думаю, что из его вопроса он хорошо знает, как использовать Intents и как обрабатывать различные действия, но проблема в том, что один и тот же Intent достигает нескольких приложений, хотя только одно должно его получить. Такова природа трансляций, и вы ничего не можете с этим поделать. Но вы можете использовать LocalBroadcasts, чтобы обойти это, смотрите мой ответ для получения дополнительной информации. - person Xaver Kapeller; 12.05.2014
comment
Вы имеете право на свое мнение, но грубо отрицать технически правильный ответ, даже если вы с ним не согласны. На самом деле... см. мои комментарии к вашему ответу - person Phil Haigh; 12.05.2014
comment
Я не согласен с этим, и я знаю, что это технически правильно. Но это просто не то, о чем просил ОП. Вы никогда не сможете реализовать это так, как хочет OP, с обычными трансляциями, поскольку они просто так не работают. Трансляции всегда видны всем приложениям, и вы не можете и не должны пытаться настроить таргетинг на определенные приложения с помощью трансляций. Вопрос ОП не в том, как использовать трансляции или что-то в этом роде, его проблема в том, что трансляции видны всем приложениям. - person Xaver Kapeller; 12.05.2014
comment
Не нужно драться ;) На самом деле я думал о том, чтобы сделать намерения отчетливыми. Проблема, которую я вижу в этом решении, заключается в том, что библиотеку может использовать кто угодно, и ее нельзя модифицировать. Таким образом, приложение, которое использует мою библиотеку, должно определить некоторые отдельные значения в своем собственном приложении, которые я затем использую в библиотеке. Это, конечно, возможно, но я ищу элегантный способ минимизировать шаги, необходимые для включения библиотеки. - person Stefan Medack; 12.05.2014
comment
Вы предполагаете, что трансляция никогда не будет применима к другим приложениям. Мы этого не знаем. В конце концов, трудно дать полезный совет, не зная, как ОП реализовал свою библиотеку и т. Д., Не так ли? - person Phil Haigh; 12.05.2014
comment
@Zonic, тогда, если библиотека упакована с приложением, LocalBroadcastManager - это то, что вам нужно. - person Phil Haigh; 12.05.2014
comment
@Phil Я не нашел источника, позволяющего мне зарегистрировать LocalBroadcastManager в manifest.xml. Но важно, чтобы приложение постоянно прослушивало намерения из моей библиотеки. Поэтому я решил воспользоваться вашим первым советом, чтобы сделать намерения разными для каждого приложения, использующего библиотеку. Хотя мне все еще кажется, что это грязное исправление ... - person Stefan Medack; 13.05.2014
comment
@Zonic, не могли бы вы ввести вызов «инициализации» для библиотеки, это могло бы получить информацию о приложении, в котором оно работает, и сформировать широковещательное имя для конкретного приложения. Код приложения может запросить у библиотеки, какое широковещательное имя она должна прослушивать, поэтому все это аккуратно инкапсулировано. - person Phil Haigh; 14.05.2014

Вы можете использовать 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);
person Xaver Kapeller    schedule 12.05.2014
comment
Локальная трансляция работает только в контексте процесса. Если библиотека фактически распространяется как отдельная автономная установка, это решение не подходит. Я отредактирую свое решение, чтобы уточнить параметры. - person Phil Haigh; 12.05.2014
comment
@ Фил Да, это правда. Как я уже сказал в своем ответе, трудно дать полезный совет, не зная, как ОП реализовал свою библиотеку и т. Д. - person Xaver Kapeller; 12.05.2014
comment
И все же мое решение «неправильное», а ваше… менее неправильное? Я не собираюсь отрицать ваше решение, хотя оно и заманчиво. - person Phil Haigh; 12.05.2014
comment
Спасибо за ваши ответы, Фил и Ксавер. LocalBroadcastManager мне тоже кажется интересным. Но проблема, которую я вижу в этой реализации, заключается в том, что мой BroadcastReceiver должен быть зарегистрирован вне любого контекста Activity. Уведомления GCM могут появляться, даже если приложение не активно, и приложение все еще должно их прослушивать. Вы случайно не знаете, можно ли определить LocalBroadcasts в manifest.xml? Я тоже сам проверю. На самом деле большое спасибо вам обоим :) - person Stefan Medack; 12.05.2014
comment
Вы можете сделать это наоборот, используя Intent для регистрации Service в вашей библиотеке GCM, так как теперь у вас есть классы в вашей библиотеке, для этого вам не нужна трансляция. С этого момента вы можете нацеливать зарегистрированные Service на свои Intents, и вам не нужно прибегать к широковещательным рассылкам. Я бы посоветовал вам написать класс менеджера/помощника, чтобы сделать это в клиентском приложении. Может быть, специальный подкласс Service, который должен использовать каждый, кто использует вашу библиотеку. Они просто реализуют этот подкласс Service, и он автоматически позаботится о регистрации в библиотеке и т. д. - person Xaver Kapeller; 12.05.2014
comment
Можно ли отправить локальную широковещательную рассылку из PendingIntent? Как PendingIntent.getBroadcast... - person IgorGanapolsky; 05.02.2015