2011-10-12 79 views
0

我正在做一個局域網聊天應用程序bewteen android(客戶端)和pc(java_server)都在eclipse上運行。問題是android非常無法使用,並且經常崩潰但是,它在我的java版本的客戶端和服務器上運行得非常好。請幫忙!Android:「線程退出與未捕獲的異常(組= 0x4001d800)」

有我的代碼:

package android.client; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import java.util.PriorityQueue; 
import java.util.Queue; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.ListView; 
import android.widget.TextView; 
import android.widget.Toast; 

公共類Chat_client擴展活動實現Runnable {

private Socket socket = null; 
//private Thread thread = null; 
private DataOutputStream requestOut; 
private int clientID; 
private String playerName; 
private DataInputStream requestIn; 
private EditText text; 
private ListView msgView; 
private ArrayAdapter<String> msgArrayAdapter; 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    try { 
     socket = new Socket("192.168.2.2", 5558); 
     Toast.makeText(this, 
       "Connected to " + this.socket.getInetAddress(), 
       Toast.LENGTH_LONG + 10).show(); 
     this.playerName = "wei"; 
     this.clientID = socket.getLocalPort(); 
     requestOut = new DataOutputStream(socket.getOutputStream()); 
     requestIn = new DataInputStream(socket.getInputStream()); 
     text = (EditText) findViewById(R.id.editText1);// black textfield 
     msgArrayAdapter = new ArrayAdapter<String>(this, R.layout.message); 
     msgView = (ListView) findViewById(R.id.in); 
     msgView.setAdapter(this.msgArrayAdapter); 
     new Thread(this).start(); 
    } catch (UnknownHostException uke) { 
     Toast.makeText(this, "Host unknown:" + uke.getMessage(), 
       Toast.LENGTH_LONG).show(); 
    } catch (IOException ioe) { 
     Toast.makeText(this, "Unexpected exception: " + ioe.getMessage(), 
       Toast.LENGTH_LONG).show(); 
    } 
} 


