added code to close the netlink socket.
[contrib/iotivity.git] / java / examples-android / guiclient / src / main / java / org / iotivity / guiclient / MainActivity.java
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Corporation.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 package org.iotivity.guiclient;
22
23 import android.app.AlertDialog;
24 import android.content.DialogInterface;
25 import android.support.v7.app.ActionBarActivity;
26 import android.os.Bundle;
27 import android.util.Log;
28 import android.view.Menu;
29 import android.view.MenuItem;
30 import android.view.View;
31 import android.widget.ExpandableListView;
32 import android.widget.ProgressBar;
33
34 import java.util.ArrayList;
35 import java.util.List;
36
37 import static org.iotivity.guiclient.OcAttributeInfo.OC_ATTRIBUTE_TYPE.LIGHT_DIMMER;
38 import static org.iotivity.guiclient.OcAttributeInfo.OC_ATTRIBUTE_TYPE.LIGHT_SWITCH;
39 import static org.iotivity.guiclient.OcAttributeInfo.OC_ATTRIBUTE_TYPE.PLATFORM_LED_SWITCH;
40 import static org.iotivity.guiclient.R.id.expandableResourceListView;
41
42 /**
43  * MainActivity instantiates a ExpandableListView of type ExpandableResourceListView, and
44  * also creates and starts a OcWorker object to handle the IoTivity specific work.
45  *
46  * @see org.iotivity.guiclient.OcWorker
47  * @see org.iotivity.guiclient.OcWorkerListener
48  * @see org.iotivity.guiclient.ExpandableResourceListAdapter
49  */
50 public class MainActivity
51         extends ActionBarActivity
52         implements OcWorkerListener, View.OnClickListener, ExpandableListView.OnChildClickListener {
53     /**
54      * Hardcoded TAG... if project never uses proguard then
55      * MyOcClient.class.getName() is the better way.
56      */
57     private static final String TAG = "MainActivity";
58
59     private static final boolean LOCAL_LOGV = true; // set to false to compile out verbose logging
60
61     /**
62      * The data structure behind the displayed List of resources and attributes.
63      */
64     private List<OcResourceInfo> mResourceList;
65
66     /**
67      * The custom adapter for displaying the ResourceListItem List
68      */
69     private ExpandableResourceListAdapter mResourceListAdapter;
70
71     /**
72      * The OIC-aware worker class which does all the OIC API interaction
73      * and handles the results, notifying MainActivity whenever an event
74      * requires a UI update.
75      */
76     private OcWorker mOcWorker;
77
78     /**
79      * Preserve a ref to Action Bar Menu for changing progress icon
80      */
81     private Menu optionsMenu;
82
83     @Override
84     protected void onCreate(Bundle savedInstanceState) {
85         if (LOCAL_LOGV) Log.v(TAG, "onCreate()");
86
87         super.onCreate(savedInstanceState);
88
89         setContentView(R.layout.activity_main);
90
91         // start the OcWorker thread and register as a listener
92         if(null == this.mOcWorker) {
93             this.mOcWorker = new OcWorker(this);
94             this.mOcWorker.start(); // configures the OIC platform and wait for further calls
95             this.mOcWorker.registerListener(this);
96         }
97
98         // init the Resource display list
99         if(null == this.mResourceList) {
100             this.mResourceList = new ArrayList<>();
101         }
102
103         // init the ListView Adapter
104         if(null == this.mResourceListAdapter) {
105             this.mResourceListAdapter = new ExpandableResourceListAdapter(this.mResourceList,
106                     this);
107         }
108
109         // init the Expandable List View
110         ExpandableListView exListView =
111                 (ExpandableListView) findViewById(expandableResourceListView);
112         exListView.setIndicatorBounds(5, 5);
113         exListView.setIndicatorBounds(0, 20);
114         exListView.setAdapter(this.mResourceListAdapter);
115         exListView.setOnChildClickListener(this);
116     }
117
118     @Override
119     public void onRestoreInstanceState(Bundle savedInstanceState) {
120         if (LOCAL_LOGV) Log.v(TAG, "onRestoreInstanceState()");
121     }
122
123     @Override
124     public void onSaveInstanceState(Bundle outState) {
125         if (LOCAL_LOGV) Log.v(TAG, "onSaveInstanceState()");
126     }
127
128     @Override
129     public void onClick(View v) {
130         if (LOCAL_LOGV) Log.v(TAG, "onClick()");
131
132         this.setRefreshActionButtonState(false);
133     }
134
135     @Override
136     public boolean onChildClick(ExpandableListView parent,
137                                 View v,
138                                 int groupPosition,
139                                 int childPosition,
140                                 long id) {
141         if (LOCAL_LOGV) Log.v(TAG, "onChildClick()");
142
143         this.mOcWorker.doGetResource(mResourceList.get(groupPosition));
144
145         return false;
146     }
147
148     @Override
149     public boolean onCreateOptionsMenu(Menu menu) {
150         if (LOCAL_LOGV) Log.v(TAG, "onCreateOptionsMenu()");
151
152         // save a reference for use in controlling refresh icon later
153         this.optionsMenu = menu;
154
155         // Inflate the menu; this adds items to the action bar if it is present.
156         getMenuInflater().inflate(R.menu.menu_main, menu);
157
158         return true;
159     }
160
161     @Override
162     public boolean onOptionsItemSelected(MenuItem item) {
163         if (LOCAL_LOGV) Log.v(TAG, String.format("onOptionsItemSelected(%s)", item.toString()));
164         // Handle action bar item clicks here. The action bar will
165         // automatically handle clicks on the Home/Up button, so long
166         // as you specify a parent activity in AndroidManifest.xml.
167         int id = item.getItemId();
168
169         // Handle the "settings" icon/text click
170         if (id == R.id.action_settings) {
171             return true;
172         }
173
174         // Handle the "developer test" icon/text click
175         if (id == R.id.action_test) {
176             return true;
177         }
178
179         // Handle the trash can "discard" icon click
180         if (id == R.id.action_discard) {
181             AlertDialog diaBox = confirmDiscard();
182             diaBox.show();
183         }
184
185         // Handle the refresh/progress icon click
186         if (id == R.id.action_refresh) {
187             // show the indeterminate progress bar
188             this.setRefreshActionButtonState(true);
189             // use OcWorker to discover resources
190             this.mOcWorker.doDiscoverResources();
191         }
192
193         return super.onOptionsItemSelected(item);
194     }
195
196     /**
197      * Handle a resource changed callback from OcWorker by posting a runnable to our
198      * own UI-safe looper/handler
199      */
200     @Override
201     public void onResourceChanged(final OcResourceInfo resourceInfo) {
202         if (LOCAL_LOGV) Log.v(TAG, "onResourceChanged()");
203
204         runOnUiThread(new Runnable() {
205             @Override
206             public void run() {
207                 // in case we were waiting for a refresh, hide the indeterminate progress bar
208                 setRefreshActionButtonState(false);
209
210                 mResourceListAdapter.notifyDataSetChanged();
211             }
212         });
213     }
214
215     /**
216      * Handle a new resource found callback from OcWorker by posting a runnable to our
217      * own UI-safe looper/handler
218      */
219     @Override
220     public void onResourceFound(final OcResourceInfo resourceInfo) {
221         if (LOCAL_LOGV) Log.v(TAG, "onResourceFound()");
222
223         runOnUiThread(new Runnable() {
224             @Override
225             public void run() {
226                 // in case we were waiting for a refresh, hide the indeterminate progress bar
227                 setRefreshActionButtonState(false);
228
229                 // if resource not already in list, add it
230                 if(!mResourceList.contains(resourceInfo)) {
231                     mResourceList.add(resourceInfo);
232                 }
233
234                 mResourceListAdapter.notifyDataSetChanged();
235             }
236         });
237     }
238
239     public void toggleLedSwitch(OcResourceInfo resourceInfo, boolean onOff) {
240         if (LOCAL_LOGV) Log.d(TAG, String.format("toggleLedSwitch(%s, %s)",
241                 resourceInfo.getHost() + resourceInfo.getUri(), String.valueOf(onOff)));
242
243         // send a msg to OcWorker to put the switch value
244         for(OcAttributeInfo ai : resourceInfo.getAttributes()) {
245             if(ai.getType() == PLATFORM_LED_SWITCH) {
246                 if(onOff) {
247                     ai.setValueInt(1);
248                 } else {
249                     ai.setValueInt(0);
250                 }
251             }
252         }
253         this.mOcWorker.doPutResource(resourceInfo);
254     }
255
256     public void toggleLightSwitch(OcResourceInfo resourceInfo, boolean onOff) {
257         if (LOCAL_LOGV) Log.d(TAG, String.format("toggleLightSwitch(%s, %s)",
258                 resourceInfo.getHost() + resourceInfo.getUri(), String.valueOf(onOff)));
259
260         // send a msg to OcWorker to put the switch value
261         for(OcAttributeInfo ai : resourceInfo.getAttributes()) {
262             if(ai.getType() == LIGHT_SWITCH) {
263                 ai.setValueBool(onOff);
264             }
265         }
266         this.mOcWorker.doPutResource(resourceInfo);
267     }
268
269     public void setLightDimmerLevel(OcResourceInfo resourceInfo, int value) {
270         if (LOCAL_LOGV) Log.d(TAG, String.format("setLightDimmerLevel(%s, %s)",
271                 resourceInfo.getHost() + resourceInfo.getUri(), String.valueOf(value)));
272
273         // send a msg to OcWorker to put the switch value
274         for(OcAttributeInfo ai : resourceInfo.getAttributes()) {
275             if(ai.getType() == LIGHT_DIMMER) {
276                 ai.setValueInt(value);
277             }
278         }
279         this.mOcWorker.doPutResource(resourceInfo);
280     }
281
282     /**
283      * Sets the Action Bar icon to "progress" (spinning circle), or returns it to refresh icon
284      *
285      * @param refreshing true sets icon to animated "progress" spinner; false to static
286      *                   refresh icon
287      */
288     private void setRefreshActionButtonState(final boolean refreshing) {
289         if (this.optionsMenu != null) {
290             final MenuItem refreshItem
291          = this.optionsMenu
292                     .findItem(R.id.action_refresh);
293             if (refreshItem != null) {
294                 if (refreshing) {
295                     refreshItem.setActionView(R.layout.actionbar_indeterminate_progress);
296                     ProgressBar progressBar =
297                             (ProgressBar) findViewById(R.id.find_resource_progress_bar);
298                     progressBar.setOnClickListener(this);
299
300                 } else {
301                     refreshItem.setActionView(null);
302                 }
303             }
304         }
305     }
306
307     private AlertDialog confirmDiscard()
308     {
309         if (LOCAL_LOGV) Log.v(TAG, "confirmDiscard()");
310
311         return new AlertDialog.Builder(this)
312                 .setTitle("Clear Resource List?")
313                 .setIcon(R.drawable.ic_action_discard_dark)
314                 .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
315                     public void onClick(DialogInterface dialog, int whichButton) {
316                         // clear OcWorker's list
317                         mOcWorker.doClearResources();
318                         // in case its running, hide the indeterminate progress bar
319                         setRefreshActionButtonState(false);
320                         // clear our local data model list
321                         mResourceList.clear();
322                         mResourceListAdapter.notifyDataSetChanged();
323                         dialog.dismiss();
324                     }
325                 })
326
327                 .setNegativeButton("No", new DialogInterface.OnClickListener() {
328                     public void onClick(DialogInterface dialog, int which) {
329                         dialog.dismiss();
330                     }
331                 })
332
333                 .create();
334     }
335
336 }