2010-12-13 3 views
4

Je développe une application réseau orientée groupe. La chose est que lorsque je suis sur le point de rejoindre un groupe, il vérifie d'abord si le groupe est sécurisé, et si oui, il demande un utilisateur et un mot de passe. Obtenir la sécurité du groupe peut prendre quelques secondes afin que je génère un nouveau thread pour l'ensemble du processus. J'aimerais faire apparaître une boîte de dialogue au cas où le groupe aurait besoin de sécurité. Je pense que cela peut avoir à faire avec les threads de fond, ils peuvent ne pas être en mesure de faire apparaître les dialogues ... Mais le fait est que je dois vérifier la sécurité du groupe dans le thread d'arrière-plan parce que cela prend un peu de temps.Création d'une boîte de dialogue à partir d'un thread non-interface utilisateur

Espérons que n'importe qui peut trouver la solution ou n'importe quel moyen de demander l'utilisateur/passer seulement quand le groupe est sécurisé. Voici le fil de fond:

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)); 
} 

Où showUserPasswordDialog fait (Mactivity est l'activité qui a donné naissance à ce fil):

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(); 

} 

Je reçois cette exception:

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 

La mise en page XML le fichier est:

<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" /> 

Répondre

6

Vous avez raison de ne pas pouvoir effectuer d'opérations d'interface utilisateur à partir d'un thread d'arrière-plan. La façon de le faire est d'utiliser le Handler que vous avez déjà implémenté pour faire apparaître la boîte de dialogue. Donc, quelque chose comme:

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; 
     } 
    } 
}; 

Ensuite, votre méthode d'exécution serait:

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)); 
    } 
} 
2

Vous avez raison. Les threads d'arrière-plan ne peuvent pas afficher de boîtes de dialogue. Ce dont vous avez besoin est un Handler sur votre thread UI pour faire apparaître la boîte de dialogue pour vous.

Questions connexes