Как отобразить диалоговое окно в андроиде без контекста активности?
Кажется, что это должно быть просто, но я не нахожу ответа нигде. У меня есть приложение для Android, которое выполняет сетевые задачи в фоновом режиме. Если ошибка вернется, я хочу отобразить диалоговое окно с ошибкой. Когда задача возвращается, я не знаю, какая из них находится на переднем плане. Основываясь на этом сообщении, похоже, что мы не можем использовать контекст приложения для отображения диалогового окна (и действительно, я получаю сбой при попытке).
Итак, как я могу получить контекст текущей активности? Опять же, приемник для сетевой задачи выполняется в контексте приложения, а не в конкретном Activity. Любые другие идеи?
Изменить: я должен уточнить. Я не хочу отображать диалоговое окно с ошибкой, если я не приложение переднего плана. Меня интересует только тот случай, когда наше приложение находится на переднем плане.
Ответы
Ответ 1
Если ошибка вернется, я хочу отобразить диалоговое окно с ошибкой.
Пожалуйста, сделайте это, только если вы знаете, что пользователь активно использует ваше приложение. Пользователь будет очень раздражен, если вы прервете их в середине чего-то другого (игра в игру, просмотр фильма, чтение книги).
Итак, как я могу получить контекст текущей активности?
Нет. В лучшем случае вы позволяете текущей деятельности знать, что ей нужно что-то делать.
Любые другие идеи?
Одна из возможностей - использовать упорядоченную широковещательную рассылку, поэтому, если у вас есть активность переднего плана, она получает контроль, в противном случае вы поднимаете Notification
, чтобы дать пользователю возможность узнать о проблеме без появления диалога. Операция, которая получает упорядоченную трансляцию, может отображать AlertDialog
или иначе сообщить пользователю о проблеме. Я писал о том, как это сделать в сообщении в блоге (и глава книги), и вот пример приложения, демонстрирующий технику.
Или запросите служебный вызов startActivity()
, чтобы запустить диалоговое действие.
Ответ 2
Я создал вспомогательный класс, который реализует идею CommonsWare. Действия, которые хотят отображать предупреждения, просто нужно вызвать Alerts.register() и Alerts.unregister(). Тогда любой может вызвать Alerts.displayError().
Комментарии приветствуются.
public class Alerts {
private static class AlertReceiver extends BroadcastReceiver {
private static HashMap<Activity, AlertReceiver> registrations;
private Context activityContext;
static {
registrations = new HashMap<Activity, AlertReceiver>();
}
static void register(Activity activity) {
AlertReceiver receiver = new AlertReceiver(activity);
activity.registerReceiver(receiver, new IntentFilter(MyApplication.INTENT_DISPLAYERROR));
registrations.put(activity, receiver);
}
static void unregister(Activity activity) {
AlertReceiver receiver = registrations.get(activity);
if(receiver != null) {
activity.unregisterReceiver(receiver);
registrations.remove(activity);
}
}
private AlertReceiver(Activity activity) {
activityContext = activity;
}
@Override
public void onReceive(Context context, Intent intent) {
abortBroadcast();
String msg = intent.getStringExtra(Intent.EXTRA_TEXT);
displayErrorInternal(activityContext, msg);
}
}
public static void register(Activity activity) {
AlertReceiver.register(activity);
}
public static void unregister(Activity activity) {
AlertReceiver.unregister(activity);
}
public static void displayError(Context context, String msg) {
Intent intent = new Intent(MyApplication.INTENT_DISPLAYERROR);
intent.putExtra(Intent.EXTRA_TEXT, msg);
context.sendOrderedBroadcast(intent, null);
}
private static void displayErrorInternal(Context context, String msg) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Error")
.setMessage(msg)
.setCancelable(false)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
final AlertDialog alert = builder.create();
alert.show();
}
}
Ответ 3
Я также сталкиваюсь с проблемой. Я нахожу простое и эффективное решение. Usuallay, мы имеем базовую активность, используемую для обработки некоторой общей логики. Так получилось:
public class BaseActionBarActivity extends ActionBarActivity{ //this BaseActionBarActivity is the Base Act
private static BaseActionBarActivity current;
@Override
protected void onStart() {
super.onStart();
current=this;
}
public static BaseActionBarActivity getCurrentContext() {
return current;
}
}
текущее поле - текущее действие контекста. И я считаю, что вопрос об утечке памяти отсутствует. Это хорошо работает для меня! Надеемся на помощь
Ответ 4
Вот реализация, которая позволит отображать AlertDialog поверх текущей активной активности (это пример диалогового окна сообщений, но также может использоваться для предупреждений).
public class AlertsDialogue
{
private AlertDialog.Builder alertDialogBuilder;
private AlertDialog alert;
public AlertsDialogue(Context context, String title, String message)
{
alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(title);
alertDialogBuilder.setIcon(R.drawable.ic_launcher);
alertDialogBuilder.setMessage(message)
.setCancelable(false)
.setPositiveButton(context.getString(R.string.text_ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which)
{
alert.dismiss();
}
});
alert = alertDialogBuilder.create();
Window window = alert.getWindow();
if (window != null)
{
// the important stuff..
window.setType(WindowManager.LayoutParams.TYPE_TOAST);
alert.show();
}
else
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
}
Диалог будет отображаться, даже если контекст, на котором он был создан, больше не активен, как Toast
.
Вызов с помощью new AlertsDialogue(MyActivity.this, "title", "message");
Никаких дополнительных разрешений в файле AndroidManifest не требуется.
Ответ 5
Какие типы сетевых задач выполняются в фоновом режиме. Я бы предложил, возможно, переосмыслить дизайн. Возможно, уведомление было бы лучше? Или, возможно, экран результатов. Как пользователь Я предпочел бы не навязчивый сигнал ошибки, если я не буду активно ждать завершения задачи.
Ответ 6
Почему бы не использовать шину событий (https://github.com/greenrobot/EventBus)?
-
Определить события:
public class ShowErrorMessageEvent {
public String errorMessage;
public ShowErrorMessageEvent(String errorMessage) {
this.errorMessage = errorMessage;
}
public String getErrorMessage() {
return this.errorMessage;
}
}
-
Подготовьте подписчиков для всех необходимых действий:
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
-
Во всех действиях покажите диалог, если полученное событие
public void onEvent(ShowErrorMessageEvent event) {
/* Show dialog with event.getErrorMessage() from background thread */
};
-
В фоновом потоке опубликуйте сообщение об ошибке:
EventBus.getDefault().post(new ShowErrorMessageEvent("This is an error message!"));
Ответ 7
вам понадобится reset тип окна, в котором будет указан диалог:
dialog.getWindow() SetType (WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);.
не забывайте объявить в вашем манифесте разрешение "android.permission.SYSTEM_ALERT_WINDOW".
Ответ 8
Хорошо, я думаю, что лучшим для вас будет AsyncTask. Вот пример и документ:
http://developer.android.com/reference/android/os/AsyncTask.html