From 1e809e8e65173eb1495180fd8f1d05af3367bf5c Mon Sep 17 00:00:00 2001 From: mastermichi <68911754+mastermichi@users.noreply.github.com> Date: Sun, 6 Nov 2022 21:04:22 +0100 Subject: [PATCH] Hue Bridge --- build.gradle | 1 + res/drawable/ic_hue_bridge.xml | 39 +++ res/drawable/ic_hue_bridge_connect.xml | 34 +++ res/layout/hue_connect_preferences.xml | 24 ++ res/xml-v14/preferences_about.xml | 11 + res/xml-v14/preferences_smarthome.xml | 23 +- .../HueApi/HueBridgeSearch.java | 52 ++++ .../HueApi/models/HueViewModel.java | 242 ++++++++++++++++++ .../SmartHomePreferenceFragment.java | 210 ++++++++++++++- .../nightdream/ui/HueConnectPreference.java | 39 +++ .../HueConnectPreferenceFragmentCompat.java | 99 +++++++ 11 files changed, 769 insertions(+), 5 deletions(-) create mode 100644 res/drawable/ic_hue_bridge.xml create mode 100644 res/drawable/ic_hue_bridge_connect.xml create mode 100644 res/layout/hue_connect_preferences.xml create mode 100644 src/com/firebirdberlin/HueApi/HueBridgeSearch.java create mode 100644 src/com/firebirdberlin/HueApi/models/HueViewModel.java create mode 100644 src/com/firebirdberlin/nightdream/ui/HueConnectPreference.java create mode 100644 src/com/firebirdberlin/nightdream/ui/HueConnectPreferenceFragmentCompat.java diff --git a/build.gradle b/build.gradle index 32744e96..b75ff4aa 100644 --- a/build.gradle +++ b/build.gradle @@ -56,6 +56,7 @@ dependencies { implementation 'androidx.work:work-runtime-ktx:2.7.1' implementation 'androidx.work:work-multiprocess:2.7.1' implementation 'com.prof18.rssparser:rssparser:4.0.2' + implementation 'io.github.zeroone3010:yetanotherhueapi:2.7.0' // https://developer.android.com/studio/build/multidex diff --git a/res/drawable/ic_hue_bridge.xml b/res/drawable/ic_hue_bridge.xml new file mode 100644 index 00000000..d0f03c77 --- /dev/null +++ b/res/drawable/ic_hue_bridge.xml @@ -0,0 +1,39 @@ + + + + + + + + diff --git a/res/drawable/ic_hue_bridge_connect.xml b/res/drawable/ic_hue_bridge_connect.xml new file mode 100644 index 00000000..406c8786 --- /dev/null +++ b/res/drawable/ic_hue_bridge_connect.xml @@ -0,0 +1,34 @@ + + + + + + + diff --git a/res/layout/hue_connect_preferences.xml b/res/layout/hue_connect_preferences.xml new file mode 100644 index 00000000..bf9b1fed --- /dev/null +++ b/res/layout/hue_connect_preferences.xml @@ -0,0 +1,24 @@ + + + + + + \ No newline at end of file diff --git a/res/xml-v14/preferences_about.xml b/res/xml-v14/preferences_about.xml index fdb5de45..f7f1358f 100644 --- a/res/xml-v14/preferences_about.xml +++ b/res/xml-v14/preferences_about.xml @@ -307,6 +307,17 @@ vi - Phong Nguyen"/> /> + + + + - + + + + + + diff --git a/src/com/firebirdberlin/HueApi/HueBridgeSearch.java b/src/com/firebirdberlin/HueApi/HueBridgeSearch.java new file mode 100644 index 00000000..cf4d6121 --- /dev/null +++ b/src/com/firebirdberlin/HueApi/HueBridgeSearch.java @@ -0,0 +1,52 @@ +package com.firebirdberlin.HueApi; + +import android.content.Context; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.work.Data; +import androidx.work.Worker; +import androidx.work.WorkerParameters; + +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import io.github.zeroone3010.yahueapi.discovery.HueBridgeDiscoveryService; + +public class HueBridgeSearch extends Worker { + private static final String TAG = "HueBridgeSearch"; + + public HueBridgeSearch(@NonNull Context context, @NonNull WorkerParameters params) { + super(context, params); + } + + @NonNull + @Override + public Result doWork() { + Log.d(TAG, "HueBridgeSearch doWork()"); + + Future> bridgesFuture = new HueBridgeDiscoveryService() + .discoverBridges(bridge -> Log.d(TAG, "ppt Bridge found: " + bridge)); + final List bridges; + try { + bridges = bridgesFuture.get(); + if (!bridges.isEmpty()) { + final String bridgeIp = bridges.get(0).getIp(); + Log.d(TAG, "Bridge found at " + bridgeIp); + // Then follow the code snippets below under the "Once you have a Bridge IP address" header + Data myData = new Data.Builder() + .putString("bridgeIP", bridgeIp) + .build(); + return Result.success(myData); + } + } catch (ExecutionException e) { + e.printStackTrace(); + return Result.failure(); + } catch (InterruptedException e) { + e.printStackTrace(); + return Result.failure(); + } + return Result.success(); + } +} diff --git a/src/com/firebirdberlin/HueApi/models/HueViewModel.java b/src/com/firebirdberlin/HueApi/models/HueViewModel.java new file mode 100644 index 00000000..2d0e384b --- /dev/null +++ b/src/com/firebirdberlin/HueApi/models/HueViewModel.java @@ -0,0 +1,242 @@ +package com.firebirdberlin.HueApi.models; + +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.os.NetworkOnMainThreadException; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; +import androidx.lifecycle.ViewModelStoreOwner; +import androidx.work.Constraints; +import androidx.work.ExistingWorkPolicy; +import androidx.work.NetworkType; +import androidx.work.OneTimeWorkRequest; +import androidx.work.WorkManager; + +import com.firebirdberlin.nightdream.Utility; +import com.firebirdberlin.HueApi.HueBridgeSearch; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; + +import io.github.zeroone3010.yahueapi.Hue; +import io.github.zeroone3010.yahueapi.TrustEverythingManager; + + +public class HueViewModel extends ViewModel { + private static final String TAG = "HueViewModel"; + + private final MutableLiveData hueIPLiveData = new MutableLiveData<>(); + private static MutableLiveData hueKeyLiveData = new MutableLiveData<>(); + private static ExecutorService executor = Executors.newSingleThreadExecutor(); + + private void findHueBridge(Context context, LifecycleOwner lifecycleOwner) { + Log.d(TAG, "findHueBridge()"); + + //return no LAN + if (!Utility.hasNetworkConnection(context)) { + Log.e(TAG, "findHueBridge() no Network Connection"); + hueIPLiveData.postValue("Error:No Network connection"); + return; + } + + //return IP already found + if (hueIPLiveData.getValue() != null && !hueIPLiveData.getValue().isEmpty() && !hueIPLiveData.getValue().contains("Error")) { + return; + } + + Constraints constraints = + new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build(); + + OneTimeWorkRequest getHueBridgeIP = + new OneTimeWorkRequest.Builder( + HueBridgeSearch.class) + .addTag(TAG) + .setConstraints(constraints) + .build(); + + WorkManager manager = WorkManager.getInstance(context); + manager.enqueueUniqueWork(TAG, ExistingWorkPolicy.KEEP, getHueBridgeIP); + + WorkManager.getInstance(context).getWorkInfoByIdLiveData(getHueBridgeIP.getId()) + .observe(lifecycleOwner, info -> { + if (info != null && info.getState().isFinished()) { + Log.d(TAG, "findHueBridge() onChanged"); + manager.getWorkInfoByIdLiveData(getHueBridgeIP.getId()).removeObservers(lifecycleOwner); + String myResult = info.getOutputData().getString("bridgeIP"); + if (myResult == null){ + hueIPLiveData.setValue(""); + }else { + hueIPLiveData.setValue(myResult); + } + } + }); + } + + private void findHueKey(Context context, String bridgeIP) { + Log.d(TAG, "findHueKey() bridgeIP: " + bridgeIP); + + if (!Utility.hasNetworkConnection(context)) { + Log.e(TAG, "findHueKey() no Network Connection"); + hueKeyLiveData.setValue("Error:No Network connection"); + } else { + if (executor.isShutdown()) { + executor = Executors.newSingleThreadExecutor(); + } + + executor.execute(() -> { //background thread + Log.d(TAG, "findHueKey() executor"); + final String appName = "nightdream"; // Fill in the name of your application + final CompletableFuture apiKey = Hue.hueBridgeConnectionBuilder(bridgeIP).initializeApiConnection(appName); + String key; + + // Push the button on your Hue Bridge to resolve the apiKey future: + try { + key = apiKey.get(); + Log.d(TAG, "findHueKey() Store this API key for future use: " + key); + String finalKey = key; + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(() -> { //like onPostExecute() + if (!finalKey.isEmpty()) { + hueKeyLiveData.postValue(finalKey); + Log.d(TAG, "findHueKey() executor after: " + Hue.hueBridgeConnectionBuilder(bridgeIP).initializeApiConnection(appName).isDone()); + testHueConnection(bridgeIP, finalKey); + } + apiKey.cancel(true); + executor.shutdown(); + }); + } catch (ExecutionException e) { + Log.e(TAG, "findHueKey() ExecutionException: " + e.getMessage()); + handleHueApiException(e.getMessage()); + apiKey.cancel(true); + executor.shutdown(); + } catch (InterruptedException e) { + Log.e(TAG, "findHueKey() InterruptedException: " + e.toString()); + handleHueApiException(e.getMessage()); + apiKey.cancel(true); + executor.shutdown(); + } + }); + } + } + + private void handleHueApiException(String exception) { + if (exception != null) { + String[] splitStr = exception.split(":"); + Log.e(TAG, "handleHueApiException() Error: " + splitStr[splitStr.length - 1].trim()); + hueKeyLiveData.postValue("Error:" + splitStr[splitStr.length - 1].trim()); + } else { + hueKeyLiveData.postValue("Error:unknown"); + } + } + + private MutableLiveData getHueIP() { + return hueIPLiveData; + } + + private MutableLiveData getHueKey() { + return hueKeyLiveData; + } + + public static void stopExecutor() { + Log.d(TAG, "stopExecutor()"); + executor.shutdownNow(); + } + + public static void observeIP(Context context, LifecycleOwner lifecycleOwner, @NonNull Observer observer) { + HueViewModel model = new ViewModelProvider((ViewModelStoreOwner) context).get(HueViewModel.class); + model.findHueBridge(context, lifecycleOwner); + model.getHueIP().observe(lifecycleOwner, observer); + } + + public static void observeKey(Context context, LifecycleOwner lifecycleOwner, String BridgeIP, @NonNull Observer observer) { + hueKeyLiveData = new MutableLiveData<>(); + HueViewModel model = new ViewModelProvider((ViewModelStoreOwner) context).get(HueViewModel.class); + model.findHueKey(context, BridgeIP); + LiveDataUtil.observeOnce(model.getHueKey(), observer); + } + + public static boolean testHueIP(String bridgeIP) { + Log.d(TAG, "testHueIP (" + bridgeIP + ")"); + final AtomicBoolean b = new AtomicBoolean(false); + + Thread thread = new Thread(() -> { + try { + TrustEverythingManager.trustAllSslConnectionsByDisablingCertificateVerification(); + HttpURLConnection urlConnection = (HttpURLConnection) new URL("https://" + bridgeIP + "/api/config").openConnection(); + int responseCode = urlConnection.getResponseCode(); + Log.d(TAG, "testHueIP(): " + responseCode); + if (HttpURLConnection.HTTP_OK == responseCode){ + b.set(true); + } + } catch (IOException e) { + Log.e(TAG, "testHueIP(): " + e.toString()); + b.set(false); + } + }); + + thread.start(); + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return b.get(); + } + + public static boolean testHueConnection(String bridgeIP, String apiKey) { + Log.d(TAG, "testHueConnection (" + bridgeIP + "," + apiKey + ")"); + final AtomicBoolean b = new AtomicBoolean(false); + final Hue hue = new Hue(bridgeIP, apiKey); + + Thread thread = new Thread(() -> { + try { + try { + hue.getAllLights(); + b.set(true); + Log.d(TAG, "testHueConnection() true"); + } catch (NetworkOnMainThreadException e) { + Log.d(TAG, "testHueConnection() failed: " + e); + } + } catch (Exception e) { + e.printStackTrace(); + } + }); + + thread.start(); + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return b.get(); + } + + private static class LiveDataUtil { + public static void observeOnce(final LiveData liveData, final Observer observer) { + liveData.observeForever(new Observer() { + @Override + public void onChanged(T t) { + liveData.removeObserver(this); + observer.onChanged(t); + } + }); + } + } + +} diff --git a/src/com/firebirdberlin/nightdream/SmartHomePreferenceFragment.java b/src/com/firebirdberlin/nightdream/SmartHomePreferenceFragment.java index 896544a1..7f08fc04 100644 --- a/src/com/firebirdberlin/nightdream/SmartHomePreferenceFragment.java +++ b/src/com/firebirdberlin/nightdream/SmartHomePreferenceFragment.java @@ -1,22 +1,28 @@ package com.firebirdberlin.nightdream; -import android.content.Intent; import android.content.SharedPreferences; -import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.text.InputType; +import android.util.Log; import android.widget.EditText; import androidx.annotation.NonNull; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentResultListener; +import androidx.fragment.app.FragmentTransaction; import androidx.preference.EditTextPreference; import androidx.preference.Preference.SummaryProvider; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; +import com.firebirdberlin.HueApi.models.HueViewModel; +import com.firebirdberlin.nightdream.ui.HueConnectPreferenceFragmentCompat; +import com.firebirdberlin.nightdream.ui.HueConnectPreference; public class SmartHomePreferenceFragment extends PreferenceFragmentCompat { public static final String PREFS_KEY = "NightDream preferences"; + public static final String TAG = "SmartHomePrefFragment"; Settings settings = null; @@ -24,11 +30,16 @@ public class SmartHomePreferenceFragment extends PreferenceFragmentCompat { new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + Log.d(TAG, "onSharedPreferenceChanged: " + key); + switch (key) { + case "switchHue": + connectToHueBridge(sharedPreferences); + break; + } } }; - @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { getPreferenceManager().setSharedPreferencesName(PREFS_KEY); @@ -67,6 +78,8 @@ public void onBindEditText(@NonNull final EditText editText) { } ); } + + connectToHueBridge(prefs); } private void showPreference(String key, boolean visible) { @@ -75,4 +88,193 @@ private void showPreference(String key, boolean visible) { preference.setVisible(visible); } } + + @Override + public void onCreate(Bundle savedInstanceState) { + Log.d(TAG, "onCreate()"); + super.onCreate(savedInstanceState); + + getParentFragmentManager().setFragmentResultListener("hueKey", this, new FragmentResultListener() { + @Override + public void onFragmentResult(@NonNull String requestKey, @NonNull Bundle bundle) { + SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); + + // We use a String here, but any type that can be put in a Bundle is supported + String hueKey = bundle.getString("hueKey"); + Log.d(TAG, "onCreate() setFragmentResultListener: " + hueKey); + + // Do something with the result + + if (hueKey.contains("Error")) { + handleHueError("connectHue", hueKey); + } else { + Log.d(TAG, "onCreate() Key found"); + //Key found + if (prefs != null) { + testHueKey(prefs.getString("hueBridgeIP", ""), hueKey); + } + } + } + }); + } + + private void connectToHueBridge(SharedPreferences prefs) { + Log.d(TAG, "connectToHueBridge()"); + Preference switchHuePreference = findPreference("switchHue"); + Preference hueKeyPreference = findPreference("connectHue"); + + if (switchHuePreference != null) { + boolean on = prefs.getBoolean("switchHue", false); + Log.d(TAG, "connectToHueBridge() enable:" + on); + + if (on) { + //return no Network connection + if (getContext() != null && !Utility.hasNetworkConnection(getContext())) { + Log.e(TAG, "connectToHueBridge() no Network Connection"); + handleHueError("switchHue", "No Network connection"); + return; + } + + switchHuePreference.setSummary("suche nach Hue Bridge"); + Log.d(TAG, "connectToHueBridge() prefs hueBridgeIP: " + prefs.getString("hueBridgeIP", "No IP")); + String hueBridgeIP = prefs.getString("hueBridgeIP", ""); + + if (hueBridgeIP.isEmpty() || !HueViewModel.testHueIP(hueBridgeIP)) { + Log.d(TAG, "connectToHueBridge() no working hueBridgeIP in prefs"); + HueViewModel.observeIP(getContext(), getViewLifecycleOwner(), bridgeIP -> { + Log.d(TAG, "connectToHueBridge() found hueBridgeIP: " + bridgeIP); + + //Save IP + SharedPreferences.Editor editor = prefs.edit(); + editor.putString("hueBridgeIP", bridgeIP); + editor.apply(); + + boolean showIp = prefs.getBoolean("switchHue", false); + if (showIp && !bridgeIP.isEmpty()) { + if (bridgeIP.contains("Error")) { + handleHueError("switchHue", bridgeIP); + } else { + switchHuePreference.setSummary(bridgeIP); + enablePreference("connectHue", true); + + String hueKey = prefs.getString("hueKey", ""); + if (hueKey.isEmpty()) { + Log.d(TAG, "connectToHueBridge() empty hueKey in prefs"); + if (hueKeyPreference != null) { + hueKeyPreference.setSummary("not connected"); + } + showHueDialog(prefs, "connectHue"); + } else { + Log.d(TAG, "connectToHueBridge() found hueKey in prefs: " + hueKey); + testHueKey(bridgeIP, hueKey); + } + } + } + }); + } else { + //bridge IP found in prefs + Log.d(TAG, "connectToHueBridge() hueBridgeIP found in prefs: "+hueBridgeIP); + switchHuePreference.setSummary(hueBridgeIP); + enablePreference("connectHue", true); + String hueKey = prefs.getString("hueKey", ""); + if (hueKey.isEmpty()) { + Log.d(TAG, "connectToHueBridge() empty hueKey in prefs"); + if (hueKeyPreference != null) { + hueKeyPreference.setSummary("not connected"); + } + } else { + Log.d(TAG, "connectToHueBridge() found hueKey in prefs: " + hueKey); + testHueKey(hueBridgeIP, hueKey); + } + } + } else { + switchHuePreference.setSummary(""); + if (hueKeyPreference != null) { + hueKeyPreference.setSummary(""); + } + enablePreference("connectHue", false); + switchHuePreference.setIcon(R.drawable.ic_hue_bridge_connect); + } + } + } + + private void testHueKey(String hueBridgeIP, String hueKey) { + SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); + Preference switchHuePreference = findPreference("switchHue"); + Preference switchHueKeyPreference = findPreference("connectHue"); + + if (prefs != null) { + if (HueViewModel.testHueConnection(hueBridgeIP, hueKey)) { + Log.d(TAG, "onCreate() testHueConnection ok"); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString("hueKey", hueKey); + editor.apply(); + + if (switchHuePreference != null) { + switchHuePreference.setIcon(R.drawable.ic_hue_bridge); + } + + if (switchHueKeyPreference != null) { + switchHueKeyPreference.setSummary("Connected"); + } + } else { + Log.e(TAG, "onCreate() testHueConnection failed"); + handleHueError("connectHue", "Can not connect to Hue Bridge"); + } + } + } + + private void showHueDialog(SharedPreferences prefs, String key) { + Log.d(TAG, "showHueDialog"); + FragmentTransaction ft = getParentFragmentManager().beginTransaction(); + Fragment prev = getParentFragmentManager().findFragmentByTag("HueDialog"); + if (prev != null) { + ft.remove(prev); + } + ft.addToBackStack(null); + DialogFragment dialogFragment = HueConnectPreferenceFragmentCompat + .newInstance(key, prefs.getString("hueBridgeIP", "")); + + dialogFragment.setTargetFragment(this, 0); + dialogFragment.show(ft, "HueDialog"); + } + + private void handleHueError(String huePreferenceKey, String errorMessage) { + Log.d(TAG, "handleHueError() : "+errorMessage); + Preference huePreference = findPreference(huePreferenceKey); + if (huePreference != null) { + String[] splitStr = errorMessage.split(":"); + Log.e(TAG, "handleHueError(): " + splitStr[splitStr.length - 1].trim()); + switch (splitStr[splitStr.length - 1].trim()) { + case "No Network connection": + case "Host unreachable": + case "link button not pressed": + case "Can not connect to Hue Bridge": + case "No address associated with hostname": + huePreference.setSummary(splitStr[splitStr.length - 1].trim()); + break; + default: + huePreference.setSummary("Unknown Error"); + break; + } + } + } + + private void enablePreference(String key, boolean on) { + Preference preference = findPreference(key); + if (preference != null) { + Log.d(TAG, "enablePreference(): " + preference.getKey()); + preference.setEnabled(on); + } else { + Log.w(TAG, "WARNING: preference " + key + " not found."); + } + } + + @Override + public void onDisplayPreferenceDialog(@NonNull Preference preference) { + if (preference instanceof HueConnectPreference) { + Log.d(TAG, "onDisplayPreferenceDialog() preference instanceof HueConnectPreference"); + showHueDialog(getPreferenceManager().getSharedPreferences(), preference.getKey()); + } else super.onDisplayPreferenceDialog(preference); + } } diff --git a/src/com/firebirdberlin/nightdream/ui/HueConnectPreference.java b/src/com/firebirdberlin/nightdream/ui/HueConnectPreference.java new file mode 100644 index 00000000..fa70c530 --- /dev/null +++ b/src/com/firebirdberlin/nightdream/ui/HueConnectPreference.java @@ -0,0 +1,39 @@ +package com.firebirdberlin.nightdream.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; + +import androidx.preference.DialogPreference; + +import com.firebirdberlin.nightdream.R; + +public class HueConnectPreference extends DialogPreference { + private static final String TAG = "HueConnectPreference"; + + public HueConnectPreference(Context context) { + this(context, null); + } + + public HueConnectPreference(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.dialogPreferenceStyle); + } + + public HueConnectPreference(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, defStyleAttr); + } + + public HueConnectPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + Log.d(TAG, "HueConnectPreference()"); + + // Do custom stuff here, read attributes etc. + setPositiveButtonText(null); + setNegativeButtonText(android.R.string.cancel); + } + + @Override + public int getDialogLayoutResource() { + return R.layout.hue_connect_preferences; + } +} diff --git a/src/com/firebirdberlin/nightdream/ui/HueConnectPreferenceFragmentCompat.java b/src/com/firebirdberlin/nightdream/ui/HueConnectPreferenceFragmentCompat.java new file mode 100644 index 00000000..b5517702 --- /dev/null +++ b/src/com/firebirdberlin/nightdream/ui/HueConnectPreferenceFragmentCompat.java @@ -0,0 +1,99 @@ +package com.firebirdberlin.nightdream.ui; + +import android.content.DialogInterface; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.preference.PreferenceDialogFragmentCompat; + +import com.firebirdberlin.nightdream.R; +import com.firebirdberlin.HueApi.models.HueViewModel; + +public class HueConnectPreferenceFragmentCompat extends PreferenceDialogFragmentCompat { + private static final String TAG = "HueConnectPrefFragmentC"; + private static String bridgeIP; + private boolean isDismissible = false; + + public static HueConnectPreferenceFragmentCompat newInstance(String key, String bridge_IP) { + final HueConnectPreferenceFragmentCompat + fragment = new HueConnectPreferenceFragmentCompat(); + final Bundle b = new Bundle(1); + b.putString(ARG_KEY, key); + fragment.setArguments(b); + + bridgeIP = bridge_IP; + + return fragment; + } + + @Override + protected void onBindDialogView(@NonNull View view) { + super.onBindDialogView(view); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + Log.d(TAG, "onCreateView()"); + + HueViewModel.observeKey(getContext(), getViewLifecycleOwner(), bridgeIP, Key -> { + + Log.d(TAG, "onCreateView() found Key: " + Key); + + if (!Key.isEmpty()) { + setFragmentResult(Key); + dismissAllowingStateLoss(); + } else { + Log.d(TAG, "onCreateView() Key empty"); + } + + }); + + return inflater.inflate(R.layout.hue_connect_preferences, container, false); + } + + @Override + public void onDialogClosed(boolean positiveResult) { + Log.d(TAG, "onDialogClosed(): " + positiveResult); + HueViewModel.stopExecutor(); + } + + @Override + public void dismiss() { + Log.d(TAG, "dismiss()"); + try { + isDismissible = true; + super.dismiss(); + Log.d(TAG, "dismiss() Dialog dismissed!"); + } catch (IllegalStateException e) { + Log.d(TAG, "dismiss() error: " + e.toString()); + } + } + + @Override + public void onDismiss(@NonNull DialogInterface dialog) { + Log.d(TAG, "onDismiss()"); + if (isDismissible) { + super.onDismiss(dialog); + } + } + + private void setFragmentResult(String hueKey) { + if (isAdded()) { + Bundle result = new Bundle(); + result.putString("hueKey", hueKey); + getParentFragmentManager().setFragmentResult("hueKey", result); + } + } + +}