1 //******************************************************************
3 // Copyright 2014 Intel Corporation.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 package org.iotivity.guiclient;
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;
34 import java.util.ArrayList;
35 import java.util.List;
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;
43 * MainActivity instantiates a ExpandableListView of type ExpandableResourceListView, and
44 * also creates and starts a OcWorker object to handle the IoTivity specific work.
46 * @see org.iotivity.guiclient.OcWorker
47 * @see org.iotivity.guiclient.OcWorkerListener
48 * @see org.iotivity.guiclient.ExpandableResourceListAdapter
50 public class MainActivity
51 extends ActionBarActivity
52 implements OcWorkerListener, View.OnClickListener, ExpandableListView.OnChildClickListener {
54 * Hardcoded TAG... if project never uses proguard then
55 * MyOcClient.class.getName() is the better way.
57 private static final String TAG = "MainActivity";
59 private static final boolean LOCAL_LOGV = true; // set to false to compile out verbose logging
62 * The data structure behind the displayed List of resources and attributes.
64 private List<OcResourceInfo> mResourceList;
67 * The custom adapter for displaying the ResourceListItem List
69 private ExpandableResourceListAdapter mResourceListAdapter;
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.
76 private OcWorker mOcWorker;
79 * Preserve a ref to Action Bar Menu for changing progress icon
81 private Menu optionsMenu;
84 protected void onCreate(Bundle savedInstanceState) {
85 if (LOCAL_LOGV) Log.v(TAG, "onCreate()");
87 super.onCreate(savedInstanceState);
89 setContentView(R.layout.activity_main);
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);
98 // init the Resource display list
99 if(null == this.mResourceList) {
100 this.mResourceList = new ArrayList<>();
103 // init the ListView Adapter
104 if(null == this.mResourceListAdapter) {
105 this.mResourceListAdapter = new ExpandableResourceListAdapter(this.mResourceList,
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);
119 public void onRestoreInstanceState(Bundle savedInstanceState) {
120 if (LOCAL_LOGV) Log.v(TAG, "onRestoreInstanceState()");
124 public void onSaveInstanceState(Bundle outState) {
125 if (LOCAL_LOGV) Log.v(TAG, "onSaveInstanceState()");
129 public void onClick(View v) {
130 if (LOCAL_LOGV) Log.v(TAG, "onClick()");
132 this.setRefreshActionButtonState(false);
136 public boolean onChildClick(ExpandableListView parent,
141 if (LOCAL_LOGV) Log.v(TAG, "onChildClick()");
143 this.mOcWorker.doGetResource(mResourceList.get(groupPosition));
149 public boolean onCreateOptionsMenu(Menu menu) {
150 if (LOCAL_LOGV) Log.v(TAG, "onCreateOptionsMenu()");
152 // save a reference for use in controlling refresh icon later
153 this.optionsMenu = menu;
155 // Inflate the menu; this adds items to the action bar if it is present.
156 getMenuInflater().inflate(R.menu.menu_main, menu);
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();
169 // Handle the "settings" icon/text click
170 if (id == R.id.action_settings) {
174 // Handle the "developer test" icon/text click
175 if (id == R.id.action_test) {
179 // Handle the trash can "discard" icon click
180 if (id == R.id.action_discard) {
181 AlertDialog diaBox = confirmDiscard();
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();
193 return super.onOptionsItemSelected(item);
197 * Handle a resource changed callback from OcWorker by posting a runnable to our
198 * own UI-safe looper/handler
201 public void onResourceChanged(final OcResourceInfo resourceInfo) {
202 if (LOCAL_LOGV) Log.v(TAG, "onResourceChanged()");
204 runOnUiThread(new Runnable() {
207 // in case we were waiting for a refresh, hide the indeterminate progress bar
208 setRefreshActionButtonState(false);
210 mResourceListAdapter.notifyDataSetChanged();
216 * Handle a new resource found callback from OcWorker by posting a runnable to our
217 * own UI-safe looper/handler
220 public void onResourceFound(final OcResourceInfo resourceInfo) {
221 if (LOCAL_LOGV) Log.v(TAG, "onResourceFound()");
223 runOnUiThread(new Runnable() {
226 // in case we were waiting for a refresh, hide the indeterminate progress bar
227 setRefreshActionButtonState(false);
229 // if resource not already in list, add it
230 if(!mResourceList.contains(resourceInfo)) {
231 mResourceList.add(resourceInfo);
234 mResourceListAdapter.notifyDataSetChanged();
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)));
243 // send a msg to OcWorker to put the switch value
244 for(OcAttributeInfo ai : resourceInfo.getAttributes()) {
245 if(ai.getType() == PLATFORM_LED_SWITCH) {
253 this.mOcWorker.doPutResource(resourceInfo);
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)));
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);
266 this.mOcWorker.doPutResource(resourceInfo);
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)));
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);
279 this.mOcWorker.doPutResource(resourceInfo);
283 * Sets the Action Bar icon to "progress" (spinning circle), or returns it to refresh icon
285 * @param refreshing true sets icon to animated "progress" spinner; false to static
288 private void setRefreshActionButtonState(final boolean refreshing) {
289 if (this.optionsMenu != null) {
290 final MenuItem refreshItem
292 .findItem(R.id.action_refresh);
293 if (refreshItem != null) {
295 refreshItem.setActionView(R.layout.actionbar_indeterminate_progress);
296 ProgressBar progressBar =
297 (ProgressBar) findViewById(R.id.find_resource_progress_bar);
298 progressBar.setOnClickListener(this);
301 refreshItem.setActionView(null);
307 private AlertDialog confirmDiscard()
309 if (LOCAL_LOGV) Log.v(TAG, "confirmDiscard()");
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();
327 .setNegativeButton("No", new DialogInterface.OnClickListener() {
328 public void onClick(DialogInterface dialog, int which) {