1. 程式人生 > >Android中傳送序列化物件出現的ClassNotFoundException解決辦法

Android中傳送序列化物件出現的ClassNotFoundException解決辦法

http://waynehu16.iteye.com/blog/1530760

最近在做課程設計,老師要求是基於Android上的wifi通訊的,之前沒事的時候寫過一個套接字程式設計的,完成了一個類似於聊天工具的功能。於是就想著改改,湊合著用用交上去。沒想到在寫的時候發現了一個很讓人摸不著頭腦的異常:ClassNotFoundException。

先說一下編碼之前的思路,我想在PC上做服務端,在Android上做客戶端,同時,在兩端封裝了RequestObject,ResponseObject等序列化的物件,用於在服務端和客戶端之前傳遞請求和響應物件(通過ObjectInputStream和ObjectOutputStream),如下專案結構,可是在傳送物件的時候發現了RequestObject出現了ClassNotFoundException,然後就直接無語中,明明服務端和客戶端的RequestObject等用於傳遞進物件流的物件都是一模一樣的,沒道理找不到類啊。


經過一番嘗試未果,索性把兩個.java檔案中唯一不一樣的一行改掉,即為import xxx.xxx.xxx,我將兩個專案中有關傳遞資訊的model包的包名改為一樣的。果然測試通過了,可能識別這種物件的時候,包名也是一個必要的因素吧。

問題雖然解決了,但是總覺得不方便,因為如果服務端這邊的序列化物件要更改資訊,勢必客戶端這邊的物件也要改,同一次修改缺要改兩遍資訊,而且還很容易混淆,於是我又做了如下處理:新建了一個專案,用於儲存有關任何需要傳遞的序列化物件,將這個專案匯出.jar檔案,再作為外部jar檔案匯入至客戶端和服務端的專案裡,這樣就省去了很多工作,在正式往專案裡新增操作之前,做了一個demo測試。


建立3個專案,分別是Android客戶端,需要傳遞的資料,PC的服務端。分別編寫好各個程式碼

服務端程式碼  收藏程式碼
  1. /**  
  2.  * 2012-5-15  
  3.  * By WayneHu  
  4.  */  
  5. package pc.test;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8. import java.io.ObjectInputStream;  
  9. import java.net.ServerSocket;  
  10. import java.net.Socket;  
  11. import object.RequestObject;  
  12. public class MyServer {  
  13.     public static void main(String[] args) {  
  14.         try {  
  15.             ServerSocket server = new ServerSocket(10000);  
  16.             while (true) {  
  17.                 System.out.println("Server is waiting...");  
  18.                 Socket socket = server.accept();  
  19.                 InputStream is;  
  20.                 is = socket.getInputStream();  
  21.                 ObjectInputStream ois = new ObjectInputStream(is);  
  22.                 RequestObject request = (RequestObject) ois.readObject();  
  23.                 System.out.println(request.getRequestClass());  
  24.                 ois.close();  
  25.                 is.close();  
  26.                 socket.close();  
  27.             }  
  28.         } catch (IOException e) {  
  29.             e.printStackTrace();  
  30.         } catch (ClassNotFoundException e) {  
  31.             // TODO Auto-generated catch block  
  32.             e.printStackTrace();  
  33.         }  
  34.     }  
  35. }  
客戶端程式碼  收藏程式碼
  1. package android.test;  
  2. import java.io.IOException;  
  3. import java.io.ObjectOutputStream;  
  4. import java.io.OutputStream;  
  5. import java.net.Socket;  
  6. import java.net.UnknownHostException;  
  7. import object.RequestObject;  
  8. import android.app.Activity;  
  9. import android.os.Bundle;  
  10. import android.view.View;  
  11. import android.widget.EditText;  
  12. public class AndroidClientActivity extends Activity {  
  13.     /** Called when the activity is first created. */  
  14.     private EditText et_input;  
  15.     private String input;  
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.         et_input = (EditText) findViewById(R.id.input);  
  21.     }  
  22.     public void onClick_send(View view) {  
  23.         input = et_input.getText().toString();  
  24.         RequestObject request = new RequestObject(1, input, null);  
  25.         try {  
  26.             Socket socket = new Socket("10.0.2.2"10000);  
  27.             OutputStream os = socket.getOutputStream();  
  28.             ObjectOutputStream oos = new ObjectOutputStream(os);  
  29.             oos.writeObject(request);  
  30.             oos.close();  
  31.             os.close();  
  32.             socket.close();  
  33.         } catch (UnknownHostException e) {  
  34.             // TODO Auto-generated catch block  
  35.             e.printStackTrace();  
  36.         } catch (IOException e) {  
  37.             // TODO Auto-generated catch block  
  38.             e.printStackTrace();  
  39.         }  
  40.     }  
  41. }  

