package org.itxtech.daedalus; import android.app.ActivityManager; import android.app.Application; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; import android.graphics.drawable.Icon; import android.net.Uri; import android.os.Build; import android.preference.PreferenceManager; import android.util.Log; import com.google.firebase.crash.FirebaseCrash; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonParseException; import com.google.gson.stream.JsonReader; import org.itxtech.daedalus.activity.MainActivity; import org.itxtech.daedalus.service.DaedalusVpnService; import org.itxtech.daedalus.util.Configurations; import org.itxtech.daedalus.util.Logger; import org.itxtech.daedalus.util.Rule; import org.itxtech.daedalus.util.RuleResolver; import org.itxtech.daedalus.util.server.DNSServer; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Daedalus Project * * @author iTX Technologies * @link https://itxtech.org *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. */ public class Daedalus extends Application { static { Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { FirebaseCrash.report(e); } }); } private static final String SHORTCUT_ID_ACTIVATE = "shortcut_activate"; public static final List DNS_SERVERS = new ArrayList() {{ add(new DNSServer("119.23.248.241", R.string.server_fundns_south_china)); add(new DNSServer("118.89.45.176", R.string.server_fundns_north_china)); add(new DNSServer("115.159.146.99", R.string.server_aixyz_east_china)); add(new DNSServer("123.206.21.48", R.string.server_aixyz_south_china)); add(new DNSServer("119.29.105.234", R.string.server_cutedns_south_china)); }}; public static final List RULES = new ArrayList() {{ //Build-in Hosts rule providers add(new Rule("googlehosts/hosts", "googlehosts.hosts", Rule.TYPE_HOSTS, "https://raw.githubusercontent.com/googlehosts/hosts/master/hosts-files/hosts", false)); add(new Rule("sy618/hosts", "sy618.hosts", Rule.TYPE_HOSTS, "https://raw.githubusercontent.com/sy618/hosts/master/FQ", false)); add(new Rule("vokins/yhosts", "vokins.hosts", Rule.TYPE_HOSTS, "https://raw.githubusercontent.com/vokins/yhosts/master/hosts", false)); add(new Rule("lengers/connector", "connector.hosts", Rule.TYPE_HOSTS, "https://git.oschina.net/lengers/connector/raw/master/hosts", false)); add(new Rule("wangchunming/2017hosts", "2017.hosts", Rule.TYPE_HOSTS, "https://raw.githubusercontent.com/wangchunming/2017hosts/master/hosts-pc", false)); add(new Rule("adaway", "adaway.hosts", Rule.TYPE_HOSTS, "https://adaway.org/hosts.txt", false)); //Build-in DNSMasq rule providers add(new Rule("vokins/yhosts/union", "union.dnsmasq", Rule.TYPE_DNAMASQ, "https://raw.githubusercontent.com/vokins/yhosts/master/dnsmasq/union.conf", false)); add(new Rule("sy618/hosts/dnsfq", "dnsfq.dnsmasq", Rule.TYPE_DNAMASQ, "https://raw.githubusercontent.com/sy618/hosts/master/dnsmasq/dnsfq", false)); }}; public static final String[] DEFAULT_TEST_DOMAINS = new String[]{ "google.com", "twitter.com", "youtube.com", "facebook.com", "wikipedia.org" }; public static Configurations configurations; public static String rulePath = null; public static String logPath = null; private static String configPath = null; private static Daedalus instance = null; private SharedPreferences prefs; private Thread mResolver; @Override public void onCreate() { super.onCreate(); instance = this; Logger.init(); mResolver = new Thread(new RuleResolver()); mResolver.start(); initData(); } private void initDirectory(String dir) { File directory = new File(dir); if (!directory.isDirectory()) { Logger.warning(dir + " is not a directory. Delete result: " + String.valueOf(directory.delete())); } if (!directory.exists()) { Logger.debug(dir + " does not exist. Create result: " + String.valueOf(directory.mkdirs())); } } private void initData() { PreferenceManager.setDefaultValues(this, R.xml.perf_settings, false); prefs = PreferenceManager.getDefaultSharedPreferences(this); if (getExternalFilesDir(null) != null) { rulePath = getExternalFilesDir(null).getPath() + "/rules/"; logPath = getExternalFilesDir(null).getPath() + "/logs/"; configPath = getExternalFilesDir(null).getPath() + "/config.json"; initDirectory(rulePath); initDirectory(logPath); } if (configPath != null) { configurations = Configurations.load(new File(configPath)); } else { configurations = new Configurations(); } } public static T parseJson(Class beanClass, JsonReader reader) throws JsonParseException { GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create(); return gson.fromJson(reader, beanClass); } public static void initHostsResolver() { if (Daedalus.getPrefs().getBoolean("settings_local_rules_resolution", false)) { ArrayList pendingLoad = new ArrayList<>(); ArrayList usingRules = configurations.getUsingRules(); if (usingRules != null && usingRules.size() > 0) { for (Rule rule : usingRules) { if (rule.isUsing()) { pendingLoad.add(rulePath + rule.getFileName()); } } if (pendingLoad.size() > 0) { String[] arr = new String[pendingLoad.size()]; pendingLoad.toArray(arr); switch (usingRules.get(0).getType()) { case Rule.TYPE_HOSTS: RuleResolver.startLoadHosts(arr); break; case Rule.TYPE_DNAMASQ: RuleResolver.startLoadDnsmasq(arr); break; } } } else { RuleResolver.clear(); } } } public static void setRulesChanged() { if (instance.isServiceActivated() && getPrefs().getBoolean("settings_allow_dynamic_rule_reload", false)) { initHostsResolver(); } } public static SharedPreferences getPrefs() { return getInstance().prefs; } public static boolean isDarkTheme() { return false; } @Override public void onTerminate() { Log.d("Daedalus", "onTerminate"); super.onTerminate(); instance = null; prefs = null; RuleResolver.shutdown(); mResolver.interrupt(); RuleResolver.clear(); mResolver = null; Logger.shutdown(); } public Intent getServiceIntent() { return new Intent(this, DaedalusVpnService.class); } public boolean isAppOnForeground() { // Returns a list of application processes that are running on the // device ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE); String packageName = getApplicationContext().getPackageName(); List appProcesses = activityManager .getRunningAppProcesses(); if (appProcesses == null) return false; for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { // The name of the process that this object is associated with. if (appProcess.processName.equals(packageName) && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { return true; } } return false; } public void deactivateService() { startService(getServiceIntent().setAction(DaedalusVpnService.ACTION_DEACTIVATE)); stopService(getServiceIntent()); } public boolean isServiceActivated() { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if (DaedalusVpnService.class.getName().equals(service.service.getClassName())) { return true; } } return false; } public static void updateShortcut(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { Log.d("Daedalus", "Updating shortcut"); //shortcut! String notice = context.getString(R.string.button_text_activate); boolean activate = true; ActivityManager manager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE); for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if (DaedalusVpnService.class.getName().equals(service.service.getClassName())) { notice = context.getString(R.string.button_text_deactivate); activate = false; } } ShortcutInfo info = new ShortcutInfo.Builder(context, Daedalus.SHORTCUT_ID_ACTIVATE) .setLongLabel(notice) .setShortLabel(notice) .setIcon(Icon.createWithResource(context, R.mipmap.ic_launcher)) .setIntent(new Intent(context, MainActivity.class).setAction(Intent.ACTION_VIEW) .putExtra(MainActivity.LAUNCH_ACTION, activate ? MainActivity.LAUNCH_ACTION_ACTIVATE : MainActivity.LAUNCH_ACTION_DEACTIVATE)) .build(); ShortcutManager shortcutManager = (ShortcutManager) context.getSystemService(SHORTCUT_SERVICE); shortcutManager.addDynamicShortcuts(Collections.singletonList(info)); } } public static void donate() { openUri("https://qr.alipay.com/a6x07022gffiehykicipv1a"); } public static void openUri(String uri) { try { instance.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(uri)) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); } catch (Exception e) { Logger.logException(e); } } public static Daedalus getInstance() { return instance; } }