[controller] rediseño de botones y lógica en visualización

This commit is contained in:
Luis Guzmán 2026-03-31 18:45:18 -06:00
parent 875df57422
commit c86c17c0be
4 changed files with 777 additions and 723 deletions

View File

@ -21,6 +21,7 @@ import android.content.Context;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ClipData; import android.content.ClipData;
import android.content.res.ColorStateList;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -28,6 +29,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.graphics.Color;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
@ -63,6 +65,8 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity implements View.OnClickListener { public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "IIAB-MainActivity"; private static final String TAG = "IIAB-MainActivity";
@ -108,6 +112,13 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
private final Handler sizeUpdateHandler = new Handler(); private final Handler sizeUpdateHandler = new Handler();
private Runnable sizeUpdateRunnable; private Runnable sizeUpdateRunnable;
// Variables for adaptive localhost server check
private final Handler serverCheckHandler = new Handler(android.os.Looper.getMainLooper());
private Runnable serverCheckRunnable;
private static final int MIN_CHECK_INTERVAL = 5000; // 5 seconds floor
private static final int MAX_CHECK_INTERVAL = 60000; // 60 seconds ceiling
private int currentCheckInterval = MIN_CHECK_INTERVAL;
private final BroadcastReceiver logReceiver = new BroadcastReceiver() { private final BroadcastReceiver logReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
@ -241,6 +252,15 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
sizeUpdateHandler.postDelayed(this, 10000); sizeUpdateHandler.postDelayed(this, 10000);
} }
}; };
serverCheckRunnable = new Runnable() {
@Override
public void run() {
checkServerStatus();
serverCheckHandler.postDelayed(this, currentCheckInterval);
}
};
serverCheckHandler.post(serverCheckRunnable);
} }
private void showBatterySnackbar() { private void showBatterySnackbar() {
@ -380,6 +400,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
stopLogSizeUpdates(); stopLogSizeUpdates();
serverCheckHandler.removeCallbacks(serverCheckRunnable);
} }
@Override @Override
@ -403,6 +424,8 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
if (connectionLog != null && connectionLog.getVisibility() == View.VISIBLE) { if (connectionLog != null && connectionLog.getVisibility() == View.VISIBLE) {
startLogSizeUpdates(); startLogSizeUpdates();
} }
serverCheckHandler.removeCallbacks(serverCheckRunnable);
serverCheckHandler.post(serverCheckRunnable);
} }
@Override @Override
@ -432,8 +455,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
.setPositiveButton(R.string.go_to_settings, (dialog, which) -> openBatterySettings(manufacturer)) .setPositiveButton(R.string.go_to_settings, (dialog, which) -> openBatterySettings(manufacturer))
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.show(); .show();
} } else {
else {
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + getPackageName())); intent.setData(Uri.parse("package:" + getPackageName()));
batteryOptLauncher.launch(intent); batteryOptLauncher.launch(intent);
@ -459,8 +481,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
success = true; success = true;
} catch (Exception e2) {} } catch (Exception e2) {}
} }
} } else if (manufacturer.contains("xiaomi")) {
else if (manufacturer.contains("xiaomi")) {
try { try {
Intent intent = new Intent("miui.intent.action.APP_BATTERY_SAVER_SETTINGS"); Intent intent = new Intent("miui.intent.action.APP_BATTERY_SAVER_SETTINGS");
intent.setComponent(new ComponentName("com.miui.powerkeeper", "com.miui.powerkeeper.ui.HiddenAppsConfigActivity")); intent.setComponent(new ComponentName("com.miui.powerkeeper", "com.miui.powerkeeper.ui.HiddenAppsConfigActivity"));
@ -476,8 +497,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName())); intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent); startActivity(intent);
} catch (Exception ex) { } catch (Exception ex) {}
}
} }
} }
@ -576,8 +596,6 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} }
private void handleWatchdogClick() { private void handleWatchdogClick() {
// if (prefs.getWatchdogEnable()) showWatchdogBiometricPrompt();
// else toggleWatchdog(false);
toggleWatchdog(prefs.getWatchdogEnable()); toggleWatchdog(prefs.getWatchdogEnable());
} }
@ -638,7 +656,6 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
// --- Secure Advanced Settings Menu --- // --- Secure Advanced Settings Menu ---
private void handleConfigToggle() { private void handleConfigToggle() {
if (configLayout.getVisibility() == View.GONE) { if (configLayout.getVisibility() == View.GONE) {
// The menu is closed. We want to open it, so we check for security first.
BiometricManager bm = BiometricManager.from(this); BiometricManager bm = BiometricManager.from(this);
int auth = BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL; int auth = BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
@ -649,10 +666,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
if (bm.canAuthenticate(auth) == BiometricManager.BIOMETRIC_SUCCESS || (km != null && km.isDeviceSecure())) { if (bm.canAuthenticate(auth) == BiometricManager.BIOMETRIC_SUCCESS || (km != null && km.isDeviceSecure())) {
showConfigBiometricPrompt(); showConfigBiometricPrompt();
} else { } else {
showEnrollmentDialog(); // Forces user to set a PIN if device has no security showEnrollmentDialog();
} }
} else { } else {
// The menu is open. Just close it without asking for fingerprint.
toggleVisibility(configLayout, configLabel, getString(R.string.advanced_settings_label)); toggleVisibility(configLayout, configLabel, getString(R.string.advanced_settings_label));
} }
} }
@ -663,7 +679,6 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
@Override @Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) { public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result); super.onAuthenticationSucceeded(result);
// Auth successful! Open the menu.
toggleVisibility(configLayout, configLabel, getString(R.string.advanced_settings_label)); toggleVisibility(configLayout, configLabel, getString(R.string.advanced_settings_label));
} }
}); });
@ -673,14 +688,12 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
auth = BiometricManager.Authenticators.BIOMETRIC_WEAK | BiometricManager.Authenticators.DEVICE_CREDENTIAL; auth = BiometricManager.Authenticators.BIOMETRIC_WEAK | BiometricManager.Authenticators.DEVICE_CREDENTIAL;
} }
// Reusing your existing strings to avoid compilation errors
bp.authenticate(new BiometricPrompt.PromptInfo.Builder() bp.authenticate(new BiometricPrompt.PromptInfo.Builder()
.setTitle(getString(R.string.auth_required_title)) .setTitle(getString(R.string.auth_required_title))
.setSubtitle(getString(R.string.auth_required_subtitle)) .setSubtitle(getString(R.string.auth_required_subtitle))
.setAllowedAuthenticators(auth) .setAllowedAuthenticators(auth)
.build()); .build());
} }
// ------------------------------------------------
private void showWatchdogBiometricPrompt() { private void showWatchdogBiometricPrompt() {
Executor ex = ContextCompat.getMainExecutor(this); Executor ex = ContextCompat.getMainExecutor(this);
@ -714,11 +727,6 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
button_control.setText(R.string.control_enable); button_control.setText(R.string.control_enable);
button_control.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_vpn_off)); button_control.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_vpn_off));
} }
if (vpnActive) {
button_browse_content.setVisibility(View.VISIBLE);
} else {
button_browse_content.setVisibility(View.GONE);
}
if (watchdogActive) { if (watchdogActive) {
watchdogControl.setText(R.string.watchdog_disable); 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));
@ -750,39 +758,67 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} }
} }
//DEFAULT VALUES ON ORIGINAL INTERFACE private void checkServerStatus() {
// private void savePrefs() { new Thread(() -> {
// prefs.setSocksAddress(edittext_socks_addr.getText().toString()); boolean isReachable = false;
// prefs.setSocksPort(Integer.parseInt(edittext_socks_port.getText().toString())); try {
// prefs.setSocksUdpAddress(edittext_socks_udp_addr.getText().toString()); URL url = new URL("http://localhost:8085/home");
// prefs.setSocksUsername(edittext_socks_user.getText().toString()); HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// prefs.setSocksPassword(edittext_socks_pass.getText().toString()); connection.setConnectTimeout(1500);
// prefs.setDnsIpv4(edittext_dns_ipv4.getText().toString()); connection.setReadTimeout(1500);
// prefs.setDnsIpv6(edittext_dns_ipv6.getText().toString()); connection.setRequestMethod("GET");
// prefs.setIpv4(checkbox_ipv4.isChecked()); int responseCode = connection.getResponseCode();
// prefs.setIpv6(checkbox_ipv6.isChecked());
// prefs.setGlobal(checkbox_global.isChecked()); isReachable = (responseCode >= 200 && responseCode < 400);
// prefs.setUdpInTcp(checkbox_udp_in_tcp.isChecked()); } catch (Exception e) {
// prefs.setRemoteDns(checkbox_remote_dns.isChecked()); isReachable = false;
// prefs.setMaintenanceMode(checkbox_maintenance.isChecked()); }
// }
final boolean serverAlive = isReachable;
runOnUiThread(() -> updateUIColorsAndVisibility(serverAlive));
}).start();
}
private void updateUIColorsAndVisibility(boolean isServerAlive) {
boolean isVpnActive = prefs.getEnable();
if (!isServerAlive) {
currentCheckInterval = MIN_CHECK_INTERVAL;
button_control.setEnabled(false); // Disable ESPW click
button_browse_content.setVisibility(View.GONE);
if (isVpnActive) {
button_control.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_vpn_on_dim));
} else {
button_control.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_vpn_off_dim));
}
} else {
currentCheckInterval = Math.min((int)(currentCheckInterval * 1.5), MAX_CHECK_INTERVAL);
button_control.setEnabled(true); // Enable ESPW click
button_browse_content.setVisibility(View.VISIBLE); // Always visible if server is alive
updateUI();
if (isVpnActive) {
button_browse_content.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_explore_ready));
} else {
button_browse_content.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_explore_disabled));
}
}
}
private void savePrefs() { private void savePrefs() {
// 1. Hardcoded / Hidden Secure Values (Walled Garden defaults)
prefs.setSocksAddress("127.0.0.1"); prefs.setSocksAddress("127.0.0.1");
prefs.setSocksPort(1080); prefs.setSocksPort(1080);
prefs.setSocksUdpAddress(""); // Empty by default prefs.setSocksUdpAddress("");
prefs.setSocksUsername(""); prefs.setSocksUsername("");
prefs.setSocksPassword(""); prefs.setSocksPassword("");
prefs.setIpv4(true); prefs.setIpv4(true);
prefs.setIpv6(true); prefs.setIpv6(true);
prefs.setUdpInTcp(false); prefs.setUdpInTcp(false);
prefs.setRemoteDns(true); prefs.setRemoteDns(true);
// CRITICAL: Force Global to TRUE so the tunnel catches ALL system traffic
prefs.setGlobal(true); prefs.setGlobal(true);
// 2. User Editable Values (The only things read from the UI)
prefs.setDnsIpv4(edittext_dns_ipv4.getText().toString()); prefs.setDnsIpv4(edittext_dns_ipv4.getText().toString());
prefs.setDnsIpv6(edittext_dns_ipv6.getText().toString()); prefs.setDnsIpv6(edittext_dns_ipv6.getText().toString());
prefs.setMaintenanceMode(checkbox_maintenance.isChecked()); prefs.setMaintenanceMode(checkbox_maintenance.isChecked());

View File

@ -85,8 +85,12 @@ public class PortalActivity extends AppCompatActivity {
resetTimer.run(); resetTimer.run();
}); });
Preferences prefs = new Preferences(this);
boolean isVpnActive = prefs.getEnable();
String targetUrl = isVpnActive ? "http://box/" : "http://localhost:8085/home";
btnHome.setOnClickListener(v -> { btnHome.setOnClickListener(v -> {
webView.loadUrl("http://box/"); webView.loadUrl(targetUrl);
resetTimer.run(); resetTimer.run();
}); });
@ -156,14 +160,14 @@ public class PortalActivity extends AppCompatActivity {
webView.getSettings().setDomStorageEnabled(true); webView.getSettings().setDomStorageEnabled(true);
// 2. Port and Mirror logic // 2. Port and Mirror logic
Preferences prefs = new Preferences(this);
int tempPort = prefs.getSocksPort(); int tempPort = prefs.getSocksPort();
if (tempPort <= 0) tempPort = 1080; if (tempPort <= 0) tempPort = 1080;
// Variable safe to read in lambda // Variable safe to read in lambda
final int finalProxyPort = tempPort; final int finalProxyPort = tempPort;
// 3. Proxy block // 3. Proxy block (ONLY IF VPN IS ACTIVE)
if (isVpnActive) {
if (WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE)) { if (WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE)) {
ProxyConfig proxyConfig = new ProxyConfig.Builder() ProxyConfig proxyConfig = new ProxyConfig.Builder()
.addProxyRule("socks5://127.0.0.1:" + finalProxyPort) .addProxyRule("socks5://127.0.0.1:" + finalProxyPort)
@ -174,13 +178,17 @@ public class PortalActivity extends AppCompatActivity {
ProxyController.getInstance().setProxyOverride(proxyConfig, executor, () -> { ProxyController.getInstance().setProxyOverride(proxyConfig, executor, () -> {
Log.d(TAG, "Proxy configured on port: " + finalProxyPort); Log.d(TAG, "Proxy configured on port: " + finalProxyPort);
// Load HTML only when proxy is ready // Load HTML only when proxy is ready
webView.loadUrl("http://box/"); webView.loadUrl(targetUrl);
}); });
} else { } else {
// Fallback for older devices // Fallback for older devices
Log.w(TAG, "Proxy Override not supported"); Log.w(TAG, "Proxy Override not supported");
webView.loadUrl(targetUrl);
}
} else {
// VPN is OFF. Do NOT use proxy. Just load localhost directly.
webView.loadUrl(targetUrl);
} }
webView.loadUrl("http://box/");
} }
// 4. Cleanup (Important to not leave the proxy active) // 4. Cleanup (Important to not leave the proxy active)

View File

@ -57,7 +57,7 @@
android:padding="16dp"> android:padding="16dp">
<!-- HR below Watchdog --> <!-- HR below Watchdog -->
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="#444444" android:layout_marginBottom="20dp"/> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/divider_color" android:layout_marginBottom="20dp"/>
<!-- VPN Control Section --> <!-- VPN Control Section -->
<Button <Button
@ -69,7 +69,7 @@
android:textStyle="bold" android:textStyle="bold"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:background="@drawable/rounded_button" android:background="@drawable/rounded_button"
android:backgroundTint="#2E7D32" android:backgroundTint="@color/btn_vpn_off"
android:textAllCaps="false"/> android:textAllCaps="false"/>
<TextView <TextView
@ -94,7 +94,7 @@
android:textStyle="bold" android:textStyle="bold"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:background="@drawable/rounded_button" android:background="@drawable/rounded_button"
android:backgroundTint="#F57C00" android:backgroundTint="@color/btn_explore_disabled"
android:textAllCaps="false" android:textAllCaps="false"
android:elevation="4dp" android:elevation="4dp"
android:visibility="gone" /> android:visibility="gone" />
@ -235,7 +235,7 @@
</LinearLayout> </LinearLayout>
<!-- HR above Watchdog --> <!-- HR above Watchdog -->
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="#444444" android:layout_marginBottom="16dp"/> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/divider_color" android:layout_marginBottom="16dp"/>
<!-- Watchdog Control Section --> <!-- Watchdog Control Section -->
<Button <Button
@ -247,7 +247,7 @@
android:textStyle="bold" android:textStyle="bold"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:background="@drawable/rounded_button" android:background="@drawable/rounded_button"
android:backgroundTint="#1976D2" android:backgroundTint="@color/btn_watchdog_off"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:textAllCaps="false"/> android:textAllCaps="false"/>
@ -260,7 +260,7 @@
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
android:layout_marginBottom="16dp"/> android:layout_marginBottom="16dp"/>
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="#444444" android:layout_marginVertical="20dp"/> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/divider_color" android:layout_marginVertical="20dp"/>
<!-- Log Section (Collapsible) --> <!-- Log Section (Collapsible) -->
<TextView <TextView
@ -280,7 +280,7 @@
android:id="@+id/log_warning_text" android:id="@+id/log_warning_text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="#FF9800" android:textColor="@color/text_warning"
android:textSize="11sp" android:textSize="11sp"
android:textStyle="italic" android:textStyle="italic"
android:padding="4dp" android:padding="4dp"
@ -340,7 +340,7 @@
android:layout_weight="1" android:layout_weight="1"
android:text="@string/reset_log" android:text="@string/reset_log"
android:textSize="12sp" android:textSize="12sp"
android:backgroundTint="#D32F2F" android:backgroundTint="@color/btn_danger"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textAllCaps="false" android:textAllCaps="false"
android:layout_marginEnd="4dp"/> android:layout_marginEnd="4dp"/>
@ -352,21 +352,21 @@
android:layout_weight="1" android:layout_weight="1"
android:text="@string/copy_all" android:text="@string/copy_all"
android:textSize="12sp" android:textSize="12sp"
android:backgroundTint="#388E3C" android:backgroundTint="@color/btn_success"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textAllCaps="false" android:textAllCaps="false"
android:layout_marginStart="4dp"/> android:layout_marginStart="4dp"/>
</LinearLayout> </LinearLayout>
<!-- Version Footer --> <!-- Version Footer -->
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="#444444" android:layout_marginTop="32dp" android:layout_marginBottom="8dp"/> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/divider_color" android:layout_marginTop="32dp" android:layout_marginBottom="8dp"/>
<TextView <TextView
android:id="@+id/version_text" android:id="@+id/version_text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:text="v0.1.17alpha" android:text="v0.1.17alpha"
android:textColor="#888888" android:textColor="@color/text_muted"
android:textSize="10sp" android:textSize="10sp"
android:paddingBottom="16dp"/> android:paddingBottom="16dp"/>

View File

@ -13,9 +13,19 @@
<color name="btn_watchdog_off">#1976D2</color> <!-- Material Blue --> <color name="btn_watchdog_off">#1976D2</color> <!-- Material Blue -->
<color name="btn_vpn_on">#C62828</color> <!-- Dark Red --> <color name="btn_vpn_on">#C62828</color> <!-- Dark Red -->
<color name="btn_vpn_off">#2E7D32</color> <!-- Material Green --> <color name="btn_vpn_off">#2E7D32</color> <!-- Material Green -->
<color name="btn_explore_ready">#F57C00</color>
<color name="btn_explore_disabled">#9E9E9E</color>
<color name="btn_vpn_on_dim">#EF9A9A</color>
<color name="btn_vpn_off_dim">#A5D6A7</color>
<!-- Secciones --> <!-- Secciones -->
<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>
<color name="text_warning">#FF9800</color>
<color name="text_muted">#888888</color>
<color name="divider_color">#444444</color>
<color name="btn_danger">#D32F2F</color>
<color name="btn_success">#388E3C</color>
</resources> </resources>