mirror of
https://github.com/PurpleI2P/i2pd-android.git
synced 2025-03-10 12:31:41 +00:00
Perferences (#66)
This commit is contained in:
parent
938a85bc3c
commit
cf5fe2e948
@ -5,14 +5,29 @@ plugins {
|
||||
dependencies {
|
||||
implementation 'androidx.core:core:1.9.0'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
// implementation 'org.ini4j:ini4j:0.5.4'
|
||||
implementation 'org.apache.commons:commons-configuration2:2.9.0'
|
||||
}
|
||||
configurations {
|
||||
all{
|
||||
//exclude group: 'commons-logging', module: 'commons-logging'
|
||||
//exclude group: 'org.apache.httpcomponents'
|
||||
exclude module: 'httpclient'
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
lintOptions {
|
||||
// Not so a good way
|
||||
disable 'DuplicatePlatformClasses'
|
||||
}
|
||||
|
||||
compileSdkVersion 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId "org.purplei2p.i2pd"
|
||||
targetSdkVersion 33
|
||||
// TODO: 24?
|
||||
minSdkVersion 16
|
||||
versionCode 2500200
|
||||
versionName "2.50.2"
|
||||
|
@ -23,6 +23,17 @@
|
||||
android:theme="@android:style/Theme.DeviceDefault"
|
||||
android:usesCleartextTraffic="true">
|
||||
|
||||
<service
|
||||
android:name=".I2PdQSTileService"
|
||||
android:exported="true"
|
||||
android:label="I2Pd"
|
||||
android:icon="@drawable/ic_logo"
|
||||
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.quicksettings.action.QS_TILE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<receiver
|
||||
android:enabled="true"
|
||||
android:name="org.purplei2p.i2pd.receivers.BootUpReceiver"
|
||||
@ -64,6 +75,8 @@
|
||||
|
||||
<service
|
||||
android:name=".ForegroundService"
|
||||
android:exported="false"
|
||||
android:stopWithTask="false"
|
||||
android:enabled="true" />
|
||||
|
||||
<activity
|
||||
@ -74,5 +87,11 @@
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.purplei2p.i2pd.I2PDPermsAskerActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".MainPreferenceActivity"
|
||||
android:label="Settings"
|
||||
>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
|
@ -111,7 +111,7 @@ public class I2PDActivity extends Activity {
|
||||
Log.d(TAG, "onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
startService(new Intent(this, ForegroundService.class));
|
||||
textView = (TextView) findViewById(R.id.appStatusText);
|
||||
HTTPProxyState = (CheckBox) findViewById(R.id.service_httpproxy_box);
|
||||
SOCKSProxyState = (CheckBox) findViewById(R.id.service_socksproxy_box);
|
||||
|
@ -183,6 +183,7 @@ public class I2PDPermsAskerActivity extends Activity {
|
||||
}
|
||||
}
|
||||
} else if (requestCode == APP_STORAGE_ACCESS_REQUEST_CODE && resultCode == RESULT_OK) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
if (Environment.isExternalStorageManager()) {
|
||||
startMainActivity();
|
||||
} else {
|
||||
@ -195,5 +196,6 @@ public class I2PDPermsAskerActivity extends Activity {
|
||||
} else {
|
||||
finish(); // close the app
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
56
app/src/main/java/org/purplei2p/i2pd/I2PdQSTileService.java
Normal file
56
app/src/main/java/org/purplei2p/i2pd/I2PdQSTileService.java
Normal file
@ -0,0 +1,56 @@
|
||||
package org.purplei2p.i2pd;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.service.quicksettings.Tile;
|
||||
import android.service.quicksettings.TileService;
|
||||
import android.util.Log;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
public class I2PdQSTileService extends TileService {
|
||||
|
||||
private static final String TAG = "MyQSTileService";
|
||||
@Override
|
||||
public void onClick() {
|
||||
super.onClick();
|
||||
Log.d(TAG, "Tile clicked.");
|
||||
|
||||
try {
|
||||
// Add the FLAG_ACTIVITY_NEW_TASK flag
|
||||
Intent intent = new Intent(this, I2PDActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
startActivityAndCollapse(intent);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error starting ForegroundService", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onStartListening() {
|
||||
super.onStartListening();
|
||||
Log.d(TAG, "Tile started listening.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopListening() {
|
||||
super.onStopListening();
|
||||
Log.d(TAG, "Tile stopped listening.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTileAdded() {
|
||||
super.onTileAdded();
|
||||
Log.d(TAG, "Tile added.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTileRemoved() {
|
||||
super.onTileRemoved();
|
||||
Log.d(TAG, "Tile removed.");
|
||||
}
|
||||
}
|
459
app/src/main/java/org/purplei2p/i2pd/MainPreferenceActivity.java
Normal file
459
app/src/main/java/org/purplei2p/i2pd/MainPreferenceActivity.java
Normal file
@ -0,0 +1,459 @@
|
||||
package org.purplei2p.i2pd;
|
||||
import android.os.Build;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import android.util.Log;
|
||||
import java.io.File;
|
||||
import org.apache.commons.configuration2.INIConfiguration;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.*;
|
||||
|
||||
public class MainPreferenceActivity extends PreferenceActivity {
|
||||
private Boolean isOldConfigExists = false;
|
||||
public static final String CONFIG_FILE_PATH = "/sdcard/i2pd/i2pd.conf";
|
||||
private static final String OLD_FILE_PREFIX= "__old";
|
||||
|
||||
boolean isOldConfigExists()
|
||||
{
|
||||
try {
|
||||
return new File(CONFIG_FILE_PATH + OLD_FILE_PREFIX).exists();
|
||||
}catch(Exception e) { return false; }
|
||||
}
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.preferences_i2pd);
|
||||
INIConfiguration properties = readConfiguration();
|
||||
// backup old configuration.
|
||||
if (!isOldConfigExists)
|
||||
{
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (Files.exists(Paths.get(CONFIG_FILE_PATH))) {
|
||||
Files.copy(Paths.get(CONFIG_FILE_PATH), Paths.get(CONFIG_FILE_PATH + OLD_FILE_PREFIX));
|
||||
}
|
||||
} // if build ...
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
// delete empty sections
|
||||
{
|
||||
writeConfiguration(properties);
|
||||
}
|
||||
// Main Categoryре
|
||||
ListPreference logLevel = (ListPreference) findPreference("logLevelPreference");
|
||||
logLevel.setValue(properties.getString("log", "info"));
|
||||
logLevel.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
// Modify properties
|
||||
//properties.setProperty("log", (String) newValue);
|
||||
// Save modified properties
|
||||
//writeConfiguration(properties);
|
||||
writeConfiguration(properties, "log", (String) newValue);
|
||||
return true;
|
||||
});
|
||||
|
||||
CheckBoxPreference ipv4Enable = (CheckBoxPreference) findPreference("ipv4EnablePreference");
|
||||
boolean ipv4Enabled = Boolean.parseBoolean(properties.getString("ipv4", "true")); // "true" - значение по умолчанию, если ключ отсутствует
|
||||
ipv4Enable.setChecked(ipv4Enabled);
|
||||
ipv4Enable.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
// Modify properties
|
||||
// Convert Object to boolean
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
//properties.setProperty("ipv4", String.valueOf(newValueBoolean)); // assuming "ipv4" is the key
|
||||
// Save modified properties
|
||||
writeConfiguration(properties, "ipv4", String.valueOf(newValueBoolean));
|
||||
return true;
|
||||
});
|
||||
CheckBoxPreference ipv6Enable = (CheckBoxPreference) findPreference("ipv6EnablePreference");
|
||||
boolean ipv6Enabled = Boolean.parseBoolean(properties.getString("ipv6", "false"));
|
||||
ipv6Enable.setChecked(ipv6Enabled);
|
||||
ipv6Enable.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
// Modify properties
|
||||
// Convert Object to boolean
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
//properties.setProperty("ipv6", String.valueOf(newValueBoolean)); // assuming "ipv4" is the key
|
||||
// Save modified properties
|
||||
writeConfiguration(properties, "ipv6", String.valueOf(newValueBoolean));
|
||||
return true;
|
||||
});
|
||||
// Example for portPreference (EditTextPreference)
|
||||
EditTextPreference portPreference = (EditTextPreference) findPreference("portPreference");
|
||||
String portValue = properties.getString("port", "auto");
|
||||
portPreference.setText(portValue);
|
||||
portPreference.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
// Modify properties
|
||||
/*Properties properties = readProperties();
|
||||
// Convert Object to String (assuming "port" is the key)
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("port", newValueString);
|
||||
// Save modified properties
|
||||
writeProperties(properties);*/
|
||||
Toast.makeText(MainPreferenceActivity.this, "For security reasons, changes are not allowed. If you really want this, open the config.", Toast.LENGTH_SHORT).show();
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// Example for bandwidthPreference (ListPreference)
|
||||
ListPreference bandwidthPreference = (ListPreference) findPreference("bandwidthPreference");
|
||||
String bandwidthValue = properties.getString("bandwidth", "L");
|
||||
bandwidthPreference.setValue(bandwidthValue);
|
||||
bandwidthPreference.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
//properties.setProperty("bandwidth", newValueString);
|
||||
writeConfiguration(properties, "bandwidth", newValueString);
|
||||
return true;
|
||||
});
|
||||
// Example for noTransitPreference (CheckBoxPreference)
|
||||
CheckBoxPreference noTransitPreference = (CheckBoxPreference) findPreference("noTransitPreference");
|
||||
boolean noTransitPreferenceEnabled = Boolean.parseBoolean(properties.getString("notransit", "false"));
|
||||
noTransitPreference.setChecked(noTransitPreferenceEnabled);
|
||||
|
||||
noTransitPreference.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
//properties.setProperty("notransit", String.valueOf(newValueBoolean));
|
||||
writeConfiguration(properties, "notransit", String.valueOf(newValueBoolean));
|
||||
return true;
|
||||
});
|
||||
CheckBoxPreference floodfillPreference = (CheckBoxPreference) findPreference("floodfillPreference");
|
||||
boolean floodfillPreferenceEnabled = Boolean.parseBoolean(properties.getString("floodfill", "false"));
|
||||
floodfillPreference.setChecked(floodfillPreferenceEnabled);
|
||||
floodfillPreference.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
//properties.setProperty("floodfill", String.valueOf(newValueBoolean));
|
||||
writeConfiguration(properties, "floodfill", String.valueOf(newValueBoolean));
|
||||
return true;
|
||||
});
|
||||
// ^^^ general
|
||||
// vvv not general (sections name)
|
||||
CheckBoxPreference ssuPreference = (CheckBoxPreference) findPreference("ssuPreference");
|
||||
boolean ssuPreferenceEnabled = Boolean.parseBoolean(properties.getString("ssu2.enabled", "true"));
|
||||
ssuPreference.setChecked(ssuPreferenceEnabled);
|
||||
ssuPreference.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
|
||||
properties.setProperty("ssu2.enabled", String.valueOf(newValueBoolean));
|
||||
writeConfiguration(properties);
|
||||
|
||||
return true; // Allow the change
|
||||
});
|
||||
// NTCP2 Category
|
||||
CheckBoxPreference ntcp2Enable = (CheckBoxPreference) findPreference("ntcp2EnablePreference");
|
||||
|
||||
boolean ntcp2EnabledPreference = Boolean.parseBoolean(properties.getString("ntcp2.enabled", "true"));
|
||||
ntcp2Enable.setChecked(ntcp2EnabledPreference);
|
||||
|
||||
|
||||
ntcp2Enable.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
|
||||
properties.setProperty("ntcp2.enabled", String.valueOf(newValueBoolean));
|
||||
writeConfiguration(properties);
|
||||
|
||||
return true; // Allow the change
|
||||
});
|
||||
CheckBoxPreference ntcp2Publish = (CheckBoxPreference) findPreference("ntcp2PublishPreference");
|
||||
|
||||
boolean ntcp2PublishEnabledPreference = Boolean.parseBoolean(properties.getString("ntcp2.published", "true"));
|
||||
ntcp2Publish.setChecked(ntcp2EnabledPreference);
|
||||
|
||||
|
||||
ntcp2Publish.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
|
||||
properties.setProperty("ntcp2.published", String.valueOf(newValueBoolean));
|
||||
writeConfiguration(properties);
|
||||
|
||||
return true; // Allow the change
|
||||
});
|
||||
// Web Console Category
|
||||
CheckBoxPreference webConsoleEnable = (CheckBoxPreference) findPreference("webConsoleEnablePreference");
|
||||
boolean webConsoleEnableValue = Boolean.parseBoolean(properties.getString("http.enabled", "false"));
|
||||
webConsoleEnable.setChecked(webConsoleEnableValue);
|
||||
|
||||
webConsoleEnable.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
properties.setProperty("http.enabled", String.valueOf(newValueBoolean));
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference webConsoleAddress = (EditTextPreference) findPreference("webConsoleAddressPreference");
|
||||
String webConsoleAddressValue = properties.getString("http.address", "127.0.0.1");
|
||||
webConsoleAddress.setText(webConsoleAddressValue);
|
||||
webConsoleAddress.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("http.address", newValueString);
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference webConsolePort = (EditTextPreference) findPreference("webConsolePortPreference");
|
||||
String webConsolePortValue = properties.getString("http.port", "7070");
|
||||
webConsolePort.setText(webConsolePortValue);
|
||||
webConsolePort.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("http.port", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
CheckBoxPreference webConsoleAuth = (CheckBoxPreference) findPreference("webConsoleAuthPreference");
|
||||
boolean webConsoleAuthValue = Boolean.parseBoolean(properties.getString("http.auth", "false"));
|
||||
webConsoleAuth.setChecked(webConsoleAuthValue);
|
||||
webConsoleAuth.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
properties.setProperty("http.auth", String.valueOf(newValueBoolean));
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference webConsoleUser = (EditTextPreference) findPreference("webConsoleUserPreference");
|
||||
String webConsoleUserValue = properties.getString("http.user", "user");
|
||||
webConsoleUser.setText(webConsoleUserValue);
|
||||
webConsoleUser.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("http.user", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference webConsolePassword = (EditTextPreference) findPreference("webConsolePasswordPreference");
|
||||
String webConsolePasswordValue = properties.getString("http.pass", "pass");
|
||||
webConsolePassword.setText(webConsolePasswordValue);
|
||||
|
||||
webConsolePassword.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("http.pass", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
// HTTP Proxy Category
|
||||
CheckBoxPreference httpProxyEnable = (CheckBoxPreference) findPreference("httpProxyEnablePreference");
|
||||
boolean httpProxyEnabled = Boolean.parseBoolean(properties.getString("httpproxy.enabled", "true"));
|
||||
httpProxyEnable.setChecked(httpProxyEnabled);
|
||||
httpProxyEnable.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
properties.setProperty("httpproxy.enabled", String.valueOf(newValueBoolean));
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference httpProxyAddress = (EditTextPreference) findPreference("httpProxyAddressPreference");
|
||||
String httpProxyAddressValue = properties.getString("httpproxy.address", "127.0.0.1");
|
||||
httpProxyAddress.setText(httpProxyAddressValue);
|
||||
|
||||
httpProxyAddress.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("httpproxy.address", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference httpProxyPort = (EditTextPreference) findPreference("httpProxyPortPreference");
|
||||
String httpProxyPortValue = properties.getString("httpproxy.port", "4444");
|
||||
httpProxyPort.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("httpproxy.port", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference httpProxyKeys = (EditTextPreference) findPreference("httpProxyKeysPreference");
|
||||
String httpProxyKeyValue = properties.getString("httpproxy.keys", "transient");
|
||||
httpProxyKeys.setText(httpProxyKeyValue);
|
||||
httpProxyKeys.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("httpproxy.keys", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
|
||||
// SOCKS Proxy Category
|
||||
CheckBoxPreference socksProxyEnable = (CheckBoxPreference) findPreference("socksProxyEnablePreference");
|
||||
boolean socksProxyEnabled = Boolean.parseBoolean(properties.getString("socksproxy.enabled", "true"));
|
||||
socksProxyEnable.setChecked(socksProxyEnabled);
|
||||
socksProxyEnable.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
properties.setProperty("socksproxy.enabled", String.valueOf(newValueBoolean));
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference socksProxyAddress = (EditTextPreference) findPreference("socksProxyAddressPreference");
|
||||
String socksProxyAddressValue = properties.getString("socksproxy.address", "127.0.0.1");
|
||||
socksProxyAddress.setText(socksProxyAddressValue);
|
||||
socksProxyAddress.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("socksproxy.address", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference socksProxyPort = (EditTextPreference) findPreference("socksProxyPortPreference");
|
||||
String socksProxyPortValue = properties.getString("socksproxy.port", "4447");
|
||||
socksProxyPort.setText(socksProxyPortValue);
|
||||
socksProxyPort.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("socksproxy.port", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference socksProxyKeys = (EditTextPreference) findPreference("socksProxyKeysPreference");
|
||||
String socksProxyKeysValue = properties.getString("socksproxy.keys", "transient");
|
||||
socksProxyKeys.setText(socksProxyKeysValue);
|
||||
socksProxyKeys.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("socksproxy.keys", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
// SAM Category
|
||||
CheckBoxPreference samEnable = (CheckBoxPreference) findPreference("samEnablePreference");
|
||||
boolean samEnableValue = Boolean.parseBoolean(properties.getString("sam.enabled", "true"));
|
||||
samEnable.setChecked(samEnableValue);
|
||||
samEnable.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
properties.setProperty("sam.enabled", String.valueOf(newValueBoolean));
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference samAddress = (EditTextPreference) findPreference("samAddressPreference");
|
||||
String samAddressValue = properties.getString("sam.address", "127.0.0.1");
|
||||
samAddress.setText(samAddressValue);
|
||||
samAddress.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("sam.address", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference samPort = (EditTextPreference) findPreference("samPortPreference");
|
||||
String samPortValue = properties.getString("sam.port", "7656");
|
||||
samPort.setText(samPortValue);
|
||||
samPort.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("sam.port", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
// UPnP Category
|
||||
CheckBoxPreference upnpEnable = (CheckBoxPreference) findPreference("upnpEnablePreference");
|
||||
boolean upnpEnableValue = Boolean.parseBoolean(properties.getString("upnp.enabled", "true"));
|
||||
upnpEnable.setChecked(upnpEnableValue);
|
||||
upnpEnable.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean newValueBoolean = (boolean) newValue;
|
||||
properties.setProperty("upnp.enabled", String.valueOf(newValueBoolean));
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
EditTextPreference upnpForwardName = (EditTextPreference) findPreference("upnpForwardNamePreference");
|
||||
String upnpForwardNameValue = properties.getString("upnp.name", "I2Pd");
|
||||
upnpForwardName.setText(upnpForwardNameValue);
|
||||
upnpForwardName.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("upnp.name", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
// Limits Category
|
||||
EditTextPreference transitTunnelEdit = (EditTextPreference) findPreference("transitTunnelPreference");
|
||||
String transitTunnelValue = properties.getString("limits.transittunnels", "3000");
|
||||
transitTunnelEdit.setText(transitTunnelValue);
|
||||
transitTunnelEdit.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String newValueString = newValue.toString();
|
||||
properties.setProperty("limits.transittunnels", newValueString);
|
||||
// Save modified properties
|
||||
writeConfiguration(properties);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
/*
|
||||
private Properties readProperties() {
|
||||
if (isOldConfigExists) {
|
||||
Toast.makeText(this, oldConfigErrMsg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
Properties properties = new Properties();
|
||||
try (FileReader reader = new FileReader(CONFIG_FILE_PATH)) {
|
||||
properties.load(reader);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
private void writeProperties(Properties properties) {
|
||||
if (isOldConfigExists) {
|
||||
Toast.makeText(this, oldConfigErrMsg, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
try (FileWriter writer = new FileWriter(CONFIG_FILE_PATH)) {
|
||||
properties.store(writer, "Updated properties");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
private INIConfiguration readConfiguration() {
|
||||
INIConfiguration iniConfiguration = new INIConfiguration();
|
||||
try (FileReader reader = new FileReader(CONFIG_FILE_PATH)) {
|
||||
iniConfiguration.read(reader);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return iniConfiguration;
|
||||
}
|
||||
private void writeConfiguration(INIConfiguration iniConfiguration)
|
||||
{
|
||||
writeConfiguration(iniConfiguration, "", "");
|
||||
}
|
||||
private void writeConfiguration(INIConfiguration iniConfiguration, String option, String value) {
|
||||
try (FileWriter writer = new FileWriter(CONFIG_FILE_PATH)) {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
iniConfiguration.write(stringWriter);
|
||||
String configFileContent = stringWriter.toString();
|
||||
|
||||
// Удаление пустых секций из строки конфигурации
|
||||
String regexEmptySections = "(\\[\\w+\\]\\n(\\n|$)|\\[\\w+\\](\\z|\\Z))";
|
||||
configFileContent = configFileContent.replaceAll(regexEmptySections, "");
|
||||
|
||||
// Если указана опция для перемещения
|
||||
if (!option.isEmpty()) {
|
||||
Log.d("configFileContent","option is not empty");
|
||||
String optionPattern = option + "\\s+?=\\s+?\\w+"; // Паттерн для поиска опции с присваиванием в начале строки
|
||||
Log.d("confiFileContent","config File contains option");
|
||||
if (configFileContent.contains(option)) configFileContent = configFileContent.replaceAll(optionPattern, ""); // Удаляем первое вхождение
|
||||
Log.d("confiFileContent", option);
|
||||
Log.d("confiFileContent", value);
|
||||
Log.d("confiFileContent","Add on start line");
|
||||
configFileContent = option + "=" + value + "\n" + configFileContent;
|
||||
|
||||
}
|
||||
Log.d("configFileContent", configFileContent);
|
||||
writer.write(configFileContent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -11,8 +11,12 @@ import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.Switch;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@ -21,7 +25,6 @@ import java.util.Objects;
|
||||
//import org.purplei2p.i2pd.iniedotr.IniEditor;
|
||||
|
||||
public class SettingsActivity extends Activity {
|
||||
//protected IniEditor iniedit = new IniEditor();
|
||||
private String TAG = "i2pdSrvcSettings";
|
||||
private File cacheDir;
|
||||
public static String onBootFileName = "/onBoot"; // just file, empty, if exist the do autostart, if not then no.
|
||||
@ -83,9 +86,16 @@ public class SettingsActivity extends Activity {
|
||||
setContentView(R.layout.activity_settings);
|
||||
Objects.requireNonNull(getActionBar()).setDisplayHomeAsUpEnabled(true);
|
||||
Switch autostart_switch = findViewById(R.id.autostart_enable);
|
||||
|
||||
Button openPreferences = findViewById(R.id.OpenPreferences);
|
||||
cacheDir = getApplicationContext().getCacheDir();
|
||||
File onBoot = new File(cacheDir.getAbsolutePath() + onBootFileName);
|
||||
openPreferences.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent intent = new Intent(SettingsActivity.this, MainPreferenceActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
autostart_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
// do something, the isChecked will be
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -52,7 +52,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Large"
|
||||
android:textAppearance="@android:style/TextAppearance.Large"
|
||||
android:textColor="#DFDFDF" />
|
||||
|
||||
<Space
|
||||
@ -65,7 +65,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/services"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Medium"
|
||||
android:textAppearance="@android:style/TextAppearance.Medium"
|
||||
android:textColor="#DFDFDF" />
|
||||
|
||||
<TableLayout
|
||||
@ -84,7 +84,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="false"
|
||||
android:text="@string/services_http_proxy"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Small"
|
||||
android:textAppearance="@android:style/TextAppearance.Small"
|
||||
android:textColor="#DFDFDF" />
|
||||
|
||||
</TableRow>
|
||||
@ -100,7 +100,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="false"
|
||||
android:text="@string/services_socks_proxy"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Small"
|
||||
android:textAppearance="@android:style/TextAppearance.Small"
|
||||
android:textColor="#DFDFDF" />
|
||||
</TableRow>
|
||||
|
||||
@ -115,7 +115,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="false"
|
||||
android:text="@string/services_bob"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Small"
|
||||
android:textAppearance="@android:style/TextAppearance.Small"
|
||||
android:textColor="#DFDFDF" />
|
||||
</TableRow>
|
||||
|
||||
@ -130,7 +130,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="false"
|
||||
android:text="@string/services_sam"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Small"
|
||||
android:textAppearance="@android:style/TextAppearance.Small"
|
||||
android:textColor="#DFDFDF" />
|
||||
</TableRow>
|
||||
|
||||
@ -145,11 +145,11 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="false"
|
||||
android:text="@string/services_i2cp"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Small"
|
||||
android:textAppearance="@android:style/TextAppearance.Small"
|
||||
android:textColor="#DFDFDF" />
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
</ScrollView>
|
||||
|
@ -28,6 +28,18 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Button
|
||||
android:id="@+id/OpenPreferences"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/OpenPreferences" />
|
||||
</LinearLayout>
|
||||
<!--
|
||||
<TextView
|
||||
android:id="@+id/settings_section2"
|
||||
|
@ -43,4 +43,5 @@
|
||||
<string name="add_tunnel_button">Добавить туннель</string>
|
||||
<string name="add_tunnel">Управление туннелями</string>
|
||||
<string name="del_tunnel_button">Удалить туннель</string>
|
||||
<string name="OpenPreferences">Открыть основные настройки</string>
|
||||
</resources>
|
||||
|
@ -60,5 +60,6 @@
|
||||
<string name="add_tunnel">Tunnels management</string>
|
||||
|
||||
<string name="del_tunnel_button">Delete tunnel</string>
|
||||
<string name="OpenPreferences">Open i2pd settings</string>
|
||||
|
||||
</resources>
|
||||
|
@ -3,97 +3,108 @@
|
||||
|
||||
<PreferenceCategory android:title="Main">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="check_box_preference_1"
|
||||
android:title="Log" />
|
||||
<ListPreference
|
||||
android:id="@+id/LogLevel"
|
||||
android:defaultValue="1"
|
||||
android:entries="@array/pref_loglevel"
|
||||
android:entryValues="@array/pref_loglevel"
|
||||
android:key="list_preference_1"
|
||||
android:key="logLevelPreference"
|
||||
android:summary="Logging level to file. Use 'none' to reduce memory usage"
|
||||
android:title="Log level" />
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/IPV4Enable"
|
||||
android:defaultValue="true"
|
||||
android:key="check_box_preference_1"
|
||||
android:key="ipv4EnablePreference"
|
||||
android:title="IPv4" />
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/IPV6Enable"
|
||||
android:defaultValue="false"
|
||||
android:key="check_box_preference_1"
|
||||
android:key="ipv6EnablePreference"
|
||||
android:title="IPv6" />
|
||||
<EditTextPreference
|
||||
android:defaultValue="Default value"
|
||||
android:key="edit_text_preference_1"
|
||||
android:id="@+id/Port"
|
||||
android:defaultValue="auto"
|
||||
android:key="portPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Port" />
|
||||
<ListPreference
|
||||
android:id="@+id/BandWithType"
|
||||
android:entries="@array/pref_bandwidth_limit_flags"
|
||||
android:entryValues="@array/pref_bandwidth_limit_flags"
|
||||
android:key="list_preference_1"
|
||||
android:key="bandwidthPreference"
|
||||
android:summary="Bandwidth limit for transit traffic"
|
||||
android:title="Bandwidth" />
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/NoTransitCheckbox"
|
||||
android:defaultValue="false"
|
||||
android:key="check_box_preference_1"
|
||||
android:key="noTransitPreference"
|
||||
android:summary="Disable transit"
|
||||
android:title="No transit" />
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/FloodfillCheckBox"
|
||||
android:defaultValue="false"
|
||||
android:key="check_box_preference_1"
|
||||
android:key="floodfillPreference"
|
||||
android:summary="Uses more battery"
|
||||
android:title="Floodfill" />
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/SSUCheckBox"
|
||||
android:defaultValue="true"
|
||||
android:key="check_box_preference_1"
|
||||
android:key="ssuPreference"
|
||||
android:title="SSU" />
|
||||
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="NTCP2">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/NTCP2Checkbox"
|
||||
android:defaultValue="true"
|
||||
android:key="check_box_preference_1"
|
||||
android:key="ntcp2EnablePreference"
|
||||
android:title="Enable" />
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/NTCPPublishCheckbox"
|
||||
android:defaultValue="true"
|
||||
android:key="check_box_preference_1"
|
||||
android:key="ntcp2PublishPreference"
|
||||
android:summary="Disable to make unable to connect to your device"
|
||||
android:title="Publish" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="Web Console">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/WebConsoleEnableCheckbox"
|
||||
android:defaultValue="true"
|
||||
android:key="check_box_preference_1"
|
||||
android:key="webConsoleEnablePreference"
|
||||
android:title="Enable" />
|
||||
<EditTextPreference
|
||||
android:id="@+id/WebConsoleIPText"
|
||||
android:defaultValue="127.0.0.1"
|
||||
android:key="edit_text_preference_1"
|
||||
android:key="webConsoleAddressPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Address" />
|
||||
<EditTextPreference
|
||||
android:id="@+id/WebConsolePortText"
|
||||
android:defaultValue="7070"
|
||||
android:key="edit_text_preference_1"
|
||||
android:key="webConsolePortPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Port" />
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/WebConsoleUseAuthCheckbox"
|
||||
android:defaultValue="false"
|
||||
android:key="check_box_preference_1"
|
||||
android:key="webConsoleAuthPreference"
|
||||
android:summary="Use HTTP authorization to access Web Console"
|
||||
android:title="Autorization" />
|
||||
android:title="Authorization" />
|
||||
<EditTextPreference
|
||||
android:id="@+id/WebConsoleUser"
|
||||
android:defaultValue="Default value"
|
||||
android:key="edit_text_preference_1"
|
||||
android:key="webConsoleUserPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="User" />
|
||||
<EditTextPreference
|
||||
android:id="@+id/WebConsoleUserPassword"
|
||||
android:defaultValue="Default value"
|
||||
android:key="edit_text_preference_1"
|
||||
android:key="webConsolePasswordPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Password" />
|
||||
@ -101,24 +112,28 @@
|
||||
<PreferenceCategory android:title="@string/services_http_proxy">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/EnableHTTPProxy"
|
||||
android:defaultValue="true"
|
||||
android:key="check_box_preference_1"
|
||||
android:key="httpProxyEnablePreference"
|
||||
android:title="Enable" />
|
||||
<EditTextPreference
|
||||
android:id="@+id/HTTPProxyHost"
|
||||
android:defaultValue="127.0.0.1"
|
||||
android:key="edit_text_preference_1"
|
||||
android:key="httpProxyAddressPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Address" />
|
||||
<EditTextPreference
|
||||
android:id="@+id/HTTPProxyPort"
|
||||
android:defaultValue="4444"
|
||||
android:key="edit_text_preference_1"
|
||||
android:key="httpProxyPortPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Port" />
|
||||
<EditTextPreference
|
||||
android:defaultValue="proxy-keys.dat"
|
||||
android:key="edit_text_preference_1"
|
||||
android:id="@+id/HTTPProxyKeys"
|
||||
android:defaultValue="transient"
|
||||
android:key="httpProxyKeysPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Keys" />
|
||||
@ -126,24 +141,28 @@
|
||||
<PreferenceCategory android:title="SOCKS Proxy">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/SocksProxyEnableCheckbox"
|
||||
android:defaultValue="false"
|
||||
android:key="check_box_preference_1"
|
||||
android:key="socksProxyEnablePreference"
|
||||
android:title="Enable" />
|
||||
<EditTextPreference
|
||||
android:id="@+id/SocksProxyHost"
|
||||
android:defaultValue="127.0.0.1"
|
||||
android:key="edit_text_preference_1"
|
||||
android:key="socksProxyAddressPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Address" />
|
||||
<EditTextPreference
|
||||
android:id="@+id/SocksProxyPort"
|
||||
android:defaultValue="4447"
|
||||
android:key="edit_text_preference_1"
|
||||
android:key="socksProxyPortPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Port" />
|
||||
<EditTextPreference
|
||||
android:defaultValue="proxy-keys.dat"
|
||||
android:key="edit_text_preference_1"
|
||||
android:id="@+id/SocksProxyKey"
|
||||
android:defaultValue="transient"
|
||||
android:key="socksProxyKeysPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Keys" />
|
||||
@ -151,18 +170,21 @@
|
||||
<PreferenceCategory android:title="SAM">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/SAMEnable"
|
||||
android:defaultValue="false"
|
||||
android:key="check_box_preference_1"
|
||||
android:key="samEnablePreference"
|
||||
android:title="Enable" />
|
||||
<EditTextPreference
|
||||
android:id="@+id/SAMHost"
|
||||
android:defaultValue="127.0.0.1"
|
||||
android:key="edit_text_preference_1"
|
||||
android:key="samAddressPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Address" />
|
||||
<EditTextPreference
|
||||
android:id="@+id/SAMPort"
|
||||
android:defaultValue="7656"
|
||||
android:key="edit_text_preference_1"
|
||||
android:key="samPortPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Port" />
|
||||
@ -170,12 +192,14 @@
|
||||
<PreferenceCategory android:title="UPnP">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="check_box_preference_1"
|
||||
android:id="@+id/UPnPEnable"
|
||||
android:defaultValue="false"
|
||||
android:key="upnpEnablePreference"
|
||||
android:title="Enable" />
|
||||
<EditTextPreference
|
||||
android:id="@+id/UPnPForwardName"
|
||||
android:defaultValue="I2Pd"
|
||||
android:key="edit_text_preference_1"
|
||||
android:key="upnpForwardNamePreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="Forwarding name" />
|
||||
@ -183,11 +207,12 @@
|
||||
<PreferenceCategory android:title="Limits">
|
||||
|
||||
<EditTextPreference
|
||||
android:defaultValue="50"
|
||||
android:key="edit_text_preference_1"
|
||||
android:id="@+id/TransitTunnelEdit"
|
||||
android:defaultValue="3000"
|
||||
android:key="transitTunnelPreference"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:summary="Limit possible built transit tunnels"
|
||||
android:title="Transit tunnels" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
</PreferenceScreen>
|
||||
|
Loading…
x
Reference in New Issue
Block a user