这是indexloc提供的服务,不要输入任何密码
Skip to content

Commit ba2836b

Browse files
Added: Request disable battery optimizations and grant draw over apps permission
Previously, the `REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` and `SYSTEM_ALERT_WINDOW` (draw over apps) permissions weren't requested by the `termux-api` app (only `termux-app`), so the options to disable/grant them wasn't shown in android settings. Moreover, `TermuxAPIActivity` have added warnings to request them if they have not been, in addition to vendor specific warnings, including link to https://dontkillmyapp.com.
1 parent c845650 commit ba2836b

File tree

5 files changed

+211
-2
lines changed

5 files changed

+211
-2
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@
2626
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
2727
<uses-permission android:name="android.permission.RECORD_AUDIO" />
2828
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
29+
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
2930
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
3031
<uses-permission android:name="android.permission.SEND_SMS" />
3132
<uses-permission android:name="android.permission.SET_WALLPAPER" />
33+
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
3234
<uses-permission android:name="android.permission.TRANSMIT_IR" />
3335
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
3436
<uses-permission android:name="android.permission.VIBRATE" />

app/src/main/java/com/termux/api/activities/TermuxAPIActivity.java

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@
55
import android.os.Environment;
66
import android.view.Menu;
77
import android.view.MenuItem;
8+
import android.widget.Button;
89
import android.widget.TextView;
910

1011
import androidx.appcompat.app.AppCompatActivity;
1112

13+
import com.termux.api.util.ViewUtils;
1214
import com.termux.shared.activities.ReportActivity;
1315
import com.termux.shared.activity.ActivityUtils;
1416
import com.termux.shared.activity.media.AppCompatActivityUtils;
1517
import com.termux.shared.android.AndroidUtils;
18+
import com.termux.shared.android.PermissionUtils;
19+
import com.termux.shared.data.IntentUtils;
1620
import com.termux.shared.file.FileUtils;
1721
import com.termux.shared.logger.Logger;
1822
import com.termux.shared.models.ReportInfo;
@@ -24,6 +28,12 @@
2428

2529
public class TermuxAPIActivity extends AppCompatActivity {
2630

31+
private TextView mBatteryOptimizationNotDisabledWarning;
32+
private TextView mDisplayOverOtherAppsPermissionNotGrantedWarning;
33+
34+
private Button mDisableBatteryOptimization;
35+
private Button mGrantDisplayOverOtherAppsPermission;
36+
2737
private static final String LOG_TAG = "TermuxAPIActivity";
2838

2939
@Override
@@ -44,8 +54,23 @@ protected void onCreate(Bundle savedInstanceState) {
4454
pluginInfo.setText(getString(R.string.plugin_info, TermuxConstants.TERMUX_GITHUB_REPO_URL,
4555
TermuxConstants.TERMUX_API_GITHUB_REPO_URL, TermuxConstants.TERMUX_API_APT_PACKAGE_NAME,
4656
TermuxConstants.TERMUX_API_APT_GITHUB_REPO_URL));
57+
58+
mBatteryOptimizationNotDisabledWarning = findViewById(R.id.textview_battery_optimization_not_disabled_warning);
59+
mDisableBatteryOptimization = findViewById(R.id.btn_disable_battery_optimizations);
60+
mDisableBatteryOptimization.setOnClickListener(v -> requestDisableBatteryOptimizations());
61+
62+
mDisplayOverOtherAppsPermissionNotGrantedWarning = findViewById(R.id.textview_display_over_other_apps_not_granted_warning);
63+
mGrantDisplayOverOtherAppsPermission = findViewById(R.id.btn_grant_display_over_other_apps_permission);
64+
mGrantDisplayOverOtherAppsPermission.setOnClickListener(v -> requestDisplayOverOtherAppsPermission());
4765
}
4866

67+
@Override
68+
protected void onResume() {
69+
super.onResume();
70+
71+
checkIfBatteryOptimizationNotDisabled();
72+
checkIfDisplayOverOtherAppsPermissionNotGranted();
73+
}
4974

5075
@Override
5176
public boolean onCreateOptionsMenu(Menu menu) {
@@ -92,6 +117,73 @@ public void run() {
92117
}.start();
93118
}
94119

120+
121+
122+
private void checkIfBatteryOptimizationNotDisabled() {
123+
if (mBatteryOptimizationNotDisabledWarning == null) return;
124+
125+
// If battery optimizations not disabled
126+
if (!PermissionUtils.checkIfBatteryOptimizationsDisabled(this)) {
127+
ViewUtils.setWarningTextViewAndButtonState(this, mBatteryOptimizationNotDisabledWarning,
128+
mDisableBatteryOptimization, true, getString(R.string.action_disable_battery_optimizations));
129+
} else {
130+
ViewUtils.setWarningTextViewAndButtonState(this, mBatteryOptimizationNotDisabledWarning,
131+
mDisableBatteryOptimization, false, getString(R.string.action_already_disabled));
132+
}
133+
}
134+
135+
private void requestDisableBatteryOptimizations() {
136+
Logger.logDebug(LOG_TAG, "Requesting to disable battery optimizations");
137+
PermissionUtils.requestDisableBatteryOptimizations(this, PermissionUtils.REQUEST_DISABLE_BATTERY_OPTIMIZATIONS);
138+
}
139+
140+
141+
142+
private void checkIfDisplayOverOtherAppsPermissionNotGranted() {
143+
if (mDisplayOverOtherAppsPermissionNotGrantedWarning == null) return;
144+
145+
// If display over other apps permission not granted
146+
if (!PermissionUtils.checkDisplayOverOtherAppsPermission(this)) {
147+
ViewUtils.setWarningTextViewAndButtonState(this, mDisplayOverOtherAppsPermissionNotGrantedWarning,
148+
mGrantDisplayOverOtherAppsPermission, true, getString(R.string.action_grant_display_over_other_apps_permission));
149+
} else {
150+
ViewUtils.setWarningTextViewAndButtonState(this, mDisplayOverOtherAppsPermissionNotGrantedWarning,
151+
mGrantDisplayOverOtherAppsPermission, false, getString(R.string.action_already_granted));
152+
}
153+
}
154+
155+
private void requestDisplayOverOtherAppsPermission() {
156+
Logger.logDebug(LOG_TAG, "Requesting to grant display over other apps permission");
157+
PermissionUtils.requestDisplayOverOtherAppsPermission(this, PermissionUtils.REQUEST_GRANT_DISPLAY_OVER_OTHER_APPS_PERMISSION);
158+
}
159+
160+
161+
162+
@Override
163+
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
164+
super.onActivityResult(requestCode, resultCode, data);
165+
Logger.logVerbose(LOG_TAG, "onActivityResult: requestCode: " + requestCode + ", resultCode: " + resultCode + ", data: " + IntentUtils.getIntentString(data));
166+
167+
switch (requestCode) {
168+
case PermissionUtils.REQUEST_DISABLE_BATTERY_OPTIMIZATIONS:
169+
if(PermissionUtils.checkIfBatteryOptimizationsDisabled(this))
170+
Logger.logDebug(LOG_TAG, "Battery optimizations disabled by user on request.");
171+
else
172+
Logger.logDebug(LOG_TAG, "Battery optimizations not disabled by user on request.");
173+
break;
174+
case PermissionUtils.REQUEST_GRANT_DISPLAY_OVER_OTHER_APPS_PERMISSION:
175+
if(PermissionUtils.checkDisplayOverOtherAppsPermission(this))
176+
Logger.logDebug(LOG_TAG, "Display over other apps granted by user on request.");
177+
else
178+
Logger.logDebug(LOG_TAG, "Display over other apps denied by user on request.");
179+
break;
180+
default:
181+
Logger.logError(LOG_TAG, "Unknown request code \"" + requestCode + "\" passed to onRequestPermissionsResult");
182+
}
183+
}
184+
185+
186+
95187
private void openSettings() {
96188
ActivityUtils.startActivity(this, new Intent().setClassName(TermuxConstants.TERMUX_PACKAGE_NAME, TermuxConstants.TERMUX_APP.TERMUX_SETTINGS_ACTIVITY_NAME));
97189
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.termux.api.util;
2+
3+
import android.content.Context;
4+
import android.widget.Button;
5+
import android.widget.TextView;
6+
7+
import androidx.annotation.NonNull;
8+
import androidx.core.content.ContextCompat;
9+
10+
import com.termux.api.R;
11+
import com.termux.shared.theme.ThemeUtils;
12+
13+
public class ViewUtils {
14+
15+
public static void setWarningTextViewAndButtonState(@NonNull Context context,
16+
@NonNull TextView textView, @NonNull Button button,
17+
boolean warningState, String text) {
18+
if (warningState) {
19+
textView.setTextColor(ContextCompat.getColor(context, R.color.red_error));
20+
textView.setLinkTextColor(ContextCompat.getColor(context, R.color.red_error_link));
21+
button.setEnabled(true);
22+
button.setAlpha(1);
23+
} else {
24+
textView.setTextColor(ThemeUtils.getTextColorPrimary(context));
25+
textView.setLinkTextColor(ThemeUtils.getTextColorLink(context));
26+
button.setEnabled(false);
27+
button.setAlpha(0.5f);
28+
}
29+
30+
button.setText(text);
31+
}
32+
33+
}

app/src/main/res/layout/activity_termux_api.xml

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
<LinearLayout
3+
xmlns:android="http://schemas.android.com/apk/res/android"
4+
xmlns:app="http://schemas.android.com/apk/res-auto"
5+
xmlns:tools="http://schemas.android.com/tools"
36
android:layout_width="match_parent"
47
android:layout_height="match_parent"
58
android:orientation="vertical">
@@ -9,7 +12,6 @@
912
android:id="@+id/partial_primary_toolbar"/>
1013

1114
<ScrollView
12-
xmlns:tools="http://schemas.android.com/tools"
1315
android:layout_width="match_parent"
1416
android:layout_height="match_parent" >
1517
<LinearLayout
@@ -34,6 +36,63 @@
3436
android:textColor="?android:textColorPrimary"
3537
android:textColorLink="?android:textColorLink"
3638
android:autoLink="web"/>
39+
40+
<View style="@style/ViewDivider"/>
41+
42+
<com.google.android.material.textview.MaterialTextView
43+
android:id="@+id/textview_battery_optimization_not_disabled_warning"
44+
android:layout_width="match_parent"
45+
android:layout_height="wrap_content"
46+
android:paddingBottom="@dimen/activity_vertical_margin"
47+
android:gravity="start|center_vertical"
48+
android:text="@string/msg_battery_optimization_not_disabled_warning"
49+
android:textSize="14sp"
50+
android:textStyle="normal"
51+
android:textColor="@color/red_error"
52+
android:textColorLink="@color/red_error_link"
53+
android:autoLink="web"/>
54+
55+
<com.google.android.material.button.MaterialButton
56+
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
57+
android:id="@+id/btn_disable_battery_optimizations"
58+
android:layout_width="wrap_content"
59+
android:layout_height="wrap_content"
60+
android:layout_gravity="end"
61+
android:gravity="center"
62+
android:text="@string/action_disable_battery_optimizations"
63+
android:textSize="12sp"
64+
android:textColor="?android:textColorPrimary"
65+
app:strokeColor="?android:textColorPrimary"
66+
app:strokeWidth="2dp"/>
67+
68+
<View style="@style/ViewDivider"/>
69+
70+
<com.google.android.material.textview.MaterialTextView
71+
android:id="@+id/textview_display_over_other_apps_not_granted_warning"
72+
android:layout_width="match_parent"
73+
android:layout_height="wrap_content"
74+
android:paddingBottom="@dimen/activity_vertical_margin"
75+
android:gravity="start|center_vertical"
76+
android:text="@string/msg_display_over_other_apps_permission_not_granted_warning"
77+
android:textSize="14sp"
78+
android:textStyle="normal"
79+
android:textColor="@color/red_error"
80+
android:textColorLink="@color/red_error_link"
81+
android:autoLink="web"/>
82+
83+
<com.google.android.material.button.MaterialButton
84+
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
85+
android:id="@+id/btn_grant_display_over_other_apps_permission"
86+
android:layout_width="wrap_content"
87+
android:layout_height="wrap_content"
88+
android:layout_gravity="end"
89+
android:gravity="center"
90+
android:layout_marginBottom="@dimen/activity_vertical_margin"
91+
android:text="@string/action_grant_display_over_other_apps_permission"
92+
android:textSize="12sp"
93+
android:textColor="?android:textColorPrimary"
94+
app:strokeColor="?android:textColorPrimary"
95+
app:strokeWidth="2dp"/>
3796
</LinearLayout>
3897

3998
</ScrollView>

app/src/main/res/values/strings.xml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,29 @@
2929
\n\nReports for some crashes may be shown when you restart &TERMUX_APP_NAME; app.</string>
3030

3131

32+
33+
<!-- TermuxAPIActivity -->
34+
<string name="msg_battery_optimization_not_disabled_warning">Android battery optimizations
35+
should be disabled for the &TERMUX_API_APP_NAME; app so that termux-api script can start
36+
it from the background if its failing to do so. Do not worry, this will not drain battery,
37+
the app currently only runs commands when called from termux-api script.
38+
Check https://developer.android.com/about/versions/oreo/background and
39+
https://developer.android.com/guide/components/foreground-services#background-start-restrictions
40+
for more info.
41+
42+
\n\nAlso check https://dontkillmyapp.com for info on vendor specific app killers.
43+
Depending on vendor you may need to do things like enable AutoStart, disable DuraSpeed,
44+
enable `Display pop-up windows while running in the background` for the app.</string>
45+
<string name="action_disable_battery_optimizations">Disable Battery Optimizations</string>
46+
<string name="msg_display_over_other_apps_permission_not_granted_warning">The display over other
47+
apps permission should be granted to &TERMUX_API_APP_NAME; app for starting foreground
48+
activities from background. Check https://developer.android.com/guide/components/activities/background-starts
49+
for more info.
50+
</string>
51+
<string name="action_grant_display_over_other_apps_permission">Grant Draw Over Apps Permission</string>
52+
53+
<string name="action_already_granted">Already Granted</string>
54+
<string name="action_already_disabled">Already Disabled</string>
3255
<string name="action_info">Info</string>
3356
<string name="action_settings">Settings</string>
3457

0 commit comments

Comments
 (0)