From 6e20c152a9c1f8387567fe301712c12bcf0f9a35 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 15 Dec 2024 16:39:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=97=A5=E5=BF=97=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 7 +- app/src/main/AndroidManifest.xml | 11 +- .../github/zerorooot/nap511/MainActivity.kt | 25 +-- .../nap511/activity/OfflineTaskActivity.kt | 4 - .../nap511/screen/AllWebViewScreen.kt | 4 +- .../zerorooot/nap511/screen/AppTopBar.kt | 24 +++ .../zerorooot/nap511/screen/DropdownMenu.kt | 7 +- .../zerorooot/nap511/screen/LogScreen.kt | 174 ++++++++++++++++++ .../java/github/zerorooot/nap511/util/App.kt | 31 ++++ .../zerorooot/nap511/util/ConfigKeyUtil.kt | 5 + app/src/main/res/drawable/baseline_log_24.xml | 5 + app/src/main/res/values/strings.xml | 6 + 12 files changed, 282 insertions(+), 21 deletions(-) create mode 100644 app/src/main/java/github/zerorooot/nap511/screen/LogScreen.kt create mode 100644 app/src/main/res/drawable/baseline_log_24.xml diff --git a/app/build.gradle b/app/build.gradle index e668677..c5a46ff 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -51,11 +51,12 @@ android { } dependencies { + //log + implementation 'com.elvishew:xlog:1.11.1' + implementation 'com.github.nanihadesuka:LazyColumnScrollbar:2.2.0' //restart app implementation 'com.jakewharton:process-phoenix:3.0.0' -// implementation 'org.java-websocket:Java-WebSocket:1.5.6' -// implementation 'com.pusher:pusher-java-client:0.3.1' //setting screen // implementation "com.github.JamalMulla:ComposePrefs3:1.0.3" implementation "com.github.JamalMulla:ComposePrefs:1.0.6" @@ -107,7 +108,7 @@ dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version") // LiveData implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version") - + implementation 'androidx.work:work-runtime-ktx:2.10.0' implementation 'androidx.core:core-ktx:1.15.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d111f5b..6f80c0c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,11 @@ + + + @@ -14,6 +19,7 @@ android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:requestLegacyExternalStorage="true" android:supportsRtl="true" android:theme="@style/Theme.Nap511" android:usesCleartextTraffic="true" @@ -26,11 +32,12 @@ tools:ignore="AppLinkUrlError"> + - + @@ -48,6 +55,7 @@ tools:ignore="AppLinkUrlError"> + @@ -61,6 +69,7 @@ https://github.com/LibreOffice/online/blob/d0edfeabbdc969a9a66cf90976a63c2f4403a6d3/android/app/src/main/AndroidManifest.xml#L119-L129 --> + diff --git a/app/src/main/java/github/zerorooot/nap511/MainActivity.kt b/app/src/main/java/github/zerorooot/nap511/MainActivity.kt index 98fcd62..e40a4a1 100644 --- a/app/src/main/java/github/zerorooot/nap511/MainActivity.kt +++ b/app/src/main/java/github/zerorooot/nap511/MainActivity.kt @@ -6,7 +6,6 @@ import android.content.ClipData import android.content.ClipboardManager import android.content.Intent import android.os.Bundle -import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.BackHandler import androidx.activity.compose.setContent @@ -54,6 +53,7 @@ import androidx.work.WorkQuery import coil.compose.rememberAsyncImagePainter import coil.request.CachePolicy import coil.request.ImageRequest +import com.elvishew.xlog.XLog import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.gson.Gson import com.google.gson.reflect.TypeToken @@ -66,6 +66,7 @@ import github.zerorooot.nap511.screen.CaptchaWebViewScreen import github.zerorooot.nap511.screen.CookieDialog import github.zerorooot.nap511.screen.ExitApp import github.zerorooot.nap511.screen.FileScreen +import github.zerorooot.nap511.screen.LogScreen import github.zerorooot.nap511.screen.LoginWebViewScreen import github.zerorooot.nap511.screen.MyPhotoScreen import github.zerorooot.nap511.screen.OfflineDownloadScreen @@ -165,10 +166,12 @@ class MainActivity : ComponentActivity() { if (intent.action == "check") { App.selectedItem = ConfigKeyUtil.VERIFY_MAGNET_LINK_ACCOUNT intent.action = "" + XLog.d("handleIntent check $intent") } //跳转到默认下载目录 if (intent.action == "jump") { - viewModels().value.getFiles( + val fileViewModel: FileViewModel by viewModels() + fileViewModel.getFiles( DataStoreUtil.getData( ConfigKeyUtil.DEFAULT_OFFLINE_CID, "0" @@ -176,13 +179,16 @@ class MainActivity : ComponentActivity() { ) //清除action,不然会一直跳转到默认下载目录 intent.action = "" + XLog.d("handleIntent jump $intent $fileViewModel ${fileViewModel.remainingSpace}") } if (intent.action == "copy") { val clipboard = ContextCompat.getSystemService(this, ClipboardManager::class.java) val clip = ClipData.newPlainText("label", intent.getStringExtra("link")) clipboard?.setPrimaryClip(clip) intent.action = "" + XLog.d("handleIntent copy $intent") } + } /** @@ -204,10 +210,6 @@ class MainActivity : ComponentActivity() { val workInfos: List = WorkManager.getInstance(applicationContext).getWorkInfos(workQuery).get() val size = workInfos.size - Log.d( - "nap511 main activity", - "checkOfflineTask workManager size $size workInfos $workInfos" - ) if (size != 0) { return } @@ -217,15 +219,13 @@ class MainActivity : ComponentActivity() { .filter { i -> i != "" && i != " " } .toSet() .toMutableList() - Log.d( - "nap511 main activity", - "checkOfflineTask currentOfflineTask size ${currentOfflineTask.size}" - ) - //currentOfflineTask等于0,证明没有离线链接缓存 if (currentOfflineTask.isEmpty()) { return } + XLog.d( + "checkOfflineTask workManager workInfos $workInfos currentOfflineTask size ${currentOfflineTask.size}" + ) //添加离线链接 val listType = object : TypeToken?>() {}.type val list = Gson().toJson(currentOfflineTask, listType) @@ -259,6 +259,7 @@ class MainActivity : ComponentActivity() { // R.drawable.baseline_web_24 to "ConfigUtil.WEB", R.drawable.ic_baseline_delete_24 to ConfigKeyUtil.RECYCLE_BIN, R.drawable.baseline_settings_24 to ConfigKeyUtil.ADVANCED_SETTINGS, + R.drawable.baseline_log_24 to ConfigKeyUtil.LOG_SCREEN, R.drawable.android_exit to ConfigKeyUtil.EXIT_APPLICATION ) ModalNavigationDrawer(gesturesEnabled = App.gesturesEnabled, @@ -314,7 +315,9 @@ class MainActivity : ComponentActivity() { CaptchaVideoWebViewScreen() } + ConfigKeyUtil.LOG_SCREEN -> LogScreen() ConfigKeyUtil.EXIT_APPLICATION -> ExitApp() + ConfigKeyUtil.PHOTO -> { MyPhotoScreen(fileViewModel) } diff --git a/app/src/main/java/github/zerorooot/nap511/activity/OfflineTaskActivity.kt b/app/src/main/java/github/zerorooot/nap511/activity/OfflineTaskActivity.kt index d77986f..672c23f 100644 --- a/app/src/main/java/github/zerorooot/nap511/activity/OfflineTaskActivity.kt +++ b/app/src/main/java/github/zerorooot/nap511/activity/OfflineTaskActivity.kt @@ -9,7 +9,6 @@ import android.content.Context import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity -import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat @@ -25,17 +24,14 @@ import github.zerorooot.nap511.MainActivity import github.zerorooot.nap511.R import github.zerorooot.nap511.bean.BaseReturnMessage import github.zerorooot.nap511.bean.SignBean -import github.zerorooot.nap511.factory.CookieViewModelFactory import github.zerorooot.nap511.util.App import github.zerorooot.nap511.util.ConfigKeyUtil import github.zerorooot.nap511.util.DataStoreUtil -import github.zerorooot.nap511.viewmodel.OfflineFileViewModel import okhttp3.FormBody import okhttp3.OkHttpClient import okhttp3.Request import java.util.StringJoiner import java.util.concurrent.TimeUnit -import kotlin.getValue class OfflineTaskActivity : ComponentActivity() { diff --git a/app/src/main/java/github/zerorooot/nap511/screen/AllWebViewScreen.kt b/app/src/main/java/github/zerorooot/nap511/screen/AllWebViewScreen.kt index 80a92fe..27f0b1c 100644 --- a/app/src/main/java/github/zerorooot/nap511/screen/AllWebViewScreen.kt +++ b/app/src/main/java/github/zerorooot/nap511/screen/AllWebViewScreen.kt @@ -25,6 +25,7 @@ import androidx.work.OneTimeWorkRequest import androidx.work.WorkManager import com.acsbendi.requestinspectorwebview.RequestInspectorWebViewClient import com.acsbendi.requestinspectorwebview.WebViewRequest +import com.elvishew.xlog.XLog import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.jakewharton.processphoenix.ProcessPhoenix @@ -163,11 +164,12 @@ fun loginWebViewClient(webView: WebView): WebViewClient { if (url.startsWith("https://webapi.115.com/label/list") || url.startsWith("https://115.com/?cid=0&offset=0&mode=wangpan")) { val message = "登录失败~,请重试" val cookie = webViewRequest.headers["cookie"] + XLog.d("loginWebViewClient $cookie") if (cookie == null) { App.instance.toast(message) return super.shouldInterceptRequest(view, webViewRequest) } - println(cookie) + //USERSESSIONID=xx; UID=xx; CID=xx; SEID=xx; PHPSESSID=xx; acw_tc=xx; UID=xx; CID=xx; SEID=xx val uidRegex = Regex("UID=\\w+") val cidRegex = Regex("CID=\\w+") diff --git a/app/src/main/java/github/zerorooot/nap511/screen/AppTopBar.kt b/app/src/main/java/github/zerorooot/nap511/screen/AppTopBar.kt index fc47c40..af19d76 100644 --- a/app/src/main/java/github/zerorooot/nap511/screen/AppTopBar.kt +++ b/app/src/main/java/github/zerorooot/nap511/screen/AppTopBar.kt @@ -132,6 +132,30 @@ fun AppTopBarOfflineFile(title: String, onClick: (name: String) -> Unit) { } ) } +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AppTopBarLogScreen(title: String, onClick: (name: String) -> Unit) { +// val contextForToast = LocalContext.current.applicationContext + TopAppBar( + title = { + Text(text = title) + }, + colors = TopAppBarDefaults.topAppBarColors(containerColor = Purple80), + navigationIcon = { + TopAppBarActionButton( + imageVector = Icons.Rounded.Menu, + description = "navigationIcon" + ) { + onClick.invoke("ModalNavigationDrawerMenu") + } + }, + actions = { + LogScreenTopBarDropdownMenu(onClick = { itemValue, _ -> + onClick.invoke(itemValue) + }) + } + ) +} @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/github/zerorooot/nap511/screen/DropdownMenu.kt b/app/src/main/java/github/zerorooot/nap511/screen/DropdownMenu.kt index fea1094..4ca283b 100644 --- a/app/src/main/java/github/zerorooot/nap511/screen/DropdownMenu.kt +++ b/app/src/main/java/github/zerorooot/nap511/screen/DropdownMenu.kt @@ -112,7 +112,12 @@ fun OfflineFileAppTopBarDropdownMenu(onClick: (String, Int) -> Unit) { val listOf = stringArrayResource(id = R.array.offlineFileAppBarMenu).toList() BaseAppTorBarMenu(listOf = listOf, onClick = onClick) } - +@Composable +fun LogScreenTopBarDropdownMenu(onClick: (String, Int) -> Unit) { + val listOf = stringArrayResource(id = R.array.logScreenAppBarMenu).toList() +// val listOf = listOf("滚动顶部", "滚动底部", "清空日志","导出日志") + BaseAppTorBarMenu(listOf = listOf, onClick = onClick) +} @Composable fun RecycleAppTopBarDropdownMenu(onClick: (String, Int) -> Unit) { val listOf = listOf("清空所有文件") diff --git a/app/src/main/java/github/zerorooot/nap511/screen/LogScreen.kt b/app/src/main/java/github/zerorooot/nap511/screen/LogScreen.kt new file mode 100644 index 0000000..4da2389 --- /dev/null +++ b/app/src/main/java/github/zerorooot/nap511/screen/LogScreen.kt @@ -0,0 +1,174 @@ +package github.zerorooot.nap511.screen + +import android.app.Application +import android.content.ContentValues +import android.os.Build +import android.os.Environment +import android.provider.MediaStore +import androidx.compose.foundation.horizontalScroll +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.pullrefresh.PullRefreshIndicator +import androidx.compose.material.pullrefresh.pullRefresh +import androidx.compose.material.pullrefresh.rememberPullRefreshState +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.elvishew.xlog.XLog +import github.zerorooot.nap511.util.App +import github.zerorooot.nap511.util.ConfigKeyUtil +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import java.io.BufferedInputStream +import java.io.ByteArrayOutputStream +import java.io.File +import java.io.FileInputStream +import java.io.IOException +import java.io.InputStream + +@OptIn(ExperimentalMaterialApi::class) +@Composable +fun LogScreen() { + var log = remember { + mutableStateOf( + try { + readInputStreamAsString( + FileInputStream( + File( + App.instance.cacheDir, + "log" + ) + ) + ) + } catch (_: Exception) { + "" + } + ) + } + + val verticalScrollState = rememberScrollState() + val horizontalScrollState = rememberScrollState() + val coroutine = rememberCoroutineScope() + val appBarOnClick = { name: String -> + when (name) { + "滚动顶部" -> { + coroutine.launch { + verticalScrollState.animateScrollTo(0) + } + } + + "滚动底部" -> { + coroutine.launch { + verticalScrollState.animateScrollTo(verticalScrollState.maxValue) + } + } + + "清空日志" -> { + File( + App.instance.cacheDir, + "log" + ).delete() + log.value = "" + } + + "导出日志" -> { + writeToPublicExternalStorage(App.instance, "log.txt", log.value) + } + + "ModalNavigationDrawerMenu" -> App.instance.openDrawerState() + else -> {} + } + } + + Column { + AppTopBarLogScreen(ConfigKeyUtil.LOG_SCREEN, appBarOnClick as (String) -> Unit) + Box( + modifier = Modifier + .fillMaxSize() + .verticalScroll(verticalScrollState) + .horizontalScroll(horizontalScrollState) + ) { + Text( + text = log.value, + style = MaterialTheme.typography.bodyLarge + ) + } + + } + + + LaunchedEffect(Unit) { + delay(10) + verticalScrollState.animateScrollTo(verticalScrollState.maxValue) + } + +} + +//private fun checkAndRequestPermissions() { +// if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { +// requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 1) +// } +//} + +fun writeToPublicExternalStorage( + applicationContext: Application, + fileName: String, + content: String +) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + // Scoped Storage for Android 10+ + val resolver = applicationContext.contentResolver + val values = ContentValues().apply { + put(MediaStore.Downloads.DISPLAY_NAME, fileName) + put(MediaStore.Downloads.MIME_TYPE, "text/plain") + put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS) + } + val uri = + resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values) + uri?.let { + resolver.openOutputStream(it)?.use { outputStream -> + outputStream.write(content.toByteArray()) + App.instance.toast("导出成功,日志文件保存至 Downloads 目录") + XLog.d("FileWrite File written to Downloads: $uri") + } + } + } else { + // Legacy method for Android 9 and below + val file = File( + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), + fileName + ) + try { + file.writeText(content) + XLog.d("FileWrite File written to: ${file.absolutePath}") + } catch (e: IOException) { + e.printStackTrace() + XLog.e("FileWrite Error writing file: $e") + } + } +} + + +fun readInputStreamAsString(`in`: InputStream): String { + val bis = BufferedInputStream(`in`) + val buf = ByteArrayOutputStream() + var result = bis.read() + while (result != -1) { + val b = result.toByte() + buf.write(b.toInt()) + result = bis.read() + } + return buf.toString() +} \ No newline at end of file diff --git a/app/src/main/java/github/zerorooot/nap511/util/App.kt b/app/src/main/java/github/zerorooot/nap511/util/App.kt index cfc18be..cf33b9e 100644 --- a/app/src/main/java/github/zerorooot/nap511/util/App.kt +++ b/app/src/main/java/github/zerorooot/nap511/util/App.kt @@ -4,16 +4,27 @@ import android.app.AppOpsManager import android.app.Application import android.content.Context import android.content.Intent +import android.os.Debug import android.os.Handler import android.os.Looper import android.util.Log import android.widget.Toast +import androidx.compose.animation.scaleOut import androidx.compose.material3.DrawerState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelStore +import com.elvishew.xlog.LogConfiguration +import com.elvishew.xlog.LogItem +import com.elvishew.xlog.XLog +import com.elvishew.xlog.flattener.ClassicFlattener +import com.elvishew.xlog.interceptor.AbstractFilterInterceptor +import com.elvishew.xlog.printer.AndroidPrinter +import com.elvishew.xlog.printer.ConsolePrinter +import com.elvishew.xlog.printer.file.FilePrinter +import com.elvishew.xlog.printer.file.clean.FileLastModifiedCleanStrategy import com.google.gson.Gson import com.google.gson.JsonObject import github.zerorooot.nap511.bean.AvatarBean @@ -24,6 +35,7 @@ import kotlinx.coroutines.launch import okhttp3.Interceptor import okhttp3.OkHttpClient import okhttp3.Request +import java.lang.Thread.UncaughtExceptionHandler import java.lang.reflect.Field import java.lang.reflect.InvocationTargetException import java.lang.reflect.Method @@ -70,6 +82,25 @@ class App : Application() { ViewModelStore(), cookieViewModelFactory )[OfflineFileViewModel::class.java] + + //log + val build = LogConfiguration.Builder().addInterceptor(object : AbstractFilterInterceptor() { + override fun reject(log: LogItem?): Boolean { + return Debug.isDebuggerConnected() + } + }).build() + val print = FilePrinter + .Builder(this.cacheDir.absolutePath) + .cleanStrategy(FileLastModifiedCleanStrategy(7 * 24 * 60 * 60 * 1000)) + .flattener(ClassicFlattener()) + .build() + XLog.init(build, ConsolePrinter(), print); + + val handler = Thread.getDefaultUncaughtExceptionHandler() + Thread.setDefaultUncaughtExceptionHandler { thread, e -> + XLog.enableStackTrace(50).e("程序崩溃退出", e) + handler?.uncaughtException(thread, e) + } } fun toast(text: String) { diff --git a/app/src/main/java/github/zerorooot/nap511/util/ConfigKeyUtil.kt b/app/src/main/java/github/zerorooot/nap511/util/ConfigKeyUtil.kt index 6af2791..20bc327 100644 --- a/app/src/main/java/github/zerorooot/nap511/util/ConfigKeyUtil.kt +++ b/app/src/main/java/github/zerorooot/nap511/util/ConfigKeyUtil.kt @@ -150,5 +150,10 @@ class ConfigKeyUtil { */ const val PHOTO = "照片模式" + /** + * 日志页面 + */ + const val LOG_SCREEN="日志页面" + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/baseline_log_24.xml b/app/src/main/res/drawable/baseline_log_24.xml new file mode 100644 index 0000000..21b2f46 --- /dev/null +++ b/app/src/main/res/drawable/baseline_log_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2d50949..9d7489a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -4,6 +4,12 @@ 文件排序 刷新文件 + + 滚动顶部 + 滚动底部 + 清空日志 + 导出日志 + 刷新文件 复制所有下载链接