簡體   English   中英

Android和Java程序之間的套接字編程問題

[英]Issue With Socket Programming Between Android and Java Program

我正在嘗試使用Socket編程交換數據。 我使用Android應用程序作為客戶端和服務器作為Java程序,我能夠建立連接,只要按下發送按鈕,應用程序就會異常停止。 我附上了我的代碼

活動Java代碼:

package com.example.communidemo;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.io.DataOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;

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

public class MainActivity extends Activity implements OnClickListener {


    private EditText ipBox, msgbox;
    private ToggleButton connBtn;
    private Button sendBtn;
    private TextView txtView;
    private Socket client;
    private DataOutputStream out;
    private BufferedReader in;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setUpAllViews(R.layout.activity_main);  
    }

    void setUpAllViews(int layout)
    {
     setContentView(layout);
     ipBox = (EditText) findViewById(R.id.ipBox);
     msgbox = (EditText) findViewById(R.id.msgbox);
     connBtn = (ToggleButton) findViewById(R.id.connect);
     sendBtn = (Button) findViewById(R.id.send);
     txtView = (TextView) findViewById(R.id.text);

     connBtn.setOnClickListener(this);     
    }


    @Override
    public void onClick(View v)
    {       
     Toast.makeText(this, ipBox.getText(), Toast.LENGTH_LONG).show();
     Toast.makeText(this, v.getId(), Toast.LENGTH_LONG).show();
     switch(v.getId())
     {
     case R.id.connect:
         if(connBtn.isChecked())
         {
             Toast.makeText(this, "Enabling", Toast.LENGTH_LONG).show();
             enableConnection();
         }
         else
         {
             Toast.makeText(this, "Disabling", Toast.LENGTH_LONG).show();
             disableConnection();
         }
         break;
     case R.id.send:
         sendDataOverCommunication();
         break;
     }     
    }

    private void setValues(int id, boolean value)    
    {
     switch(id)
     {
     case R.id.ipBox: ipBox.setEnabled(value); break;
     case R.id.msgbox: msgbox.setEnabled(value); break;
     case R.id.send: sendBtn.setEnabled(value); break;
     case R.id.connect: connBtn.setChecked(value); break;
     }
    }
    private void setUpIOStreams()
    {
     try
     {

     Thread thread = new Thread(new Runnable(){
            @Override
            public void run() {
                try {
                    InetAddress addr = InetAddress.getByName(ipBox.getText().toString());
                    client = new Socket(addr,5800);
                    out = new DataOutputStream(client.getOutputStream());
                    in = new BufferedReader(new InputStreamReader(client.getInputStream()));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        thread.start(); 
     /*
     InetAddress addr = InetAddress.getByName(ipBox.getText().toString());
     client = new Socket(addr,5800);
     out = new DataOutputStream(client.getOutputStream());
     in = new BufferedReader(new InputStreamReader(client.getInputStream()));*/
     }
     catch(Exception e)
     {
      Toast.makeText(this, "Connection Problem", Toast.LENGTH_LONG).show();
      Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
     }
    }

    private void enableConnection()
    {
      try
      {
       setUpIOStreams();                         
       setValues(R.id.connect,true);
       setValues(R.id.send,true);
       setValues(R.id.ipBox,false);
       setValues(R.id.msgbox,true);
       sendBtn.setOnClickListener(this);
      }
      catch(Exception e)
      {
       setValues(R.id.connect,false);
       Toast.makeText(this, "Enable Problem", Toast.LENGTH_LONG).show();
       Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
      }
    }

    private void disableConnection()
    {
     if(client != null)
     {
      try
       {     
        client.close();
       }
      catch(Exception e)
       {
        Toast.makeText(this, "Disable Problem", Toast.LENGTH_LONG).show();  
        Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();     
       }
      setValues(R.id.connect,false);
      setValues(R.id.ipBox,true);
      setValues(R.id.msgbox,false);
      setValues(R.id.send,false);         
    }
     else
     {
      setValues(R.id.connect,false);     
     }
    }

    private void sendDataOverCommunication()
    {
     Thread thread = new Thread(new Runnable(){
         @Override
         public void run(){                  
      try
      {                           
              if(client.isClosed())
                  setUpIOStreams();
              String sentence = msgbox.getText().toString();
              out.writeBytes(sentence);
              Toast.makeText(MainActivity.this, "Sent "+sentence, Toast.LENGTH_LONG).show();
              out.flush();
              out.close();
              sentence = in.readLine();
              msgbox.setText(sentence);
              Toast.makeText(MainActivity.this, "Received "+sentence, Toast.LENGTH_LONG).show();
              client.close();                                   
      }      
     catch(IOException e)
     {
      Toast.makeText(MainActivity.this, "Problem in sending", Toast.LENGTH_LONG).show();     
      Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
      setValues(R.id.ipBox,true);
      setValues(R.id.connect,false);
      setValues(R.id.send,false);
      setValues(R.id.msgbox,false);
     }}}
      );
     thread.start();
    }    
}

XML布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/linearlayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

    <EditText
       android:id="@+id/ipBox"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:layout_weight="1"
       android:hint="@string/ip_address"
        >
       <requestFocus /> 
    </EditText>

    <ToggleButton
        android:id="@+id/connect"
        android:onClick="onclick"
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:textOn="@string/disconnected"
        android:textOff="@string/connected"
        >
    </ToggleButton>    

</LinearLayout>

<LinearLayout
    android:id="@+id/linearlayout2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >
    <EditText
        android:id="@+id/msgbox"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:enabled="false" 
        >
    </EditText>

    <Button
        android:id="@+id/send"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="@string/send"
        android:enabled="false"
        >      
    </Button>

</LinearLayout>

    <TextView
        android:id="@+id/text"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/connect_prompt"/>

</LinearLayout>

字符串資源:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">CommuniDemo</string>
    <string name="hello_world">Hello world!</string>
    <string name="connect_prompt">Start the client by pressing the connect button</string>
    <string name="send_prompt">Enter your message and press the send button</string>
    <string name="ip_address">IP Address</string>enter code here
    <string name="message_prompt">Say something</string>
    <string name="device_ip">Device\'s IP Address: </string>
    <string name="server_ip">Server\'s IP Address: </string>
    <string name="connected">Connect</string>
    <string name="disconnected">Disconnect</string>
    <string name="send">Send</string>


</resources>

清單文件:

 <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.communidemo"
        android:versionCode="1"
        android:versionName="1.0" >

        <uses-permission android:name="android.permission.INTERNET"/> 
        <uses-sdk
            android:minSdkVersion="8"
            android:targetSdkVersion="16" />


        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme">      
            <activity
                android:name="com.example.communidemo.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

                    <category android:name="android.intent.category.LAUNCHER" `enter code here`/>
                </intent-filter>
            </activity>
        </application>enter code here

    </manifest>

請幫我解決一下這個。 我附加了來自LOG-CAT的錯誤。

``03-01 09:16:32.468: E/Trace(1852): error opening trace file: No such file or directory (2)
03-01 09:17:39.288: E/AndroidRuntime(1852): FATAL EXCEPTION: Thread-156
03-01 09:17:39.288: E/AndroidRuntime(1852): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
03-01 09:17:39.288: E/AndroidRuntime(1852):     at android.os.Handler.<init>(Handler.java:197)
03-01 09:17:39.288: E/AndroidRuntime(1852):     at android.os.Handler.<init>(Handler.java:111)
03-01 09:17:39.288: E/AndroidRuntime(1852):     at android.widget.Toast$TN.<init>(Toast.java:324)
03-01 09:17:39.288: E/AndroidRuntime(1852):     at android.widget.Toast.<init>(Toast.java:91)
03-01 09:17:39.288: E/AndroidRuntime(1852):     at android.widget.Toast.makeText(Toast.java:238)
03-01 09:17:39.288: E/AndroidRuntime(1852):     at com.example.communidemo.MainActivity$2.run(MainActivity.java:171)
03-01 09:17:39.288: E/AndroidRuntime(1852):     at java.lang.Thread.run(Thread.java:856)

您正在使用Toast和setText進行UI工作,這樣就可以解決問題了。 UI在runOnUiThread下工作

private void sendDataOverCommunication()
    {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try
                {                           
                    if(client.isClosed())
                        setUpIOStreams();
                    String sentence = msgbox.getText().toString();
                    out.writeBytes(sentence);
                    Toast.makeText(MainActivity.this, "Sent "+sentence, Toast.LENGTH_LONG).show();
                    out.flush();
                    out.close();
                    sentence = in.readLine();
                    msgbox.setText(sentence);
                    Toast.makeText(MainActivity.this, "Received "+sentence, Toast.LENGTH_LONG).show();
                    client.close();                                   
                }      
                catch(IOException e)
                {
                    Toast.makeText(MainActivity.this, "Problem in sending", Toast.LENGTH_LONG).show();     
                    Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
                    setValues(R.id.ipBox,true);
                    setValues(R.id.connect,false);
                    setValues(R.id.send,false);
                    setValues(R.id.msgbox,false);
                }
            }
        });
    }    
Toast.makeText(MainActivity.this, "Sent "+sentence, Toast.LENGTH_LONG).show();
//...
Toast.makeText(MainActivity.this, "Received "+sentence, Toast.LENGTH_LONG).show();

您不能在后台線程中使用Toast ,只能在UI線程中使用Toast

好像你可以使用android.util.Log類從你的后台線程獲得這樣的調試輸出。

您沒有以適當的方式處理異常。 嘗試這個

catch (UnknownHostException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
} catch (Exception e) {};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM