Как я могу показать DialogFragment в обработчике?

Я хотел бы показать пользователю сообщение, если что-то пошло не так в потоке сетевого общения.

По этой причине необходимо показать диалог из обработчика.

Это правильный путь?, потому что я не нашел способа, как получить FragmentManager в классе обработчика.

class ErrorMessageHandler extends Handler
{
    @Override
    public void handleMessage(Message msg) 
    {
        super.handleMessage(msg);

        AlertDialogFragment dialog = new AlertDialogFragment((String) msg.getData().get("MESSAGE"));

        dialog.show(FragmentManager, TAG)

     }  

}

person Chris    schedule 28.01.2013    source источник


Ответы (3)


Через некоторое время я нашел действительно простое решение:

Вы должны реализовать этот метод в своем классе службы:

void alert(String message) 
{
    AlertDialog.Builder alertDialog = new AlertDialog.Builder(getApplication());
    alertDialog.setMessage(message);
    alertDialog.setNeutralButton("OK", null);
    alertDialog.create().show();
}

Иногда это может быть очень просто :)

person Chris    schedule 08.02.2013

Почему бы не отобразить простое всплывающее сообщение со строкой сообщения об ошибке, которое вы получили (или любое другое сообщение, которое вы хотели бы установить)

Может быть, я неправильно понял ваш вопрос, но для меня это кажется логичным. Я использую простые тосты для отображения сообщений об ошибках сети или что-то в этом роде.

Toast.makeText(context, text, duration).show();

После ваших комментариев можно предложить другое решение:

При ошибке отображать диалоговое окно подтверждения (AlertDialog) и давать пользователю возможность выбрать, хочет ли он прочитать справку:

    new AlertDialog.Builder(this)
    .setTitle("Network Error")
    .setMessage(An error occured, would you like to read the help section ...)
    .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
          // Open here the new view with the help message etc.
        }

    })
    .setNegativeButton(R.string.no, null)
    .show();

Так что в этом случае вы не будете сразу надоедать пользователю длинным текстом справки. Сначала вы сообщите ему, что произошла ошибка, и если он захочет прочитать справку о том, как решить проблему, он может подтвердить и пойти дальше. Это может быть полезно для дизайна вашего приложения, потому что обычно пользователи не любят читать большое количество текста, особенно некоторые справочные инструкции.

В конце вы можете отобразить свой Alertdialog с коротким сообщением об ошибке и предложить проверить справку. Там вы можете пригласить его проверить, включено ли его интернет-соединение, объяснить, как включить, предложить кнопку, чтобы перейти непосредственно на страницу вашего телефона, где он может включить / отключить Wi-Fi и т. д.

person Miloš    schedule 28.01.2013
comment
Я думал об этом раньше, но я хотел бы дать пользователю несколько советов, как он может решить проблему (например, включить Wlan). Короткий: текст, который я хочу показать, слишком длинный для тоста. - person Chris; 28.01.2013
comment
Что вы можете сделать: Показать диалоговое окно подтверждения с сообщением об ошибке и вопросом, хочет ли пользователь прочитать справку. Если он нажмет «ОК», вы сможете отобразить другой вид с соответствующей помощью. Если он нажмет «нет» (или «отмена»), то просто закройте диалог. - person Miloš; 28.01.2013
comment
Кажется, это хороший способ! Я попробовал это, но, к сожалению, мое приложение вылетает, если я это делаю. Я пытаюсь открыть это в сервисе. Это тоже возможно, или это причина сбоя? - person Chris; 28.01.2013
comment
Можно показать диалог из службы: см. здесь stackoverflow.com/questions/4131619/ С каким сбоем вы столкнулись, можете ли вы дать некоторые журналы. Или просто отобразите диалог из основного потока, если это возможно. Это будет намного проще. - person Miloš; 28.01.2013
comment
Это ошибка: 01-28 15:01:33.725: E/AndroidRuntime(3732): android.view.WindowManager$BadTokenException: невозможно добавить окно - нулевой токен не для приложения 01-28 15:01:33.725 : E/AndroidRuntime(3732): в android.view.ViewRootImpl.setView(ViewRootImpl.java:571) 01-28 15:01:33.725: E/AndroidRuntime(3732): в android.view.WindowManagerGlobal.addView(WindowManagerGlobal. java:246) 01-28 15:01:33.725: E/AndroidRuntime(3732): в android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69) - person Chris; 28.01.2013
comment
Проблема в этом случае заключается в том, что вы пытаетесь создать Dialog с контекстом приложения. Диалог должен быть создан с контекстом Activity: MyActivity.this, где MyActivity — это имя вашей активности. - person Miloš; 28.01.2013
comment
Вы не можете ссылаться в службе на действие (таким образом). Там появляется ошибка «нет вложенного экземпляра». Я работаю над решением, включая мессенджер. Я надеюсь, что это работает. Я опубликую свое решение, если оно у меня есть. - person Chris; 28.01.2013

Итак... Я нашел способ решить эту проблему, но это не идеальный способ (дополнительная информация находится внизу этого ответа).

Сначала создайте мессенджер:

private Messenger AlertDialogMessenger = new Messenger(new AlertDialogMessageHandler());

Второй обработчик, который показывает это диалоговое окно:

class AlertDialogMessageHandler extends Handler
{

    @Override
    public void handleMessage(Message msg) 
    {
        super.handleMessage(msg);

        AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).create();

        dialog.setTitle("Attention");
        dialog.setMessage((CharSequence) msg.getData().get("MESSAGE"));
        dialog.setOnCancelListener(new DialogInterface.OnCancelListener() 
        {               
            @Override
            public void onCancel(DialogInterface dialog) 
            {
                //Do something
            }
        });
        dialog.setButton(DialogInterface.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() 
        {               
            @Override
            public void onClick(DialogInterface dialog, int which) 
            {
                //Do something
                dialog.dismiss();
            }
        });

        dialog.show();                              
    }

}

И тогда вам останется только отправить мессенджер на сервис:

Intent intent = new Intent(this,MyService.class);
intent.putExtra(MainActivity.EXTRA_FROM_SERVICE_MESSENGER, this.AlertDialogMessenger);
this.bindService(intent, this.conn, Context.BIND_AUTO_CREATE);

На Сервисе вы должны поймать мессенджера:

@Override
public IBinder onBind(Intent intent) 
{       
    this.AlertDialoMessenger = intent.getParcelableExtra(MainActivity.EXTRA_FROM_SERVICE_MESSENGER);
    return null;
}

И затем вы можете отобразить диалог, отправив сообщение:

Message msg = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("MESSAGE", "This is a test message");

msg.setData(bundle);
try 
{
    AlertDialoMessenger.send(msg);
} 
catch (RemoteException e1) 
{
    e1.printStackTrace();
}

Вот и все.

К сожалению, я не могу использовать это в своем случае, потому что это работает только в том случае, если у вас есть только одно действие (в данном случае MainActivity). Потому что диалог будет отображаться только в этом действии.

В моем проекте у меня больше Activity и поэтому нет смысла использовать это.

Я решил показать короткое всплывающее сообщение, например «Ошибка сети», и предоставить страницу справки в меню «Параметры».

Спасибо Милошу! и я надеюсь, что этот код иногда помогает кому-то :)

person Chris    schedule 29.01.2013