Android Socket + ObjectOutputStream работает неправильно

Я разрабатываю программу клиент/сервер, где клиент является устройством Android.

На сервере есть класс прослушивателя, который считывает объект из входного потока. Я создал клиентское программное обеспечение для другого КОМПЬЮТЕРА, которое отправляет небольшой объект по локальной сети. Компьютер-компьютер работает отлично, я прочитал объект и распечатал содержимое. Однако ТО ЖЕ ЖЕ код, перенесенный на Android (я его на всякий случай переписал), не работает. Я создаю объект (ЛЮБОЙ объект), который можно сериализовать, и отправляю его через ObjectOutputStream. Мой сервер, работающий на компьютере, подключается к устройству, но выдает исключение ClassNotFound, даже если я печатаю объект (у которого есть toString). Как я уже сказал, тот же код, работающий на другом КОМПЬЮТЕРЕ (в виде файла .jar), работает отлично.

Вот что действительно странно: если я отправлю логическое значение или строку (с устройства), оно сработает... это просто мои пользовательские объекты, которые не работают. Я предполагаю, что это будет работать для любого стандартного объекта Java.

Если вы обнаружите ошибку, имейте в виду, что код работает, но только с другого компьютера на мой компьютер... а не с устройства Android на компьютер. Если вы все же найдете еще одну вопиющую ошибку, то круто :)

ПРОГРАММА ДЛЯ ANDROID:

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();
        }
        
    }
}

Спасибо!!


person somanys21    schedule 19.10.2010    source источник


Ответы (1)


Я подозреваю, что формат сериализации Android может быть несовместим с форматом Java VM. Можете ли вы попробовать преобразовать свои объекты в XML или какой-либо другой текстовый формат?

person Purush Rudrakshala    schedule 19.10.2010
comment
Да, вы правы. Он работает только для примитивных типов... это объясняет, почему он работает со строками и т. д.... это действительно идиотизм. Есть ли способ легко преобразовать объект (с примитивными типами и массивом) в формат, который я могу отправить? - person somanys21; 19.10.2010
comment
Я обнаружил проблему. Странно, но процесс сериализации смотрит на то, в каком Package находится ваш исходный класс. Это просто поразило меня, это дало мне исключение ClassNotFoundException. Вот почему, предположим, мой проект Main Server имеет clas XXXX.java в пакете Extra. Мой тестовый клиент имеет его в пакете под названием Main. Это тот же класс XXXX.java, просто другой пакет. Процесс сериализации фактически учитывает местоположение пакета, а затем отправляет его. Я могу подтвердить это, потому что я сделал свое приложение для Android идентичным моему серверу с точки зрения управления пакетами, и это сработало! - person somanys21; 20.10.2010
comment
Да, имя пакета включено в полное имя класса. Одно и то же имя класса может существовать в разных пакетах. - person Purush Rudrakshala; 21.10.2010
comment
Невозможно понять, почему вы отметили этот ответ как правильный. Это не так. Вашей фактической проблемой было изменение имени пакета, которое укусило бы вас как в Java, так и в Android. - person user207421; 02.11.2020