diff --git a/app/build.gradle b/app/build.gradle index db475477..6cc7a222 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -42,7 +42,7 @@ android { buildTypes { alpha { applicationIdSuffix ".beta" // keep as beta by popular request - versionNameSuffix "-alpha02" + versionNameSuffix "-alpha03" manifestPlaceholders = [icon_placeholder: "@mipmap/ic_launcher_alpha", icon_placeholder_round: "@mipmap/ic_launcher_alpha_round"] debuggable System.getenv("CI") == null isDefault true diff --git a/app/src/google/java/ani/dantotsu/others/AppUpdater.kt b/app/src/google/java/ani/dantotsu/others/AppUpdater.kt index 595aaab4..ec9acfc6 100644 --- a/app/src/google/java/ani/dantotsu/others/AppUpdater.kt +++ b/app/src/google/java/ani/dantotsu/others/AppUpdater.kt @@ -14,8 +14,18 @@ import androidx.core.content.ContextCompat import androidx.core.content.FileProvider import androidx.core.content.getSystemService import androidx.fragment.app.FragmentActivity -import ani.dantotsu.* +import ani.dantotsu.BuildConfig +import ani.dantotsu.Mapper +import ani.dantotsu.R +import ani.dantotsu.client +import ani.dantotsu.currContext +import ani.dantotsu.logError +import ani.dantotsu.openLinkInBrowser import ani.dantotsu.settings.saving.PrefManager +import ani.dantotsu.snackString +import ani.dantotsu.toast +import ani.dantotsu.tryWithSuspend +import ani.dantotsu.util.Logger import io.noties.markwon.Markwon import io.noties.markwon.SoftBreakAddsNewLinePlugin import kotlinx.coroutines.Dispatchers @@ -50,7 +60,7 @@ object AppUpdater { res to res.substringAfter("# ").substringBefore("\n") } - logger("Git Version : $version") + Logger.log("Git Version : $version") val dontShow = PrefManager.getCustomVal("dont_ask_for_update_$version", false) if (compareVersion(version) && !dontShow && !activity.isDestroyed) activity.runOnUiThread { CustomBottomDialog.newInstance().apply { diff --git a/app/src/main/java/ani/dantotsu/App.kt b/app/src/main/java/ani/dantotsu/App.kt index bd664906..51336438 100644 --- a/app/src/main/java/ani/dantotsu/App.kt +++ b/app/src/main/java/ani/dantotsu/App.kt @@ -21,6 +21,8 @@ import ani.dantotsu.parsers.novel.NovelExtensionManager import ani.dantotsu.settings.SettingsActivity import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName +import ani.dantotsu.util.FinalExceptionHandler +import ani.dantotsu.util.Logger import com.google.android.material.color.DynamicColors import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager @@ -83,7 +85,8 @@ class App : MultiDexApplication() { } crashlytics.setCustomKey("device Info", SettingsActivity.getDeviceInfo()) - + Logger.init(this) + Thread.setDefaultUncaughtExceptionHandler(FinalExceptionHandler()) initializeNetwork(baseContext) @@ -99,19 +102,19 @@ class App : MultiDexApplication() { val animeScope = CoroutineScope(Dispatchers.Default) animeScope.launch { animeExtensionManager.findAvailableExtensions() - logger("Anime Extensions: ${animeExtensionManager.installedExtensionsFlow.first()}") + Logger.log("Anime Extensions: ${animeExtensionManager.installedExtensionsFlow.first()}") AnimeSources.init(animeExtensionManager.installedExtensionsFlow) } val mangaScope = CoroutineScope(Dispatchers.Default) mangaScope.launch { mangaExtensionManager.findAvailableExtensions() - logger("Manga Extensions: ${mangaExtensionManager.installedExtensionsFlow.first()}") + Logger.log("Manga Extensions: ${mangaExtensionManager.installedExtensionsFlow.first()}") MangaSources.init(mangaExtensionManager.installedExtensionsFlow) } val novelScope = CoroutineScope(Dispatchers.Default) novelScope.launch { novelExtensionManager.findAvailableExtensions() - logger("Novel Extensions: ${novelExtensionManager.installedExtensionsFlow.first()}") + Logger.log("Novel Extensions: ${novelExtensionManager.installedExtensionsFlow.first()}") NovelSources.init(novelExtensionManager.installedExtensionsFlow) } val commentsScope = CoroutineScope(Dispatchers.Default) @@ -138,7 +141,8 @@ class App : MultiDexApplication() { try { Notifications.createChannels(this) } catch (e: Exception) { - logcat(LogPriority.ERROR, e) { "Failed to modify notification channels" } + Logger.log("Failed to modify notification channels") + Logger.log(e) } } diff --git a/app/src/main/java/ani/dantotsu/Functions.kt b/app/src/main/java/ani/dantotsu/Functions.kt index b8333b6a..aafad39f 100644 --- a/app/src/main/java/ani/dantotsu/Functions.kt +++ b/app/src/main/java/ani/dantotsu/Functions.kt @@ -28,7 +28,6 @@ import android.telephony.TelephonyManager import android.text.InputFilter import android.text.Spanned import android.util.AttributeSet -import android.util.Log import android.util.TypedValue import android.view.* import android.view.ViewGroup.LayoutParams.WRAP_CONTENT @@ -60,6 +59,7 @@ import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.internal.PreferenceKeystore import ani.dantotsu.settings.saving.internal.PreferenceKeystore.Companion.generateSalt import ani.dantotsu.subcriptions.NotificationClickReceiver +import ani.dantotsu.util.Logger import com.bumptech.glide.Glide import com.bumptech.glide.RequestBuilder import com.bumptech.glide.RequestManager @@ -128,13 +128,6 @@ fun currActivity(): Activity? { var loadMedia: Int? = null var loadIsMAL = false -fun logger(e: Any?, print: Boolean = true) { - if (print) - //println(e) - Log.d("Logger", e.toString()) -} - - fun initActivity(a: Activity) { val window = a.window WindowCompat.setDecorFitsSystemWindows(window, false) @@ -306,7 +299,7 @@ class InputFilterMinMax( val input = (dest.toString() + source.toString()).toDouble() if (isInRange(min, max, input)) return null } catch (nfe: NumberFormatException) { - logger(nfe.stackTraceToString()) + Logger.log(nfe) } return "" } @@ -761,7 +754,7 @@ fun saveImage(image: Bitmap, path: String, imageFileName: String): File? { private fun scanFile(path: String, context: Context) { MediaScannerConnection.scanFile(context, arrayOf(path), null) { p, _ -> - logger("Finished scanning $p") + Logger.log("Finished scanning $p") } } @@ -903,7 +896,7 @@ class EmptyAdapter(private val count: Int) : RecyclerView.Adapter().logException(e) } return null diff --git a/app/src/main/java/ani/dantotsu/MainActivity.kt b/app/src/main/java/ani/dantotsu/MainActivity.kt index fbfe58a6..358331ed 100644 --- a/app/src/main/java/ani/dantotsu/MainActivity.kt +++ b/app/src/main/java/ani/dantotsu/MainActivity.kt @@ -49,6 +49,7 @@ import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.SharedPreferenceBooleanLiveData import ani.dantotsu.subcriptions.Subscription.Companion.startSubscription import ani.dantotsu.themes.ThemeManager +import ani.dantotsu.util.Logger import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.Snackbar import eu.kanade.domain.source.service.SourcePreferences diff --git a/app/src/main/java/ani/dantotsu/Network.kt b/app/src/main/java/ani/dantotsu/Network.kt index dd58849a..e45f080a 100644 --- a/app/src/main/java/ani/dantotsu/Network.kt +++ b/app/src/main/java/ani/dantotsu/Network.kt @@ -5,6 +5,7 @@ import android.os.Build import androidx.fragment.app.FragmentActivity import ani.dantotsu.others.webview.CloudFlare import ani.dantotsu.others.webview.WebViewBottomDialog +import ani.dantotsu.util.Logger import com.lagradost.nicehttp.Requests import com.lagradost.nicehttp.ResponseParser import com.lagradost.nicehttp.addGenericDns @@ -104,6 +105,7 @@ fun logError(e: Throwable, post: Boolean = true, snackbar: Boolean = true) { toast(e.localizedMessage) } e.printStackTrace() + Logger.log(e) } fun tryWith(post: Boolean = false, snackbar: Boolean = true, call: () -> T): T? { diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/Anilist.kt b/app/src/main/java/ani/dantotsu/connections/anilist/Anilist.kt index 55b1098c..dae4150c 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/Anilist.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/Anilist.kt @@ -14,6 +14,7 @@ import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString import ani.dantotsu.toast import ani.dantotsu.tryWithSuspend +import ani.dantotsu.util.Logger import java.util.Calendar object Anilist { @@ -150,7 +151,7 @@ object Anilist { cacheTime = cache ?: 10 ) val remaining = json.headers["X-RateLimit-Remaining"]?.toIntOrNull() ?: -1 - Log.d("AnilistQuery", "Remaining requests: $remaining") + Logger.log("Remaining requests: $remaining") if (json.code == 429) { val retry = json.headers["Retry-After"]?.toIntOrNull() ?: -1 val passedLimitReset = json.headers["X-RateLimit-Reset"]?.toLongOrNull() ?: 0 @@ -161,13 +162,13 @@ object Anilist { toast("Rate limited. Try after $retry seconds") throw Exception("Rate limited after $retry seconds") } - if (!json.text.startsWith("{")) throw Exception(currContext()?.getString(R.string.anilist_down)) + if (!json.text.startsWith("{")) {throw Exception(currContext()?.getString(R.string.anilist_down))} if (show) println("Response : ${json.text}") json.parsed() } else null } catch (e: Exception) { if (show) snackString("Error fetching Anilist data: ${e.message}") - Log.e("AnilistQuery", "Error: ${e.message}") + Logger.log("Anilist Query Error: ${e.message}") null } } diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt index 07d93b9c..5eb28a79 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistViewModel.kt @@ -15,6 +15,7 @@ import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString import ani.dantotsu.tryWithSuspend +import ani.dantotsu.util.Logger import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -99,6 +100,7 @@ class AnilistHomeViewModel : ViewModel() { suspend fun initHomePage() { val res = Anilist.query.initHomePage() + Logger.log("AnilistHomeViewModel : res=$res") res["currentAnime"]?.let { animeContinue.postValue(it) } res["favoriteAnime"]?.let { animeFav.postValue(it) } res["plannedAnime"]?.let { animePlanned.postValue(it) } diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/Login.kt b/app/src/main/java/ani/dantotsu/connections/anilist/Login.kt index 7512fc5d..c5c56bc3 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/Login.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/Login.kt @@ -4,7 +4,7 @@ import android.net.Uri import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import ani.dantotsu.logError -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.startMainActivity @@ -16,7 +16,7 @@ class Login : AppCompatActivity() { ThemeManager(this).applyTheme() val data: Uri? = intent?.data - logger(data.toString()) + Logger.log(data.toString()) try { Anilist.token = Regex("""(?<=access_token=).+(?=&token_type)""").find(data.toString())!!.value diff --git a/app/src/main/java/ani/dantotsu/connections/crashlytics/CrashlyticsStub.kt b/app/src/main/java/ani/dantotsu/connections/crashlytics/CrashlyticsStub.kt index 524d42bf..6c4e988a 100644 --- a/app/src/main/java/ani/dantotsu/connections/crashlytics/CrashlyticsStub.kt +++ b/app/src/main/java/ani/dantotsu/connections/crashlytics/CrashlyticsStub.kt @@ -1,17 +1,18 @@ package ani.dantotsu.connections.crashlytics import android.content.Context +import ani.dantotsu.util.Logger class CrashlyticsStub : CrashlyticsInterface { override fun initialize(context: Context) { //no-op } override fun logException(e: Throwable) { - //no-op + Logger.log(e) } override fun log(message: String) { - //no-op + Logger.log(message) } override fun setUserId(id: String) { diff --git a/app/src/main/java/ani/dantotsu/connections/discord/DiscordService.kt b/app/src/main/java/ani/dantotsu/connections/discord/DiscordService.kt index 761dbeac..0a29ab60 100644 --- a/app/src/main/java/ani/dantotsu/connections/discord/DiscordService.kt +++ b/app/src/main/java/ani/dantotsu/connections/discord/DiscordService.kt @@ -15,7 +15,6 @@ import android.os.Environment import android.os.IBinder import android.os.PowerManager import android.provider.MediaStore -import android.util.Log import androidx.core.app.ActivityCompat import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat @@ -26,6 +25,7 @@ import ani.dantotsu.connections.discord.serializers.User import ani.dantotsu.isOnline import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName +import ani.dantotsu.util.Logger import com.google.gson.JsonArray import com.google.gson.JsonObject import com.google.gson.JsonParser @@ -274,7 +274,7 @@ class DiscordService : Service() { return } } - t.message?.let { Log.d("WebSocket", "onFailure() $it") } + t.message?.let { Logger.log("onFailure() $it") } log("WebSocket: Error, onFailure() reason: ${t.message}") client = OkHttpClient() client.newWebSocket( @@ -289,7 +289,7 @@ class DiscordService : Service() { override fun onClosing(webSocket: WebSocket, code: Int, reason: String) { super.onClosing(webSocket, code, reason) - Log.d("WebSocket", "onClosing() $code $reason") + Logger.log("onClosing() $code $reason") if (::heartbeatThread.isInitialized && !heartbeatThread.isInterrupted) { heartbeatThread.interrupt() } @@ -297,7 +297,7 @@ class DiscordService : Service() { override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { super.onClosed(webSocket, code, reason) - Log.d("WebSocket", "onClosed() $code $reason") + Logger.log("onClosed() $code $reason") if (code >= 4000) { log("WebSocket: Error, code: $code reason: $reason") client = OkHttpClient() @@ -382,52 +382,7 @@ class DiscordService : Service() { } fun log(string: String) { - Log.d("WebSocket_Discord", string) - //log += "${SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().time)} $string\n" - } - - fun saveLogToFile() { - val fileName = "log_${System.currentTimeMillis()}.txt" - - // ContentValues to store file metadata - val values = ContentValues().apply { - put(MediaStore.MediaColumns.DISPLAY_NAME, fileName) - put(MediaStore.MediaColumns.MIME_TYPE, "text/plain") - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - put(MediaStore.MediaColumns.RELATIVE_PATH, "Download/") - } - } - - // Inserting the file in the MediaStore - val resolver = baseContext.contentResolver - val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values) - } else { - val directory = - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) - val file = File(directory, fileName) - - // Make sure the Downloads directory exists - if (!directory.exists()) { - directory.mkdirs() - } - - // Use FileProvider to get the URI for the file - val authority = - "${baseContext.packageName}.provider" // Adjust with your app's package name - Uri.fromFile(file) - } - - // Writing to the file - uri?.let { - resolver.openOutputStream(it).use { outputStream -> - OutputStreamWriter(outputStream).use { writer -> - writer.write(log) - } - } - } ?: run { - log("Error saving log file") - } + //Logger.log(string) } fun resume() { diff --git a/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt b/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt index dd0198ec..8b19d9ab 100644 --- a/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt +++ b/app/src/main/java/ani/dantotsu/download/anime/AnimeDownloaderService.kt @@ -27,7 +27,7 @@ import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.video.ExoplayerDownloadService import ani.dantotsu.download.video.Helper -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.media.Media import ani.dantotsu.media.SubtitleDownloader import ani.dantotsu.media.anime.AnimeWatchFragment @@ -249,7 +249,7 @@ class AnimeDownloaderService : Service() { hasDownloadStarted(downloadManager, task, 30000) // 30 seconds timeout if (!downloadStarted) { - logger("Download failed to start") + Logger.log("Download failed to start") builder.setContentText("${task.title} - ${task.episode} Download failed to start") notificationManager.notify(NOTIFICATION_ID, builder.build()) snackString("${task.title} - ${task.episode} Download failed to start") @@ -263,11 +263,11 @@ class AnimeDownloaderService : Service() { val download = downloadManager.downloadIndex.getDownload(task.video.file.url) if (download != null) { if (download.state == androidx.media3.exoplayer.offline.Download.STATE_FAILED) { - logger("Download failed") + Logger.log("Download failed") builder.setContentText("${task.title} - ${task.episode} Download failed") notificationManager.notify(NOTIFICATION_ID, builder.build()) snackString("${task.title} - ${task.episode} Download failed") - logger("Download failed: ${download.failureReason}") + Logger.log("Download failed: ${download.failureReason}") downloadsManager.removeDownload( DownloadedType( task.title, @@ -289,7 +289,7 @@ class AnimeDownloaderService : Service() { break } if (download.state == androidx.media3.exoplayer.offline.Download.STATE_COMPLETED) { - logger("Download completed") + Logger.log("Download completed") builder.setContentText("${task.title} - ${task.episode} Download completed") notificationManager.notify(NOTIFICATION_ID, builder.build()) snackString("${task.title} - ${task.episode} Download completed") @@ -309,7 +309,7 @@ class AnimeDownloaderService : Service() { break } if (download.state == androidx.media3.exoplayer.offline.Download.STATE_STOPPED) { - logger("Download stopped") + Logger.log("Download stopped") builder.setContentText("${task.title} - ${task.episode} Download stopped") notificationManager.notify(NOTIFICATION_ID, builder.build()) snackString("${task.title} - ${task.episode} Download stopped") @@ -328,7 +328,7 @@ class AnimeDownloaderService : Service() { } } catch (e: Exception) { if (e.message?.contains("Coroutine was cancelled") == false) { //wut - logger("Exception while downloading file: ${e.message}") + Logger.log("Exception while downloading file: ${e.message}") snackString("Exception while downloading file: ${e.message}") e.printStackTrace() Injekt.get().logException(e) diff --git a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt index 4c91a43b..4ff5497c 100644 --- a/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt +++ b/app/src/main/java/ani/dantotsu/download/anime/OfflineAnimeFragment.kt @@ -33,7 +33,7 @@ import ani.dantotsu.currContext import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager import ani.dantotsu.initActivity -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.media.Media import ani.dantotsu.media.MediaDetailsActivity import ani.dantotsu.navBarHeight @@ -318,8 +318,8 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener { val mediaJson = media.readText() gson.fromJson(mediaJson, Media::class.java) } catch (e: Exception) { - logger("Error loading media.json: ${e.message}") - logger(e.printStackTrace()) + Logger.log("Error loading media.json: ${e.message}") + Logger.log(e) Injekt.get().logException(e) null } @@ -374,8 +374,8 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener { bannerUri ) } catch (e: Exception) { - logger("Error loading media.json: ${e.message}") - logger(e.printStackTrace()) + Logger.log("Error loading media.json: ${e.message}") + Logger.log(e) Injekt.get().logException(e) return OfflineAnimeModel( "unknown", diff --git a/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt b/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt index de91960c..cad2f85e 100644 --- a/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt +++ b/app/src/main/java/ani/dantotsu/download/manga/MangaDownloaderService.kt @@ -21,7 +21,7 @@ import ani.dantotsu.R import ani.dantotsu.connections.crashlytics.CrashlyticsInterface import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.media.Media import ani.dantotsu.media.manga.ImageData import ani.dantotsu.media.manga.MangaReadFragment.Companion.ACTION_DOWNLOAD_FAILED @@ -251,7 +251,7 @@ class MangaDownloaderService : Service() { snackString("${task.title} - ${task.chapter} Download finished") } } catch (e: Exception) { - logger("Exception while downloading file: ${e.message}") + Logger.log("Exception while downloading file: ${e.message}") snackString("Exception while downloading file: ${e.message}") Injekt.get().logException(e) broadcastDownloadFailed(task.chapter) diff --git a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt index 7bd43c9a..0c97a8df 100644 --- a/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt +++ b/app/src/main/java/ani/dantotsu/download/manga/OfflineMangaFragment.kt @@ -30,7 +30,7 @@ import ani.dantotsu.currContext import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager import ani.dantotsu.initActivity -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.media.Media import ani.dantotsu.media.MediaDetailsActivity import ani.dantotsu.navBarHeight @@ -308,8 +308,8 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener { val mediaJson = media.readText() gson.fromJson(mediaJson, Media::class.java) } catch (e: Exception) { - logger("Error loading media.json: ${e.message}") - logger(e.printStackTrace()) + Logger.log("Error loading media.json: ${e.message}") + Logger.log(e) Injekt.get().logException(e) null } @@ -358,8 +358,8 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener { bannerUri ) } catch (e: Exception) { - logger("Error loading media.json: ${e.message}") - logger(e.printStackTrace()) + Logger.log("Error loading media.json: ${e.message}") + Logger.log(e) Injekt.get().logException(e) return OfflineMangaModel( "unknown", diff --git a/app/src/main/java/ani/dantotsu/download/novel/NovelDownloaderService.kt b/app/src/main/java/ani/dantotsu/download/novel/NovelDownloaderService.kt index f6a7e2ed..06043976 100644 --- a/app/src/main/java/ani/dantotsu/download/novel/NovelDownloaderService.kt +++ b/app/src/main/java/ani/dantotsu/download/novel/NovelDownloaderService.kt @@ -20,7 +20,7 @@ import ani.dantotsu.R import ani.dantotsu.connections.crashlytics.CrashlyticsInterface import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.media.Media import ani.dantotsu.media.novel.NovelReadFragment import ani.dantotsu.snackString @@ -186,15 +186,15 @@ class NovelDownloaderService : Service() { val contentType = response.header("Content-Type") val contentDisposition = response.header("Content-Disposition") - logger("Content-Type: $contentType") - logger("Content-Disposition: $contentDisposition") + Logger.log("Content-Type: $contentType") + Logger.log("Content-Disposition: $contentDisposition") // Return true if the Content-Type or Content-Disposition indicates an EPUB file contentType == "application/epub+zip" || (contentDisposition?.contains(".epub") == true) } } catch (e: Exception) { - logger("Error checking file type: ${e.message}") + Logger.log("Error checking file type: ${e.message}") false } } @@ -225,12 +225,12 @@ class NovelDownloaderService : Service() { if (!isEpubFile(task.downloadLink)) { if (isAlreadyDownloaded(task.originalLink)) { - logger("Already downloaded") + Logger.log("Already downloaded") broadcastDownloadFinished(task.originalLink) snackString("Already downloaded") return@withContext } - logger("Download link is not an .epub file") + Logger.log("Download link is not an .epub file") broadcastDownloadFailed(task.originalLink) snackString("Download link is not an .epub file") return@withContext @@ -301,7 +301,7 @@ class NovelDownloaderService : Service() { withContext(Dispatchers.Main) { val progress = (downloadedBytes * 100 / totalBytes).toInt() - logger("Download progress: $progress") + Logger.log("Download progress: $progress") broadcastDownloadProgress(task.originalLink, progress) } lastBroadcastUpdate = downloadedBytes @@ -316,7 +316,7 @@ class NovelDownloaderService : Service() { } } } catch (e: Exception) { - logger("Exception while downloading .epub inside request: ${e.message}") + Logger.log("Exception while downloading .epub inside request: ${e.message}") throw e } } @@ -340,7 +340,7 @@ class NovelDownloaderService : Service() { snackString("${task.title} - ${task.chapter} Download finished") } } catch (e: Exception) { - logger("Exception while downloading .epub: ${e.message}") + Logger.log("Exception while downloading .epub: ${e.message}") snackString("Exception while downloading .epub: ${e.message}") Injekt.get().logException(e) broadcastDownloadFailed(task.originalLink) diff --git a/app/src/main/java/ani/dantotsu/download/video/Helper.kt b/app/src/main/java/ani/dantotsu/download/video/Helper.kt index 7f92eda6..4e82e76c 100644 --- a/app/src/main/java/ani/dantotsu/download/video/Helper.kt +++ b/app/src/main/java/ani/dantotsu/download/video/Helper.kt @@ -43,6 +43,7 @@ import ani.dantotsu.parsers.SubtitleType import ani.dantotsu.parsers.Video import ani.dantotsu.parsers.VideoType import ani.dantotsu.settings.saving.PrefManager +import ani.dantotsu.util.Logger import eu.kanade.tachiyomi.network.NetworkHelper import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -157,15 +158,15 @@ object Helper { finalException: Exception? ) { if (download.state == Download.STATE_COMPLETED) { - Log.e("Downloader", "Download Completed") + Logger.log("Download Completed") } else if (download.state == Download.STATE_FAILED) { - Log.e("Downloader", "Download Failed") + Logger.log("Download Failed") } else if (download.state == Download.STATE_STOPPED) { - Log.e("Downloader", "Download Stopped") + Logger.log("Download Stopped") } else if (download.state == Download.STATE_QUEUED) { - Log.e("Downloader", "Download Queued") + Logger.log("Download Queued") } else if (download.state == Download.STATE_DOWNLOADING) { - Log.e("Downloader", "Download Downloading") + Logger.log("Download Downloading") } } } diff --git a/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt b/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt index 8f10863f..650e722d 100644 --- a/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt +++ b/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt @@ -9,7 +9,7 @@ import androidx.lifecycle.ViewModel import ani.dantotsu.R import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.currContext -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.media.anime.Episode import ani.dantotsu.media.anime.SelectorDialogFragment import ani.dantotsu.media.manga.MangaChapter @@ -223,7 +223,7 @@ class MediaDetailsViewModel : ViewModel() { } fun setEpisode(ep: Episode?, who: String) { - logger("set episode ${ep?.number} - $who", false) + Logger.log("set episode ${ep?.number} - $who") episode.postValue(ep) MainScope().launch(Dispatchers.Main) { episode.value = null @@ -270,7 +270,7 @@ class MediaDetailsViewModel : ViewModel() { mangaChapters suspend fun loadMangaChapters(media: Media, i: Int, invalidate: Boolean = false) { - logger("Loading Manga Chapters : $mangaLoaded") + Logger.log("Loading Manga Chapters : $mangaLoaded") if (!mangaLoaded.containsKey(i) || invalidate) tryWithSuspend { mangaLoaded[i] = mangaReadSources?.loadChaptersFromMedia(i, media) ?: return@tryWithSuspend diff --git a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt index ee4623a9..eb70520e 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt @@ -86,6 +86,7 @@ import ani.dantotsu.settings.PlayerSettingsActivity import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.themes.ThemeManager +import ani.dantotsu.util.Logger import com.bumptech.glide.Glide import com.google.android.gms.cast.framework.CastButtonFactory import com.google.android.gms.cast.framework.CastContext @@ -1372,8 +1373,8 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL mediaItem = if (downloadedMediaItem == null) { val builder = MediaItem.Builder().setUri(video!!.file.url).setMimeType(mimeType) - logger("url: ${video!!.file.url}") - logger("mimeType: $mimeType") + Logger.log("url: ${video!!.file.url}") + Logger.log("mimeType: $mimeType") if (sub != null) { val listofnotnullsubs = listOfNotNull(sub) diff --git a/app/src/main/java/ani/dantotsu/media/manga/MangaCache.kt b/app/src/main/java/ani/dantotsu/media/manga/MangaCache.kt index 50eec776..ebf1c57f 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/MangaCache.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/MangaCache.kt @@ -10,7 +10,7 @@ import android.os.Build import android.os.Environment import android.provider.MediaStore import android.util.LruCache -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.snackString import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.online.HttpSource @@ -32,8 +32,8 @@ data class ImageData( try { // Fetch the image val response = httpSource.getImage(page) - logger("Response: ${response.code}") - logger("Response: ${response.message}") + Logger.log("Response: ${response.code}") + Logger.log("Response: ${response.message}") // Convert the Response to an InputStream val inputStream = response.body.byteStream() @@ -47,7 +47,7 @@ data class ImageData( return@withContext bitmap } catch (e: Exception) { // Handle any exceptions - logger("An error occurred: ${e.message}") + Logger.log("An error occurred: ${e.message}") snackString("An error occurred: ${e.message}") return@withContext null } diff --git a/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt b/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt index 369f446e..859dfdac 100644 --- a/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/novel/NovelReadFragment.kt @@ -31,6 +31,7 @@ import ani.dantotsu.media.MediaDetailsViewModel import ani.dantotsu.media.novel.novelreader.NovelReaderActivity import ani.dantotsu.navBarHeight import ani.dantotsu.parsers.ShowResponse +import ani.dantotsu.util.Logger import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -59,7 +60,7 @@ class NovelReadFragment : Fragment(), var loaded = false override fun downloadTrigger(novelDownloadPackage: NovelDownloadPackage) { - Log.e("downloadTrigger", novelDownloadPackage.link) + Logger.log("novel link: ${novelDownloadPackage.link}") val downloadTask = NovelDownloaderService.DownloadTask( title = media.mainName(), chapter = novelDownloadPackage.novelName, diff --git a/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt b/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt index 0ab80e14..9cbffc50 100644 --- a/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/novel/NovelResponseAdapter.kt @@ -11,6 +11,7 @@ import ani.dantotsu.databinding.ItemNovelResponseBinding import ani.dantotsu.parsers.ShowResponse import ani.dantotsu.setAnimation import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import com.bumptech.glide.Glide import com.bumptech.glide.load.model.GlideUrl @@ -181,7 +182,7 @@ class NovelResponseAdapter( if (position != -1) { list[position].extra?.remove("0") list[position].extra?.set("0", "Downloading: $progress%") - Log.d("NovelResponseAdapter", "updateDownloadProgress: $progress, position: $position") + Logger.log( "updateDownloadProgress: $progress, position: $position") notifyItemChanged(position) } } diff --git a/app/src/main/java/ani/dantotsu/others/JsUnpacker.kt b/app/src/main/java/ani/dantotsu/others/JsUnpacker.kt index 35ebe7b5..ecb5f0ce 100644 --- a/app/src/main/java/ani/dantotsu/others/JsUnpacker.kt +++ b/app/src/main/java/ani/dantotsu/others/JsUnpacker.kt @@ -1,6 +1,6 @@ package ani.dantotsu.others -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import java.util.regex.Pattern import kotlin.math.pow @@ -64,7 +64,7 @@ class JsUnpacker(packedJS: String?) { return decoded.toString() } } catch (e: Exception) { - logger(e) + Logger.log(e) } return null } diff --git a/app/src/main/java/ani/dantotsu/others/Kitsu.kt b/app/src/main/java/ani/dantotsu/others/Kitsu.kt index 374f0dd0..f548fc31 100644 --- a/app/src/main/java/ani/dantotsu/others/Kitsu.kt +++ b/app/src/main/java/ani/dantotsu/others/Kitsu.kt @@ -2,7 +2,7 @@ package ani.dantotsu.others import ani.dantotsu.FileUrl import ani.dantotsu.client -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.media.Media import ani.dantotsu.media.anime.Episode import ani.dantotsu.tryWithSuspend @@ -41,8 +41,7 @@ object Kitsu { } suspend fun getKitsuEpisodesDetails(media: Media): Map? { - val print = false - logger("Kitsu : title=${media.mainName()}", print) + Logger.log("Kitsu : title=${media.mainName()}") val query = """ query { @@ -70,7 +69,7 @@ query { val result = getKitsuData(query) ?: return null - logger("Kitsu : result=$result", print) + //Logger.log("Kitsu : result=$result") media.idKitsu = result.data?.lookupMapping?.id val a = (result.data?.lookupMapping?.episodes?.nodes ?: return null).mapNotNull { ep -> val num = ep?.number?.toString() ?: return@mapNotNull null @@ -81,7 +80,7 @@ query { thumb = FileUrl[ep.thumbnail?.original?.url], ) }.toMap() - logger("Kitsu : a=$a", print) + //Logger.log("Kitsu : a=$a") return a } diff --git a/app/src/main/java/ani/dantotsu/parsers/AniyomiAdapter.kt b/app/src/main/java/ani/dantotsu/parsers/AniyomiAdapter.kt index 7ec22cdb..04b50c54 100644 --- a/app/src/main/java/ani/dantotsu/parsers/AniyomiAdapter.kt +++ b/app/src/main/java/ani/dantotsu/parsers/AniyomiAdapter.kt @@ -11,7 +11,7 @@ import android.os.Environment import android.provider.MediaStore import ani.dantotsu.FileUrl import ani.dantotsu.currContext -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.media.anime.AnimeNameAdapter import ani.dantotsu.media.manga.ImageData import ani.dantotsu.media.manga.MangaCache @@ -129,7 +129,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() { val configurableSource = extension.sources[sourceLanguage] as? ConfigurableAnimeSource ?: return false currContext()?.let { context -> - logger("isDubAvailableSeparately: ${configurableSource.getPreferenceKey()}") + Logger.log("isDubAvailableSeparately: ${configurableSource.getPreferenceKey()}") val sharedPreferences = context.getSharedPreferences( configurableSource.getPreferenceKey(), @@ -205,7 +205,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() { } return sortedEpisodes.map { SEpisodeToEpisode(it) } } catch (e: Exception) { - logger("Exception: $e") + Logger.log("Exception: $e") } return emptyList() } @@ -240,7 +240,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() { val videos = source.getVideoList(sEpisode) videos.map { VideoToVideoServer(it) } } catch (e: Exception) { - logger("Exception occurred: ${e.message}") + Logger.log("Exception occurred: ${e.message}") emptyList() } } @@ -260,16 +260,16 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() { ?: return emptyList()) return try { val res = source.fetchSearchAnime(1, query, source.getFilterList()).awaitSingle() - logger("query: $query") + Logger.log("query: $query") convertAnimesPageToShowResponse(res) } catch (e: CloudflareBypassException) { - logger("Exception in search: $e") + Logger.log("Exception in search: $e") withContext(Dispatchers.Main) { snackString("Failed to bypass Cloudflare") } emptyList() } catch (e: Exception) { - logger("General exception in search: $e") + Logger.log("General exception in search: $e") emptyList() } } @@ -358,12 +358,12 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { val res = source.getChapterList(sManga) val reversedRes = res.reversed() val chapterList = reversedRes.map { SChapterToMangaChapter(it) } - logger("chapterList size: ${chapterList.size}") - logger("chapterList: ${chapterList[1].title}") - logger("chapterList: ${chapterList[1].description}") + Logger.log("chapterList size: ${chapterList.size}") + Logger.log("chapterList: ${chapterList[1].title}") + Logger.log("chapterList: ${chapterList[1].description}") chapterList } catch (e: Exception) { - logger("loadChapters Exception: $e") + Logger.log("loadChapters Exception: $e") emptyList() } } @@ -379,7 +379,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { var imageDataList: List = listOf() val ret = coroutineScope { try { - logger("source.name " + source.name) + Logger.log("source.name " + source.name) val res = source.getPageList(sChapter) val reIndexedPages = res.mapIndexed { index, page -> Page(index, page.url, page.imageUrl, page.uri) } @@ -388,7 +388,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { async(Dispatchers.IO) { mangaCache.put(page.imageUrl ?: "", ImageData(page, source)) imageDataList += ImageData(page, source) - logger("put page: ${page.imageUrl}") + Logger.log("put page: ${page.imageUrl}") pageToMangaImage(page) } } @@ -396,7 +396,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { deferreds.awaitAll() } catch (e: Exception) { - logger("loadImages Exception: $e") + Logger.log("loadImages Exception: $e") snackString("Failed to load images: $e") emptyList() } @@ -414,7 +414,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { return coroutineScope { try { - logger("source.name " + source.name) + Logger.log("source.name " + source.name) val res = source.getPageList(sChapter) val reIndexedPages = res.mapIndexed { index, page -> Page(index, page.url, page.imageUrl, page.uri) } @@ -430,7 +430,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { deferreds.awaitAll() } catch (e: Exception) { - logger("loadImages Exception: $e") + Logger.log("loadImages Exception: $e") snackString("Failed to load images: $e") emptyList() } @@ -446,8 +446,8 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { try { // Fetch the image val response = httpSource.getImage(page) - logger("Response: ${response.code}") - logger("Response: ${response.message}") + Logger.log("Response: ${response.code}") + Logger.log("Response: ${response.message}") // Convert the Response to an InputStream val inputStream = response.body.byteStream() @@ -467,7 +467,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { return@withContext bitmap } catch (e: Exception) { // Handle any exceptions - logger("An error occurred: ${e.message}") + Logger.log("An error occurred: ${e.message}") return@withContext null } } @@ -500,7 +500,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { inputStream.close() } catch (e: Exception) { // Handle any exceptions - logger("An error occurred: ${e.message}") + Logger.log("An error occurred: ${e.message}") } } } @@ -547,7 +547,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { } } catch (e: Exception) { // Handle exception here - logger("Exception while saving image: ${e.message}") + Logger.log("Exception while saving image: ${e.message}") } } @@ -562,16 +562,16 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() { return try { val res = source.fetchSearchManga(1, query, source.getFilterList()).awaitSingle() - logger("res observable: $res") + Logger.log("res observable: $res") convertMangasPageToShowResponse(res) } catch (e: CloudflareBypassException) { - logger("Exception in search: $e") + Logger.log("Exception in search: $e") withContext(Dispatchers.Main) { snackString("Failed to bypass Cloudflare") } emptyList() } catch (e: Exception) { - logger("General exception in search: $e") + Logger.log("General exception in search: $e") emptyList() } } @@ -714,7 +714,7 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() { // If the format is still undetermined, log an error if (format == null) { - logger("Unknown video format: $videoUrl") + Logger.log("Unknown video format: $videoUrl") format = VideoType.CONTAINER } val headersMap: Map = @@ -746,7 +746,7 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() { private fun headRequest(fileName: String, networkHelper: NetworkHelper): VideoType? { return try { - logger("attempting head request for $fileName") + Logger.log("attempting head request for $fileName") val request = Request.Builder() .url(fileName) .head() @@ -771,13 +771,13 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() { else -> null } } else { - logger("failed head request for $fileName") + Logger.log("failed head request for $fileName") null } } } catch (e: Exception) { - logger("Exception in headRequest: $e") + Logger.log("Exception in headRequest: $e") null } diff --git a/app/src/main/java/ani/dantotsu/parsers/BaseParser.kt b/app/src/main/java/ani/dantotsu/parsers/BaseParser.kt index e61c6890..6c2d5f79 100644 --- a/app/src/main/java/ani/dantotsu/parsers/BaseParser.kt +++ b/app/src/main/java/ani/dantotsu/parsers/BaseParser.kt @@ -3,7 +3,7 @@ package ani.dantotsu.parsers import ani.dantotsu.FileUrl import ani.dantotsu.R import ani.dantotsu.currContext -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.media.Media import ani.dantotsu.settings.saving.PrefManager import eu.kanade.tachiyomi.animesource.model.SAnime @@ -59,11 +59,11 @@ abstract class BaseParser { saveShowResponse(mediaObj.id, response, true) } else { setUserText("Searching : ${mediaObj.mainName()}") - logger("Searching : ${mediaObj.mainName()}") + Logger.log("Searching : ${mediaObj.mainName()}") val results = search(mediaObj.mainName()) //log all results results.forEach { - logger("Result: ${it.name}") + Logger.log("Result: ${it.name}") } val sortedResults = if (results.isNotEmpty()) { results.sortedByDescending { @@ -83,7 +83,7 @@ abstract class BaseParser { ) < 100 ) { setUserText("Searching : ${mediaObj.nameRomaji}") - logger("Searching : ${mediaObj.nameRomaji}") + Logger.log("Searching : ${mediaObj.nameRomaji}") val romajiResults = search(mediaObj.nameRomaji) val sortedRomajiResults = if (romajiResults.isNotEmpty()) { romajiResults.sortedByDescending { @@ -96,10 +96,10 @@ abstract class BaseParser { emptyList() } val closestRomaji = sortedRomajiResults.firstOrNull() - logger("Closest match from RomajiResults: ${closestRomaji?.name ?: "None"}") + Logger.log("Closest match from RomajiResults: ${closestRomaji?.name ?: "None"}") response = if (response == null) { - logger("No exact match found in results. Using closest match from RomajiResults.") + Logger.log("No exact match found in results. Using closest match from RomajiResults.") closestRomaji } else { val romajiRatio = FuzzySearch.ratio( @@ -110,14 +110,14 @@ abstract class BaseParser { response.name.lowercase(), mediaObj.mainName().lowercase() ) - logger("Fuzzy ratio for closest match in results: $mainNameRatio for ${response.name.lowercase()}") - logger("Fuzzy ratio for closest match in RomajiResults: $romajiRatio for ${closestRomaji?.name?.lowercase() ?: "None"}") + Logger.log("Fuzzy ratio for closest match in results: $mainNameRatio for ${response.name.lowercase()}") + Logger.log("Fuzzy ratio for closest match in RomajiResults: $romajiRatio for ${closestRomaji?.name?.lowercase() ?: "None"}") if (romajiRatio > mainNameRatio) { - logger("RomajiResults has a closer match. Replacing response.") + Logger.log("RomajiResults has a closer match. Replacing response.") closestRomaji } else { - logger("Results has a closer or equal match. Keeping existing response.") + Logger.log("Results has a closer or equal match. Keeping existing response.") response } } diff --git a/app/src/main/java/ani/dantotsu/parsers/BaseSources.kt b/app/src/main/java/ani/dantotsu/parsers/BaseSources.kt index 5aa6ffc2..475d681f 100644 --- a/app/src/main/java/ani/dantotsu/parsers/BaseSources.kt +++ b/app/src/main/java/ani/dantotsu/parsers/BaseSources.kt @@ -1,7 +1,7 @@ package ani.dantotsu.parsers import ani.dantotsu.Lazier -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.media.Media import ani.dantotsu.media.anime.Episode import ani.dantotsu.media.manga.MangaChapter @@ -96,7 +96,7 @@ abstract class MangaReadSources : BaseSources() { } //must be downloaded if (show.sManga == null) { - logger("sManga is null") + Logger.log("sManga is null") } if (parser is OfflineMangaParser && show.sManga == null) { tryWithSuspend(true) { @@ -106,11 +106,11 @@ abstract class MangaReadSources : BaseSources() { } } } else { - logger("Parser is not an instance of OfflineMangaParser") + Logger.log("Parser is not an instance of OfflineMangaParser") } - logger("map size ${map.size}") + Logger.log("map size ${map.size}") return map } } diff --git a/app/src/main/java/ani/dantotsu/parsers/NovelSources.kt b/app/src/main/java/ani/dantotsu/parsers/NovelSources.kt index 8fb66650..9420feb8 100644 --- a/app/src/main/java/ani/dantotsu/parsers/NovelSources.kt +++ b/app/src/main/java/ani/dantotsu/parsers/NovelSources.kt @@ -6,6 +6,7 @@ import ani.dantotsu.parsers.novel.DynamicNovelParser import ani.dantotsu.parsers.novel.NovelExtension import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName +import ani.dantotsu.util.Logger import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.first @@ -47,8 +48,8 @@ object NovelSources : NovelReadSources() { } private fun createParsersFromExtensions(extensions: List): List> { - Log.d("NovelSources", "createParsersFromExtensions") - Log.d("NovelSources", extensions.toString()) + Logger.log("createParsersFromExtensions") + Logger.log(extensions.toString()) return extensions.map { extension -> val name = extension.name Lazier({ DynamicNovelParser(extension) }, name) diff --git a/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt b/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt index deffb420..25099d78 100644 --- a/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt +++ b/app/src/main/java/ani/dantotsu/parsers/OfflineMangaParser.kt @@ -3,7 +3,7 @@ package ani.dantotsu.parsers import android.os.Environment import ani.dantotsu.currContext import ani.dantotsu.download.DownloadsManager -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.media.manga.MangaNameAdapter import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga @@ -68,7 +68,7 @@ class OfflineMangaParser : MangaParser() { matchResult?.groups?.get(1)?.value?.toIntOrNull() ?: Int.MAX_VALUE } for (image in images) { - logger("imageNumber: ${image.url.url}") + Logger.log("imageNumber: ${image.url.url}") } return images } diff --git a/app/src/main/java/ani/dantotsu/parsers/StringMatcher.kt b/app/src/main/java/ani/dantotsu/parsers/StringMatcher.kt index 191fecff..46c09781 100644 --- a/app/src/main/java/ani/dantotsu/parsers/StringMatcher.kt +++ b/app/src/main/java/ani/dantotsu/parsers/StringMatcher.kt @@ -1,6 +1,6 @@ package ani.dantotsu.parsers -import ani.dantotsu.logger +import ani.dantotsu.util.Logger class StringMatcher { companion object { @@ -54,10 +54,10 @@ class StringMatcher { val closestShowAndIndex = closestShow(target, shows) val closestIndex = closestShowAndIndex.second if (closestIndex == -1) { - logger("No closest show found for $target") + Logger.log("No closest show found for $target") return shows // Return original list if no closest show found } - logger("Closest show found for $target is ${closestShowAndIndex.first.name}") + Logger.log("Closest show found for $target is ${closestShowAndIndex.first.name}") return listOf(shows[closestIndex]) + shows.subList(0, closestIndex) + shows.subList( closestIndex + 1, shows.size diff --git a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionGithubApi.kt b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionGithubApi.kt index 4381ee27..9867658e 100644 --- a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionGithubApi.kt +++ b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionGithubApi.kt @@ -2,7 +2,7 @@ package ani.dantotsu.parsers.novel import android.content.Context -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import eu.kanade.tachiyomi.extension.ExtensionUpdateNotifier @@ -14,9 +14,7 @@ import eu.kanade.tachiyomi.network.awaitSuccess import eu.kanade.tachiyomi.network.parseAs import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json -import logcat.LogPriority import tachiyomi.core.util.lang.withIOContext -import tachiyomi.core.util.system.logcat import uy.kohesive.injekt.injectLazy import java.util.Date import kotlin.time.Duration.Companion.days @@ -41,20 +39,20 @@ class NovelExtensionGithubApi { .newCall(GET("${REPO_URL_PREFIX}index.min.json")) .awaitSuccess() } catch (e: Throwable) { - logcat(LogPriority.ERROR, e) { "Failed to get extensions from GitHub" } + Logger.log("Failed to get extensions from GitHub") requiresFallbackSource = true null } } val response = githubResponse ?: run { - logger("using fallback source") + Logger.log("using fallback source") networkService.client .newCall(GET("${FALLBACK_REPO_URL_PREFIX}index.min.json")) .awaitSuccess() } - logger("response: $response") + Logger.log("response: $response") val extensions = with(json) { response @@ -67,7 +65,7 @@ class NovelExtensionGithubApi { /*if (extensions.size < 10) { //TODO: uncomment when more extensions are added throw Exception() }*/ - logger("extensions: $extensions") + Logger.log("extensions: $extensions") extensions } } diff --git a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstallReceiver.kt b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstallReceiver.kt index 7835cb1d..056118a5 100644 --- a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstallReceiver.kt +++ b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstallReceiver.kt @@ -3,6 +3,7 @@ package ani.dantotsu.parsers.novel import android.os.FileObserver import android.util.Log import ani.dantotsu.parsers.novel.FileObserver.fileObserver +import ani.dantotsu.util.Logger import java.io.File @@ -22,24 +23,24 @@ class NovelExtensionFileObserver(private val listener: Listener, private val pat override fun onEvent(event: Int, file: String?) { - Log.e("NovelExtensionFileObserver", "Event: $event") + Logger.log("Event: $event") if (file == null) return val fullPath = File(path, file) when (event) { CREATE -> { - Log.e("NovelExtensionFileObserver", "File created: $fullPath") + Logger.log("File created: $fullPath") listener.onExtensionFileCreated(fullPath) } DELETE -> { - Log.e("NovelExtensionFileObserver", "File deleted: $fullPath") + Logger.log("File deleted: $fullPath") listener.onExtensionFileDeleted(fullPath) } MODIFY -> { - Log.e("NovelExtensionFileObserver", "File modified: $fullPath") + Logger.log("File modified: $fullPath") listener.onExtensionFileModified(fullPath) } } diff --git a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstaller.kt b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstaller.kt index 8bbf0561..14d7b75e 100644 --- a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstaller.kt +++ b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionInstaller.kt @@ -15,13 +15,12 @@ import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import androidx.core.net.toUri import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import com.jakewharton.rxrelay.PublishRelay import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.util.storage.getUriCompat -import logcat.LogPriority import rx.Observable import rx.android.schedulers.AndroidSchedulers -import tachiyomi.core.util.system.logcat import java.io.File import java.io.FileInputStream import java.io.FileOutputStream @@ -77,12 +76,12 @@ internal class NovelExtensionInstaller(private val context: Context) { val fileToDelete = File("$sourcePath/${url.toUri().lastPathSegment}") if (fileToDelete.exists()) { if (fileToDelete.delete()) { - Log.i("Install APK", "APK file deleted successfully.") + Logger.log("APK file deleted successfully.") } else { - Log.e("Install APK", "Failed to delete APK file.") + Logger.log("Failed to delete APK file.") } } else { - Log.e("Install APK", "APK file not found.") + Logger.log("APK file not found.") } // Register the receiver after removing (and unregistering) the previous download @@ -161,7 +160,7 @@ internal class NovelExtensionInstaller(private val context: Context) { // Check if source path is obtained correctly if (sourcePath == null) { - Log.e("Install APK", "Source APK path not found.") + Logger.log("Source APK path not found.") downloadsRelay.call(downloadId to InstallStep.Error) return InstallStep.Error } @@ -172,14 +171,14 @@ internal class NovelExtensionInstaller(private val context: Context) { destinationDir.mkdirs() } if (destinationDir?.setWritable(true) == false) { - Log.e("Install APK", "Failed to set destinationDir to writable.") + Logger.log("Failed to set destinationDir to writable.") downloadsRelay.call(downloadId to InstallStep.Error) return InstallStep.Error } // Copy the file to the new location copyFileToInternalStorage(sourcePath, destinationPath) - Log.i("Install APK", "APK moved to $destinationPath") + Logger.log("APK moved to $destinationPath") downloadsRelay.call(downloadId to InstallStep.Installed) return InstallStep.Installed } @@ -198,9 +197,9 @@ internal class NovelExtensionInstaller(private val context: Context) { val fileToDelete = File(apkPath) //give write permission to the file if (fileToDelete.exists() && !fileToDelete.canWrite()) { - Log.i("Uninstall APK", "File is not writable. Giving write permission.") + Logger.log("File is not writable. Giving write permission.") val a = fileToDelete.setWritable(true) - Log.i("Uninstall APK", "Success: $a") + Logger.log("Success: $a") } //set the directory to writable val destinationDir = File(apkPath).parentFile @@ -208,27 +207,27 @@ internal class NovelExtensionInstaller(private val context: Context) { destinationDir.mkdirs() } val s = destinationDir?.setWritable(true) - Log.i("Uninstall APK", "Success destinationDir: $s") + Logger.log("Success destinationDir: $s") if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { try { Files.delete(fileToDelete.toPath()) } catch (e: Exception) { - Log.e("Uninstall APK", "Failed to delete APK file.") - Log.e("Uninstall APK", e.toString()) + Logger.log("Failed to delete APK file.") + Logger.log(e) snackString("Failed to delete APK file.") } } else { if (fileToDelete.exists()) { if (fileToDelete.delete()) { - Log.i("Uninstall APK", "APK file deleted successfully.") + Logger.log("APK file deleted successfully.") snackString("APK file deleted successfully.") } else { - Log.e("Uninstall APK", "Failed to delete APK file.") + Logger.log("Failed to delete APK file.") snackString("Failed to delete APK file.") } } else { - Log.e("Uninstall APK", "APK file not found.") + Logger.log("APK file not found.") snackString("APK file not found.") } } @@ -242,9 +241,9 @@ internal class NovelExtensionInstaller(private val context: Context) { //delete the file if it already exists if (destination.exists()) { if (destination.delete()) { - Log.i("File Copy", "File deleted successfully.") + Logger.log("File deleted successfully.") } else { - Log.e("File Copy", "Failed to delete file.") + Logger.log("Failed to delete file.") } } @@ -262,7 +261,7 @@ internal class NovelExtensionInstaller(private val context: Context) { outputChannel?.close() } - Log.i("File Copy", "File copied to internal storage.") + Logger.log("File copied to internal storage.") } private fun getRealPathFromURI(context: Context, contentUri: Uri): String? { @@ -350,7 +349,7 @@ internal class NovelExtensionInstaller(private val context: Context) { // Set next installation step if (uri == null) { - logcat(LogPriority.ERROR) { "Couldn't locate downloaded APK" } + Logger.log("Couldn't locate downloaded APK") downloadsRelay.call(id to InstallStep.Error) return } @@ -371,7 +370,7 @@ internal class NovelExtensionInstaller(private val context: Context) { val uri = Uri.parse(localUri) val path = uri.path val pkgName = path?.substring(path.lastIndexOf('/') + 1)?.removeSuffix(".apk") - Log.i("Install APK", "Package name: $pkgName") + Logger.log("Package name: $pkgName") return pkgName ?: "" } } diff --git a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionLoader.kt b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionLoader.kt index 94574e20..78535115 100644 --- a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionLoader.kt +++ b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionLoader.kt @@ -7,7 +7,7 @@ import android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES import android.os.Build import android.util.Log import ani.dantotsu.connections.crashlytics.CrashlyticsInterface -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.parsers.NovelInterface import ani.dantotsu.snackString import dalvik.system.PathClassLoader @@ -26,21 +26,20 @@ internal object NovelExtensionLoader { val installDir = context.getExternalFilesDir(null)?.absolutePath + "/extensions/novel/" val results = mutableListOf() //the number of files - Log.e("NovelExtensionLoader", "Loading extensions from $installDir") - Log.e( - "NovelExtensionLoader", + Logger.log("Loading extensions from $installDir") + Logger.log( "Loading extensions from ${File(installDir).listFiles()?.size}" ) File(installDir).setWritable(false) File(installDir).listFiles()?.forEach { //set the file to read only it.setWritable(false) - Log.e("NovelExtensionLoader", "Loading extension ${it.name}") + Logger.log("Loading extension ${it.name}") val extension = loadExtension(context, it) if (extension is NovelLoadResult.Success) { results.add(extension) } else { - logger("Failed to load extension ${it.name}") + Logger.log("Failed to load extension ${it.name}") } } return results @@ -62,7 +61,7 @@ internal object NovelExtensionLoader { context.packageManager.getPackageArchiveInfo(path, 0) } catch (error: Exception) { // Unlikely, but the package may have been uninstalled at this point - logger("Failed to load extension $pkgName") + Logger.log("Failed to load extension $pkgName") return NovelLoadResult.Error(Exception("Failed to load extension")) } return loadExtension(context, File(path)) @@ -88,8 +87,8 @@ internal object NovelExtensionLoader { val signatureHash = getSignatureHash(packageInfo) if ((signatureHash == null) || !signatureHash.contains(officialSignature)) { - logger("Package ${packageInfo.packageName} isn't signed") - logger("signatureHash: $signatureHash") + Logger.log("Package ${packageInfo.packageName} isn't signed") + Logger.log("signatureHash: $signatureHash") snackString("Package ${packageInfo.packageName} isn't signed") //return NovelLoadResult.Error(Exception("Extension not signed")) } @@ -128,12 +127,12 @@ internal object NovelExtensionLoader { private fun loadSources(context: Context, file: File, className: String): List { return try { - Log.e("NovelExtensionLoader", "isFileWritable: ${file.canWrite()}") + Logger.log("isFileWritable: ${file.canWrite()}") if (file.canWrite()) { val a = file.setWritable(false) - Log.e("NovelExtensionLoader", "success: $a") + Logger.log("success: $a") } - Log.e("NovelExtensionLoader", "isFileWritable: ${file.canWrite()}") + Logger.log("isFileWritable: ${file.canWrite()}") val classLoader = PathClassLoader(file.absolutePath, null, context.classLoader) val className = "some.random.novelextensions.${className.lowercase(Locale.getDefault())}.$className" diff --git a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionManager.kt b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionManager.kt index c7a9723c..d52edd30 100644 --- a/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionManager.kt +++ b/app/src/main/java/ani/dantotsu/parsers/novel/NovelExtensionManager.kt @@ -2,7 +2,7 @@ package ani.dantotsu.parsers.novel import android.content.Context import android.graphics.drawable.Drawable -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.snackString import eu.kanade.tachiyomi.extension.InstallStep import kotlinx.coroutines.flow.MutableStateFlow @@ -70,7 +70,7 @@ class NovelExtensionManager(private val context: Context) { val extensions: List = try { api.findExtensions() } catch (e: Exception) { - logger("Error finding extensions: ${e.message}") + Logger.log("Error finding extensions: ${e.message}") withUIContext { snackString("Failed to get Novel extensions list") } emptyList() } diff --git a/app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt b/app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt index 5d85b0fc..f7fa8eec 100644 --- a/app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt +++ b/app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt @@ -14,7 +14,7 @@ import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.connections.anilist.AnilistQueries import ani.dantotsu.connections.anilist.api.Activity import ani.dantotsu.databinding.FragmentFeedBinding -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.profile.ProfileActivity import ani.dantotsu.snackString import com.xwray.groupie.GroupieAdapter diff --git a/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt b/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt index 97bde283..f7108bc7 100644 --- a/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/InstalledAnimeExtensionsFragment.kt @@ -25,7 +25,7 @@ import androidx.viewpager2.widget.ViewPager2 import ani.dantotsu.R import ani.dantotsu.connections.crashlytics.CrashlyticsInterface import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.others.LanguageMapper import ani.dantotsu.parsers.AnimeSources import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment @@ -146,7 +146,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler { }, { error -> Injekt.get().logException(error) - Log.e("AnimeExtensionsAdapter", "Error: ", error) // Log the error + Logger.log(error) // Log the error val builder = NotificationCompat.Builder( context, Notifications.CHANNEL_DOWNLOADER_ERROR diff --git a/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt b/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt index a102c76c..2da2a777 100644 --- a/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/InstalledMangaExtensionsFragment.kt @@ -32,6 +32,7 @@ import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import com.google.android.material.tabs.TabLayout import com.google.android.material.textfield.TextInputLayout import eu.kanade.tachiyomi.data.notification.Notifications @@ -143,7 +144,7 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler { }, { error -> Injekt.get().logException(error) - Log.e("MangaExtensionsAdapter", "Error: ", error) // Log the error + Logger.log(error) // Log the error val builder = NotificationCompat.Builder( context, Notifications.CHANNEL_DOWNLOADER_ERROR diff --git a/app/src/main/java/ani/dantotsu/settings/InstalledNovelExtensionsFragment.kt b/app/src/main/java/ani/dantotsu/settings/InstalledNovelExtensionsFragment.kt index 8353596d..5c46a5c9 100644 --- a/app/src/main/java/ani/dantotsu/settings/InstalledNovelExtensionsFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/InstalledNovelExtensionsFragment.kt @@ -30,6 +30,7 @@ import ani.dantotsu.parsers.novel.NovelExtensionManager import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import eu.kanade.tachiyomi.data.notification.Notifications import kotlinx.coroutines.launch import rx.android.schedulers.AndroidSchedulers @@ -72,7 +73,7 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler { }, { error -> Injekt.get().logException(error) - Log.e("NovelExtensionsAdapter", "Error: ", error) // Log the error + Logger.log(error) // Log the error val builder = NotificationCompat.Builder( context, Notifications.CHANNEL_DOWNLOADER_ERROR @@ -216,7 +217,7 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_extension, parent, false) - Log.d("NovelExtensionsAdapter", "onCreateViewHolder: $view") + Logger.log("onCreateViewHolder: $view") return ViewHolder(view) } diff --git a/app/src/main/java/ani/dantotsu/settings/NovelExtensionsFragment.kt b/app/src/main/java/ani/dantotsu/settings/NovelExtensionsFragment.kt index ffcc17e9..83b93c9c 100644 --- a/app/src/main/java/ani/dantotsu/settings/NovelExtensionsFragment.kt +++ b/app/src/main/java/ani/dantotsu/settings/NovelExtensionsFragment.kt @@ -59,7 +59,6 @@ class NovelExtensionsFragment : Fragment(), lifecycleScope.launch { viewModel.pagerFlow.collectLatest { pagingData -> - Log.d("NovelExtensionsFragment", "collectLatest") adapter.submitData(pagingData) } } diff --git a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt index d2ecb4e7..245da7bb 100644 --- a/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt +++ b/app/src/main/java/ani/dantotsu/settings/SettingsActivity.kt @@ -45,7 +45,7 @@ import ani.dantotsu.download.video.ExoplayerDownloadService import ani.dantotsu.downloadsPermission import ani.dantotsu.initActivity import ani.dantotsu.loadImage -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.navBarHeight import ani.dantotsu.openLinkInBrowser import ani.dantotsu.others.AppUpdater @@ -730,6 +730,16 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene binding.settingsShareUsername.isChecked = false } + binding.settingsLogToFile.isChecked = PrefManager.getVal(PrefName.LogToFile) + binding.settingsLogToFile.setOnCheckedChangeListener { _, isChecked -> + PrefManager.setVal(PrefName.LogToFile, isChecked) + restartApp() + } + + binding.settingsShareLog.setOnClickListener { + Logger.shareLog(this) + } + binding.settingsAccountHelp.setOnClickListener { val title = getString(R.string.account_help) val full = getString(R.string.full_account_help) @@ -884,7 +894,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene if (dialogTag == "colorPicker") { val color = extras.getInt(SimpleColorDialog.COLOR) PrefManager.setVal(PrefName.CustomThemeInt, color) - logger("Custom Theme: $color") + Logger.log("Custom Theme: $color") } } return true diff --git a/app/src/main/java/ani/dantotsu/settings/extensionprefs/AnimePreferenceFragmentCompat.kt b/app/src/main/java/ani/dantotsu/settings/extensionprefs/AnimePreferenceFragmentCompat.kt index c7fd31a6..0751454e 100644 --- a/app/src/main/java/ani/dantotsu/settings/extensionprefs/AnimePreferenceFragmentCompat.kt +++ b/app/src/main/java/ani/dantotsu/settings/extensionprefs/AnimePreferenceFragmentCompat.kt @@ -61,11 +61,7 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() { pref.isIconSpaceReserved = false if (pref is DialogPreference) { pref.dialogTitle = pref.title - //println("pref.dialogTitle: ${pref.dialogTitle}") //TODO: could be useful for dub/sub selection } - /*for (entry in sharedPreferences.all.entries) { - Log.d("Preferences", "Key: ${entry.key}, Value: ${entry.value}") - }*/ // Apply incognito IME for EditTextPreference if (pref is EditTextPreference) { diff --git a/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt b/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt index 7c17221f..43b17abc 100644 --- a/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt +++ b/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt @@ -159,6 +159,7 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files FirstComment(Pref(Location.Irrelevant, Boolean::class, true)), CommentAuthResponse(Pref(Location.Irrelevant, AuthResponse::class, "")), CommentTokenExpiry(Pref(Location.Irrelevant, Long::class, 0L)), + LogToFile(Pref(Location.Irrelevant, Boolean::class, false)), //Protected DiscordToken(Pref(Location.Protected, String::class, "")), diff --git a/app/src/main/java/ani/dantotsu/subcriptions/AlarmReceiver.kt b/app/src/main/java/ani/dantotsu/subcriptions/AlarmReceiver.kt index c1c17e1f..c9c59c09 100644 --- a/app/src/main/java/ani/dantotsu/subcriptions/AlarmReceiver.kt +++ b/app/src/main/java/ani/dantotsu/subcriptions/AlarmReceiver.kt @@ -7,7 +7,7 @@ import android.content.Context import android.content.Intent import ani.dantotsu.currContext import ani.dantotsu.isOnline -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.subcriptions.Subscription.Companion.defaultTime @@ -22,7 +22,7 @@ class AlarmReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { when (intent?.action) { Intent.ACTION_BOOT_COMPLETED -> tryWith(true) { - logger("Starting Dantotsu Subscription Service on Boot") + Logger.log("Starting Dantotsu Subscription Service on Boot") context?.startSubscription() } } diff --git a/app/src/main/java/ani/dantotsu/subcriptions/Subscription.kt b/app/src/main/java/ani/dantotsu/subcriptions/Subscription.kt index 050953ce..fb4e529d 100644 --- a/app/src/main/java/ani/dantotsu/subcriptions/Subscription.kt +++ b/app/src/main/java/ani/dantotsu/subcriptions/Subscription.kt @@ -10,6 +10,7 @@ import ani.dantotsu.parsers.Episode import ani.dantotsu.parsers.MangaChapter import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName +import ani.dantotsu.util.Logger import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay @@ -27,7 +28,7 @@ class Subscription { alreadyStarted = true SubscriptionWorker.enqueue(this) AlarmReceiver.alarm(this) - } else logger("Already Subscribed") + } else Logger.log("Already Subscribed") } private var currentlyPerforming = false diff --git a/app/src/main/java/ani/dantotsu/util/Logger.kt b/app/src/main/java/ani/dantotsu/util/Logger.kt new file mode 100644 index 00000000..a8dfb631 --- /dev/null +++ b/app/src/main/java/ani/dantotsu/util/Logger.kt @@ -0,0 +1,146 @@ +package ani.dantotsu.util + +import android.content.Context +import android.content.Intent +import androidx.core.content.FileProvider +import ani.dantotsu.BuildConfig +import ani.dantotsu.connections.crashlytics.CrashlyticsInterface +import ani.dantotsu.settings.saving.PrefManager +import ani.dantotsu.settings.saving.PrefName +import ani.dantotsu.snackString +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import java.io.File +import java.util.Date +import java.util.concurrent.Executors + +object Logger { + var file: File? = null + private val loggerExecutor = Executors.newSingleThreadExecutor() + + fun init(context: Context) { + try { + if (!PrefManager.getVal(PrefName.LogToFile) || file != null) return + file = File(context.getExternalFilesDir(null), "log.txt") + if (file?.exists() == true) { + val oldFile = File(context.getExternalFilesDir(null), "old_log.txt") + file?.copyTo(oldFile, true) + } else { + file?.createNewFile() + } + file?.writeText("log started\n") + file?.appendText("date/time: ${Date()}\n") + file?.appendText("device: ${android.os.Build.MODEL}\n") + file?.appendText("os version: ${android.os.Build.VERSION.RELEASE}\n") + file?.appendText( + "app version: ${ + context.packageManager.getPackageInfo( + context.packageName, + 0 + ).versionName + }\n" + ) + file?.appendText( + "app version code: ${ + context.packageManager.getPackageInfo( + context.packageName, + 0 + ).versionCode + }\n" + ) + file?.appendText("sdk version: ${android.os.Build.VERSION.SDK_INT}\n") + file?.appendText("manufacturer: ${android.os.Build.MANUFACTURER}\n") + file?.appendText("brand: ${android.os.Build.BRAND}\n") + file?.appendText("product: ${android.os.Build.PRODUCT}\n") + file?.appendText("device: ${android.os.Build.DEVICE}\n") + file?.appendText("hardware: ${android.os.Build.HARDWARE}\n") + file?.appendText("host: ${android.os.Build.HOST}\n") + file?.appendText("id: ${android.os.Build.ID}\n") + file?.appendText("type: ${android.os.Build.TYPE}\n") + file?.appendText("user: ${android.os.Build.USER}\n") + file?.appendText("tags: ${android.os.Build.TAGS}\n") + file?.appendText("time: ${android.os.Build.TIME}\n") + file?.appendText("radio: ${android.os.Build.RADIO}\n") + file?.appendText("bootloader: ${android.os.Build.BOOTLOADER}\n") + file?.appendText("board: ${android.os.Build.BOARD}\n") + file?.appendText("fingerprint: ${android.os.Build.FINGERPRINT}\n") + file?.appendText("supported_abis: ${android.os.Build.SUPPORTED_ABIS.joinToString()}\n") + file?.appendText("supported_32_bit_abis: ${android.os.Build.SUPPORTED_32_BIT_ABIS.joinToString()}\n") + file?.appendText("supported_64_bit_abis: ${android.os.Build.SUPPORTED_64_BIT_ABIS.joinToString()}\n") + file?.appendText("is emulator: ${android.os.Build.FINGERPRINT.contains("generic")}\n") + file?.appendText("--------------------------------\n") + } catch (e: Exception) { + Injekt.get().logException(e) + file = null + } + } + + fun log(message: String) { + val trace = Thread.currentThread().stackTrace[3] + loggerExecutor.execute { + if (file == null) println(message) + else { + val className = trace.className + val methodName = trace.methodName + val lineNumber = trace.lineNumber + file?.appendText("date/time: ${Date()} | $className.$methodName($lineNumber)\n") + file?.appendText("message: $message\n-\n") + } + } + } + + fun log(e: Exception) { + loggerExecutor.execute { + if (file == null) e.printStackTrace() else { + file?.appendText("---------------------------Exception---------------------------\n") + file?.appendText("date/time: ${Date()} | ${e.message}\n") + file?.appendText("trace: ${e.stackTrace}\n") + } + } + } + + fun log(e: Throwable) { + loggerExecutor.execute { + if (file == null) e.printStackTrace() else { + file?.appendText("---------------------------Exception---------------------------\n") + file?.appendText("date/time: ${Date()} | ${e.message}\n") + file?.appendText("trace: ${e.stackTrace}\n") + } + } + } + + fun shareLog(context: Context) { + if (file == null) { + snackString("No log file found") + return + } + val oldFile = File(context.getExternalFilesDir(null), "old_log.txt") + val fileToUse = if (oldFile.exists()) { + file?.readText()?.let { oldFile.appendText(it) } + oldFile + } else { + file + } + val shareIntent = Intent(Intent.ACTION_SEND) + shareIntent.type = "text/plain" + shareIntent.putExtra( + Intent.EXTRA_STREAM, + FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.provider", fileToUse!!) + ) + shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Log file") + shareIntent.putExtra(Intent.EXTRA_TEXT, "Log file") + shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + context.startActivity(Intent.createChooser(shareIntent, "Share log file")) + } +} + +class FinalExceptionHandler : Thread.UncaughtExceptionHandler { + private val defaultUEH: Thread.UncaughtExceptionHandler? = + Thread.getDefaultUncaughtExceptionHandler() + + override fun uncaughtException(t: Thread, e: Throwable) { + Logger.log(e) + Injekt.get().logException(e) + defaultUEH?.uncaughtException(t, e) + } +} \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsFactory.kt b/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsFactory.kt index 3fd890bb..75f35588 100644 --- a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsFactory.kt +++ b/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsFactory.kt @@ -7,7 +7,7 @@ import android.graphics.BitmapFactory import android.widget.RemoteViews import android.widget.RemoteViewsService import ani.dantotsu.R -import ani.dantotsu.logger +import ani.dantotsu.util.Logger import java.io.InputStream import java.net.HttpURLConnection import java.net.URL @@ -19,7 +19,7 @@ class CurrentlyAiringRemoteViewsFactory(private val context: Context, intent: In override fun onCreate() { // 4 items for testing widgetItems.clear() - logger("CurrentlyAiringRemoteViewsFactory onCreate") + Logger.log("CurrentlyAiringRemoteViewsFactory onCreate") widgetItems = List(4) { WidgetItem( "Show $it", @@ -31,7 +31,7 @@ class CurrentlyAiringRemoteViewsFactory(private val context: Context, intent: In override fun onDataSetChanged() { // 4 items for testing - logger("CurrentlyAiringRemoteViewsFactory onDataSetChanged") + Logger.log("CurrentlyAiringRemoteViewsFactory onDataSetChanged") widgetItems.clear() widgetItems.add( WidgetItem( @@ -79,7 +79,7 @@ class CurrentlyAiringRemoteViewsFactory(private val context: Context, intent: In } override fun getViewAt(position: Int): RemoteViews { - logger("CurrentlyAiringRemoteViewsFactory getViewAt") + Logger.log("CurrentlyAiringRemoteViewsFactory getViewAt") val item = widgetItems[position] val rv = RemoteViews(context.packageName, R.layout.item_currently_airing_widget).apply { setTextViewText(R.id.text_show_title, item.title) diff --git a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsService.kt b/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsService.kt index 9770ff86..a0ff2efc 100644 --- a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsService.kt +++ b/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsService.kt @@ -2,11 +2,11 @@ package ani.dantotsu.widgets import android.content.Intent import android.widget.RemoteViewsService -import ani.dantotsu.logger +import ani.dantotsu.util.Logger class CurrentlyAiringRemoteViewsService : RemoteViewsService() { override fun onGetViewFactory(intent: Intent): RemoteViewsFactory { - logger("CurrentlyAiringRemoteViewsFactory onGetViewFactory") + Logger.log("CurrentlyAiringRemoteViewsFactory onGetViewFactory") return CurrentlyAiringRemoteViewsFactory(applicationContext, intent) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/AnimeExtensionManager.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/AnimeExtensionManager.kt index 82588463..198f557c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/AnimeExtensionManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/AnimeExtensionManager.kt @@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.extension.anime import android.content.Context import android.graphics.drawable.Drawable import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.extension.anime.api.AnimeExtensionGithubApi @@ -16,11 +17,9 @@ import eu.kanade.tachiyomi.util.preference.plusAssign import kotlinx.coroutines.async import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow -import logcat.LogPriority import rx.Observable import tachiyomi.core.util.lang.launchNow import tachiyomi.core.util.lang.withUIContext -import tachiyomi.core.util.system.logcat import tachiyomi.domain.source.anime.model.AnimeSourceData import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -120,7 +119,7 @@ class AnimeExtensionManager( val extensions: List = try { api.findExtensions() } catch (e: Exception) { - logcat(LogPriority.ERROR, e) + Logger.log(e) withUIContext { snackString("Failed to get extensions list") } emptyList() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/api/AnimeExtensionGithubApi.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/api/AnimeExtensionGithubApi.kt index a927373d..e71c6422 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/api/AnimeExtensionGithubApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/api/AnimeExtensionGithubApi.kt @@ -1,6 +1,7 @@ package eu.kanade.tachiyomi.extension.anime.api import android.content.Context +import ani.dantotsu.util.Logger import eu.kanade.tachiyomi.extension.ExtensionUpdateNotifier import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension @@ -13,11 +14,9 @@ import eu.kanade.tachiyomi.network.awaitSuccess import eu.kanade.tachiyomi.network.parseAs import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json -import logcat.LogPriority import tachiyomi.core.preference.Preference import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.util.lang.withIOContext -import tachiyomi.core.util.system.logcat import uy.kohesive.injekt.injectLazy import java.util.Date import kotlin.time.Duration.Companion.days @@ -45,7 +44,7 @@ internal class AnimeExtensionGithubApi { .newCall(GET("${REPO_URL_PREFIX}index.min.json")) .awaitSuccess() } catch (e: Throwable) { - logcat(LogPriority.ERROR, e) { "Failed to get extensions from GitHub" } + Logger.log("Failed to get extensions from GitHub") requiresFallbackSource = true null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/installer/PackageInstallerInstallerAnime.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/installer/PackageInstallerInstallerAnime.kt index ffa12c70..baa7411e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/installer/PackageInstallerInstallerAnime.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/installer/PackageInstallerInstallerAnime.kt @@ -10,12 +10,11 @@ import android.content.pm.PackageInstaller import android.os.Build import androidx.core.content.ContextCompat import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.util.lang.use import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat import eu.kanade.tachiyomi.util.system.getUriSize -import logcat.LogPriority -import tachiyomi.core.util.system.logcat class PackageInstallerInstallerAnime(private val service: Service) : InstallerAnime(service) { @@ -30,7 +29,7 @@ class PackageInstallerInstallerAnime(private val service: Service) : InstallerAn PackageInstaller.STATUS_PENDING_USER_ACTION -> { val userAction = intent.getParcelableExtraCompat(Intent.EXTRA_INTENT) if (userAction == null) { - logcat(LogPriority.ERROR) { "Fatal error for $intent" } + Logger.log("Fatal error for $intent") continueQueue(InstallStep.Error) return } @@ -89,11 +88,8 @@ class PackageInstallerInstallerAnime(private val service: Service) : InstallerAn session.commit(intentSender) } } catch (e: Exception) { - logcat( - LogPriority.ERROR, - e - ) { "Failed to install extension ${entry.downloadId} ${entry.uri}" } - logcat(LogPriority.ERROR) { "Exception: $e" } + Logger.log(e) + Logger.log("Failed to install extension ${entry.downloadId} ${entry.uri}") snackString("Failed to install extension ${entry.downloadId} ${entry.uri}") activeSession?.let { (_, sessionId) -> packageInstaller.abandonSession(sessionId) diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallReceiver.kt index 0dd3302d..9ccc0f7b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallReceiver.kt @@ -5,15 +5,14 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import androidx.core.content.ContextCompat +import ani.dantotsu.util.Logger import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension import eu.kanade.tachiyomi.extension.anime.model.AnimeLoadResult import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async -import logcat.LogPriority import tachiyomi.core.util.lang.launchNow -import tachiyomi.core.util.system.logcat /** * Broadcast receiver that listens for the system's packages installed, updated or removed, and only @@ -103,7 +102,7 @@ internal class AnimeExtensionInstallReceiver(private val listener: Listener) : private suspend fun getExtensionFromIntent(context: Context, intent: Intent?): AnimeLoadResult { val pkgName = getPackageNameFromIntent(intent) if (pkgName == null) { - logcat(LogPriority.WARN) { "Package name not found" } + Logger.log("Package name not found") return AnimeLoadResult.Error } return GlobalScope.async(Dispatchers.Default, CoroutineStart.DEFAULT) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallService.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallService.kt index 87e6ab6a..7dd3fc80 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstallService.kt @@ -8,6 +8,7 @@ import android.net.Uri import android.os.Build import android.os.IBinder import ani.dantotsu.R +import ani.dantotsu.util.Logger import eu.kanade.domain.base.BasePreferences import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.extension.anime.installer.InstallerAnime @@ -15,8 +16,6 @@ import eu.kanade.tachiyomi.extension.anime.installer.PackageInstallerInstallerAn import eu.kanade.tachiyomi.extension.anime.util.AnimeExtensionInstaller.Companion.EXTRA_DOWNLOAD_ID import eu.kanade.tachiyomi.util.system.getSerializableExtraCompat import eu.kanade.tachiyomi.util.system.notificationBuilder -import logcat.LogPriority -import tachiyomi.core.util.system.logcat class AnimeExtensionInstallService : Service() { @@ -60,7 +59,7 @@ class AnimeExtensionInstallService : Service() { ) else -> { - logcat(LogPriority.ERROR) { "Not implemented for installer $installerUsed" } + Logger.log("Not implemented for installer $installerUsed") stopSelf() return START_NOT_STICKY } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstaller.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstaller.kt index 41bfdd9b..70f7da53 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstaller.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionInstaller.kt @@ -10,16 +10,15 @@ import android.os.Environment import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import androidx.core.net.toUri +import ani.dantotsu.util.Logger import com.jakewharton.rxrelay.PublishRelay import eu.kanade.domain.base.BasePreferences import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.extension.anime.installer.InstallerAnime import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension import eu.kanade.tachiyomi.util.storage.getUriCompat -import logcat.LogPriority import rx.Observable import rx.android.schedulers.AndroidSchedulers -import tachiyomi.core.util.system.logcat import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.File @@ -248,7 +247,7 @@ internal class AnimeExtensionInstaller(private val context: Context) { // Set next installation step if (uri == null) { - logcat(LogPriority.ERROR) { "Couldn't locate downloaded APK" } + Logger.log("Couldn't locate downloaded APK") downloadsRelay.call(id to InstallStep.Error) return } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionLoader.kt index cce7b7e9..2ce2aaf7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/anime/util/AnimeExtensionLoader.kt @@ -6,6 +6,7 @@ import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.os.Build import androidx.core.content.pm.PackageInfoCompat +import ani.dantotsu.util.Logger import dalvik.system.PathClassLoader import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource @@ -17,8 +18,6 @@ import eu.kanade.tachiyomi.util.lang.Hash import eu.kanade.tachiyomi.util.system.getApplicationIcon import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking -import logcat.LogPriority -import tachiyomi.core.util.system.logcat import uy.kohesive.injekt.injectLazy /** @@ -91,11 +90,11 @@ internal object AnimeExtensionLoader { context.packageManager.getPackageInfo(pkgName, PACKAGE_FLAGS) } catch (error: PackageManager.NameNotFoundException) { // Unlikely, but the package may have been uninstalled at this point - logcat(LogPriority.ERROR, error) + Logger.log(error) return AnimeLoadResult.Error } if (!isPackageAnExtension(pkgInfo)) { - logcat(LogPriority.WARN) { "Tried to load a package that wasn't a extension ($pkgName)" } + Logger.log("Tried to load a package that wasn't a extension ($pkgName)") return AnimeLoadResult.Error } return loadExtension(context, pkgName, pkgInfo) @@ -119,7 +118,7 @@ internal object AnimeExtensionLoader { pkgManager.getApplicationInfo(pkgName, PackageManager.GET_META_DATA) } catch (error: PackageManager.NameNotFoundException) { // Unlikely, but the package may have been uninstalled at this point - logcat(LogPriority.ERROR, error) + Logger.log(error) return AnimeLoadResult.Error } @@ -128,24 +127,23 @@ internal object AnimeExtensionLoader { val versionCode = PackageInfoCompat.getLongVersionCode(pkgInfo) if (versionName.isNullOrEmpty()) { - logcat(LogPriority.WARN) { "Missing versionName for extension $extName" } + Logger.log("Missing versionName for extension $extName") return AnimeLoadResult.Error } // Validate lib version val libVersion = versionName.substringBeforeLast('.').toDoubleOrNull() if (libVersion == null || libVersion < LIB_VERSION_MIN || libVersion > LIB_VERSION_MAX) { - logcat(LogPriority.WARN) { - "Lib version is $libVersion, while only versions " + + Logger.log("Lib version is $libVersion, while only versions " + "$LIB_VERSION_MIN to $LIB_VERSION_MAX are allowed" - } + ) return AnimeLoadResult.Error } val signatureHash = getSignatureHash(pkgInfo) if (signatureHash == null) { - logcat(LogPriority.WARN) { "Package $pkgName isn't signed" } + Logger.log("Package $pkgName isn't signed") return AnimeLoadResult.Error } else if (signatureHash !in trustedSignatures) { val extension = AnimeExtension.Untrusted( @@ -156,13 +154,13 @@ internal object AnimeExtensionLoader { libVersion, signatureHash ) - logcat(LogPriority.WARN, message = { "Extension $pkgName isn't trusted" }) + Logger.log("Extension $pkgName isn't trusted") return AnimeLoadResult.Untrusted(extension) } val isNsfw = appInfo.metaData.getInt(METADATA_NSFW) == 1 if (!loadNsfwSource && isNsfw) { - logcat(LogPriority.WARN) { "NSFW extension $pkgName not allowed" } + Logger.log("NSFW extension $pkgName not allowed") return AnimeLoadResult.Error } @@ -189,7 +187,7 @@ internal object AnimeExtensionLoader { else -> throw Exception("Unknown source class type! ${obj.javaClass}") } } catch (e: Throwable) { - logcat(LogPriority.ERROR, e) { "Extension load error: $extName ($it)" } + Logger.log("Extension load error: $extName ($it)") return AnimeLoadResult.Error } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/MangaExtensionManager.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/MangaExtensionManager.kt index fe098455..f581f4e1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/MangaExtensionManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/MangaExtensionManager.kt @@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.extension.manga import android.content.Context import android.graphics.drawable.Drawable import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.extension.manga.api.MangaExtensionGithubApi @@ -16,11 +17,9 @@ import eu.kanade.tachiyomi.util.preference.plusAssign import kotlinx.coroutines.async import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow -import logcat.LogPriority import rx.Observable import tachiyomi.core.util.lang.launchNow import tachiyomi.core.util.lang.withUIContext -import tachiyomi.core.util.system.logcat import tachiyomi.domain.source.manga.model.MangaSourceData import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -117,7 +116,7 @@ class MangaExtensionManager( val extensions: List = try { api.findExtensions() } catch (e: Exception) { - logcat(LogPriority.ERROR, e) + Logger.log(e) withUIContext { snackString("Failed to get manga extensions") } emptyList() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/api/MangaExtensionGithubApi.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/api/MangaExtensionGithubApi.kt index ad21741f..a5fdbc5a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/api/MangaExtensionGithubApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/api/MangaExtensionGithubApi.kt @@ -1,6 +1,7 @@ package eu.kanade.tachiyomi.extension.manga.api import android.content.Context +import ani.dantotsu.util.Logger import eu.kanade.tachiyomi.extension.ExtensionUpdateNotifier import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager import eu.kanade.tachiyomi.extension.manga.model.AvailableMangaSources @@ -13,11 +14,9 @@ import eu.kanade.tachiyomi.network.awaitSuccess import eu.kanade.tachiyomi.network.parseAs import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json -import logcat.LogPriority import tachiyomi.core.preference.Preference import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.util.lang.withIOContext -import tachiyomi.core.util.system.logcat import uy.kohesive.injekt.injectLazy import java.util.Date import kotlin.time.Duration.Companion.days @@ -45,7 +44,7 @@ internal class MangaExtensionGithubApi { .newCall(GET("${REPO_URL_PREFIX}index.min.json")) .awaitSuccess() } catch (e: Throwable) { - logcat(LogPriority.ERROR, e) { "Failed to get extensions from GitHub" } + Logger.log("Failed to get extensions from GitHub") requiresFallbackSource = true null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/installer/PackageInstallerInstallerManga.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/installer/PackageInstallerInstallerManga.kt index 3802be8f..d8da743b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/installer/PackageInstallerInstallerManga.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/installer/PackageInstallerInstallerManga.kt @@ -10,12 +10,11 @@ import android.content.pm.PackageInstaller import android.os.Build import androidx.core.content.ContextCompat import ani.dantotsu.snackString +import ani.dantotsu.util.Logger import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.util.lang.use import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat import eu.kanade.tachiyomi.util.system.getUriSize -import logcat.LogPriority -import tachiyomi.core.util.system.logcat class PackageInstallerInstallerManga(private val service: Service) : InstallerManga(service) { @@ -30,7 +29,7 @@ class PackageInstallerInstallerManga(private val service: Service) : InstallerMa PackageInstaller.STATUS_PENDING_USER_ACTION -> { val userAction = intent.getParcelableExtraCompat(Intent.EXTRA_INTENT) if (userAction == null) { - logcat(LogPriority.ERROR) { "Fatal error for $intent" } + Logger.log("Fatal error for $intent") continueQueue(InstallStep.Error) return } @@ -89,8 +88,8 @@ class PackageInstallerInstallerManga(private val service: Service) : InstallerMa session.commit(intentSender) } } catch (e: Exception) { - logcat(LogPriority.ERROR) { "Failed to install extension ${entry.downloadId} ${entry.uri}" } - logcat(LogPriority.ERROR) { "Exception: $e" } + Logger.log("Failed to install extension ${entry.downloadId} ${entry.uri}") + Logger.log(e) snackString("Failed to install extension ${entry.downloadId} ${entry.uri}") activeSession?.let { (_, sessionId) -> packageInstaller.abandonSession(sessionId) diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallReceiver.kt index ad3c7053..4db3e42c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallReceiver.kt @@ -5,15 +5,14 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import androidx.core.content.ContextCompat +import ani.dantotsu.util.Logger import eu.kanade.tachiyomi.extension.manga.model.MangaExtension import eu.kanade.tachiyomi.extension.manga.model.MangaLoadResult import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async -import logcat.LogPriority import tachiyomi.core.util.lang.launchNow -import tachiyomi.core.util.system.logcat /** * Broadcast receiver that listens for the system's packages installed, updated or removed, and only @@ -103,7 +102,7 @@ internal class MangaExtensionInstallReceiver(private val listener: Listener) : private suspend fun getExtensionFromIntent(context: Context, intent: Intent?): MangaLoadResult { val pkgName = getPackageNameFromIntent(intent) if (pkgName == null) { - logcat(LogPriority.WARN) { "Package name not found" } + Logger.log("Package name not found") return MangaLoadResult.Error } return GlobalScope.async(Dispatchers.Default, CoroutineStart.DEFAULT) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallService.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallService.kt index f6cc24cc..c698d3dc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstallService.kt @@ -8,6 +8,7 @@ import android.net.Uri import android.os.Build import android.os.IBinder import ani.dantotsu.R +import ani.dantotsu.util.Logger import eu.kanade.domain.base.BasePreferences import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.extension.manga.installer.InstallerManga @@ -15,8 +16,6 @@ import eu.kanade.tachiyomi.extension.manga.installer.PackageInstallerInstallerMa import eu.kanade.tachiyomi.extension.manga.util.MangaExtensionInstaller.Companion.EXTRA_DOWNLOAD_ID import eu.kanade.tachiyomi.util.system.getSerializableExtraCompat import eu.kanade.tachiyomi.util.system.notificationBuilder -import logcat.LogPriority -import tachiyomi.core.util.system.logcat class MangaExtensionInstallService : Service() { @@ -60,7 +59,7 @@ class MangaExtensionInstallService : Service() { ) else -> { - logcat(LogPriority.ERROR) { "Not implemented for installer $installerUsed" } + Logger.log("Not implemented for installer $installerUsed") stopSelf() return START_NOT_STICKY } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstaller.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstaller.kt index f05db16c..53bfb599 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstaller.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionInstaller.kt @@ -10,16 +10,15 @@ import android.os.Environment import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import androidx.core.net.toUri +import ani.dantotsu.util.Logger import com.jakewharton.rxrelay.PublishRelay import eu.kanade.domain.base.BasePreferences import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.extension.manga.installer.InstallerManga import eu.kanade.tachiyomi.extension.manga.model.MangaExtension import eu.kanade.tachiyomi.util.storage.getUriCompat -import logcat.LogPriority import rx.Observable import rx.android.schedulers.AndroidSchedulers -import tachiyomi.core.util.system.logcat import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.File @@ -245,7 +244,7 @@ internal class MangaExtensionInstaller(private val context: Context) { // Set next installation step if (uri == null) { - logcat(LogPriority.ERROR) { "Couldn't locate downloaded APK" } + Logger.log("Couldn't locate downloaded APK") downloadsRelay.call(id to InstallStep.Error) return } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionLoader.kt index c76bd0bb..0fd6f987 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/manga/util/MangaExtensionLoader.kt @@ -6,6 +6,7 @@ import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.os.Build import androidx.core.content.pm.PackageInfoCompat +import ani.dantotsu.util.Logger import dalvik.system.PathClassLoader import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.tachiyomi.extension.manga.model.MangaExtension @@ -17,8 +18,6 @@ import eu.kanade.tachiyomi.util.lang.Hash import eu.kanade.tachiyomi.util.system.getApplicationIcon import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking -import logcat.LogPriority -import tachiyomi.core.util.system.logcat import uy.kohesive.injekt.injectLazy /** @@ -91,11 +90,11 @@ internal object MangaExtensionLoader { context.packageManager.getPackageInfo(pkgName, PACKAGE_FLAGS) } catch (error: PackageManager.NameNotFoundException) { // Unlikely, but the package may have been uninstalled at this point - logcat(LogPriority.ERROR, error) + Logger.log(error) return MangaLoadResult.Error } if (!isPackageAnExtension(pkgInfo)) { - logcat(LogPriority.WARN) { "Tried to load a package that wasn't a extension ($pkgName)" } + Logger.log("Tried to load a package that wasn't a extension ($pkgName)") return MangaLoadResult.Error } return loadMangaExtension(context, pkgName, pkgInfo) @@ -119,7 +118,7 @@ internal object MangaExtensionLoader { pkgManager.getApplicationInfo(pkgName, PackageManager.GET_META_DATA) } catch (error: PackageManager.NameNotFoundException) { // Unlikely, but the package may have been uninstalled at this point - logcat(LogPriority.ERROR, error) + Logger.log(error) return MangaLoadResult.Error } @@ -129,17 +128,16 @@ internal object MangaExtensionLoader { val versionCode = PackageInfoCompat.getLongVersionCode(pkgInfo) if (versionName.isNullOrEmpty()) { - logcat(LogPriority.WARN) { "Missing versionName for extension $extName" } + Logger.log("Missing versionName for extension $extName") return MangaLoadResult.Error } // Validate lib version val libVersion = versionName.substringBeforeLast('.').toDoubleOrNull() if (libVersion == null || libVersion < LIB_VERSION_MIN || libVersion > LIB_VERSION_MAX) { - logcat(LogPriority.WARN) { - "Lib version is $libVersion, while only versions " + + Logger.log("Lib version is $libVersion, while only versions " + "$LIB_VERSION_MIN to $LIB_VERSION_MAX are allowed" - } + ) return MangaLoadResult.Error } @@ -147,18 +145,18 @@ internal object MangaExtensionLoader { /* temporarily disabling signature check TODO: remove? if (signatureHash == null) { - logcat(LogPriority.WARN) { "Package $pkgName isn't signed" } + Logger.log("Package $pkgName isn't signed") return MangaLoadResult.Error } else if (signatureHash !in trustedSignatures) { val extension = MangaExtension.Untrusted(extName, pkgName, versionName, versionCode, libVersion, signatureHash) - logcat(LogPriority.WARN) { "Extension $pkgName isn't trusted" } + Logger.log("Extension $pkgName isn't trusted") return MangaLoadResult.Untrusted(extension) } */ val isNsfw = appInfo.metaData.getInt(METADATA_NSFW) == 1 if (!loadNsfwSource && isNsfw) { - logcat(LogPriority.WARN) { "NSFW extension $pkgName not allowed" } + Logger.log("NSFW extension $pkgName not allowed") return MangaLoadResult.Error } @@ -185,7 +183,7 @@ internal object MangaExtensionLoader { else -> throw Exception("Unknown source class type! ${obj.javaClass}") } } catch (e: Throwable) { - logcat(LogPriority.ERROR, e) { "Extension load error: $extName ($it)" } + Logger.log("Extension load error: $extName ($it)") return MangaLoadResult.Error } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt index d7cacb64..231443bb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt @@ -21,10 +21,9 @@ import androidx.core.graphics.blue import androidx.core.graphics.green import androidx.core.graphics.red import androidx.core.net.toUri +import ani.dantotsu.util.Logger import com.hippo.unifile.UniFile import eu.kanade.tachiyomi.util.lang.truncateCenter -import logcat.LogPriority -import tachiyomi.core.util.system.logcat import java.io.File import kotlin.math.roundToInt @@ -47,7 +46,7 @@ fun Context.copyToClipboard(label: String, content: String) { toast("Copied to clipboard: " + content.truncateCenter(50)) } } catch (e: Throwable) { - logcat(LogPriority.ERROR, e) + Logger.log(e) toast("Failed to copy to clipboard") } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt index 57950eda..95a38aee 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/DeviceUtil.kt @@ -2,8 +2,7 @@ package eu.kanade.tachiyomi.util.system import android.annotation.SuppressLint import android.os.Build -import logcat.LogPriority -import tachiyomi.core.util.system.logcat +import ani.dantotsu.util.Logger object DeviceUtil { @@ -72,7 +71,7 @@ object DeviceUtil { .getDeclaredMethod("get", String::class.java) .invoke(null, key) as String } catch (e: Exception) { - logcat(LogPriority.WARN, e) { "Unable to use SystemProperties.get()" } + Logger.log("Unable to use SystemProperties.get()") null } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt index beef906d..88158ecd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt @@ -6,8 +6,7 @@ import android.content.pm.PackageManager import android.webkit.CookieManager import android.webkit.WebSettings import android.webkit.WebView -import logcat.LogPriority -import tachiyomi.core.util.system.logcat +import ani.dantotsu.util.Logger object WebViewUtil { const val SPOOF_PACKAGE_NAME = "org.chromium.chrome" @@ -20,7 +19,7 @@ object WebViewUtil { // is not installed CookieManager.getInstance() } catch (e: Throwable) { - logcat(LogPriority.ERROR, e) + Logger.log(e) return false } diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 69130dbf..4b83127e 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -989,6 +989,52 @@ app:showText="false" app:thumbTint="@color/button_switch_track" /> + + + + + + + + + + + + + + + Log to File + Logging to a file will slow down the app. Only enable if you are experiencing issues.