From 322b36f275782a06ed66b950083f28cc37f5690a Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Tue, 12 Oct 2021 16:52:11 -0700 Subject: [PATCH] Convert LogcatActivity to Kotlin. https://redmine.stoutner.com/issues/770 --- app/build.gradle | 18 +- .../activities/LogcatActivity.java | 331 ------------------ .../activities/LogcatActivity.kt | 321 +++++++++++++++++ .../activities/MainWebViewActivity.java | 6 +- .../activities/ViewSourceActivity.kt | 6 +- .../privacybrowser/asynctasks/GetLogcat.java | 121 ------- .../main/res/layout/logcat_bottom_appbar.xml | 8 +- app/src/main/res/layout/logcat_top_appbar.xml | 8 +- .../res/menu/about_version_options_menu.xml | 2 +- app/src/main/res/menu/logcat_options_menu.xml | 4 +- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-it/strings.xml | 2 +- app/src/main/res/values-night/colors.xml | 6 +- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-tr/strings.xml | 2 +- app/src/main/res/values/colors.xml | 6 +- app/src/main/res/values/strings.xml | 2 +- build.gradle | 2 +- 21 files changed, 352 insertions(+), 503 deletions(-) delete mode 100644 app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.java create mode 100644 app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.kt delete mode 100644 app/src/main/java/com/stoutner/privacybrowser/asynctasks/GetLogcat.java diff --git a/app/build.gradle b/app/build.gradle index 3cc3256b..5ce0872c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,15 +17,17 @@ * along with Privacy Browser. If not, see . */ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' +plugins { + id 'com.android.application' + id 'kotlin-android' +} android { - compileSdkVersion 30 + compileSdk 30 defaultConfig { - minSdkVersion 19 - targetSdkVersion 30 + minSdk 19 + targetSdk 30 versionCode 56 versionName "3.8.1" @@ -62,13 +64,7 @@ android { } } -repositories { - mavenCentral() -} - dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - // Include the following AndroidX libraries. implementation 'androidx.arch.core:core-common:2.1.0' implementation 'androidx.arch.core:core-runtime:2.1.0' diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.java deleted file mode 100644 index 87bb0a3b..00000000 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright © 2019-2021 Soren Stoutner . - * - * This file is part of Privacy Browser . - * - * Privacy Browser is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Privacy Browser is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Privacy Browser. If not, see . - */ - -package com.stoutner.privacybrowser.activities; - -import android.app.Activity; -import android.app.Dialog; -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.net.Uri; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.util.TypedValue; -import android.view.Menu; -import android.view.MenuItem; -import android.view.WindowManager; -import android.widget.EditText; -import android.widget.ScrollView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; -import androidx.fragment.app.DialogFragment; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - -import com.google.android.material.snackbar.Snackbar; - -import com.stoutner.privacybrowser.R; -import com.stoutner.privacybrowser.asynctasks.GetLogcat; -import com.stoutner.privacybrowser.dialogs.SaveDialog; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.nio.charset.StandardCharsets; - -public class LogcatActivity extends AppCompatActivity implements SaveDialog.SaveListener { - // Declare the class constants. - private final String SCROLLVIEW_POSITION = "scrollview_position"; - - // Define the class views. - private TextView logcatTextView; - - @Override - public void onCreate(Bundle savedInstanceState) { - // Get a handle for the shared preferences. - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - - // Get the preferences. - boolean allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false); - boolean bottomAppBar = sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false); - - // Disable screenshots if not allowed. - if (!allowScreenshots) { - getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); - } - - // Set the theme. - setTheme(R.style.PrivacyBrowser); - - // Run the default commands. - super.onCreate(savedInstanceState); - - // Set the content view. - if (bottomAppBar) { - setContentView(R.layout.logcat_bottom_appbar); - } else { - setContentView(R.layout.logcat_top_appbar); - } - - // Get handles for the views. - Toolbar toolbar = findViewById(R.id.logcat_toolbar); - SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.logcat_swiperefreshlayout); - - // Set the toolbar as the action bar. - setSupportActionBar(toolbar); - - // Get a handle for the action bar. - ActionBar actionBar = getSupportActionBar(); - - // Remove the incorrect lint warning that the action bar might be null. - assert actionBar != null; - - // Display the the back arrow in the action bar. - actionBar.setDisplayHomeAsUpEnabled(true); - - // Populate the class views. - logcatTextView = findViewById(R.id.logcat_textview); - - // Implement swipe to refresh. - swipeRefreshLayout.setOnRefreshListener(() -> { - // Get the current logcat. - new GetLogcat(this, 0).execute(); - }); - - // Get the current theme status. - int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; - - // Set the refresh color scheme according to the theme. - if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) { - swipeRefreshLayout.setColorSchemeResources(R.color.blue_700); - } else { - swipeRefreshLayout.setColorSchemeResources(R.color.blue_500); - } - - // Initialize a color background typed value. - TypedValue colorBackgroundTypedValue = new TypedValue(); - - // Get the color background from the theme. - getTheme().resolveAttribute(android.R.attr.colorBackground, colorBackgroundTypedValue, true); - - // Get the color background int from the typed value. - int colorBackgroundInt = colorBackgroundTypedValue.data; - - // Set the swipe refresh background color. - swipeRefreshLayout.setProgressBackgroundColorSchemeColor(colorBackgroundInt); - - // Initialize the scrollview Y position int. - int scrollViewYPositionInt = 0; - - // Check to see if the activity has been restarted. - if (savedInstanceState != null) { - // Get the saved scrollview position. - scrollViewYPositionInt = savedInstanceState.getInt(SCROLLVIEW_POSITION); - } - - // Get the logcat. - new GetLogcat(this, scrollViewYPositionInt).execute(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - // Inflate the menu. This adds items to the action bar. - getMenuInflater().inflate(R.menu.logcat_options_menu, menu); - - // Display the menu. - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem menuItem) { - // Get the selected menu item ID. - int menuItemId = menuItem.getItemId(); - - // Run the commands that correlate to the selected menu item. - if (menuItemId == R.id.copy) { // Copy was selected. - // Get a handle for the clipboard manager. - ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); - - // Remove the incorrect lint error below that the clipboard manager might be null. - assert clipboardManager != null; - - // Save the logcat in a clip data. - ClipData logcatClipData = ClipData.newPlainText(getString(R.string.logcat), logcatTextView.getText()); - - // Place the clip data on the clipboard. - clipboardManager.setPrimaryClip(logcatClipData); - - // Display a snackbar. - Snackbar.make(logcatTextView, R.string.logcat_copied, Snackbar.LENGTH_SHORT).show(); - - // Consume the event. - return true; - } else if (menuItemId == R.id.save) { // Save was selected. - // Instantiate the save alert dialog. - DialogFragment saveDialogFragment = SaveDialog.save(SaveDialog.SAVE_LOGCAT); - - // Show the save alert dialog. - saveDialogFragment.show(getSupportFragmentManager(), getString(R.string.save_logcat)); - - // Consume the event. - return true; - } else if (menuItemId == R.id.clear) { // Clear was selected. - try { - // Clear the logcat. `-c` clears the logcat. `-b all` clears all the buffers (instead of just crash, main, and system). - Process process = Runtime.getRuntime().exec("logcat -b all -c"); - - // Wait for the process to finish. - process.waitFor(); - - // Reload the logcat. - new GetLogcat(this, 0).execute(); - } catch (IOException | InterruptedException exception) { - // Do nothing. - } - - // Consume the event. - return true; - } else { // The home button was pushed. - // Do not consume the event. The system will process the home command. - return super.onOptionsItemSelected(menuItem); - } - } - - @Override - public void onSaveInstanceState(@NonNull Bundle savedInstanceState) { - // Run the default commands. - super.onSaveInstanceState(savedInstanceState); - - // Get a handle for the logcat scrollview. - ScrollView logcatScrollView = findViewById(R.id.logcat_scrollview); - - // Get the scrollview Y position. - int scrollViewYPositionInt = logcatScrollView.getScrollY(); - - // Store the scrollview Y position in the bundle. - savedInstanceState.putInt(SCROLLVIEW_POSITION, scrollViewYPositionInt); - } - - // The activity result is called after browsing for a file in the save alert dialog. - @Override - public void onActivityResult(int requestCode, int resultCode, Intent returnedIntent) { - // Run the default commands. - super.onActivityResult(requestCode, resultCode, returnedIntent); - - // Only do something if the user didn't press back from the file picker. - if (resultCode == Activity.RESULT_OK) { - // Get a handle for the save dialog fragment. - DialogFragment saveDialogFragment = (DialogFragment) getSupportFragmentManager().findFragmentByTag(getString(R.string.save_logcat)); - - // Only update the file name if the dialog still exists. - if (saveDialogFragment != null) { - // Get a handle for the save dialog. - Dialog saveDialog = saveDialogFragment.getDialog(); - - // Remove the lint warning below that the save dialog might be null. - assert saveDialog != null; - - // Get a handle for the file name edit text. - EditText fileNameEditText = saveDialog.findViewById(R.id.file_name_edittext); - - // Get the file name URI from the intent. - Uri fileNameUri = returnedIntent.getData(); - - // Get the file name string from the URI. - String fileNameString = fileNameUri.toString(); - - // Set the file name text. - fileNameEditText.setText(fileNameString); - - // Move the cursor to the end of the file name edit text. - fileNameEditText.setSelection(fileNameString.length()); - } - } - } - - @Override - public void onSave(int saveType, DialogFragment dialogFragment) { - // Get a handle for the dialog. - Dialog dialog = dialogFragment.getDialog(); - - // Remove the lint warning below that the dialog might be null. - assert dialog != null; - - // Get a handle for the file name edit text. - EditText fileNameEditText = dialog.findViewById(R.id.file_name_edittext); - - // Get the file path string. - String fileNameString = fileNameEditText.getText().toString(); - - try { - // Get the logcat as a string. - String logcatString = logcatTextView.getText().toString(); - - // Create an input stream with the contents of the logcat. - InputStream logcatInputStream = new ByteArrayInputStream(logcatString.getBytes(StandardCharsets.UTF_8)); - - // Create a logcat buffered reader. - BufferedReader logcatBufferedReader = new BufferedReader(new InputStreamReader(logcatInputStream)); - - // Open an output stream. - OutputStream outputStream = getContentResolver().openOutputStream(Uri.parse(fileNameString)); - - // Create a file buffered writer. - BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); - - // Create a transfer string. - String transferString; - - // Use the transfer string to copy the logcat from the buffered reader to the buffered writer. - while ((transferString = logcatBufferedReader.readLine()) != null) { - // Append the line to the buffered writer. - bufferedWriter.append(transferString); - - // Append a line break. - bufferedWriter.append("\n"); - } - - // Flush the buffered writer. - bufferedWriter.flush(); - - // Close the inputs and outputs. - logcatBufferedReader.close(); - logcatInputStream.close(); - bufferedWriter.close(); - outputStream.close(); - - // Display a snackbar with the saved logcat information. - Snackbar.make(logcatTextView, getString(R.string.file_saved) + " " + fileNameString, Snackbar.LENGTH_SHORT).show(); - } catch (Exception exception) { - // Display a snackbar with the error message. - Snackbar.make(logcatTextView, getString(R.string.error_saving_file) + " " + exception.toString(), Snackbar.LENGTH_INDEFINITE).show(); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.kt new file mode 100644 index 00000000..23e6d525 --- /dev/null +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.kt @@ -0,0 +1,321 @@ +/* + * Copyright © 2019-2021 Soren Stoutner . + * + * This file is part of Privacy Browser . + * + * Privacy Browser is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Privacy Browser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Browser. If not, see . + */ + +package com.stoutner.privacybrowser.activities + +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.os.Bundle +import android.provider.OpenableColumns +import android.util.TypedValue +import android.view.Menu +import android.view.MenuItem +import android.view.WindowManager +import android.widget.EditText +import android.widget.TextView +import android.widget.ScrollView + +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.Toolbar +import androidx.fragment.app.DialogFragment +import androidx.preference.PreferenceManager +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout + +import com.google.android.material.snackbar.Snackbar + +import com.stoutner.privacybrowser.R +import com.stoutner.privacybrowser.dialogs.SaveDialog + +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStreamReader +import java.lang.Exception +import java.nio.charset.StandardCharsets + +// Define the class constants. +private const val SCROLLVIEW_POSITION = "scrollview_position" + +class LogcatActivity : AppCompatActivity(), SaveDialog.SaveListener { + // Define the class variables. + private var scrollViewYPositionInt = 0 + + // Define the class views. + private lateinit var swipeRefreshLayout: SwipeRefreshLayout + private lateinit var logcatScrollView: ScrollView + private lateinit var logcatTextView: TextView + + public override fun onCreate(savedInstanceState: Bundle?) { + // Get a handle for the shared preferences. + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) + + // Get the preferences. + val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false) + val bottomAppBar = sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false) + + // Disable screenshots if not allowed. + if (!allowScreenshots) { + window.addFlags(WindowManager.LayoutParams.FLAG_SECURE) + } + + // Set the theme. + setTheme(R.style.PrivacyBrowser) + + // Run the default commands. + super.onCreate(savedInstanceState) + + // Set the content view. + if (bottomAppBar) { + setContentView(R.layout.logcat_bottom_appbar) + } else { + setContentView(R.layout.logcat_top_appbar) + } + + // Get handles for the views. + val toolbar = findViewById(R.id.toolbar) + swipeRefreshLayout = findViewById(R.id.swiperefreshlayout) + logcatScrollView = findViewById(R.id.scrollview) + logcatTextView = findViewById(R.id.logcat_textview) + + // Set the toolbar as the action bar. + setSupportActionBar(toolbar) + + // Get a handle for the action bar. + val actionBar = supportActionBar!! + + // Display the back arrow in the action bar. + actionBar.setDisplayHomeAsUpEnabled(true) + + // Implement swipe to refresh. + swipeRefreshLayout.setOnRefreshListener { + // Get the current logcat. + getLogcat() + } + + // Set the swipe refresh color scheme according to the theme. + swipeRefreshLayout.setColorSchemeResources(R.color.blue_text) + + // Initialize a color background typed value. + val colorBackgroundTypedValue = TypedValue() + + // Get the color background from the theme. + theme.resolveAttribute(android.R.attr.colorBackground, colorBackgroundTypedValue, true) + + // Get the color background int from the typed value. + val colorBackgroundInt = colorBackgroundTypedValue.data + + // Set the swipe refresh background color. + swipeRefreshLayout.setProgressBackgroundColorSchemeColor(colorBackgroundInt) + + // Check to see if the activity has been restarted. + if (savedInstanceState != null) { + // Get the saved scrollview position. + scrollViewYPositionInt = savedInstanceState.getInt(SCROLLVIEW_POSITION) + } + + // Get the logcat. + getLogcat() + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + // Inflate the menu. This adds items to the action bar. + menuInflater.inflate(R.menu.logcat_options_menu, menu) + + // Display the menu. + return true + } + + override fun onOptionsItemSelected(menuItem: MenuItem): Boolean { + // Run the commands that correlate to the selected menu item. + return when (menuItem.itemId) { + R.id.copy -> { // Copy was selected. + // Get a handle for the clipboard manager. + val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager + + // Save the logcat in a clip data. + val logcatClipData = ClipData.newPlainText(getString(R.string.logcat), logcatTextView.text) + + // Place the clip data on the clipboard. + clipboardManager.setPrimaryClip(logcatClipData) + + // Display a snackbar. + Snackbar.make(logcatTextView, R.string.logcat_copied, Snackbar.LENGTH_SHORT).show() + + // Consume the event. + true + } + + R.id.save -> { // Save was selected. + // Instantiate the save alert dialog. + val saveDialogFragment: DialogFragment = SaveDialog.save(SaveDialog.SAVE_LOGCAT) + + // Show the save alert dialog. + saveDialogFragment.show(supportFragmentManager, getString(R.string.save_logcat)) + + // Consume the event. + true + } + + R.id.clear -> { // Clear was selected. + try { + // Clear the logcat. `-c` clears the logcat. `-b all` clears all the buffers (instead of just crash, main, and system). + val process = Runtime.getRuntime().exec("logcat -b all -c") + + // Wait for the process to finish. + process.waitFor() + + // Reset the scroll view Y position int. + scrollViewYPositionInt = 0 + + // Reload the logcat. + getLogcat() + } catch (exception: Exception) { + // Do nothing. + } + + // Consume the event. + true + } + + else -> { // The home button was pushed. + // Do not consume the event. The system will process the home command. + super.onOptionsItemSelected(menuItem) + } + } + } + + public override fun onSaveInstanceState(savedInstanceState: Bundle) { + // Run the default commands. + super.onSaveInstanceState(savedInstanceState) + + // Get the scrollview Y position. + val scrollViewYPositionInt = logcatScrollView.scrollY + + // Store the scrollview Y position in the bundle. + savedInstanceState.putInt(SCROLLVIEW_POSITION, scrollViewYPositionInt) + } + + private fun getLogcat() { + try { + // Get the logcat. `-b all` gets all the buffers (instead of just crash, main, and system). `-v long` produces more complete information. `-d` dumps the logcat and exits. + val getLogcatProcess = Runtime.getRuntime().exec("logcat -b all -v long -d") + + // Wrap the logcat in a buffered reader. + val logcatBufferedReader = BufferedReader(InputStreamReader(getLogcatProcess.inputStream)) + + // Display the logcat. + logcatTextView.text = logcatBufferedReader.readText() + + // Close the buffered reader. + logcatBufferedReader.close() + } catch (exception: IOException) { + // Do nothing. + } + + // Update the scroll position after the text is populated. + logcatTextView.post { + // Set the scroll position. + logcatScrollView.scrollY = scrollViewYPositionInt + } + + // Stop the swipe to refresh animation if it is displayed. + swipeRefreshLayout.isRefreshing = false + } + + // The activity result is called after browsing for a file in the save alert dialog. + public override fun onActivityResult(requestCode: Int, resultCode: Int, returnedIntent: Intent?) { + // Run the default commands. + super.onActivityResult(requestCode, resultCode, returnedIntent) + + // Only do something if the user didn't press back from the file picker. + if (resultCode == RESULT_OK) { + // Get a handle for the save dialog fragment. + val saveDialogFragment = supportFragmentManager.findFragmentByTag(getString(R.string.save_logcat)) as DialogFragment? + + // Only update the file name if the dialog still exists. + if (saveDialogFragment != null) { + // Get a handle for the save dialog. + val saveDialog = saveDialogFragment.dialog!! + + // Get a handle for the file name edit text. + val fileNameEditText = saveDialog.findViewById(R.id.file_name_edittext) + + // Get the file name URI from the intent. + val fileNameUri = returnedIntent!!.data + + // Get the file name string from the URI. + val fileNameString = fileNameUri.toString() + + // Set the file name text. + fileNameEditText.setText(fileNameString) + + // Move the cursor to the end of the file name edit text. + fileNameEditText.setSelection(fileNameString.length) + } + } + } + + override fun onSave(saveType: Int, dialogFragment: DialogFragment) { + // Get a handle for the dialog. + val dialog = dialogFragment.dialog!! + + // Get a handle for the file name edit text. + val fileNameEditText = dialog.findViewById(R.id.file_name_edittext) + + // Get the file path string. + var fileNameString = fileNameEditText.text.toString() + + try { + // Get the logcat as a string. + val logcatString = logcatTextView.text.toString() + + // Open an output stream. + val outputStream = contentResolver.openOutputStream(Uri.parse(fileNameString))!! + + // Write the logcat string to the output stream. + outputStream.write(logcatString.toByteArray(StandardCharsets.UTF_8)) + + // Close the output stream. + outputStream.close() + + // Get the actual file name if the API >= 26. + if (Build.VERSION.SDK_INT >= 26) { + // Get a cursor from the content resolver. + val contentResolverCursor = contentResolver.query(Uri.parse(fileNameString), null, null, null)!! + + // Move to the first row. + contentResolverCursor.moveToFirst() + + // Get the file name from the cursor. + fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)) + + // Close the cursor. + contentResolverCursor.close() + } + + // Display a snackbar with the saved logcat information. + Snackbar.make(logcatTextView, getString(R.string.file_saved) + " " + fileNameString, Snackbar.LENGTH_SHORT).show() + } catch (exception: Exception) { + // Display a snackbar with the error message. + Snackbar.make(logcatTextView, getString(R.string.error_saving_file) + " " + exception.toString(), Snackbar.LENGTH_INDEFINITE).show() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java index 38fae2ed..498b034e 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -3434,11 +3434,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook defaultProgressViewEndOffset = swipeRefreshLayout.getProgressViewEndOffset(); // Set the refresh color scheme according to the theme. - if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) { - swipeRefreshLayout.setColorSchemeResources(R.color.blue_700); - } else { - swipeRefreshLayout.setColorSchemeResources(R.color.violet_500); - } + swipeRefreshLayout.setColorSchemeResources(R.color.blue_text); // Initialize a color background typed value. TypedValue colorBackgroundTypedValue = new TypedValue(); diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.kt index 532eda55..759b79c0 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.kt @@ -186,11 +186,7 @@ class ViewSourceActivity: AppCompatActivity(), UntrustedSslCertificateListener { } // Set the refresh color scheme according to the theme. - if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) { - swipeRefreshLayout.setColorSchemeResources(R.color.blue_700) - } else { - swipeRefreshLayout.setColorSchemeResources(R.color.violet_500) - } + swipeRefreshLayout.setColorSchemeResources(R.color.blue_text) // Initialize a color background typed value. val colorBackgroundTypedValue = TypedValue() diff --git a/app/src/main/java/com/stoutner/privacybrowser/asynctasks/GetLogcat.java b/app/src/main/java/com/stoutner/privacybrowser/asynctasks/GetLogcat.java deleted file mode 100644 index 8abd75ac..00000000 --- a/app/src/main/java/com/stoutner/privacybrowser/asynctasks/GetLogcat.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright © 2020-2021 Soren Stoutner . - * - * This file is part of Privacy Browser . - * - * Privacy Browser is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Privacy Browser is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Privacy Browser. If not, see . - */ - -package com.stoutner.privacybrowser.asynctasks; - -import android.app.Activity; -import android.os.AsyncTask; -import android.widget.ScrollView; -import android.widget.TextView; - -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - -import com.stoutner.privacybrowser.R; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.ref.WeakReference; - -// `Void` does not declare any parameters. `Void` does not declare progress units. `String` contains the results. -public class GetLogcat extends AsyncTask { - // Define the class variables. - private final WeakReference activityWeakReference; - private final int scrollViewYPositionInt; - - // The public constructor. - public GetLogcat(Activity activity, int scrollViewYPositionInt) { - // Populate the weak reference to the calling activity. - activityWeakReference = new WeakReference<>(activity); - - // Store the scrollview Y position. - this.scrollViewYPositionInt = scrollViewYPositionInt; - } - - @Override - protected String doInBackground(Void... parameters) { - // Get a handle for the activity. - Activity activity = activityWeakReference.get(); - - // Abort if the activity is gone. - if ((activity == null) || activity.isFinishing()) { - return ""; - } - - // Create a log string builder. - StringBuilder logStringBuilder = new StringBuilder(); - - try { - // Get the logcat. `-b all` gets all the buffers (instead of just crash, main, and system). `-v long` produces more complete information. `-d` dumps the logcat and exits. - Process process = Runtime.getRuntime().exec("logcat -b all -v long -d"); - - // Wrap the logcat in a buffered reader. - BufferedReader logBufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); - - // Create a log transfer string. - String logTransferString; - - // Use the log transfer string to copy the logcat from the buffered reader to the string builder. - while ((logTransferString = logBufferedReader.readLine()) != null) { - // Append a line. - logStringBuilder.append(logTransferString); - - // Append a line break. - logStringBuilder.append("\n"); - } - - // Close the buffered reader. - logBufferedReader.close(); - } catch (IOException exception) { - // Do nothing. - } - - // Return the logcat. - return logStringBuilder.toString(); - } - - // `onPostExecute()` operates on the UI thread. - @Override - protected void onPostExecute(String logcatString) { - // Get a handle for the activity. - Activity activity = activityWeakReference.get(); - - // Abort if the activity is gone. - if ((activity == null) || activity.isFinishing()) { - return; - } - - // Get handles for the views. - TextView logcatTextView = activity.findViewById(R.id.logcat_textview); - SwipeRefreshLayout swipeRefreshLayout = activity.findViewById(R.id.logcat_swiperefreshlayout); - ScrollView scrollView = activity.findViewById(R.id.logcat_scrollview); - - // Display the logcat. - logcatTextView.setText(logcatString); - - // Update the scroll position after the text is populated. - logcatTextView.post(() -> { - // Set the scroll position. - scrollView.setScrollY(scrollViewYPositionInt); - }); - - // Stop the swipe to refresh animation if it is displayed. - swipeRefreshLayout.setRefreshing(false); - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/logcat_bottom_appbar.xml b/app/src/main/res/layout/logcat_bottom_appbar.xml index e7e4051a..9637997d 100644 --- a/app/src/main/res/layout/logcat_bottom_appbar.xml +++ b/app/src/main/res/layout/logcat_bottom_appbar.xml @@ -19,7 +19,6 @@ along with Privacy Browser. If not, see . --> @@ -54,14 +53,13 @@ diff --git a/app/src/main/res/layout/logcat_top_appbar.xml b/app/src/main/res/layout/logcat_top_appbar.xml index 8179fa8c..005c2f56 100644 --- a/app/src/main/res/layout/logcat_top_appbar.xml +++ b/app/src/main/res/layout/logcat_top_appbar.xml @@ -19,7 +19,6 @@ along with Privacy Browser. If not, see . --> @@ -32,25 +31,24 @@ diff --git a/app/src/main/res/menu/about_version_options_menu.xml b/app/src/main/res/menu/about_version_options_menu.xml index c434633f..3e1914af 100644 --- a/app/src/main/res/menu/about_version_options_menu.xml +++ b/app/src/main/res/menu/about_version_options_menu.xml @@ -25,7 +25,7 @@ diff --git a/app/src/main/res/menu/logcat_options_menu.xml b/app/src/main/res/menu/logcat_options_menu.xml index f8c8dd11..c8524547 100644 --- a/app/src/main/res/menu/logcat_options_menu.xml +++ b/app/src/main/res/menu/logcat_options_menu.xml @@ -20,12 +20,12 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" > diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 3fe09724..4a9bf34f 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -376,7 +376,7 @@ Import fehlgeschlagen: - kopieren + kopieren Logcat kopiert. leeren diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index c6d22475..fd26948d 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -373,7 +373,7 @@ Importación fallida: - Copiar + Copiar Logcat copiado. Borrar diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 525cb0f8..77e29dec 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -373,7 +373,7 @@ L\'import a échoué : - Copie + Copie Journal système copié. Vider diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index c6fd0842..336db917 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -372,7 +372,7 @@ Importazione fallita: - Copia + Copia Logcat copiato. Cancella diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 8ba568fc..eeeb5f79 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -20,10 +20,8 @@ - - #FF9E9E9E - #FF616161 - #FFB71C1C + + @color/violet_500 #66000000 diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 6387356d..8bc85358 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -371,7 +371,7 @@ A importação falhou: - Cópia + Cópia Logcat copiado. Limpar diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ec1a4028..c8bbd363 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -369,7 +369,7 @@ Сбой при импорте: - Копировать + Копировать Logcat скопирован. Очистить diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 5fdea5c4..9318cbfd 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -334,7 +334,7 @@ İçe aktarım başarısız: - Kopyala + Kopyala Logcat kopyalandı. Temizle diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 4a24aff2..69bf0664 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -20,10 +20,8 @@ - - #FF757575 - #FFB7B7B7 - #FFB71C1C + + @color/blue_700 #66000000 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 01508721..74ec28b9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -378,7 +378,7 @@ Import failed: - Copy + Copy Logcat copied. Clear diff --git a/build.gradle b/build.gradle index ded45940..d384f0f0 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:7.0.2' + classpath 'com.android.tools.build:gradle:7.0.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31" // NOTE: Do not place your application dependencies here; they belong -- 2.45.2