From c5a49fc7b3d1d2acbd6875e9c8371d0ade684717 Mon Sep 17 00:00:00 2001 From: ericek111 Date: Fri, 25 Sep 2026 14:05:39 +0000 Subject: [PATCH] Avoid JDK APIs newer than Android's minSdk 33 in core Files.readString/writeString (API 36.1), Path.of, ByteBuffer.slice(int, int) and Matcher.appendReplacement(StringBuilder) (API 34) threw NoSuchMethodError on Android; connecting crashed in ChatLogStore. Each replacement keeps the original desktop code in a comment above it. Co-Authored-By: Claude Opus 5.5 --- .../src/main/java/com/ts3client/chatlog/ChatLogStore.java | 5 ++++- .../core/src/main/java/com/ts3client/config/AppDirs.java | 5 ++++- .../src/main/java/com/ts3client/contacts/ContactStore.java | 4 +++- .../main/java/com/ts3client/net/TeamspeakConnection.java | 6 ++++-- .../core/src/main/java/com/ts3client/sound/WaveFile.java | 6 +++++- .../core/src/main/java/com/ts3client/text/HtmlText.java | 4 +++- 6 files changed, 23 insertions(+), 7 deletions(-) diff --git a/ts3-client/core/src/main/java/com/ts3client/chatlog/ChatLogStore.java b/ts3-client/core/src/main/java/com/ts3client/chatlog/ChatLogStore.java index 8c5d36a..da7da14 100644 --- a/ts3-client/core/src/main/java/com/ts3client/chatlog/ChatLogStore.java +++ b/ts3-client/core/src/main/java/com/ts3client/chatlog/ChatLogStore.java @@ -174,7 +174,10 @@ public final class ChatLogStore { Files.createDirectories(files.txt.getParent()); Files.createDirectories(files.html.getParent()); if (!Files.exists(files.html)) { - Files.writeString(files.html, HTML_HEADER + System.lineSeparator(), StandardCharsets.UTF_8, + // Android < API 36.1 lacks Files.writeString; original: + // Files.writeString(files.html, HTML_HEADER + System.lineSeparator(), StandardCharsets.UTF_8, + // StandardOpenOption.CREATE, StandardOpenOption.APPEND); + Files.write(files.html, (HTML_HEADER + System.lineSeparator()).getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.APPEND); } if (!Files.exists(files.txt)) Files.createFile(files.txt); diff --git a/ts3-client/core/src/main/java/com/ts3client/config/AppDirs.java b/ts3-client/core/src/main/java/com/ts3client/config/AppDirs.java index 94ef603..ca87ea9 100644 --- a/ts3-client/core/src/main/java/com/ts3client/config/AppDirs.java +++ b/ts3-client/core/src/main/java/com/ts3client/config/AppDirs.java @@ -2,6 +2,7 @@ package com.ts3client.config; import java.io.File; import java.nio.file.Path; +import java.nio.file.Paths; /** * Where the client keeps its own state. On the desktop that is {@code ~/.ts3jclient}, with chat @@ -50,7 +51,9 @@ public final class AppDirs { public static Path chatLogs() { Path dir = chatLogs; if (dir == null) { - dir = Path.of(System.getProperty("user.home", "."), ".ts3client", "chats"); + // Android < API 34 lacks Path.of; original: + // dir = Path.of(System.getProperty("user.home", "."), ".ts3client", "chats"); + dir = Paths.get(System.getProperty("user.home", "."), ".ts3client", "chats"); chatLogs = dir; } return dir; diff --git a/ts3-client/core/src/main/java/com/ts3client/contacts/ContactStore.java b/ts3-client/core/src/main/java/com/ts3client/contacts/ContactStore.java index 8a66c65..a870fdd 100644 --- a/ts3-client/core/src/main/java/com/ts3client/contacts/ContactStore.java +++ b/ts3-client/core/src/main/java/com/ts3client/contacts/ContactStore.java @@ -70,7 +70,9 @@ public final class ContactStore { void readFile() { String text; try { - text = Files.readString(file.toPath(), StandardCharsets.UTF_8); + // Android < API 36.1 lacks Files.readString; original: + // text = Files.readString(file.toPath(), StandardCharsets.UTF_8); + text = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); } catch (IOException e) { return; } diff --git a/ts3-client/core/src/main/java/com/ts3client/net/TeamspeakConnection.java b/ts3-client/core/src/main/java/com/ts3client/net/TeamspeakConnection.java index fece234..f6c3be7 100644 --- a/ts3-client/core/src/main/java/com/ts3client/net/TeamspeakConnection.java +++ b/ts3-client/core/src/main/java/com/ts3client/net/TeamspeakConnection.java @@ -34,7 +34,7 @@ import com.ts3client.text.TsLink; import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; -import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -1399,7 +1399,9 @@ public final class TeamspeakConnection implements TS3Listener { return; } String dir = settings.chatLogDir == null ? "" : settings.chatLogDir.trim(); - ChatLogStore logs = new ChatLogStore(dir.isEmpty() ? ChatLogStore.defaultRoot() : Path.of(dir), uniqueId); + // Android < API 34 lacks Path.of; original: + // ChatLogStore logs = new ChatLogStore(dir.isEmpty() ? ChatLogStore.defaultRoot() : Path.of(dir), uniqueId); + ChatLogStore logs = new ChatLogStore(dir.isEmpty() ? ChatLogStore.defaultRoot() : Paths.get(dir), uniqueId); chatLogs = logs; logs.begin(); List serverHistory = logs.serverHtmlHistory(); diff --git a/ts3-client/core/src/main/java/com/ts3client/sound/WaveFile.java b/ts3-client/core/src/main/java/com/ts3client/sound/WaveFile.java index 379ab15..722437b 100644 --- a/ts3-client/core/src/main/java/com/ts3client/sound/WaveFile.java +++ b/ts3-client/core/src/main/java/com/ts3client/sound/WaveFile.java @@ -35,7 +35,11 @@ final class WaveFile { int id = in.getInt(); int size = in.getInt(); if (size < 0 || size > in.remaining()) size = in.remaining(); // truncated files still play - ByteBuffer chunk = in.slice(in.position(), size).order(ByteOrder.LITTLE_ENDIAN); + // Android < API 34 lacks ByteBuffer.slice(int, int); original: + // ByteBuffer chunk = in.slice(in.position(), size).order(ByteOrder.LITTLE_ENDIAN); + ByteBuffer chunk = in.duplicate(); + chunk.limit(chunk.position() + size); + chunk = chunk.slice().order(ByteOrder.LITTLE_ENDIAN); if (id == fourCc("fmt ") && size >= 16) { format = chunk.getShort() & 0xFFFF; channels = chunk.getShort() & 0xFFFF; diff --git a/ts3-client/core/src/main/java/com/ts3client/text/HtmlText.java b/ts3-client/core/src/main/java/com/ts3client/text/HtmlText.java index b024b90..1b4b059 100644 --- a/ts3-client/core/src/main/java/com/ts3client/text/HtmlText.java +++ b/ts3-client/core/src/main/java/com/ts3client/text/HtmlText.java @@ -21,7 +21,9 @@ public final class HtmlText { private static String unescape(String s) { Matcher m = ENTITY.matcher(s); - StringBuilder out = new StringBuilder(s.length()); + // Android < API 34 lacks Matcher.appendReplacement/appendTail(StringBuilder); original: + // StringBuilder out = new StringBuilder(s.length()); + StringBuffer out = new StringBuffer(s.length()); while (m.find()) { String decoded = decode(m.group(1)); m.appendReplacement(out, Matcher.quoteReplacement(decoded == null ? m.group() : decoded));