2017-06-24 7 views
1

まず、私はAndroid、Javaの完全な初心者で、スタックオーバーフローで投稿します。Androidのソケットクライアント - メッセージを送信することができません

私はソケットを利用したプロジェクトのためのシンプルなアプリを作成しようとしています。私は、PC上で実行されているサーバーにコマンドを送信するAndroidデバイス上にクライアントを設定したいと考えています。私はPythonでサーバーを書いてテストしたので、プロジェクトの側面が分かっていることは分かっています。 Androidアプリの実装に問題があります。

私は私のクライアントアプリケーションを書くために、このガイドに従っ:私は私のアプリを実行すると https://examples.javacodegeeks.com/android/core/socket-core/android-socket-example/

、私のサーバーは、クライアントがそれに接続されていることを認めています。ただし、データを送信しようとすると、サーバーによって何も受信されません。これは、(それはかなり上記のリンクと同じです)私のコードは次のようになります。

<?xml version="1.0" encoding="utf-8"?> 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:orientation="vertical" > 

     <EditText 
      android:id="@+id/editText" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:text="TestData" > 
     </EditText> 

     <Button 
      android:id="@+id/myButton" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:onClick="onClick" 
      android:text="Send" > 
     </Button> 

    </LinearLayout> 

activity_main.xml

MainActivity.java

package com.example.user.sockettest; 

import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.OutputStreamWriter; 
import java.io.PrintWriter; 
import java.net.InetAddress; 
import java.net.Socket; 
import java.net.UnknownHostException; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.EditText; 

public class MainActivity extends Activity { 


    private Socket socket; 

    private static final int SERVERPORT = 8000; 
    private static final String SERVER_IP = "192.168.0.17"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     new Thread(new ClientThread()).start(); 
    } 

    public void onClick(View view) { 
     try { 
      EditText et = (EditText) findViewById(R.id.editText); 
      String str = et.getText().toString(); 
      PrintWriter out = new PrintWriter(new BufferedWriter(
        new OutputStreamWriter(socket.getOutputStream())), 
        true); 
      out.println(str); 
     } catch (UnknownHostException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    class ClientThread implements Runnable { 

     @Override 
     public void run() { 

      try { 
       InetAddress serverAddr = InetAddress.getByName(SERVER_IP); 

       socket = new Socket(serverAddr, SERVERPORT); 

      } catch (UnknownHostException e1) { 
       e1.printStackTrace(); 
      } catch (IOException e1) { 
       e1.printStackTrace(); 
      } 

     } 

    } 
} 

AndroidManifest.xmlを

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.example.user.sockettest"> 

    android:versionCode="1" 
    android:versionName="1.0" > 

    <uses-sdk 
     android:minSdkVersion="8" 
     android:targetSdkVersion="17" /> 

    <uses-permission android:name="android.permission.INTERNET" > 
    </uses-permission> 

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" > 
    </uses-permission> 

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 

    <application 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 

     <activity android:name="com.example.user.sockettest.MainActivity"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

他のスレッドで推奨されているように権限を設定しましたが、これは役に立たないようです。 ソケットは別のスレッド上で動作するので、ブロック問題であるとは思えません。私はそのJava実装では非常に基本的な何かが欠けていると確信しているように、ソケットプログラミングと

私の経験では、主にPythonであります!

助けや指針は本当にありがとうございます!

EDIT:今取り組んでいる 更新コード、ゲイブSechanの答え

public class MainActivity extends Activity { 


    private Socket socket; 
    boolean sendData = false; // Flag to indicate whether data should be sent 
    String message; 

    private static final int SERVERPORT = 8000; 
    private static final String SERVER_IP = "192.168.0.17"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     new Thread(new ClientThread()).start(); 
    } 

    public void onClick(View view) { 
     EditText et = (EditText) findViewById(R.id.editText); 
     message = et.getText().toString(); 
     sendData = true; 
    } 

    class ClientThread implements Runnable { 

     @Override 
     public void run() { 
      try { 
       InetAddress serverAddr = InetAddress.getByName(SERVER_IP); 

       socket = new Socket(serverAddr, SERVERPORT); 
       BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

       // Loop forever checking if a message needs to be send 
       while (socket.isConnected()){ 
        if (sendData){ 
         // If a message is ready to be sent, call sendMessage method 
         sendMessage(); 
        } 
       } 
      } catch (UnknownHostException e1) { 
       e1.printStackTrace(); 
      } catch (IOException e1) { 
       e1.printStackTrace(); 
      } 
     } 

     private void sendMessage(){ 
      // Send message over socket 
      try { 
       PrintWriter out = new PrintWriter(socket.getOutputStream()); 
       out.println(message); 
       out.flush(); 
       // Reset flag 
       sendData=false; 
      } catch (UnknownHostException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

答えて

2

のおかげで私はあなたがクラッシュしていない驚いています。クリックハンドラはメインスレッド上で実行されます。メインスレッドはネットワークIOを実行できません。試行するには例外をスローする必要があります。 BufferedWriterがあなたを保存している可能性があります。ストリームをフラッシュしていないため、メッセージが小さければ、実際のソケットに書き込んでいない可能性があります。

だから最初にやるべきことは、おそらくあなたのClientThread別のスレッドに書き込みを行うと、それへの書き込みコマンドを送信するメッセージパッシングのいくつかのフォームを使用しています。次に必要なのは、出力ライターを単純化することです。実際に何かにラップする必要はありません。出力ストリームに直接書き込むだけで十分です。

+0

BufferedWriterのデフォルトのバッファサイズは8192 'char'sなので、予想通りです。 –

+0

答えてくれてありがとうGabe!私はあなたの答えの解釈を実装し、それは動作します(私は私の解釈が実際に正確かどうかわからないので、これは初めてです)!元の投稿を編集して作業コードを追加しました。私はベストプラクティスを壊しているかどうかはわかりません(特に、送信するメッセージの無限ループチェック)。 – TheLight

+0

スレッド上の無限ループはかなり一般的です。 isInterruptedもチェックする必要があります。スレッドが終了するよう指示された場合、スレッドは終了することができます。そのように忙しく待つべきではありません。代わりにMessageQueueやLooperのようなものを待つべきです。そうすれば、OSはアプリケーションを一時停止し、CPU時間が必要な他のプロセスにそのコアを使用することができます。スレッドの最後の{}ブロックのソケットを閉じてソケットを適切に閉じ、アクティビティのonDestroy()のスレッドを中断して、すべてのスレッドが適切にキャンセルされ、リソースが解放されるようにする必要があります。 –

関連する問題