のためのアンドロイドWebSocketクライアント
30997 ワード
WebSocketsは、モバイルアプリケーションとバックエンドの双方向通信を実現するための素晴らしい方法です.アマゾンのAPIゲートウェイサービスlaunched serverless support for WebSockets .
それをすべて設定すると多少関与している.で始まることをお勧めしますSimple WebSockets Chat backend 彼らはデモとして提供しています.私たちはどのようにAndroidから話をするにはOkHttp またはJetbrains ' newerKtor .
事前の要件 安activate an AWS account
The latest version of the AWS CLI
AWS SAM CLI Homebrew(Mac上での場合)を介してインストール Android Studio
バックエンドの設定
Serverlessデモアプリケーションのインストールはかなりまっすぐです.
チェックアウトチャットアプリケーション:
すべてを作成したものを理解するために出力を見た後、WebSocketエンドポイント自体でゼロにしよう.クライアントが利用できるURIを見つけ、それにアクセスする必要があります.
コマンドラインテスト
他の何かをパスしようとすると動作しません.
からのAPIを呼び出す
WebSocket APIが機能していることを知ったので、代わりにクライアントとして使用するAndroidアプリの構築を始めましょう.
websocketsはsupported in OkHttp since 3.5 , それは2016年にずっと戻ってきた.
WebSocketクライアントの初期化は直進です.
からのAPIを呼び出す
KTORは、あなたがCoroutinesを使用していて、あなた自身の範囲/文脈を管理しているという仮定で造られます.これは、より柔軟なツールになりますが、いくつかの追加の複雑さを追加します.
ツールの基本的な設定は以下のようになります.
エー エー
WebSocketセッションの閉鎖の中にいくつかの簡単なメッセージを送受信するのはかなり些細なことです.
私たちは、同時にデータを送受信したいと思います 接続が開いて閉じたときに通知を取得します.
KTORにおける並列送受信
我々の目標は、最終的にメッセージの流れを派遣することです
最初にボタンクリックをマップ化する拡張機能を作成しましょう
この場合、結果をマップする値はあまりありません.ソケット上で受信する値は、
ライフサイクルイベント
OkHTTPは、コールバックを
回復する最も簡単なものはソケットが開くときのイベントです.それは、中で起こる最初のものだけです
ラッピング
さて、OkHTTPとKTORを使用してAmazon APIゲートウェイWebSockets APIを消費する方法についての、荒々しく説明できない説明があります.🥳.
The code for this project is available on my GitHub page .
それをすべて設定すると多少関与している.で始まることをお勧めしますSimple WebSockets Chat backend 彼らはデモとして提供しています.私たちはどのようにAndroidから話をするにはOkHttp またはJetbrains ' newerKtor .
事前の要件
wscat
インストールnpm
. AWS SAM CLI Homebrew(Mac上での場合)を介してインストール
バックエンドの設定
Serverlessデモアプリケーションのインストールはかなりまっすぐです.
チェックアウトチャットアプリケーション:
git clone https://github.com/aws-samples/simple-websockets-chat-app.git
そして、それをあなたのアカウントに展開します.sam deploy --guided
しばらくしたら、そのコマンドは終了します.CloudFormationスタックの出力を検査することで、プロビジョニングされたリソースを見ることができます.aws cloudformation describe-stacks \
--stack-name simple-websocket-chat-app \
--query 'Stacks[].Outputs'
これは、DynamoDBテーブル、3つのラムダ関数、AWS IAMロール、およびWebSocketsサポート付きのAPIゲートウェイを作成します.すべてを作成したものを理解するために出力を見た後、WebSocketエンドポイント自体でゼロにしよう.クライアントが利用できるURIを見つけ、それにアクセスする必要があります.
aws cloudformation describe-stacks \
--stack-name simple-websocket-chat-app \
--query 'Stacks[].Outputs[]' | \
jq -r '.[]|select(.OutputKey=="WebSocketURI").OutputValue'
次のように出力します.wss://azgu36n0vf.execute-api.us-east-1.amazonaws.com/Prod
コマンドラインテスト
wscat
すぐにバックエンドをテストしましょう.私たちは wscat
command-line utility . 以下のコマンドは、APIゲートウェイへの長寿命接続をオープンし、サブシェルでメッセージを送受信できるようになります.$ wscat -c wss://azgu36n0vf.execute-api.us-east-1.amazonaws.com/Prod
Connected (press CTRL+C to quit)
> {"action": "sendmessage", "data": "foo"}
< foo
上記のJSON形式は、我々が展開したアプリで必要です.あなたの値を変更することができます"foo"
, しかし、あなたは何も変えることができません.他の何かをパスしようとすると動作しません.
> Hello, how are you?
< {"message": "Forbidden", "connectionId":"Y0bEuc0UIAMCIiA=", "requestId":"Y0bwuGjXIAMFmEg="}
しかし、複数の端末ウィンドウを開き、それらをエンドポイントに接続すれば、有効なメッセージを受け取るでしょう.からのAPIを呼び出す
WebSocket APIが機能していることを知ったので、代わりにクライアントとして使用するAndroidアプリの構築を始めましょう.
websocketsはsupported in OkHttp since 3.5 , それは2016年にずっと戻ってきた.
WebSocketクライアントの初期化は直進です.
val request = Request.Builder()
.url("wss://azgu36n0vf.execute-api.us-east-1.amazonaws.com/Prod")
.build()
val listener = object: WebSocketListener() {
override fun onMessage(ws: WebSocket, mess: String) {
// Called asynchronously when messages arrive
}
}
val ws = OkHttpClient()
.newWebSocket(request, listener)
メッセージをAPIゲートウェイに送るには、以下のようにします.ws.send(JSONObject()
.put("action", "sendmessage")
.put("data", "Hello from Android!")
.toString())
私達は私達のUIにボタンを追加することができますViewBinding , をクリックすると、WebSocketメッセージを起動します.ui.button.setOnClickListener {
ws.send(JSONObject()
.put("action", "Hello from Android!")
.put("data", command)
.toString())
}
スレッドのすべてがOKHTTPの中で扱われるので、本当にそれにそれほど多くはありません.あなたのビューバインディングにハンドルを保存し、あなたのWebSocketクライアントにActivity
:class MainActivity : AppCompatActivity() {
private lateinit var ui: ActivityMainBinding
private lateinit var ws: WebSocket
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ui = ActivityMainBinding.inflate(layoutInflater)
setContentView(ui.root)
connect() // As above
}
からのAPIを呼び出す
KTORは、あなたがCoroutinesを使用していて、あなた自身の範囲/文脈を管理しているという仮定で造られます.これは、より柔軟なツールになりますが、いくつかの追加の複雑さを追加します.
ツールの基本的な設定は以下のようになります.
private suspend fun connect(ktor: HttpClient, u: Url) {
ktor.wss(Get, u.host, u.port, u.encodedPath) {
// Access to a WebSocket session
}
}
private /* not suspend */ fun connect() {
val url = Url("wss://azgu36n0vf.execute-api.us-east-1.amazonaws.com/Prod")
val ktor = HttpClient(OkHttp) {
install(WebSockets)
}
lifecycleScope.launch(Dispatchers.IO) {
connect(ktor, url)
}
}
末尾の閉鎖の内部では、 DefaultClientWebSocketSession
. それには2つの重要なメンバーがあります.ReceiveChannel
名前ingoing
, and SendChannel
名前outgoing
. SendChannel
and ReceiveChannel
コリンの入口と出口 Channel
, これは基本的にはサスペンションのキューのようです.WebSocketセッションの閉鎖の中にいくつかの簡単なメッセージを送受信するのはかなり些細なことです.
ktor.wss(Get, u.host, u.port, u.encodedPath) {
// Send a message outbound
val json = JSONObject()
.put("action", "sendmessage")
.put("data", "Hello from Android!")
.toString()
outgoing.send(Frame.Text(json))
// Receive an inbound message
val frame = incoming.receive()
if (frame is Frame.Text) {
ui.status.append(frame.readText())
}
}
しかし、我々は我々が我々のOKHTTP解決で持っていた機能の束を逃しています.つまりKTORにおける並列送受信
我々の目標は、最終的にメッセージの流れを派遣することです
outgoing
チャンネルからのメッセージの流れを消費するingoing
チャンネル、同時に.我々が使用する基本的なアプローチは、2ビットの仕事を非同期的に起動し、それらを終了するのを待つことです.ktor.wss(Get, u.host, u.port, u.encodedPath) {
awaitAll(async {
// Code that will send messages
}, async {
// Code that will receive messages
})
}
送信メッセージをトリガーするイベントが必要です.UIにボタン要素を追加すると意味があります.しかし、我々はコマンドの流れとしてボタンクリックをモデル化したいと思います.最初にボタンクリックをマップ化する拡張機能を作成しましょう
Flow<Unit>
信用StackOverflow ):private fun View.clicks(): Flow<Unit> = callbackFlow {
setOnClickListener { offer(Unit) }
awaitClose { setOnClickListener(null) }
}
今、我々はボタンからイベントの流れを聞くことができます、我々が必要とする形式にそれらを写像して、彼らを送ってください:ui.button.clicks()
.map { click -> "Hello from Android!" }
.map { message -> JSONObject()
.put("action", "sendmessage")
.put("data", message)
.toString()
}
.map { json -> Frame.Text(json) }
.collect { outgoing.send(it) }
それは出てくる出来事によく役立つだろう.今、我々はちょうど2番目のインバウンドイベントに対応する必要がありますasync
ブロック.この場合、結果をマップする値はあまりありません.ソケット上で受信する値は、
"data"
メッセージのキー.例えば、我々は得るかもしれない"Hello from Android!"
:incoming.consumeEach { frame ->
if (frame is Frame.Text) {
ui.status.append(frame.readText())
}
}
それがすべて言われて、されるとき、我々はこれのような何かで終わります:ktor.wss(Get, u.host, u.port, u.encodedPath) {
awaitAll(async {
ui.button.clicks()
.map { click -> JSONObject()
.put("action", "sendmessage")
.put("data", "Hello from Android!")
.toString()
}
.map { json -> Frame.Text(json) }
.collect { outgoing.send(it) }
}, async {
incoming.consumeEach { frame ->
if (frame is Frame.Text) {
ui.status.append(frame.readText())
}
}
}
})
ライフサイクルイベント
OkHTTPは、コールバックを
WebSocketListener
, さまざまなライフサイクルイベントを通知するval listener = WebSocketListener() {
override fun onOpen(ws: WebSocket, res: Response) {
// when WebSocket is first opened
}
override fun onClosed(ws: WebSocket, code: Int, reason: String) {
// when WebSocket is closed
}
}
Ktorはそのように動作しません.彼らはdifferent approaches to recover those events .回復する最も簡単なものはソケットが開くときのイベントです.それは、中で起こる最初のものだけです
wss
セッションの閉鎖:ktor.wss(Get, u.host, u.port, u.encodedPath) {
ui.status.append("Connected to $u!")
}
WebSocketの終了についての洞察を得るには、受信ブロックで処理を展開できます.incoming.consumeEach { frame ->
when (frame) {
is Frame.Text -> { /* as above */ }
is Frame.Close -> {
val reason = closeReason.await()!!.message
ui.status.append("Closing: $reason")
}
}
}
失敗を捕らえるのもかなり簡単です.private fun connect() {
val url = Url("wss://azgu36n0vf.execute-api.us-east-1.amazonaws.com/Prod")
val client = HttpClient(OkHttp) {
install(WebSockets)
}
lifecycleScope.launch(Dispatchers.IO) {
try {
connect(client, url)
} catch (e: Throwable) {
val message = "WebSocket failed: ${e.message}"
ui.status.append(message)
}
}
}
ラッピング
さて、OkHTTPとKTORを使用してAmazon APIゲートウェイWebSockets APIを消費する方法についての、荒々しく説明できない説明があります.🥳.
The code for this project is available on my GitHub page .
Reference
この問題について(のためのアンドロイドWebSocketクライアント), 我々は、より多くの情報をここで見つけました https://dev.to/jameson/android-websocket-clients-for-amazon-api-gateway-1oa8テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol