▼Androidメモ▼
ソケット通信


ソケットを利用してチャットを行うプログラムを作成する。チャットサーバとなるPC用のJavaアプリも作成する。



 


ソースコード
SocketEx.java
package net.npaka.socketex;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

//ソケット通信
public class SocketEx extends Activity
implements View.OnClickListener {
private final static String BR=System.getProperty("line.separator");
private final static int WC=LinearLayout.LayoutParams.WRAP_CONTENT;
private final static int MP=LinearLayout.LayoutParams.MATCH_PARENT;

//IPアドレスの指定
private final static String IP="192.168.11.7";

private TextView lblReceive;//受信ラベル
private EditText edtSend; //送信エディットテキスト
private Button btnSend; //送信ボタン

private Socket socket; //ソケット
private InputStream in; //入力ストリーム
private OutputStream out; //出力ストリーム
private boolean error; //エラー

private final Handler handler=new Handler();//ハンドラ

//アクティビティ起動時に呼ばれる
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
requestWindowFeature(Window.FEATURE_NO_TITLE);

//レイアウトの生成
LinearLayout layout=new LinearLayout(this);
layout.setBackgroundColor(Color.WHITE);
layout.setOrientation(LinearLayout.VERTICAL);
setContentView(layout);

//送信エディットテキストの生成
edtSend=new EditText(this);
edtSend.setText("");
edtSend.setLayoutParams(new LinearLayout.LayoutParams(MP,WC));
layout.addView(edtSend);

//送信ボタンの生成
btnSend=new Button(this);
btnSend.setText("送信");
btnSend.setOnClickListener(this);
btnSend.setLayoutParams(new LinearLayout.LayoutParams(WC,WC));
layout.addView(btnSend);

//受信ラベルの生成
lblReceive=new TextView(this);
lblReceive.setText("");
lblReceive.setTextSize(16.0f);
lblReceive.setTextColor(Color.BLACK);
lblReceive.setLayoutParams(new LinearLayout.LayoutParams(MP,WC));
layout.addView(lblReceive);
}

//アクティビティ開始時に呼ばれる
@Override
public void onStart() {
super.onStart();

//スレッドの生成
Thread thread=new Thread(){
public void run() {
try {
connect(IP,8081);
} catch (Exception e) {
}
}
};
thread.start();
}

//アクティビティの停止時に呼ばれる
@Override
public void onStop() {
super.onStop();
disconnect();
}

//受信テキストの追加
private void addText(final String text) {
//ハンドラの生成
handler.post(new Runnable(){
public void run() {
lblReceive.setText(text+BR+
lblReceive.getText());
}
});
}

//接続
private void connect(String ip,int port) {
int size;
String str;
byte[] w=new byte[1024];
try {
//ソケット接続
addText("接続中");
socket=new Socket(ip,port);
in =socket.getInputStream();
out=socket.getOutputStream();
addText("接続完了");

//受信ループ
while (socket!=null && socket.isConnected()) {
//データの受信
size=in.read(w);
if (size<=0) continue;
str=new String(w,0,size,"UTF-8");

//ラベルへの文字列追加
addText(str);
}
} catch (Exception e) {
addText("通信失敗しました");
}
}

//切断
private void disconnect() {
try {
socket.close();
socket=null;
} catch (Exception e) {
}
}

//ボタンクリックイベントの処理
public void onClick(View v) {
//スレッッドの生成
Thread thread=new Thread(new Runnable(){public void run(){
error=false;
try {
//データの送信
if (socket!=null && socket.isConnected()) {
byte[] w=edtSend.getText().toString().getBytes("UTF8");
out.write(w);
out.flush();
}
} catch (Exception e) {
error=true;
}
//ハンドラの生成
handler.post(new Runnable(){public void run() {
if (!error) {
edtSend.setText("");
} else {
addText("通信失敗しました");
}
}});
}});
thread.start();
}
}

AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.npaka.socketex"
android:versionCode="1"
android:versionName="1.0">

<uses-sdk android:minSdkVersion="13" android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.INTERNET"/>

<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:theme="@style/AppTheme">
<activity
android:label="@string/app_name"
android:name=".SocketEx" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />

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

</manifest>


チャットサーバ(PC用Javaアプリ)
ChatServer.java
import java.io.*;
import java.net.*;
import java.util.*;

//チャットサーバ
public class ChatServer {

//開始
public void start(int port) {
ServerSocket server;//サーバソケット
Socket socket;//ソケット
ChatServerThread thread;//スレッド

try {
server=new ServerSocket(port);
System.err.println("チャットサーバ実行開始:"+port);
while(true) {
try {
//接続待機
socket=server.accept();

//チャットサーバスレッド開始
thread=new ChatServerThread(socket);
thread.start();
} catch (IOException e) {
}
}
} catch (IOException e) {
System.err.println(e);
}
}

//メイン
public static void main(String[] args) {
ChatServer server=new ChatServer();
server.start(8081);
}
}


ChatServerThread.java
import java.io.*;
import java.net.*;
import java.util.*;

//チャットサーバスレッド
public class ChatServerThread extends Thread {
private static List<ChatServerThread> threads=
new ArrayList<ChatServerThread>();//スレッド郡
private Socket socket;//ソケット

// コンストラクタ
public ChatServerThread(Socket socket) {
super();
this.socket=socket;
threads.add(this);
}

//処理
public void run() {
InputStream in =null;
String message;
int size;
byte[] w=new byte[10240];
try {
//ストリーム
in =socket.getInputStream();
while(true) {
try {
//受信待ち
size=in.read(w);

//切断
if (size<=0) throw new IOException();

//読み込み
message=new String(w,0,size,"UTF8");

//全員にメッセージ送信
sendMessageAll(message);
} catch (IOException e) {
socket.close();
threads.remove(this);
return;
}
}
} catch (IOException e) {
System.err.println(e);
}
}

//全員にメッセージ送信
public void sendMessageAll(String message) {
ChatServerThread thread;
for (int i=0;i<threads.size();i++) {
thread=(ChatServerThread)threads.get(i);
if (thread.isAlive()) thread.sendMessage(this,message);
}
System.out.println(message);
}

//メッセージ送信
public void sendMessage(ChatServerThread talker,String message){
try {
OutputStream out=socket.getOutputStream();
byte[] w=message.getBytes("UTF8");
out.write(w);
out.flush();
} catch (IOException e) {
}
}
}

−戻る−