1

Parcel을 사용하는 방법에 대한 기사를 많이 읽었지만 앱에서 사용했지만 작동하지 않습니다. 방금 Sockets을 사용하여 컴퓨터에 연결할 수있는 활동을 만들었습니다. 소켓 OutputStreamjava.io.PrintWriter을 열었으며 다른 액티비티 (첫 번째 액티비티의 버튼을 터치하면 열림)가이 PrintWriter을 사용합니다. 나는 여기서 실수하고있는 것은 PrintWriter object을 복제하지 않는 것이라고 생각한다. 나는 그것을 복제하는 방법을 모른다. 되는 다음 활동의 코드 여기 Android : Parcel을 사용하여 한 활동에서 다른 활동으로 개체를 전달하는 데 어려움이 있습니다.

public class TestActivity extends Activity implements OnClickListener 
{ 
    String ip; 
    int port; 
    Socket soc; 
    PrintWriter writer; // this works fine here 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     ip = ""; 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     // Connect button click handler (you can skip this part) 
     Button connect = (Button)findViewById(R.id.connectBTN); 
     connect.setOnClickListener(new View.OnClickListener() 
     { 
      public void onClick(View v) 
      { 
       EditText TB = (EditText)findViewById(R.id.ipTB); 
       ip = TB.getText().toString(); 
       TB = (EditText)findViewById(R.id.portTB); 
       port = Integer.parseInt(TB.getText().toString()); 
       try { 
       soc = new Socket(ip,port); 
       showDialog("Connected successfully!"); 
       writer = new PrintWriter(soc.getOutputStream(), true); 
       } 
       catch(Exception er) 
       { 
        showDialog("Couldn't connect.\n"+er.getMessage()); 
        soc = null; 
       } 
      } 
     }); 

     findViewById(R.id.controlmouseBTN).setOnClickListener(this); 

     // disconnect click handler (skip this part too) 
     Button disconnectBTN = (Button)findViewById(R.id.disconnectBTN); 
     disconnectBTN.setOnClickListener(new View.OnClickListener() 
     { 
      public void onClick(View v) 
      { 
       try 
       { 
        if(soc.isConnected()) soc.close(); 
        writer.close(); 
       } 
       catch(Exception er) { showDialog("Couldn't close connection.\n"+er.getMessage()); } 
      } 
     }); 

    } 

    @Override 
    public void onClick(View v) // here is the erroneous part 
    { 
     //if(soc == null || !soc.isConnected()) { showDialog("Not connected to any computer."); return; } 
     //if(writer == null) return; 
     Intent i = new Intent(getApplicationContext(), PCController.class); 
     Intermediate inter = new Intermediate(); // this is the Parcelable class I've created 
     //inter.set(new String("hello")); (I tried sending a string, which worked fine, just to confirm that my Parcelable class is working) 
     inter.set(writer); 
     i.putExtra("printer", inter); 
     startActivity(i); 
    } 

} 

이 중간체 Parcelable 클래스 다음

import android.os.*; 

public class Intermediate implements Parcelable 
{ 
    Object ob; 

    public Intermediate() 
    {} 

    public Intermediate(Parcel parcel) 
    { 
     this.ob = parcel.readValue(Intermediate.class.getClassLoader()); 
    } 

    public void set(Object o) 
    { this.ob = o; } 

    public Object get() 
    { 
     return ob; 
    } 

    @Override 
    public int describeContents() 
    { return 0; } 

    @Override 
    public void writeToParcel(Parcel dest, int flags) 
    { 
     dest.writeValue(this.ob); 
    } 

    // I don't understand this part though! Just copy pasted and modified the ClassName 

    public static final Intermediate.Creator<Intermediate> CREATOR = new Intermediate.Creator<Intermediate>() { 
     public Intermediate createFromParcel(Parcel in) { 
      return new Intermediate(in); } 

     public Intermediate[] newArray(int size) { 
      return new Intermediate[size]; } 
    }; 
} 

의 코드는 다음과 같습니다

여기에 (내가 몇 가지 불필요한 기능을 삭제했습니다) 1 차 활동입니다 해고 됐어. 내가 연결하지 않는 경우

PrintWriter writer; 
    String s; // for testing purpose 
    Swipe swipe; // a SurfaceView 

    public void onCreate(Bundle bundle) 
    { 
     super.onCreate(bundle); 
     swipe = new Swipe(this); 
     swipe.setOnTouchListener(this); 
     setContentView(swipe); 
     Intent i = getIntent(); 
     Intermediate ob = (Intermediate)i.getParcelableExtra("printer"); 
     writer = (PrintWriter)ob.get(); 
     //s = (String)ob.get(); 
     //showDialog(s); // this shows up the string I had sent, which means the string is getting passed. 
    } 

자 (즉, writer가 null) (난 단지 중요한 부분을 게시 한)와 나는 다음 활동, 아무 일도 발생하지 않습니다 (오류없이)를 시작합니다. 하지만 (writer이 아닌) 연결하고 다음 활동을 시작하면 MAIN 활동이 단순히 중단됩니다. 오류 메시지를 기록하는 데 신경 쓰지 않았습니다. 왜냐하면 제가 여기서 정말로 잘못된 것을하고 있기 때문입니다.

도움이 될 것입니다. 감사!

편집 : 여기 스택 추적

10-26 00:37:55.445: WARN/System.err(251): java.lang.RuntimeException: Parcel: unable to marshal value [email protected] 
10-26 00:37:55.474: WARN/System.err(251):  at android.os.Parcel.writeValue(Parcel.java:1087) 
10-26 00:37:55.484: WARN/System.err(251):  at android.test.Intermediate.writeToParcel(Intermediate.java:33) 
10-26 00:37:55.484: WARN/System.err(251):  at android.os.Parcel.writeParcelable(Parcel.java:1106) 
10-26 00:37:55.494: WARN/System.err(251):  at android.os.Parcel.writeValue(Parcel.java:1029) 
10-26 00:37:55.504: WARN/System.err(251):  at android.os.Parcel.writeMapInternal(Parcel.java:469) 
10-26 00:37:55.514: WARN/System.err(251):  at android.os.Bundle.writeToParcel(Bundle.java:1445) 
10-26 00:37:55.524: WARN/System.err(251):  at android.os.Parcel.writeBundle(Parcel.java:483) 
10-26 00:37:55.534: WARN/System.err(251):  at android.content.Intent.writeToParcel(Intent.java:5237) 
10-26 00:37:55.544: WARN/System.err(251):  at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:1204) 
10-26 00:37:55.554: WARN/System.err(251):  at android.app.Instrumentation.execStartActivity(Instrumentation.java:1373) 
10-26 00:37:55.564: WARN/System.err(251):  at android.app.Activity.startActivityForResult(Activity.java:2749) 
10-26 00:37:55.574: WARN/System.err(251):  at android.app.Activity.startActivity(Activity.java:2855) 
10-26 00:37:55.584: WARN/System.err(251):  at android.test.TestActivity.onClick(TestActivity.java:80) 
10-26 00:37:55.594: WARN/System.err(251):  at android.view.View.performClick(View.java:2364) 
10-26 00:37:55.606: WARN/System.err(251):  at android.view.View.onTouchEvent(View.java:4179) 
10-26 00:37:55.615: WARN/System.err(251):  at android.widget.TextView.onTouchEvent(TextView.java:6541) 
10-26 00:37:55.624: WARN/System.err(251):  at android.view.View.dispatchTouchEvent(View.java:3709) 
10-26 00:37:55.634: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:37:55.634: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:37:55.644: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:37:55.656: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:37:55.664: WARN/System.err(251):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1659) 
10-26 00:37:55.674: WARN/System.err(251):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107) 
10-26 00:37:55.684: WARN/System.err(251):  at android.app.Activity.dispatchTouchEvent(Activity.java:2061) 
10-26 00:37:55.694: WARN/System.err(251):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1643) 
10-26 00:37:55.705: WARN/System.err(251):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1691) 
10-26 00:37:55.714: WARN/System.err(251):  at android.os.Handler.dispatchMessage(Handler.java:99) 
10-26 00:37:55.724: WARN/System.err(251):  at android.os.Looper.loop(Looper.java:123) 
10-26 00:37:55.734: WARN/System.err(251):  at android.app.ActivityThread.main(ActivityThread.java:4363) 
10-26 00:37:55.744: WARN/System.err(251):  at java.lang.reflect.Method.invokeNative(Native Method) 
10-26 00:37:55.754: WARN/System.err(251):  at java.lang.reflect.Method.invoke(Method.java:521) 
10-26 00:37:55.764: WARN/System.err(251):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
10-26 00:37:55.774: WARN/System.err(251):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
10-26 00:37:55.785: WARN/System.err(251):  at dalvik.system.NativeStart.main(Native Method) 
10-26 00:38:02.424: WARN/System.err(251): java.lang.RuntimeException: Parcel: unable to marshal value [email protected] 
10-26 00:38:02.454: WARN/System.err(251):  at android.os.Parcel.writeValue(Parcel.java:1087) 
10-26 00:38:02.454: WARN/System.err(251):  at android.test.Intermediate.writeToParcel(Intermediate.java:33) 
10-26 00:38:02.464: WARN/System.err(251):  at android.os.Parcel.writeParcelable(Parcel.java:1106) 
10-26 00:38:02.474: WARN/System.err(251):  at android.os.Parcel.writeValue(Parcel.java:1029) 
10-26 00:38:02.486: WARN/System.err(251):  at android.os.Parcel.writeMapInternal(Parcel.java:469) 
10-26 00:38:02.494: WARN/System.err(251):  at android.os.Bundle.writeToParcel(Bundle.java:1445) 
10-26 00:38:02.505: WARN/System.err(251):  at android.os.Parcel.writeBundle(Parcel.java:483) 
10-26 00:38:02.514: WARN/System.err(251):  at android.content.Intent.writeToParcel(Intent.java:5237) 
10-26 00:38:02.524: WARN/System.err(251):  at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:1204) 
10-26 00:38:02.534: WARN/System.err(251):  at android.app.Instrumentation.execStartActivity(Instrumentation.java:1373) 
10-26 00:38:02.544: WARN/System.err(251):  at android.app.Activity.startActivityForResult(Activity.java:2749) 
10-26 00:38:02.554: WARN/System.err(251):  at android.app.Activity.startActivity(Activity.java:2855) 
10-26 00:38:02.554: WARN/System.err(251):  at android.test.TestActivity.onClick(TestActivity.java:80) 
10-26 00:38:02.564: WARN/System.err(251):  at android.view.View.performClick(View.java:2364) 
10-26 00:38:02.574: WARN/System.err(251):  at android.view.View.onTouchEvent(View.java:4179) 
10-26 00:38:02.584: WARN/System.err(251):  at android.widget.TextView.onTouchEvent(TextView.java:6541) 
10-26 00:38:02.594: WARN/System.err(251):  at android.view.View.dispatchTouchEvent(View.java:3709) 
10-26 00:38:02.604: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:38:02.614: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:38:02.625: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:38:02.634: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:38:02.644: WARN/System.err(251):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1659) 
10-26 00:38:02.654: WARN/System.err(251):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107) 
10-26 00:38:02.664: WARN/System.err(251):  at android.app.Activity.dispatchTouchEvent(Activity.java:2061) 
10-26 00:38:02.674: WARN/System.err(251):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1643) 
10-26 00:38:02.684: WARN/System.err(251):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1691) 
10-26 00:38:02.694: WARN/System.err(251):  at android.os.Handler.dispatchMessage(Handler.java:99) 
10-26 00:38:02.704: WARN/System.err(251):  at android.os.Looper.loop(Looper.java:123) 
10-26 00:38:02.714: WARN/System.err(251):  at android.app.ActivityThread.main(ActivityThread.java:4363) 
10-26 00:38:02.714: WARN/System.err(251):  at java.lang.reflect.Method.invokeNative(Native Method) 
10-26 00:38:02.724: WARN/System.err(251):  at java.lang.reflect.Method.invoke(Method.java:521) 
10-26 00:38:02.734: WARN/System.err(251):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
10-26 00:38:02.744: WARN/System.err(251):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
10-26 00:38:02.754: WARN/System.err(251):  at dalvik.system.NativeStart.main(Native Method) 
+0

