WebSocketプロトコルは、クライアントとサーバー間の双方向通信のための常時接続を提供します。これは、マルチプレイヤーゲーム、モノのインターネットアプリケーション、チャットアプリなど、リアルタイム接続を必要とするアプリケーションに最適です。このチュートリアルのユースケースは、リアルタイム通信の典型的な例であるチャット・アプリケーションです。このチュートリアルでは、Spring Bootを使ってWebSocketサーバーに接続するシンプルなAndroidクライアントをセットアップします。
Java WebSocketクライアント
Androidクライアントでは、かわいい動物の4つの画像ボタンを含む簡単なデモアプリを作成します。Javaの実装に入る前に、KotlinがAndroidの開発で人気のある選択肢になっていることに注目する価値がある。まず、Android Studioで新しいプロジェクトを初期化し、JavaWebSocketClientという基本アクティビティを作成します。このアプリには、GitHubのレポにある軽量なWebSocketクライアント・ライブラリを使用します。このライブラリを使うには、appディレクトリのbuild.gradleファイルに追加する必要がある。依存関係に以下を追加し、プロジェクトを同期する:
dependencies {
// Add this
implementation 'tech.gusavila92:java-android-websocket-client:<latest-version>'
implementation fileTree(dir: 'libs', include: ['*.jar'])
...
}
マニフェスト・ファイルにインターネット・アクセス許可を必ず含めること:
<uses-permission android:name="android.permission.INTERNET" />
クライアントをサーバーに接続する
MainActivity.javaに移動し、以下のパッケージをインポートし、onCreate()を設定します:
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import java.net.URI;
import java.net.URISyntaxException;
import tech.gusavila92.websocketclient.WebSocketClient;
public class MainActivity extends AppCompatActivity {
private WebSocketClient webSocketClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.animal_sounds);
createWebSocketClient();
}
}
次に、新しいメソッドcreateWebSocketClient() を作成します:
private void createWebSocketClient() {
URI uri;
try {
// Connect to local host
uri = new URI("ws://10.0.2.2:8080/websocket");
}
catch (URISyntaxException e) {
e.printStackTrace();
return;
}
webSocketClient = new WebSocketClient(uri) {
@Override
public void onOpen() {
Log.i("WebSocket", "Session is starting");
webSocketClient.send("Hello World!");
}
@Override
public void onTextReceived(String s) {
Log.i("WebSocket", "Message received");
final String message = s;
runOnUiThread(new Runnable() {
@Override
public void run() {
try{
TextView textView = findViewById(R.id.animalSound);
textView.setText(message);
} catch (Exception e){
e.printStackTrace();
}
}
});
}
@Override
public void onBinaryReceived(byte[] data) {
}
@Override
public void onPingReceived(byte[] data) {
}
@Override
public void onPongReceived(byte[] data) {
}
@Override
public void onException(Exception e) {
Log.e("WebSocket", e.getMessage());
}
@Override
public void onCloseReceived() {
Log.i("WebSocket", "Closed ");
}
};
webSocketClient.setConnectTimeout(10000);
webSocketClient.setReadTimeout(60000);
webSocketClient.enableAutomaticReconnection(5000);
webSocketClient.connect();
}
これはたくさんあるように見えるかもしれませんが、実際にはこのメソッドで4つの重要なことを行っています:
ローカルホスト "ws://10.0.2.2:8080/websocket" への新しい WebSocket 接続を開始する。
接続が開かれたら、サーバーにメッセージを送信する。
サーバーから送信されたメッセージをアプリに表示する。
タイムアウトと自動再接続を設定する。
クライアントをサーバーに接続したところで、サーバーにメッセージを送信するメソッドを設定しましょう。
サーバーへのメッセージ送信
MainActivity.javaの sendMessage()に以下を追加します:
public void sendMessage(View view) {
Log.i("WebSocket", "Button was clicked");
// Send button id string to WebSocket Server
switch(view.getId()){
case(R.id.dogButton):
webSocketClient.send("1");
break;
case(R.id.catButton):
webSocketClient.send("2");
break;
case(R.id.pigButton):
webSocketClient.send("3");
break;
case(R.id.foxButton):
webSocketClient.send("4");
break;
}
}
ボタンが押されたら、そのボタンIDを サーバーに送信する。このメソッドはanimal_sounds.xmlから呼び出されます。an*imal_sounds.xmlは私のJava WebSocket Programming Repoから入手できます。values*ディレクトリの下にあるstrings.xmlファイルを必ず修正して、XMLファイルにエラーが出ないようにしてください。
クライアント側で行う最後のことは、drawableディレクトリに動物の画像を追加することです。画像は 、www.flaticon.com 、 Freepikによって 作成さ れました。
Androidアプリをエミュレーターで実行します:
サーバーがセットアップされていないので、今は何も起こりません。今すぐ実行しましょう!
Spring Boot WebSocketサーバー
サーバーにはSpring Bootを使う。プロジェクトを素早くブートストラップするために、Spring Initializrを使う。ここではGradleプロジェクトを生成するが、必要に応じてMavenプロジェクトを生成することもできる。以下のスクリーンショットのようにInitializrを設定し、依存関係としてWebSocketを追加してください:
プロジェクトを生成してzipファイルをダウンロードする。ファイルを解凍したら、srcディレクトリに移動し、JavaWebSocketServerApplication.javaファイルに到達するまでサブディレクトリをクリックし続けます。
package com.example.javawebsocketserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JavaWebSocketServerApplication {
public static void main(String[] args) {
SpringApplication.run(JavawebsocketserverApplication.class, args);
}
}
WebSocketHandler.javaと WebSocketConfiguration.javaの2つのファイルをディレクトリに追加します。
WebSocket メッセージの処理
サーバーに到着した受信メッセージを処理する必要があります。そのために、WebSocketHandler.java でhandleTextMessage() メソッドを実装するクラスを継承します。このファイルに以下のコードを追加します:
package com.server.javawebsocketserver;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import java.io.IOException;
public class WebSocketHandler extends AbstractWebSocketHandler {
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
String msg = String.valueOf(message.getPayload());
// Send back a unique message depending on the id received from the client
switch(msg){
case("1"):
Log.i("WebSocket", "Dog button was pressed");
session.sendMessage(new TextMessage("Woooof"));
break;
case("2"):
Log.i("WebSocket", "Cat button was pressed");
session.sendMessage(new TextMessage("Meooow"));
break;
case("3"):
Log.i("WebSocket", "Pig button was pressed");
session.sendMessage(new TextMessage("Bork Bork"));
break;
case("4"):
Log.i("WebSocket", "Fox button was pressed");
session.sendMessage(new TextMessage("Fraka-kaka-kaka"));
break;
default:
Log.i("WebSocket", "Connected to Client");
}
}
}
メソッド内部では、単純にメッセージのペイロードの文字列値を取得し、各ケースの値とメッセージの値をチェックするswitch式を実行します。動物の鳴き声が入ったユニークなメッセージがクライアントに送信されます。
WebSocket リクエスト処理の設定
WebSocketConfiguration.java でWebSocketConfigurer インターフェースを実装し、以下のコードを追加します:
package com.server.javawebsocketserver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new WebSocketHandler(), "/websocket");
}
}
registerWebSocketHandlers メソッドを設定し、パス "/websocket" にWebSocketHandler を設定します。サーバーサイドの設定は以上です。これですべての設定が完了したので、WebSocketサーバーを起動してアプリを実行してみましょう!
サーバーとクライアント間でデータを送信する
ターミナルでSpring Bootプロジェクトのルートディレクトリに移動し、以下のコマンドを実行してサーバーを起動する:
gradle bootRun
次に、Android StudioでAndroidクライアントを実行し、アプリがロードされたら、4つのボタンのいずれかをクリックします。
Androidアプリを操作して、WebSocketを使ってクライアントからサーバーにどのようにメッセージが送信されるかを確認する!
AndroidクライアントをPub/Subに更新する
クライアントからサーバーへ、またはサーバーからクライアントへデータを送信することは難しくありませんし、かなり速く行うことができます。しかし、クライアントからクライアントへデータを送信したい場合はどうすればいいでしょうか?サーバにルーティングとメッセージブローカのロジック(enableSimpleBrokerと
MessageBrokerRegistry
型への登録)を実装しない限り、クライアントを直接接続することはできません。
この作業に時間がかからないようにするために使えるツールがいくつかある。そのひとつがSocket.IO で、クライアント間でリアルタイムの双方向接続を確立します。これは素晴らしいオープンソースのツールだが、サーバーをセットアップし、クライアントをサーバーに接続する必要がある。もう1つのそのようなツールは、Spring BootでSTOMPのようなサブプロトコルを使ってSTOMPメッセージを埋め込むことだ。このサブプロトコルはWebSocketの上で動作し、WebSocketメッセージハンドリングを可能にする。しかし、StompEndpointRegistry
型を使って自分でエンドポイントを設定し、addEndPoint
メソッドでエンドポイントを追加しなければなりません。手動でサーバーをセットアップすることなく、クライアント間で安全かつ確実にデータを送信する簡単な方法はないだろうか?PubNubを使えば可能です。
PubNubは、TCPを話すあらゆるデバイスに電力を供給するリアルタイムインフラを提供します。PubNubのグローバルデータストリームネットワークを使用して、クライアント間、クライアントからサーバー間、サーバーからクライアント間のデータを100ミリ秒未満でストリーミングできます!PubNubでは、WebSocketと同様にチャネルに接続されたデバイス間で常時接続が行われます。PubNubはサーバーレスで無限にスケーラブルなので、バックエンドサーバーのセットアップやサーバーのメンテナンスを心配する必要がないのが最大の特徴です。
PubNubによってクライアントからクライアントへのデータ送信プロセスがどのように簡素化されるかを確認するために、先に構築したAndroidアプリを修正する。その前に、無料のPubNubアカウントにサインアップして 無料のPub/Sub APIキーを入手してください。
Androidクライアントの修正
更新したアプリを古いアプリと区別するために、PubNubJavaClientという新しいAndroidプロジェクトを作成します。PubNubのAndroid SDKを使用するため、appディレクトリのbuild.gradleファイルに以下を追加してjsonを更新し、プロジェクトを同期します:
dependencies {
implementation group: 'com.pubnub', name: 'pubnub-gson', version: '6.4.5' // Add this
implementation fileTree(dir: 'libs', include: ['*.jar'])
...
}
マニフェストファイルに次のパーミッションを含めます:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
MainActivity.java以外は同じです。以前のアプリから、次のファイルを更新後のアプリに追加します:animal_sounds.xml、strings.xml、およびdrawableディレクトリの画像。これが終わったら、MainActivity.javaに 新しいコードを追加します。以下のパッケージをインポートし、onCreate()を設定します:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import com.pubnub.api.PNConfiguration;
import com.pubnub.api.PubNub;
import com.pubnub.api.callbacks.PNCallback;
import com.pubnub.api.callbacks.SubscribeCallback;
import com.pubnub.api.models.consumer.PNPublishResult;
import com.pubnub.api.models.consumer.PNStatus;
import com.pubnub.api.models.consumer.pubsub.PNMessageResult;
import com.pubnub.api.models.consumer.pubsub.PNPresenceEventResult;
import java.util.Arrays;
public class MainActivity extends AppCompatActivity {
PubNub pubnub;
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.animal_sounds);
initPubNub(); // Initialize PubNub
}
initPubNub()を呼び出してPubNubを初期化します:
public void initPubNub(){
PNConfiguration pnConfiguration = new PNConfiguration();
pnConfiguration.setPublishKey("ENTER_YOUR_PUB_KEY"); // REPLACE with your pub key
pnConfiguration.setSubscribeKey("ENTER_YOUR_SUB_KEY"); // REPLACE with your sub key
pnConfiguration.setSecure(true);
pubnub = new PubNub(pnConfiguration);
// Listen to messages that arrive on the channel
pubnub.addListener(new SubscribeCallback() {
@Override
public void status(PubNub pub, PNStatus status) {
}
@Override
public void message(PubNub pub, final PNMessageResult message) {
// Replace double quotes with a blank space
final String msg = message.getMessage().toString().replace("\"", "");
textView = findViewById(R.id.animalSound);
runOnUiThread(new Runnable() {
@Override
public void run() {
try{
// Display the message on the app
textView.setText(msg);
} catch (Exception e){
System.out.println("Error");
e.printStackTrace();
}
}
});
}
@Override
public void presence(PubNub pub, PNPresenceEventResult presence) {
}
});
// Subscribe to the global channel
pubnub.subscribe()
.channels(Arrays.asList("global_channel"))
.execute();
}
このメソッドでは3つの重要なことを行います:
PubNubクライアントAPIを初期化します。ENTER_YOUR_PUB_KEY "と "ENTER_YOUR_SUB_KEY "をあなたのPub/Subキーに置き換えてください。
チャンネルに到着したメッセージの通知を受けるリスナーをセットアップします。先ほど行ったように、クライアントが見ることができるようにアプリにメッセージを表示します。
メッセージがパブリッシュされるグローバルチャネルをサブスクライブする。
ユーザーがボタンを押すと、sendMessage() メソッドが呼び出されます:
// This method is called when a button is pressed
public void sendMessage(View view) {
// Get button ID
switch(view.getId()){
case(R.id.dogButton):
publishMessage("Woooof");
break;
case(R.id.catButton):
publishMessage("Meooow");
break;
case(R.id.pigButton):
publishMessage("Bork Bork");
break;
case(R.id.foxButton):
publishMessage("Fraka-kaka-kaka");
break;
}
}
このメソッドは先ほどと似ていますが、実際のメッセージである動物の鳴き声を、サーバーではなくグローバルチャンネルに公開する点が異なります。publishMessage()は、メッセージをパブリッシュするためのヘルパー関数です。
public void publishMessage(String animal_sound){
// Publish message to the global chanel
pubnub.publish()
.message(animal_sound)
.channel("global_channel")
.async(new PNCallback<PNPublishResult>() {
@Override
public void onResponse(PNPublishResult result, PNStatus status) {
// status.isError() to see if error happened and print status code if error
if(status.isError()) {
System.out.println("pub status code: " + status.getStatusCode());
}
}
});
}
アプリを起動して実行するのに必要なのはこれだけだ!
クライアント間でデータを送信する
Androidアプリを2つのエミュレーターで実行し、メッセージがリアルタイムで表示されるのを確認してみましょう。
注意:クライアント間でシームレスな通信を行うには、両方のAndroidエミュレータが同じPubNubキーを持ち、同じチャネルにサブスクライブしていることを確認してください。これはリアルタイム通信のためのWebSocket接続を正常に確立するために非常に重要です。
JavaでWebSocketを使用してデータを送信する方法を学んだので、私たちの他のリソースを探索することを忘れないでください。
最後に、PubNubが提供するMessage Actions、Objects、Signalメッセージなどの追加機能について学ぶために私たちのドキュメントをチェックして、あなたのアプリケーションに堅牢なエッジを与えてください。より包括的な理解のために、更新されたスクリーンショットとリソースリンクをチェックしてください。
PubNubを使用すると、ジオロケーション、エッジメッセージバス、エンタープライズソフトウェア、ゲーム、デジタルヘルス、eコマース向けにカスタマイズされたソリューションを作成することもできます。
まずは、一般的なセットアップガイドをご覧ください。メッセージの送受信方法についてご興味のある方は、こちらもご覧ください。詳しくは、メッセージ送信ガイドと メッセージ受信ガイドをご覧ください。
チャットシナリオでのメッセージ送信、メッセージ受信、未読カウントなど、より高度な機能については、以下のドキュメントを参照してください:メッセージ送信、メッセージ受信、未読カウント。
Androidプラットフォームで作業していて、プッシュ通知を実装したい場合、私たちはあなたをカバーしています。firebaseとPubNubを使ったプッシュ通知の設定方法についてはAndroidプッシュガイドと 送信プッシュガイドをご覧ください。
この記事の内容に関して提案や質問がありますか?devrel@pubnub.com までご連絡ください。
PubNubはあなたのお役に立ちますか?
この記事はPubNub.comに掲載されたものです。
私たちのプラットフォームは、開発者がWebアプリ、モバイルアプリ、およびIoTデバイスのためのリアルタイムのインタラクティブ性を構築、配信、管理するのに役立ちます。
私たちのプラットフォームの基盤は、業界最大かつ最もスケーラブルなリアルタイムエッジメッセージングネットワークです。世界15か所以上で8億人の月間アクティブユーザーをサポートし、99.999%の信頼性を誇るため、停電や同時実行数の制限、トラフィックの急増による遅延の問題を心配する必要はありません。
PubNubを体験
ライブツアーをチェックして、5分以内にすべてのPubNub搭載アプリの背後にある本質的な概念を理解する
セットアップ
PubNubアカウントにサインアップすると、PubNubキーに無料ですぐにアクセスできます。
始める
PubNubのドキュメントは、ユースケースやSDKに関係なく、あなたを立ち上げ、実行することができます。
Top comments (0)