У меня есть два приложения Xamarin для Android - назовем их «Archy» и «Mehitabel».
Archy имеет некоторую постоянную информацию о состоянии (которая, скажем, для аргументации, находится в базе данных SQLite).
Если с Mehitabel что-то происходит, ей нужно знать часть этой государственной информации.
Чтобы совершить этот подвиг, я попросил Мехитабель отправить намерение Арчи. У Арчи есть широковещательный приемник, который слышит это, собирает необходимое состояние и отправляет другое намерение обратно в Mehitabel.
Вот код от Archy:
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new [] { "com.example.Archy.SendStateToMehitabel"})]
public class StateQueryReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
var msg = new Intent("com.example.Mehitabel.StateFromArchy");
msg.PutExtra("ImportantStateInfo", GetSomeState());
context.SendBroadcast(msg);
}
}
А вот код от Mehitabel:
private async Task AskArchyForState()
{
var filter = new IntentFilter("com.example.Mehitabel.StateFromArchy");
var csrc = new TaskCompletionSource<bool>();
var rcvr = new ActionBroadcastReceiver((context, intent) =>
{
State = intent.GetStringExtra("ImportantStateInfo");
csrc.TrySetResult(State != null);
});
RegisterReceiver(rcvr, filter);
var msg = new Intent("com.example.Archy.SendStateToMehitabel");
SendBroadcast(msg);
var task = await Task.WhenAny(csrc.Task, Task.Delay(Timeout));
UnregisterReceiver(rcvr);
if (task != csrc.Task)
bomb("Archy has not answered state query after {0}ms", Timeout);
if (!csrc.Task.IsCompletedSuccessfully || csrc.Task.Result == false)
bomb("failed to get all necessary state from Archy");
}
Все это отлично работает, при условии, что Archy действительно запущен (т. Е. Показан в списке «недавних»). Если Archy не запущен, код получателя Archy никогда не выполняется, а время ожидания Mehitabel истекает.
Я надеюсь, что мне не хватает чего-то простого (например, флага в одном из атрибутов получателя или какой-то секретный соус в намерении com.example.Archy.SendStateToMehitabel).
Вы можете сказать мне, что мне здесь не хватает?
Нужно ли мне использовать совершенно другой подход (например, иметь Mehitabel StartActivityForResult () как действие в Archy или использовать службу, которая запускается при загрузке и работает все время)?
Основываясь на моем исследовании, я думаю, что вы могли бы открыть Archy до того, как вам понадобятся данные в Mehitabel. Это демонстрация открытия приложения в коде.
Intent launchIntent = PackageManager.GetLaunchIntentForPackage("NewTestApp.NewTestApp");
if (launchIntent != null)
{
StartActivity(launchIntent);
}
Примечание. NewTestApp.NewTestApp - это имя пакета Archy.
Оказывается, использование StartActivityForResult()
- более простой способ сделать это. Подробнее см. мой ответ на связанный вопрос.
Я заставил это работать, но с некоторыми оговорками: 1) Это работает лучше, когда я пишу имя своего пакета правильно. 2) Archy запускается дольше, чем ожидалось - от отправки намерения запуска до ответа на мою трансляцию прошло более 25 секунд. 3) Мне пришлось добавить цикл повтора к коду Mehitabel в моем исходном вопросе, чтобы иметь дело с (2), поскольку широковещательные сообщения, отправленные до того, как Archy будет готов, теряются.