質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

5376閲覧

Android Studio でソケット通信→画像の転送がしたい

XionCode

総合スコア46

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

1グッド

1クリップ

投稿2020/07/04 09:09

編集2020/07/04 09:39

Android Studioでソケット通信のプログラムを組み、Android端末間で画像を転送するプログラムを作ろうとしています。手始めとしてクライアントから一回サーバーに送信するだけのプログラムです。
文章を送るプログラムを以前に自分で書いたので、そのコピーを改造して作っています。
しかし、実機デバッグがうまくいきません。

具体的には、サーバー側のonPostExecute()で、成功した時に表示する__"Succeeded! Sabrina Carpenter..."__がちゃんと画面に表示されますが、肝心の画像が表示されません。

パーミッションは問題ないはずです。
実機はそれぞれ Android 10, 9 の端末間での通信です。

考えられるのは
・クライアント側での ImageView -> byte[] の変換が間違っている
・サーバー側での byte[] -> Drawable の変換が間違っている
・byte[] 列が正しく送られていない
のどれかです。

以下問題のコードです。
#クライアントのプロジェクト

myClass.java

Java

1//AsyncTask doInBackgroundの引数になるオブジェクト 2public class myClass{ 3 public String string; 4 public byte[] bytes; 5 6 public myClass(String s, byte[] b){ 7 this.string = s; 8 this.bytes = b; 9 } 10}
MainActivity.java
public class MainActivity extends AppCompatActivity { ImageView image1; Button button1; String IPAddress; Activity activity; EditText editText; TextView tv; byte[] buff; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //widget image1= (ImageView)this.findViewById(R.id.imageSabrina); button1 = (Button)this.findViewById(R.id.button1); activity = this; editText = (EditText)this.findViewById(R.id.textInput); tv = (TextView)activity.findViewById(R.id.tview1); buff = new byte[200000]; button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Drawable drawable = image1.getDrawable(); //ImageViewをbyte[]に変換 try { ByteArrayOutputStream byteos = new ByteArrayOutputStream(); ObjectOutputStream objos = new ObjectOutputStream(byteos); objos.writeObject(drawable); objos.close(); buff = byteos.toByteArray(); byteos.close(); } catch (IOException e) { e.printStackTrace(); tv.setText(e.toString()); } IPAddress = ""; IPAddress += editText.getText().toString(); myClass info = new myClass(IPAddress, buff); //ソケットの実行 if(IPAddress != "") new ClientSock(activity).execute(info); else { tv.setText("error : ↓SetIP here"); } } }); } }
ClientSock.java

Java

1public class ClientSock extends AsyncTask<myClass, Void, String> { 2 private Activity activity; 3 DataOutputStream writer; 4 5 public ClientSock(Activity activity1){ activity = activity1; } 6 7 @Override 8 protected String doInBackground(myClass... info){ 9 InetSocketAddress endpoint = new InetSocketAddress(info[0].string, 12345); 10 11 //ソケットを生成しDataOutputStreamで送信処理 12 try{ 13 Socket sock = new Socket(); 14 sock.connect(endpoint); 15 writer = new DataOutputStream(sock.getOutputStream()); 16 writer.write(info[0].bytes, 0, info[0].bytes.length); 17 sock.close(); 18 return "Succeeded in sending a message to " + info[0].string; 19 }catch(IOException e){ 20 return e.toString() + "\nfailed to send a message to " + info[0].string; 21 } 22 } 23 24 @Override 25 protected void onPostExecute(String s){ 26 TextView tv = (TextView)activity.findViewById(R.id.tview1); 27 tv.setText(s); 28 } 29}

サーバーのプロジェクト

MainActivity.java

Java

1public class MainActivity extends AppCompatActivity { 2 Button button; 3 Activity activity; 4 ImageView imageView; 5 Drawable drawable; 6 7 @Override 8 protected void onCreate(Bundle savedInstanceState) { 9 super.onCreate(savedInstanceState); 10 setContentView(R.layout.activity_main); 11 12 //widget 13 button = (Button)this.findViewById(R.id.button); 14 activity = this; 15 imageView = (ImageView)this.findViewById(R.id.receivedPicture); 16 17 button.setOnClickListener(new View.OnClickListener() { 18 @Override 19 public void onClick(View v) { 20 //ソケットの実行 21 new ServerSock(activity).execute(); 22 } 23 }); 24 } 25}

######ServerSock

Java

1public class ServerSock extends AsyncTask<Void, Void, Drawable> { 2 private Activity activity; 3 InputStream input; 4 ImageView imageView; 5 TextView textView; 6 7 public ServerSock(Activity activity1){ activity = activity1; } 8 9 @Override 10 protected Drawable doInBackground(Void... voids) { 11 textView = (TextView) activity.findViewById(R.id.textview); 12 try { 13 //ソケットを生成し、InputStreamで通信処理 14 ServerSocket SS = new ServerSocket(12345); 15 Socket sock = SS.accept(); 16 input = new BufferedInputStream(sock.getInputStream()); 17 18 byte[] b = new byte[200000]; 19 byte[] tem = new byte[1024]; 20 int a; 21 int count = 0; 22 23 //byte配列を読み込む 24 while((a = input.read(tem)) > -1){ 25 for(int i = 0; i < a; i++) b[count + i] = tem[i]; 26 count += a; 27 } 28 input.close(); 29 sock.close(); 30 31 //byte[]を Drawableに変換 32 ByteArrayInputStream byteis = new ByteArrayInputStream(b, 0, count); 33 ObjectInputStream objis = new ObjectInputStream(byteis); 34 Drawable drawable = (Drawable) objis.readObject(); 35 return drawable; 36 } catch (IOException | ClassNotFoundException e) { 37 e.printStackTrace(); 38 return null; 39 } 40 } 41 42 @Override 43 protected void onPostExecute(Drawable drawable) { 44 //Drawableを imageviewにセット 45 imageView = (ImageView) activity.findViewById(R.id.receivedPicture); 46 imageView.setImageDrawable(drawable); 47 textView.setText("Succeeded! Sabrina Carpenter..."); 48 } 49}

ご返答お待ちしています。
よろしくお願いします。

gken👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2020/07/04 09:13

「Android Studio」をタグとして追加してください。
XionCode

2020/07/04 09:40

ありがとうございます、修正しました。
hoshi-takanori

2020/07/04 11:17

Drawable はたぶん送信できないので、画像データを送信する必要があると思います。
XionCode

2020/07/04 12:03

そうでしたか… Drawable から 画像データ を抽出・変換はできないでしょうか?
hoshi-takanori

2020/07/04 12:12

どんな画像データを送りたいかにもよりますが、assets に画像ファイルを置いといて、それを送信するのが手っ取り早いのでは。
XionCode

2020/07/06 03:41

あそっかassetsの画像を使えばいいんですね…… やってみます
XionCode

2020/07/11 13:18

みなさんご回答ありがとうございました。 無事解決いたしました。
guest

回答1

0

ベストアンサー

DrawableではなくBitmapで送ってみてはどうでしょうか。次のような修正で送信できるのではないかと思います。

  • クライアントのMainActivity.java(一部)

java

1 button1.setOnClickListener(new View.OnClickListener() { 2 @Override 3 public void onClick(View v) { 4 Bitmap bitmap = ((BitmapDrawable) image1.getDrawable()).getBitmap(); 5 6 //Bitmapをbyte[]に変換 7 try { 8 ByteArrayOutputStream byteos = new ByteArrayOutputStream(); 9 bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteos); 10 buff = byteos.toByteArray(); 11 byteos.close(); 12 } catch (IOException e) { 13 e.printStackTrace(); 14 tv.setText(e.toString()); 15 } 16
  • サーバーのServerSock.java(一部)

java

1public class ServerSock extends AsyncTask<Void, Void, Bitmap> { 2 3 (中略) 4 5 @Override 6 protected Bitmap doInBackground(Void... voids) { 7 8 (中略) 9 10 //byte[]を Bitmapに変換 11 Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, count); 12 return bitmap; 13 } catch (IOException e) { 14 e.printStackTrace(); 15 return null; 16 } 17 } 18 19 @Override 20 protected void onPostExecute(Bitmap bitmap) { 21 //Bitmapを imageviewにセット 22 imageView = (ImageView) activity.findViewById(R.id.receivedPicture); 23 imageView.setImageBitmap(bitmap); 24 textView.setText("Succeeded! Sabrina Carpenter..."); 25 } 26}

(2020/07/09追記)
ServerSock.javaの受信部分、こんな感じでByteArrayOutputStreamを活用すれば、受信するデータサイズに依存しないようにできるんじゃないかと思います。

java

1 ByteArrayOutputStream byteos = new ByteArrayOutputStream(); 2 byte[] tem = new byte[1024]; 3 int a; 4 int count = 0; 5 6 //byte配列を読み込む 7 while ((a = input.read(tem)) > -1) { 8 byteos.write(tem, 0, a); 9 count += a; 10 } 11 input.close(); 12 sock.close(); 13 14 byte[] b = byteos.toByteArray(); 15

投稿2020/07/04 16:35

編集2020/07/09 09:24
keicha_hrs

総合スコア6768

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

XionCode

2020/07/07 00:55

ありがとうございます。 bitmap.conpress()ですね。やってみます。
XionCode

2020/07/08 15:15

報告遅くなりました。 bitmap.compress()を使ってみましたが、送信後にサーバーがおちてしまうようになりました。 bitmap.recycle()など、うまくいってないのでしょうか。
keicha_hrs

2020/07/09 06:10 編集

受信処理のバッファーが足りなくて、確保したbyte配列の領域外への書き込みをしようとしているのではありませんか?Android StudioでLogCatを確認すると、ArrayIndexOutOfBoundsExceptionが発生していませんか? まずはClientSock.javaの「ソケットを生成しDataOutputStreamで送信処理」のところにブレークポイントを設定して、info[0].bytes.lengthがいくつになっているか(何バイト送信しようとしているか)確認してはどうでしょうか。
XionCode

2020/07/11 06:56

お察しのとおりArrayIndexOutOfBoundsExceptionが発生していました。  Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, count); ここで発生していました。 また、いただいた追記の表現で試してみても発生しています。
keicha_hrs

2020/07/11 07:48 編集

なぜそこで発生するのか不思議です。送信したときのバイト数と、その処理を実行するときのcountの値が一致しているでしょうか?countを宣言したときに0を代入していますか?countが初期化されておらず、不適当な値がdecodeByteArray()に渡されているようなことはないでしょうか。 一応、私の手元で実験して問題なく画像転送できたコードを提示したつもりなのですが。
XionCode

2020/07/11 13:18

ごめんなさい! 凡ミスでクライアントから送る側で大問題しでかしておりました。 すみません… 問題なくできましたので報告いたします。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問