2021-03-13 11:49:29 +00:00
|
|
|
package com.termux.app.utils;
|
|
|
|
|
2021-03-23 21:38:37 +00:00
|
|
|
import android.annotation.SuppressLint;
|
Refactor TermuxActivity
This commit majorly refactors `TermuxActivity` and moves its view components and functions into dedicated classes.
- The view layouts and ids have been given meaningful names, like `termux_activity.xml`.
- The `TerminalToolbarViewPager` class has been created to handle the now called toolbar that shows on the bottom of the terminal view. It currently contains extra keys view defined by `terminal_toolbar_extra_keys_view.xml` file and a text input view defined by `terminal_toolbar_text_input_view.xml` file when user can switch to by swiping left. The input text will now be preserved if android destroys the activity or its recreated.
- The `TermuxSessionsListViewController` class has been created to handle view related functionality of the termux sessions list shown in the left drawer, namely view creation, `onItemClick()`, `onItemLongClick()`, etc. Its list view is defined by `termux_activity.xml` file and each item's layout is defined by the `terminal_sessions_list_item.xml` file.
- The `TextDataUtils` class has been added to the `com.termux.app.utils` package for text utils.
- The design for the `SessionChangedCallback` interface for `TerminalSession` has been majorly changed. Firstly, it has been renamed and moved from `TerminalSession` to the dedicated `TerminalSessionClient` class file. The interface now also supports the termux app centralized logging framework so that `TerminalSession` and `TerminalEmulator` can use them. Previously, `TermuxService` was implementing a wrapper interface, which would then call the real interface defined by the `TermuxActivity` if it was currently bound to the service. This cluttered and partially duplicated the code. Now, the implementation is defined by the `TermuxSessionClientBase` and `TermuxSessionClient` classes. The `TermuxSessionClientBase` implements the `TerminalSessionClient` interface but the definition of the activity related functions do not do anything, only the background ones like the logging functions are fully implemented. The `TermuxSessionClient` class inherits from the `TermuxSessionClientBase` class and provides the implementation for the activity related functions. The design for how this works is that if the `TermuxService` is not bound to `TermuxActivity`, it just passes the `TermuxSessionClientBase` implementation to `TerminalSession`. If the activity is bound at some point, then in `onServiceConnected()` it replaces/updates the client objects stored in `TerminalSession` and `TerminalEmulator` with `TermuxSessionClient`, and then replaces them back with `TermuxSessionClientBase` in `onDestroy()`. This seems to be working for now without an issue.
2021-03-16 00:01:09 +00:00
|
|
|
import android.content.ComponentName;
|
2021-03-13 11:49:29 +00:00
|
|
|
import android.content.Context;
|
Refactor TermuxActivity
This commit majorly refactors `TermuxActivity` and moves its view components and functions into dedicated classes.
- The view layouts and ids have been given meaningful names, like `termux_activity.xml`.
- The `TerminalToolbarViewPager` class has been created to handle the now called toolbar that shows on the bottom of the terminal view. It currently contains extra keys view defined by `terminal_toolbar_extra_keys_view.xml` file and a text input view defined by `terminal_toolbar_text_input_view.xml` file when user can switch to by swiping left. The input text will now be preserved if android destroys the activity or its recreated.
- The `TermuxSessionsListViewController` class has been created to handle view related functionality of the termux sessions list shown in the left drawer, namely view creation, `onItemClick()`, `onItemLongClick()`, etc. Its list view is defined by `termux_activity.xml` file and each item's layout is defined by the `terminal_sessions_list_item.xml` file.
- The `TextDataUtils` class has been added to the `com.termux.app.utils` package for text utils.
- The design for the `SessionChangedCallback` interface for `TerminalSession` has been majorly changed. Firstly, it has been renamed and moved from `TerminalSession` to the dedicated `TerminalSessionClient` class file. The interface now also supports the termux app centralized logging framework so that `TerminalSession` and `TerminalEmulator` can use them. Previously, `TermuxService` was implementing a wrapper interface, which would then call the real interface defined by the `TermuxActivity` if it was currently bound to the service. This cluttered and partially duplicated the code. Now, the implementation is defined by the `TermuxSessionClientBase` and `TermuxSessionClient` classes. The `TermuxSessionClientBase` implements the `TerminalSessionClient` interface but the definition of the activity related functions do not do anything, only the background ones like the logging functions are fully implemented. The `TermuxSessionClient` class inherits from the `TermuxSessionClientBase` class and provides the implementation for the activity related functions. The design for how this works is that if the `TermuxService` is not bound to `TermuxActivity`, it just passes the `TermuxSessionClientBase` implementation to `TerminalSession`. If the activity is bound at some point, then in `onServiceConnected()` it replaces/updates the client objects stored in `TerminalSession` and `TerminalEmulator` with `TermuxSessionClient`, and then replaces them back with `TermuxSessionClientBase` in `onDestroy()`. This seems to be working for now without an issue.
2021-03-16 00:01:09 +00:00
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.pm.ResolveInfo;
|
2021-03-23 21:38:37 +00:00
|
|
|
import android.os.Build;
|
|
|
|
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
|
|
|
|
import com.google.common.base.Joiner;
|
2021-03-13 11:49:29 +00:00
|
|
|
|
Implement crash handler and reporting
Now whenever the Termux app crashes, the crash report (stacktrace, app and device info) will be logged to ~/crash_log.md file. When the user will reopen the app, a notification will be shown which when clicked will show the crash report content in the ReportActivity. The activity will have important links like email, reddit, github issues of termux app and packages at which the user can optionally report an issue if necessary after copying the crash report text. The ~/crash_log.md file will be moved to ~/crash_log-backup.md so that a notification is not shown again on next startup and can be viewed again via SAF, etc.
This will allow reports for bugs that are submitted to have complete and useful info, specially in markdown format, making lives of devs a tad bit easier. Also more bugs that are rare might be submitted since users will have the info to report with and know where to report at.
ToDo:
- The TermuxConstants.TERMUX_SUPPORT_EMAIL_URL needs to be updated with a valid support email once its set up. The TermuxUtils.getReportIssueMarkdownString() function currently also has "email" lines commented out which will need to be uncommented.
- Currently, crashes will only be handled for the main app thread, other threads will have to manually hooked into where necessary.
2021-04-06 11:15:00 +00:00
|
|
|
import com.termux.R;
|
2021-03-13 11:49:29 +00:00
|
|
|
import com.termux.app.TermuxConstants;
|
|
|
|
|
2021-03-23 21:38:37 +00:00
|
|
|
import java.io.BufferedReader;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
import java.util.Date;
|
Refactor TermuxActivity
This commit majorly refactors `TermuxActivity` and moves its view components and functions into dedicated classes.
- The view layouts and ids have been given meaningful names, like `termux_activity.xml`.
- The `TerminalToolbarViewPager` class has been created to handle the now called toolbar that shows on the bottom of the terminal view. It currently contains extra keys view defined by `terminal_toolbar_extra_keys_view.xml` file and a text input view defined by `terminal_toolbar_text_input_view.xml` file when user can switch to by swiping left. The input text will now be preserved if android destroys the activity or its recreated.
- The `TermuxSessionsListViewController` class has been created to handle view related functionality of the termux sessions list shown in the left drawer, namely view creation, `onItemClick()`, `onItemLongClick()`, etc. Its list view is defined by `termux_activity.xml` file and each item's layout is defined by the `terminal_sessions_list_item.xml` file.
- The `TextDataUtils` class has been added to the `com.termux.app.utils` package for text utils.
- The design for the `SessionChangedCallback` interface for `TerminalSession` has been majorly changed. Firstly, it has been renamed and moved from `TerminalSession` to the dedicated `TerminalSessionClient` class file. The interface now also supports the termux app centralized logging framework so that `TerminalSession` and `TerminalEmulator` can use them. Previously, `TermuxService` was implementing a wrapper interface, which would then call the real interface defined by the `TermuxActivity` if it was currently bound to the service. This cluttered and partially duplicated the code. Now, the implementation is defined by the `TermuxSessionClientBase` and `TermuxSessionClient` classes. The `TermuxSessionClientBase` implements the `TerminalSessionClient` interface but the definition of the activity related functions do not do anything, only the background ones like the logging functions are fully implemented. The `TermuxSessionClient` class inherits from the `TermuxSessionClientBase` class and provides the implementation for the activity related functions. The design for how this works is that if the `TermuxService` is not bound to `TermuxActivity`, it just passes the `TermuxSessionClientBase` implementation to `TerminalSession`. If the activity is bound at some point, then in `onServiceConnected()` it replaces/updates the client objects stored in `TerminalSession` and `TerminalEmulator` with `TermuxSessionClient`, and then replaces them back with `TermuxSessionClientBase` in `onDestroy()`. This seems to be working for now without an issue.
2021-03-16 00:01:09 +00:00
|
|
|
import java.util.List;
|
2021-03-23 21:38:37 +00:00
|
|
|
import java.util.Properties;
|
|
|
|
import java.util.TimeZone;
|
|
|
|
import java.util.regex.Matcher;
|
|
|
|
import java.util.regex.Pattern;
|
Refactor TermuxActivity
This commit majorly refactors `TermuxActivity` and moves its view components and functions into dedicated classes.
- The view layouts and ids have been given meaningful names, like `termux_activity.xml`.
- The `TerminalToolbarViewPager` class has been created to handle the now called toolbar that shows on the bottom of the terminal view. It currently contains extra keys view defined by `terminal_toolbar_extra_keys_view.xml` file and a text input view defined by `terminal_toolbar_text_input_view.xml` file when user can switch to by swiping left. The input text will now be preserved if android destroys the activity or its recreated.
- The `TermuxSessionsListViewController` class has been created to handle view related functionality of the termux sessions list shown in the left drawer, namely view creation, `onItemClick()`, `onItemLongClick()`, etc. Its list view is defined by `termux_activity.xml` file and each item's layout is defined by the `terminal_sessions_list_item.xml` file.
- The `TextDataUtils` class has been added to the `com.termux.app.utils` package for text utils.
- The design for the `SessionChangedCallback` interface for `TerminalSession` has been majorly changed. Firstly, it has been renamed and moved from `TerminalSession` to the dedicated `TerminalSessionClient` class file. The interface now also supports the termux app centralized logging framework so that `TerminalSession` and `TerminalEmulator` can use them. Previously, `TermuxService` was implementing a wrapper interface, which would then call the real interface defined by the `TermuxActivity` if it was currently bound to the service. This cluttered and partially duplicated the code. Now, the implementation is defined by the `TermuxSessionClientBase` and `TermuxSessionClient` classes. The `TermuxSessionClientBase` implements the `TerminalSessionClient` interface but the definition of the activity related functions do not do anything, only the background ones like the logging functions are fully implemented. The `TermuxSessionClient` class inherits from the `TermuxSessionClientBase` class and provides the implementation for the activity related functions. The design for how this works is that if the `TermuxService` is not bound to `TermuxActivity`, it just passes the `TermuxSessionClientBase` implementation to `TerminalSession`. If the activity is bound at some point, then in `onServiceConnected()` it replaces/updates the client objects stored in `TerminalSession` and `TerminalEmulator` with `TermuxSessionClient`, and then replaces them back with `TermuxSessionClientBase` in `onDestroy()`. This seems to be working for now without an issue.
2021-03-16 00:01:09 +00:00
|
|
|
|
2021-03-13 11:49:29 +00:00
|
|
|
public class TermuxUtils {
|
|
|
|
|
2021-03-28 04:06:17 +00:00
|
|
|
/**
|
|
|
|
* Get the {@link Context} for {@link TermuxConstants#TERMUX_PACKAGE_NAME} package.
|
|
|
|
*
|
|
|
|
* @param context The {@link Context} to use to get the {@link Context} of the package.
|
|
|
|
* @return Returns the {@link Context}. This will {@code null} if an exception is raised.
|
|
|
|
*/
|
|
|
|
public static Context getTermuxPackageContext(@NonNull Context context) {
|
|
|
|
return PackageUtils.getContextForPackage(context, TermuxConstants.TERMUX_PACKAGE_NAME);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the {@link Context} for {@link TermuxConstants#TERMUX_API_PACKAGE_NAME} package.
|
|
|
|
*
|
|
|
|
* @param context The {@link Context} to use to get the {@link Context} of the package.
|
|
|
|
* @return Returns the {@link Context}. This will {@code null} if an exception is raised.
|
|
|
|
*/
|
|
|
|
public static Context getTermuxAPIPackageContext(@NonNull Context context) {
|
|
|
|
return PackageUtils.getContextForPackage(context, TermuxConstants.TERMUX_API_PACKAGE_NAME);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the {@link Context} for {@link TermuxConstants#TERMUX_BOOT_PACKAGE_NAME} package.
|
|
|
|
*
|
|
|
|
* @param context The {@link Context} to use to get the {@link Context} of the package.
|
|
|
|
* @return Returns the {@link Context}. This will {@code null} if an exception is raised.
|
|
|
|
*/
|
|
|
|
public static Context getTermuxBootPackageContext(@NonNull Context context) {
|
|
|
|
return PackageUtils.getContextForPackage(context, TermuxConstants.TERMUX_BOOT_PACKAGE_NAME);
|
2021-03-13 11:49:29 +00:00
|
|
|
}
|
Refactor TermuxActivity
This commit majorly refactors `TermuxActivity` and moves its view components and functions into dedicated classes.
- The view layouts and ids have been given meaningful names, like `termux_activity.xml`.
- The `TerminalToolbarViewPager` class has been created to handle the now called toolbar that shows on the bottom of the terminal view. It currently contains extra keys view defined by `terminal_toolbar_extra_keys_view.xml` file and a text input view defined by `terminal_toolbar_text_input_view.xml` file when user can switch to by swiping left. The input text will now be preserved if android destroys the activity or its recreated.
- The `TermuxSessionsListViewController` class has been created to handle view related functionality of the termux sessions list shown in the left drawer, namely view creation, `onItemClick()`, `onItemLongClick()`, etc. Its list view is defined by `termux_activity.xml` file and each item's layout is defined by the `terminal_sessions_list_item.xml` file.
- The `TextDataUtils` class has been added to the `com.termux.app.utils` package for text utils.
- The design for the `SessionChangedCallback` interface for `TerminalSession` has been majorly changed. Firstly, it has been renamed and moved from `TerminalSession` to the dedicated `TerminalSessionClient` class file. The interface now also supports the termux app centralized logging framework so that `TerminalSession` and `TerminalEmulator` can use them. Previously, `TermuxService` was implementing a wrapper interface, which would then call the real interface defined by the `TermuxActivity` if it was currently bound to the service. This cluttered and partially duplicated the code. Now, the implementation is defined by the `TermuxSessionClientBase` and `TermuxSessionClient` classes. The `TermuxSessionClientBase` implements the `TerminalSessionClient` interface but the definition of the activity related functions do not do anything, only the background ones like the logging functions are fully implemented. The `TermuxSessionClient` class inherits from the `TermuxSessionClientBase` class and provides the implementation for the activity related functions. The design for how this works is that if the `TermuxService` is not bound to `TermuxActivity`, it just passes the `TermuxSessionClientBase` implementation to `TerminalSession`. If the activity is bound at some point, then in `onServiceConnected()` it replaces/updates the client objects stored in `TerminalSession` and `TerminalEmulator` with `TermuxSessionClient`, and then replaces them back with `TermuxSessionClientBase` in `onDestroy()`. This seems to be working for now without an issue.
2021-03-16 00:01:09 +00:00
|
|
|
|
2021-03-28 04:06:17 +00:00
|
|
|
/**
|
|
|
|
* Get the {@link Context} for {@link TermuxConstants#TERMUX_FLOAT_PACKAGE_NAME} package.
|
|
|
|
*
|
|
|
|
* @param context The {@link Context} to use to get the {@link Context} of the package.
|
|
|
|
* @return Returns the {@link Context}. This will {@code null} if an exception is raised.
|
|
|
|
*/
|
|
|
|
public static Context getTermuxFloatPackageContext(@NonNull Context context) {
|
|
|
|
return PackageUtils.getContextForPackage(context, TermuxConstants.TERMUX_FLOAT_PACKAGE_NAME);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the {@link Context} for {@link TermuxConstants#TERMUX_STYLING_PACKAGE_NAME} package.
|
|
|
|
*
|
|
|
|
* @param context The {@link Context} to use to get the {@link Context} of the package.
|
|
|
|
* @return Returns the {@link Context}. This will {@code null} if an exception is raised.
|
|
|
|
*/
|
|
|
|
public static Context getTermuxStylingPackageContext(@NonNull Context context) {
|
|
|
|
return PackageUtils.getContextForPackage(context, TermuxConstants.TERMUX_STYLING_PACKAGE_NAME);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the {@link Context} for {@link TermuxConstants#TERMUX_TASKER_PACKAGE_NAME} package.
|
|
|
|
*
|
|
|
|
* @param context The {@link Context} to use to get the {@link Context} of the package.
|
|
|
|
* @return Returns the {@link Context}. This will {@code null} if an exception is raised.
|
|
|
|
*/
|
|
|
|
public static Context getTermuxTaskerPackageContext(@NonNull Context context) {
|
|
|
|
return PackageUtils.getContextForPackage(context, TermuxConstants.TERMUX_TASKER_PACKAGE_NAME);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the {@link Context} for {@link TermuxConstants#TERMUX_WIDGET_PACKAGE_NAME} package.
|
|
|
|
*
|
|
|
|
* @param context The {@link Context} to use to get the {@link Context} of the package.
|
|
|
|
* @return Returns the {@link Context}. This will {@code null} if an exception is raised.
|
|
|
|
*/
|
|
|
|
public static Context getTermuxWidgetPackageContext(@NonNull Context context) {
|
|
|
|
return PackageUtils.getContextForPackage(context, TermuxConstants.TERMUX_WIDGET_PACKAGE_NAME);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
Refactor TermuxActivity
This commit majorly refactors `TermuxActivity` and moves its view components and functions into dedicated classes.
- The view layouts and ids have been given meaningful names, like `termux_activity.xml`.
- The `TerminalToolbarViewPager` class has been created to handle the now called toolbar that shows on the bottom of the terminal view. It currently contains extra keys view defined by `terminal_toolbar_extra_keys_view.xml` file and a text input view defined by `terminal_toolbar_text_input_view.xml` file when user can switch to by swiping left. The input text will now be preserved if android destroys the activity or its recreated.
- The `TermuxSessionsListViewController` class has been created to handle view related functionality of the termux sessions list shown in the left drawer, namely view creation, `onItemClick()`, `onItemLongClick()`, etc. Its list view is defined by `termux_activity.xml` file and each item's layout is defined by the `terminal_sessions_list_item.xml` file.
- The `TextDataUtils` class has been added to the `com.termux.app.utils` package for text utils.
- The design for the `SessionChangedCallback` interface for `TerminalSession` has been majorly changed. Firstly, it has been renamed and moved from `TerminalSession` to the dedicated `TerminalSessionClient` class file. The interface now also supports the termux app centralized logging framework so that `TerminalSession` and `TerminalEmulator` can use them. Previously, `TermuxService` was implementing a wrapper interface, which would then call the real interface defined by the `TermuxActivity` if it was currently bound to the service. This cluttered and partially duplicated the code. Now, the implementation is defined by the `TermuxSessionClientBase` and `TermuxSessionClient` classes. The `TermuxSessionClientBase` implements the `TerminalSessionClient` interface but the definition of the activity related functions do not do anything, only the background ones like the logging functions are fully implemented. The `TermuxSessionClient` class inherits from the `TermuxSessionClientBase` class and provides the implementation for the activity related functions. The design for how this works is that if the `TermuxService` is not bound to `TermuxActivity`, it just passes the `TermuxSessionClientBase` implementation to `TerminalSession`. If the activity is bound at some point, then in `onServiceConnected()` it replaces/updates the client objects stored in `TerminalSession` and `TerminalEmulator` with `TermuxSessionClient`, and then replaces them back with `TermuxSessionClientBase` in `onDestroy()`. This seems to be working for now without an issue.
2021-03-16 00:01:09 +00:00
|
|
|
/**
|
|
|
|
* Send the {@link TermuxConstants#BROADCAST_TERMUX_OPENED} broadcast to notify apps that Termux
|
|
|
|
* app has been opened.
|
|
|
|
*
|
|
|
|
* @param context The Context to send the broadcast.
|
|
|
|
*/
|
2021-03-28 04:06:17 +00:00
|
|
|
public static void sendTermuxOpenedBroadcast(@NonNull Context context) {
|
|
|
|
if (context == null) return;
|
|
|
|
|
Refactor TermuxActivity
This commit majorly refactors `TermuxActivity` and moves its view components and functions into dedicated classes.
- The view layouts and ids have been given meaningful names, like `termux_activity.xml`.
- The `TerminalToolbarViewPager` class has been created to handle the now called toolbar that shows on the bottom of the terminal view. It currently contains extra keys view defined by `terminal_toolbar_extra_keys_view.xml` file and a text input view defined by `terminal_toolbar_text_input_view.xml` file when user can switch to by swiping left. The input text will now be preserved if android destroys the activity or its recreated.
- The `TermuxSessionsListViewController` class has been created to handle view related functionality of the termux sessions list shown in the left drawer, namely view creation, `onItemClick()`, `onItemLongClick()`, etc. Its list view is defined by `termux_activity.xml` file and each item's layout is defined by the `terminal_sessions_list_item.xml` file.
- The `TextDataUtils` class has been added to the `com.termux.app.utils` package for text utils.
- The design for the `SessionChangedCallback` interface for `TerminalSession` has been majorly changed. Firstly, it has been renamed and moved from `TerminalSession` to the dedicated `TerminalSessionClient` class file. The interface now also supports the termux app centralized logging framework so that `TerminalSession` and `TerminalEmulator` can use them. Previously, `TermuxService` was implementing a wrapper interface, which would then call the real interface defined by the `TermuxActivity` if it was currently bound to the service. This cluttered and partially duplicated the code. Now, the implementation is defined by the `TermuxSessionClientBase` and `TermuxSessionClient` classes. The `TermuxSessionClientBase` implements the `TerminalSessionClient` interface but the definition of the activity related functions do not do anything, only the background ones like the logging functions are fully implemented. The `TermuxSessionClient` class inherits from the `TermuxSessionClientBase` class and provides the implementation for the activity related functions. The design for how this works is that if the `TermuxService` is not bound to `TermuxActivity`, it just passes the `TermuxSessionClientBase` implementation to `TerminalSession`. If the activity is bound at some point, then in `onServiceConnected()` it replaces/updates the client objects stored in `TerminalSession` and `TerminalEmulator` with `TermuxSessionClient`, and then replaces them back with `TermuxSessionClientBase` in `onDestroy()`. This seems to be working for now without an issue.
2021-03-16 00:01:09 +00:00
|
|
|
Intent broadcast = new Intent(TermuxConstants.BROADCAST_TERMUX_OPENED);
|
|
|
|
List<ResolveInfo> matches = context.getPackageManager().queryBroadcastReceivers(broadcast, 0);
|
|
|
|
|
|
|
|
// send broadcast to registered Termux receivers
|
|
|
|
// this technique is needed to work around broadcast changes that Oreo introduced
|
|
|
|
for (ResolveInfo info : matches) {
|
|
|
|
Intent explicitBroadcast = new Intent(broadcast);
|
|
|
|
ComponentName cname = new ComponentName(info.activityInfo.applicationInfo.packageName,
|
|
|
|
info.activityInfo.name);
|
|
|
|
explicitBroadcast.setComponent(cname);
|
|
|
|
context.sendBroadcast(explicitBroadcast);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-23 21:38:37 +00:00
|
|
|
/**
|
2021-03-28 04:06:17 +00:00
|
|
|
* Get a markdown {@link String} for the app info. If the {@code context} passed is different
|
|
|
|
* from the {@link TermuxConstants#TERMUX_PACKAGE_NAME} package context, then this function
|
|
|
|
* must have been called by a different package like a plugin, so we return info for both packages
|
|
|
|
* if {@code returnTermuxPackageInfoToo} is {@code true}.
|
|
|
|
*
|
|
|
|
* @param currentPackageContext The context of current package.
|
|
|
|
* @param returnTermuxPackageInfoToo If set to {@code true}, then will return info of the
|
|
|
|
* {@link TermuxConstants#TERMUX_PACKAGE_NAME} package as well if its different from current package.
|
|
|
|
* @return Returns the markdown {@link String}.
|
|
|
|
*/
|
|
|
|
public static String getAppInfoMarkdownString(@NonNull final Context currentPackageContext, final boolean returnTermuxPackageInfoToo) {
|
|
|
|
if (currentPackageContext == null) return "null";
|
|
|
|
|
|
|
|
StringBuilder markdownString = new StringBuilder();
|
|
|
|
|
|
|
|
Context termuxPackageContext = getTermuxPackageContext(currentPackageContext);
|
|
|
|
|
|
|
|
String termuxPackageName = null;
|
|
|
|
String termuxAppName = null;
|
|
|
|
if(termuxPackageContext != null) {
|
|
|
|
termuxPackageName = PackageUtils.getPackageNameForPackage(termuxPackageContext);
|
|
|
|
termuxAppName = PackageUtils.getAppNameForPackage(termuxPackageContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
String currentPackageName = PackageUtils.getPackageNameForPackage(currentPackageContext);
|
|
|
|
String currentAppName = PackageUtils.getAppNameForPackage(currentPackageContext);
|
|
|
|
|
|
|
|
boolean isTermuxPackage = (termuxPackageName != null && termuxPackageName.equals(currentPackageName));
|
|
|
|
|
|
|
|
|
|
|
|
if(returnTermuxPackageInfoToo && !isTermuxPackage)
|
|
|
|
markdownString.append("## ").append(currentAppName).append(" App Info (Current)\n");
|
|
|
|
else
|
|
|
|
markdownString.append("## ").append(currentAppName).append(" App Info\n");
|
|
|
|
markdownString.append(getAppInfoMarkdownStringInner(currentPackageContext));
|
|
|
|
|
|
|
|
if(returnTermuxPackageInfoToo && !isTermuxPackage) {
|
|
|
|
markdownString.append("\n\n## ").append(termuxAppName).append(" App Info\n");
|
|
|
|
markdownString.append(getAppInfoMarkdownStringInner(termuxPackageContext));
|
|
|
|
}
|
|
|
|
|
|
|
|
markdownString.append("\n##\n");
|
|
|
|
|
|
|
|
return markdownString.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a markdown {@link String} for the app info for the package associated with the {@code context}.
|
|
|
|
*
|
|
|
|
* @param context The context for operations for the package.
|
|
|
|
* @return Returns the markdown {@link String}.
|
|
|
|
*/
|
|
|
|
public static String getAppInfoMarkdownStringInner(@NonNull final Context context) {
|
|
|
|
StringBuilder markdownString = new StringBuilder();
|
|
|
|
|
|
|
|
appendPropertyToMarkdown(markdownString,"APP_NAME", PackageUtils.getAppNameForPackage(context));
|
|
|
|
appendPropertyToMarkdown(markdownString,"PACKAGE_NAME", PackageUtils.getPackageNameForPackage(context));
|
|
|
|
appendPropertyToMarkdown(markdownString,"VERSION_NAME", PackageUtils.getVersionNameForPackage(context));
|
|
|
|
appendPropertyToMarkdown(markdownString,"VERSION_CODE", PackageUtils.getVersionCodeForPackage(context));
|
|
|
|
appendPropertyToMarkdown(markdownString,"TARGET_SDK", PackageUtils.getTargetSDKForPackage(context));
|
|
|
|
appendPropertyToMarkdown(markdownString,"IS_DEBUG_BUILD", PackageUtils.isAppForPackageADebugBuild(context));
|
|
|
|
|
|
|
|
return markdownString.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a markdown {@link String} for the device info.
|
2021-03-23 21:38:37 +00:00
|
|
|
*
|
|
|
|
* @param context The context for operations.
|
|
|
|
* @return Returns the markdown {@link String}.
|
|
|
|
*/
|
2021-03-28 04:06:17 +00:00
|
|
|
public static String getDeviceInfoMarkdownString(@NonNull final Context context) {
|
2021-03-23 21:38:37 +00:00
|
|
|
if (context == null) return "null";
|
|
|
|
|
|
|
|
// Some properties cannot be read with {@link System#getProperty(String)} but can be read
|
|
|
|
// directly by running getprop command
|
|
|
|
Properties systemProperties = getSystemProperties();
|
|
|
|
|
|
|
|
StringBuilder markdownString = new StringBuilder();
|
|
|
|
|
2021-03-28 04:06:17 +00:00
|
|
|
markdownString.append("## Device Info");
|
|
|
|
|
|
|
|
markdownString.append("\n\n### Software\n");
|
|
|
|
appendPropertyToMarkdown(markdownString,"OS_VERSION", getSystemPropertyWithAndroidAPI("os.version"));
|
|
|
|
appendPropertyToMarkdown(markdownString, "SDK_INT", Build.VERSION.SDK_INT);
|
2021-03-23 21:38:37 +00:00
|
|
|
// If its a release version
|
|
|
|
if ("REL".equals(Build.VERSION.CODENAME))
|
2021-03-28 04:06:17 +00:00
|
|
|
appendPropertyToMarkdown(markdownString, "RELEASE", Build.VERSION.RELEASE);
|
2021-03-23 21:38:37 +00:00
|
|
|
else
|
2021-03-28 04:06:17 +00:00
|
|
|
appendPropertyToMarkdown(markdownString, "CODENAME", Build.VERSION.CODENAME);
|
|
|
|
appendPropertyToMarkdown(markdownString, "INCREMENTAL", Build.VERSION.INCREMENTAL);
|
|
|
|
appendPropertyToMarkdownIfSet(markdownString, "SECURITY_PATCH", systemProperties.getProperty("ro.build.version.security_patch"));
|
|
|
|
appendPropertyToMarkdownIfSet(markdownString, "IS_DEBUGGABLE", systemProperties.getProperty("ro.debuggable"));
|
|
|
|
appendPropertyToMarkdownIfSet(markdownString, "IS_EMULATOR", systemProperties.getProperty("ro.boot.qemu"));
|
|
|
|
appendPropertyToMarkdownIfSet(markdownString, "IS_TREBLE_ENABLED", systemProperties.getProperty("ro.treble.enabled"));
|
|
|
|
appendPropertyToMarkdown(markdownString, "TYPE", Build.TYPE);
|
|
|
|
appendPropertyToMarkdown(markdownString, "TAGS", Build.TAGS);
|
|
|
|
|
|
|
|
markdownString.append("\n\n### Hardware\n");
|
|
|
|
appendPropertyToMarkdown(markdownString, "MANUFACTURER", Build.MANUFACTURER);
|
|
|
|
appendPropertyToMarkdown(markdownString, "BRAND", Build.BRAND);
|
|
|
|
appendPropertyToMarkdown(markdownString, "MODEL", Build.MODEL);
|
|
|
|
appendPropertyToMarkdown(markdownString, "PRODUCT", Build.PRODUCT);
|
|
|
|
appendPropertyToMarkdown(markdownString, "DISPLAY", Build.DISPLAY);
|
|
|
|
appendPropertyToMarkdown(markdownString, "ID", Build.ID);
|
|
|
|
appendPropertyToMarkdown(markdownString, "BOARD", Build.BOARD);
|
|
|
|
appendPropertyToMarkdown(markdownString, "HARDWARE", Build.HARDWARE);
|
|
|
|
appendPropertyToMarkdown(markdownString, "DEVICE", Build.DEVICE);
|
|
|
|
appendPropertyToMarkdown(markdownString, "SUPPORTED_ABIS", Joiner.on(", ").skipNulls().join(Build.SUPPORTED_ABIS));
|
|
|
|
|
|
|
|
markdownString.append("\n##\n");
|
2021-03-23 21:38:37 +00:00
|
|
|
|
|
|
|
return markdownString.toString();
|
|
|
|
}
|
|
|
|
|
Implement crash handler and reporting
Now whenever the Termux app crashes, the crash report (stacktrace, app and device info) will be logged to ~/crash_log.md file. When the user will reopen the app, a notification will be shown which when clicked will show the crash report content in the ReportActivity. The activity will have important links like email, reddit, github issues of termux app and packages at which the user can optionally report an issue if necessary after copying the crash report text. The ~/crash_log.md file will be moved to ~/crash_log-backup.md so that a notification is not shown again on next startup and can be viewed again via SAF, etc.
This will allow reports for bugs that are submitted to have complete and useful info, specially in markdown format, making lives of devs a tad bit easier. Also more bugs that are rare might be submitted since users will have the info to report with and know where to report at.
ToDo:
- The TermuxConstants.TERMUX_SUPPORT_EMAIL_URL needs to be updated with a valid support email once its set up. The TermuxUtils.getReportIssueMarkdownString() function currently also has "email" lines commented out which will need to be uncommented.
- Currently, crashes will only be handled for the main app thread, other threads will have to manually hooked into where necessary.
2021-04-06 11:15:00 +00:00
|
|
|
/**
|
|
|
|
* Get a markdown {@link String} for reporting an issue.
|
|
|
|
*
|
|
|
|
* @param context The context for operations.
|
|
|
|
* @return Returns the markdown {@link String}.
|
|
|
|
*/
|
|
|
|
public static String getReportIssueMarkdownString(@NonNull final Context context) {
|
|
|
|
if (context == null) return "null";
|
|
|
|
|
|
|
|
StringBuilder markdownString = new StringBuilder();
|
|
|
|
|
2021-04-06 12:09:54 +00:00
|
|
|
markdownString.append("## Where To Report An Issue");
|
Implement crash handler and reporting
Now whenever the Termux app crashes, the crash report (stacktrace, app and device info) will be logged to ~/crash_log.md file. When the user will reopen the app, a notification will be shown which when clicked will show the crash report content in the ReportActivity. The activity will have important links like email, reddit, github issues of termux app and packages at which the user can optionally report an issue if necessary after copying the crash report text. The ~/crash_log.md file will be moved to ~/crash_log-backup.md so that a notification is not shown again on next startup and can be viewed again via SAF, etc.
This will allow reports for bugs that are submitted to have complete and useful info, specially in markdown format, making lives of devs a tad bit easier. Also more bugs that are rare might be submitted since users will have the info to report with and know where to report at.
ToDo:
- The TermuxConstants.TERMUX_SUPPORT_EMAIL_URL needs to be updated with a valid support email once its set up. The TermuxUtils.getReportIssueMarkdownString() function currently also has "email" lines commented out which will need to be uncommented.
- Currently, crashes will only be handled for the main app thread, other threads will have to manually hooked into where necessary.
2021-04-06 11:15:00 +00:00
|
|
|
|
|
|
|
markdownString.append("\n\n").append(context.getString(R.string.msg_report_issue)).append("\n");
|
|
|
|
|
|
|
|
//markdownString.append("\n\n### Email\n");
|
|
|
|
//markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_SUPPORT_EMAIL, TermuxConstants.TERMUX_SUPPORT_EMAIL_MAILTO_URL)).append(" ");
|
|
|
|
|
|
|
|
markdownString.append("\n\n### Reddit\n");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_REDDIT_SUBREDDIT, TermuxConstants.TERMUX_REDDIT_SUBREDDIT_URL)).append(" ");
|
|
|
|
|
|
|
|
markdownString.append("\n\n### Github Issues for Termux apps\n");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_APP_NAME, TermuxConstants.TERMUX_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_API_APP_NAME, TermuxConstants.TERMUX_API_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_BOOT_APP_NAME, TermuxConstants.TERMUX_BOOT_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_FLOAT_APP_NAME, TermuxConstants.TERMUX_FLOAT_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_STYLING_APP_NAME, TermuxConstants.TERMUX_STYLING_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_TASKER_APP_NAME, TermuxConstants.TERMUX_TASKER_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_WIDGET_APP_NAME, TermuxConstants.TERMUX_WIDGET_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
|
|
|
|
markdownString.append("\n\n### Github Issues for Termux packages\n");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_PACKAGES_GITHUB_REPO_NAME, TermuxConstants.TERMUX_PACKAGES_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_GAME_PACKAGES_GITHUB_REPO_NAME, TermuxConstants.TERMUX_GAME_PACKAGES_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_SCIENCE_PACKAGES_GITHUB_REPO_NAME, TermuxConstants.TERMUX_SCIENCE_PACKAGES_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_ROOT_PACKAGES_GITHUB_REPO_NAME, TermuxConstants.TERMUX_ROOT_PACKAGES_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_UNSTABLE_PACKAGES_GITHUB_REPO_NAME, TermuxConstants.TERMUX_UNSTABLE_PACKAGES_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
markdownString.append("\n").append(MarkdownUtils.getLinkMarkdownString(TermuxConstants.TERMUX_X11_PACKAGES_GITHUB_REPO_NAME, TermuxConstants.TERMUX_X11_PACKAGES_GITHUB_ISSUES_REPO_URL)).append(" ");
|
|
|
|
|
|
|
|
markdownString.append("\n##\n");
|
|
|
|
|
|
|
|
return markdownString.toString();
|
|
|
|
}
|
|
|
|
|
2021-03-23 21:38:37 +00:00
|
|
|
public static Properties getSystemProperties() {
|
|
|
|
Properties systemProperties = new Properties();
|
|
|
|
|
|
|
|
// getprop commands returns values in the format `[key]: [value]`
|
|
|
|
// Regex matches string starting with a literal `[`,
|
|
|
|
// followed by one or more characters that do not match a closing square bracket as the key,
|
|
|
|
// followed by a literal `]: [`,
|
|
|
|
// followed by one or more characters as the value,
|
|
|
|
// followed by string ending with literal `]`
|
|
|
|
// multiline values will be ignored
|
|
|
|
Pattern propertiesPattern = Pattern.compile("^\\[([^]]+)]: \\[(.+)]$");
|
|
|
|
|
|
|
|
try {
|
|
|
|
Process process = new ProcessBuilder()
|
|
|
|
.command("/system/bin/getprop")
|
|
|
|
.redirectErrorStream(true)
|
|
|
|
.start();
|
|
|
|
|
|
|
|
InputStream inputStream = process.getInputStream();
|
|
|
|
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
|
|
|
|
String line, key, value;
|
|
|
|
|
|
|
|
while ((line = bufferedReader.readLine()) != null) {
|
|
|
|
Matcher matcher = propertiesPattern.matcher(line);
|
|
|
|
if (matcher.matches()) {
|
|
|
|
key = matcher.group(1);
|
|
|
|
value = matcher.group(2);
|
|
|
|
if(key != null && value != null && !key.isEmpty() && !value.isEmpty())
|
|
|
|
systemProperties.put(key, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bufferedReader.close();
|
|
|
|
process.destroy();
|
|
|
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
Logger.logStackTraceWithMessage("Failed to get run \"/system/bin/getprop\" to get system properties.", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
//for (String key : systemProperties.stringPropertyNames()) {
|
|
|
|
// Logger.logVerbose(key + ": " + systemProperties.get(key));
|
|
|
|
//}
|
|
|
|
|
|
|
|
return systemProperties;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static String getSystemPropertyWithAndroidAPI(@NonNull String property) {
|
|
|
|
try {
|
|
|
|
return System.getProperty(property);
|
|
|
|
} catch (Exception e) {
|
|
|
|
Logger.logVerbose("Failed to get system property \"" + property + "\":" + e.getMessage());
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-28 04:06:17 +00:00
|
|
|
private static void appendPropertyToMarkdownIfSet(StringBuilder markdownString, String label, Object value) {
|
2021-03-23 21:38:37 +00:00
|
|
|
if(value == null) return;
|
|
|
|
if(value instanceof String && (((String) value).isEmpty()) || "REL".equals(value)) return;
|
|
|
|
markdownString.append("\n").append(getPropertyMarkdown(label, value));
|
|
|
|
}
|
|
|
|
|
2021-03-28 04:06:17 +00:00
|
|
|
private static void appendPropertyToMarkdown(StringBuilder markdownString, String label, Object value) {
|
2021-03-23 21:38:37 +00:00
|
|
|
markdownString.append("\n").append(getPropertyMarkdown(label, value));
|
|
|
|
}
|
|
|
|
|
|
|
|
private static String getPropertyMarkdown(String label, Object value) {
|
|
|
|
return MarkdownUtils.getSingleLineMarkdownStringEntry(label, value, "-");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static String getCurrentTimeStamp() {
|
|
|
|
@SuppressLint("SimpleDateFormat")
|
Implement crash handler and reporting
Now whenever the Termux app crashes, the crash report (stacktrace, app and device info) will be logged to ~/crash_log.md file. When the user will reopen the app, a notification will be shown which when clicked will show the crash report content in the ReportActivity. The activity will have important links like email, reddit, github issues of termux app and packages at which the user can optionally report an issue if necessary after copying the crash report text. The ~/crash_log.md file will be moved to ~/crash_log-backup.md so that a notification is not shown again on next startup and can be viewed again via SAF, etc.
This will allow reports for bugs that are submitted to have complete and useful info, specially in markdown format, making lives of devs a tad bit easier. Also more bugs that are rare might be submitted since users will have the info to report with and know where to report at.
ToDo:
- The TermuxConstants.TERMUX_SUPPORT_EMAIL_URL needs to be updated with a valid support email once its set up. The TermuxUtils.getReportIssueMarkdownString() function currently also has "email" lines commented out which will need to be uncommented.
- Currently, crashes will only be handled for the main app thread, other threads will have to manually hooked into where necessary.
2021-04-06 11:15:00 +00:00
|
|
|
final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
|
2021-03-23 21:38:37 +00:00
|
|
|
df.setTimeZone(TimeZone.getTimeZone("UTC"));
|
|
|
|
return df.format(new Date());
|
|
|
|
}
|
|
|
|
|
2021-03-13 11:49:29 +00:00
|
|
|
}
|