[controller] mejorar tabla de permismos
This commit is contained in:
parent
d393748393
commit
a041c433f9
|
|
@ -636,11 +636,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
filter.addAction(WatchdogService.ACTION_STATE_STARTED);
|
filter.addAction(WatchdogService.ACTION_STATE_STARTED);
|
||||||
filter.addAction(WatchdogService.ACTION_STATE_STOPPED);
|
filter.addAction(WatchdogService.ACTION_STATE_STOPPED);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
ContextCompat.registerReceiver(this, logReceiver, filter, ContextCompat.RECEIVER_NOT_EXPORTED);
|
||||||
registerReceiver(logReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
|
|
||||||
} else {
|
|
||||||
registerReceiver(logReceiver, filter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.animation.Animation;
|
||||||
|
import android.view.animation.AnimationUtils;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
|
@ -19,6 +22,7 @@ import androidx.activity.result.contract.ActivityResultContracts;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.widget.SwitchCompat;
|
import androidx.appcompat.widget.SwitchCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
public class SetupActivity extends AppCompatActivity {
|
public class SetupActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
|
@ -26,6 +30,9 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private SwitchCompat switchNotif, switchTermux, switchVpn, switchBattery;
|
private SwitchCompat switchNotif, switchTermux, switchVpn, switchBattery;
|
||||||
private Button btnContinue;
|
private Button btnContinue;
|
||||||
|
private Button btnManageAll;
|
||||||
|
private Button btnTermuxOverlay;
|
||||||
|
private Button btnManageTermux;
|
||||||
|
|
||||||
private ActivityResultLauncher<String> requestPermissionLauncher;
|
private ActivityResultLauncher<String> requestPermissionLauncher;
|
||||||
private ActivityResultLauncher<Intent> vpnLauncher;
|
private ActivityResultLauncher<Intent> vpnLauncher;
|
||||||
|
|
@ -44,6 +51,9 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
switchVpn = findViewById(R.id.switch_perm_vpn);
|
switchVpn = findViewById(R.id.switch_perm_vpn);
|
||||||
switchBattery = findViewById(R.id.switch_perm_battery);
|
switchBattery = findViewById(R.id.switch_perm_battery);
|
||||||
btnContinue = findViewById(R.id.btn_setup_continue);
|
btnContinue = findViewById(R.id.btn_setup_continue);
|
||||||
|
btnManageAll = findViewById(R.id.btn_manage_all);
|
||||||
|
btnTermuxOverlay = findViewById(R.id.btn_termux_overlay);
|
||||||
|
btnManageTermux = findViewById(R.id.btn_manage_termux);
|
||||||
|
|
||||||
// Hide Notification switch if Android < 13
|
// Hide Notification switch if Android < 13
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
|
@ -82,22 +92,34 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private void setupListeners() {
|
private void setupListeners() {
|
||||||
switchNotif.setOnClickListener(v -> {
|
switchNotif.setOnClickListener(v -> {
|
||||||
|
if (hasNotifPermission()) {
|
||||||
|
handleRevokeAttempt(v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (switchNotif.isChecked()) {
|
if (switchNotif.isChecked()) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
|
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switchNotif.setChecked(hasNotifPermission()); // Revert visual state pending system response
|
switchNotif.setChecked(false); // Force visual state back until system confirms
|
||||||
});
|
});
|
||||||
|
|
||||||
switchTermux.setOnClickListener(v -> {
|
switchTermux.setOnClickListener(v -> {
|
||||||
|
if (hasTermuxPermission()) {
|
||||||
|
handleRevokeAttempt(v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (switchTermux.isChecked()) {
|
if (switchTermux.isChecked()) {
|
||||||
requestPermissionLauncher.launch(TERMUX_PERMISSION);
|
requestPermissionLauncher.launch(TERMUX_PERMISSION);
|
||||||
}
|
}
|
||||||
switchTermux.setChecked(hasTermuxPermission());
|
switchTermux.setChecked(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
switchVpn.setOnClickListener(v -> {
|
switchVpn.setOnClickListener(v -> {
|
||||||
|
if (hasVpnPermission()) {
|
||||||
|
handleRevokeAttempt(v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (switchVpn.isChecked()) {
|
if (switchVpn.isChecked()) {
|
||||||
Intent intent = VpnService.prepare(this);
|
Intent intent = VpnService.prepare(this);
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
|
|
@ -106,10 +128,14 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
checkAllPermissions(); // Already granted
|
checkAllPermissions(); // Already granted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switchVpn.setChecked(hasVpnPermission());
|
switchVpn.setChecked(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
switchBattery.setOnClickListener(v -> {
|
switchBattery.setOnClickListener(v -> {
|
||||||
|
if (hasBatteryPermission()) {
|
||||||
|
handleRevokeAttempt(v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (switchBattery.isChecked()) {
|
if (switchBattery.isChecked()) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
||||||
|
|
@ -117,7 +143,30 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
batteryLauncher.launch(intent);
|
batteryLauncher.launch(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switchBattery.setChecked(hasBatteryPermission());
|
switchBattery.setChecked(false);
|
||||||
|
});
|
||||||
|
// Direct access to all the Controller permissions
|
||||||
|
btnManageAll.setOnClickListener(v -> openAppSettings());
|
||||||
|
// Direct access to Termux Overlay permissions
|
||||||
|
btnTermuxOverlay.setOnClickListener(v -> {
|
||||||
|
try {
|
||||||
|
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
|
||||||
|
intent.setData(Uri.parse("package:com.termux"));
|
||||||
|
startActivity(intent);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Snackbar.make(v, "Termux is not installed or device not supported.", Snackbar.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Direct access to Controller settings (Reuses the method from Phase 1)
|
||||||
|
btnManageTermux.setOnClickListener(v -> {
|
||||||
|
try {
|
||||||
|
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
|
intent.setData(Uri.parse("package:com.termux"));
|
||||||
|
startActivity(intent);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Snackbar.make(v, "Termux is not installed.", Snackbar.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,6 +176,29 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
checkAllPermissions(); // Refresh state if user returns from settings
|
checkAllPermissions(); // Refresh state if user returns from settings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It displays visual feedback (shake) and a message when the user
|
||||||
|
* tries to turn off a permission.
|
||||||
|
*/
|
||||||
|
private void handleRevokeAttempt(View switchView) {
|
||||||
|
// Force the switch to stay checked visually
|
||||||
|
((SwitchCompat) switchView).setChecked(true);
|
||||||
|
|
||||||
|
// Animate the switch (Shake)
|
||||||
|
Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);
|
||||||
|
switchView.startAnimation(shake);
|
||||||
|
|
||||||
|
// Show Snackbar with action to go to Settings
|
||||||
|
Snackbar.make(findViewById(android.R.id.content), "To revoke permissions, you must do it from system settings.", Snackbar.LENGTH_LONG)
|
||||||
|
.setAction("SETTINGS", v -> openAppSettings()).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openAppSettings() {
|
||||||
|
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
|
intent.setData(Uri.parse("package:" + getPackageName()));
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
private void checkAllPermissions() {
|
private void checkAllPermissions() {
|
||||||
boolean notif = hasNotifPermission();
|
boolean notif = hasNotifPermission();
|
||||||
boolean termux = hasTermuxPermission();
|
boolean termux = hasTermuxPermission();
|
||||||
|
|
@ -138,12 +210,6 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
switchVpn.setChecked(vpn);
|
switchVpn.setChecked(vpn);
|
||||||
switchBattery.setChecked(battery);
|
switchBattery.setChecked(battery);
|
||||||
|
|
||||||
// Lock switches if already granted to prevent user confusion
|
|
||||||
if (notif) switchNotif.setEnabled(false);
|
|
||||||
if (termux) switchTermux.setEnabled(false);
|
|
||||||
if (vpn) switchVpn.setEnabled(false);
|
|
||||||
if (battery) switchBattery.setEnabled(false);
|
|
||||||
|
|
||||||
boolean allGranted = termux && vpn && battery;
|
boolean allGranted = termux && vpn && battery;
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
allGranted = allGranted && notif;
|
allGranted = allGranted && notif;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:interpolator="@android:anim/overshoot_interpolator"
|
||||||
|
android:fillAfter="true">
|
||||||
|
|
||||||
|
<translate
|
||||||
|
android:startOffset="0"
|
||||||
|
android:fromXDelta="0%p"
|
||||||
|
android:toXDelta="5%p"
|
||||||
|
android:duration="50" />
|
||||||
|
|
||||||
|
<translate
|
||||||
|
android:startOffset="50"
|
||||||
|
android:fromXDelta="5%p"
|
||||||
|
android:toXDelta="-5%p"
|
||||||
|
android:duration="50" />
|
||||||
|
|
||||||
|
<translate
|
||||||
|
android:startOffset="100"
|
||||||
|
android:fromXDelta="-5%p"
|
||||||
|
android:toXDelta="5%p"
|
||||||
|
android:duration="50" />
|
||||||
|
|
||||||
|
<translate
|
||||||
|
android:startOffset="150"
|
||||||
|
android:fromXDelta="5%p"
|
||||||
|
android:toXDelta="-5%p"
|
||||||
|
android:duration="50" />
|
||||||
|
|
||||||
|
<translate
|
||||||
|
android:startOffset="200"
|
||||||
|
android:fromXDelta="-5%p"
|
||||||
|
android:toXDelta="0%p"
|
||||||
|
android:duration="50" />
|
||||||
|
</set>
|
||||||
|
|
@ -38,7 +38,8 @@
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:paddingVertical="12dp"
|
android:paddingVertical="12dp"
|
||||||
android:layout_marginBottom="8dp"/>
|
android:layout_marginBottom="8dp"
|
||||||
|
android:theme="@style/PurpleSwitchTheme"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
android:id="@+id/switch_perm_termux"
|
android:id="@+id/switch_perm_termux"
|
||||||
|
|
@ -48,7 +49,8 @@
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:paddingVertical="12dp"
|
android:paddingVertical="12dp"
|
||||||
android:layout_marginBottom="8dp"/>
|
android:layout_marginBottom="8dp"
|
||||||
|
android:theme="@style/PurpleSwitchTheme"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
android:id="@+id/switch_perm_vpn"
|
android:id="@+id/switch_perm_vpn"
|
||||||
|
|
@ -58,7 +60,8 @@
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:paddingVertical="12dp"
|
android:paddingVertical="12dp"
|
||||||
android:layout_marginBottom="8dp"/>
|
android:layout_marginBottom="8dp"
|
||||||
|
android:theme="@style/PurpleSwitchTheme"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
android:id="@+id/switch_perm_battery"
|
android:id="@+id/switch_perm_battery"
|
||||||
|
|
@ -68,8 +71,60 @@
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:paddingVertical="12dp"
|
android:paddingVertical="12dp"
|
||||||
|
android:theme="@style/PurpleSwitchTheme"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_manage_all"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Manage All Permissions"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:gravity="start|center_vertical"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:paddingVertical="12dp"
|
||||||
|
android:paddingStart="0dp"
|
||||||
|
android:paddingEnd="0dp"
|
||||||
|
android:minHeight="0dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:layout_marginBottom="12dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_marginBottom="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Termux custom permissions"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:layout_marginBottom="8dp"/>
|
android:layout_marginBottom="8dp"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_termux_overlay"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Display over other apps"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
style="?android:attr/borderlessButtonStyle"
|
||||||
|
android:gravity="start|center_vertical"
|
||||||
|
android:textColor="@color/lightGray66" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_manage_termux"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Manage Termux permissions"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
style="?android:attr/borderlessButtonStyle"
|
||||||
|
android:gravity="start|center_vertical"
|
||||||
|
android:textColor="@color/lightGray66" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<color name="colorAccent">#2E7D32</color>
|
<color name="colorAccent">#2E7D32</color>
|
||||||
<color name="white">#FFFFFF</color>
|
<color name="white">#FFFFFF</color>
|
||||||
<color name="black">#000000</color>
|
<color name="black">#000000</color>
|
||||||
|
<color name="lightGray66">#AAAAAA</color>
|
||||||
<color name="background_dark">#121212</color>
|
<color name="background_dark">#121212</color>
|
||||||
|
|
||||||
<!-- Status Colors (Fixed for readability) -->
|
<!-- Status Colors (Fixed for readability) -->
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
<color name="btn_vpn_on_dim">#EF9A9A</color>
|
<color name="btn_vpn_on_dim">#EF9A9A</color>
|
||||||
<color name="btn_vpn_off_dim">#A5D6A7</color>
|
<color name="btn_vpn_off_dim">#A5D6A7</color>
|
||||||
|
|
||||||
<!-- Secciones -->
|
<!-- Sections -->
|
||||||
<color name="section_header_bg">#333333</color>
|
<color name="section_header_bg">#333333</color>
|
||||||
<color name="section_body_bg_light">#F5F5F5</color>
|
<color name="section_body_bg_light">#F5F5F5</color>
|
||||||
<color name="section_body_bg_dark">#1A1A1A</color>
|
<color name="section_body_bg_dark">#1A1A1A</color>
|
||||||
|
|
|
||||||
|
|
@ -17,4 +17,7 @@
|
||||||
<item name="android:windowNoTitle">true</item>
|
<item name="android:windowNoTitle">true</item>
|
||||||
<item name="android:backgroundDimEnabled">false</item>
|
<item name="android:backgroundDimEnabled">false</item>
|
||||||
</style>
|
</style>
|
||||||
|
<style name="PurpleSwitchTheme" parent="">
|
||||||
|
<item name="colorControlActivated">#8A2BE2</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue