1616
1717package com .earthstormsoftware .motecontrol ;
1818
19+ import android .content .BroadcastReceiver ;
20+ import android .content .Context ;
21+ import android .content .Intent ;
22+ import android .content .IntentFilter ;
1923import android .content .SharedPreferences ;
2024import android .graphics .Color ;
2125import android .graphics .drawable .GradientDrawable ;
2226import android .preference .PreferenceManager ;
2327import android .support .v4 .app .Fragment ;
2428import android .os .Bundle ;
29+ import android .util .Log ;
2530import android .view .LayoutInflater ;
2631import android .view .View ;
2732import android .view .ViewGroup ;
3035import android .widget .Toast ;
3136import android .widget .ToggleButton ;
3237
33- import okhttp3 .OkHttpClient ;
34- import okhttp3 .logging .HttpLoggingInterceptor ;
35- import retrofit2 .Call ;
36- import retrofit2 .Callback ;
37- import retrofit2 .Response ;
38- import retrofit2 .Retrofit ;
39- import retrofit2 .converter .gson .GsonConverterFactory ;
38+ import com .earthstormsoftware .motecontrol .com .earthstormsoftware .motecontrol .moteutil .Mote ;
39+ import com .earthstormsoftware .motecontrol .com .earthstormsoftware .motecontrol .moteutil .MoteAPIResponseType ;
40+ import com .earthstormsoftware .motecontrol .com .earthstormsoftware .motecontrol .moteutil .MoteMode ;
4041
4142/*
42- Fragment used to display the main UI. Using fragments is generally considered good practice,
43- even though the initial UI is quite simple.
43+ * Fragment used to display the main UI. Using fragments is generally considered good practice,
44+ * even though the initial UI is quite simple.
4445 */
4546
4647public class MainActivityFragment extends Fragment {
4748
4849 private String moteURI ;
4950
51+ private Mote mote ;
5052 private ToggleButton tglMoteSwitch ;
5153 private Button btnColourPicker ;
5254 private int initialPickerColor ;
5355
56+ private BroadcastReceiver moteUpdateReceiver ;
5457 private ColorPickerDialog colorPickerDialog ;
5558
5659 public MainActivityFragment () {
@@ -65,16 +68,26 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
6568
6669 // Retrieve the URL of the Mote API from device storage
6770 SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences (getActivity ());
68- moteURI = prefs .getString ("mote_uri" , "http://127.0.0.1" );
71+ moteURI = prefs .getString ("mote_uri" , null );
72+
73+ // Create the local Mote object and get the current status of the Mote from the host device
74+ if (moteURI != null ){
75+ mote = new Mote (moteURI ,"1" ,"Mote1" ,false , MoteMode .COLOUR );
76+ mote .updateMoteStatus ();
77+ } else {
78+ Toast .makeText (getActivity (), R .string .configure_api_url , Toast .LENGTH_SHORT ).show ();
79+ }
6980
7081 // Setup the colour picker dialog that will be called when the user clicks the button
7182 initialPickerColor = Color .WHITE ;
7283 colorPickerDialog = new ColorPickerDialog (getActivity (), initialPickerColor , new ColorPickerDialog .OnColorSelectedListener () {
7384
7485 @ Override
7586 public void onColorSelected (int color ) {
76- GradientDrawable bgShape = (GradientDrawable )btnColourPicker .getBackground ();
77- bgShape .setColor (color );
87+ Log .i (MoteControl .TAG ,"Color selected: " + color );
88+ if (mote != null ) {
89+ mote .setColour (color );
90+ }
7891 setMoteColour (color );
7992 }
8093 });
@@ -84,152 +97,126 @@ public void onColorSelected(int color) {
8497 btnColourPicker .setOnClickListener (new View .OnClickListener () {
8598 @ Override
8699 public void onClick (View view ) {
87- colorPickerDialog .show ();
100+ if (mote != null ) {
101+ colorPickerDialog .show ();
102+ } else {
103+ Toast .makeText (getActivity (), R .string .configure_api_url , Toast .LENGTH_SHORT ).show ();
104+ }
105+
88106 }
89107 });
90108
91-
92109 // Setup the toggle button which will turn the Mote on and off
93110 tglMoteSwitch = (ToggleButton ) view .findViewById (R .id .tglMoteSwitch );
94111 tglMoteSwitch .setOnCheckedChangeListener (new CompoundButton .OnCheckedChangeListener () {
95112 public void onCheckedChanged (CompoundButton buttonView , boolean isChecked ) {
96- if (isChecked ) {
97- toggleMoteStatus (true );
113+ if (mote != null ) {
114+ if (isChecked ) {
115+ setMoteState (true );
116+ } else {
117+ setMoteState (false );
118+ }
98119 } else {
99- toggleMoteStatus (false );
120+ if (isChecked ) {
121+ tglMoteSwitch .setChecked (false );
122+ Toast .makeText (getActivity (), R .string .configure_api_url , Toast .LENGTH_SHORT ).show ();
123+ }
100124 }
101125 }
102126 });
103-
104- // Try and get the current status of the Mote
105- updateMoteStatus ();
106-
107127 return view ;
108128 }
109129
110- // Call the Mote API to get the current state and colour of the Mote
111- public void updateMoteStatus (){
130+ @ Override
131+ public void onResume () {
132+ super .onResume ();
133+
134+ /*
135+ * When the Fragment is visible and active, use a BroadcastReceiver to receive notifications
136+ * when an API response is received so the displayed information can be updated.
137+ */
138+ if (moteUpdateReceiver == null ){
139+ moteUpdateReceiver = new BroadcastReceiver () {
140+ @ Override
141+ public void onReceive (Context context , Intent intent ) {
142+ MoteAPIResponseType mrt = (MoteAPIResponseType ) intent .getSerializableExtra ("result" );
143+ if (mrt == MoteAPIResponseType .OK ) {
144+ updateDisplay ();
145+ } else {
146+ Toast .makeText (getActivity (), mrt .toString (), Toast .LENGTH_SHORT ).show ();
147+ }
148+ }
149+ };
150+ Log .i (MoteControl .TAG ,"BroadcastReceiver created" );
151+ }
152+ IntentFilter intent = new IntentFilter (MoteControl .MOTE_API_RESPONSE );
153+ getActivity ().registerReceiver (moteUpdateReceiver , intent );
154+ Log .i (MoteControl .TAG ,"BroadcastReceiver registered" );
112155
113- // Uncomment to enable Retrofit logging
114- //HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
115- //logging.setLevel(HttpLoggingInterceptor.Level.BODY);
116- OkHttpClient .Builder httpClient = new OkHttpClient .Builder ();
117- //httpClient.addInterceptor(logging);
156+ // Update the display whenever the user returns to this fragment
157+ updateDisplay ();
158+ }
118159
119- Retrofit retrofit = new Retrofit .Builder ()
120- .baseUrl (moteURI )
121- .addConverterFactory (GsonConverterFactory .create ())
122- .client (httpClient .build ())
123- .build ();
160+ @ Override
161+ public void onPause () {
162+ super .onPause ();
124163
125- MoteAPI moteAPI = retrofit .create (MoteAPI .class );
164+ // If the user navigates away from the fragment, unregister the BroadcastReveiver as
165+ // notifications are not required.
166+ getActivity ().unregisterReceiver (moteUpdateReceiver );
167+ Log .i (MoteControl .TAG ,"BroadcastReceiver unregistered" );
168+ }
126169
127- // This is where the API actually gets called.
128- // Note: Using Enqueue means this is an asynchronous call, and not handled on the UI thread.
129- final Call <MoteStatus > call = moteAPI .getMoteStatus ();
130- call .enqueue (new Callback <MoteStatus >() {
131- @ Override
132- public void onResponse (Call <MoteStatus > call , Response <MoteStatus > response ) {
170+ // Update the UI elements based on the current known state
171+ private void updateDisplay (){
133172
134- // Change the toggle switch setting depending on the Mote status
135- if (response .body ().getStatus () == 1 ){
136- tglMoteSwitch .setChecked (true );
137- } else {
138- tglMoteSwitch .setChecked (false );
139- }
173+ Log .i (MoteControl .TAG ,"Updating UI based on current status" );
140174
141- // Change the colour button depending on the Mote colour/
142- int curColour = Color .parseColor ("#" + response .body ().getColour ());
143- GradientDrawable bgShape = (GradientDrawable )btnColourPicker .getBackground ();
144- bgShape .setColor (curColour );
175+ if (mote != null ) {
176+ // Change the toggle switch setting depending on the Mote status
177+ if (mote .isOn ()){
178+ tglMoteSwitch .setChecked (true );
179+ } else {
180+ tglMoteSwitch .setChecked (false );
145181 }
146182
147- @ Override
148- public void onFailure (Call <MoteStatus > call , Throwable t ) {
149- // If the API call fails for any reason a short toast will be popped up.
150- Toast .makeText (getActivity (), R .string .txt_mote_api_error , Toast .LENGTH_SHORT ).show ();
151- }
152- });
183+ // Change the colour button depending on the Mote colour/
184+ GradientDrawable bgShape = (GradientDrawable )btnColourPicker .getBackground ();
185+ bgShape .setColor (mote .getColour ());
186+ }
153187 }
154188
155- // Call the Mote API to set the current state (on or off) of the Mote
156- public void toggleMoteStatus (boolean newState ){
157-
158- //HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
159- //logging.setLevel(HttpLoggingInterceptor.Level.BODY);
160- OkHttpClient .Builder httpClient = new OkHttpClient .Builder ();
161- //httpClient.addInterceptor(logging);
162-
163- Retrofit retrofit = new Retrofit .Builder ()
164- .baseUrl (moteURI )
165- .addConverterFactory (GsonConverterFactory .create ())
166- .client (httpClient .build ())
167- .build ();
168-
169- MoteAPI moteAPI = retrofit .create (MoteAPI .class );
170-
171- // Call different API methods for turning on and off
172- Call <MoteStatus > call ;
173- if (newState == true ) {
174- call = moteAPI .setMoteOn ();
189+ // Call the Mote API to get the current status of the Mote from the host device
190+ public void updateMoteStatus (){
191+ if (mote != null ){
192+ Log .i (MoteControl .TAG ,"Requesting Mote status update" );
193+ mote .updateMoteStatus ();
194+ updateDisplay ();
175195 } else {
176- call = moteAPI . setMoteOff ();
196+ Toast . makeText ( getActivity (), R . string . configure_api_url , Toast . LENGTH_SHORT ). show ();
177197 }
198+ }
178199
179- call .enqueue (new Callback <MoteStatus >() {
180- @ Override
181- public void onResponse (Call <MoteStatus > call , Response <MoteStatus > response ) {
182-
183- // If the call worked, the toggle switch will already have been set to the desired
184- // state, so we just need to update the current colour, which is provided in the
185- // response
186- int curColour = Color .parseColor ("#" + response .body ().getColour ());
187- GradientDrawable bgShape = (GradientDrawable )btnColourPicker .getBackground ();
188- bgShape .setColor (curColour );
189- }
190-
191- @ Override
192- public void onFailure (Call <MoteStatus > call , Throwable t ) {
193- Toast .makeText (getActivity (), R .string .txt_mote_api_error , Toast .LENGTH_SHORT ).show ();
194- }
195- });
200+ // Call the Mote API to set the current state (on or off) on the Mote device
201+ public void setMoteState (boolean newState ){
202+ if (mote != null ){
203+ Log .i (MoteControl .TAG ,"Setting new Mote state" );
204+ mote .setMoteState (newState );
205+ updateDisplay ();
206+ } else {
207+ Toast .makeText (getActivity (), R .string .configure_api_url , Toast .LENGTH_SHORT ).show ();
208+ }
196209 }
197210
198- // Call the Mote API to set the desired colour of the Mote
211+ // Call the Mote API to set the desired colour of the Mote on the host device
199212 public void setMoteColour (int newColour ){
213+ if (mote != null ){
214+ Log .i (MoteControl .TAG ,"Setting new Mote colour" );
215+ mote .setMoteColour ();
216+ updateDisplay ();
217+ } else {
218+ Toast .makeText (getActivity (), R .string .configure_api_url , Toast .LENGTH_SHORT ).show ();
219+ }
200220
201- //HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
202- //logging.setLevel(HttpLoggingInterceptor.Level.BODY);
203- OkHttpClient .Builder httpClient = new OkHttpClient .Builder ();
204- //httpClient.addInterceptor(logging);
205-
206- Retrofit retrofit = new Retrofit .Builder ()
207- .baseUrl (moteURI )
208- .addConverterFactory (GsonConverterFactory .create ())
209- .client (httpClient .build ())
210- .build ();
211-
212- MoteAPI moteAPI = retrofit .create (MoteAPI .class );
213-
214- // Android stores colour as ints, but the API expects RGB values in the form RRGGBB, so we
215- // need to convert before calling the API
216- String strColour = String .format ("%06X" , (0xFFFFFF & newColour ));
217- final Call <MoteStatus > call = moteAPI .setMoteColour (strColour );
218-
219- call .enqueue (new Callback <MoteStatus >() {
220- @ Override
221- public void onResponse (Call <MoteStatus > call , Response <MoteStatus > response ) {
222-
223- // The state (on or off) was not changed, so just update the colour
224- int curColour = Color .parseColor ("#" + response .body ().getColour ());
225- GradientDrawable bgShape = (GradientDrawable )btnColourPicker .getBackground ();
226- bgShape .setColor (curColour );
227- }
228-
229- @ Override
230- public void onFailure (Call <MoteStatus > call , Throwable t ) {
231- Toast .makeText (getActivity (), R .string .txt_mote_api_error , Toast .LENGTH_SHORT ).show ();
232- }
233- });
234221 }
235222}
0 commit comments