2011-10-25 22 views
1

私はパーセルの使い方に関する記事を読んだことがありますが、アプリで使用しましたが機能しません。私は、Socketsを使ってコンピュータに接続できるアクティビティを作成しました。ソケットOutputStreamjava.io.PrintWriterを開きました。もう1つのアクティビティ(1回目のアクティビティのボタンをタップすると開きます)は同じPrintWriterを使用します。私がここで作っている間違いは、PrintWriter objectを複製していないことだと思います。私はそれを複製する方法を知らない。Android:パーセルを使用してあるアクティビティから別のアクティビティにオブジェクトを渡すのが難しい場合

ここで第一のアクティビティ(私はいくつかの不要な機能を削除しました)です:

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]; } 
    }; 
} 

発砲した。私は接続していないとき

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)(Iは要部のみを掲載しました)と私は、次のアクティビティ、何も起こりません(エラーなし)を起動します。 しかし、接続すると(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というアクティビティの間を渡そうとしているクラスに2つの静的メソッドを作成することです。 toBundleは、転送したいクラスのインスタンスを取り、バンドルを返します。 fromBunleはバンドルを取り、そのクラスのインスタンスを返します。

私は、アクティビティ間でPrintWriterのような複雑なオブジェクトを渡す方法について知らない。しかし、コードには他にも問題があります。あなたは、メインのUIスレッドでネットワークのことをしています。これはあなたのアプリがたくさん凍ってしまう原因になります。すべてのIOを別のスレッドに移動する必要があります。これは、両方のアクティビティからアクセス可能な個別のクラスにすべてのIO情報を移動できるため、これは良いことです。たとえば、IntentServiceを使用します。これはあなたのアプリをもっと良くするsoooooooになります。記事Painless Threadingもお読みください。私はすべてのアンドロイドの開発者にお勧めする重要な読書です。

+0

実際のコードを投稿してもう少し説明できますか?私はPrintWriterオブジェクトを渡す方法を理解できません。 – Rushil

+0

具体的には、オブジェクトを「バンドルアップ」するにはどうすればよいですか?バンドルは、私がクラスのインスタンスをラップアップするために使用できるメソッドを持っていないようです。 – Rushil

+0

ルシル、それは正しいです。 PrintWritterをバンドルすることはできません。私はこれに対処するために私の答えを拡大しました。 –

0

通常のAndroidデータ転送メソッド(Bundles/Parcels)のいずれかを使用して、2つのAndroidアクティビティ間でPrintWriterを渡すことはできません。 2つのアクティビティ間でPrintWriterを共有する必要がある場合は、静的変数を使用できます。

あなたは、各アクティビティにアクセスして使用するサービスを書くこともできます。それを行う方法の例については、ApiDemosプロジェクトのLocalServiceの例を参照してください。これに関してオンラインで無数のチュートリアルもあります。

関連する問題