Android Button内部运行线程崩溃

时间:2012-11-24 21:50:13

标签: android multithreading sockets button

谢谢我通过按钮

使用Toggled Value让它工作
public void onClick(View v) {
                               // TODO Auto-generated method stub

                             doit=1;
                             Log.e("ErrorButton","NextTime "+doit);
                           }
                       });  
                      if(doit==1)
                      {
                          Log.e("ErrorButton","If");
                      ////
                          out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true); 
                        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));                

                        out.println("Helloo");

                        while ((text = in.readLine()) != null) {
                            finall += text;
                            Log.e("Test","Final: "+finall);
                          if(text=="quit")
                          {
                              socket.close();
                          }
                      Log.e("ClientActivity", "After Read "+doit+" "+finall);
                     // in.close();

                       doit=0;
                       Log.e("ClientActivity", "After If "+doit);
                      } 

每当我点击按钮时代码执行其任务然后崩溃

继承我的安卓代码:

package com.example.socketclient;


import android.R.string;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.InputStream;
import java.io.OutputStreamWriter; 
import java.io.InputStreamReader;
import java.io.PrintWriter; 
import java.net.InetAddress; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import android.util.Log; 

public class SocketCode extends Activity {
    private boolean connected = false;
    //private Handler handler = new Handler();
    public TextView txt;
    protected SocketCore Conn;
    public Button b;
    public EditText TextToSend;
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_socket_code);
        b = (Button)findViewById(R.id.button1);
        txt = (TextView)findViewById(R.id.textView1);
        TextToSend = (EditText)findViewById(R.id.editText1);
        //Conn = new SocketCore(this,txt);

        Thread cThread = new Thread(new ClientThread());
        cThread.start();

    }
    public class ClientThread implements Runnable {
        Socket socket ;
String finall;
        public void run() {
            try {
                InetAddress serverAddr = InetAddress.getByName("192.168.0.150");
                Log.d("ClientActivity", "C: Connecting...");
                socket= new Socket(serverAddr,4444);
                connected = true;
                while (connected) {
                    try {
                        Log.d("ClientActivity", "C: Sending command.");

                       b.setOnClickListener(new View.OnClickListener() {

                           public void onClick(View v) {
                               // TODO Auto-generated method stub

                               ClientHandler("Hex");

                           }
                       });  




                            Log.d("ClientActivity", "C: Sent.");


                    } catch (Exception e) {
                        Log.e("ClientActivity", "S: Error", e);
                    }
                    Thread.sleep(2000);
                }
                socket.close();
                txt.setText("Closed Socket");
                Log.d("ClientActivity", "C: Closed.");
            } catch (Exception e) {
                Log.e("ClientActivity", "C: Error", e);
                connected = false;
            }
        }

        public void ClientHandler(String Send)
        {
            try{
              PrintWriter   out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
                       .getOutputStream())), true);
          out.println(Send);
           BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
           finall = in.readLine();

           txt.setText(finall);
            }
            catch(IOException e)
            {txt.setText("Exception");}
        }


    }

}

以下是错误日志:

11-24 23:44:12.920: E/AndroidRuntime(10046): FATAL EXCEPTION: main
11-24 23:44:12.920: E/AndroidRuntime(10046): android.os.NetworkOnMainThreadException
11-24 23:44:12.920: E/AndroidRuntime(10046):    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1118)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:163)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at libcore.io.IoBridge.recvfrom(IoBridge.java:513)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at java.io.InputStreamReader.read(InputStreamReader.java:244)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at java.io.BufferedReader.fillBuf(BufferedReader.java:130)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at java.io.BufferedReader.readLine(BufferedReader.java:354)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at com.example.socketclient.SocketCode$ClientThread.ClientHandler(SocketCode.java:103)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at com.example.socketclient.SocketCode$ClientThread$1.onClick(SocketCode.java:66)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at android.view.View.performClick(View.java:4211)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at android.view.View$PerformClick.run(View.java:17267)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at android.os.Handler.handleCallback(Handler.java:615)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at android.os.Handler.dispatchMessage(Handler.java:92)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at android.os.Looper.loop(Looper.java:137)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at android.app.ActivityThread.main(ActivityThread.java:4898)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at java.lang.reflect.Method.invokeNative(Native Method)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at java.lang.reflect.Method.invoke(Method.java:511)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
11-24 23:44:12.920: E/AndroidRuntime(10046):    at dalvik.system.NativeStart.main(Native Method)

注意:服务器端接受没有问题的连接也会在崩溃之前接受来自客户端的数据

4 个答案:

答案 0 :(得分:1)

根据this。应用程序尝试在其主线程上执行网络操作时引发的异常。

问题在于这一行

PrintWriter   out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
                   .getOutputStream())), true);

执行b.setOnClickListener时,您的View.OnClickListener()因此ClientHandler由UI线程而不是生成的thead执行。后来的UI线程尝试执行上述操作,其中包含socket.getOutputStream(),因此包含异常

这主要是因为Android工具包和许多其他工具包一样不是线程安全的。 UI Thread执行所有UI次操作。网络操作通常具有与之相关的延迟。如果Ui线程忙于做网络,它怎么能在屏幕上呈现任何东西?

答案 1 :(得分:1)

更改此部件并添加runOnUiThread:

runOnUiThread(new Runnable() 
{
    public void run() 
    {
        b.setOnClickListener(new View.OnClickListener() {...});
        // and also Logs
    }
});

答案 2 :(得分:0)

查看http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html。根据官方文档,如果您使用的是Honeycomb SDK或更高版本,则不应将网络操作放在主/ UI线程上。针对早期SDK版本的应用程序可以在其主要事件循环线程上进行网络连接,但是它非常不鼓励,因为它会阻止UI并导致ANR。

您需要使用后台线程或AsyncTask进行网络操作,以避免出现此异常。

作为一般规则,总是将耗时的任务放在后台线程或AsyncTask

答案 3 :(得分:0)

严格模式是用于检测UI线程中某些操作的开发人员工具。请阅读此内容以获取详细信息http://developer.android.com/reference/android/os/StrictMode.html

默认情况下,从Android 3.0版开始启用严格模式。