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 <noreply@anthropic.com>
This commit is contained in:
2026-09-25 14:05:39 +00:00
parent 5d67b0c1e3
commit c5a49fc7b3
6 changed files with 23 additions and 7 deletions

View File

@@ -174,7 +174,10 @@ public final class ChatLogStore {
Files.createDirectories(files.txt.getParent()); Files.createDirectories(files.txt.getParent());
Files.createDirectories(files.html.getParent()); Files.createDirectories(files.html.getParent());
if (!Files.exists(files.html)) { 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); StandardOpenOption.CREATE, StandardOpenOption.APPEND);
} }
if (!Files.exists(files.txt)) Files.createFile(files.txt); if (!Files.exists(files.txt)) Files.createFile(files.txt);

View File

@@ -2,6 +2,7 @@ package com.ts3client.config;
import java.io.File; import java.io.File;
import java.nio.file.Path; 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 * 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() { public static Path chatLogs() {
Path dir = chatLogs; Path dir = chatLogs;
if (dir == null) { 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; chatLogs = dir;
} }
return dir; return dir;

View File

@@ -70,7 +70,9 @@ public final class ContactStore {
void readFile() { void readFile() {
String text; String text;
try { 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) { } catch (IOException e) {
return; return;
} }

View File

@@ -34,7 +34,7 @@ import com.ts3client.text.TsLink;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.file.Path; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -1399,7 +1399,9 @@ public final class TeamspeakConnection implements TS3Listener {
return; return;
} }
String dir = settings.chatLogDir == null ? "" : settings.chatLogDir.trim(); 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; chatLogs = logs;
logs.begin(); logs.begin();
List<String> serverHistory = logs.serverHtmlHistory(); List<String> serverHistory = logs.serverHtmlHistory();

View File

@@ -35,7 +35,11 @@ final class WaveFile {
int id = in.getInt(); int id = in.getInt();
int size = in.getInt(); int size = in.getInt();
if (size < 0 || size > in.remaining()) size = in.remaining(); // truncated files still play 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) { if (id == fourCc("fmt ") && size >= 16) {
format = chunk.getShort() & 0xFFFF; format = chunk.getShort() & 0xFFFF;
channels = chunk.getShort() & 0xFFFF; channels = chunk.getShort() & 0xFFFF;

View File

@@ -21,7 +21,9 @@ public final class HtmlText {
private static String unescape(String s) { private static String unescape(String s) {
Matcher m = ENTITY.matcher(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()) { while (m.find()) {
String decoded = decode(m.group(1)); String decoded = decode(m.group(1));
m.appendReplacement(out, Matcher.quoteReplacement(decoded == null ? m.group() : decoded)); m.appendReplacement(out, Matcher.quoteReplacement(decoded == null ? m.group() : decoded));