我正在尝试使用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)
答案 0 :(得分:2)
你正在使用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);
}
}
});
}
答案 1 :(得分:0)
Toast.makeText(MainActivity.this, "Sent "+sentence, Toast.LENGTH_LONG).show();
//...
Toast.makeText(MainActivity.this, "Received "+sentence, Toast.LENGTH_LONG).show();
您不能在后台线程中使用Toast
,只能在UI线程中使用。
好像你可以使用android.util.Log
类从后台线程获得这样的调试输出。
答案 2 :(得分:0)
您没有以适当的方式处理异常。试试这个
catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {};