Hacer estallar un diálogo de un hilo no perteneciente a la interfaz de usuario

Estoy desarrollando una aplicación de red, que está orientada a grupos. La cosa es que cuando estoy a punto de unirse a un grupo, primero verifica si el grupo es seguro, y si es así, pide el usuario y la contraseña. Obtener seguridad de grupo puede tardar un par de segundos, así que generar un nuevo hilo para todo el proceso. Me gustaría hacer aparecer un diálogo en caso de que el grupo requiera seguridad. Estoy pensando que puede tener que ver con los hilos de fondo, no puede ser capaz de pop-up Diálogos … Pero la cosa es que tengo que comprobar la seguridad del grupo en el hilo de fondo porque se necesita un poco de tiempo.

Espero que cualquiera pueda llegar a la solución o cualquier forma de preguntar al usuario / pasar sólo cuando el grupo está seguro. Aquí está el hilo de fondo:

public void run() { secInf = mGroupId.getSecurityInformation(); if (secInf.getAdmissionLevel() == CreateGroupDialog.PRIVATE_KEY_ACCESS) { showUserPasswordDialog(); } else { mService.joinGroup(mGroupId); // Notifies handler to dismiss ProgresDialog and start activity mHandler.sendMessage(Message.obtain(mHandler, GroupsActivity.JOIN_SUCCESSFUL)); } 

Donde showUserPasswordDialog hace (mActivity es la actividad que generó este hilo):

  private void showUserPasswordDialog() { AlertDialog dialog; // add this to your code // This example shows how to add a custom layout to an AlertDialog LayoutInflater factory = LayoutInflater.from(mActivity); final View textEntryView = factory.inflate( R.layout.alert_dialog_text_entry, null); AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); builder.setIcon(R.drawable.alert_dialog_icon); builder.setTitle(R.string.ask_user_password); builder.setView(textEntryView); builder.setPositiveButton(R.string.ok_text, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { String userName = ((EditText) mActivity .findViewById(R.id.username_edit_alert_dialog)) .getText().toString(); String password = ((EditText) mActivity .findViewById(R.id.password_edit_alert_dialog)) .getText().toString(); Credentials cred = new CredentialsL1(userName, password); mSmeppService.joinGroup(mGroupId, cred); mHandler.sendMessage(Message.obtain(mHandler, GroupsActivity.JOIN_SUCCESSFUL)); }); builder.setNegativeButton(R.string.cancel_text, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { dialog.cancel(); mHandler.sendMessage(Message.obtain(mHandler, GroupsActivity.DISMISS_PROGRESS_DIALOG)); } }); dialog = builder.create(); /* I found this somewhere, but didn't work either */ // Window window = dialog.getWindow(); // WindowManager.LayoutParams lp = window.getAttributes(); // lp.token = textEntryView.getWindowToken(); // lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; // window.setAttributes(lp); // window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); dialog.show(); } 

Estoy recibiendo esta excepción:

 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): FATAL EXCEPTION: Thread-38 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): android.view.InflateException: Binary XML file line #17: Error inflating class android.widget.EditText 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.view.LayoutInflater.createView(LayoutInflater.java:513) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:563) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.view.LayoutInflater.rInflate(LayoutInflater.java:618) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.view.LayoutInflater.inflate(LayoutInflater.java:407) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.view.LayoutInflater.inflate(LayoutInflater.java:320) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.view.LayoutInflater.inflate(LayoutInflater.java:276) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at org.pfc.threads.GroupJoinerThread.showUserPasswordDialog(GroupJoinerThread.java:76) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at org.pfc.threads.GroupJoinerThread.run(GroupJoinerThread.java:52) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): Caused by: java.lang.reflect.InvocationTargetException 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.widget.EditText.<init>(EditText.java:51) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at java.lang.reflect.Constructor.constructNative(Native Method) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at java.lang.reflect.Constructor.newInstance(Constructor.java:446) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.view.LayoutInflater.createView(LayoutInflater.java:500) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): ... 8 more 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.os.Handler.<init>(Handler.java:121) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.text.method.MetaKeyKeyListener$MetaKeyDropbackHandler.<init>(MetaKeyKeyListener.java:605) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.text.method.MetaKeyKeyListener.<init>(MetaKeyKeyListener.java:96) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.text.method.BaseKeyListener.<init>(BaseKeyListener.java:25) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.text.method.TextKeyListener.<init>(TextKeyListener.java:66) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.text.method.TextKeyListener.getInstance(TextKeyListener.java:83) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.widget.TextView.<init>(TextView.java:806) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): at android.widget.EditText.<init>(EditText.java:55) 12-13 19:18:31.823: ERROR/AndroidRuntime(1702): ... 12 more 

El archivo de diseño XML es:

  <EditText android:id="@+id/username_edit_alert_dialog" android:enabled="false" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_marginLeft="20dip" android:layout_marginRight="20dip" android:scrollHorizontally="true" android:autoText="false" android:capitalize="none" android:gravity="fill_horizontal" android:textAppearance="?android:attr/textAppearanceMedium" /> <!-- Password --> <TextView android:id="@+id/password_view" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_marginLeft="20dip" android:layout_marginRight="20dip" android:text="@string/password_view_text" android:gravity="left" android:textAppearance="?android:attr/textAppearanceMedium" /> <EditText android:id="@+id/password_edit_alert_dialog" android:enabled="false" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_marginLeft="20dip" android:layout_marginRight="20dip" android:scrollHorizontally="true" android:autoText="false" android:capitalize="none" android:gravity="fill_horizontal" android:password="true" android:textAppearance="?android:attr/textAppearanceMedium" /> 

Está correcto que no puede realizar operaciones de interfaz de usuario desde un subproceso de fondo. La forma de hacerlo es usar el Handler que ya ha implementado para abrir el diálogo. Así que algo como:

 private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch(msg.what){ case GroupsActivity.DISMISS_PROGRESS_DIALOG: //your existing dismiss code break; case GroupsActivity.CREATE_PROGRESS_DIALOG: //create the dialog break; } } }; 

Entonces su método de ejecución sería:

 public void run() { secInf = mGroupId.getSecurityInformation(); if (secInf.getAdmissionLevel() == CreateGroupDialog.PRIVATE_KEY_ACCESS) { // do stuff mHandler.sendMessage(Message.obtain(mHandler, GroupsActivity.CREATE_PROGRESS_DIALOG)); // do more stuff } else { mService.joinGroup(mGroupId); // Notifies handler to dismiss ProgresDialog and start activity mHandler.sendMessage(Message.obtain(mHandler, GroupsActivity.JOIN_SUCCESSFUL)); } } 

Estás en lo correcto. Los subprocesos de fondo no pueden mostrar diálogos. Lo que necesitas es un Handler en tu interfaz de usuario para que aparezca el diálogo para ti.

  • Cómo mostrar el icono apropiado en el cuadro de diálogo
  • Android alertdialog personalizado diferente en ICS y Gingerbread
  • AlertDialog con EditText con el correo electrónico InputType - Android
  • Eliminar el borde del diálogo de alerta con tema personalizado
  • Android: especificación del tema personalizado para el diálogo personalizado AlertDialog.Builder envuelve el contenido en un diálogo
  • Cómo cerrar un cuadro de diálogo en Android mediante programación?
  • Diálogo de alerta simple de Android
  • cómo obtener un título de alerta multilínea en Android
  • ¿Cómo mostrar el diálogo de alerta en cualquier actividad en la aplicación Android?
  • Android: cambia el texto del botón positivo de un AlertDialog
  • error: requestFeature () debe ser llamado antes de agregar contenido - Todavía no funcionará
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.