Java Android Socket+;ObjectOutputStream工作不正常
我正在开发一个客户端/服务器程序,其中客户端是安卓设备 服务器有一个从输入流读取对象的侦听器类。我为另一台计算机创建了一个客户端软件,它通过本地网络发送一个小对象计算机对计算机工作得非常好,我阅读了对象并打印了内容。然而,移植到android上的相同代码(我只是为了以防万一重写了它)不起作用。我构造了一个可序列化的对象(任意对象),并通过ObjectOutputStream发送它。我在计算机上运行的服务器确实连接到设备,但它给我一个ClassNotFound异常,即使我正在打印对象(它有一个toString)。正如我所说,在另一台计算机上运行的相同代码(作为.jar文件)工作得非常好 这里是一个非常奇怪的部分,如果我发送一个布尔值或字符串(从设备发送),它会工作……这只是我的“自定义”对象不工作。我认为这适用于任何“标准”java对象。 如果你发现了错误,请记住代码确实有效,但只能从另一台计算机到我的计算机…而不能从Android设备到计算机。如果你还发现了另一个明显的错误,那就太棒了:) ANDROID程序:Java Android Socket+;ObjectOutputStream工作不正常,java,android,sockets,objectoutputstream,classnotfoundexception,Java,Android,Sockets,Objectoutputstream,Classnotfoundexception,我正在开发一个客户端/服务器程序,其中客户端是安卓设备 服务器有一个从输入流读取对象的侦听器类。我为另一台计算机创建了一个客户端软件,它通过本地网络发送一个小对象计算机对计算机工作得非常好,我阅读了对象并打印了内容。然而,移植到android上的相同代码(我只是为了以防万一重写了它)不起作用。我构造了一个可序列化的对象(任意对象),并通过ObjectOutputStream发送它。我在计算机上运行的服务器确实连接到设备,但它给我一个ClassNotFound异常,即使我正在打印对象(它有一个to
package WaitDroid.Main;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class main extends Activity {
/** Called when the activity is first created. */
private Button a;
private TextView x;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.a = (Button) this.findViewById(R.id.Send_Order);
this.x = (TextView) this.findViewById(R.id.TextView1);
this.a.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
sendMenu();
}
});
}
private void sendMenu()
{
try
{
InetAddress serverAddress = InetAddress.getByName("128.153.180.109");
Socket socket = new Socket(serverAddress, 4322);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
TestObject send = new TestObject("Hi", 32);
out.writeObject(send);
out.close();
socket.close();
}
catch(Exception e)
{
x.setText(e.getMessage());
}
}
}
package WaitDroid.Main;
import java.io.Serializable;
public class TestObject implements Serializable
{
private String name;
private int number;
public TestObject(String a, int b)
{
name = a;
number = b;
}
public String toString()
{
return name +" - "+ number;
}
}
package Main;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectInputStream.GetField;
import java.net.ServerSocket;
import java.net.Socket;
import Order.Order;
public class ServerListener extends Thread
{
public void run() {
try {
ServerSocket listen = new ServerSocket(4322);
while (true) {
Socket socket = listen.accept();
String clientInetAddr = socket.getInetAddress().toString();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
System.out.println("Connected to: " + clientInetAddr);
try
{
Object a = in.readObject();
System.out.println(a);
//RestaurantServerRun.n.server.addOrder(a);
}
catch(IOException e)
{
System.err.println(e.getMessage());
}
in.close();
socket.close();
}
}
catch (Exception e) {
System.err.println("Error in run()");
e.printStackTrace();
}
}
}
测试对象:
package WaitDroid.Main;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class main extends Activity {
/** Called when the activity is first created. */
private Button a;
private TextView x;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.a = (Button) this.findViewById(R.id.Send_Order);
this.x = (TextView) this.findViewById(R.id.TextView1);
this.a.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
sendMenu();
}
});
}
private void sendMenu()
{
try
{
InetAddress serverAddress = InetAddress.getByName("128.153.180.109");
Socket socket = new Socket(serverAddress, 4322);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
TestObject send = new TestObject("Hi", 32);
out.writeObject(send);
out.close();
socket.close();
}
catch(Exception e)
{
x.setText(e.getMessage());
}
}
}
package WaitDroid.Main;
import java.io.Serializable;
public class TestObject implements Serializable
{
private String name;
private int number;
public TestObject(String a, int b)
{
name = a;
number = b;
}
public String toString()
{
return name +" - "+ number;
}
}
package Main;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectInputStream.GetField;
import java.net.ServerSocket;
import java.net.Socket;
import Order.Order;
public class ServerListener extends Thread
{
public void run() {
try {
ServerSocket listen = new ServerSocket(4322);
while (true) {
Socket socket = listen.accept();
String clientInetAddr = socket.getInetAddress().toString();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
System.out.println("Connected to: " + clientInetAddr);
try
{
Object a = in.readObject();
System.out.println(a);
//RestaurantServerRun.n.server.addOrder(a);
}
catch(IOException e)
{
System.err.println(e.getMessage());
}
in.close();
socket.close();
}
}
catch (Exception e) {
System.err.println("Error in run()");
e.printStackTrace();
}
}
}
服务器侦听器:
package WaitDroid.Main;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class main extends Activity {
/** Called when the activity is first created. */
private Button a;
private TextView x;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.a = (Button) this.findViewById(R.id.Send_Order);
this.x = (TextView) this.findViewById(R.id.TextView1);
this.a.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
sendMenu();
}
});
}
private void sendMenu()
{
try
{
InetAddress serverAddress = InetAddress.getByName("128.153.180.109");
Socket socket = new Socket(serverAddress, 4322);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
TestObject send = new TestObject("Hi", 32);
out.writeObject(send);
out.close();
socket.close();
}
catch(Exception e)
{
x.setText(e.getMessage());
}
}
}
package WaitDroid.Main;
import java.io.Serializable;
public class TestObject implements Serializable
{
private String name;
private int number;
public TestObject(String a, int b)
{
name = a;
number = b;
}
public String toString()
{
return name +" - "+ number;
}
}
package Main;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectInputStream.GetField;
import java.net.ServerSocket;
import java.net.Socket;
import Order.Order;
public class ServerListener extends Thread
{
public void run() {
try {
ServerSocket listen = new ServerSocket(4322);
while (true) {
Socket socket = listen.accept();
String clientInetAddr = socket.getInetAddress().toString();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
System.out.println("Connected to: " + clientInetAddr);
try
{
Object a = in.readObject();
System.out.println(a);
//RestaurantServerRun.n.server.addOrder(a);
}
catch(IOException e)
{
System.err.println(e.getMessage());
}
in.close();
socket.close();
}
}
catch (Exception e) {
System.err.println("Error in run()");
e.printStackTrace();
}
}
}
谢谢 我怀疑Android的序列化格式可能与Java VM的格式不兼容。您能尝试将对象转换为XML或其他文本格式吗?是的,您是对的。它只适用于基本类型…这就解释了为什么它适用于字符串等…这真是愚蠢。有什么方法可以轻松地将对象(带有基元类型和arraylist)转换为我可以发送的格式吗?我发现问题很奇怪,但序列化过程会查看原始类所在的包。它击中了我,给了我一个ClassNotFoundException。下面是为什么,假设我的主服务器项目在包“Extra”中有clas XXXX.java。我的测试客户机将它放在一个名为“Main”的包中。它是同一个XXXX.java类,只是一个不同的包。序列化过程实际上考虑了包的位置,然后将其发送到其他服务器。我可以确认这一点,因为我使我的android应用程序在包管理方面与我的服务器完全相同,而且它工作正常!!是的,包名包含在完整类名中。相同的类名可以存在于不同的包中。不可能理解为什么您将此答案标记为正确。事实并非如此。您的实际问题是更改包名,这会让您在Java和Android中都感到痛苦。