2010-12-13 46 views
4

我正在开发一个面向组的网络应用程序。问题是,当我即将加入一个组时,它首先检查该组是否安全,如果是,则要求输入用户名和密码。获得组安全性可能需要几秒钟,因此我为整个过程创建了一个新线程。如果小组需要安全性,我想弹出一个对话框。我认为这可能与后台线程有关,他们可能无法弹出对话框......但问题是我需要在后台线程中检查组安全性,因为它需要一些时间。从非UI线程弹出对话框

希望任何人都可以拿出解决方案或任何方式来询问用户/只有当这个团队是安全的时候才通过。这里的后台线程:

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

凡showUserPasswordDialog做(mActivity是催生这个线程的活动):

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

} 

我得到这个异常:

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 

的XML布局文件是:

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

回答

6

你是正确的,你不能从后台线程执行UI操作。做到这一点的方法是使用已经实现的Handler来弹出对话框。因此,像:

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

那么你的run方法是:

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

你是正确的。后台线程无法弹出对话框。你需要在你的UI线程上使用Handler来为你弹出对话框。