// This method is called at button click because we assigned the name to the 
// "On Click property" of the button 
public void myClickHandler(View v) { 
    Toast.makeText(this, "sending", Toast.LENGTH_LONG/2).show(); 
    TextView view = (TextView) findViewById(R.id.editText1); 
    String message = view.getText().toString(); 
    text.setText(""); 
    Packet p; 
    if (message.startsWith("#")) { 
     p = new Packet(playerName, 1, clientID,message.substring(1, message.length())); 
    } 
    else 
     p = new Packet(playerName, -1, clientID,message); 
    try { 
     this.requestOut.writeUTF(p.convertToSendFormat()); 
     requestOut.flush(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    msgArrayAdapter.add("Me: <" + message + ">"); 

} 

public void run() { 
    while (true) { 
     String r; 
     try { 
      r = this.requestIn.readUTF(); 
      if (r != null) { 
       Packet p = convert(r); 
       if (p != null) 
        handle(p); 
      } 
     } catch (IOException ioe) { 
      System.exit(0); 
     } 
    } 
} 
private synchronized Packet convert(String n) { 
    String data = ""; 
    String[] p = n.split(" ", 4); 
    if (p.length < 4) 
     return null; 
    data = p[3]; 
    return new Packet(p[0], Integer.parseInt(p[1]), Integer.parseInt(p[2]), 
      data); 
} 
public synchronized void handle(Packet re) { 
    if (re.getChannelID() == clientID){ 
     msgArrayAdapter.add("Me" + re.toString());} 
    else{ 
     msgArrayAdapter.add(re.getSenderName() + re.toString()); 
     } 
    } 

}

package android.client; 

import java.io.Serializable; 
/** 
* This class handles the networking packet 
* @author Wei 
*/ 
public class Packet implements Serializable { 
    private static final long serialVersionUID = 1509287973845358190L; 
    private String senderName; 
    private int actionID; 
    private long channelID; 
    private int sent; 
    private String data; 

    public Packet(String name, int actionID,int cid, String action2) { 
     this.senderName=name; 
     this.channelID = cid; 
     this.actionID = actionID; 
     this.data = action2; 
     this.sent = -1; 
    } 

    public String getSenderName(){ 
     return this.senderName; 
    } 
    public int getActionID(){ 
     return this.actionID; 
    } 
    public String getData(){ 
     return this.data; 
    } 

    protected void setChannelID(int id){ 
     this.channelID = id; 
    } 
    public long getChannelID(){ 
     return this.channelID; 
    } 

    protected void setSent(boolean b){ 
     if(b) 
     this.sent = 1; 
     else 
      this.sent=-1; 
    } 
    protected int checkSent(){ 
     return this.sent; 
    } 

    public String toString(){ 
     return (" : "+this.data); 
    } 
    public void addTimeStamp(String time){ 
     this.data+=time; 
    } 
    public String convertToSendFormat(){ 
     return this.senderName+" "+this.actionID+" "+this.channelID+" "+this.data; 
    } 
    public int getFlag() { 
     return 0; 
    } 

    public void setFlag(boolean response) { 
    } 


} 

有日誌:

10-12 12:54:22.763: DEBUG/AndroidRuntime(360): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<< 
10-12 12:54:22.763: DEBUG/AndroidRuntime(360): CheckJNI is ON 
10-12 12:54:22.895: DEBUG/AndroidRuntime(360): --- registering native functions --- 
10-12 12:54:23.513: INFO/ActivityManager(59): Force stopping package android.client uid=10033 
10-12 12:54:23.513: INFO/ActivityManager(59): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=android.client/.Chat_client } 
10-12 12:54:23.633: DEBUG/AndroidRuntime(360): Shutting down VM 
10-12 12:54:23.645: INFO/ActivityManager(59): Start proc android.client for activity android.client/.Chat_client: pid=366 uid=10033 gids={3003} 
10-12 12:54:23.664: DEBUG/jdwp(360): Got wake-up signal, bailing out of select 
10-12 12:54:23.664: DEBUG/dalvikvm(360): Debugger has detached; object registry had 1 entries 
10-12 12:54:24.024: WARN/ActivityThread(366): Application android.client is waiting for the debugger on port 8100... 
10-12 12:54:24.044: INFO/System.out(366): Sending WAIT chunk 
10-12 12:54:24.054: INFO/dalvikvm(366): Debugger is active 
10-12 12:54:24.244: INFO/System.out(366): Debugger has connected 
10-12 12:54:24.244: INFO/System.out(366): waiting for debugger to settle... 
10-12 12:54:24.444: INFO/System.out(366): waiting for debugger to settle... 
10-12 12:54:24.644: INFO/System.out(366): waiting for debugger to settle... 
10-12 12:54:24.843: INFO/System.out(366): waiting for debugger to settle... 
10-12 12:54:25.053: INFO/System.out(366): waiting for debugger to settle... 
10-12 12:54:25.254: INFO/System.out(366): waiting for debugger to settle... 
10-12 12:54:25.454: INFO/System.out(366): waiting for debugger to settle... 
10-12 12:54:25.654: INFO/System.out(366): waiting for debugger to settle... 
10-12 12:54:25.866: INFO/System.out(366): waiting for debugger to settle... 
10-12 12:54:26.075: INFO/System.out(366): waiting for debugger to settle... 
10-12 12:54:26.284: INFO/System.out(366): debugger has settled (1322) 
10-12 12:54:27.544: INFO/ActivityManager(59): Displayed activity android.client/.Chat_client: 3912 ms (total 3912 ms) 
10-12 12:54:33.313: DEBUG/dalvikvm(124): GC_EXPLICIT freed 642 objects/35976 bytes in 203ms 
10-12 12:54:38.335: DEBUG/dalvikvm(225): GC_EXPLICIT freed 152 objects/11144 bytes in 177ms 
10-12 12:54:43.384: DEBUG/dalvikvm(261): GC_EXPLICIT freed 249 objects/11840 bytes in 205ms 
10-12 12:55:14.583: WARN/KeyCharacterMap(108): No keyboard for id 0 
10-12 12:55:14.583: WARN/KeyCharacterMap(108): Using default keymap: /system/usr/keychars/qwerty.kcm.bin 
10-12 12:55:37.295: WARN/dalvikvm(366): threadid=7: thread exiting with uncaught exception (group=0x4001d800) 
+0

