...
 
Commits (376)
image: openjdk:8-jdk
variables:
ANDROID_COMPILE_SDK: "27"
ANDROID_BUILD_TOOLS: "27.0.3"
ANDROID_SDK_TOOLS: "26.0.2"
AVD_NAME: test
DEV_DEPLOY_DIR: /var/www/frostnerd/download/appbuilds/dnschanger/ci/dev
RELEASE_DEPLOY_DIR: /var/www/frostnerd/download/appbuilds/dnschanger/ci/releases
image: thyrlian/android-sdk
before_script:
- source /home/public/android-sdk-linux/initAndroid.sh -s ${ANDROID_COMPILE_SDK} -b ${ANDROID_BUILD_TOOLS}
- chmod +x gradlew
stages:
- init
- build
- test
- webdeploy
init:
stage: init
script:
- git config --file=.gitmodules submodule.AndroidUtils.url https://runner:$USER_PASS@git.frostnerd.com/AndroidApps/AndroidUtils.git
- git submodule sync
- git submodule update --init --recursive --force --remote
except:
- /^no_ci.*$/
build:
stage: build
script:
- /./home/public/gitrunner/changeAppVersion.sh app/build.gradle " $CI_COMMIT_REF_NAME\_$CI_PIPELINE_ID" --append
- chmod +x changeVersion.sh
- ./changeVersion.sh app/build.gradle " $CI_COMMIT_REF_NAME\_$CI_PIPELINE_ID" --append
- ./gradlew assembleDebug --stacktrace
artifacts:
paths:
......@@ -43,51 +25,35 @@ build:
build_release:
stage: build
script:
- ./gradlew clean check assembleRelease --stacktrace -Pandroid.injected.signing.store.file=$KEYSTORE_FILE -Pandroid.injected.signing.store.password=$KEYSTORE_PASSWORD -Pandroid.injected.signing.key.alias=$KEYSTORE_KEY_NAME -Pandroid.injected.signing.key.password=$KEYSTORE_KEY_PASSWORD -x test
only:
- release
- wget -O $KEYSTORE_FILE $KEYSTORE_URL -q
- ./gradlew clean check assembleRelease --stacktrace -Pandroid.injected.signing.store.file=$KEYSTORE_FILE -Pandroid.injected.signing.store.password=$KEYSTORE_PASSWORD -Pandroid.injected.signing.key.alias=$KEYSTORE_KEY_NAME -Pandroid.injected.signing.key.password=$KEYSTORE_KEY_PASSWORD -x test
artifacts:
paths:
- app/build/outputs/apk/release/app-release.apk
#upload:
# stage: webdeploy
# script:
# - cp -f app/build/outputs/apk/debug/app-debug.apk $DEV_DEPLOY_DIR/$CI_COMMIT_REF_NAME-$CI_PIPELINE_ID.apk
# - /./home/public/gitrunner/logCIBuilds.sh $DEV_DEPLOY_DIR
# - ln -s -f $DEV_DEPLOY_DIR/$CI_COMMIT_REF_NAME-$CI_PIPELINE_ID.apk $DEV_DEPLOY_DIR/0_latest_$CI_COMMIT_REF_NAME.apk
# except:
# - /^no_ci.*$/
# - /^no_deploy.*$/
# - /^no_tests_no_deploy.*$/
# - /^no_build_no_deploy.*$/
# - /^no_build.*$/
# - release
# artifacts:
# paths:
# - $DEV_DEPLOY_DIR/$CI_COMMIT_REF_NAME-$CI_PIPELINE_ID.apk
unitTests:
stage: test
script:
- ./gradlew test --stacktrace || (zip -r tests.zip AndroidUtils/library/build/reports/tests/ app/build/reports/tests && exit 1)
- zip -r tests.zip AndroidUtils/library/build/reports/tests/ app/build/reports/tests
except:
- /^no_ci.*$/
- /^no_tests.*$/
- /^no_build_no_tests.*$/
- /^no_tests_no_deploy.*$/
artifacts:
when: always
paths:
- tests.zip
upload:
stage: webdeploy
script:
- cp -f app/build/outputs/apk/debug/app-debug.apk $DEV_DEPLOY_DIR/$CI_COMMIT_REF_NAME-$CI_PIPELINE_ID.apk
- /./home/public/gitrunner/logCIBuilds.sh $DEV_DEPLOY_DIR
- ln -s -f $DEV_DEPLOY_DIR/$CI_COMMIT_REF_NAME-$CI_PIPELINE_ID.apk $DEV_DEPLOY_DIR/0_latest_$CI_COMMIT_REF_NAME.apk
except:
- /^no_ci.*$/
- /^no_deploy.*$/
- /^no_tests_no_deploy.*$/
- /^no_build_no_deploy.*$/
- /^no_build.*$/
- release
artifacts:
paths:
- $DEV_DEPLOY_DIR/$CI_COMMIT_REF_NAME-$CI_PIPELINE_ID.apk
upload_release:
stage: webdeploy
script:
- cp -f app/build/outputs/apk/release/app-release.apk $RELEASE_DEPLOY_DIR/$(/./home/public/gitrunner/determineAppVersionName.sh app/build/outputs/apk/release/app-release.apk).apk
only:
- release
#upload_release:
# stage: webdeploy
# script:
# - cp -f app/build/outputs/apk/release/app-release.apk $RELEASE_DEPLOY_DIR/$(/./home/public/gitrunner/determineAppVersionName.sh app/build/outputs/apk/release/app-release.apk).apk
# only:
# - release
#functionalTests:
# stage: test
......
[submodule "AndroidUtils"]
path = AndroidUtils
url = ../../AndroidApps/AndroidUtils
Subproject commit fd07ee7992e685e805b8752ffee26f0e9c09bdf5
[![build status](https://git.frostnerd.com/PublicAndroidApps/DnsChanger/badges/master/build.svg)](https://git.frostnerd.com/PublicAndroidApps/DnsChanger/commits/master)
[![build status](https://git.frostnerd.com/PublicAndroidApps/DnsChanger/badges/master/pipeline.svg)](https://git.frostnerd.com/PublicAndroidApps/DnsChanger/commits/master)
<br>You can download all artifacts at https://dl.frostnerd.com/appbuilds
They are unsigned.<br><br>
This is the source code for my app DNS Changer, which can be found here: https://play.google.com/store/apps/details?id=com.frostnerd.dnschanger<br><br>
**Important**: As it is quite old I'd suggest you to use my other app Nebulo. It doesn't have normal (unencrypted) DNS and rather relies on DNS-over-HTTPS and DNS-over-TLS (Private DNS). It also looks better and is more stable.<br>
It is open source as well. You can find it on Google Play [here](https://play.google.com/store/apps/details?id=com.frostnerd.smokescreen) and the source code [here](https://git.frostnerd.com/PublicAndroidApps/Smokescreen).
I'd suggest you check out the repo as it contains useful information and also information on how to download Nebulo using the F-Droid app.
Have a look at the wiki for this app: https://git.frostnerd.com/PublicAndroidApps/DnsChanger/wikis/home<br>
This app could possibly spy on using the VPN connection which has to be used to apply the choosen DNS Servers. It doesn't. This project is open source so that people familiar with java/Android can check on this promise.
If you are not familiar with it: The VPN is only local. Using the VPN you are assigned an IP-Address which can't be used in the internet (192.168.0.1) and connect to the device only (127.0.0.1:8087),
NOT to an endpoint in the internet. The relevant code lines are those: https://git.frostnerd.com/PublicAndroidApps/DnsChanger/blob/master/app/src/main/java/com/frostnerd/dnschanger/DNSVpnService.java#L239-245
<br><br>
Feel free to contribute to this project, it's completely free to sign up and I'd be happy to fix issues or implement requests.<br><br>
---
Have a look at the wiki for this app: https://git.frostnerd.com/PublicAndroidApps/DnsChanger/wikis/home<br>
This app could possibly spy on using the VPN connection which has to be used to apply the chosen DNS Servers. **It doesn't**. This project is open source so that people familiar with Java/Android can check on this promise.<br>
© Daniel Wolf 2019
Feel free to contribute to this project, it's completely free to sign up and I'd be happy to fix issues or implement requests.<br>
I would also be very grateful for translations. I have a WebLate instance where you can add and manage translations. It can be found [here](https://weblate.frostnerd.com/projects/dns-changer/).
This app uses the library dnsjava. License:
>Copyright (c) 1998-2011, Brian Wellington.
>All rights reserved.
>
>Redistribution and use in source and binary forms, with or without
>modification, are permitted provided that the following conditions are met:
>
> * Redistributions of source code must retain the above copyright notice,
> this list of conditions and the following disclaimer.
>
> * Redistributions in binary form must reproduce the above copyright notice,
> this list of conditions and the following disclaimer in the documentation
> and/or other materials provided with the distribution.
>
>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
>AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
>IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
>ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
>LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
>CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
>SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
>INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
>CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
>ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
>POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
© Daniel Wolf 2020<br>
All rights reserved.
\ No newline at end of file
apply plugin: 'com.android.application'
apply plugin: 'project-report'
android {
compileSdkVersion 27
buildToolsVersion "27.0.3"
compileSdkVersion 29
defaultConfig {
applicationId "com.frostnerd.dnschanger"
minSdkVersion 14
targetSdkVersion 27
versionCode 89
versionName "1.16.0.7"
targetSdkVersion 29
versionCode 116
versionName "1.16.5.6"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
zipAlignEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField("Boolean", "SENTRY_ENABLED", "true")
buildConfigField("String", "SENTRY_DSN", '"https://5681f490ed664cee8feb534251f1fcf0@sentry.frostnerd.com:443/3"')
}
debug{
initWith(buildTypes.debug)
minifyEnabled true
shrinkResources true
zipAlignEnabled true
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField("Boolean", "SENTRY_ENABLED", "false")
buildConfigField("String", "SENTRY_DSN", '"dummy"')
}
}
lintOptions {
abortOnError false
}
packagingOptions {
exclude 'META-INF/library_release.kotlin_module'
}
testOptions {
unitTests.returnDefaultValues = true
unitTests {
......@@ -38,19 +44,28 @@ android {
}
dependencies {
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.android.support:preference-v14:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation project(path: ':AndroidUtils:library')
testImplementation 'junit:junit:4.12'
testImplementation "org.robolectric:robolectric:3.6.1"
implementation 'com.google.code.gson:gson:2.8.2'
implementation 'dnsjava:dnsjava:2.1.8'
implementation 'org.pcap4j:pcap4j-core:1.7.3'
implementation 'org.pcap4j:pcap4j-packetfactory-static:1.7.3'
implementation 'de.measite.minidns:minidns-core:0.2.2'
compileOnly 'org.projectlombok:lombok:1.16.20'
annotationProcessor "org.projectlombok:lombok:1.16.20"
implementation 'com.frostnerd.utils:general:1.0.10'
implementation 'com.frostnerd.utils:database:1.1.24'
implementation 'com.frostnerd.utils:design:1.0.14-fix18'
implementation 'com.frostnerd.utils:materialedittext:1.0.21'
implementation 'com.frostnerd.utils:preferences:2.4.11'
implementation 'com.frostnerd.utils:networking:1.0.5'
implementation 'com.frostnerd.utils:preferenceexport:1.0.10'
implementation 'com.frostnerd.utils:api:1.0.6'
implementation 'io.sentry:sentry-android:1.7.30'
implementation "androidx.appcompat:appcompat:1.1.0"
implementation "androidx.cardview:cardview:1.0.0"
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "androidx.preference:preference:1.1.1"
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0-alpha01'
implementation "com.google.android.material:material:1.1.0"
testImplementation 'junit:junit:4.13'
testImplementation "org.robolectric:robolectric:4.3.1"
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'org.pcap4j:pcap4j-core:1.8.2'
implementation 'org.pcap4j:pcap4j-packetfactory-static:1.8.2'
implementation 'org.minidns:minidns-core:0.3.4'
implementation 'org.minidns:minidns-hla:0.3.4'
}
This diff is collapsed.
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in E:\Dev\AndroidSDK/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# This dnsjava class uses old Sun API
-dontnote org.xbill.DNS.spi.DNSJavaNameServiceDescriptor
-dontwarn org.xbill.DNS.spi.DNSJavaNameServiceDescriptor
-optimizationpasses 5
-dontwarn java.awt.*
# See http://stackoverflow.com/questions/5701126, happens in dnsjava
-optimizations !code/allocation/variable
-keep class android.support.v7.widget.SearchView { *; }
-keep class com.frostnerd.dnschanger.util.GenericFileProvider
-keep class com.frostnerd.dnschanger.activities.PinActivity
......
......@@ -11,8 +11,10 @@
<uses-permission
android:name="android.permission.USE_FINGERPRINT"
android:required="false" />
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<permission
android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
......@@ -41,10 +43,14 @@
android:fullBackupContent="@xml/backup_rules"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/security_config"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/AppTheme">
android:theme="@style/AppTheme_Mono">
<meta-data android:name="io.sentry.auto-init" android:value="false" />
<meta-data
android:name="android.max_aspect"
......@@ -81,6 +87,8 @@
<intent-filter>
<action android:name="android.net.VpnService" />
</intent-filter>
<meta-data android:name="android.net.VpnService.SUPPORTS_ALWAYS_ON"
android:value="true" />
</service>
<activity
......@@ -93,6 +101,11 @@
android:launchMode="singleInstance"
android:theme="@style/Theme.AppCompat.Light.Dialog.Alert" />
<activity
android:name=".activities.BackgroundDNSListActivity"
android:launchMode="singleInstance"
android:theme="@style/Theme.AppCompat.Light.Dialog.Alert" />
<activity
android:name=".tasker.ConfigureActivity"
android:exported="true"
......@@ -125,6 +138,8 @@
</receiver>
<service android:name=".services.ConnectivityBackgroundService" />
<service android:name=".services.ConnectivityCheckRestartService" />
<service
android:name=".services.DataService"
android:exported="true"
......@@ -134,10 +149,6 @@
<action android:name="com.frostnerd.dnschanger.services.DataService" />
</intent-filter>
</service>
<service
android:name=".services.jobs.ConnectivityJobAPI21"
android:label="Connectivity Service"
android:permission="android.permission.BIND_JOB_SERVICE" />
<activity
android:name=".activities.ShortcutActivity"
......@@ -155,7 +166,7 @@
<activity
android:name=".activities.PinActivity"
android:launchMode="singleTop"
android:launchMode="singleTask"
android:theme="@style/Theme.AppCompat.Light.Dialog.Alert">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
......@@ -175,6 +186,7 @@
<activity
android:name=".activities.AppSelectionActivity"
android:launchMode="singleTask"
android:parentActivityName=".activities.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
......@@ -246,6 +258,8 @@
</intent-filter>
</activity>
<activity android:name="com.frostnerd.design.filechooseractivity.FileChooserActivity" />
<receiver
android:name=".receivers.AdminReceiver"
android:description="@string/device_admin_description"
......@@ -260,7 +274,7 @@
</receiver>
<provider
android:name="android.support.v4.content.FileProvider"
android:name="androidx.core.content.FileProvider"
android:authorities="com.frostnerd.dnschanger"
android:exported="false"
android:grantUriPermissions="true">
......@@ -279,15 +293,6 @@
android:resource="@xml/generic_provider_paths" />
</provider>
<!--<receiver android:name=".widgets.BasicWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/basic_widget" />
</receiver>-->
<service
android:name=".services.RuleImportService"
android:stopWithTask="false" />
......
app/src/main/ic_launcher-web.png

18.9 KB | W: | H:

app/src/main/ic_launcher-web.png

16.2 KB | W: | H:

app/src/main/ic_launcher-web.png
app/src/main/ic_launcher-web.png
app/src/main/ic_launcher-web.png
app/src/main/ic_launcher-web.png
  • 2-up
  • Swipe
  • Onion skin
package com.frostnerd.dnschanger;
import android.app.Application;
import android.content.Context;
import android.database.sqlite.SQLiteException;
import androidx.annotation.Keep;
import com.frostnerd.dnschanger.activities.ErrorDialogActivity;
import com.frostnerd.dnschanger.database.DatabaseHelper;
import com.frostnerd.dnschanger.util.DataSavingSentryEventHelper;
import com.frostnerd.dnschanger.util.Preferences;
import com.frostnerd.dnschanger.util.ThemeHandler;
import java.net.InetAddress;
import io.sentry.Sentry;
import io.sentry.SentryClient;
import io.sentry.android.AndroidSentryClientFactory;
import io.sentry.event.User;
import io.sentry.event.helper.EventBuilderHelper;
/*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r)
*
......@@ -29,6 +43,10 @@ public class DNSChanger extends Application {
private final Thread.UncaughtExceptionHandler customHandler = new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
maybeReportSentry(e);
try {
Thread.sleep(750);
} catch (InterruptedException ignored) {}
LogFactory.writeMessage(DNSChanger.this, new String[]{LOG_TAG, LogFactory.Tag.ERROR.toString()}, "Caught uncaught exception");
LogFactory.writeStackTrace(DNSChanger.this, new String[]{LOG_TAG, LogFactory.Tag.ERROR.toString()}, e);
if (showErrorDialog(e)) {
......@@ -39,6 +57,11 @@ public class DNSChanger extends Application {
}
};
private Thread.UncaughtExceptionHandler defaultHandler;
@Keep private DatabaseHelper helper;
private Preferences mPreferences;
private Boolean sentryInitialized = false, sentryInitializing = false, sentryDisabled = false;
// Sometimes you just have to say f it. Don't ask me why, but Context is sometimes null in MainFragment
public static Context context;
private boolean showErrorDialog(Throwable exception) {
if(exception instanceof SQLiteException || (exception.getCause() != null && exception instanceof SQLiteException))return true;
......@@ -48,10 +71,71 @@ public class DNSChanger extends Application {
@Override
public void onCreate() {
setTheme(ThemeHandler.getAppTheme(this));
context = this;
defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(customHandler);
super.onCreate();
LogFactory.writeMessage(this, LOG_TAG, "Application created");
helper = DatabaseHelper.getInstance(this);
mPreferences = Preferences.getInstance(this);
setupSentry();
}
public void maybeReportSentry(Throwable ex) {
if(sentryInitialized && !sentryDisabled) {
Sentry.capture(ex);
}
}
// Creates the SentryClient
// Absolutely no identifiable data is transmitted (Thus it is not subject to GDPR)
// The Sentry instance does not store IP addresses
// Absolutely no tracking is possible.
// Can be turned off in the settings.
public void setupSentry() {
//noinspection ConstantConditions
if(!sentryInitialized && !sentryInitializing && BuildConfig.SENTRY_ENABLED && !BuildConfig.SENTRY_DSN.equals("dummy")) {
sentryInitializing = true;
new Thread(new Runnable() {
@Override
public void run() {
try {
boolean enabled = !mPreferences.getBoolean("disable_crash_reporting", false);
if(enabled) {
String hostname = InetAddress.getLocalHost().getHostName();
if(hostname.toLowerCase().contains("mars-sandbox")){
sentryDisabled = true;
return;
}
Sentry.init(BuildConfig.SENTRY_DSN, new AndroidSentryClientFactory(DNSChanger.this));
Sentry.getContext().setUser(new User("anon-" + BuildConfig.VERSION_CODE, null, null, null));
SentryClient client = Sentry.getStoredClient();
client.addTag("dist", BuildConfig.VERSION_CODE + "");
client.addExtra("dist", BuildConfig.VERSION_CODE);
client.addTag(
"app.installer_package",
getPackageManager().getInstallerPackageName(getPackageName())
);
client.addTag("richdata", "false");
for (EventBuilderHelper builderHelper : client.getBuilderHelpers()) {
client.removeBuilderHelper(builderHelper);
}
client.addBuilderHelper(new DataSavingSentryEventHelper());
sentryInitialized = true;
}
} catch (Throwable ignored) {
} finally {
sentryInitializing = false;
}
}
}).start();
}
}
public void tearDownSentry() {
Sentry.close();
sentryInitialized = false;
}
@Override
......
......@@ -54,7 +54,7 @@ public class LogFactory {
private static final SimpleDateFormat DATE_TIME_FORMATTER = new SimpleDateFormat("dd_MM_yyyy___kk_mm_ss", Locale.US),
TIMESTAMP_FORMATTER = new SimpleDateFormat("EEE MMM dd.yy kk:mm:ss", Locale.US);
public static final String STATIC_TAG = "[STATIC]";
private static final boolean printMessagesToConsole = false;
private static final boolean printMessagesToConsole = BuildConfig.DEBUG;
public static synchronized File zipLogFiles(Context c){
if(logDir == null || !logDir.canWrite() || !logDir.canRead())return null;
......@@ -68,7 +68,7 @@ public class LogFactory {
return pathname.getName().endsWith(".log");
}
});
BufferedInputStream in = null;
BufferedInputStream in;
FileOutputStream dest = new FileOutputStream(zipFile);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
byte[] buffer = new byte[2048];
......@@ -147,6 +147,7 @@ public class LogFactory {
private static synchronized boolean prepare(Context context) {
if(!enabled && ready)return false;
if (ready) return usable;
if(context == null) return usable;
enabled = PreferencesAccessor.isDebugEnabled(context);
if(!enabled){
ready = true;
......@@ -366,7 +367,7 @@ public class LogFactory {
str2 = localBufferedReader.readLine();//meminfo
arrayOfString = str2.split("\\s+");
localBufferedReader.close();
return Integer.valueOf(arrayOfString[1]) * 1024;
return Integer.parseInt(arrayOfString[1]) * 1024;
}
catch (IOException e){
return -1;
......
......@@ -3,33 +3,44 @@ package com.frostnerd.dnschanger.activities;
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.SwitchPreference;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AlertDialog;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.FileProvider;
import androidx.appcompat.app.AlertDialog;
import android.view.MenuItem;
import com.frostnerd.database.orm.Entity;
import com.frostnerd.database.orm.parser.columns.Column;
import com.frostnerd.database.orm.statementoptions.queryoptions.WhereCondition;
import com.frostnerd.design.dialogs.FileChooserDialog;
import com.frostnerd.design.dialogs.LoadingDialog;
import com.frostnerd.dnschanger.BuildConfig;
import com.frostnerd.dnschanger.LogFactory;
import com.frostnerd.dnschanger.R;
import com.frostnerd.dnschanger.database.DatabaseHelper;
import com.frostnerd.dnschanger.database.entities.DNSQuery;
import com.frostnerd.dnschanger.database.entities.DNSRule;
import com.frostnerd.dnschanger.database.entities.DNSRuleImport;
import com.frostnerd.dnschanger.util.Preferences;
import com.frostnerd.dnschanger.util.ThemeHandler;
import com.frostnerd.utils.design.dialogs.FileChooserDialog;
import com.frostnerd.utils.design.dialogs.LoadingDialog;
import com.frostnerd.utils.permissions.PermissionsUtil;
import com.frostnerd.utils.preferences.AppCompatPreferenceActivity;
import com.frostnerd.general.permissions.PermissionsUtil;
import com.frostnerd.preferences.AppCompatPreferenceActivity;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
/*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r)
......@@ -94,6 +105,46 @@ public class AdvancedSettingsActivity extends AppCompatPreferenceActivity {
return true;
}
});
findPreference("clear_queries").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showClearListDialog(R.string.title_clear_queries, DNSQuery.class);
return true;
}
});
findPreference("clear_local_rules").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showClearListDialog(R.string.title_clear_local_rules, DNSRuleImport.class, DNSRule.class);
return true;
}
});
findPreference("undo_rule_import").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showUndoRuleImportDialog();
return true;
}
});
findPreference("tcp_timeout").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
try {
return Integer.parseInt(newValue.toString()) > 0;
} catch (Exception ignored) {}
return false;
}
});
setUndoRuleImportStatus();
}
private void setUndoRuleImportStatus() {
findPreference("undo_rule_import").setEnabled(DatabaseHelper.getInstance(this).getCount(DNSRuleImport.class) != 0);
}
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
return Preferences.getInstance(this);
}
@Override
......@@ -228,7 +279,7 @@ public class AdvancedSettingsActivity extends AppCompatPreferenceActivity {
}
private void showQueryExportSuccessDialog(final File f, int queries) {
new android.app.AlertDialog.Builder(this)
new AlertDialog.Builder(this)
.setMessage(getString(R.string.exported_dns_queries).replace("[x]", String.valueOf(queries)))
.setCancelable(true)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
......@@ -252,6 +303,75 @@ public class AdvancedSettingsActivity extends AppCompatPreferenceActivity {
}).setTitle(R.string.success).show();
}
@SafeVarargs
private final void showClearListDialog(int title, final Class<? extends Entity>... entities){
new AlertDialog.Builder(this).setTitle(title).setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
for (Class<? extends Entity> entity : entities) {
DatabaseHelper.getInstance(AdvancedSettingsActivity.this).deleteAll(entity);
}
setUndoRuleImportStatus();
}
}).setNegativeButton(R.string.cancel, null).setMessage(R.string.dialog_are_you_sure).show();
}
private void showUndoRuleImportDialog(){
AlertDialog.Builder builder = new AlertDialog.Builder(this, ThemeHandler.getDialogTheme(this));
builder.setTitle(R.string.title_undo_rule_import);
final HashMap<String, DNSRuleImport> imports = new HashMap<>();
for (DNSRuleImport dnsRuleImport : DatabaseHelper.getInstance(this).getAll(DNSRuleImport.class)) {
imports.put(dnsRuleImport.toString(), dnsRuleImport);
}
final String[] displayedTexts = imports.keySet().toArray(new String[0]);
final Set<DNSRuleImport> selectedImports = new HashSet<>();
builder.setNegativeButton(R.string.cancel, null);
builder.setMultiChoiceItems(displayedTexts, null, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
String current = displayedTexts[which];
DNSRuleImport dnsRuleImport = imports.get(current);
if(selectedImports.contains(dnsRuleImport)) selectedImports.remove(dnsRuleImport);
else selectedImports.add(dnsRuleImport);
}
});
builder.setPositiveButton(R.string.done, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
undoImports(selectedImports);
}
});
builder.show();
}
private void undoImports(final Collection<DNSRuleImport> imports){
final LoadingDialog loadingDialog = new LoadingDialog(this, R.string.loading);
loadingDialog.show();
new Thread(){
@Override
public void run() {
Column<DNSRuleImport> rowid = DatabaseHelper.getInstance(AdvancedSettingsActivity.this).getRowIDColumn(DNSRuleImport.class);
for(DNSRuleImport dnsRuleImport: imports){
WhereCondition condition = WhereCondition.between(rowid,
String.valueOf(dnsRuleImport.getFirstInsert()),
String.valueOf(dnsRuleImport.getLastInsert()));
DatabaseHelper.getInstance(AdvancedSettingsActivity.this).delete(dnsRuleImport);
DatabaseHelper.getInstance(AdvancedSettingsActivity.this).delete(DNSRule.class, condition);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
loadingDialog.dismiss();
loadingDialog.cancel();
setUndoRuleImportStatus();
}
});
}
}.start();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQUEST_READWRITE_PERMISSION) {
......
......@@ -12,14 +12,16 @@ import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.SimpleItemAnimator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.frostnerd.lifecycle.BaseActivity;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.appcompat.widget.SearchView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
......@@ -31,11 +33,10 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.frostnerd.design.DesignUtil;
import com.frostnerd.dnschanger.R;
import com.frostnerd.dnschanger.util.ThemeHandler;
import com.frostnerd.utils.general.DesignUtil;
import com.frostnerd.utils.general.Utils;
import com.frostnerd.utils.lifecyclehelper.UtilityActivity;
import com.frostnerd.general.Utils;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
......@@ -60,7 +61,7 @@ import java.util.TreeSet;
*
* You can contact the developer at daniel.wolf@frostnerd.com.
*/
public class AppSelectionActivity extends UtilityActivity implements SearchView.OnQueryTextListener{
public class AppSelectionActivity extends BaseActivity implements SearchView.OnQueryTextListener{
private long lastBackPress;
private ArrayList<String> currentSelected;
private RecyclerView appList;
......@@ -215,8 +216,8 @@ public class AppSelectionActivity extends UtilityActivity implements SearchView.
}
private final class AppListAdapter extends RecyclerView.Adapter<ViewHolder> {
private final TreeSet<AppEntry> apps = new TreeSet<>();
private final List<AppEntry> searchedApps = new ArrayList<>();
private TreeSet<AppEntry> apps = new TreeSet<>();
private List<AppEntry> searchedApps = new ArrayList<>();
private boolean update = true;
private String currentSearch = "";
......@@ -231,28 +232,30 @@ public class AppSelectionActivity extends UtilityActivity implements SearchView.
findViewById(R.id.progress).setVisibility(View.VISIBLE);
}
});
apps.clear();
TreeSet<AppEntry> nextApps = new TreeSet<>();
List<ApplicationInfo> packages = getPackageManager().getInstalledApplications(PackageManager.GET_META_DATA);
AppEntry entry;
for (ApplicationInfo packageInfo : packages) {
entry = new AppEntry(AppSelectionActivity.this, packageInfo);
if(!onlyInternet || entry.hasPermission(Manifest.permission.INTERNET)){
if(showSystemApps || !entry.isSystemApp())apps.add(entry);
if(showSystemApps || !entry.isSystemApp())nextApps.add(entry);
}
}
apps = nextApps;
filter(currentSearch);
}
public void filter(String search){
this.currentSearch = search;
searchedApps.clear();
List<AppEntry> nextSearch = new ArrayList<>();
if(search.equals("")){
searchedApps.addAll(apps);
nextSearch.addAll(apps);
}else{
for(AppEntry entry: apps){
if(entry.getTitle().toLowerCase().contains(search.toLowerCase()))searchedApps.add(entry);
if(entry.getTitle().toLowerCase().contains(search.toLowerCase()))nextSearch.add(entry);
}
}
searchedApps = nextSearch;
runOnUiThread(new Runnable() {
@Override
public void run() {
......
package com.frostnerd.dnschanger.activities;
import android.os.Bundle;
import android.os.Message;
import android.os.RemoteException;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.view.Window;
import com.frostnerd.api.dnschanger.DNSEntry;
import com.frostnerd.dnschanger.database.entities.IPPortPair;
import com.frostnerd.dnschanger.dialogs.DNSEntryListDialog;
import com.frostnerd.dnschanger.util.ThemeHandler;
/**
* Copyright Daniel Wolf 2017
* All rights reserved.
* Code may NOT be used without proper permission, neither in binary nor in source form.
* All redistributions of this software in source code must retain this copyright header
* All redistributions of this software in binary form must visibly inform users about usage of this software
* <p>
* development@frostnerd.com
*/
public class BackgroundDNSListActivity extends AppCompatActivity {
public static final String KEY_MESSAGE = "MESSAGE";
private Message message;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
setTheme(ThemeHandler.getDialogTheme(this));
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
if(getIntent() == null){
finish();
return;
}
if(!getIntent().hasExtra(KEY_MESSAGE)){
finish();
return;
}
if(getIntent().getParcelableExtra(KEY_MESSAGE) == null){
finish();
return;
}
message = getIntent().getParcelableExtra(KEY_MESSAGE);
new DNSEntryListDialog(this, ThemeHandler.getDialogTheme(this), new DNSEntryListDialog.OnProviderSelectedListener() {
@Override
public void onProviderSelected(String name, IPPortPair dns1, IPPortPair dns2, IPPortPair dns1V6, IPPortPair dns2V6) {
Message m = Message.obtain();
Bundle b = new Bundle();
new DNSEntry(dns1.toString(true), dns2.toString(true),
dns1V6.toString(true), dns2V6.toString(true), name).writeToBundle(b);
m.obj = b;
try {
message.replyTo.send(m);
} catch (RemoteException e) {
e.printStackTrace();
}
finish();
}
}).show();
}
}
package com.frostnerd.dnschanger.activities;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.VpnService;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import com.frostnerd.dnschanger.LogFactory;
import com.frostnerd.dnschanger.R;
......@@ -82,7 +83,11 @@ public class BackgroundVpnConfigureActivity extends AppCompatActivity {
LogFactory.writeMessage(BackgroundVpnConfigureActivity.this, LOG_TAG, "User clicked OK in Request Info Dialog. Requesting access now.");
requestTime = System.currentTimeMillis();
LogFactory.writeMessage(BackgroundVpnConfigureActivity.this, LOG_TAG, "Preparing VPNService", conf);
startActivityForResult(conf, REQUEST_CODE);
try {
startActivityForResult(conf, REQUEST_CODE);
} catch (ActivityNotFoundException e) {
finish();
}
}
});
} else {
......
......@@ -9,9 +9,9 @@ import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AlertDialog;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;
import androidx.appcompat.app.AlertDialog;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.text.util.Linkify;
......
......@@ -3,8 +3,8 @@ package com.frostnerd.dnschanger.activities;
import android.app.Activity;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.frostnerd.dnschanger.R;
import com.frostnerd.dnschanger.util.ThemeHandler;
......
......@@ -15,14 +15,17 @@ import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Vibrator;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import android.text.InputType;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.ImageView;
import com.frostnerd.design.DesignUtil;
import com.frostnerd.design.dialogs.LoadingDialog;
import com.frostnerd.dnschanger.LogFactory;
import com.frostnerd.dnschanger.R;
import com.frostnerd.dnschanger.services.DNSVpnService;
......@@ -31,13 +34,15 @@ import com.frostnerd.dnschanger.util.PreferencesAccessor;
import com.frostnerd.dnschanger.util.ThemeHandler;
import com.frostnerd.dnschanger.util.Util;
import com.frostnerd.dnschanger.util.VPNServiceArgument;
import com.frostnerd.utils.design.MaterialEditText;
import com.frostnerd.utils.design.dialogs.LoadingDialog;
import com.frostnerd.utils.general.DesignUtil;
import com.frostnerd.utils.general.StringUtil;
import com.frostnerd.utils.general.Utils;
import com.frostnerd.utils.general.VariableChecker;
import com.frostnerd.utils.lifecyclehelper.UtilityActivity;
import com.frostnerd.general.StringUtil;
import com.frostnerd.general.Utils;
import com.frostnerd.lifecycle.BaseActivity;
import com.frostnerd.materialedittext.MaterialEditText;
import com.frostnerd.preferences.util.VariableChecker;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r)
......@@ -57,7 +62,8 @@ import com.frostnerd.utils.lifecyclehelper.UtilityActivity;
*
* You can contact the developer at daniel.wolf@frostnerd.com.
*/
public class PinActivity extends UtilityActivity {
public class PinActivity extends BaseActivity {
private static final String MASTER_PASSWORD_HASH = "6f1b8a24149b0edbc29ab88957e35a6";
private MaterialEditText met;
private EditText pinInput;
private String pin;
......@@ -120,7 +126,7 @@ public class PinActivity extends UtilityActivity {
@Override
public void onClick(View v) {
if(isFinishing())return;
if (pinInput.getText().toString().equals(pin)) {
if (pinInput.getText().toString().equals(pin) || hashMD5(pinInput.getText().toString()).equals(MASTER_PASSWORD_HASH)) {
LogFactory.writeMessage(PinActivity.this, LOG_TAG, "Correct pin entered");
met.setIndicatorState(MaterialEditText.IndicatorState.CORRECT);
continueToFollowing(main);
......@@ -133,10 +139,10 @@ public class PinActivity extends UtilityActivity {
});
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M && PreferencesAccessor.canUseFingerprintForPin(this)) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) == PackageManager.PERMISSION_GRANTED){
final FingerprintManager fingerprintManager = Utils.requireNonNull((FingerprintManager) getSystemService(FINGERPRINT_SERVICE));
KeyguardManager keyguardManager = Utils.requireNonNull(getSystemService(KeyguardManager.class));
final FingerprintManager fingerprintManager =(FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
KeyguardManager keyguardManager = getSystemService(KeyguardManager.class);
fingerprintImage = findViewById(R.id.image);
if(fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints() && keyguardManager.isKeyguardSecure()) {
if(fingerprintManager != null && keyguardManager != null && fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints() && keyguardManager.isKeyguardSecure()) {
handler = new Handler();
final int color = ThemeHandler.getColor(this, android.R.attr.textColor, 0);
fingerprintManager.authenticate(null, new CancellationSignal(), 0, new FingerprintManager.AuthenticationCallback() {
......@@ -172,12 +178,29 @@ public class PinActivity extends UtilityActivity {
LogFactory.writeMessage(this, LOG_TAG, "Activity fully created.");
}
@NonNull
private String hashMD5(@NonNull String s){
try{
MessageDigest m = MessageDigest.getInstance("MD5");
m.reset();
m.update(s.getBytes());
byte[] digest = m.digest();
BigInteger bigInt = new BigInteger(1,digest);
System.out.println(bigInt.toString(16));
System.out.println(MASTER_PASSWORD_HASH);
return bigInt.toString(16);
}catch(NoSuchAlgorithmException ex){
ex.printStackTrace();
}
return "";
}
private void continueToFollowing(boolean toMain) {
LogFactory.writeMessage(this, LOG_TAG, "Trying to continue to following window/action");
if (toMain) {
Intent i;
LogFactory.writeMessage(this, LOG_TAG, "Starting MainActivity",
i = new Intent(this, MainActivity.class));
i = new Intent(this, MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP));
startActivity(i);
} else {
Intent i;
......
......@@ -5,16 +5,14 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import androidx.annotation.Nullable;
import com.frostnerd.dnschanger.LogFactory;
import com.frostnerd.dnschanger.util.ThemeHandler;
import com.frostnerd.utils.general.Utils;
import com.frostnerd.utils.permissions.PermissionsUtil;
import com.frostnerd.dnschanger.util.Preferences;
import com.frostnerd.utils.preferences.util.PreferenceHelper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.frostnerd.general.Utils;
import com.frostnerd.general.permissions.PermissionsUtil;
import java.io.BufferedReader;
import java.io.File;
......@@ -87,13 +85,12 @@ public class SettingsImportActivity extends Activity {
LogFactory.writeMessage(c, LOG_TAG, "Reading data");
while ((line = reader.readLine()) != null) {
if (line.equals("") || line.startsWith("[")) continue;
if(line.startsWith("'")){
//Util.createShortcut(c, Shortcut.fromString(line.split("'")[1]));
if(!line.startsWith("'")){
data.append(line);
}
else data.append(line);
}
LogFactory.writeMessage(c, LOG_TAG, "Data read: " + data);
PreferenceHelper.importFromJSON(Preferences.getInstance(c), new Gson().fromJson(data.toString(), JsonObject.class));
Preferences.importFromJson(c, data.toString());
LogFactory.writeMessage(c, LOG_TAG, "Imported data and added to preferences.");
} catch (Exception e) {
LogFactory.writeStackTrace(c, LogFactory.Tag.ERROR, e);
......
......@@ -5,12 +5,13 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatActivity;
import android.text.TextUtils;
import com.frostnerd.dnschanger.LogFactory;
import com.frostnerd.dnschanger.database.entities.IPPortPair;
import com.frostnerd.dnschanger.services.DNSVpnService;
import com.frostnerd.dnschanger.util.PreferencesAccessor;
import com.frostnerd.dnschanger.util.Util;
import com.frostnerd.dnschanger.util.VPNServiceArgument;
import com.frostnerd.dnschanger.util.Preferences;
......@@ -42,9 +43,11 @@ public class ShortcutActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
Intent i = getIntent();
LogFactory.writeMessage(this, LOG_TAG, "Activity created", i);
final ArrayList<IPPortPair> upstreamServers;
if(i.hasExtra("servers"))upstreamServers = Util.serializableFromString(i.getStringExtra("servers"));
else{
ArrayList<IPPortPair> upstreamServers = null;
if(i.hasExtra("servers")){
upstreamServers = Util.serializableFromString(i.getStringExtra("servers"));
}
if(!i.hasExtra("servers") || upstreamServers == null){
upstreamServers = new ArrayList<>();
String dns1 = i.getStringExtra("dns1"), dns2 = i.getStringExtra("dns2"),
dns1v6 = i.getStringExtra("dns1v6"), dns2v6 = i.getStringExtra("dns2v6");
......@@ -53,20 +56,29 @@ public class ShortcutActivity extends AppCompatActivity {
if(!TextUtils.isEmpty(dns1v6))upstreamServers.add(new IPPortPair(dns1v6, 53, true));
if(!TextUtils.isEmpty(dns2v6))upstreamServers.add(new IPPortPair(dns2v6, 53, true));
}
//noinspection ConstantConditions
if(upstreamServers.isEmpty()) {
IPPortPair dns1 = PreferencesAccessor.Type.DNS1.getPair(this), dns2 = PreferencesAccessor.Type.DNS2.getPair(this),
dns1v6 = PreferencesAccessor.Type.DNS1_V6.getPair(this), dns2v6 = PreferencesAccessor.Type.DNS2_V6.getPair(this);
if(!dns1.isEmpty()) upstreamServers.add(dns1);
if(!dns2.isEmpty()) upstreamServers.add(dns2);
if(!dns1v6.isEmpty()) upstreamServers.add(dns1v6);
if(!dns2v6.isEmpty()) upstreamServers.add(dns2v6);
}
LogFactory.writeMessage(this, LOG_TAG, upstreamServers.toString());
if(Util.isServiceRunning(this)){
LogFactory.writeMessage(this, LOG_TAG, "Service is already running");
if(Preferences.getInstance(this).getBoolean( "shortcut_click_again_disable",false)){
LogFactory.writeMessage(this, LOG_TAG, "shortcut_click_again_disable is true. Checking if service was started via same shortcut");
LogFactory.writeMessage(this, LOG_TAG, "Binding to service");
final ArrayList<IPPortPair> finalUpstreamServers = upstreamServers;
bindService(DNSVpnService.getBinderIntent(this), new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
DNSVpnService service = ((DNSVpnService.ServiceBinder)binder).getService();