[controller] maintenance, cleaning and move strings.

This commit is contained in:
Luis Guzmán 2026-03-06 11:12:23 -06:00
parent f247a1f173
commit 3fec55ca56
2 changed files with 80 additions and 71 deletions

View File

@ -10,6 +10,8 @@
package org.iiab.controller; package org.iiab.controller;
import android.os.Bundle; import android.os.Bundle;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
@ -22,7 +24,6 @@ import android.content.ClipboardManager;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
@ -73,8 +74,6 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
private Button watchdogControl; private Button watchdogControl;
private TextView connectionLog; private TextView connectionLog;
private LinearLayout logActions; private LinearLayout logActions;
private Button btnClearLog;
private Button btnCopyLog;
private LinearLayout configLayout; private LinearLayout configLayout;
private TextView configLabel; private TextView configLabel;
private LinearLayout advancedConfig; private LinearLayout advancedConfig;
@ -83,7 +82,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
private ImageButton themeToggle; private ImageButton themeToggle;
private TextView versionFooter; private TextView versionFooter;
private BroadcastReceiver logReceiver = new BroadcastReceiver() { private ActivityResultLauncher<Intent> vpnPermissionLauncher;
private final BroadcastReceiver logReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (IIABWatchdog.ACTION_LOG_MESSAGE.equals(intent.getAction())) { if (IIABWatchdog.ACTION_LOG_MESSAGE.equals(intent.getAction())) {
@ -100,45 +101,55 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
prefs = new Preferences(this); prefs = new Preferences(this);
setContentView(R.layout.main); setContentView(R.layout.main);
edittext_socks_addr = (EditText) findViewById(R.id.socks_addr); // Initialize the VPN permission launcher
edittext_socks_udp_addr = (EditText) findViewById(R.id.socks_udp_addr); vpnPermissionLauncher = registerForActivityResult(
edittext_socks_port = (EditText) findViewById(R.id.socks_port); new ActivityResultContracts.StartActivityForResult(),
edittext_socks_user = (EditText) findViewById(R.id.socks_user); result -> {
edittext_socks_pass = (EditText) findViewById(R.id.socks_pass); if (result.getResultCode() == RESULT_OK && prefs.getEnable()) {
edittext_dns_ipv4 = (EditText) findViewById(R.id.dns_ipv4); connectVpn();
edittext_dns_ipv6 = (EditText) findViewById(R.id.dns_ipv6); }
checkbox_ipv4 = (CheckBox) findViewById(R.id.ipv4); }
checkbox_ipv6 = (CheckBox) findViewById(R.id.ipv6); );
checkbox_global = (CheckBox) findViewById(R.id.global);
checkbox_udp_in_tcp = (CheckBox) findViewById(R.id.udp_in_tcp);
checkbox_remote_dns = (CheckBox) findViewById(R.id.remote_dns);
button_apps = (Button) findViewById(R.id.apps);
button_save = (Button) findViewById(R.id.save);
button_control = (Button) findViewById(R.id.control);
watchdogControl = (Button) findViewById(R.id.watchdog_control); edittext_socks_addr = findViewById(R.id.socks_addr);
edittext_socks_udp_addr = findViewById(R.id.socks_udp_addr);
edittext_socks_port = findViewById(R.id.socks_port);
edittext_socks_user = findViewById(R.id.socks_user);
edittext_socks_pass = findViewById(R.id.socks_pass);
edittext_dns_ipv4 = findViewById(R.id.dns_ipv4);
edittext_dns_ipv6 = findViewById(R.id.dns_ipv6);
checkbox_ipv4 = findViewById(R.id.ipv4);
checkbox_ipv6 = findViewById(R.id.ipv6);
checkbox_global = findViewById(R.id.global);
checkbox_udp_in_tcp = findViewById(R.id.udp_in_tcp);
checkbox_remote_dns = findViewById(R.id.remote_dns);
button_apps = findViewById(R.id.apps);
button_save = findViewById(R.id.save);
button_control = findViewById(R.id.control);
watchdogControl = findViewById(R.id.watchdog_control);
watchdogControl.setOnClickListener(this); watchdogControl.setOnClickListener(this);
logActions = (LinearLayout) findViewById(R.id.log_actions); logActions = findViewById(R.id.log_actions);
btnClearLog = (Button) findViewById(R.id.btn_clear_log); Button btnClearLog = findViewById(R.id.btn_clear_log);
btnCopyLog = (Button) findViewById(R.id.btn_copy_log); Button btnCopyLog = findViewById(R.id.btn_copy_log);
btnClearLog.setOnClickListener(this); btnClearLog.setOnClickListener(this);
btnCopyLog.setOnClickListener(this); btnCopyLog.setOnClickListener(this);
connectionLog = (TextView) findViewById(R.id.connection_log); connectionLog = findViewById(R.id.connection_log);
connectionLog.setMovementMethod(new ScrollingMovementMethod()); connectionLog.setMovementMethod(new ScrollingMovementMethod());
// Enable text selection for copying large logs // Enable text selection for copying large logs
connectionLog.setTextIsSelectable(true); connectionLog.setTextIsSelectable(true);
configLayout = (LinearLayout) findViewById(R.id.config_layout); configLayout = findViewById(R.id.config_layout);
configLabel = (TextView) findViewById(R.id.config_label); configLabel = findViewById(R.id.config_label);
configLabel.setOnClickListener(v -> toggleVisibility(configLayout, configLabel, "Configuration")); configLabel.setOnClickListener(v -> toggleVisibility(configLayout, configLabel, "Configuration"));
advancedConfig = (LinearLayout) findViewById(R.id.advanced_config); advancedConfig = findViewById(R.id.advanced_config);
advConfigLabel = (TextView) findViewById(R.id.adv_config_label); advConfigLabel = findViewById(R.id.adv_config_label);
advConfigLabel.setOnClickListener(v -> toggleVisibility(advancedConfig, advConfigLabel, "Advanced Settings")); advConfigLabel.setOnClickListener(v -> toggleVisibility(advancedConfig, advConfigLabel, "Advanced Settings"));
logLabel = (TextView) findViewById(R.id.log_label); logLabel = findViewById(R.id.log_label);
logLabel.setOnClickListener(v -> { logLabel.setOnClickListener(v -> {
if (connectionLog.getVisibility() == View.GONE) { if (connectionLog.getVisibility() == View.GONE) {
readBlackBoxLogs(); // Load logs from file when expanding readBlackBoxLogs(); // Load logs from file when expanding
@ -147,11 +158,11 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
logActions.setVisibility(connectionLog.getVisibility()); logActions.setVisibility(connectionLog.getVisibility());
}); });
themeToggle = (ImageButton) findViewById(R.id.theme_toggle); themeToggle = findViewById(R.id.theme_toggle);
themeToggle.setOnClickListener(v -> toggleTheme()); themeToggle.setOnClickListener(v -> toggleTheme());
applySavedTheme(); applySavedTheme();
versionFooter = (TextView) findViewById(R.id.version_text); versionFooter = findViewById(R.id.version_text);
setVersionFooter(); setVersionFooter();
checkbox_udp_in_tcp.setOnClickListener(this); checkbox_udp_in_tcp.setOnClickListener(this);
@ -164,15 +175,22 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
/* Request VPN permission */ /* Request VPN permission */
Intent intent = VpnService.prepare(MainActivity.this); Intent intent = VpnService.prepare(MainActivity.this);
if (intent != null) if (intent != null) {
startActivityForResult(intent, 0); vpnPermissionLauncher.launch(intent);
else } else if (prefs.getEnable()) {
onActivityResult(0, RESULT_OK, null); connectVpn();
}
checkBatteryOptimizations(); checkBatteryOptimizations();
addToLog("Application Started"); addToLog("Application Started");
} }
private void connectVpn() {
Intent intent = new Intent(this, TProxyService.class);
startService(intent.setAction(TProxyService.ACTION_CONNECT));
addToLog("VPN Permission Granted. Connecting...");
}
private void readBlackBoxLogs() { private void readBlackBoxLogs() {
File logFile = new File(getFilesDir(), "watchdog_heartbeat_log.txt"); File logFile = new File(getFilesDir(), "watchdog_heartbeat_log.txt");
if (!logFile.exists()) { if (!logFile.exists()) {
@ -290,7 +308,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
super.onStart(); super.onStart();
IntentFilter filter = new IntentFilter(IIABWatchdog.ACTION_LOG_MESSAGE); IntentFilter filter = new IntentFilter(IIABWatchdog.ACTION_LOG_MESSAGE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(logReceiver, filter, Context.RECEIVER_EXPORTED); registerReceiver(logReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
} else { } else {
registerReceiver(logReceiver, filter); registerReceiver(logReceiver, filter);
} }
@ -306,16 +324,6 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} }
} }
@Override
protected void onActivityResult(int request, int result, Intent data) {
super.onActivityResult(request, result, data);
if ((result == RESULT_OK) && prefs.getEnable()) {
Intent intent = new Intent(this, TProxyService.class);
startService(intent.setAction(TProxyService.ACTION_CONNECT));
addToLog("VPN Permission Granted. Connecting...");
}
}
@Override @Override
public void onClick(View view) { public void onClick(View view) {
if (view == checkbox_global || view == checkbox_remote_dns) { if (view == checkbox_global || view == checkbox_remote_dns) {
@ -377,9 +385,12 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
showBiometricPrompt(); showBiometricPrompt();
} else { } else {
BiometricManager biometricManager = BiometricManager.from(this); BiometricManager biometricManager = BiometricManager.from(this);
int authenticators = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) ?
(BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL) : int authenticators = BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL;
BiometricManager.Authenticators.BIOMETRIC_WEAK; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
// For older versions, DEVICE_CREDENTIAL behaves differently, but androidx.biometric handles fallback
authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK | BiometricManager.Authenticators.DEVICE_CREDENTIAL;
}
boolean isSecure = false; boolean isSecure = false;
android.app.KeyguardManager km = (android.app.KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); android.app.KeyguardManager km = (android.app.KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
@ -418,17 +429,15 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} }
}); });
BiometricPrompt.PromptInfo.Builder promptBuilder = new BiometricPrompt.PromptInfo.Builder() int authenticators = BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL;
.setTitle("Authentication required")
.setSubtitle("Authenticate to disable the secure environment");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
promptBuilder.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG | .setTitle("Authentication required")
BiometricManager.Authenticators.DEVICE_CREDENTIAL); .setSubtitle("Authenticate to disable the secure environment")
} else { .setAllowedAuthenticators(authenticators)
promptBuilder.setDeviceCredentialAllowed(true); .build();
}
biometricPrompt.authenticate(promptBuilder.build()); biometricPrompt.authenticate(promptInfo);
} }
private void showWatchdogBiometricPrompt() { private void showWatchdogBiometricPrompt() {
@ -441,17 +450,15 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} }
}); });
BiometricPrompt.PromptInfo.Builder promptBuilder = new BiometricPrompt.PromptInfo.Builder() int authenticators = BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL;
.setTitle("Unlock Master Watchdog")
.setSubtitle("Authentication required to stop Termux protection");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
promptBuilder.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG | .setTitle("Unlock Master Watchdog")
BiometricManager.Authenticators.DEVICE_CREDENTIAL); .setSubtitle("Authentication required to stop Termux protection")
} else { .setAllowedAuthenticators(authenticators)
promptBuilder.setDeviceCredentialAllowed(true); .build();
}
biometricPrompt.authenticate(promptBuilder.build()); biometricPrompt.authenticate(promptInfo);
} }
private void toggleService(boolean isEnable) { private void toggleService(boolean isEnable) {
@ -481,10 +488,10 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} }
if (watchdogActive) { if (watchdogActive) {
watchdogControl.setText("Disable Master Watchdog"); watchdogControl.setText(R.string.watchdog_disable);
watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_watchdog_on)); watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_watchdog_on));
} else { } else {
watchdogControl.setText("Enable Master Watchdog"); watchdogControl.setText(R.string.watchdog_enable);
watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_watchdog_off)); watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_watchdog_off));
} }

View File

@ -18,4 +18,6 @@
<string name="control_enable">Enable Safe Pocket Web</string> <string name="control_enable">Enable Safe Pocket Web</string>
<string name="control_disable">Disable Safe Pocket Web</string> <string name="control_disable">Disable Safe Pocket Web</string>
<string name="vpn_description">Enable friendly URLs. Lock out the threats.</string> <string name="vpn_description">Enable friendly URLs. Lock out the threats.</string>
<string name="watchdog_enable">Enable Master Watchdog</string>
<string name="watchdog_disable">Disable Master Watchdog</string>
</resources> </resources>