From de3f9462e020ad2f4c7302ec07fa808d177cec95 Mon Sep 17 00:00:00 2001
From: 夜雨飘零 <yeyupiaoling@foxmail.com>
Date: 星期三, 18 十月 2023 16:20:35 +0800
Subject: [PATCH] change send data size (#1014)
---
funasr/runtime/android/images/image3.png | 0
funasr/runtime/android/AndroidClient/app/src/main/res/layout/dialog_input_hotwords.xml | 18 +++
funasr/runtime/android/AndroidClient/app/src/main/res/drawable/logo.png | 0
funasr/runtime/android/images/image1.png | 0
funasr/runtime/android/AndroidClient/app/src/main/java/com/yeyupiaoling/androidclient/SSLSocketClient.java | 71 ++++++++++++++
funasr/runtime/android/AndroidClient/app/src/main/java/com/yeyupiaoling/androidclient/MainActivity.java | 165 +++++++++++++++++++++++++-------
/dev/null | 0
funasr/runtime/android/readme.md | 13 ++
funasr/runtime/android/AndroidClient/app/src/main/res/menu/menu.xml | 9 +
funasr/runtime/android/AndroidClient/app/src/main/res/drawable/edittext_border.xml | 4
funasr/runtime/android/images/QRcode.png | 0
funasr/runtime/android/images/image2.png | 0
funasr/runtime/android/AndroidClient/app/src/main/AndroidManifest.xml | 4
funasr/runtime/android/AndroidClient/app/src/main/res/layout/dialog_input_uri.xml | 15 +++
14 files changed, 255 insertions(+), 44 deletions(-)
diff --git a/funasr/runtime/android/AndroidClient/app/src/main/AndroidManifest.xml b/funasr/runtime/android/AndroidClient/app/src/main/AndroidManifest.xml
index 19af8b3..74c5d0c 100644
--- a/funasr/runtime/android/AndroidClient/app/src/main/AndroidManifest.xml
+++ b/funasr/runtime/android/AndroidClient/app/src/main/AndroidManifest.xml
@@ -10,9 +10,9 @@
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
- android:icon="@mipmap/ic_launcher"
+ android:icon="@drawable/logo"
android:label="@string/app_name"
- android:roundIcon="@mipmap/ic_launcher_round"
+ android:roundIcon="@drawable/logo"
android:supportsRtl="true"
android:theme="@style/Theme.AndroidClient"
tools:targetApi="31">
diff --git a/funasr/runtime/android/AndroidClient/app/src/main/java/com/yeyupiaoling/androidclient/MainActivity.java b/funasr/runtime/android/AndroidClient/app/src/main/java/com/yeyupiaoling/androidclient/MainActivity.java
index 1ea426a..be14bd3 100644
--- a/funasr/runtime/android/AndroidClient/app/src/main/java/com/yeyupiaoling/androidclient/MainActivity.java
+++ b/funasr/runtime/android/AndroidClient/app/src/main/java/com/yeyupiaoling/androidclient/MainActivity.java
@@ -2,26 +2,31 @@
import android.Manifest;
import android.annotation.SuppressLint;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
+import android.widget.EditText;
import android.widget.TextView;
+import android.widget.Toast;
import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-
-import javax.net.ssl.HostnameVerifier;
import okhttp3.OkHttpClient;
import okhttp3.Request;
@@ -32,8 +37,15 @@
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
- // WebSocket鍦板潃锛屽鏋滄湇鍔$娌℃湁浣跨敤SSL锛岃浣跨敤ws://
- public static final String ASR_HOST = "wss://192.168.0.1:10095";
+ // WebSocket鍦板潃
+ public String ASR_HOST = "";
+ // 鍙戦�佺殑JSON鏁版嵁
+ public static final String MODE = "2pass";
+ public static final String CHUNK_SIZE = "5, 10, 5";
+ public static final int CHUNK_INTERVAL = 10;
+ public static final int SEND_SIZE = 1920;
+ // 鐑瘝
+ private String hotWords = "闃块噷宸村反 杈炬懇闄� 澶滈洦椋橀浂";
// 閲囨牱鐜�
public static final int SAMPLE_RATE = 16000;
// 澹伴亾鏁�
@@ -42,10 +54,10 @@
public static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
private AudioRecord audioRecord;
private boolean isRecording = false;
- private int minBufferSize;
private AudioView audioView;
private String allAsrText = "";
private String asrText = "";
+ private SharedPreferences sharedPreferences;
// 鎺т欢
private Button recordBtn;
private TextView resultText;
@@ -60,8 +72,6 @@
if (!hasPermission()) {
requestPermission();
}
- // 褰曢煶鍙傛暟
- minBufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL, AUDIO_FORMAT);
// 鏄剧ず璇嗗埆缁撴灉鎺т欢
resultText = findViewById(R.id.result_text);
// 鏄剧ず褰曢煶鐘舵�佹帶浠�
@@ -71,22 +81,100 @@
recordBtn = findViewById(R.id.record_button);
recordBtn.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_UP) {
- isRecording = false;
- stopRecording();
- recordBtn.setText("鎸変笅褰曢煶");
- } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
- if (webSocket != null){
- webSocket.cancel();
- webSocket = null;
+ if (!ASR_HOST.equals("")) {
+ isRecording = false;
+ stopRecording();
+ recordBtn.setText("鎸変笅褰曢煶");
}
- allAsrText = "";
- asrText = "";
- isRecording = true;
- startRecording();
- recordBtn.setText("褰曢煶涓�...");
+ } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ if (!ASR_HOST.equals("")) {
+ allAsrText = "";
+ asrText = "";
+ isRecording = true;
+ startRecording();
+ recordBtn.setText("褰曢煶涓�...");
+ }
}
return true;
});
+ // 璇诲彇WebSocket鍦板潃
+ sharedPreferences = getSharedPreferences("FunASR", MODE_PRIVATE);
+ String uri = sharedPreferences.getString("uri", "");
+ if (uri.equals("")) {
+ showUriInput();
+ } else {
+ ASR_HOST = uri;
+ }
+ // 璇诲彇鐑瘝
+ String hotWords = sharedPreferences.getString("hotwords", "");
+ if (!hotWords.equals("")) {
+ this.hotWords = hotWords;
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+ int id = item.getItemId();
+ if (id == R.id.change_uri) {
+ showUriInput();
+ return true;
+ } else if (id == R.id.change_hotwords) {
+ showHotWordsInput();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ // 鏄剧ずWebSocket鍦板潃杈撳叆妗�
+ private void showUriInput() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
+ builder.setTitle("璇疯緭鍏ebSocket鍦板潃锛�");
+ View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.dialog_input_uri, null);
+ final EditText input = view.findViewById(R.id.uri_edit_text);
+ if (!ASR_HOST.equals("")) {
+ input.setText(ASR_HOST);
+ }
+ builder.setView(view);
+ builder.setPositiveButton("纭畾", (dialog, id) -> {
+ ASR_HOST = input.getText().toString();
+ if (!ASR_HOST.equals("")) {
+ Toast.makeText(MainActivity.this, "WebSocket鍦板潃锛�" + ASR_HOST, Toast.LENGTH_SHORT).show();
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putString("uri", ASR_HOST);
+ editor.apply();
+ }
+ });
+ AlertDialog dialog = builder.create();
+ dialog.show();
+ }
+
+ // 鏄剧ず鐑瘝杈撳叆妗�
+ private void showHotWordsInput() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
+ builder.setTitle("璇疯緭鍏ョ儹璇嶏細");
+ View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.dialog_input_hotwords, null);
+ final EditText input = view.findViewById(R.id.hotwords_edit_text);
+ if (!this.hotWords.equals("")) {
+ input.setText(this.hotWords);
+ }
+ builder.setView(view);
+ builder.setPositiveButton("纭畾", (dialog, id) -> {
+ String hotwords = input.getText().toString();
+ if (!hotwords.equals("")) {
+ this.hotWords = hotwords;
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putString("hotwords", hotwords);
+ editor.apply();
+ }
+ });
+ AlertDialog dialog = builder.create();
+ dialog.show();
}
// 寮�濮嬪綍闊�
@@ -94,12 +182,12 @@
// 鍑嗗褰曢煶鍣�
try {
// 纭繚鏈夋潈闄�
- if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
+ if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
requestPermission();
return;
}
// 鍒涘缓褰曢煶鍣�
- audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE, CHANNEL, AUDIO_FORMAT, minBufferSize);
+ audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE, CHANNEL, AUDIO_FORMAT, SEND_SIZE);
} catch (IllegalStateException e) {
e.printStackTrace();
}
@@ -127,14 +215,12 @@
// 璇诲彇褰曢煶鏁版嵁
private void setAudioData() throws Exception {
- // 濡傛灉浣跨敤姝e父鐨剋ss锛屽彲浠ュ幓鎺夎繖涓�
- HostnameVerifier hostnameVerifier = (hostname, session) -> {
- // 鎬绘槸杩斿洖true锛岃〃绀轰笉楠岃瘉鍩熷悕
- return true;
- };
// 寤虹珛WebSocket杩炴帴
OkHttpClient client = new OkHttpClient.Builder()
- .hostnameVerifier(hostnameVerifier)
+ // 蹇界暐楠岃瘉璇佷功
+ .sslSocketFactory(SSLSocketClient.getSSLSocketFactory(), SSLSocketClient.getX509TrustManager())
+ // 涓嶉獙璇佸煙鍚�
+ .hostnameVerifier(SSLSocketClient.getHostnameVerifier())
.build();
Request request = new Request.Builder()
.url(ASR_HOST)
@@ -145,6 +231,7 @@
public void onOpen(@NonNull WebSocket webSocket, @NonNull Response response) {
// 杩炴帴鎴愬姛鏃剁殑澶勭悊
Log.d(TAG, "WebSocket杩炴帴鎴愬姛");
+ runOnUiThread(() -> Toast.makeText(MainActivity.this, "WebSocket杩炴帴鎴愬姛", Toast.LENGTH_SHORT).show());
}
@Override
@@ -189,15 +276,16 @@
public void onFailure(@NonNull WebSocket webSocket, @NonNull Throwable t, Response response) {
// 杩炴帴澶辫触鏃剁殑澶勭悊
Log.d(TAG, "WebSocket杩炴帴澶辫触: " + t + ": " + response);
+ runOnUiThread(() -> Toast.makeText(MainActivity.this, "WebSocket杩炴帴澶辫触锛�" + t, Toast.LENGTH_SHORT).show());
}
});
- String message = getMessage("2pass", "5, 10, 5", 10, true);
+ String message = getMessage(true);
webSocket.send(message);
audioRecord.startRecording();
- byte[] bytes = new byte[minBufferSize];
+ byte[] bytes = new byte[SEND_SIZE];
while (isRecording) {
- int readSize = audioRecord.read(bytes, 0, minBufferSize);
+ int readSize = audioRecord.read(bytes, 0, SEND_SIZE);
if (readSize > 0) {
ByteString byteString = ByteString.of(bytes);
webSocket.send(byteString);
@@ -211,20 +299,19 @@
}
// 鍙戦�佺涓�姝ョ殑JSON鏁版嵁
- public String getMessage(String mode, String strChunkSize, int chunkInterval, boolean isSpeaking) {
+ public String getMessage(boolean isSpeaking) {
try {
JSONObject obj = new JSONObject();
- obj.put("mode", mode);
+ obj.put("mode", MODE);
JSONArray array = new JSONArray();
- String[] chunkList = strChunkSize.split(",");
+ String[] chunkList = CHUNK_SIZE.split(",");
for (String s : chunkList) {
array.put(Integer.valueOf(s.trim()));
}
obj.put("chunk_size", array);
- obj.put("chunk_interval", chunkInterval);
+ obj.put("chunk_interval", CHUNK_INTERVAL);
obj.put("wav_name", "default");
- // 鐑瘝
- obj.put("hotwords", "闃块噷宸村反 杈炬懇闄�");
+ obj.put("hotwords", hotWords);
obj.put("wav_format", "pcm");
obj.put("is_speaking", isSpeaking);
return obj.toString();
@@ -236,13 +323,13 @@
// 妫�鏌ユ潈闄�
private boolean hasPermission() {
- return checkSelfPermission(android.Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED &&
- checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
+ return checkSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED &&
+ checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
// 璇锋眰鏉冮檺
private void requestPermission() {
- requestPermissions(new String[]{android.Manifest.permission.RECORD_AUDIO,
+ requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO,
Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
}
\ No newline at end of file
diff --git a/funasr/runtime/android/AndroidClient/app/src/main/java/com/yeyupiaoling/androidclient/SSLSocketClient.java b/funasr/runtime/android/AndroidClient/app/src/main/java/com/yeyupiaoling/androidclient/SSLSocketClient.java
new file mode 100644
index 0000000..0bc190a
--- /dev/null
+++ b/funasr/runtime/android/AndroidClient/app/src/main/java/com/yeyupiaoling/androidclient/SSLSocketClient.java
@@ -0,0 +1,71 @@
+package com.yeyupiaoling.androidclient;
+
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+public class SSLSocketClient {
+ //鑾峰彇SSLSocketFactory
+ public static SSLSocketFactory getSSLSocketFactory() {
+ try {
+ SSLContext sslContext = SSLContext.getInstance("SSL");
+ sslContext.init(null, getTrustManager(), new SecureRandom());
+ return sslContext.getSocketFactory();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ //鑾峰彇X509TrustManager
+ public static X509TrustManager getX509TrustManager() {
+ X509TrustManager x509TrustManager = new X509TrustManager() {
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+ };
+ return x509TrustManager;
+ }
+
+ //鑾峰彇TrustManager
+ private static TrustManager[] getTrustManager() {
+ TrustManager[] trustAllCerts = new TrustManager[]{
+ new X509TrustManager() {
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType) {
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType) {
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[]{};
+ }
+ }
+ };
+ return trustAllCerts;
+ }
+
+ //鑾峰彇HostnameVerifier
+ public static HostnameVerifier getHostnameVerifier() {
+ HostnameVerifier hostnameVerifier = (s, sslSession) -> true;
+ return hostnameVerifier;
+ }
+}
+
diff --git a/funasr/runtime/android/AndroidClient/app/src/main/res/drawable/edittext_border.xml b/funasr/runtime/android/AndroidClient/app/src/main/res/drawable/edittext_border.xml
new file mode 100644
index 0000000..a278e3c
--- /dev/null
+++ b/funasr/runtime/android/AndroidClient/app/src/main/res/drawable/edittext_border.xml
@@ -0,0 +1,4 @@
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <stroke android:width="1dp" android:color="#000000" />
+ <padding android:left="5dp" android:top="5dp" android:right="5dp" android:bottom="5dp" />
+</shape>
\ No newline at end of file
diff --git a/funasr/runtime/android/AndroidClient/app/src/main/res/drawable/logo.png b/funasr/runtime/android/AndroidClient/app/src/main/res/drawable/logo.png
new file mode 100644
index 0000000..96b2bab
--- /dev/null
+++ b/funasr/runtime/android/AndroidClient/app/src/main/res/drawable/logo.png
Binary files differ
diff --git a/funasr/runtime/android/AndroidClient/app/src/main/res/layout/dialog_input_hotwords.xml b/funasr/runtime/android/AndroidClient/app/src/main/res/layout/dialog_input_hotwords.xml
new file mode 100644
index 0000000..8ee1e16
--- /dev/null
+++ b/funasr/runtime/android/AndroidClient/app/src/main/res/layout/dialog_input_hotwords.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <EditText
+ android:id="@+id/hotwords_edit_text"
+ android:layout_width="match_parent"
+ android:layout_height="200dp"
+ android:layout_margin="10dp"
+ android:inputType="textMultiLine"
+ android:background="@drawable/edittext_border"
+ android:minLines="3"
+ android:gravity="top"
+ android:hint="姣忎釜鐑瘝鐢ㄧ┖鏍奸殧寮�" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/funasr/runtime/android/AndroidClient/app/src/main/res/layout/dialog_input_uri.xml b/funasr/runtime/android/AndroidClient/app/src/main/res/layout/dialog_input_uri.xml
new file mode 100644
index 0000000..f172dca
--- /dev/null
+++ b/funasr/runtime/android/AndroidClient/app/src/main/res/layout/dialog_input_uri.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <EditText
+ android:id="@+id/uri_edit_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp"
+ android:background="@drawable/edittext_border"
+ android:hint="wss://" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/funasr/runtime/android/AndroidClient/app/src/main/res/menu/menu.xml b/funasr/runtime/android/AndroidClient/app/src/main/res/menu/menu.xml
new file mode 100644
index 0000000..86ec93f
--- /dev/null
+++ b/funasr/runtime/android/AndroidClient/app/src/main/res/menu/menu.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:id="@+id/change_uri"
+ android:title="鏈嶅姟鍦板潃" />
+ <item
+ android:id="@+id/change_hotwords"
+ android:title="鐑瘝" />
+</menu>
\ No newline at end of file
diff --git a/funasr/runtime/android/images/QRcode.png b/funasr/runtime/android/images/QRcode.png
new file mode 100644
index 0000000..fa2e441
--- /dev/null
+++ b/funasr/runtime/android/images/QRcode.png
Binary files differ
diff --git a/funasr/runtime/android/images/demo.png b/funasr/runtime/android/images/demo.png
deleted file mode 100644
index 1b5047d..0000000
--- a/funasr/runtime/android/images/demo.png
+++ /dev/null
Binary files differ
diff --git a/funasr/runtime/android/images/image1.png b/funasr/runtime/android/images/image1.png
new file mode 100644
index 0000000..3a287f0
--- /dev/null
+++ b/funasr/runtime/android/images/image1.png
Binary files differ
diff --git a/funasr/runtime/android/images/image2.png b/funasr/runtime/android/images/image2.png
new file mode 100644
index 0000000..730e284
--- /dev/null
+++ b/funasr/runtime/android/images/image2.png
Binary files differ
diff --git a/funasr/runtime/android/images/image3.png b/funasr/runtime/android/images/image3.png
new file mode 100644
index 0000000..b1aa37e
--- /dev/null
+++ b/funasr/runtime/android/images/image3.png
Binary files differ
diff --git a/funasr/runtime/android/readme.md b/funasr/runtime/android/readme.md
index e0427c7..3a48957 100644
--- a/funasr/runtime/android/readme.md
+++ b/funasr/runtime/android/readme.md
@@ -2,12 +2,19 @@
鍏堣鏄庯紝鏈」鐩槸浣跨敤WebSocket杩炴帴鏈嶅姟鍣ㄧ殑璇煶璇嗗埆鏈嶅姟锛屽苟涓嶆槸灏咶unASR閮ㄧ讲鍒癆ndroid閲岋紝鏈嶅姟鍚姩鏂瑰紡璇锋煡鐪嬫枃妗SDK_advanced_guide_online_zh.md](https://github.com/alibaba-damo-academy/FunASR/blob/main/funasr/runtime/docs/SDK_advanced_guide_online_zh.md)銆�
-浣跨敤鏈�鏂扮殑 Android Studio 鎵撳紑`AndroidClient`椤圭洰锛岃繍琛屽嵆鍙紝鍦ㄨ繍琛屼箣鍓嶈繕闇�瑕佷慨鏀筦ASR_HOST`鍙傛暟锛岃鍙傛暟鏄闊宠瘑鍒湇鍔$殑WebSocket鎺ュ彛鍦板潃锛岄渶瑕佷慨澶嶄负寮�鍙戣�呰嚜宸辩殑鏈嶅姟鍦板潃銆�
+浣跨敤鏈�鏂扮殑 Android Studio 鎵撳紑`AndroidClient`椤圭洰锛岃繍琛屽嵆鍙�備篃鍙互鐩存帴涓嬭浇[APK瀹夎鍖匽(https://yeyupiaoling.cn/AndroidClient.apk)瀹夎浣跨敤锛屾垨鑰呬娇鐢ㄦ墜鏈烘壂鐮佷笅杞姐��
-搴旂敤鍙湁涓�涓姛鑳斤紝鎸夐挳涓嬪紑濮嬭瘑鍒紝鏉惧紑鎸夐挳缁撴潫璇嗗埆銆�
+<div align="center">
+ <img src="./images/QRcode.png" alt="APK瀹夎鍖�" width="300">
+</div>
+
+
+搴旂敤鍙湁涓�涓姛鑳斤紝鎸夐挳涓嬪紑濮嬭瘑鍒紝鏉惧紑鎸夐挳缁撴潫璇嗗埆銆傜涓�娆℃墦寮�搴旂敤闇�瑕佽缃甒ebSocket鐨勫湴鍧�锛屼篃鍙互鍦ㄨ彍鍗曟爮淇敼锛屽悓鏃朵篃鍙互鍦ㄨ彍鍗曟爮淇敼鐑瘝銆�
搴旂敤鏁堟灉鍥撅細
<div align="center">
- <img src="./images/demo.png" alt="搴旂敤鏁堟灉鍥�" width="300">
+ <img src="./images/image1.png" alt="搴旂敤鏁堟灉鍥�" width="300">
+ <img src="./images/image2.png" alt="搴旂敤鏁堟灉鍥�" width="300">
+ <img src="./images/image3.png" alt="搴旂敤鏁堟灉鍥�" width="300">
</div>
--
Gitblit v1.9.1