Added: Add isTermuxAppInstalled() and isTermuxAppAccessible() functions to TermuxUtils

The `TermuxUtils.isTermuxAppInstalled()` function can be used by external apps to check if termux app is installed and enabled.

The `TermuxUtils.isTermuxAppAccessible()` function can be used by termux plugin apps to check if termux app is installed, enabled, accessible as per `sharedUserId` and `TERMUX_PREFIX_DIR_PATH` is accessible and has read, write and execute permission.
This commit is contained in:
agnostic-apollo
2021-09-04 08:06:54 +05:00
parent 4e5f2c7e01
commit e5c0548942
2 changed files with 97 additions and 0 deletions

View File

@@ -3,11 +3,14 @@ package com.termux.shared.termux;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.termux.shared.R; import com.termux.shared.R;
import com.termux.shared.file.FileUtils;
import com.termux.shared.file.TermuxFileUtils; import com.termux.shared.file.TermuxFileUtils;
import com.termux.shared.logger.Logger; import com.termux.shared.logger.Logger;
import com.termux.shared.markdown.MarkdownUtils; import com.termux.shared.markdown.MarkdownUtils;
@@ -101,6 +104,90 @@ public class TermuxUtils {
/**
* Check if Termux app is installed and enabled. This can be used by external apps that don't
* share `sharedUserId` with the Termux app.
*
* If your third-party app is targeting sdk `30` (android `11`), then it needs to add `com.termux`
* package to the `queries` element or request `QUERY_ALL_PACKAGES` permission in its
* `AndroidManifest.xml`. Otherwise it will get `PackageSetting{...... com.termux/......} BLOCKED`
* errors in `logcat` and `RUN_COMMAND` won't work.
* Check [package-visibility](https://developer.android.com/training/basics/intents/package-visibility#package-name),
* `QUERY_ALL_PACKAGES` [googleplay policy](https://support.google.com/googleplay/android-developer/answer/10158779
* and this [article](https://medium.com/androiddevelopers/working-with-package-visibility-dc252829de2d) for more info.
*
* {@code
* <manifest
* <queries>
* <package android:name="com.termux" />
* </queries>
* </manifest>
* }
*
* @param currentPackageContext The context of current package.
* @return Returns {@code errmsg} if termux package is not installed or disabled, otherwise {@code null}.
*/
public static String isTermuxAppInstalled(@NonNull final Context currentPackageContext) {
String errmsg = null;
PackageManager packageManager = currentPackageContext.getPackageManager();
ApplicationInfo applicationInfo;
try {
applicationInfo = packageManager.getApplicationInfo(TermuxConstants.TERMUX_PACKAGE_NAME, 0);
} catch (final PackageManager.NameNotFoundException e) {
applicationInfo = null;
}
boolean termuxAppEnabled = (applicationInfo != null && applicationInfo.enabled);
// If Termux app is not installed or is disabled
if (!termuxAppEnabled)
errmsg = currentPackageContext.getString(R.string.error_termux_app_not_installed_or_disabled_warning);
return errmsg;
}
/**
* Check if Termux app is installed and accessible. This can only be used by apps that share
* `sharedUserId` with the Termux app.
*
* This is done by checking if first checking if app is installed and enabled and then if
* {@code currentPackageContext} can be used to get the {@link Context} of the app with
* {@link TermuxConstants#TERMUX_PACKAGE_NAME} and then if
* {@link TermuxConstants#TERMUX_PREFIX_DIR_PATH} exists and has
* {@link FileUtils#APP_WORKING_DIRECTORY_PERMISSIONS} permissions. The directory will not
* be automatically created and neither the missing permissions automatically set.
*
* @param currentPackageContext The context of current package.
* @return Returns {@code errmsg} if failed to get termux package {@link Context} or
* {@link TermuxConstants#TERMUX_PREFIX_DIR_PATH} is accessible, otherwise {@code null}.
*/
public static String isTermuxAppAccessible(@NonNull final Context currentPackageContext) {
String errmsg = isTermuxAppInstalled(currentPackageContext);
if (errmsg == null) {
Context termuxPackageContext = TermuxUtils.getTermuxPackageContext(currentPackageContext);
// If failed to get Termux app package context
if (termuxPackageContext == null)
errmsg = currentPackageContext.getString(R.string.error_termux_app_package_context_not_accessible);
if (errmsg == null) {
// If TermuxConstants.TERMUX_PREFIX_DIR_PATH is not a directory or does not have required permissions
Error error = TermuxFileUtils.isTermuxPrefixDirectoryAccessible(false, false);
if (error != null)
errmsg = currentPackageContext.getString(R.string.error_termux_prefix_dir_path_not_accessible,
PackageUtils.getAppNameForPackage(currentPackageContext));
}
}
if (errmsg != null)
return errmsg + " " + currentPackageContext.getString(R.string.msg_termux_app_required_by_app,
PackageUtils.getAppNameForPackage(currentPackageContext));
else
return null;
}
/** /**
* Send the {@link TermuxConstants#BROADCAST_TERMUX_OPENED} broadcast to notify apps that Termux * Send the {@link TermuxConstants#BROADCAST_TERMUX_OPENED} broadcast to notify apps that Termux
* app has been opened. * app has been opened.

View File

@@ -9,6 +9,7 @@
<!ENTITY TERMUX_STYLING_APP_NAME "Termux:Styling"> <!ENTITY TERMUX_STYLING_APP_NAME "Termux:Styling">
<!ENTITY TERMUX_TASKER_APP_NAME "Termux:Tasker"> <!ENTITY TERMUX_TASKER_APP_NAME "Termux:Tasker">
<!ENTITY TERMUX_WIDGET_APP_NAME "Termux:Widget"> <!ENTITY TERMUX_WIDGET_APP_NAME "Termux:Widget">
<!ENTITY TERMUX_PREFIX_DIR_PATH "/data/data/com.termux/files/usr">
]> ]>
<resources> <resources>
@@ -71,6 +72,15 @@
on github or other official termux community forums **will likely be automatically closed/deleted** and may on github or other official termux community forums **will likely be automatically closed/deleted** and may
even result in **temporary or permanent** ban. Check %1$s/wiki/Hacking for details.</string> even result in **temporary or permanent** ban. Check %1$s/wiki/Hacking for details.</string>
<string name="msg_termux_app_required_by_app">The &TERMUX_APP_NAME; is required by the %1$s app to run termux commands."</string>
<string name="error_termux_app_not_installed_or_disabled_warning">The &TERMUX_APP_NAME; app is not installed or is disabled."</string>
<string name="error_termux_app_package_context_not_accessible">The &TERMUX_APP_NAME; app (package context) is not accessible."</string>
<string name="error_termux_prefix_dir_path_not_accessible">The &TERMUX_APP_NAME; app $PREFIX directory is not accessible by the %1$s app.
This may be because you have not installed or setup &TERMUX_APP_NAME; app or
&TERMUX_APP_NAME; app and %1$s app both have different APK signatures because you have managed to install both apps from different sources.
It may also be because &TERMUX_APP_NAME; $PREFIX directory \"&TERMUX_PREFIX_DIR_PATH;\" does not exist or does not have read,
write and execute permissions."</string>
<!-- Miscellaneous --> <!-- Miscellaneous -->