Androidのweb開発 - socket通信
Socket通信の概要
サーバ
- ServerSocket(int port)
- ServerSocket(int port, int backlog)
- ServerSocket(int port, int backlog, InetAddress localAddr)
クライアント
- Socket(InetAddress/String remoteAddress, int port)
- Socket(InetAddress/String remoteAddress, int port, InetAddress localAddr, int localPort)
Socketのinputストリームとoutputストリーム
- InputStream getInputStream() : データを取り出す
- OutputStream getOutputStream() : データを流す
サーバを通して複数の人の間のチャットするサンプルコード
サーバ
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; public class ChatServer { // クライアント接続Socketリスト public static ArrayList<Socket> socketList = new ArrayList<Socket>(); public static void main(String[] args) throws IOException { // ポート番号31234でサーバ起動 ServerSocket server = new ServerSocket(31234); while(true) { // 接続があった際 Socket socket = server.accept(); // リストに追加 socketList.add(socket); // クライアントから接続があった場合、別スレッドを起動する new Thread(new ServerTread(socket)).start(); } } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.Socket; import java.net.SocketException; import java.util.Iterator; public class ServerTread implements Runnable{ Socket socket = null; BufferedReader br = null; public ServerTread(Socket socket) throws UnsupportedEncodingException, IOException { this.socket = socket; // INPUTストリーム初期化 br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8")); } @Override public void run() { try{ String content = null; while ((content = readFromClient()) != null) { // サーバのソケットリストを繰り返す for (Iterator<Socket> it = ChatServer.socketList.iterator(); it.hasNext();) { Socket s = it.next(); try { OutputStream os = s.getOutputStream(); os.write((content + "\n").getBytes("utf-8")); } catch (SocketException e) { e.printStackTrace(); // サーバのSocketリストから削除 it.remove(); } } } } catch(Exception e) { e.printStackTrace(); } } private String readFromClient() { try { return br.readLine(); } catch (Exception e) { e.printStackTrace(); // サーバのSocketリストから削除 ChatServer.socketList.remove(socket); } return null; } }
Android(クライアント)
① AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
② activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- チャット内容入力 --> <EditText android:id="@+id/input" android:layout_width="280dp" android:layout_height="wrap_content" /> <Button android:id="@+id/send" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="8dp" android:text="送信"/> </LinearLayout> <!-- サーバからのメッセージ受信 --> <TextView android:id="@+id/show" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="top" android:background="#ffff" android:textSize="14dp" android:textColor="#f000"/> </LinearLayout>
③ MainActivity.java
ネット接続は別スレッドで起動する
package com.example.liguofeng.chatclient; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.view.View.OnClickListener; import android.os.Handler; public class MainActivity extends AppCompatActivity { EditText input; TextView show; Button send; Handler handler; // サーバと通信するスレッド ClientThread clientThread; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // view取得 input = (EditText) findViewById(R.id.input); send = (Button) findViewById(R.id.send); show = (TextView) findViewById(R.id.show); handler = new Handler() { @Override public void handleMessage(Message msg) { // サブスレッドからのメッセージ if (msg.what == 0x123) { // 表示する show.append("\n" + msg.obj.toString()); } } }; clientThread = new ClientThread(handler); // サーバ接続スレッド開始 new Thread(clientThread).start(); send.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { // メッセージ送信 Message msg = new Message(); msg.what = 0x345; msg.obj = input.getText().toString(); clientThread.revHandler.sendMessage(msg); // テキストクリア input.setText(""); } catch (Exception e) { e.printStackTrace(); } } }); } }
④ ClientThread.java(別スレッド)
package com.example.liguofeng.chatclient; import android.os.Handler; import android.os.Looper; import android.os.Message; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; import java.net.SocketTimeoutException; public class ClientThread implements Runnable { private Socket s; private Handler handler; public Handler revHandler; BufferedReader br = null; OutputStream os = null; public ClientThread(Handler handler) { this.handler = handler; } public void run() { try { s = new Socket("192.168.0.7", 31234); br = new BufferedReader(new InputStreamReader( s.getInputStream())); os = s.getOutputStream(); // スレッド起動 new Thread() { @Override public void run() { String content = null; // Socketのinputストリーム読み取り try { while ((content = br.readLine()) != null) { // Mainスレッドに通知 Message msg = new Message(); msg.what = 0x123; msg.obj = content; handler.sendMessage(msg); } } catch (IOException e) { e.printStackTrace(); } } }.start(); // Lopper初期化 Looper.prepare(); revHandler = new Handler() { @Override public void handleMessage(Message msg) { // UIスレッドメッセージ取得 if (msg.what == 0x345) { // サーバにチャット内容送信 try { os.write((msg.obj.toString() + "\r\n") .getBytes("utf-8")); } catch (Exception e) { e.printStackTrace(); } } } }; // Looper起動 Looper.loop(); } catch (SocketTimeoutException e1) { System.out.println("TIME OUT!!"); } catch (Exception e) { e.printStackTrace(); } } }