aboutsummaryrefslogtreecommitdiff
path: root/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main')
-rw-r--r--app/src/main/java/invalid/lena/scrcpy/Devices.java44
-rw-r--r--app/src/main/java/invalid/lena/scrcpy/Main.java58
-rw-r--r--app/src/main/res/layout/main.xml43
-rw-r--r--app/src/main/res/values/strings.xml13
4 files changed, 92 insertions, 66 deletions
diff --git a/app/src/main/java/invalid/lena/scrcpy/Devices.java b/app/src/main/java/invalid/lena/scrcpy/Devices.java
index c3e5141..0ba61a3 100644
--- a/app/src/main/java/invalid/lena/scrcpy/Devices.java
+++ b/app/src/main/java/invalid/lena/scrcpy/Devices.java
@@ -30,9 +30,13 @@ public final class Devices {
this.port = port;
}
+ // Bracket IPv6 literals so the port stays unambiguous. Round-trips
+ // through parseAddress().
@Override
public String toString() {
- return host + ":" + port;
+ return host.indexOf(':') < 0
+ ? host + ":" + port
+ : "[" + host + "]:" + port;
}
@Override
@@ -49,6 +53,44 @@ public final class Devices {
private Devices() {}
+ // Parse "host:port" exactly as the target's Wireless debugging screen
+ // prints it. IPv6 literals must be bracketed ("[fe80::1]:5555") because
+ // the address itself contains colons; an unbracketed one is rejected
+ // rather than silently split at the wrong colon. Returns null on
+ // anything malformed - the only caller is a text field.
+ public static Device parseAddress(String s) {
+ if (s == null) return null;
+ s = s.trim();
+ String host, port;
+ if (s.startsWith("[")) {
+ int end = s.indexOf(']');
+ if (end < 0 || !s.startsWith("]:", end)) return null;
+ host = s.substring(1, end);
+ port = s.substring(end + 2);
+ } else {
+ int colon = s.indexOf(':');
+ if (colon < 0 || colon != s.lastIndexOf(':')) return null;
+ host = s.substring(0, colon);
+ port = s.substring(colon + 1);
+ }
+ int p = parsePort(port);
+ if (host.isEmpty() || p < 0) return null;
+ return new Device(host, p);
+ }
+
+ // Digits only, 1-65535. Returns -1 if it is not a usable port.
+ // Integer.parseInt() alone would accept "+5555" and " 5555".
+ public static int parsePort(String s) {
+ if (s == null) return -1;
+ s = s.trim();
+ if (s.isEmpty() || s.length() > 5) return -1;
+ for (int i = 0; i < s.length(); i++) {
+ if (s.charAt(i) < '0' || s.charAt(i) > '9') return -1;
+ }
+ int p = Integer.parseInt(s);
+ return p >= 1 && p <= 65535 ? p : -1;
+ }
+
// Pure-java parse: returns whatever rows are well-formed; logs and
// skips anything malformed instead of nuking the list.
public static List<Device> parse(String json) {
diff --git a/app/src/main/java/invalid/lena/scrcpy/Main.java b/app/src/main/java/invalid/lena/scrcpy/Main.java
index eb8d400..28a0870 100644
--- a/app/src/main/java/invalid/lena/scrcpy/Main.java
+++ b/app/src/main/java/invalid/lena/scrcpy/Main.java
@@ -18,12 +18,14 @@ import java.util.List;
// Pairing form + saved-device list.
//
-// Layout: host, pair-port, pair-code, connect-port + a single "Pair and save"
-// button. After a successful pair() against the daemon, the row is appended
-// to devices.json with the *connect* port (different from the pair port on
-// Android 11+). Tapping a saved row launches the Mirror activity with the
-// target host/port; Mirror owns its own Adb instance loaded from the same
-// on-disk keypair.
+// Layout: device address ("ip:port"), pair-port, pair-code + a single
+// "Pair and save" button. The address is the connect endpoint printed on
+// the target's Wireless debugging screen; pairing happens on a different,
+// short-lived port from the pairing dialog, against the same host. After a
+// successful pair() against the daemon, the row is appended to devices.json
+// with the *connect* port. Tapping a saved row launches the Mirror activity
+// with the target host/port; Mirror owns its own Adb instance loaded from
+// the same on-disk keypair.
public final class Main extends Activity {
private volatile Adb adb;
@@ -41,10 +43,9 @@ public final class Main extends Activity {
Ui.padForInsets(findViewById(R.id.root),
WindowInsets.Type.systemBars() | WindowInsets.Type.ime());
- EditText host = findViewById(R.id.host);
+ EditText address = findViewById(R.id.device_address);
EditText pairPort = findViewById(R.id.pair_port);
EditText pairCode = findViewById(R.id.pair_code);
- EditText connectPort = findViewById(R.id.connect_port);
pairButton = findViewById(R.id.pair);
View settingsBtn = findViewById(R.id.settings);
ListView devices = findViewById(R.id.devices);
@@ -89,7 +90,7 @@ public final class Main extends Activity {
Devices.Device d = adapter.getItem(pos);
new AlertDialog.Builder(this)
.setTitle(R.string.forget_device)
- .setMessage(d.host + ":" + d.port)
+ .setMessage(d.toString())
.setPositiveButton(android.R.string.ok, (dlg, w) -> {
Log.i("forget device: %s", d);
try {
@@ -110,41 +111,36 @@ public final class Main extends Activity {
pairButton.setOnClickListener(v -> {
if (adb == null) return; // still initialising
- String h = host.getText().toString().trim();
- String pp = pairPort.getText().toString().trim();
- String pc = pairCode.getText().toString().trim();
- String cp = connectPort.getText().toString().trim();
- if (TextUtils.isEmpty(h) || TextUtils.isEmpty(pp)
- || TextUtils.isEmpty(pc) || TextUtils.isEmpty(cp)) {
- Toast.makeText(this, "fill all four fields", Toast.LENGTH_SHORT).show();
+ // The saved endpoint is the address field verbatim; pairing
+ // reuses its host with the pairing port.
+ Devices.Device target = Devices.parseAddress(address.getText().toString());
+ if (target == null) {
+ Toast.makeText(this, R.string.bad_address, Toast.LENGTH_LONG).show();
return;
}
- int pairP, connP;
- try {
- pairP = Integer.parseInt(pp);
- connP = Integer.parseInt(cp);
- } catch (NumberFormatException e) {
- Toast.makeText(this, "ports must be numeric", Toast.LENGTH_SHORT).show();
+ int pairP = Devices.parsePort(pairPort.getText().toString());
+ if (pairP < 0) {
+ Toast.makeText(this, R.string.bad_pair_port, Toast.LENGTH_LONG).show();
return;
}
- if (pairP < 1 || pairP > 65535 || connP < 1 || connP > 65535) {
- Toast.makeText(this, "ports must be 1-65535", Toast.LENGTH_SHORT).show();
+ String pc = pairCode.getText().toString().trim();
+ if (TextUtils.isEmpty(pc)) {
+ Toast.makeText(this, R.string.bad_pair_code, Toast.LENGTH_LONG).show();
return;
}
pairButton.setEnabled(false);
Toast.makeText(this, R.string.pairing, Toast.LENGTH_SHORT).show();
- new Thread(() -> pairAndSave(h, pairP, pc, connP, pairButton), "pair").start();
+ new Thread(() -> pairAndSave(target, pairP, pc, pairButton), "pair").start();
});
}
- private void pairAndSave(String host, int pairPort, String code, int connPort, Button btn) {
+ private void pairAndSave(Devices.Device target, int pairPort, String code, Button btn) {
try {
- Log.i("pair: %s:%d", host, pairPort);
- boolean ok = adb.pair(host, pairPort, code);
+ Log.i("pair: %s:%d", target.host, pairPort);
+ boolean ok = adb.pair(target.host, pairPort, code);
if (!ok) throw new IllegalStateException("pair returned false");
- Log.i("pair ok host=%s pair_port=%d", host, pairPort);
- Devices.Device d = new Devices.Device(host, connPort);
- List<Devices.Device> updated = Devices.upsert(this, d);
+ Log.i("pair ok host=%s pair_port=%d", target.host, pairPort);
+ List<Devices.Device> updated = Devices.upsert(this, target);
runOnUiThread(() -> {
adapter.clear();
adapter.addAll(updated);
diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml
index 2e722b0..0b1273b 100644
--- a/app/src/main/res/layout/main.xml
+++ b/app/src/main/res/layout/main.xml
@@ -44,8 +44,10 @@
</LinearLayout>
- <!-- Pairing form. Fields are grouped and labelled by where their
- value comes from on the target's Wireless debugging screen. -->
+ <!-- Pairing form. Each field is one value the target already prints,
+ copied verbatim: the Wireless debugging screen shows the device
+ address as a single "ip:port" string, and the pairing dialog adds
+ its own port plus the code. -->
<LinearLayout
style="@style/Card"
android:layout_width="match_parent"
@@ -67,15 +69,22 @@
style="@style/FieldLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/label_host"/>
+ android:text="@string/label_address"/>
+
+ <TextView
+ style="@style/Caption"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/sub_address"/>
<EditText
- android:id="@+id/host"
+ android:id="@+id/device_address"
style="@style/Field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:hint="@string/host_hint"
- android:inputType="text"
+ android:layout_marginTop="@dimen/space_xs"
+ android:hint="@string/address_hint"
+ android:inputType="textUri"
android:autofillHints="postalAddress"/>
<TextView
@@ -120,28 +129,6 @@
</LinearLayout>
- <TextView
- style="@style/FieldLabel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/label_connect"/>
-
- <TextView
- style="@style/Caption"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/sub_connect"/>
-
- <EditText
- android:id="@+id/connect_port"
- style="@style/Field"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/space_xs"
- android:hint="@string/connect_port_hint"
- android:inputType="number"
- android:autofillHints="off"/>
-
<Button
android:id="@+id/pair"
style="@style/Button.Primary"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a9a552c..d7c45ac 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,16 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">scrcpy</string>
- <string name="host_hint">192.168.1.42</string>
+ <string name="address_hint">192.168.1.42:41234</string>
<string name="pair_port_hint">37123</string>
<string name="pair_code_hint">6 digits</string>
- <string name="connect_port_hint">41234</string>
<string name="pair_help">On the target: Settings &gt; Developer options &gt; Wireless debugging</string>
- <string name="label_host">Host / IP address</string>
+ <string name="label_address">Device address</string>
+ <string name="sub_address">The “IP address &amp; Port” on the Wireless debugging screen</string>
<string name="label_pairing">Pairing port and code</string>
- <string name="sub_pairing">From the “Pair device with pairing code” dialog</string>
- <string name="label_connect">Connection port</string>
- <string name="sub_connect">Shown on the Wireless debugging screen</string>
+ <string name="sub_pairing">From the “Pair device with pairing code” dialog. Same IP, different port</string>
+ <string name="bad_address">Enter the device address as 192.168.1.42:41234</string>
+ <string name="bad_pair_port">Pairing port must be a number from 1 to 65535</string>
+ <string name="bad_pair_code">Enter the 6-digit pairing code</string>
<string name="pair_and_save">Pair and save</string>
<string name="pair_a_device">Pair a device</string>
<string name="saved_devices">Saved devices</string>