android: Move logging into it's own repository class.
Logs will be maintained and appended even when the main UI is not bound to the service. This also lets us log without filling a Handler with a bunch of messages we might just throw away anyway.
This commit is contained in:
parent
5d122c3bc8
commit
324bd95c91
|
@ -5,5 +5,4 @@ interface IMainCallback
|
||||||
void onStarted();
|
void onStarted();
|
||||||
void onStopped();
|
void onStopped();
|
||||||
void onError(String error);
|
void onError(String error);
|
||||||
void onLog(int priority, String msg);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
package org.musicpd;
|
package org.musicpd;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
@ -21,15 +20,18 @@ import android.os.PowerManager;
|
||||||
import android.os.RemoteCallbackList;
|
import android.os.RemoteCallbackList;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.RemoteViews;
|
|
||||||
|
|
||||||
import androidx.core.app.ServiceCompat;
|
|
||||||
|
|
||||||
|
import org.musicpd.data.LoggingRepository;
|
||||||
import org.musicpd.ui.SettingsActivity;
|
import org.musicpd.ui.SettingsActivity;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
public class Main extends Service implements Runnable {
|
public class Main extends Service implements Runnable {
|
||||||
private static final String TAG = "Main";
|
private static final String TAG = "Main";
|
||||||
private static final String WAKELOCK_TAG = "mpd:wakelockmain";
|
private static final String WAKELOCK_TAG = "mpd:wakelockmain";
|
||||||
|
@ -39,7 +41,6 @@ public class Main extends Service implements Runnable {
|
||||||
private static final int MAIN_STATUS_STARTED = 1;
|
private static final int MAIN_STATUS_STARTED = 1;
|
||||||
|
|
||||||
private static final int MSG_SEND_STATUS = 0;
|
private static final int MSG_SEND_STATUS = 0;
|
||||||
private static final int MSG_SEND_LOG = 1;
|
|
||||||
|
|
||||||
private Thread mThread = null;
|
private Thread mThread = null;
|
||||||
private int mStatus = MAIN_STATUS_STOPPED;
|
private int mStatus = MAIN_STATUS_STOPPED;
|
||||||
|
@ -50,6 +51,9 @@ public class Main extends Service implements Runnable {
|
||||||
private boolean mPauseOnHeadphonesDisconnect = false;
|
private boolean mPauseOnHeadphonesDisconnect = false;
|
||||||
private PowerManager.WakeLock mWakelock = null;
|
private PowerManager.WakeLock mWakelock = null;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
LoggingRepository logging;
|
||||||
|
|
||||||
static class MainStub extends IMain.Stub {
|
static class MainStub extends IMain.Stub {
|
||||||
private Main mService;
|
private Main mService;
|
||||||
MainStub(Main service) {
|
MainStub(Main service) {
|
||||||
|
@ -98,9 +102,6 @@ public class Main extends Service implements Runnable {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MSG_SEND_LOG:
|
|
||||||
cb.onLog(arg1, (String) obj);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
}
|
}
|
||||||
|
@ -111,7 +112,7 @@ public class Main extends Service implements Runnable {
|
||||||
private Bridge.LogListener mLogListener = new Bridge.LogListener() {
|
private Bridge.LogListener mLogListener = new Bridge.LogListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onLog(int priority, String msg) {
|
public void onLog(int priority, String msg) {
|
||||||
sendMessage(MSG_SEND_LOG, priority, 0, msg);
|
logging.addLogItem(priority, msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -303,7 +304,6 @@ public class Main extends Service implements Runnable {
|
||||||
public void onStarted();
|
public void onStarted();
|
||||||
public void onStopped();
|
public void onStopped();
|
||||||
public void onError(String error);
|
public void onError(String error);
|
||||||
public void onLog(int priority, String msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean mBound = false;
|
private boolean mBound = false;
|
||||||
|
@ -327,11 +327,6 @@ public class Main extends Service implements Runnable {
|
||||||
public void onError(String error) throws RemoteException {
|
public void onError(String error) throws RemoteException {
|
||||||
mCallback.onError(error);
|
mCallback.onError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLog(int priority, String msg) throws RemoteException {
|
|
||||||
mCallback.onLog(priority, msg);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private final ServiceConnection mServiceConnection = new ServiceConnection() {
|
private final ServiceConnection mServiceConnection = new ServiceConnection() {
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package org.musicpd.data
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
private const val MAX_LOGS = 500
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class LoggingRepository @Inject constructor() {
|
||||||
|
|
||||||
|
private val _logItemFLow = MutableStateFlow(listOf<String>())
|
||||||
|
val logItemFLow: StateFlow<List<String>> = _logItemFLow
|
||||||
|
|
||||||
|
fun addLogItem(priority: Int, message: String) {
|
||||||
|
if (_logItemFLow.value.size > MAX_LOGS) {
|
||||||
|
_logItemFLow.value = _logItemFLow.value.drop(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
val priorityString: String = when (priority) {
|
||||||
|
Log.DEBUG -> "D"
|
||||||
|
Log.ERROR -> "E"
|
||||||
|
Log.INFO -> "I"
|
||||||
|
Log.VERBOSE -> "V"
|
||||||
|
Log.WARN -> "W"
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
|
||||||
|
_logItemFLow.value = _logItemFLow.value + ("$priorityString/$message")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -37,12 +37,14 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
import com.google.accompanist.permissions.isGranted
|
import com.google.accompanist.permissions.isGranted
|
||||||
import com.google.accompanist.permissions.rememberPermissionState
|
import com.google.accompanist.permissions.rememberPermissionState
|
||||||
import com.google.accompanist.permissions.shouldShowRationale
|
import com.google.accompanist.permissions.shouldShowRationale
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.musicpd.Main
|
import org.musicpd.Main
|
||||||
import org.musicpd.R
|
import org.musicpd.R
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
class SettingsActivity : ComponentActivity() {
|
class SettingsActivity : ComponentActivity() {
|
||||||
|
|
||||||
private val settingsViewModel: SettingsViewModel by viewModels()
|
private val settingsViewModel: SettingsViewModel by viewModels()
|
||||||
|
@ -72,10 +74,6 @@ class SettingsActivity : ComponentActivity() {
|
||||||
settingsViewModel.updateStatus(error, false)
|
settingsViewModel.updateStatus(error, false)
|
||||||
connectClient()
|
connectClient()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLog(priority: Int, msg: String) {
|
|
||||||
settingsViewModel.addLogItem(priority, msg)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
settingsViewModel.setClient(client)
|
settingsViewModel.setClient(client)
|
||||||
|
@ -138,7 +136,7 @@ fun SettingsContainer(settingsViewModel: SettingsViewModel = viewModel()) {
|
||||||
settingsViewModel.setPauseOnHeadphonesDisconnect(newValue)
|
settingsViewModel.setPauseOnHeadphonesDisconnect(newValue)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
LogView(settingsViewModel.logItemFLow.collectAsStateWithLifecycle())
|
LogView(settingsViewModel.getLogs().collectAsStateWithLifecycle())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
package org.musicpd.ui
|
package org.musicpd.ui
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import org.musicpd.Main
|
import org.musicpd.Main
|
||||||
import org.musicpd.Preferences
|
import org.musicpd.Preferences
|
||||||
|
import org.musicpd.data.LoggingRepository
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
private const val MAX_LOGS = 500
|
|
||||||
|
|
||||||
class SettingsViewModel : ViewModel() {
|
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class SettingsViewModel @Inject constructor(
|
||||||
|
private var loggingRepository: LoggingRepository
|
||||||
|
) : ViewModel() {
|
||||||
private var mClient: Main.Client? = null
|
private var mClient: Main.Client? = null
|
||||||
|
|
||||||
private val _logItemFLow = MutableStateFlow(listOf<String>())
|
|
||||||
val logItemFLow: StateFlow<List<String>> = _logItemFLow
|
|
||||||
|
|
||||||
data class StatusUiState(
|
data class StatusUiState(
|
||||||
val statusMessage: String = "",
|
val statusMessage: String = "",
|
||||||
val running: Boolean = false
|
val running: Boolean = false
|
||||||
|
@ -26,21 +26,8 @@ class SettingsViewModel : ViewModel() {
|
||||||
private val _statusUIState = MutableStateFlow(StatusUiState())
|
private val _statusUIState = MutableStateFlow(StatusUiState())
|
||||||
val statusUIState: StateFlow<StatusUiState> = _statusUIState.asStateFlow()
|
val statusUIState: StateFlow<StatusUiState> = _statusUIState.asStateFlow()
|
||||||
|
|
||||||
fun addLogItem(priority: Int, message: String) {
|
fun getLogs(): StateFlow<List<String>> {
|
||||||
if (_logItemFLow.value.size > MAX_LOGS) {
|
return loggingRepository.logItemFLow
|
||||||
_logItemFLow.value = _logItemFLow.value.drop(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
val priorityString: String = when (priority) {
|
|
||||||
Log.DEBUG -> "D"
|
|
||||||
Log.ERROR -> "E"
|
|
||||||
Log.INFO -> "I"
|
|
||||||
Log.VERBOSE -> "V"
|
|
||||||
Log.WARN -> "W"
|
|
||||||
else -> ""
|
|
||||||
}
|
|
||||||
|
|
||||||
_logItemFLow.value = _logItemFLow.value + ("$priorityString/$message")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateStatus(message: String, running: Boolean) {
|
fun updateStatus(message: String, running: Boolean) {
|
||||||
|
|
Loading…
Reference in New Issue