diff --git a/app/src/main/java/io/netbird/client/MainActivity.java b/app/src/main/java/io/netbird/client/MainActivity.java
index b8fd1517..c7fb0b54 100644
--- a/app/src/main/java/io/netbird/client/MainActivity.java
+++ b/app/src/main/java/io/netbird/client/MainActivity.java
@@ -413,6 +413,14 @@ public void deselectRoute(String route) throws Exception {
mBinder.deselectRoute(route);
}
+ @Override
+ public String debugBundle(boolean anonymize) throws Exception {
+ if (mBinder == null) {
+ throw new Exception("VPN service not connected");
+ }
+ return mBinder.debugBundle(anonymize);
+ }
+
@Override
public void addRouteChangeListener(RouteChangeListener listener) {
if (mBinder == null) {
diff --git a/app/src/main/java/io/netbird/client/ServiceAccessor.java b/app/src/main/java/io/netbird/client/ServiceAccessor.java
index bf17e443..d37d399c 100644
--- a/app/src/main/java/io/netbird/client/ServiceAccessor.java
+++ b/app/src/main/java/io/netbird/client/ServiceAccessor.java
@@ -17,4 +17,6 @@ public interface ServiceAccessor {
void addRouteChangeListener(RouteChangeListener listener);
void removeRouteChangeListener(RouteChangeListener listener);
+
+ String debugBundle(boolean anonymize) throws Exception;
}
\ No newline at end of file
diff --git a/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java b/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java
index ed060c57..3f1e2a7c 100644
--- a/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java
+++ b/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java
@@ -1,6 +1,5 @@
package io.netbird.client.ui.advanced;
-import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
@@ -20,7 +19,6 @@
import io.netbird.client.R;
import io.netbird.client.databinding.ComponentSwitchBinding;
import io.netbird.client.databinding.FragmentAdvancedBinding;
-import io.netbird.client.tool.Logcat;
import io.netbird.client.tool.Preferences;
import io.netbird.client.tool.ProfileManagerWrapper;
@@ -103,28 +101,7 @@ public View onCreateView(@NonNull LayoutInflater inflater,
setPreSharedKey(presharedKey, inflater.getContext());
});
- // Enable trace logs
Preferences preferences = new Preferences(inflater.getContext());
- binding.switchTraceLog.setChecked(preferences.isTraceLogEnabled());
-
- // Handle trace log switch toggle
- binding.switchTraceLog.setOnCheckedChangeListener((buttonView, isChecked) -> {
- if (isChecked) {
- preferences.enableTraceLog();
- } else {
- preferences.disableTraceLog();
- }
- });
-
- // Make parent layout clickable to toggle switch (for TV remote)
- binding.traceLogLayout.setOnClickListener(v -> {
- binding.switchTraceLog.toggle();
- });
-
- // Handle "Share Logs" button click
- binding.buttonShareLogs.setOnClickListener(v -> {
- shareLog();
- });
// Rosenpass settings
try {
@@ -362,17 +339,4 @@ private boolean hasPreSharedKey(Context context) {
}
}
- private void shareLog() {
- Activity activity = getActivity();
- if (activity == null) {
- return;
- }
-
- try {
- Logcat logcat = new Logcat(activity);
- logcat.dump();
- } catch (Exception e) {
- Log.e(LOGTAG, "failed to dump log", e);
- }
- }
}
diff --git a/app/src/main/java/io/netbird/client/ui/troubleshoot/TroubleshootFragment.java b/app/src/main/java/io/netbird/client/ui/troubleshoot/TroubleshootFragment.java
new file mode 100644
index 00000000..7d6fffe6
--- /dev/null
+++ b/app/src/main/java/io/netbird/client/ui/troubleshoot/TroubleshootFragment.java
@@ -0,0 +1,92 @@
+package io.netbird.client.ui.troubleshoot;
+
+import android.app.Activity;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+
+import io.netbird.client.R;
+import io.netbird.client.ServiceAccessor;
+import io.netbird.client.databinding.FragmentTroubleshootBinding;
+import io.netbird.client.tool.Preferences;
+
+public class TroubleshootFragment extends Fragment {
+
+ private static final String LOGTAG = "TroubleshootFragment";
+ private FragmentTroubleshootBinding binding;
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ binding = FragmentTroubleshootBinding.inflate(inflater, container, false);
+
+ Preferences preferences = new Preferences(inflater.getContext());
+ binding.switchTraceLog.setChecked(preferences.isTraceLogEnabled());
+
+ binding.switchTraceLog.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ if (isChecked) {
+ preferences.enableTraceLog();
+ } else {
+ preferences.disableTraceLog();
+ }
+ });
+
+ binding.traceLogLayout.setOnClickListener(v -> {
+ binding.switchTraceLog.toggle();
+ });
+
+ binding.anonymizeLayout.setOnClickListener(v -> {
+ binding.switchAnonymize.toggle();
+ });
+
+ binding.buttonDebugBundle.setOnClickListener(v -> {
+ generateDebugBundle();
+ });
+
+ return binding.getRoot();
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ binding = null;
+ }
+
+ private void generateDebugBundle() {
+ Activity activity = getActivity();
+ if (activity == null || !(activity instanceof ServiceAccessor)) {
+ return;
+ }
+
+ boolean anonymize = binding.switchAnonymize.isChecked();
+ binding.buttonDebugBundle.setEnabled(false);
+ new Thread(() -> {
+ try {
+ String key = ((ServiceAccessor) activity).debugBundle(anonymize);
+ activity.runOnUiThread(() -> {
+ if (binding == null || !isAdded()) return;
+ binding.buttonDebugBundle.setEnabled(true);
+ ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipData clip = ClipData.newPlainText("Debug bundle key", key);
+ clipboard.setPrimaryClip(clip);
+ Toast.makeText(activity, "Debug bundle key copied to clipboard", Toast.LENGTH_SHORT).show();
+ });
+ } catch (Exception e) {
+ Log.e(LOGTAG, "failed to create debug bundle", e);
+ activity.runOnUiThread(() -> {
+ if (binding == null || !isAdded()) return;
+ binding.buttonDebugBundle.setEnabled(true);
+ Toast.makeText(activity, "Failed to create debug bundle: " + e.getMessage(), Toast.LENGTH_LONG).show();
+ });
+ }
+ }).start();
+ }
+}
diff --git a/app/src/main/res/drawable-hdpi/ic_menu_about.png b/app/src/main/res/drawable-hdpi/ic_menu_about.png
deleted file mode 100644
index dbe0a307..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_menu_about.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_menu_advanced.png b/app/src/main/res/drawable-hdpi/ic_menu_advanced.png
deleted file mode 100644
index d2ffac1f..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_menu_advanced.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_menu_change_server.png b/app/src/main/res/drawable-hdpi/ic_menu_change_server.png
deleted file mode 100644
index eba2e0ed..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_menu_change_server.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_menu_docs.png b/app/src/main/res/drawable-hdpi/ic_menu_docs.png
deleted file mode 100644
index 9529c358..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_menu_docs.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_menu_about.png b/app/src/main/res/drawable-mdpi/ic_menu_about.png
deleted file mode 100644
index c84b3218..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_menu_about.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_menu_advanced.png b/app/src/main/res/drawable-mdpi/ic_menu_advanced.png
deleted file mode 100644
index cb3ff32a..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_menu_advanced.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_menu_change_server.png b/app/src/main/res/drawable-mdpi/ic_menu_change_server.png
deleted file mode 100644
index 5f9e6701..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_menu_change_server.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_menu_docs.png b/app/src/main/res/drawable-mdpi/ic_menu_docs.png
deleted file mode 100644
index 03cefc6e..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_menu_docs.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_menu_about.png b/app/src/main/res/drawable-xhdpi/ic_menu_about.png
deleted file mode 100644
index 49183765..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_menu_about.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_menu_advanced.png b/app/src/main/res/drawable-xhdpi/ic_menu_advanced.png
deleted file mode 100644
index dc15c100..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_menu_advanced.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_menu_change_server.png b/app/src/main/res/drawable-xhdpi/ic_menu_change_server.png
deleted file mode 100644
index abc46db3..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_menu_change_server.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_menu_docs.png b/app/src/main/res/drawable-xhdpi/ic_menu_docs.png
deleted file mode 100644
index 0ef79f45..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_menu_docs.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_menu_about.png b/app/src/main/res/drawable-xxhdpi/ic_menu_about.png
deleted file mode 100644
index 5837beb0..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_menu_about.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_menu_advanced.png b/app/src/main/res/drawable-xxhdpi/ic_menu_advanced.png
deleted file mode 100644
index b7ad9ff3..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_menu_advanced.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_menu_change_server.png b/app/src/main/res/drawable-xxhdpi/ic_menu_change_server.png
deleted file mode 100644
index 4c991899..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_menu_change_server.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_menu_docs.png b/app/src/main/res/drawable-xxhdpi/ic_menu_docs.png
deleted file mode 100644
index 6862e799..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_menu_docs.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_menu_about.png b/app/src/main/res/drawable-xxxhdpi/ic_menu_about.png
deleted file mode 100644
index f8497e63..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_menu_about.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_menu_advanced.png b/app/src/main/res/drawable-xxxhdpi/ic_menu_advanced.png
deleted file mode 100644
index 36c1fa69..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_menu_advanced.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_menu_change_server.png b/app/src/main/res/drawable-xxxhdpi/ic_menu_change_server.png
deleted file mode 100644
index d6187ca1..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_menu_change_server.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_menu_docs.png b/app/src/main/res/drawable-xxxhdpi/ic_menu_docs.png
deleted file mode 100644
index f0ae1d5c..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_menu_docs.png and /dev/null differ
diff --git a/app/src/main/res/drawable/ic_menu_about.xml b/app/src/main/res/drawable/ic_menu_about.xml
new file mode 100644
index 00000000..8f674e76
--- /dev/null
+++ b/app/src/main/res/drawable/ic_menu_about.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_menu_advanced.xml b/app/src/main/res/drawable/ic_menu_advanced.xml
new file mode 100644
index 00000000..37563dd5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_menu_advanced.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_menu_change_server.xml b/app/src/main/res/drawable/ic_menu_change_server.xml
new file mode 100644
index 00000000..b0bc26ea
--- /dev/null
+++ b/app/src/main/res/drawable/ic_menu_change_server.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_menu_docs.xml b/app/src/main/res/drawable/ic_menu_docs.xml
new file mode 100644
index 00000000..7173201c
--- /dev/null
+++ b/app/src/main/res/drawable/ic_menu_docs.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_menu_troubleshoot.xml b/app/src/main/res/drawable/ic_menu_troubleshoot.xml
new file mode 100644
index 00000000..9856cc1e
--- /dev/null
+++ b/app/src/main/res/drawable/ic_menu_troubleshoot.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_advanced.xml b/app/src/main/res/layout/fragment_advanced.xml
index c25aa711..ad46aea4 100644
--- a/app/src/main/res/layout/fragment_advanced.xml
+++ b/app/src/main/res/layout/fragment_advanced.xml
@@ -76,63 +76,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/preshared_key" />
-
-
-
-
-
-
-
-
-
-
-
+ app:layout_constraintTop_toBottomOf="@id/btn_save" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml
index 19a6b4c6..bcbd34d0 100644
--- a/app/src/main/res/menu/activity_main_drawer.xml
+++ b/app/src/main/res/menu/activity_main_drawer.xml
@@ -16,16 +16,20 @@
android:icon="@drawable/ic_menu_advanced"
android:title="@string/menu_advanced" />
+ android:id="@+id/nav_change_server"
+ android:icon="@drawable/ic_menu_change_server"
+ android:title="@string/menu_change_server" />
+ android:id="@+id/nav_troubleshoot"
+ android:icon="@drawable/ic_menu_troubleshoot"
+ android:title="@string/menu_troubleshoot" />
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml
index a49b0332..3f749393 100644
--- a/app/src/main/res/navigation/mobile_navigation.xml
+++ b/app/src/main/res/navigation/mobile_navigation.xml
@@ -18,6 +18,12 @@
android:label="@string/menu_advanced"
tools:layout="@layout/fragment_advanced" />
+
+
Docs
Change Server
Profiles
+ Troubleshoot
Disconnected
background mask
@@ -77,6 +78,8 @@
Failed to save pre-shared key
Enable trace log level.
Share logs
+ Upload debug bundle
+ Anonymize sensitive data
Enable Rosenpass
Enable Rosenpass permissive mode.
Network & Security
diff --git a/netbird b/netbird
index 4eed459f..f01c1eea 160000
--- a/netbird
+++ b/netbird
@@ -1 +1 @@
-Subproject commit 4eed459f27bd7e90faa7fe99e1edf4a59dc71265
+Subproject commit f01c1eea6ac803fff4678abe93f95b4c965e372b
diff --git a/tool/src/main/java/io/netbird/client/tool/AndroidPlatformFiles.java b/tool/src/main/java/io/netbird/client/tool/AndroidPlatformFiles.java
index cbac637b..b65e2440 100644
--- a/tool/src/main/java/io/netbird/client/tool/AndroidPlatformFiles.java
+++ b/tool/src/main/java/io/netbird/client/tool/AndroidPlatformFiles.java
@@ -5,10 +5,12 @@
public class AndroidPlatformFiles implements PlatformFiles {
private final String configurationFilePath;
private final String stateFilePath;
+ private final String cacheDir;
- public AndroidPlatformFiles(String configurationFilePath, String stateFilePath) {
+ public AndroidPlatformFiles(String configurationFilePath, String stateFilePath, String cacheDir) {
this.configurationFilePath = configurationFilePath;
this.stateFilePath = stateFilePath;
+ this.cacheDir = cacheDir;
}
@Override
@@ -20,4 +22,9 @@ public String configurationFilePath() {
public String stateFilePath() {
return stateFilePath;
}
+
+ @Override
+ public String cacheDir() {
+ return cacheDir;
+ }
}
diff --git a/tool/src/main/java/io/netbird/client/tool/EngineRunner.java b/tool/src/main/java/io/netbird/client/tool/EngineRunner.java
index 703cbd4d..dfdbf846 100644
--- a/tool/src/main/java/io/netbird/client/tool/EngineRunner.java
+++ b/tool/src/main/java/io/netbird/client/tool/EngineRunner.java
@@ -91,7 +91,7 @@ private synchronized void runClient(@Nullable URLOpener urlOpener, boolean isAnd
// Create fresh PlatformFiles with current config/state paths
// This allows profile switching without recreating the entire Client
- var platformFiles = new AndroidPlatformFiles(configurationFilePath, stateFilePath);
+ var platformFiles = new AndroidPlatformFiles(configurationFilePath, stateFilePath, context.getCacheDir().getAbsolutePath());
Log.d(LOGTAG, "Running engine with config: " + configurationFilePath + ", state: " + stateFilePath);
try {
@@ -214,6 +214,19 @@ public void renewTUN(int fd) {
}
}
+ public String debugBundle(boolean anonymize) throws Exception {
+ String configPath = profileManager.getActiveConfigPath();
+ String statePath = profileManager.getActiveStateFilePath();
+ String cacheDir = context.getCacheDir().getAbsolutePath();
+ var platformFiles = new AndroidPlatformFiles(configPath, statePath, cacheDir);
+ try {
+ return goClient.debugBundle(platformFiles, anonymize);
+ } catch (Exception e) {
+ Log.e(LOGTAG, "goClient error", e);
+ throw e;
+ }
+ }
+
public void selectRoute(String route) throws Exception {
Log.d(LOGTAG, String.format("selecting route: %s", route));
try {
diff --git a/tool/src/main/java/io/netbird/client/tool/VPNService.java b/tool/src/main/java/io/netbird/client/tool/VPNService.java
index 548ae3ce..8494d48d 100644
--- a/tool/src/main/java/io/netbird/client/tool/VPNService.java
+++ b/tool/src/main/java/io/netbird/client/tool/VPNService.java
@@ -239,6 +239,10 @@ public void removeRouteChangeListener(RouteChangeListener listener) {
}
}
+ public String debugBundle(boolean anonymize) throws Exception {
+ return engineRunner.debugBundle(anonymize);
+ }
+
public void selectRoute(String route) throws Exception {
engineRunner.selectRoute(route);
}