mirror of
https://github.com/ultrasonic/ultrasonic
synced 2025-02-16 19:50:35 +01:00
Implemented file logging settings
Implemented log rotation, log deletion Minor fixes
This commit is contained in:
parent
5de20861ca
commit
6e7ebeabef
@ -22,6 +22,7 @@ import org.moire.ultrasonic.featureflags.Feature;
|
||||
import org.moire.ultrasonic.featureflags.FeatureStorage;
|
||||
import org.moire.ultrasonic.filepicker.FilePickerDialog;
|
||||
import org.moire.ultrasonic.filepicker.OnFileSelectedListener;
|
||||
import org.moire.ultrasonic.log.FileLoggerTree;
|
||||
import org.moire.ultrasonic.provider.SearchSuggestionProvider;
|
||||
import org.moire.ultrasonic.service.Consumer;
|
||||
import org.moire.ultrasonic.service.MediaPlayerController;
|
||||
@ -70,6 +71,7 @@ public class SettingsFragment extends PreferenceFragment
|
||||
private PreferenceCategory serversCategory;
|
||||
private Preference resumeOnBluetoothDevice;
|
||||
private Preference pauseOnBluetoothDevice;
|
||||
private CheckBoxPreference debugLogToFile;
|
||||
|
||||
private SharedPreferences settings;
|
||||
|
||||
@ -118,6 +120,7 @@ public class SettingsFragment extends PreferenceFragment
|
||||
serversCategory = (PreferenceCategory) findPreference(Constants.PREFERENCES_KEY_SERVERS_KEY);
|
||||
resumeOnBluetoothDevice = findPreference(Constants.PREFERENCES_KEY_RESUME_ON_BLUETOOTH_DEVICE);
|
||||
pauseOnBluetoothDevice = findPreference(Constants.PREFERENCES_KEY_PAUSE_ON_BLUETOOTH_DEVICE);
|
||||
debugLogToFile = (CheckBoxPreference) findPreference(Constants.PREFERENCES_KEY_DEBUG_LOG_TO_FILE);
|
||||
|
||||
sharingDefaultGreeting.setText(Util.getShareGreeting(getActivity()));
|
||||
setupClearSearchPreference();
|
||||
@ -171,6 +174,8 @@ public class SettingsFragment extends PreferenceFragment
|
||||
setBluetoothPreferences(sharedPreferences.getBoolean(key, true));
|
||||
} else if (Constants.PREFERENCES_KEY_IMAGE_LOADER_CONCURRENCY.equals(key)) {
|
||||
setImageLoaderConcurrency(Integer.parseInt(sharedPreferences.getString(key, "5")));
|
||||
} else if (Constants.PREFERENCES_KEY_DEBUG_LOG_TO_FILE.equals(key)) {
|
||||
setDebugLogToFile(sharedPreferences.getBoolean(key, false));
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,6 +420,13 @@ public class SettingsFragment extends PreferenceFragment
|
||||
sendBluetoothAlbumArt.setChecked(false);
|
||||
sendBluetoothAlbumArt.setEnabled(false);
|
||||
}
|
||||
|
||||
if (debugLogToFile.isChecked()) {
|
||||
debugLogToFile.setSummary(getString(R.string.settings_debug_log_path,
|
||||
FileUtil.getUltrasonicDirectory(getActivity()), FileLoggerTree.FILENAME));
|
||||
} else {
|
||||
debugLogToFile.setSummary("");
|
||||
}
|
||||
}
|
||||
|
||||
private static void setImageLoaderConcurrency(int concurrency) {
|
||||
@ -482,4 +494,47 @@ public class SettingsFragment extends PreferenceFragment
|
||||
// Clear download queue.
|
||||
mediaPlayerControllerLazy.getValue().clear();
|
||||
}
|
||||
|
||||
private void setDebugLogToFile(boolean writeLog) {
|
||||
if (writeLog) {
|
||||
FileLoggerTree.Companion.plantToTimberForest(getActivity().getApplicationContext());
|
||||
Timber.i("Enabled debug logging to file");
|
||||
} else {
|
||||
FileLoggerTree.Companion.uprootFromTimberForest();
|
||||
Timber.i("Disabled debug logging to file");
|
||||
|
||||
int fileNum = FileLoggerTree.Companion.getLogFileNumber(getActivity());
|
||||
long fileSize = FileLoggerTree.Companion.getLogFileSizes(getActivity());
|
||||
String message = getString(R.string.settings_debug_log_summary,
|
||||
String.valueOf(fileNum),
|
||||
String.valueOf(Math.ceil(fileSize / 1000000d)),
|
||||
FileUtil.getUltrasonicDirectory(getActivity()));
|
||||
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setMessage(message)
|
||||
.setIcon(android.R.drawable.ic_dialog_info)
|
||||
.setNegativeButton(R.string.settings_debug_log_keep, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
dialogInterface.cancel();
|
||||
}
|
||||
})
|
||||
.setPositiveButton(R.string.settings_debug_log_delete, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
FileLoggerTree.Companion.deleteLogFiles(getActivity());
|
||||
Timber.i("Deleted debug log files");
|
||||
dialogInterface.dismiss();
|
||||
new AlertDialog.Builder(getActivity()).setMessage(R.string.settings_debug_log_deleted)
|
||||
.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
dialogInterface.dismiss();
|
||||
}
|
||||
}).create().show();
|
||||
}
|
||||
})
|
||||
.create().show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +134,7 @@ public final class Constants
|
||||
public static final String PREFERENCES_KEY_FIRST_RUN_EXECUTED = "firstRunExecuted";
|
||||
public static final String PREFERENCES_KEY_RESUME_ON_BLUETOOTH_DEVICE = "resumeOnBluetoothDevice";
|
||||
public static final String PREFERENCES_KEY_PAUSE_ON_BLUETOOTH_DEVICE = "pauseOnBluetoothDevice";
|
||||
public static final String PREFERENCES_KEY_DEBUG_LOG_TO_FILE = "debugLogToFile";
|
||||
|
||||
public static final int PREFERENCE_VALUE_ALL = 0;
|
||||
public static final int PREFERENCE_VALUE_A2DP = 1;
|
||||
|
@ -1457,4 +1457,11 @@ public class Util
|
||||
SharedPreferences preferences = getPreferences(context);
|
||||
return preferences.getInt(Constants.PREFERENCES_KEY_PAUSE_ON_BLUETOOTH_DEVICE, Constants.PREFERENCE_VALUE_A2DP);
|
||||
}
|
||||
|
||||
public static boolean getDebugLogToFile(Context context)
|
||||
{
|
||||
SharedPreferences preferences = getPreferences(context);
|
||||
return preferences.getBoolean(Constants.PREFERENCES_KEY_DEBUG_LOG_TO_FILE, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package org.moire.ultrasonic.app
|
||||
|
||||
import androidx.multidex.MultiDexApplication
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.android.ext.koin.androidLogger
|
||||
import org.koin.core.context.startKoin
|
||||
import org.koin.core.logger.Level
|
||||
import org.moire.ultrasonic.BuildConfig
|
||||
@ -13,8 +12,8 @@ import org.moire.ultrasonic.di.featureFlagsModule
|
||||
import org.moire.ultrasonic.di.mediaPlayerModule
|
||||
import org.moire.ultrasonic.di.musicServiceModule
|
||||
import org.moire.ultrasonic.log.FileLoggerTree
|
||||
import org.moire.ultrasonic.log.TimberKoinLogger
|
||||
import org.moire.ultrasonic.log.timberLogger
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import timber.log.Timber
|
||||
import timber.log.Timber.DebugTree
|
||||
|
||||
@ -24,7 +23,9 @@ class UApp : MultiDexApplication() {
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.plant(DebugTree())
|
||||
Timber.plant(FileLoggerTree(this))
|
||||
}
|
||||
if (Util.getDebugLogToFile(this)) {
|
||||
FileLoggerTree.plantToTimberForest(this)
|
||||
}
|
||||
|
||||
startKoin {
|
||||
|
@ -1,8 +1,8 @@
|
||||
@file:JvmName("MusicServiceModule")
|
||||
package org.moire.ultrasonic.di
|
||||
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import kotlin.math.abs
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.core.qualifier.named
|
||||
import org.koin.dsl.module
|
||||
|
@ -1,37 +1,106 @@
|
||||
package org.moire.ultrasonic.log
|
||||
|
||||
import android.content.Context
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import org.moire.ultrasonic.util.FileUtil
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
|
||||
/**
|
||||
* A Timber Tree which can be used to log to a file
|
||||
* Subclass of the DebugTree so it inherits the Tag handling
|
||||
*/
|
||||
class FileLoggerTree(val context: Context) : Timber.DebugTree() {
|
||||
private val filename = "ultrasonic.log"
|
||||
private val dateFormat = SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault())
|
||||
|
||||
/**
|
||||
* Writes a log entry to file
|
||||
*/
|
||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||
var file: File? = null
|
||||
var writer: FileWriter? = null
|
||||
callNum++
|
||||
try {
|
||||
file = File(FileUtil.getUltrasonicDirectory(context), filename)
|
||||
getNextLogFile()
|
||||
writer = FileWriter(file, true)
|
||||
val exceptionString = t?.toString() ?: "";
|
||||
writer.write("${logLevelToString(priority)} $tag $message $exceptionString\n")
|
||||
writer.flush()
|
||||
val exceptionString = t?.toString() ?: ""
|
||||
val time: String = dateFormat.format(Date())
|
||||
synchronized(file!!) {
|
||||
writer.write(
|
||||
"$time: ${logLevelToString(priority)} $tag $message $exceptionString\n"
|
||||
)
|
||||
writer.flush()
|
||||
}
|
||||
} catch (x: Throwable) {
|
||||
super.e(x, "Failed to write log to %s", file)
|
||||
// Using base class DebugTree here, we don't want to try to log this into file
|
||||
super.log(6, TAG, String.format("Failed to write log to %s", file), x)
|
||||
} finally {
|
||||
if (writer != null) Util.close(writer)
|
||||
}
|
||||
}
|
||||
|
||||
private fun logLevelToString(logLevel: Int) : String {
|
||||
return when(logLevel) {
|
||||
/**
|
||||
* Sets the file to log into
|
||||
* This function also rotates the log files periodically, when they reach the predefined size
|
||||
*/
|
||||
private fun getNextLogFile() {
|
||||
if (file == null) {
|
||||
synchronized(this) {
|
||||
if (file != null) return
|
||||
getNumberedFile(false)
|
||||
// Using base class DebugTree here, we don't want to try to log this into file
|
||||
super.log(4, TAG,String.format("Logging into file %s", file?.name), null)
|
||||
return
|
||||
}
|
||||
}
|
||||
if (callNum % 100 == 0) {
|
||||
// Gain some performance by only executing this rarely
|
||||
if (file!!.length() > MAX_LOGFILE_LENGTH) {
|
||||
synchronized(this) {
|
||||
if (file!!.length() <= MAX_LOGFILE_LENGTH) return
|
||||
getNumberedFile(true)
|
||||
// Using base class DebugTree here, we don't want to try to log this into file
|
||||
super.log(
|
||||
4,
|
||||
TAG,
|
||||
String.format("Log file rotated, logging into file %s", file?.name),
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the number of log files
|
||||
* @param next: if false, sets the current log file with the greatest number
|
||||
* if true, sets a new file for logging with the next number
|
||||
*/
|
||||
private fun getNumberedFile(next: Boolean) {
|
||||
var fileNum = 1
|
||||
val fileList = getLogFileList(context)
|
||||
|
||||
if (!fileList.isNullOrEmpty()) {
|
||||
fileList.sortByDescending { t -> t.name }
|
||||
val lastFile = fileList[0]
|
||||
val number = fileNumberRegex.find(lastFile.name)?.groups?.get(1)?.value
|
||||
if (number != null) {
|
||||
fileNum = number.toInt()
|
||||
}
|
||||
}
|
||||
|
||||
if (next) fileNum++
|
||||
file = File(
|
||||
FileUtil.getUltrasonicDirectory(context),
|
||||
FILENAME.replace("*", fileNum.toString())
|
||||
)
|
||||
}
|
||||
|
||||
private fun logLevelToString(logLevel: Int): String {
|
||||
return when (logLevel) {
|
||||
2 -> "V"
|
||||
3 -> "D"
|
||||
4 -> "I"
|
||||
@ -41,4 +110,60 @@ class FileLoggerTree(val context: Context) : Timber.DebugTree() {
|
||||
else -> "U"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TAG = FileLoggerTree::class.simpleName
|
||||
@Volatile private var file: File? = null
|
||||
const val FILENAME = "ultrasonic.*.log"
|
||||
private val fileNameRegex = Regex(
|
||||
FILENAME.replace(".", "\\.").replace("*", "\\d*")
|
||||
)
|
||||
private val fileNumberRegex = Regex(
|
||||
FILENAME.replace(".", "\\.").replace("*", "(\\d*)")
|
||||
)
|
||||
const val MAX_LOGFILE_LENGTH = 10000000
|
||||
var callNum = 0
|
||||
|
||||
fun plantToTimberForest(context: Context) {
|
||||
if (!Timber.forest().any { t -> t is FileLoggerTree }) {
|
||||
Timber.plant(FileLoggerTree(context))
|
||||
}
|
||||
}
|
||||
|
||||
fun uprootFromTimberForest() {
|
||||
val fileLoggerTree = Timber.forest().singleOrNull { t -> t is FileLoggerTree }
|
||||
?: return
|
||||
Timber.uproot(fileLoggerTree)
|
||||
file = null
|
||||
}
|
||||
|
||||
fun getLogFileNumber(context: Context): Int {
|
||||
val fileList = getLogFileList(context)
|
||||
if (!fileList.isNullOrEmpty()) return fileList.size
|
||||
return 0
|
||||
}
|
||||
|
||||
fun getLogFileSizes(context: Context): Long {
|
||||
var sizeSum: Long = 0
|
||||
val fileList = getLogFileList(context)
|
||||
if (fileList.isNullOrEmpty()) return sizeSum
|
||||
for (file in fileList) {
|
||||
sizeSum += file.length()
|
||||
}
|
||||
return sizeSum
|
||||
}
|
||||
|
||||
fun deleteLogFiles(context: Context) {
|
||||
val fileList = getLogFileList(context)
|
||||
if (fileList.isNullOrEmpty()) return
|
||||
for (file in fileList) {
|
||||
file.delete()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLogFileList(context: Context): Array<File> {
|
||||
val directory = FileUtil.getUltrasonicDirectory(context)
|
||||
return directory.listFiles { t -> t.name.matches(fileNameRegex) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ fun KoinApplication.timberLogger(
|
||||
/**
|
||||
* Timber Logger implementation for Koin
|
||||
*/
|
||||
class TimberKoinLogger (level: Level = Level.INFO) : Logger(level) {
|
||||
class TimberKoinLogger(level: Level = Level.INFO) : Logger(level) {
|
||||
|
||||
override fun log(level: Level, msg: MESSAGE) {
|
||||
if (this.level <= level) {
|
||||
|
@ -10,4 +10,4 @@ class TimberOkHttpLogger : HttpLoggingInterceptor.Logger {
|
||||
override fun log(message: String) {
|
||||
Timber.d(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -401,6 +401,13 @@
|
||||
<string name="settings.playback.bluetooth_all">All Bluetooth devices</string>
|
||||
<string name="settings.playback.bluetooth_a2dp">Only audio (A2DP) devices</string>
|
||||
<string name="settings.playback.bluetooth_disabled">Disabled</string>
|
||||
<string name="settings.debug.title">Debug options</string>
|
||||
<string name="settings.debug.log_to_file">Write debug log to file</string>
|
||||
<string name="settings.debug.log_path">The log files are available at %1$s/%2$s</string>
|
||||
<string name="settings.debug.log_summary">There are %1$s log files taking up ~%2$s MB space in the %3$s directory. Do you want to keep these?</string>
|
||||
<string name="settings.debug.log_keep">Keep files</string>
|
||||
<string name="settings.debug.log_delete">Delete files</string>
|
||||
<string name="settings.debug.log_deleted">Deleted log files.</string>
|
||||
|
||||
<string name="permissions.access_error">Ultrasonic can\'t access the music file cache. Cache location was reset to the default path.</string>
|
||||
<string name="permissions.message_box_title">Warning</string>
|
||||
|
@ -402,6 +402,13 @@
|
||||
<string name="settings.playback.bluetooth_all">Todos los dispositivos Bluetooth</string>
|
||||
<string name="settings.playback.bluetooth_a2dp">Solo dispositivos de audio (A2DP)</string>
|
||||
<string name="settings.playback.bluetooth_disabled">Deshabilitado</string>
|
||||
<string name="settings.debug.title">Debug options</string>
|
||||
<string name="settings.debug.log_to_file">Write debug log to file</string>
|
||||
<string name="settings.debug.log_path">The log files are available at %1$s/%2$s</string>
|
||||
<string name="settings.debug.log_summary">There are %1$s log files taking up ~%2$s MB space in the %3$s directory. Do you want to keep these?</string>
|
||||
<string name="settings.debug.log_keep">Keep files</string>
|
||||
<string name="settings.debug.log_delete">Delete files</string>
|
||||
<string name="settings.debug.log_deleted">Deleted log files.</string>
|
||||
|
||||
<string name="permissions.access_error">Ultrasonic no puede acceder a la caché de los ficheros de música. La ubicación de la caché se restableció a la ruta predeterminada.</string>
|
||||
<string name="permissions.message_box_title">Atención</string>
|
||||
|
@ -402,6 +402,13 @@
|
||||
<string name="settings.playback.bluetooth_all">All Bluetooth devices</string>
|
||||
<string name="settings.playback.bluetooth_a2dp">Only audio (A2DP) devices</string>
|
||||
<string name="settings.playback.bluetooth_disabled">Disabled</string>
|
||||
<string name="settings.debug.title">Debug options</string>
|
||||
<string name="settings.debug.log_to_file">Write debug log to file</string>
|
||||
<string name="settings.debug.log_path">The log files are available at %1$s/%2$s</string>
|
||||
<string name="settings.debug.log_summary">There are %1$s log files taking up ~%2$s MB space in the %3$s directory. Do you want to keep these?</string>
|
||||
<string name="settings.debug.log_keep">Keep files</string>
|
||||
<string name="settings.debug.log_delete">Delete files</string>
|
||||
<string name="settings.debug.log_deleted">Deleted log files.</string>
|
||||
|
||||
<string name="permissions.access_error">Ultrasonic can\'t access the music file cache. Cache location was reset to the default path.</string>
|
||||
<string name="permissions.message_box_title">Warning</string>
|
||||
|
@ -402,6 +402,13 @@
|
||||
<string name="settings.playback.bluetooth_all">Minden Bluetooth eszköz</string>
|
||||
<string name="settings.playback.bluetooth_a2dp">Csak audio (A2DP) eszközök</string>
|
||||
<string name="settings.playback.bluetooth_disabled">Kikapcsolva</string>
|
||||
<string name="settings.debug.title">Hibakeresési lehetőségek</string>
|
||||
<string name="settings.debug.log_to_file">Hibakeresési napló írása fájlba</string>
|
||||
<string name="settings.debug.log_path">A naplófájlok elérhetőek a következő helyen: %1$s/%2$s</string>
|
||||
<string name="settings.debug.log_summary">%1$s napló fájl ~%2$s MB méretben található a %3$s könyvtárban. Meg szeretnéd atrtani ezeket?</string>
|
||||
<string name="settings.debug.log_keep">Fájlok megtartása</string>
|
||||
<string name="settings.debug.log_delete">Fájlok törlése</string>
|
||||
<string name="settings.debug.log_deleted">Naplófájlok törölve.</string>
|
||||
|
||||
<string name="permissions.access_error">Az Ultrasonic nem éri el a zenei fájl gyorsítótárat. A gyorsítótár helye visszaállítva az alapbeállításra.</string>
|
||||
<string name="permissions.message_box_title">Figyelem</string>
|
||||
|
@ -402,6 +402,13 @@
|
||||
<string name="settings.playback.bluetooth_all">All Bluetooth devices</string>
|
||||
<string name="settings.playback.bluetooth_a2dp">Only audio (A2DP) devices</string>
|
||||
<string name="settings.playback.bluetooth_disabled">Disabled</string>
|
||||
<string name="settings.debug.title">Debug options</string>
|
||||
<string name="settings.debug.log_to_file">Write debug log to file</string>
|
||||
<string name="settings.debug.log_path">The log files are available at %1$s/%2$s</string>
|
||||
<string name="settings.debug.log_summary">There are %1$s log files taking up ~%2$s MB space in the %3$s directory. Do you want to keep these?</string>
|
||||
<string name="settings.debug.log_keep">Keep files</string>
|
||||
<string name="settings.debug.log_delete">Delete files</string>
|
||||
<string name="settings.debug.log_deleted">Deleted log files.</string>
|
||||
|
||||
<string name="permissions.access_error">Ultrasonic can\'t access the music file cache. Cache location was reset to the default path.</string>
|
||||
<string name="permissions.message_box_title">Warning</string>
|
||||
|
@ -402,6 +402,13 @@ ponieważ api Subsonic nie wspiera nowego sposobu autoryzacji dla użytkowników
|
||||
<string name="settings.playback.bluetooth_all">All Bluetooth devices</string>
|
||||
<string name="settings.playback.bluetooth_a2dp">Only audio (A2DP) devices</string>
|
||||
<string name="settings.playback.bluetooth_disabled">Disabled</string>
|
||||
<string name="settings.debug.title">Debug options</string>
|
||||
<string name="settings.debug.log_to_file">Write debug log to file</string>
|
||||
<string name="settings.debug.log_path">The log files are available at %1$s/%2$s</string>
|
||||
<string name="settings.debug.log_summary">There are %1$s log files taking up ~%2$s MB space in the %3$s directory. Do you want to keep these?</string>
|
||||
<string name="settings.debug.log_keep">Keep files</string>
|
||||
<string name="settings.debug.log_delete">Delete files</string>
|
||||
<string name="settings.debug.log_deleted">Deleted log files.</string>
|
||||
|
||||
<string name="permissions.access_error">Ultrasonic can\'t access the music file cache. Cache location was reset to the default path.</string>
|
||||
<string name="permissions.message_box_title">Warning</string>
|
||||
|
@ -402,6 +402,13 @@
|
||||
<string name="settings.playback.bluetooth_all">All Bluetooth devices</string>
|
||||
<string name="settings.playback.bluetooth_a2dp">Only audio (A2DP) devices</string>
|
||||
<string name="settings.playback.bluetooth_disabled">Disabled</string>
|
||||
<string name="settings.debug.title">Debug options</string>
|
||||
<string name="settings.debug.log_to_file">Write debug log to file</string>
|
||||
<string name="settings.debug.log_path">The log files are available at %1$s/%2$s</string>
|
||||
<string name="settings.debug.log_summary">There are %1$s log files taking up ~%2$s MB space in the %3$s directory. Do you want to keep these?</string>
|
||||
<string name="settings.debug.log_keep">Keep files</string>
|
||||
<string name="settings.debug.log_delete">Delete files</string>
|
||||
<string name="settings.debug.log_deleted">Deleted log files.</string>
|
||||
|
||||
<string name="permissions.access_error">Ultrasonic can\'t access the music file cache. Cache location was reset to the default path.</string>
|
||||
<string name="permissions.message_box_title">Warning</string>
|
||||
|
@ -402,6 +402,13 @@
|
||||
<string name="settings.playback.bluetooth_all">All Bluetooth devices</string>
|
||||
<string name="settings.playback.bluetooth_a2dp">Only audio (A2DP) devices</string>
|
||||
<string name="settings.playback.bluetooth_disabled">Disabled</string>
|
||||
<string name="settings.debug.title">Debug options</string>
|
||||
<string name="settings.debug.log_to_file">Write debug log to file</string>
|
||||
<string name="settings.debug.log_path">The log files are available at %1$s/%2$s</string>
|
||||
<string name="settings.debug.log_summary">There are %1$s log files taking up ~%2$s MB space in the %3$s directory. Do you want to keep these?</string>
|
||||
<string name="settings.debug.log_keep">Keep files</string>
|
||||
<string name="settings.debug.log_delete">Delete files</string>
|
||||
<string name="settings.debug.log_deleted">Deleted log files.</string>
|
||||
|
||||
<string name="permissions.access_error">Ultrasonic can\'t access the music file cache. Cache location was reset to the default path.</string>
|
||||
<string name="permissions.message_box_title">Warning</string>
|
||||
|
@ -405,6 +405,13 @@
|
||||
<string name="settings.playback.bluetooth_all">All Bluetooth devices</string>
|
||||
<string name="settings.playback.bluetooth_a2dp">Only audio (A2DP) devices</string>
|
||||
<string name="settings.playback.bluetooth_disabled">Disabled</string>
|
||||
<string name="settings.debug.title">Debug options</string>
|
||||
<string name="settings.debug.log_to_file">Write debug log to file</string>
|
||||
<string name="settings.debug.log_path">The log files are available at %1$s/%2$s</string>
|
||||
<string name="settings.debug.log_summary">There are %1$s log files taking up ~%2$s MB space in the %3$s directory. Do you want to keep these?</string>
|
||||
<string name="settings.debug.log_keep">Keep files</string>
|
||||
<string name="settings.debug.log_delete">Delete files</string>
|
||||
<string name="settings.debug.log_deleted">Deleted log files.</string>
|
||||
|
||||
<string name="permissions.access_error">Ultrasonic can\'t access the music file cache. Cache location was reset to the default path.</string>
|
||||
<string name="permissions.message_box_title">Warning</string>
|
||||
|
@ -305,7 +305,14 @@
|
||||
a:title="@string/feature_flags_five_star_rating_title"
|
||||
a:summary="@string/feature_flags_five_star_rating_description"
|
||||
/>
|
||||
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory a:title="@string/settings.debug.title">
|
||||
<CheckBoxPreference
|
||||
a:defaultValue="false"
|
||||
a:key="debugLogToFile"
|
||||
a:title="@string/settings.debug.log_to_file"
|
||||
a:summary=""
|
||||
/>
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
Loading…
x
Reference in New Issue
Block a user