feat: 增加密码连接
This commit is contained in:
@@ -15,6 +15,8 @@ import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.RadioGroup;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -62,6 +64,8 @@ public class MainActivity extends AppCompatActivity {
|
||||
private final Gson gson = new Gson();
|
||||
private String myDeviceId;
|
||||
private String targetDeviceId;
|
||||
private String pendingAuthType;
|
||||
private String pendingAuthValue;
|
||||
|
||||
private final Handler statsHandler = new Handler(Looper.getMainLooper());
|
||||
private final Runnable statsRunnable = new Runnable() {
|
||||
@@ -105,7 +109,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
myDeviceId = DeviceUtils.getSerialNumber(this);
|
||||
etDeviceId.setText(myDeviceId);
|
||||
|
||||
btnConnect.setOnClickListener(v -> connectToControlled());
|
||||
btnConnect.setOnClickListener(v -> showAuthDialog());
|
||||
btnDisconnect.setOnClickListener(v -> disconnect());
|
||||
|
||||
// 初始化 EGL 和远端视频渲染
|
||||
@@ -210,6 +214,56 @@ public class MainActivity extends AppCompatActivity {
|
||||
});
|
||||
}
|
||||
|
||||
/** 弹出鉴权输入对话框:选择动态验证码或固定密码,输入后发起连接。 */
|
||||
private void showAuthDialog() {
|
||||
String serverUrl = etServerUrl.getText().toString().trim();
|
||||
String target = etTargetDeviceId.getText().toString().trim();
|
||||
String myId = etDeviceId.getText().toString().trim();
|
||||
if (serverUrl.isEmpty() || target.isEmpty() || myId.isEmpty()) {
|
||||
Toast.makeText(this, "请先填写服务器地址、设备ID和目标设备ID", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
View view = getLayoutInflater().inflate(R.layout.dialog_auth_input, null);
|
||||
RadioGroup rg = view.findViewById(R.id.rg_auth_type);
|
||||
EditText et = view.findViewById(R.id.et_auth_value);
|
||||
TextView tip = view.findViewById(R.id.tv_auth_tip);
|
||||
|
||||
rg.setOnCheckedChangeListener((group, checkedId) -> {
|
||||
if (checkedId == R.id.rb_password) {
|
||||
et.setHint("请输入固定密码");
|
||||
tip.setText("固定密码为被控端设置的固定密码");
|
||||
} else {
|
||||
et.setHint("请输入动态验证码");
|
||||
tip.setText("动态验证码为被控端界面显示的 6 位大小写字母与数字组合");
|
||||
}
|
||||
});
|
||||
|
||||
AlertDialog dialog = new AlertDialog.Builder(this)
|
||||
.setTitle("连接鉴权")
|
||||
.setView(view)
|
||||
.setNegativeButton("取消", null)
|
||||
.setPositiveButton("连接", null)
|
||||
.create();
|
||||
|
||||
// 校验失败时不关闭对话框,引导用户重新输入
|
||||
dialog.setOnShowListener(d -> dialog.getButton(AlertDialog.BUTTON_POSITIVE)
|
||||
.setOnClickListener(v -> {
|
||||
boolean isPassword = (rg.getCheckedRadioButtonId() == R.id.rb_password);
|
||||
String authType = isPassword ? "PASSWORD" : "CODE";
|
||||
String authValue = et.getText().toString().trim();
|
||||
if (authValue.isEmpty()) {
|
||||
Toast.makeText(MainActivity.this, "请输入验证码或密码", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
pendingAuthType = authType;
|
||||
pendingAuthValue = authValue;
|
||||
dialog.dismiss();
|
||||
connectToControlled();
|
||||
}));
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void connectToControlled() {
|
||||
String serverUrl = etServerUrl.getText().toString().trim();
|
||||
targetDeviceId = etTargetDeviceId.getText().toString().trim();
|
||||
@@ -283,7 +337,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
});
|
||||
}
|
||||
});
|
||||
webRtcClient.createOffer(targetDeviceId, remoteVideoView);
|
||||
webRtcClient.createOffer(targetDeviceId, remoteVideoView, pendingAuthType, pendingAuthValue);
|
||||
}
|
||||
|
||||
private void handleSignalMessage(SignalMessage message) {
|
||||
@@ -330,17 +384,29 @@ public class MainActivity extends AppCompatActivity {
|
||||
*/
|
||||
private void handleConnectionRejected(SignalMessage message) {
|
||||
String targetId = message.getToDeviceId();
|
||||
String payload = message.getPayload();
|
||||
String text = (payload != null && !payload.isEmpty())
|
||||
? payload
|
||||
: "目标被控端拒绝了连接请求";
|
||||
String finalText = text;
|
||||
String reason = parseReason(message.getPayload());
|
||||
String finalText = reason;
|
||||
runOnUiThread(() -> {
|
||||
tvStatus.setText("状态: " + finalText);
|
||||
Toast.makeText(MainActivity.this, finalText, Toast.LENGTH_LONG).show();
|
||||
updateUI(false);
|
||||
});
|
||||
Log.w(TAG, "Connection request to " + targetId + " was rejected by controlled device");
|
||||
Log.w(TAG, "Connection request to " + targetId + " was rejected: " + reason);
|
||||
}
|
||||
|
||||
/** 解析拒绝原因:优先读取 JSON 中的 reason 字段,否则直接返回原文。 */
|
||||
private String parseReason(String payload) {
|
||||
if (payload == null || payload.isEmpty()) {
|
||||
return "目标被控端拒绝了连接请求";
|
||||
}
|
||||
try {
|
||||
JsonObject obj = gson.fromJson(payload, JsonObject.class);
|
||||
if (obj != null && obj.has("reason") && !obj.get("reason").isJsonNull()) {
|
||||
return obj.get("reason").getAsString();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,8 @@ public class SignalMessage {
|
||||
private String toDeviceId;
|
||||
private String deviceType;
|
||||
private String payload;
|
||||
private String authType;
|
||||
private String authValue;
|
||||
|
||||
public SignalMessage() {}
|
||||
|
||||
@@ -31,4 +33,10 @@ public class SignalMessage {
|
||||
|
||||
public String getPayload() { return payload; }
|
||||
public void setPayload(String payload) { this.payload = payload; }
|
||||
|
||||
public String getAuthType() { return authType; }
|
||||
public void setAuthType(String authType) { this.authType = authType; }
|
||||
|
||||
public String getAuthValue() { return authValue; }
|
||||
public void setAuthValue(String authValue) { this.authValue = authValue; }
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ public class WebRtcClient {
|
||||
private final WebSocketClient wsClient;
|
||||
private final String deviceId;
|
||||
private final Gson gson = new Gson();
|
||||
private String pendingAuthType;
|
||||
private String pendingAuthValue;
|
||||
|
||||
private PeerConnectionFactory peerConnectionFactory;
|
||||
private PeerConnection peerConnection;
|
||||
@@ -89,8 +91,11 @@ public class WebRtcClient {
|
||||
.createPeerConnectionFactory();
|
||||
}
|
||||
|
||||
public void createOffer(String controlledId, SurfaceViewRenderer remoteRenderer) {
|
||||
public void createOffer(String controlledId, SurfaceViewRenderer remoteRenderer,
|
||||
String authType, String authValue) {
|
||||
this.currentControlledId = controlledId;
|
||||
this.pendingAuthType = authType;
|
||||
this.pendingAuthValue = authValue;
|
||||
|
||||
List<PeerConnection.IceServer> iceServers = new ArrayList<>();
|
||||
// 添加 STUN 和 TURN 服务器
|
||||
@@ -309,6 +314,8 @@ public class WebRtcClient {
|
||||
msg.setFromDeviceId(deviceId);
|
||||
msg.setToDeviceId(controlledId);
|
||||
msg.setDeviceType("CONTROLLER");
|
||||
if (pendingAuthType != null) msg.setAuthType(pendingAuthType);
|
||||
if (pendingAuthValue != null) msg.setAuthValue(pendingAuthValue);
|
||||
|
||||
JsonObject payload = new JsonObject();
|
||||
payload.addProperty("sdp", sdp);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?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"
|
||||
android:padding="24dp">
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/rg_auth_type"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_code"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:text="动态验证码" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_password"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="固定密码" />
|
||||
</RadioGroup>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_auth_value"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:hint="请输入动态验证码"
|
||||
android:inputType="textVisiblePassword" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_auth_tip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="动态验证码为被控端界面显示的 6 位大小写字母与数字组合"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#888888" />
|
||||
</LinearLayout>
|
||||
Reference in New Issue
Block a user