2019-03-14 19:14:34 +00:00
|
|
|
/*
|
|
|
|
* 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.ui.AppSettingsActivity
|
2019-03-14 21:15:17 +00:00
|
|
|
import com.etesync.syncadapter.utils.NotificationUtils
|
2019-03-14 19:14:34 +00:00
|
|
|
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"
|
2019-03-14 21:25:47 +00:00
|
|
|
private const val LOG_VERBOSE = "log_verbose"
|
2019-03-14 19:14:34 +00:00
|
|
|
|
|
|
|
val log = java.util.logging.Logger.getLogger("etesync")!!
|
|
|
|
|
|
|
|
private lateinit var context: Context
|
2019-03-14 20:30:07 +00:00
|
|
|
private lateinit var preferences: SharedPreferences
|
2019-03-14 19:14:34 +00:00
|
|
|
|
|
|
|
fun initialize(someContext: Context) {
|
|
|
|
context = someContext.applicationContext
|
2019-03-14 20:30:07 +00:00
|
|
|
preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
|
|
|
preferences.registerOnSharedPreferenceChangeListener(this)
|
2019-03-14 19:14:34 +00:00
|
|
|
|
|
|
|
reinitialize()
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
2019-03-14 21:25:47 +00:00
|
|
|
if (key == LOG_TO_FILE || key == LOG_VERBOSE) {
|
2019-03-14 19:14:34 +00:00
|
|
|
log.info("Logging settings changed; re-initializing logger")
|
|
|
|
reinitialize()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun reinitialize() {
|
2019-03-14 20:30:07 +00:00
|
|
|
val logToFile = preferences.getBoolean(LOG_TO_FILE, false)
|
2019-03-14 21:25:47 +00:00
|
|
|
val logVerbose = preferences.getBoolean(LOG_VERBOSE, false) || Log.isLoggable(Logger.log.name, Log.DEBUG)
|
2019-03-14 19:14:34 +00:00
|
|
|
|
|
|
|
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) {
|
2019-03-14 21:15:17 +00:00
|
|
|
val builder = NotificationUtils.newBuilder(context, NotificationUtils.CHANNEL_DEBUG)
|
2019-03-14 19:14:34 +00:00
|
|
|
builder.setSmallIcon(R.drawable.ic_sd_storage_light)
|
|
|
|
.setLargeIcon(App.getLauncherBitmap(context))
|
|
|
|
.setContentTitle(context.getString(R.string.logging_davdroid_file_logging))
|
|
|
|
|
|
|
|
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))
|
2019-03-14 20:10:31 +00:00
|
|
|
.setStyle(NotificationCompat.BigTextStyle()
|
|
|
|
.bigText(context.getString(R.string.logging_to_external_storage, logDir.path)))
|
2019-03-14 19:14:34 +00:00
|
|
|
.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? {
|
2019-03-14 20:10:31 +00:00
|
|
|
val dir = File(context.getExternalFilesDir(null), "debug")
|
2019-03-14 19:14:34 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|