Obtener un diálogo ANR cuando abra los vínculos de WebView en las pestañas personalizadas de Chrome. ¿Cómo depurar esto?

Quiero usar las pestañas personalizadas de Chrome para manejar correctamente URLs fuera de mi dominio. Aquí está el código

webView.setWebViewClient(new WebViewClient() { public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request){ String url = request.getUrl().toString(); if(url.startWith("http://my.domain.name")) return false; else{ CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); builder.setToolbarColor(getResources().getColor(R.color.colorPrimary)); builder.setStartAnimations(getActivity(), R.anim.slide_in_right, R.anim.slide_out_left); builder.setExitAnimations(getActivity(), R.anim.slide_in_left, R.anim.slide_out_right); Intent actionIntent = new Intent( getApplicationContext(), ActionBroadcastReceiver.class); actionIntent.setData(Uri.parse(url)); PendingIntent menuItemPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, actionIntent, 0); builder.addMenuItem(getString(R.string.action_share), menuItemPendingIntent); CustomTabsIntent customTabsIntent = builder.build(); customTabsIntent.launchUrl(getActivity(), Uri.parse(url)); return true; } } }); 

Sin embargo, cuando hago clic en las URL de fuera del dominio, de vez en cuando me dan el diálogo ANR y la interfaz de usuario de la aplicación está congelando.

Intento depurar los rastros del anr pero no encontré ningún hilo sospechoso. El archivo de trazas ANR es bastante largo, así que lo publicé aquí: https://gist.github.com/hoavt-54/42f1109c0619eed81e82a9a8d1128a6d

Si tiene alguna sugerencia sobre cómo depurar la aplicación o cómo entender el archivo de seguimiento, realmente apreciaría eso.

La regla de 5 segundos no es relevante – Incluso un segundo de bloqueo del hilo principal aparecerá al usuario como una aplicación bloqueada.

La cantidad de trabajo que el sistema hace en segundo plano y en primer plano para su aplicación todo el tiempo es enorme, y todo se está haciendo en el hilo principal. Así que cuando no onXyz() inmediato desde cualquier llamada ( onXyz() ) – el mundo entero está bloqueando esperando por ti, no se dibujará nada, no llegará ningún evento táctil, etc.

Así que nunca haga ninguna llamada de red en el hilo principal. Siempre causará ANR por lo menos en algunos dispositivos alguna vez, por ejemplo cuando su red está apagada.

Nunca haga ninguno de estos en el hilo principal:

  • Leer / escribir en el sistema de archivos local, incluyendo propiedades y bases de datos
  • Cálculos pesados
  • red
  • Bucles largos / ocupados de cualquier tipo

Todo lo anterior causará ANR al azar para los usuarios.

Le sugeriría que tome una ventaja de StrictMode atleast en el modo de depuración. Utilice debajo del código para obtener registros de cualquier problema que ralentiza su aplicación en el hilo principal.

 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectAll() .penaltyLog() .build()); 

Puede establecer diferentes sanciones –

 penaltyLog() // to print log penaltyDeath() // This will crash you App(so costly penalty) penaltyDialog() // Show alert when something went lazy on Main thread 

Hay mucho sobre https://developer.android.com/reference/android/os/StrictMode.html

Según su código, está reemplazando la URL de Webview para pasar a las pestañas personalizadas de cromo.

Según mi comprensión de webview da una devolución de llamada en el hilo de cromo, por lo que idealmente debería ejecutar su código en la actividad utilizando la devolución de llamada y el controlador con el hilo principal de la actividad.

  @Override public void retainOldWebView() { if (mmtWebViewPop != null) { mHandler.postDelayed(new Runnable() { @Override public void run() { if (mmtWebViewPop != null) { webViewFrameLayout.removeView(mmtWebViewPop); mmtWebViewPop = null; } //TODO: write your own implementation here } }, 100); } } 

Para depurar webview sugeriría verificar los registros con etiquetas de cromo o al hacer tales experimentos habilitar depuración remota

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { WebView.setWebContentsDebuggingEnabled(true); } 

Yo como desarrollador no querría mezclar la implementación de ambos en una sola actividad, incluso si yo quisiera, preferiría crear fragmentos separados para customChromeTabs y WebView y reemplazar fragmentos cuando sea necesario. Debido a que ambos funcionan como una entidad separada y no deben confundir la implementación de ambos.

Comparte el código o implementa algo como a continuación:

  1. Las peticiones de intercepción de WebViewActivity y si el patrón de url no coincide dan una devolución de llamada y comienzan ChromeTabActivity con url pasado en paquete de intenciones.
  2. ChromeTabActivity donde su código para customChromeTab debe estar presente y trabajar independientemente uno del otro y terminar de reanudar la vista web desde el lugar de la izquierda de.
  3. Pero nunca he utilizado ChromeTabActivity para los casos similares, tengo un caso de uso en el que fb y google login no funcionaban para mí, así que abrió lo mismo en otra webview en frameLayout, que está funcionando bien para mi usecases. Tan pronto como el pageload se termina llamo esta función.

      if (null != mmtWebView) { mmtWebView.setWebChromeClient(new WebChromeClientImpl(getApplicationContext())); } 

Clase WebChromeClientImpl extends WebChromeClient {

 private final Context appContext; public WebChromeClientImpl(Context appContext) { this.appContext = appContext; } @Override public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { mmtWebViewPop = new WebView(view.getContext()); mmtWebViewPop.setVerticalScrollBarEnabled(false); mmtWebViewPop.setHorizontalScrollBarEnabled(false); mmtWebViewPop.setWebViewClient(new WebViewClientImpl(appContext, null)); mmtWebViewPop.getSettings().setJavaScriptEnabled(true); mmtWebViewPop.setLayoutParams(new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); webViewFrameLayout.addView(mmtWebViewPop); WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; transport.setWebView(mmtWebViewPop); resultMsg.sendToTarget(); return true; } @Override public boolean onConsoleMessage(ConsoleMessage consoleMessage) { return super.onConsoleMessage(consoleMessage); } @Override public void onCloseWindow(WebView window) { super.onCloseWindow(window); retainOldWebView(); } 

}

  • Las pestañas personalizadas de Chrome no abren otras aplicaciones
  • Pestaña personalizada de cierre automático de cromo
  • La ficha personalizada de Chrome no vuelve a la aplicación
  • Las pestañas personalizadas de cromo piden múltiples navegadores para elegir
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.