您的應用可能在設備旋轉時/之後崩潰了嗎? – Knickedi

+0

不確定,因爲我正在使用虛擬設備(模擬器) – user991482

回答

3

我已經解決了prolbem增加一個處理方法:

private Handler myHandler = new Handler(){ 
    @Override 
    public void handleMessage(Message msg){ 
     String str= (String) msg.obj; 
     if(msg.what==1){ 
      msgArrayAdapter.add(str); 
     } 
    } 
};` 

,當然我不知道爲什麼這個作品,但它只是works.lol,再次感謝您的幫助@Knickedi

0

這裏將是乾淨的方式來做到這一點(我不知道這是否解決您的實際問題)。但是從另一個線程更新適配器數組並不是一個好主意。而且,如果您的設備正在旋轉,而不是使用已經運行的另一個線程創建另一個線程。當您更改數組(消息)時,請不要忘記刷新您的列表,方法是致電msgArrayAdapter.notifyDataSetChanged()。這裏的藍圖和想法...

您的活動。它將在配置變化作出反應和實際銷燬的正確方法:

private MessagePollThread thread; 

public void onCreate(Bundle b) { 
    super.onCreate(b); 

    thread = (MessagePollThread) getLastNonConfigurationInstance(); 

    if (thread == null) { 
     // activity runs for first time - create thread 
     thread = new MessagePollThread(); 
     thread.activity = this; 
     thread.start(); 
    } else { 
     // just update the thread with the new activity - it's started already 
     thread.activity = this; 
    } 
} 

public Object onRetainNonConfigurationInstance() { 
    // retain the thread for configuration changes e.g. orientation change (see onCreate) 
    return thread; 

    // you could also retain your old received messages here 
    // just return new Object [] {thread, messageArray} and handle that in onCreate 
} 

public void onDestroy() { 
    super.onDestroy(); 

    if (isFinishing()) { 
     // activity is about to destroy itself 
     // shutdown the running thread 
     thread.run = false; 
     thread.interrupt(); // break the sleep 
    } 
} 

實際線程負責處理請求(如內部靜態類的活動):

private static class MessagePollThread extends Thread { 

    public volatile boolean run = true; 
    public volatile Chat_client activity; 
    private Handler handler = new Handler(); 

    public void run() { 

     // setup socket connection here 

     while (run) { 
      try { 
       // you should/could also process send requests here 
       // just use a synchronized list to check in your 
       // activity (e.g. activity.messages) for new messages in queue 
       // http://developer.android.com/reference/java/util/Collections.html#synchronizedList%28java.util.List%3CT%3E%29 

       final String r = this.requestIn.readUTF(); 

       if (!run) { 
        // the thread could be shut down meanwhile 
        continue; 
       } 

       handler.post(new Runnable() { 
        public void run() { 
         activity.handleResult(r); 
        } 
       } 
      } catch (IOException e) { 
       handler.post(new Runnable() { 
        public void run() { 
         activity.finish(); 
        } 
       } 
      } 

      try { 
       // sleep for a while 
       // non stop polling will drain your battery very fast 
       sleep(1000); 
      } catch (InterruptException e) { 
       // do nothing, just proceed 
      } 
     } 

     // destroy socket connection here 
    } 
} 
+0

仍然有問題(隨機),無論如何謝謝你的幫助。如果我不使用ArrayAdapter,請問prolbem會緩慢嗎?或者有沒有辦法不使用線程來做到這一點? – user991482

+0

它應該無關緊要。強烈建議使用線程來完成網絡任務,在這種情況下甚至有必要。您應該確保您修改了與UI線程上的UI相關的數據。對不起,我真的不知道在這一刻什麼是造成你的例外... – Knickedi

相關問題