예외 스택 추적을 게시하면 문제의 맨 아래로 갈 수 있습니다. – Craigy

+0

좋아, 할거야 – Rushil

+1

맨 끝의 예외를 살펴보면 마샬의 가치가없는 것처럼 보인다. – Rushil

답변

3

당신은 여기에 더 큰 문제가 생겼어요 예외입니다. 소포를 사용하여 활동간에 물건을 전달하지 않아야합니다. 안드로이드 문서별로 :

소포는 범용 직렬화 메커니즘이 아닙니다. 이 클래스 (및 임의의 객체를 Parcel에 배치하기위한 해당 Parcelable API)는 고성능 IPC 전송으로 설계되었습니다. 따라서 Parcel 데이터를 영구 저장소에 저장하는 것은 적절하지 않습니다. Parcel에있는 데이터의 기본 구현을 변경하면 이전 데이터를 읽을 수 없게 될 수 있습니다.

대신 번들을 사용해야합니다. 내가 일반적으로하는 일은 toBundle과 fromBundle이라는 액티비티간에 전달하려고하는 클래스에 두 개의 정적 메서드를 만드는 것입니다. toBundle은 전송하려는 클래스의 인스턴스를 가져 와서 번들을 반환합니다. fromBunle은 번들을 받아 클래스의 인스턴스를 반환합니다.

액티비티간에 PrintWriter와 같은 복잡한 개체를 전달하는 방법을 모르겠습니다. 하지만 코드에는 다른 문제가 있습니다. 기본 UI 스레드에서 네트워크 작업을 수행하고 있습니다. 이렇게하면 앱이 많이 정지됩니다. 모든 IO를 다른 스레드로 옮겨야합니다. 이것은 모든 활동을 액세스 할 수있는 별도의 클래스로 모든 IO 항목을 이동할 수 있기 때문에 유용합니다. 예를 들어, IntentService을 사용하십시오. 이렇게하면 앱을 훨씬 더 멋지게 만들 수 있습니다. 또한 Painless Threading 문서를 읽어 볼 수도 있습니다. 그것은 모든 안드로이드 개발자에게 권장하는 중요한 읽기입니다.

+0

실제 코드를 게시하여 좀 더 설명 할 수 있습니까? PrintWriter 객체를 전달하는 방법을 알 수 없습니다. – Rushil

+0

보다 구체적으로 말하자면, 객체를 "번들로 묶는"방법은 무엇입니까? 번들은 클래스의 인스턴스를 마무리하기 위해 사용할 수있는 메소드가없는 것 같습니다. – Rushil

+0

루실, 맞습니다. PrintWritter는 번들로 묶을 수 없습니다. 이 문제를 해결하기 위해 내 대답을 확장했습니다. –

0

일반적인 안드로이드 데이터 전달 방법 (Bundles/Parcels) 중 하나를 사용하여 두 가지 Android 활동간에 PrintWriter를 전달할 수 없습니다. 두 액티비티간에 PrintWriter를 공유해야하는 경우 정적 변수를 사용할 수 있습니다.

즉, 각 활동에 액세스하여 사용하는 서비스를 작성할 수도 있습니다. 이를 수행하는 방법에 대한 예제는 ApiDemos 프로젝트의 LocalService 예제를 참조하십시오. 이것에 관해서도 수많은 온라인 튜토리얼이 있습니다.

관련 문제