From 929490a57511d35bbeb213d2fe1e69cc14d2af94 Mon Sep 17 00:00:00 2001 From: Sourabh Panchal Date: Thu, 14 Nov 2024 03:20:10 +0530 Subject: [PATCH] Feat: Save logs to accessible location for easier debugging in Android Previously, logs were saved to the /android/data/appname/ directory, which became inaccessible in Android 11 and above due to scoped storage restrictions. This update modifies the log saving mechanism to store logs in the Downloads/appname/ directory, ensuring logs are stored in an accessible location for easier retrieval and debugging. This change helps developers, especially when upgrading custom Android OS versions or upstreaming custom kernels, where network connectivity may be broken (Wi-Fi, SIM, or Bluetooth). With this update, users can now copy and share logs using alternative methods, improving troubleshooting in offline scenarios. --- app/src/main/AndroidManifest.xml | 4 ++ .../main/java/com/tortel/syslog/Result.java | 9 ++- .../tortel/syslog/dialog/RunningDialog.java | 41 ++++++++++++ .../com/tortel/syslog/utils/FileUtils.java | 62 ++++++++++++++++--- app/src/main/res/values/exception-details.xml | 4 +- 5 files changed, 109 insertions(+), 11 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4e93301..5ce53eb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,6 +23,10 @@ + + + = Build.VERSION_CODES.Q) { + // For Android 10 and above, access the 'Downloads' folder or create 'SysLogs' folder there + saveDirectory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "SysLogs"); + } else { + // For Android 9 and below, you can use external storage directories directly + saveDirectory = new File(Environment.getExternalStorageDirectory(), "SysLogs"); + } + + // Create the directory if it doesn't exist + if (!saveDirectory.exists()) { + saveDirectory.mkdirs(); + } + + // Create a new file in the save directory + File savedLogFile = new File(saveDirectory, zipFile.getName()); + + // Copy the zipFile to the save directory + FileUtils.copyFile(zipFile, savedLogFile); + + // Notify the user with the correct path + Toast.makeText(getActivity(), "Logs saved to: " + savedLogFile.getAbsolutePath(), Toast.LENGTH_LONG).show(); + } catch (Exception e) { + Toast.makeText(getActivity(), "Failed to save logs: " + e.getMessage(), Toast.LENGTH_LONG).show(); + e.printStackTrace(); + } + } + /** * Called when the background log grabbing thread has a progress update * @param update diff --git a/app/src/main/java/com/tortel/syslog/utils/FileUtils.java b/app/src/main/java/com/tortel/syslog/utils/FileUtils.java index 841afca..c9153d2 100644 --- a/app/src/main/java/com/tortel/syslog/utils/FileUtils.java +++ b/app/src/main/java/com/tortel/syslog/utils/FileUtils.java @@ -18,6 +18,8 @@ package com.tortel.syslog.utils; import android.content.Context; +import android.os.Environment; +import android.os.Build; import android.os.Handler; import android.os.StatFs; import android.widget.Toast; @@ -26,6 +28,9 @@ import com.tortel.syslog.R; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; import java.io.File; import eu.chainfire.libsuperuser.Shell; @@ -48,19 +53,51 @@ public static void cleanAllLogs(@NonNull final Context context) { @Override public void run() { final double startingSpace = getStorageFreeSpace(context); - String path = getStorageDir(context).getPath(); + String path = getRootLogDir(context).getAbsolutePath(); // Use getRootLogDir instead of getStorageDir path += "/*"; Shell.SH.run("rm -rf " + path); final double endingSpace = getStorageFreeSpace(context); Handler mainHandler = new Handler(context.getMainLooper()); + String finalPath = path; mainHandler.post(() -> { - Toast.makeText(context, context.getResources().getString(R.string.space_freed, - endingSpace - startingSpace), Toast.LENGTH_SHORT).show(); + // Calculate the space freed + double spaceFreed = endingSpace - startingSpace; + // Format the message for space freed + String formattedMessage = String.format(context.getResources().getString(R.string.space_freed), spaceFreed); + // Combine the space freed message with the storage path + String message = formattedMessage + ", logs stored at: " + finalPath; + // Display the Toast message + Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); }); } }).start(); } + /** + * Copy a file from source to destination + * + * @param sourceFile the source file + * @param destFile the destination file + * @throws IOException if an error occurs during copying + */ + public static void copyFile(File sourceFile, File destFile) throws IOException { + if (!destFile.exists()) { + destFile.createNewFile(); // Create destination file if it doesn't exist + } + + try (FileInputStream fis = new FileInputStream(sourceFile); + FileOutputStream fos = new FileOutputStream(destFile)) { + + byte[] buffer = new byte[1024]; + int length; + + // Read from source and write to destination + while ((length = fis.read(buffer)) > 0) { + fos.write(buffer, 0, length); + } + } + } + /** * Clean all uncompressed log files */ @@ -98,11 +135,22 @@ private static File getStorageDir(Context context) { * @return the working directory. This is a directory that will always exist */ public static @NonNull File getRootLogDir(Context context) { - File logDir = new File(getStorageDir(context).getAbsolutePath() + LOG_DIR); - if (!logDir.isDirectory()) { - logDir.mkdir(); + // For Android 11 and above, use public directory in scoped storage + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + // Define the path inside Downloads directory + File publicDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "Syslogs/Logs"); + if (!publicDir.exists()) { + publicDir.mkdirs(); // Create the directory if it doesn't exist + } + return publicDir; + } else { + // For Android 10 and below, use traditional external storage access + File publicDir = new File(Environment.getExternalStorageDirectory(), "Syslogs/Logs"); + if (!publicDir.exists()) { + publicDir.mkdirs(); // Create the directory if it doesn't exist + } + return publicDir; } - return logDir; } /** diff --git a/app/src/main/res/values/exception-details.xml b/app/src/main/res/values/exception-details.xml index 52a22f4..8804613 100644 --- a/app/src/main/res/values/exception-details.xml +++ b/app/src/main/res/values/exception-details.xml @@ -40,8 +40,8 @@ There was an unknown exception while running. Please submit a bug report, and include the SU implementation you use. - There was no application available to send a zip file. The logs have been saved, but please install or enable - an email application or cloud storage application to easily send the file. + There was no application available to send a zip file. The logs have been saved at Downloads Folder, + but please install or enable an email application or cloud storage application to easily send the file. Your primary storage does not have enough free space. You currently have %.1f MB free. SysLog can try to free space by cleaning old log files.