оповещение мгновенно после prompt приводит к блокировке пользовательского интерфейса в WebView (с помощью .setWebChromeClient(new WebChromeClient () и диалогового окна фрагмента)

#android #android-fragments #android-webview #android-alertdialog #dialogfragment

#Android #android-фрагменты #android-webview #android-alertdialog #dialogfragment

Вопрос:

У меня есть голый проект, только webview и реализация для оповещения и подсказки … каждый из них работает нормально сам по себе, но пользовательский интерфейс перестает отвечать, если приглашение находится непосредственно внутри alert: alert (приглашение («привет», «тест»));

Есть идеи о том, что может быть причиной этого? ниже приведены соответствующие части кода:

 public class MainActivity extends AppCompatActivity implements JSDialogFragment.JSDialogResultListener{
    private WebView m_webView;

    public void OnJsDialogFragmentPositive(Bundle args, Object cb) {
        Log.d("JSDialogFragment", "OnJsDialogFragmentPositive");
        jsDialogType dType = (jsDialogType)args.getSerializable("dType");
        if(null != dType amp;amp; null != cb) {
            if(JS_DIALOG_TYPE_ALERT == dType) {
                ((JsResult) cb).confirm();
            } else if(JS_DIALOG_TYPE_PROMPT == dType) {
                String value = args.getString("value");
                ((JsPromptResult) cb).confirm(null != value ? value : "");
            }
        }
    }

    public void OnJsDialogFragmentNegative(Bundle args, Object cb) {
        Log.d("JSDialogFragment", "OnJsDialogFragmentNegative");
    }

    m_webView = (WebView) findViewById(R.id.m_webView);
    m_webView.getSettings().setJavaScriptEnabled(true);

    m_webView.setWebChromeClient(new WebChromeClient() {

        // shared set up transaction code
        FragmentTransaction showJsTransactionInit() {
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            android.app.Fragment prev = getFragmentManager().findFragmentByTag("mytag");
            if (prev != null) ft.remove(prev);
                ft.addToBackStack(null);
                    return ft;
                }

            @Override
            public boolean onJsAlert(WebView view, String url, String message, final android.webkit.JsResult result) {
                FragmentTransaction ft = showJsTransactionInit(); 
                DialogFragment frag = JSDialogFragment.newInstanceAlert(message, result);
                frag.show(ft, "mytag");
                return true; // handled
            }

            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final android.webkit.JsPromptResult result) {
                FragmentTransaction ft = showJsTransactionInit();
                DialogFragment frag = JSDialogFragment.newInstancePrompt(message, result);
                frag.show(ft, "mytag");
                return true; // handled
            }
        });
  

и реализации JSDialogFragment, которая обрабатывает диалог:

 public class JSDialogFragment extends DialogFragment {
    interface JSDialogResultListener {
        void OnJsDialogFragmentPositive(Bundle obj, Object cb);
        void OnJsDialogFragmentNegative(Bundle obj, Object cb);
    }

    private Object mCB;

    public void setCallBack(Object cb) {
        mCB = cb;
    }

    // to init alert incase it may differ from how we show prompt
    public static DialogFragment newInstanceAlert(String message, Object cb) { 
        JSDialogFragment frag = new JSDialogFragment();
        frag.setCallBack(cb);
        Bundle args = new Bundle();
        args.putString("caption", message);
        args.putSerializable("dType", jsDialogType.JS_DIALOG_TYPE_ALERT); (JS_DIALOG_TYPE_ALERT is just an enum to distinguish between the types)
        frag.setArguments(args);
        return frag;
    }

    // to init prompt incase it may differ from how we show alert
    public static DialogFragment newInstancePrompt(String message, Object cb) { 
        JSDialogFragment frag = new JSDialogFragment();
        frag.setCallBack(cb);
        Bundle args = new Bundle();
        args.putString("caption", message);
        args.putSerializable("dType", jsDialogType.JS_DIALOG_TYPE_PROMPT);
        frag.setArguments(args);
        return frag;
    }

    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (!(activity instanceof JSDialogResultListener)) {
            throw new ClassCastException(activity.toString()   " must implement JSDialogResultListener");
        }
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final Bundle args = getArguments();
        String caption = args.getString("caption");
        jsDialogType jsDType = (jsDialogType)args.getSerializable("dType");
        if(null==jsDType) jsDType = jsDialogType.JS_DIALOG_TYPE_ALERT;

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) //, R.style.jsDialogsTheme)
                .setTitle(R.string.jsDialogTitle)
                .setMessage(caption);

        switch(jsDType) {
            case JS_DIALOG_TYPE_ALERT:
                builder.setPositiveButton(android.R.string.ok , new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ((JSDialogResultListener) getActivity()).OnJsDialogFragmentPositive(args, mCB);
                        dialog.dismiss();
                    }
                });
                break;


            case JS_DIALOG_TYPE_PROMPT:
                builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        args.putString("value", "waaaawwweeeee3");
                        ((JSDialogResultListener) getActivity()).OnJsDialogFragmentPositive(args, mCB);
                        dialog.dismiss();
                    }
                }).setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ((JSDialogResultListener) getActivity()).OnJsDialogFragmentNegative(args, mCB);
                        dialog.dismiss();
                    }
                });
                break;
        }

        return builder.create();
    }
}
  

Есть мысли, предложения?

Комментарии:

1. Я забыл включить последний вызов, который переходит на страницу с предупреждением (подсказка (…, …)): m_webView.loadUrl(» example.com » );

2. Похоже, что после удаления приглашения базовый код для удаления скрывает только диалоговое окно, которое будет удалено позже, НО затем начинается создание нового фрагмента для предупреждения, и в середине его создания исходное приглашение теперь удаляется внутренним кодом, и говорит, что в backstack ничего нет…. но оповещение уже совершило транзакцию и попыталось вызвать onshow (который к настоящему времени должен был добавить еще одну транзакцию?) как правильно дождаться завершения диалога, прежде чем запускать другой….