diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7154b5f..0a0aa4a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -161,6 +161,11 @@
android:exported="false"
/>
+
+
logcatReader.addMarker());
+ findViewById(R.id.log_marker_button).setOnClickListener(v -> getLogcatReader().ifPresent(LogcatReader::addMarker));
- findViewById(R.id.toggle_recording_button).setOnClickListener(v -> {
+ findViewById(R.id.toggle_recording_button).setOnClickListener(v -> getLogcatReader().ifPresent(logcatReader -> {
if (logcatReader.isRecording()) {
Throwable error = logcatReader.stopRecording();
- if (error == null) {
- Toast.makeText(this, "recording stopped", Toast.LENGTH_SHORT).show();
- return;
- }
- Log.e(TAG, "error during recording", error);
- new AlertDialog.Builder(this)
- .setTitle("Log recording error")
- .setMessage("an error happened during the recording:\n\n" + error.getClass().getSimpleName() + ": " + error.getMessage())
- .setPositiveButton("close", null)
- .show();
+ if (error != null) onRecordingError(error);
return;
}
@@ -97,16 +92,15 @@ public class DebugActivity extends AppCompatActivity {
File logFile = getFilesDir().toPath().resolve(name).toFile();
try {
logcatReader.startRecording(logFile);
- Toast.makeText(this, "recording started", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Log.e(TAG, "failed to start recording", e);
+ onRecordingError(e);
}
})
.setNegativeButton("cancel", null)
.setCancelable(false)
.show();
-
- });
+ }));
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@@ -116,8 +110,6 @@ public class DebugActivity extends AppCompatActivity {
autoScrollSwitch.setOnCheckedChangeListener((v, checked) -> autoScroll = checked);
RecyclerView logRecyclerView = findViewById(R.id.log_recycler);
- LogUiAdapter logUiAdapter = new LogUiAdapter();
-
logRecyclerView.setLayoutManager(new LinearLayoutManager(this));
logRecyclerView.setAdapter(logUiAdapter);
logRecyclerView.setItemAnimator(null); // does not work with fast-paced logs
@@ -130,8 +122,10 @@ public class DebugActivity extends AppCompatActivity {
}
});
- logcatReader = new LogcatReader(logUiAdapter);
- logcatReader.start();
+ logUiAdapter.onLog(null, "connecting to log service...");
+
+ connector = new GeargrinderServiceConnector(TAG, this, this);
+ connector.bindLogService(BIND_AUTO_CREATE | BIND_IMPORTANT);
if (AUTOSTART_TCP_SERVER)
startService(new Intent(this, ConnectionService.class)
@@ -141,7 +135,56 @@ public class DebugActivity extends AppCompatActivity {
@Override
protected void onDestroy() {
super.onDestroy();
- logcatReader.destroy();
+ getLogcatReader().ifPresent(logcatReader -> logcatReader.unregisterUiListener(logUiAdapter));
+ connector.destroy();
+ }
+
+ private Optional getLogcatReader() {
+ return connector.getLogBinder()
+ .map(LogService.ServiceBinder::getLogcatReader);
+ }
+
+ public void updateRecordingStatus(boolean recording) {
+ Button toggleRecordingButton = findViewById(R.id.toggle_recording_button);
+ toggleRecordingButton.setText(recording ? "stop recording" : "start recording");
+ }
+
+ @Override
+ public void onLogServiceConnected(LogService.ServiceBinder binder) {
+ binder.getLogcatReader().registerUiListener(logUiAdapter);
+ binder.getLogcatReader().registerUiListener(this);
+ findViewById(R.id.log_marker_button).setEnabled(true);
+ findViewById(R.id.toggle_recording_button).setEnabled(true);
+ updateRecordingStatus(binder.getLogcatReader().isRecording());
+ }
+
+ @Override
+ public void onRecordingStart(File file) {
+ runOnUiThread(() -> {
+ updateRecordingStatus(true);
+ Toast.makeText(this, "recording started", Toast.LENGTH_SHORT).show();
+ });
+ }
+
+ @Override
+ public void onRecordingError(Throwable t) {
+ runOnUiThread(() -> {
+ Log.e(TAG, "error during recording", t);
+ new AlertDialog.Builder(this)
+ .setTitle("Log recording error")
+ .setMessage("an error happened during the recording:\n\n" + t.getClass().getSimpleName() + ": " + t.getMessage())
+ .setPositiveButton("close", null)
+ .setCancelable(false)
+ .show();
+ });
+ }
+
+ @Override
+ public void onRecordingStop() {
+ runOnUiThread(() -> {
+ updateRecordingStatus(false);
+ Toast.makeText(this, "recording stopped", Toast.LENGTH_SHORT).show();
+ });
}
@Override
diff --git a/app/src/main/java/io/benwiegand/projection/geargrinder/LogService.java b/app/src/main/java/io/benwiegand/projection/geargrinder/LogService.java
new file mode 100644
index 0000000..57604bb
--- /dev/null
+++ b/app/src/main/java/io/benwiegand/projection/geargrinder/LogService.java
@@ -0,0 +1,57 @@
+package io.benwiegand.projection.geargrinder;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+
+import androidx.annotation.Nullable;
+
+import java.io.File;
+
+import io.benwiegand.projection.geargrinder.logs.LogcatReader;
+
+public class LogService extends Service implements LogcatReader.UiLogListener {
+
+ private final LogcatReader logcatReader = new LogcatReader();
+ private final ServiceBinder binder = new ServiceBinder();
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ logcatReader.registerUiListener(this);
+ logcatReader.start();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ logcatReader.unregisterUiListener(this);
+ logcatReader.destroy();
+ }
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return binder;
+ }
+
+ @Override
+ public void onRecordingStart(File file) {
+ startService(new Intent(this, LogService.class));
+ }
+
+ @Override
+ public void onRecordingStop() {
+ stopService(new Intent(this, LogService.class));
+ }
+
+ public class ServiceBinder extends Binder {
+
+ public LogcatReader getLogcatReader() {
+ return logcatReader;
+ }
+
+ }
+
+}
diff --git a/app/src/main/java/io/benwiegand/projection/geargrinder/logs/LogcatReader.java b/app/src/main/java/io/benwiegand/projection/geargrinder/logs/LogcatReader.java
index 6e34de7..71b9a50 100644
--- a/app/src/main/java/io/benwiegand/projection/geargrinder/logs/LogcatReader.java
+++ b/app/src/main/java/io/benwiegand/projection/geargrinder/logs/LogcatReader.java
@@ -8,6 +8,10 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayDeque;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -19,19 +23,18 @@ public class LogcatReader {
private static final Pattern LOGCAT_REGEX = Pattern.compile("^(?[0-9]+-[0-9]+) +(?