Skip to content

Commit

Permalink
Added: Add isTermuxAppInstalled() and isTermuxAppAccessible() functio…
Browse files Browse the repository at this point in the history
…ns 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.
  • Loading branch information
agnostic-apollo committed Sep 4, 2021
1 parent 4e5f2c7 commit e5c0548
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;

import androidx.annotation.NonNull;

import com.termux.shared.R;
import com.termux.shared.file.FileUtils;
import com.termux.shared.file.TermuxFileUtils;
import com.termux.shared.logger.Logger;
import com.termux.shared.markdown.MarkdownUtils;
Expand Down Expand Up @@ -101,6 +104,90 @@ public static Context getTermuxWidgetPackageContext(@NonNull Context context) {



/**
* 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
* app has been opened.
Expand Down
10 changes: 10 additions & 0 deletions termux-shared/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<!ENTITY TERMUX_STYLING_APP_NAME "Termux:Styling">
<!ENTITY TERMUX_TASKER_APP_NAME "Termux:Tasker">
<!ENTITY TERMUX_WIDGET_APP_NAME "Termux:Widget">
<!ENTITY TERMUX_PREFIX_DIR_PATH "/data/data/com.termux/files/usr">
]>

<resources>
Expand Down Expand Up @@ -71,6 +72,15 @@
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>

<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 -->
Expand Down

0 comments on commit e5c0548

Please sign in to comment.