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.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.location.LocationManager; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.IBinder; import android.preference.PreferenceManager; import android.util.Log; public class WifiListenerService extends Service { public static String NOTIFICATION_CHANNEL_ID = "org.pihole.dnsproxy.service.wifiListener.NOTIFICATION"; 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 = new WifiListenerReceiver(); @Override public int onStartCommand(Intent intent, int flags, int startId) { // start the service if (intent.getAction().equals(WifiListenerService.ACTION_START)) { this.listen(); return Service.START_STICKY; } // stop the service else if (intent.getAction().equals(WifiListenerService.ACTION_STOP)) { try { this.deafen(); } catch (Exception exception) {} return Service.START_NOT_STICKY; } // stop and disable else if (intent.getAction().equals(WifiListenerService.ACTION_STOP_SET_PREFERENCE)) { WifiListenerService.disable(this); return Service.START_NOT_STICKY; } return Service.START_NOT_STICKY; } @Override public void onDestroy() { this.deafen(); super.onDestroy(); } @Override public IBinder onBind(Intent intent) { return null; } /** * Start the service */ public static void start(Context context) { context.startService((new Intent(context, WifiListenerService.class)).setAction(WifiListenerService.ACTION_START)); } /** * Stop the service */ public static void stop(Context context) { context.startService((new Intent(context, WifiListenerService.class)).setAction(WifiListenerService.ACTION_STOP)); } /** * Start/Stop based on setting */ 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); } /** * Get current Wifi SSID */ public static String getWifiSSID(Context context) { WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); String ssid = wifiInfo.getSSID(); // remove quotes around ssid ssid = ssid.substring(1, ssid.length() - 1); return ssid; } /** * 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( WifiListenerService.NOTIFICATION_CHANNEL_ID, WifiListenerService.NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT ); manager.createNotificationChannel(channel); Notification notification = new Notification.Builder(this, WifiListenerService.NOTIFICATION_CHANNEL_ID) .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); } /** * SubClass to enable auto-activation */ public static class OnActivationListener { /** * Disable auto-activation */ 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)); } } /** * Check if location services are needed */ 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); } /** * Ask User to enable location services if they are needed */ 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)); } } } }