From aba9e7bb471a9ee31b2f2899f7f8bddc491a9271 Mon Sep 17 00:00:00 2001 From: Navid Date: Wed, 31 Jul 2024 19:47:51 -0400 Subject: [PATCH] Save logs locally --- app/src/main/AndroidManifest.xml | 6 + .../dexdrip/EventLogActivity.java | 27 +++-- .../dexdrip/utilitymodels/SaveLogs.java | 110 ++++++++++++++++++ .../dexdrip/utilitymodels/SendFeedBack.java | 4 +- .../main/res/layout/activity_event_log.xml | 12 ++ .../main/res/layout/activity_save_logs.xml | 46 ++++++++ .../res/layout/activity_send_feed_back.xml | 26 +++-- app/src/main/res/values/strings.xml | 3 + 8 files changed, 213 insertions(+), 21 deletions(-) create mode 100644 app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/SaveLogs.java create mode 100644 app/src/main/res/layout/activity_save_logs.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 73df543f1f..35e672da9d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -703,6 +703,12 @@ + + 200000) { + if (builder.length() > MAX_LOG_PACKAGE_SIZE) { JoH.static_toast_long(this, "Could not package up all logs, using most recent"); + builder.append("\n\nOnly the most recent logs have been included to limit the file size.\n"); break; } } - startActivity(new Intent(getApplicationContext(), SendFeedBack.class).putExtra("generic_text", builder.toString())); + + builder.insert(0, JoH.getDeviceDetails() + "\n" + JoH.getVersionDetails() + "\n" + getBestCollectorHardwareName() + "\n===\n" + "\nLog data:\n"); // Adds device, version and collector details before the log. + builder.append("\n\nCaptured: " + JoH.dateTimeText(JoH.tsl())); // Adds date and time of capture after the log. + + return builder.toString(); } // View model container - accessible binding methods must be declared public @@ -636,5 +651,3 @@ public void onBindBinding(ViewDataBinding binding, int bindingVariable, @LayoutR } } - - diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/SaveLogs.java b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/SaveLogs.java new file mode 100644 index 0000000000..a8a806ef68 --- /dev/null +++ b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/SaveLogs.java @@ -0,0 +1,110 @@ +package com.eveningoutpost.dexdrip.utilitymodels; + +import android.Manifest; +import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.Environment; +import android.view.View; +import android.widget.TextView; + +import com.eveningoutpost.dexdrip.BaseAppCompatActivity; +import com.eveningoutpost.dexdrip.R; +import com.eveningoutpost.dexdrip.models.JoH; +import com.eveningoutpost.dexdrip.models.UserError; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import static com.eveningoutpost.dexdrip.utils.FileUtils.makeSureDirectoryExists; + +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +// Saves xDrip logs to storage. +// SendFeedBack sends logs to the lead developer. +// This does the same thing for saving logs to storage. +// Navid200 +// July 2024 + +public class SaveLogs extends BaseAppCompatActivity { + + private static final String TAG = "save logs"; + private String LOG_FILE_PATH = "/Download/xDrip-export"; // Path to where we save the log file + private String LOG_FILE_NAME = "xDrip-log.txt"; // Log file name + private final static int MY_PERMISSIONS_REQUEST_STORAGE = 104; + private String log_data = ""; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_save_logs); + + Intent intent = getIntent(); + if (intent != null) { + final Bundle bundle = intent.getExtras(); + if (bundle != null) { + final String str2 = bundle.getString("generic_text"); + if (str2 != null) { + log_data = str2; + ((TextView) findViewById(R.id.yourSaveText)).setText(log_data.length() > 300 ? "\n\nAttached " + log_data.length() + " characters of log data. (hidden)\n\n" : log_data); + } + } + } + } + + public void closeActivity(View myview) { + finish(); + } + + public void saveLogs(View myview) { + if (saveLogsToStorage(log_data)) { + UserError.Log.e(TAG, "Saved log file to /Downloads/xDrip-export/xDrip-log.txt"); + } else { + UserError.Log.e(TAG, "Could not write log file"); + } + log_data = ""; + closeActivity(null); // Let's close the menu + } + + public boolean saveLogsToStorage(String contents) { + if (isStorageWritable(this, MY_PERMISSIONS_REQUEST_STORAGE)) { + try { + final StringBuilder sb = new StringBuilder(); + sb.append(Environment.getExternalStorageDirectory().getAbsolutePath()); + sb.append(LOG_FILE_PATH); + final String dir = sb.toString(); + makeSureDirectoryExists(dir); + final String pathPlusFileName = dir + "/" + LOG_FILE_NAME; + final File myExternalFile = new File(pathPlusFileName); + FileOutputStream fos = new FileOutputStream(myExternalFile); + fos.write(contents.getBytes()); + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } else { + JoH.static_toast_long("getString(R.string.sdcard_not_writable_cannot_save)"); + return false; + } + } + + public static boolean isStorageWritable(Activity context, int request_code) { // Get write permission if not & return false. Return true if yes and not tied up. + if (ContextCompat.checkSelfPermission(context, + android.Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(context, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + request_code); + UserError.Log.e(TAG, "Did not have write permission, but should have it now"); + return false; + } + String state = Environment.getExternalStorageState(); + return Environment.MEDIA_MOUNTED.equals(state); + } + +} + diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/SendFeedBack.java b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/SendFeedBack.java index 7f05385904..7b6c080af4 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/SendFeedBack.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/utilitymodels/SendFeedBack.java @@ -78,7 +78,7 @@ protected void onCreate(Bundle savedInstanceState) { final String str2 = bundle.getString("generic_text"); if (str2 != null) { log_data = str2; - ((EditText) findViewById(R.id.yourText)).setText(log_data.length() > 300 ? "\n\nPlease describe what you think these logs may show? Explain the problem if there is one.\n\nAttached " + log_data.length() + " characters of log data. (hidden)\n\n" : log_data); + ((EditText) findViewById(R.id.yourText)).setText(log_data.length() > 300 ? "\n\nPlease describe what you think these logs may show. Explain the problem if there is one.\n\nAttached " + log_data.length() + " characters of log data. (hidden)\n\n" : log_data); type_of_message = "Log Push"; myrating.setVisibility(View.GONE); ratingtext.setVisibility(View.GONE); @@ -177,7 +177,7 @@ public void sendFeedback(View myview) { try { final RequestBody formBody = new FormEncodingBuilder() .add("contact", contact.getText().toString()) - .add("body", JoH.getDeviceDetails() + "\n" + JoH.getVersionDetails() + "\n" + getBestCollectorHardwareName() + "\n===\n\n" + yourtext.getText().toString() + " \n\n===\nType: " + type_of_message + "\nLog data:\n\n" + log_data + "\n\n\nSent: " + JoH.dateTimeText(JoH.tsl())) + .add("body",yourtext.getText().toString() + " \n\n===\nType: " + type_of_message + "\nLog data:\n\n" + log_data) // Adding "Your text" and type to the log .add("rating", String.valueOf(myrating.getRating())) .add("type", type_of_message) .build(); diff --git a/app/src/main/res/layout/activity_event_log.xml b/app/src/main/res/layout/activity_event_log.xml index 71e522b53e..a65bb8d699 100644 --- a/app/src/main/res/layout/activity_event_log.xml +++ b/app/src/main/res/layout/activity_event_log.xml @@ -139,6 +139,17 @@ android:layout_weight="1" android:onClick="uploadEventLogs" android:text="@string/upload_logs" + android:textAllCaps="false" + android:textAlignment="center" /> + +