diff --git a/android/app/build.gradle b/android/app/build.gradle
index a725c471..d2f10b2d 100755
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -23,8 +23,8 @@ android {
applicationId "com.openipc.decoder"
minSdk 21
targetSdk 36
- versionCode 35
- versionName "2.10"
+ versionCode 36
+ versionName "2.11"
buildConfigField "String", "GIT_HASH", "\"${getGitHash()}\""
}
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 922a4fe1..bb26eb26 100755
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -14,6 +14,14 @@
+
+
+
+
+
+
+
+
stats, String log, Date now, long uptimeS) {
+ StringBuilder sb = new StringBuilder(64 * 1024);
+ sb.append(REPORT_TITLE).append('\n');
+ sb.append("App: OpenIPC Decoder ").append(BuildConfig.VERSION_NAME)
+ .append(" (").append(BuildConfig.VERSION_CODE).append("), git ")
+ .append(BuildConfig.GIT_HASH).append('\n');
+ sb.append("Device: ").append(android.os.Build.MANUFACTURER).append(' ')
+ .append(android.os.Build.MODEL).append('\n');
+ sb.append("Android: ").append(android.os.Build.VERSION.RELEASE).append(" (SDK ")
+ .append(android.os.Build.VERSION.SDK_INT).append(")\n");
+ sb.append("Time: ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z", Locale.US)
+ .format(now)).append('\n');
+ sb.append("Uptime: ").append(uptime(uptimeS)).append('\n');
+ sb.append("\n== stats.json ==\n");
+ sb.append(toJson(stats, true));
+ sb.append("\n== log ==\n");
+ sb.append(log != null ? log : "");
+ return redact(sb.toString());
+ }
+
+ /** 1d 2h 3m 4s; the leading zero units left out. */
+ static String uptime(long s) {
+ long d = s / 86400, h = s % 86400 / 3600, m = s % 3600 / 60;
+ StringBuilder sb = new StringBuilder();
+ if (d > 0) sb.append(d).append("d ");
+ if (d > 0 || h > 0) sb.append(h).append("h ");
+ if (d > 0 || h > 0 || m > 0) sb.append(m).append("m ");
+ return sb.append(s % 60).append('s').toString();
+ }
+
private Map snapshot() {
Source s = source;
Map m;
@@ -270,11 +340,18 @@ private static void reply(OutputStream out, int code, String type, String body)
private static void reply(OutputStream out, int code, String type, byte[] data)
throws IOException {
+ reply(out, code, type, data, "");
+ }
+
+ /** {@code extra}: more header lines, each ending with \r\n. */
+ private static void reply(OutputStream out, int code, String type, byte[] data, String extra)
+ throws IOException {
String head = "HTTP/1.1 " + code + " " + reason(code) + "\r\n"
+ "Content-Type: " + type + "\r\n"
+ "Content-Length: " + data.length + "\r\n"
+ "Cache-Control: no-store\r\n"
+ (code == 405 ? "Allow: GET\r\n" : "")
+ + extra
+ "Connection: close\r\n\r\n";
out.write(head.getBytes(StandardCharsets.ISO_8859_1));
out.write(data);
@@ -466,7 +543,8 @@ private static void closeQuietly(Socket s) {
+ "
"
+ "