7

嘿傢伙。我正在開發一個客戶端/服務器程序,客戶端是Android設備。 服務器有一個從輸入流中讀取對象的監聽器類。我爲其他計算機創建了一個客戶端軟件,通過本地網絡發送一個小對象。 電腦到電腦的工作很好,我讀對象並打印內容。然而,代碼移植到android(我重寫它以防萬一)不起作用的代碼。我構造了一個可序列化的對象(ANY對象),並通過ObjectOutputStream發送它。我在計算機上運行的服務器確實連接到設備,但它給了我一個ClassNotFound異常,即使即時打印對象(其中有一個toString)。正如我所說,運行在另一臺計算機上的相同代碼(作爲.jar文件)可以很好地工作。Android Socket + ObjectOutputStream無法正常工作

這是真的很奇怪的部分,如果我發送布爾或字符串(從設備)它的作品....它只是我的「自定義」的對象,不。我認爲這將適用於任何「標準」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(); 
     } 

    } 
} 

謝謝!

回答

4

我懷疑Android的序列化格式可能與Java VM的格式不兼容。你可以嘗試將你的對象轉換爲XML或其他文本格式嗎?

+0

是的,你說得對。它只適用於原始類型......這將解釋爲什麼它可以與String等一起工作......這實在是愚蠢的。有什麼方法可以輕鬆地將對象(包括原始類型和數組列表)轉換爲我可以發送的格式? – somanys21 2010-10-19 02:52:43

+4

**我發現了這個問題**這很奇怪,但是序列化過程會查看您的原始類是什麼** Package **。它只是打我,它給了我一個ClassNotFoundException。這是爲什麼,假設我的主服務器項目在包「Extra」中包含了類XXXX.java。我的測試客戶端使用名爲「Main」的包。它與XXXX.java類相同,只是一個不同的包。序列化過程實際上會考慮包的位置,然後將其發送。我可以證實這一點,因爲我使我的android應用程序在包管理方面與我的服務器完全相同,並且工作正常! – somanys21 2010-10-19 23:45:20

+1

是的,包名稱包含在完整的類名中。相同的類名可以存在於不同的包中。 – 2010-10-20 22:48:35