這裡多說一句,在模擬器上的客戶端,給PC上的服務端建立連線的時候,IP應為10.0.2.2

Xml程式碼  收藏程式碼
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.     <TextView  
  7.         android:layout_width="fill_parent"  
  8.         android:layout_height="wrap_content"  
  9.         android:text="@string/hello" />  
  10.     <EditText  
  11.         android:id="@+id/input"  
  12.         android:layout_width="fill_parent"  
  13.         android:layout_height="wrap_content" />  
  14.     <Button  
  15.         android:layout_width="fill_parent"  
  16.         android:layout_height="wrap_content"  
  17.         android:onClick="onClick_send"  
  18.         android:text="SEND" />  
  19. </LinearLayout>  
用於傳遞的物件程式碼  收藏程式碼
  1. /**  
  2.  * 2012-5-15  
  3.  * By WayneHu  
  4.  */  
  5. package object;  
  6. import java.io.Serializable;  
  7. public class RequestObject implements Serializable {  
  8.     public static final int LOGIN_REQUEST = 1;  
  9.     public static final int REGIST_REQUEST = 2;  
  10.     public static final int CHAT_REQUEST = 3;  
  11.     private int requestType;  
  12.     private String requestClass;  
  13.     private Object requestBody;  
  14.     /**  
  15.      * @param requestType 請求型別  
  16.      * @param requestClass 請求類名  
  17.      * @param requestBody 請求物件  
  18.      */  
  19.     public RequestObject(int requestType, String requestClass,  
  20.             Object requestBody) {  
  21.         super();  
  22.         this.requestType = requestType;  
  23.         this.requestClass = requestClass;  
  24.         this.requestBody = requestBody;  
  25.     }  
  26.     /**  
  27.      * @return the requestType  
  28.      */  
  29.     public int getRequestType() {  
  30.         return requestType;  
  31.     }  
  32.     /**  
  33.      * @param requestType the requestType to set  
  34.      */  
  35.     public void setRequestType(int requestType) {  
  36.         this.requestType = requestType;  
  37.     }  
  38.     /**  
  39.      * @return the requestClass  
  40.      */  
  41.     public String getRequestClass() {  
  42.         return requestClass;  
  43.     }  
  44.     /**  
  45.      * @param requestClass the requestClass to set  
  46.      */  
  47.     public void setRequestClass(String requestClass) {  
  48.         this.requestClass = requestClass;  
  49.     }  
  50.     /**  
  51.      * @return the requestBody  
  52.      */  
  53.     public Object getRequestBody() {  
  54.         return requestBody;  
  55.     }  
  56.     /**  
  57.      * @param requestBody the requestBody to set  
  58.      */  
  59.     public void setRequestBody(Object requestBody) {  
  60.         this.requestBody = requestBody;  
  61.     }  
  62. }  

 然後在儲存傳遞物件的專案那裡匯出JAR檔案,如下圖,然後分別在客戶端專案和服務端專案右鍵選擇構建路徑-配置構建路徑-新增外部JAR,選擇之前匯出的JAR檔案,即可。


測試效果如下:



 

第一次寫這麼長的部落格,用來記錄自己學習路程的同時,也希望能幫助遇到同樣問題的朋友。寫的不好的地方歡迎朋友們提意見,寫的有錯的地方也希望各位大神能夠不吝賜教。還是那句話,文明看帖,歡迎輕拍。

歡迎轉載,轉載請註明出處: