From 216b51d138a5f9c1d67e4dab6d485c297806783a Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Thu, 14 Mar 2019 19:14:34 +0000 Subject: [PATCH] Create a logger object to take care of all the logging. --- .../com/etesync/syncadapter/log/Logger.kt | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 app/src/main/java/com/etesync/syncadapter/log/Logger.kt diff --git a/app/src/main/java/com/etesync/syncadapter/log/Logger.kt b/app/src/main/java/com/etesync/syncadapter/log/Logger.kt new file mode 100644 index 00000000..2ae226e9 --- /dev/null +++ b/app/src/main/java/com/etesync/syncadapter/log/Logger.kt @@ -0,0 +1,126 @@ +/* + * Copyright © Ricki Hirner (bitfire web engineering). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + */ + +package com.etesync.syncadapter.log + +import android.annotation.SuppressLint +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.content.SharedPreferences +import android.os.Process +import android.preference.PreferenceManager +import android.util.Log +import android.widget.Toast +import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationManagerCompat +import com.etesync.syncadapter.App +import com.etesync.syncadapter.Constants +import com.etesync.syncadapter.R +import com.etesync.syncadapter.model.ServiceDB +import com.etesync.syncadapter.model.Settings +import com.etesync.syncadapter.ui.AppSettingsActivity +import org.apache.commons.lang3.time.DateFormatUtils +import java.io.File +import java.io.IOException +import java.util.logging.FileHandler +import java.util.logging.Level + +@SuppressLint("StaticFieldLeak") // we'll only keep an app context +object Logger : SharedPreferences.OnSharedPreferenceChangeListener { + + private const val LOG_TO_FILE = "log_to_file" + + val log = java.util.logging.Logger.getLogger("etesync")!! + + private lateinit var context: Context + + fun initialize(someContext: Context) { + context = someContext.applicationContext + + reinitialize() + } + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { + if (key == LOG_TO_FILE) { + log.info("Logging settings changed; re-initializing logger") + reinitialize() + } + } + + private fun reinitialize() { + val dbHelper = ServiceDB.OpenHelper(context) + val settings = Settings(dbHelper.readableDatabase) + + val logToFile = settings.getBoolean(App.LOG_TO_EXTERNAL_STORAGE, false) + val logVerbose = logToFile || Log.isLoggable(App.log.name, Log.DEBUG) + + log.info("Verbose logging: $logVerbose; to file: $logToFile") + + // set logging level according to preferences + val rootLogger = java.util.logging.Logger.getLogger("") + rootLogger.level = if (logVerbose) Level.ALL else Level.INFO + + // remove all handlers and add our own logcat handler + rootLogger.useParentHandlers = false + rootLogger.handlers.forEach { rootLogger.removeHandler(it) } + rootLogger.addHandler(LogcatHandler) + + val nm = NotificationManagerCompat.from(context) + // log to external file according to preferences + if (logToFile) { + val builder = NotificationCompat.Builder(context) + builder.setSmallIcon(R.drawable.ic_sd_storage_light) + .setLargeIcon(App.getLauncherBitmap(context)) + .setContentTitle(context.getString(R.string.logging_davdroid_file_logging)) + .setLocalOnly(true) + + val logDir = debugDir(context) ?: return + val logFile = File(logDir, + "etesync-${Process.myPid()}-${DateFormatUtils.format(System.currentTimeMillis(), "yyyyMMdd-HHmmss")}.txt") + + try { + val fileHandler = FileHandler(logFile.toString(), true) + fileHandler.formatter = PlainTextFormatter.DEFAULT + rootLogger.addHandler(fileHandler) + + val prefIntent = Intent(context, AppSettingsActivity::class.java) + prefIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + + builder .setContentText(logDir.path) + .setCategory(NotificationCompat.CATEGORY_STATUS) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setSubText(context.getString(R.string.logging_to_external_storage_warning)) + .setContentIntent(PendingIntent.getActivity(context, 0, prefIntent, PendingIntent.FLAG_UPDATE_CURRENT)) + .setOngoing(true) + } catch(e: IOException) { + log.log(Level.SEVERE, "Couldn't create log file", e) + Toast.makeText(context, context.getString(R.string.logging_couldnt_create_file), Toast.LENGTH_LONG).show() + } + + nm.notify(Constants.NOTIFICATION_EXTERNAL_FILE_LOGGING, builder.build()) + } else { + nm.cancel(Constants.NOTIFICATION_EXTERNAL_FILE_LOGGING) + + // delete old logs + debugDir(context)?.deleteRecursively() + } + } + + private fun debugDir(context: Context): File? { + val dir = File(context.filesDir, "debug") + if (dir.exists() && dir.isDirectory) + return dir + + if (dir.mkdir()) + return dir + + Toast.makeText(context, context.getString(R.string.logging_couldnt_create_file), Toast.LENGTH_LONG).show() + return null + } +} \ No newline at end of file