From 309993eec6085cfa0e112cd5f45c8c55beeee5db Mon Sep 17 00:00:00 2001 From: Daniel Weipert Date: Mon, 15 May 2023 17:20:15 +0200 Subject: works as intended :) --- app/java/src/DNSProxyService.java | 59 ++++++++++++-- app/java/src/MainActivity.java | 78 +++++++++--------- app/java/src/SettingsActivity.java | 118 +++++++++++++++++++++++++-- app/java/src/WifiListenerReceiver.java | 23 ++++-- app/java/src/WifiListenerService.java | 145 +++++++++++++++++++++++++++++++-- 5 files changed, 358 insertions(+), 65 deletions(-) (limited to 'app/java/src') diff --git a/app/java/src/DNSProxyService.java b/app/java/src/DNSProxyService.java index 8911036..2b2147f 100644 --- a/app/java/src/DNSProxyService.java +++ b/app/java/src/DNSProxyService.java @@ -5,6 +5,7 @@ import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; +import android.content.SharedPreferences; import android.content.Context; import android.content.Intent; @@ -13,6 +14,8 @@ import android.net.DhcpInfo; import android.net.VpnService; import android.net.wifi.WifiManager; +import android.preference.PreferenceManager; + import android.util.Log; import java.net.InetAddress; @@ -32,11 +35,11 @@ public class DNSProxyService extends VpnService { @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent.getAction().equals(DNSProxyService.ACTION_START)) { - this.start(); + this.connect(); return Service.START_STICKY; } else { - this.stop(); + this.disconnect(); return Service.START_NOT_STICKY; } @@ -44,7 +47,7 @@ public class DNSProxyService extends VpnService { @Override public void onDestroy() { - this.stop(); + this.disconnect(); super.onDestroy(); } @@ -58,7 +61,24 @@ public class DNSProxyService extends VpnService { return DNSProxyService.connection != null; } - public void start() { + /** + * Start this service + */ + public static void start(Context context) { + context.startService((new Intent(context, DNSProxyService.class)).setAction(DNSProxyService.ACTION_START)); + } + + /** + * Stop this service + */ + public static void stop(Context context) { + context.startService((new Intent(context, DNSProxyService.class)).setAction(DNSProxyService.ACTION_STOP)); + } + + /** + * Setup connection + */ + private void connect() { this.setPiholeAddress(); DNSProxyService.connection = new DNSProxyConnection(this); @@ -71,7 +91,10 @@ public class DNSProxyService extends VpnService { sendBroadcast(notification); } - public void stop() { + /** + * Disconnect from connection + */ + private void disconnect() { DNSProxyService.connection.stop(); DNSProxyService.connection = null; @@ -82,7 +105,16 @@ public class DNSProxyService extends VpnService { sendBroadcast(notification); } + /** + * Get and set IP address of Pihole DNS server + */ private void setPiholeAddress() { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + if (!sharedPreferences.getBoolean("use_automatic_dns_server_discovery", true)) { + DNSProxyService.PIHOLE_ADDRESS = sharedPreferences.getString("dns_server_address", ""); + return; + } + WifiManager manager = (WifiManager) getSystemService(WIFI_SERVICE); DhcpInfo info = manager.getDhcpInfo(); @@ -100,11 +132,16 @@ public class DNSProxyService extends VpnService { } } + /** + * Start the Foreground notification process + */ private void startForeground() { NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); NotificationChannel channel = new NotificationChannel( - DNSProxyService.NOTIFICATION_CHANNEL_ID, DNSProxyService.NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT + DNSProxyService.NOTIFICATION_CHANNEL_ID, + DNSProxyService.NOTIFICATION_CHANNEL_ID, + NotificationManager.IMPORTANCE_DEFAULT ); manager.createNotificationChannel(channel); @@ -112,7 +149,15 @@ public class DNSProxyService extends VpnService { .setSmallIcon(R.drawable.logo) .setContentTitle("Pihole DNS Proxy") .setContentText("Running with " + DNSProxyService.PIHOLE_ADDRESS) - // .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(MainActivity.class), PendingIntent.FLAG_IMMUTABLE)) + .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), Intent.FLAG_ACTIVITY_NEW_TASK)) + .addAction( + R.drawable.logo, + "Stop", + PendingIntent.getService(this, 0, + (new Intent(this, DNSProxyService.class)).setAction(DNSProxyService.ACTION_STOP), + PendingIntent.FLAG_IMMUTABLE + ) + ) .build(); startForeground(1, notification); diff --git a/app/java/src/MainActivity.java b/app/java/src/MainActivity.java index 6d232b9..f30f91c 100644 --- a/app/java/src/MainActivity.java +++ b/app/java/src/MainActivity.java @@ -33,7 +33,7 @@ import android.provider.Settings; public class MainActivity extends Activity { private Button buttonStart; - private Intent dnsProxyService; + private Button buttonStop; private BroadcastReceiver receiveDNSProxyService = new BroadcastReceiver() { @@ -42,7 +42,7 @@ public class MainActivity extends Activity { */ @Override public void onReceive(Context context, Intent intent) { - setStateButtonStart(); + setStateButtonStartStop(); } }; @@ -53,7 +53,7 @@ public class MainActivity extends Activity { */ @Override public void onReceive(Context context, Intent intent) { - setStateButtonStart(); + setStateButtonStartStop(); } }; @@ -64,17 +64,19 @@ public class MainActivity extends Activity { setContentView(R.layout.main); this.buttonStart = (Button) findViewById(R.id.button_start); - this.dnsProxyService = new Intent(this, DNSProxyService.class); + this.buttonStop = (Button) findViewById(R.id.button_stop); } @Override public void onResume() { super.onResume(); - this.setStateButtonStart(); - this.toggleWifiListenerService(); + this.setStateButtonStartStop(); registerReceiver(this.receiveDNSProxyService, new IntentFilter(DNSProxyService.NOTIFICATION)); registerReceiver(this.receiveNetworkChange, new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION)); + + WifiListenerService.toggle(this); + WifiListenerService.OnActivationListener.askLocationIfNeeded(this); } @Override @@ -98,8 +100,7 @@ public class MainActivity extends Activity { int itemId = item.getItemId(); if (itemId == R.id.menu__settings) { - Intent intent = new Intent(MainActivity.this, SettingsActivity.class); - startActivity(intent); + startActivity(new Intent(this, SettingsActivity.class)); return true; } @@ -121,46 +122,57 @@ public class MainActivity extends Activity { * button_start is clicked */ public void onClickButtonStart(View view) { - if (!DNSProxyService.isRunning()) { //start - Intent intent = VpnService.prepare(this); - - if (intent != null) { - startActivityForResult(intent, 0); - } else { - this.onActivityResult(0, RESULT_OK, null); - } - } - else { // stop - this.stopDNSProxyService(); + this.prepareVpnService(); + } + + /** + * button_stop is clicked + */ + public void onClickButtonStop(View view) { + this.stopDNSProxyService(); + } + + /** + * prepare VpnService properly + * and ask for confirmation + */ + private void prepareVpnService() { + Intent intent = VpnService.prepare(this); + + if (intent != null) { + startActivityForResult(intent, 0); + } else { + this.onActivityResult(0, RESULT_OK, null); } } /** * Set button_start state */ - private void setStateButtonStart() { - // change text + private void setStateButtonStartStop() { if (!DNSProxyService.isRunning()) { - this.buttonStart.setText(getString(R.string.button_start__start)); + this.buttonStart.setVisibility(View.VISIBLE); + this.buttonStop.setVisibility(View.GONE); } else { - this.buttonStart.setText(getString(R.string.button_start__stop)); + this.buttonStart.setVisibility(View.GONE); + this.buttonStop.setVisibility(View.VISIBLE); } - // toggle enabled - ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); + // toggle whether enabled + /* ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); if (networkInfo.isConnected() || DNSProxyService.isRunning()) { this.buttonStart.setEnabled(true); } else if (!networkInfo.isConnected() && !DNSProxyService.isRunning()) { this.buttonStart.setEnabled(false); - } + } */ } /** * Start DNSProxyService */ private void startDNSProxyService() { - startService(this.dnsProxyService.setAction(DNSProxyService.ACTION_START)); + DNSProxyService.start(this); Toast .makeText( @@ -175,7 +187,7 @@ public class MainActivity extends Activity { * Stop DNSProxyService */ private void stopDNSProxyService() { - startService(this.dnsProxyService.setAction(DNSProxyService.ACTION_STOP)); + DNSProxyService.stop(this); Toast .makeText( @@ -185,14 +197,4 @@ public class MainActivity extends Activity { ) .show(); } - - private void toggleWifiListenerService() { - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - - if (sharedPreferences.getBoolean("use_wifi_listener", false)) { - startService(new Intent(this, WifiListenerService.class)); - } else { - stopService(new Intent(this, WifiListenerService.class)); - } - } } diff --git a/app/java/src/SettingsActivity.java b/app/java/src/SettingsActivity.java index c71693a..d04e2ba 100644 --- a/app/java/src/SettingsActivity.java +++ b/app/java/src/SettingsActivity.java @@ -7,8 +7,12 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.net.VpnService; +import android.net.wifi.WifiManager; +import android.net.wifi.WifiInfo; import android.os.Bundle; @@ -39,15 +43,9 @@ public class SettingsActivity extends PreferenceActivity { super.onCreate(savedInstanceState); getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit(); - - // if (setting.get(USE_WIFI_LISTENER)) - // requestPermissions(new String[]{ - // android.Manifest.permission.ACCESS_FINE_LOCATION, - // }, 1234); - // startService(WifiListenerService); } - public static class SettingsFragment extends PreferenceFragment { + public static class SettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener { @Override public void onCreate(Bundle savedInstanceState) { @@ -55,5 +53,111 @@ public class SettingsActivity extends PreferenceActivity { addPreferencesFromResource(R.xml.settings); } + + @Override + public void onResume() { + super.onResume(); + + getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); + + DNSServerAddress.toggleEnabled(this); + DNSServerAddress.displayValue(this); + WifiListener.SSID.displayValue(this); + } + + @Override + public void onPause() { + super.onPause(); + + getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (key.equals("use_automatic_dns_server_discovery")) { + DNSServerAddress.toggleEnabled(this); + } + + else if (key.equals("dns_server_address")) { + DNSServerAddress.displayValue(this); + } + + else if (key.equals("use_wifi_listener")) { + WifiListener.toggle(this); + } + + else if (key.equals("use_wifi_listener_for_activation")) { + if (sharedPreferences.getBoolean("use_wifi_listener_for_activation", false)) { + WifiListener.Activation.enable(this); + } + } + + else if (key.equals("wifi_listener_ssid")) { + WifiListener.SSID.displayValue(this); + } + } + + static class DNSServerAddress { + public static void toggleEnabled(PreferenceFragment context) { + context.findPreference("dns_server_address").setEnabled( + !context.getPreferenceScreen().getSharedPreferences().getBoolean("use_automatic_dns_server_discovery", true) + ); + } + + public static void displayValue(PreferenceFragment context) { + context.findPreference("dns_server_address").setSummary( + context.getPreferenceScreen().getSharedPreferences().getString("dns_server_address", "") + ); + } + } + + static class WifiListener { + public static void toggle(PreferenceFragment context) { + SharedPreferences sharedPreferences = context.getPreferenceScreen().getSharedPreferences(); + + if (sharedPreferences.getBoolean("use_wifi_listener", false)) { + WifiListenerService.start(context.getActivity()); + } else { + disable(context); + } + } + + public static void disable(PreferenceFragment context) { + SharedPreferences sharedPreferences = context.getPreferenceScreen().getSharedPreferences(); + + WifiListenerService.disable(context.getActivity()); + } + + static class Activation { + public static void enable(PreferenceFragment context) { + SharedPreferences sharedPreferences = context.getPreferenceScreen().getSharedPreferences(); + + WifiListenerService.OnActivationListener.askLocationIfNeeded(context.getActivity()); + + if (sharedPreferences.getString("wifi_listener_ssid", "").equals("")) { + WifiManager wifiManager = (WifiManager) context.getActivity().getSystemService(Context.WIFI_SERVICE); + WifiInfo wifiInfo = wifiManager.getConnectionInfo(); + String ssid = wifiInfo.getSSID(); + + // remove quotes around ssid + ssid = ssid.substring(1, ssid.length() - 1); + + if (!ssid.equals("unknown ssid")) { + SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit(); + sharedPreferencesEditor.putString("wifi_listener_ssid", ssid); + sharedPreferencesEditor.commit(); + } + } + } + } + + static class SSID { + public static void displayValue(PreferenceFragment context) { + context.findPreference("wifi_listener_ssid").setSummary( + context.getPreferenceScreen().getSharedPreferences().getString("wifi_listener_ssid", "") + ); + } + } + } } } diff --git a/app/java/src/WifiListenerReceiver.java b/app/java/src/WifiListenerReceiver.java index d34df2b..6bf93bd 100644 --- a/app/java/src/WifiListenerReceiver.java +++ b/app/java/src/WifiListenerReceiver.java @@ -5,6 +5,7 @@ import android.provider.Settings; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.net.NetworkInfo; import android.net.wifi.WifiManager; @@ -13,6 +14,8 @@ import android.net.wifi.WifiInfo; import android.os.Bundle; import android.os.Handler; +import android.preference.PreferenceManager; + import android.util.Log; public class WifiListenerReceiver extends BroadcastReceiver @@ -24,23 +27,33 @@ public class WifiListenerReceiver extends BroadcastReceiver // start if (networkInfo.getState().equals(NetworkInfo.State.CONNECTED)) { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + + if (!sharedPreferences.getBoolean("use_wifi_listener_for_activation", false)) { + return; + } + // wait a few moments for wifi to be fully there - /* (new Handler()).postDelayed(new Runnable() { + (new Handler()).postDelayed(new Runnable() { @Override public void run() { WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); + String ssid = wifiInfo.getSSID(); - // if (wifiInfo.getSSID() == setting.get(LOCAL_HOME_WIFI_SSID)) + // remove quotes around ssid + ssid = ssid.substring(1, ssid.length() - 1); - context.startService(dnsProxyService.setAction(DNSProxyService.ACTION_START)); + if (ssid.equals(sharedPreferences.getString("wifi_listener_ssid", ""))) { + DNSProxyService.start(context); + } } - }, 1000); */ + }, 1000); } // stop else if (networkInfo.getState().equals(NetworkInfo.State.DISCONNECTED) && DNSProxyService.isRunning()) { - context.startService(dnsProxyService.setAction(DNSProxyService.ACTION_STOP)); + DNSProxyService.stop(context); } } } diff --git a/app/java/src/WifiListenerService.java b/app/java/src/WifiListenerService.java index e25c325..1bf89eb 100644 --- a/app/java/src/WifiListenerService.java +++ b/app/java/src/WifiListenerService.java @@ -1,27 +1,37 @@ package org.pihole.dnsproxy; +import android.app.Activity; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; +import android.content.SharedPreferences; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.location.LocationManager; + import android.net.ConnectivityManager; import android.net.wifi.WifiManager; import android.os.IBinder; +import android.preference.PreferenceFragment; +import android.preference.PreferenceManager; + import android.util.Log; public class WifiListenerService extends Service { public static String NOTIFICATION_CHANNEL_ID = "org.pihole.dnsproxy.service.wifiListener"; + public static String ACTION_START = "org.pihole.dnsproxy.service.wifiListener.START"; + public static String ACTION_STOP = "org.pihole.dnsproxy.service.wifiListener.STOP"; + public static String ACTION_STOP_SET_PREFERENCE = "org.pihole.dnsproxy.service.wifiListener.STOP_SET_PREFERENCE"; private BroadcastReceiver receiver; @@ -34,14 +44,28 @@ public class WifiListenerService extends Service @Override public int onStartCommand(Intent intent, int flags, int startId) { - this.start(); + if (intent.getAction().equals(WifiListenerService.ACTION_START)) { + this.listen(); + + return Service.START_STICKY; + } else if (intent.getAction().equals(WifiListenerService.ACTION_STOP)) { + try { + this.deafen(); + } catch (Exception exception) {} + + return Service.START_NOT_STICKY; + } else if (intent.getAction().equals(WifiListenerService.ACTION_STOP_SET_PREFERENCE)) { + WifiListenerService.disable(this); + + return Service.START_NOT_STICKY; + } - return START_STICKY; + return Service.START_NOT_STICKY; } @Override public void onDestroy() { - this.stop(); + this.deafen(); super.onDestroy(); } @@ -49,10 +73,66 @@ public class WifiListenerService extends Service @Override public IBinder onBind(Intent intent) { return null; } - public void start() { - // registerReceiver(this.receiver, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)); + /** + * start this service + */ + public static void start(Context context) { + context.startService((new Intent(context, WifiListenerService.class)).setAction(WifiListenerService.ACTION_START)); + } + + /** + * stop this service + */ + public static void stop(Context context) { + context.startService((new Intent(context, WifiListenerService.class)).setAction(WifiListenerService.ACTION_STOP)); + } + + public static void toggle(Context context) { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + + if (sharedPreferences.getBoolean("use_wifi_listener", false)) { + WifiListenerService.start(context); + } else { + WifiListenerService.stop(context); + } + } + + /** + * Stop Wifi Listener and disable completely + */ + public static void disable(Context context) { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit(); + + WifiListenerService.stop(context); + sharedPreferencesEditor.putBoolean("use_wifi_listener", false); + sharedPreferencesEditor.commit(); + + WifiListenerService.OnActivationListener.disable(context); + } + + /** + * setup listener + */ + private void listen() { registerReceiver(this.receiver, new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION)); + this.startForeground(); + } + + /** + * stop listening + */ + private void deafen() { + unregisterReceiver(this.receiver); + + stopForeground(true); + } + + /** + * Start the Foreground notification process + */ + private void startForeground() { NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); NotificationChannel channel = new NotificationChannel( @@ -66,13 +146,62 @@ public class WifiListenerService extends Service .setSmallIcon(R.drawable.logo) .setContentTitle("Pihole DNS Proxy - WiFi Listener") .setContentText("Listening for WiFi connection change") + .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, SettingsActivity.class), Intent.FLAG_ACTIVITY_NEW_TASK)) + .addAction( + R.drawable.logo, + "Stop Listener", + PendingIntent.getService(this, 0, + (new Intent(this, WifiListenerService.class)).setAction(WifiListenerService.ACTION_STOP_SET_PREFERENCE), + PendingIntent.FLAG_IMMUTABLE + ) + ) + .addAction( + R.drawable.logo, + "Start Proxy", + PendingIntent.getService(this, 0, + (new Intent(this, DNSProxyService.class)).setAction(DNSProxyService.ACTION_START), + PendingIntent.FLAG_IMMUTABLE + ) + ) .build(); startForeground(2, notification); } - public void stop() { - unregisterReceiver(this.receiver); - stopForeground(true); + public static class OnActivationListener { + public static void disable(Context context) { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit(); + LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + + sharedPreferencesEditor.putBoolean("use_wifi_listener_for_activation", false); + sharedPreferencesEditor.commit(); + + if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { + context.startActivity((new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + } + + public static boolean checkLocationNeeded(Context context) { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + + if (!sharedPreferences.getBoolean("use_wifi_listener_for_activation", false)) { + return false; + } + + LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + + return !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); + } + + public static void askLocationIfNeeded(Activity context) { + if (checkLocationNeeded(context)) { + context.requestPermissions(new String[]{ + android.Manifest.permission.ACCESS_FINE_LOCATION, + }, 3765); + + context.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); + } + } } } -- cgit v1.2.3