/** * openHAB, the open Home Automation Bus. * Copyright (C) 2010-2012, openHAB.org <admin@openhab.org> * * See the contributors.txt file in the distribution for a * full listing of individual contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see <http://www.gnu.org/licenses>. * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or * combining it with Eclipse (or a modified version of that library), * containing parts covered by the terms of the Eclipse Public License * (EPL), the licensors of this Program grant you additional permission * to convey the resulting work. */ package org.openhab.habdroid.ui; import android.Manifest; import android.app.AlertDialog; import android.app.PendingIntent; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.net.Uri; import android.nfc.NfcAdapter; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; import android.provider.Settings; import android.speech.RecognizerIntent; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.widget.DrawerLayout; import android.text.TextUtils; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.ListView; import android.widget.Toast; import com.google.analytics.tracking.android.EasyTracker; import com.google.android.gms.gcm.GoogleCloudMessaging; import com.loopj.android.http.AsyncHttpResponseHandler; import com.loopj.android.image.WebImageCache; import org.apache.http.client.HttpResponseException; import org.apache.http.entity.StringEntity; import org.openhab.domain.IDocumentFactory; import org.openhab.domain.model.OpenHABLinkedPage; import org.openhab.domain.model.OpenHABSitemap; import org.openhab.habclient.HABApplication; import org.openhab.habclient.HABService; import org.openhab.habclient.INavDrawerActivity; import org.openhab.habclient.IOpenHABSetting; import org.openhab.habclient.MainActivity; import org.openhab.habclient.dagger.DaggerMainActivityComponent; import org.openhab.habdroid.BuildConfig; import org.openhab.habdroid.R; import org.openhab.habdroid.core.DocumentHttpResponseHandler; import org.openhab.habdroid.core.NotificationDeletedBroadcastReceiver; import org.openhab.habdroid.core.OpenHABTracker; import org.openhab.habdroid.core.OpenHABTrackerReceiver; import org.openhab.habdroid.ui.drawer.OpenHABDrawerAdapter; import org.openhab.habdroid.util.MyAsyncHttpClient; import org.openhab.habdroid.util.Util; import org.w3c.dom.Document; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import de.duenndns.ssl.MTMDecision; import de.duenndns.ssl.MemorizingResponder; import de.duenndns.ssl.MemorizingTrustManager; public class OpenHABMainActivity extends FragmentActivity implements OnWidgetSelectedListener, INavDrawerActivity, OpenHABTrackerReceiver, MemorizingResponder { // Logging TAG private static final String TAG = "OpenHABMainActivity"; // Activities request codes private static final int VOICE_RECOGNITION_REQUEST_CODE = 1001; private static final int SETTINGS_REQUEST_CODE = 1002; private static final int WRITE_NFC_TAG_REQUEST_CODE = 1003; private static final int INFO_REQUEST_CODE = 1004; public static final String GCM_SENDER_ID = "737820980945"; // Base URL of current openHAB connection private String openHABBaseUrl = "https://demo.openhab.org:8443/"; // openHAB username private String openHABUsername = ""; // openHAB password private String openHABPassword = ""; // openHAB Bonjour service name private String openHABServiceType; // view pager for widgetlist fragments private OpenHABViewPager pager; // view pager adapter for widgetlist fragments private OpenHABFragmentPagerAdapter pagerAdapter; // root URL of the current sitemap private String sitemapRootUrl; // A fragment which retains it's state through configuration changes to keep the current state of the app private StateRetainFragment stateFragment; // Enable/disable development mode private boolean isDeveloper; // preferences private SharedPreferences mSettings; // OpenHAB tracker private OpenHABTracker mOpenHABTracker; // Progress dialog private ProgressDialog mProgressDialog; // If Voice Recognition is enabled private boolean mVoiceRecognitionEnabled = false; // If openHAB discovery is enabled private boolean mServiceDiscoveryEnabled = true; // Loopj private static MyAsyncHttpClient mAsyncHttpClient; // NFC Launch data private String mNfcData; // Pending NFC page private String mPendingNfcPage; // Drawer Layout private DrawerLayout mDrawerLayout; // Drawer Toggler private ActionBarDrawerToggle mDrawerToggle; // GCM Registration expiration public static final long REGISTRATION_EXPIRY_TIME_MS = 1000 * 3600 * 24 * 7; // Google Cloud Messaging private GoogleCloudMessaging mGcm; private OpenHABDrawerAdapter mDrawerAdapter; private String[] mDrawerTitles = {"First floor", "Seconf floor", "Cellar", "Garage"}; private ListView mDrawerList; private List<OpenHABSitemap> mSitemapList; private List<OpenHABSitemap> mNavDrawerItemList; @Inject IOpenHABSetting mOpenHABSetting; @Inject IDocumentFactory mDocumentFactory; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); DaggerMainActivityComponent.builder() .appComponent(((HABApplication)getApplication()).appComponent()) .build() .inject(this); Log.d(TAG, "onCreate()"); // Check if we are in development mode isDeveloper = BuildConfig.DEBUG; startService(new Intent(this, HABService.class)); //startService(new Intent(this, SpeechService.class));//TODO - Temporary disabled // Set default values, false means do it one time during the very first launch PreferenceManager.setDefaultValues(this, R.xml.preferences, false); // Set non-persistent HABDroid version preference to current version from application package try { PreferenceManager.getDefaultSharedPreferences(this).edit().putString("default_openhab_appversion", getPackageManager().getPackageInfo(getPackageName(), 0).versionName).commit(); } catch (PackageManager.NameNotFoundException e1) { Log.d(TAG, e1.getMessage()); } checkDiscoveryPermissions(); checkVoiceRecognition(); // Set the theme to one from preferences Util.setActivityTheme(this); mSettings = PreferenceManager.getDefaultSharedPreferences(this); // Disable screen timeout if set in preferences if (mSettings.getBoolean("default_openhab_screentimeroff", false)) { getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } // Fetch openHAB service type name from strings.xml openHABServiceType = getString(R.string.openhab_service_type); // Get username/password from preferences openHABUsername = mSettings.getString("default_openhab_username", null); openHABPassword = mSettings.getString("default_openhab_password", null); mAsyncHttpClient = new MyAsyncHttpClient(this); mAsyncHttpClient.setBasicAuth(openHABUsername, openHABPassword); mAsyncHttpClient.addHeader("Accept", "application/xml"); mAsyncHttpClient.setTimeout(30000); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); requestWindowFeature(Window.FEATURE_PROGRESS); setProgressBarIndeterminateVisibility(true); setContentView(R.layout.activity_main); gcmRegisterBackground(); setUpPager(); if (savedInstanceState != null) { openHABBaseUrl = savedInstanceState.getString("openHABBaseUrl"); mOpenHABSetting.setBaseUrl(openHABBaseUrl); sitemapRootUrl = savedInstanceState.getString("sitemapRootUrl"); mOpenHABSetting.setSitemapRootUrl(sitemapRootUrl); } setUpDrawer(); MemorizingTrustManager.setResponder(this); getActionBar().setDisplayHomeAsUpEnabled(true); getActionBar().setHomeButtonEnabled(true); final Intent intent = getIntent(); if (getIntent() == null) { Log.d(TAG, "Intent == null"); return; } if ("org.openhab.notification.selected".equals(intent.getAction())) { onNotificationSelected(getIntent()); } mNfcData = getNfcDataFromIntent(intent); } private String getNfcDataFromIntent(Intent intent) { final String action = intent.getAction(); if ("android.nfc.action.NDEF_DISCOVERED".equals(action)) { Log.d(TAG, "This is NFC action"); final String dataString = intent.getDataString(); if (dataString == null) { return null; } Log.d(TAG, "NFC data = " + dataString); return dataString; } else if("SHOW_PAGE_AS_LIST".equalsIgnoreCase(action) && intent.getStringExtra("pageUrl") != null) { return intent.getStringExtra("pageUrl"); } return null; } private void setUpPager() { pager = (OpenHABViewPager)findViewById(R.id.pager); pager.setScrollDurationFactor(2.5); pager.setOffscreenPageLimit(1); pagerAdapter = new OpenHABFragmentPagerAdapter(getSupportFragmentManager()); pagerAdapter.setColumnsNumber(getResources().getInteger(R.integer.pager_columns)); pagerAdapter.setOpenHABUsername(openHABUsername); pagerAdapter.setOpenHABPassword(openHABPassword); pager.setAdapter(pagerAdapter); pager.setOnPageChangeListener(pagerAdapter); } private void setUpDrawer() { // Check if we have openHAB page url in saved instance state? mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerList = (ListView) findViewById(R.id.left_drawer); mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_navigation_drawer, R.string.app_name, R.string.app_name) { public void onDrawerClosed(View view) { Log.d(TAG, "onDrawerClosed"); } public void onDrawerOpened(View drawerView) { Log.d(TAG, "onDrawerOpened"); } }; mDrawerLayout.setDrawerListener(mDrawerToggle); mOpenHABSetting.setBaseUrl(openHABBaseUrl); mSitemapList = new ArrayList<OpenHABSitemap>(); mNavDrawerItemList = new ArrayList<OpenHABSitemap>(); mDrawerAdapter = new OpenHABDrawerAdapter(this, R.layout.openhabdrawer_item, mNavDrawerItemList, mOpenHABSetting); mOpenHABSetting.setUsername(openHABUsername); mOpenHABSetting.setPassword(openHABPassword); mOpenHABSetting.setBaseUrl(openHABBaseUrl);//Added by TA mDrawerList.setAdapter(mDrawerAdapter); mDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { Log.d(TAG, "Drawer selected item " + String.valueOf(position)); final OpenHABSitemap sitemap = (OpenHABSitemap) adapterView.getItemAtPosition(position); Log.d(TAG, "This is sitemap " + sitemap.getLink()); getDrawerLayout().closeDrawers(); openSitemap(sitemap.getHomepageLink()); } }); // mDrawerList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mDrawerTitles)); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Sync the toggle state after onRestoreInstanceState has occurred. mDrawerToggle.syncState(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mDrawerToggle.onConfigurationChanged(newConfig); } @Override public void onResume() { Log.d(TAG, "onResume()"); super.onResume(); PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, new Intent(this, OpenHABMainActivity.class).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); if (NfcAdapter.getDefaultAdapter(this) != null) NfcAdapter.getDefaultAdapter(this).enableForegroundDispatch(this, pendingIntent, null, null); if (!TextUtils.isEmpty(mNfcData)) { Log.d(TAG, "We have NFC data from launch"); } pagerAdapter.setColumnsNumber(getResources().getInteger(R.integer.pager_columns)); FragmentManager fm = getSupportFragmentManager(); stateFragment = (StateRetainFragment)fm.findFragmentByTag("stateFragment"); if (stateFragment == null) { stateFragment = new StateRetainFragment(); fm.beginTransaction().add(stateFragment, "stateFragment").commit(); mOpenHABTracker = new OpenHABTracker(this, openHABServiceType, mServiceDiscoveryEnabled); mOpenHABTracker.start(); } else { Log.d(TAG, "State fragment found"); pagerAdapter.setFragmentList(stateFragment.getFragmentList()); Log.d(TAG, String.format("Loaded %d fragments", stateFragment.getFragmentList().size())); pager.setCurrentItem(stateFragment.getCurrentPage()); Log.d(TAG, String.format("Loaded current page = %d", stateFragment.getCurrentPage())); } if (!TextUtils.isEmpty(mPendingNfcPage)) { openNFCPageIfPending(); } } public void openNFCPageIfPending() { int possiblePosition = pagerAdapter.getPositionByUrl(mPendingNfcPage); // If yes, then just switch to this page if (possiblePosition >= 0) { pager.setCurrentItem(possiblePosition); // If not, then open this page as new one } else { pagerAdapter.openPage(mPendingNfcPage); pager.setCurrentItem(pagerAdapter.getCount()-1); } mPendingNfcPage = null; } public void onOpenHABTracked(String baseUrl, String message) { if (message != null) Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); openHABBaseUrl = baseUrl; mOpenHABSetting.setBaseUrl(openHABBaseUrl); pagerAdapter.setOpenHABBaseUrl(openHABBaseUrl); if (!TextUtils.isEmpty(mNfcData)) { onNfcTag(mNfcData); openNFCPageIfPending(); } else { selectSitemap(baseUrl, false); } } public void onError(String error) { Toast.makeText(getApplicationContext(), error, Toast.LENGTH_LONG).show(); } public void onBonjourDiscoveryStarted() { mProgressDialog = ProgressDialog.show(this, "", getString(R.string.info_discovery), true); } public void onBonjourDiscoveryFinished() { mProgressDialog.dismiss(); } /** * Get sitemaps from openHAB, if user already configured preffered sitemap * just open it. If no preffered sitemap is configured - let user select one. * * @param baseUrl an absolute base URL of openHAB to open * @return void */ private void selectSitemap(final String baseUrl, final boolean forceSelect) { String restURL = baseUrl + "rest/sitemaps"; Log.d(TAG, "[AsyncHttpClient] GET Request from: " + restURL); startProgressIndicator(); mAsyncHttpClient.get(restURL, new DocumentHttpResponseHandler(mDocumentFactory) { @Override public void onSuccess(Document document) { stopProgressIndicator(); Log.d(TAG, "[AsyncHttpClient] Response: " + document.toString()); //Remove all sitemap items in navigator drawer. for (OpenHABSitemap aMSitemapList : mSitemapList) { mNavDrawerItemList.remove(aMSitemapList); } mSitemapList.clear(); mSitemapList.addAll(Util.parseSitemapList(document)); if (mSitemapList.size() == 0) { // Got an empty sitemap list! Log.e(TAG, "[AsyncHttpClient] openHAB returned empty sitemap list"); showAlertDialog(getString(R.string.error_empty_sitemap_list)); return; } mDrawerAdapter.notifyDataSetChanged(); // If we are forced to do selection, just open selection dialog if (forceSelect) { showSitemapSelectionDialog(mSitemapList); } else { // Check if we have a sitemap configured to use SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(OpenHABMainActivity.this); String configuredSitemap = settings.getString("default_openhab_sitemap", ""); // If we have sitemap configured if (configuredSitemap.length() > 0) { // Configured sitemap is on the list we got, open it! if (Util.sitemapExists(mSitemapList, configuredSitemap)) { Log.d(TAG, "Configured sitemap is on the list"); OpenHABSitemap selectedSitemap = Util.getSitemapByName(mSitemapList, configuredSitemap); openSitemap(selectedSitemap.getHomepageLink()); // Configured sitemap is not on the list we got! } else { Log.d(TAG, "Configured sitemap is not on the list"); if (mSitemapList.size() == 1) { Log.d(TAG, "Got only one sitemap"); SharedPreferences.Editor preferencesEditor = settings.edit(); preferencesEditor.putString("default_openhab_sitemap", mSitemapList.get(0).getName()); preferencesEditor.commit(); openSitemap(mSitemapList.get(0).getHomepageLink()); } else { Log.d(TAG, "Got multiply sitemaps, user have to select one"); showSitemapSelectionDialog(mSitemapList); } } // No sitemap is configured to use } else { // We got only one single sitemap from openHAB, use it if (mSitemapList.size() == 1) { Log.d(TAG, "Got only one sitemap"); SharedPreferences.Editor preferencesEditor = settings.edit(); preferencesEditor.putString("default_openhab_sitemap", mSitemapList.get(0).getName()); preferencesEditor.commit(); openSitemap(mSitemapList.get(0).getHomepageLink()); } else { Log.d(TAG, "Got multiply sitemaps, user have to select one"); showSitemapSelectionDialog(mSitemapList); } } } } @Override public void onFailure(Throwable error, String content) { stopProgressIndicator(); if (error instanceof HttpResponseException) { switch (((HttpResponseException) error).getStatusCode()) { case 401: showAlertDialog(getString(R.string.error_authentication_failed)); break; default: Log.e(TAG, String.format("Http code = %d", ((HttpResponseException) error).getStatusCode())); break; } } else if (error instanceof org.apache.http.conn.HttpHostConnectException) { Log.e(TAG, "Error connecting to host"); if (error.getMessage() != null) { Log.e(TAG, error.getMessage()); showAlertDialog(error.getMessage()); } else { showAlertDialog(getString(R.string.error_connection_failed)); } } else if (error instanceof java.net.UnknownHostException) { Log.e(TAG, "Unable to resolve hostname"); if (error.getMessage() != null) { Log.e(TAG, error.getMessage()); showAlertDialog(error.getMessage()); } else { showAlertDialog(getString(R.string.error_connection_failed)); } } else { Log.e(TAG, error.getClass().toString()); } } }); } private void showSitemapSelectionDialog(final List<OpenHABSitemap> sitemapList) { Log.d(TAG, "Opening sitemap selection dialog"); final List<String> sitemapNameList = new ArrayList<String>();; for (int i=0; i<sitemapList.size(); i++) { sitemapNameList.add(sitemapList.get(i).getName()); } AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(OpenHABMainActivity.this); dialogBuilder.setTitle(getString(R.string.mainmenu_openhab_selectsitemap)); try { dialogBuilder.setItems(sitemapNameList.toArray(new CharSequence[sitemapNameList.size()]), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { Log.d(TAG, "Selected sitemap " + sitemapNameList.get(item)); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(OpenHABMainActivity.this); SharedPreferences.Editor preferencesEditor = settings.edit(); preferencesEditor.putString("default_openhab_sitemap", sitemapList.get(item).getName()); preferencesEditor.commit(); openSitemap(sitemapList.get(item).getHomepageLink()); } }).show(); } catch (WindowManager.BadTokenException e) { Log.e(TAG, "Error while showing sitemap.", e); // Crittercism.logHandledException(e); } } public void openSitemap(String sitemapUrl) { Log.i(TAG, "Opening sitemap at " + sitemapUrl); sitemapRootUrl = sitemapUrl; mOpenHABSetting.setSitemapRootUrl(sitemapRootUrl); pagerAdapter.clearFragmentList(); pagerAdapter.openPage(sitemapRootUrl); pager.setCurrentItem(0); } public DrawerLayout getDrawerLayout() { return mDrawerLayout; } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_menu, menu); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { menu.findItem(R.id.mainmenu_voice_recognition).setVisible(mVoiceRecognitionEnabled); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.mainmenu_openhab_preferences: Intent settingsIntent = new Intent(this.getApplicationContext(), OpenHABPreferencesActivity.class); startActivityForResult(settingsIntent, SETTINGS_REQUEST_CODE); Util.overridePendingTransition(this, false); return true; case R.id.mainmenu_openhab_selectsitemap: SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(OpenHABMainActivity.this); SharedPreferences.Editor preferencesEditor = settings.edit(); preferencesEditor.putString("default_openhab_sitemap", ""); preferencesEditor.commit(); selectSitemap(openHABBaseUrl, true); return true; case android.R.id.home: Log.d(TAG, "Home selected"); if (pager.getCurrentItem() > 0) { pager.setCurrentItem(0); } return true; case R.id.mainmenu_openhab_clearcache: Log.d(TAG, "Restarting"); // Get launch intent for application Intent restartIntent = getBaseContext().getPackageManager() .getLaunchIntentForPackage( getBaseContext().getPackageName() ); restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // Finish current activity finish(); WebImageCache cache = new WebImageCache(getBaseContext()); cache.clear(); // Start launch activity startActivity(restartIntent); // Start launch activity return true; case R.id.mainmenu_openhab_writetag: Intent writeTagIntent = new Intent(this.getApplicationContext(), OpenHABWriteTagActivity.class); // TODO: get current display page url, which? how? :-/ OpenHABWidgetListFragment currentFragment = pagerAdapter.getFragment(pager.getCurrentItem()); writeTagIntent.putExtra("sitemapPage", currentFragment.getDisplayPageUrl()); startActivityForResult(writeTagIntent, WRITE_NFC_TAG_REQUEST_CODE); Util.overridePendingTransition(this, false); return true; case R.id.mainmenu_openhab_info: Intent infoIntent = new Intent(this.getApplicationContext(), OpenHABInfoActivity.class); infoIntent.putExtra("openHABBaseUrl", openHABBaseUrl); infoIntent.putExtra("username", openHABUsername); infoIntent.putExtra("password", openHABPassword); startActivityForResult(infoIntent, INFO_REQUEST_CODE); Util.overridePendingTransition(this, false); return true; case R.id.mainmenu_voice_recognition: launchVoiceRecognition(); return true; case R.id.mainmenu_openhab_flipper: this.startActivity(new Intent(this, MainActivity.class)); return true; default: return super.onOptionsItemSelected(item); } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { Log.d(TAG, String.format("onActivityResult requestCode = %d, resultCode = %d", requestCode, resultCode)); switch (requestCode) { case SETTINGS_REQUEST_CODE: // Restart app after preferences Log.d(TAG, "Restarting after settings"); // Get launch intent for application Intent restartIntent = getBaseContext().getPackageManager() .getLaunchIntentForPackage( getBaseContext().getPackageName() ); restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // Finish current activity finish(); // Start launch activity startActivity(restartIntent); break; case WRITE_NFC_TAG_REQUEST_CODE: Log.d(TAG, "Got back from Write NFC tag"); break; case VOICE_RECOGNITION_REQUEST_CODE: Log.d(TAG, "Got back from Voice recognition"); setProgressBarIndeterminateVisibility(false); if(resultCode == RESULT_OK) { ArrayList<String> textMatchList = data .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); if (!textMatchList.isEmpty()) { Log.d(TAG, textMatchList.get(0)); Log.d(TAG, "Recognized text: " + textMatchList.get(0)); Toast.makeText(this, "I recognized: " + textMatchList.get(0), Toast.LENGTH_LONG).show(); sendItemCommand("VoiceCommand", textMatchList.get(0)); } else { Log.d(TAG, "Voice recognition returned empty set"); Toast.makeText(this, "I can't read you!", Toast.LENGTH_LONG).show(); } } else { Log.d(TAG, "A voice recognition error occured"); Toast.makeText(this, "A voice recognition error occured", Toast.LENGTH_LONG).show(); } break; default: } } @Override public void onSaveInstanceState(Bundle savedInstanceState) { Log.d(TAG, "onSaveInstanceState"); // Save UI state changes to the savedInstanceState. // This bundle will be passed to onCreate if the process is // killed and restarted. savedInstanceState.putString("openHABBaseUrl", openHABBaseUrl); savedInstanceState.putString("sitemapRootUrl", sitemapRootUrl); savedInstanceState.putInt("currentFragment", pager.getCurrentItem()); super.onSaveInstanceState(savedInstanceState); } /** * Overriding onStart to enable Google Analytics stats collection */ @Override public void onStart() { super.onStart(); // Start activity tracking via Google Analytics if (!BuildConfig.DEBUG) EasyTracker.getInstance().activityStart(this); } /** * Overriding onStop to enable Google Analytics stats collection */ @Override public void onStop() { Log.d(TAG, "onStop()"); super.onStop(); // Stop activity tracking via Google Analytics if (!isDeveloper) EasyTracker.getInstance().activityStop(this); if (mOpenHABTracker != null) mOpenHABTracker.stop(); } @Override public void onPause() { Log.d(TAG, "onPause()"); super.onPause(); Log.d(TAG, String.format("Saving %d fragments", pagerAdapter.getFragmentList().size())); Log.d(TAG, String.format("Saving current page = %d", pager.getCurrentItem())); stateFragment.setFragmentList(pagerAdapter.getFragmentList()); stateFragment.setCurrentPage(pager.getCurrentItem()); // Runnable can = new Runnable() { // public void run() { // mAsyncHttpClient.cancelRequests(OpenHABMainActivity.this, true); // } // }; // new Thread(can).start(); } /** * This method is called when activity receives a new intent while running */ @Override public void onNewIntent(Intent newIntent) { if (newIntent.getAction() != null) { Log.d(TAG, "New intent received = " + newIntent.getAction()); if (newIntent.getAction().equals("android.nfc.action.NDEF_DISCOVERED")) { Log.d(TAG, "This is NFC action"); if (newIntent.getDataString() != null) { Log.d(TAG, "Action data = " + newIntent.getDataString()); onNfcTag(newIntent.getDataString()); } } else if (newIntent.getAction().equals("org.openhab.notification.selected")) { onNotificationSelected(newIntent); } } } private void onNotificationSelected(Intent intent) { Log.d(TAG, "Notification was selected"); if (intent.hasExtra("notificationId")) { Log.d(TAG, String.format("Notification id = %d", intent.getExtras().getInt("notificationId"))); // Make a fake broadcast intent to hide intent on other devices Intent deleteIntent = new Intent(this, NotificationDeletedBroadcastReceiver.class); deleteIntent.setAction("org.openhab.notification.deleted"); deleteIntent.putExtra("notificationId", intent.getExtras().getInt("notificationId")); sendBroadcast(deleteIntent); } } /** * This method processes new intents generated by NFC subsystem * @param nfcData - a data which NFC subsystem got from the NFC tag */ public void onNfcTag(String nfcData) { Log.d(TAG, "onNfcTag()"); Uri openHABURI = Uri.parse(nfcData); Log.d(TAG, "NFC Scheme = " + openHABURI.getScheme()); Log.d(TAG, "NFC Host = " + openHABURI.getHost()); Log.d(TAG, "NFC Path = " + openHABURI.getPath()); String nfcItem = openHABURI.getQueryParameter("item"); String nfcCommand = openHABURI.getQueryParameter("command"); String nfcItemType = openHABURI.getQueryParameter("itemType"); // If there is no item parameter it means tag contains only sitemap page url if (TextUtils.isEmpty(nfcItem)) { // Form the new sitemap page url String newPageUrl = openHABBaseUrl + "rest/sitemaps" + openHABURI.getPath(); // Check if we have this page in stack? mPendingNfcPage = newPageUrl; Log.d(TAG, "[NFC] This is a sitemap tag without parameters:\nmPendingNfcPage = " + newPageUrl); } else { Log.d(TAG, "Target item = " + nfcItem); sendItemCommand(nfcItem, nfcCommand); // if mNfcData is not empty, this means we were launched with NFC touch // and thus need to autoexit after an item action if (!TextUtils.isEmpty(mNfcData)) finish(); } mNfcData = ""; } public void sendItemCommand(String itemName, String command) { try { StringEntity se = new StringEntity(command); String restURL = openHABBaseUrl + "rest/items/" + itemName; Log.d(TAG, "[AsyncHttpClient] POST Request for: " + restURL); mAsyncHttpClient.post(this, restURL, se, "text/plain", new AsyncHttpResponseHandler() { @Override public void onSuccess(String response) { Log.d(TAG, "Command was sent successfully"); } @Override public void onFailure(Throwable error, String errorResponse) { Log.e(TAG, "Got command error " + error.getMessage()); if (errorResponse != null) Log.e(TAG, "Error response = " + errorResponse); } }); } catch (UnsupportedEncodingException e) { if (e.getMessage() != null) Log.e(TAG, e.getMessage()); } } public void onWidgetSelectedListener(OpenHABLinkedPage linkedPage, OpenHABWidgetListFragment source) { Log.i(TAG, "onWidgetSelectedListener() Got widget link = " + linkedPage.getLink()); Log.i(TAG, " " + String.format("Link came from fragment on position %d", source.getPosition())); pagerAdapter.openPage(linkedPage.getLink(), source.getPosition() + 1); pager.setCurrentItem(pagerAdapter.getCount()-1); setTitle(linkedPage.getTitle()); } @Override public void onBackPressed() { Log.d(TAG, String.format("onBackPressed() I'm at the %d page", pager.getCurrentItem())); if (pager.getCurrentItem() == 0) { super.onBackPressed(); } else { pager.setCurrentItem(pager.getCurrentItem() - 1, true); setTitle(pagerAdapter.getPageTitle(pager.getCurrentItem())); } } public void startProgressIndicator() { setProgressBarIndeterminateVisibility(true); } public void stopProgressIndicator() { setProgressBarIndeterminateVisibility(false); } private void launchVoiceRecognition() { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); // Specify the calling package to identify your application intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, OpenHABMainActivity.class.getPackage().getName()); // Display an hint to the user about what he should say. intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "openHAB, at your command!"); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1); startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE); } private void showAlertDialog(String alertMessage) { AlertDialog.Builder builder = new AlertDialog.Builder(OpenHABMainActivity.this); builder.setMessage(alertMessage) .setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { } }); AlertDialog alert = builder.create(); alert.show(); } private void showCertificateDialog(final int decisionId, String certMessage) { AlertDialog.Builder builder = new AlertDialog.Builder(OpenHABMainActivity.this); builder.setMessage(certMessage) .setTitle(R.string.mtm_accept_cert); builder.setPositiveButton(R.string.mtm_decision_always, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int i) { Log.d(TAG, "User decided to always accept unknown certificate"); // MemorizingTrustManager.interactResult(decisionId, MTMDecision.DECISION_ALWAYS); sendMTMDecision(decisionId, MTMDecision.DECISION_ALWAYS); } }); builder.setNeutralButton(R.string.mtm_decision_once, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int i) { Log.d(TAG, "User decided to accept unknown certificate once"); // MemorizingTrustManager.interactResult(decisionId, MTMDecision.DECISION_ONCE); sendMTMDecision(decisionId, MTMDecision.DECISION_ONCE); } }); builder.setNegativeButton(R.string.mtm_decision_abort, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int i) { Log.d(TAG, "User decided to abort unknown certificate"); // MemorizingTrustManager.interactResult(decisionId, MTMDecision.DECISION_ABORT); sendMTMDecision(decisionId, MTMDecision.DECISION_ABORT); } }); AlertDialog certAlert = builder.create(); certAlert.show(); } void sendMTMDecision(int decisionId, int decision) { Log.d(TAG, "Sending decision to MTM"); Intent i = new Intent(MemorizingTrustManager.DECISION_INTENT + "/" + getPackageName()); i.putExtra(MemorizingTrustManager.DECISION_INTENT_ID, decisionId); i.putExtra(MemorizingTrustManager.DECISION_INTENT_CHOICE, decision); sendBroadcast(i); } public void checkVoiceRecognition() { // Check if voice recognition is present PackageManager pm = getPackageManager(); List<ResolveInfo> activities = pm.queryIntentActivities(new Intent( RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0); if (activities.size() == 0) { // speakButton.setEnabled(false); // speakButton.setText("Voice recognizer not present"); Toast.makeText(this, "Voice recognizer not present, voice recognition disabled", Toast.LENGTH_SHORT).show(); } else { mVoiceRecognitionEnabled = true; } } public void checkDiscoveryPermissions() { // Check if we got all needed permissions PackageManager pm = getPackageManager(); if (!(pm.checkPermission(Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, getPackageName()) == PackageManager.PERMISSION_GRANTED)) { showAlertDialog(getString(R.string.erorr_no_wifi_mcast_permission)); mServiceDiscoveryEnabled = false; } if (!(pm.checkPermission(Manifest.permission.ACCESS_WIFI_STATE, getPackageName()) == PackageManager.PERMISSION_GRANTED)) { showAlertDialog(getString(R.string.erorr_no_wifi_state_permission)); mServiceDiscoveryEnabled = false; } } public void makeDecision(int decisionId, String certMessage) { Log.d(TAG, String.format("MTM is asking for decision on id = %d", decisionId)); if (mSettings.getBoolean("default_openhab_sslcert", false)) MemorizingTrustManager.interactResult(decisionId, MTMDecision.DECISION_ONCE); else showCertificateDialog(decisionId, certMessage); } public String getOpenHABBaseUrl() { return openHABBaseUrl; } public void setOpenHABBaseUrl(String openHABBaseUrl) { this.openHABBaseUrl = openHABBaseUrl; mOpenHABSetting.setBaseUrl(openHABBaseUrl); } public String getOpenHABUsername() { return openHABUsername; } public void setOpenHABUsername(String openHABUsername) { this.openHABUsername = openHABUsername; } public String getOpenHABPassword() { return openHABPassword; } public void setOpenHABPassword(String openHABPassword) { this.openHABPassword = openHABPassword; } public static MyAsyncHttpClient getAsyncHttpClient() { return mAsyncHttpClient; } private void gcmRegisterBackground() { // We need settings if (mSettings == null) return; // We need remote URL String remoteUrl = mSettings.getString("default_openhab_alturl", null); if (TextUtils.isEmpty(remoteUrl)) return; // We need it to be my.oh if (!remoteUrl.toLowerCase().startsWith("https://my.openhab.org")) return; // Finally, all sanity is done if (mGcm == null) mGcm = GoogleCloudMessaging.getInstance(getApplicationContext()); Log.d(TAG, "[AsyncHttpClient] Creating new GCM AsyncTask<...>"); new AsyncTask<Void, Void, String>() { @Override protected String doInBackground(Void... params) { String regId = null; try { regId = mGcm.register(GCM_SENDER_ID); String deviceModel = URLEncoder.encode(Build.MODEL, "UTF-8"); String deviceId = Settings.Secure.getString(getContentResolver(),Settings.Secure.ANDROID_ID); String regUrl = "https://my.openhab.org/addAndroidRegistration?deviceId=" + deviceId + "&deviceModel=" + deviceModel + "®Id=" + regId; Log.d(TAG, "[AsyncHttpClient] GET Request for: " + regUrl); mAsyncHttpClient.get(getApplicationContext(), regUrl, new AsyncHttpResponseHandler() { @Override public void onSuccess(String response) { Log.d(TAG, "[AsyncHttpClient] GCM reg id success"); } @Override public void onFailure(Throwable error, String errorResponse) { Log.e(TAG, "[AsyncHttpClient] GCM reg id error: " + error.getMessage()); if (errorResponse != null) Log.e(TAG, "[AsyncHttpClient] Error response = " + errorResponse); } }); } catch (IOException e) { e.printStackTrace(); Log.e(TAG, e.getMessage()); } return regId; } @Override protected void onPostExecute(String regId) { } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,null, null, null); } }