Java tutorial
/* * Copyright 2015 MbientLab Inc. All rights reserved. * * IMPORTANT: Your use of this Software is limited to those specific rights * granted under the terms of a software license agreement between the user who * downloaded the software, his/her employer (which must be your employer) and * MbientLab Inc, (the "License"). You may not use this Software unless you * agree to abide by the terms of the License which can be found at * www.mbientlab.com/terms . The License limits your use, and you acknowledge, * that the Software may not be modified, copied or distributed and can be used * solely and exclusively in conjunction with a MbientLab Inc, product. Other * than for the foregoing purpose, you may not use, reproduce, copy, prepare * derivative works of, modify, distribute, perform, display or sell this * Software and/or its documentation for any purpose. * * YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE * PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, * NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL * MBIENTLAB OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE, * STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE * THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED * TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST * PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, * SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY * DEFENSE THEREOF), OR OTHER SIMILAR COSTS. * * Should you have any questions regarding your right to use this Software, * contact MbientLab Inc, at www.mbientlab.com. */ package com.mbientlab.metawear.app; import android.app.Dialog; import android.app.ProgressDialog; import android.bluetooth.BluetoothDevice; import android.content.ComponentName; import android.content.DialogInterface; import android.content.Intent; import android.content.ServiceConnection; import android.os.Handler; import android.os.IBinder; import android.support.annotation.NonNull; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.support.v7.app.ActionBar; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.support.v4.widget.DrawerLayout; import android.widget.Toast; import com.mbientlab.metawear.MetaWearBleService; import com.mbientlab.metawear.MetaWearBoard; import com.mbientlab.metawear.MetaWearBoard.ConnectionStateHandler; import com.mbientlab.metawear.UnsupportedModuleException; import com.mbientlab.metawear.module.Debug; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public class NavigationActivity extends AppCompatActivity implements NavigationDrawerFragment.NavigationDrawerCallbacks, SensorFragment.FragmentBus, ServiceConnection { public static final String EXTRA_BT_DEVICE = "com.mbientlab.metawear.app.NavigationActivity.EXTRA_BT_DEVICE"; private static final Map<String, Class<? extends ModuleFragmentBase>> FRAGMENT_CLASSES; private static final List<String> FRAGMENT_TAGS; static { Map<String, Class<? extends ModuleFragmentBase>> tempMap = new LinkedHashMap<>(); tempMap.put("Home", HomeFragment.class); tempMap.put("Accelerometer", AccelerometerFragment.class); tempMap.put("Barometer", BarometerFragment.class); tempMap.put("Gpio", GpioFragment.class); tempMap.put("Gyro", GyroFragment.class); tempMap.put("Haptic", HapticFragment.class); tempMap.put("IBeacon", IBeaconFragment.class); tempMap.put("Light", AmbientLightFragment.class); tempMap.put("NeoPixel", NeoPixelFragment.class); tempMap.put("Settings", SettingsFragment.class); tempMap.put("Temperature", TemperatureFragment.class); FRAGMENT_CLASSES = Collections.unmodifiableMap(tempMap); FRAGMENT_TAGS = Collections.unmodifiableList(new ArrayList<>(tempMap.keySet())); } public static class ReconnectDialogFragment extends DialogFragment implements ServiceConnection { private static final String KEY_BLUETOOTH_DEVICE = "com.mbientlab.metawear.app.NavigationActivity.ReconnectDialogFragment.KEY_BLUETOOTH_DEVICE"; private ProgressDialog reconnectDialog = null; private BluetoothDevice btDevice = null; private MetaWearBoard currentMwBoard = null; public static ReconnectDialogFragment newInstance(BluetoothDevice btDevice) { Bundle args = new Bundle(); args.putParcelable(KEY_BLUETOOTH_DEVICE, btDevice); ReconnectDialogFragment newFragment = new ReconnectDialogFragment(); newFragment.setArguments(args); return newFragment; } @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { btDevice = getArguments().getParcelable(KEY_BLUETOOTH_DEVICE); getActivity().getApplicationContext().bindService(new Intent(getActivity(), MetaWearBleService.class), this, BIND_AUTO_CREATE); reconnectDialog = new ProgressDialog(getActivity()); reconnectDialog.setTitle(getString(R.string.title_reconnect_attempt)); reconnectDialog.setMessage(getString(R.string.message_wait)); reconnectDialog.setCancelable(false); reconnectDialog.setCanceledOnTouchOutside(false); reconnectDialog.setIndeterminate(true); reconnectDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.label_cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { currentMwBoard.disconnect(); getActivity().finish(); } }); return reconnectDialog; } @Override public void onServiceConnected(ComponentName name, IBinder service) { currentMwBoard = ((MetaWearBleService.LocalBinder) service).getMetaWearBoard(btDevice); } @Override public void onServiceDisconnected(ComponentName name) { } } private final String RECONNECT_DIALOG_TAG = "reconnect_dialog_tag"; private final Handler connectScheduler = new Handler(); private final ConnectionStateHandler connectionHandler = new MetaWearBoard.ConnectionStateHandler() { @Override public void connected() { ((DialogFragment) getSupportFragmentManager().findFragmentByTag(RECONNECT_DIALOG_TAG)).dismiss(); ((ModuleFragmentBase) currentFragment).reconnected(); } @Override public void disconnected() { attemptReconnect(); } @Override public void failure(int status, Throwable error) { Fragment reconnectFragment = getSupportFragmentManager().findFragmentByTag(RECONNECT_DIALOG_TAG); if (reconnectFragment != null) { mwBoard.connect(); } else { attemptReconnect(); } } }; private void attemptReconnect() { attemptReconnect(0); } private void attemptReconnect(long delay) { ReconnectDialogFragment dialogFragment = ReconnectDialogFragment.newInstance(btDevice); dialogFragment.show(getSupportFragmentManager(), RECONNECT_DIALOG_TAG); if (delay != 0) { connectScheduler.postDelayed(new Runnable() { @Override public void run() { mwBoard.connect(); } }, delay); } else { mwBoard.connect(); } } /** * Fragment managing the behaviors, interactions and presentation of the navigation drawer. */ private NavigationDrawerFragment mNavigationDrawerFragment; /** * Used to store the last screen title. For use in {@link #restoreActionBar()}. */ private CharSequence mTitle; private MetaWearBoard mwBoard; private BluetoothDevice btDevice; private Fragment currentFragment = null; @Override public void onBackPressed() { mwBoard.setConnectionStateHandler(null); mwBoard.disconnect(); super.onBackPressed(); } @Override public void onDestroy() { super.onDestroy(); ///< Unbind the service when the activity is destroyed mwBoard.setConnectionStateHandler(null); getApplicationContext().unbindService(this); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_navigation); mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager() .findFragmentById(R.id.navigation_drawer); mTitle = FRAGMENT_TAGS.get(mNavigationDrawerFragment.getCurrentPosition()); // Set up the drawer. mNavigationDrawerFragment.setUp(R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout)); btDevice = getIntent().getParcelableExtra(EXTRA_BT_DEVICE); getApplicationContext().bindService(new Intent(this, MetaWearBleService.class), this, BIND_AUTO_CREATE); } @Override public void onNavigationDrawerItemSelected(int position) { // update the main content by replacing fragments FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); if (currentFragment != null) { transaction.detach(currentFragment); } String newFragmentTag = FRAGMENT_TAGS.get(position); currentFragment = fragmentManager.findFragmentByTag(newFragmentTag); if (currentFragment == null) { try { currentFragment = FRAGMENT_CLASSES.get(newFragmentTag).getConstructor().newInstance(); } catch (Exception e) { throw new RuntimeException("Cannot instantiate fragment", e); } transaction.add(R.id.container, currentFragment, newFragmentTag); } mTitle = newFragmentTag; restoreActionBar(); transaction.attach(currentFragment).commit(); } @Override public List<String> getFragmentTags() { return FRAGMENT_TAGS; } public void restoreActionBar() { ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayShowTitleEnabled(true); actionBar.setTitle(mTitle); } } @Override public boolean onCreateOptionsMenu(Menu menu) { if (!mNavigationDrawerFragment.isDrawerOpen()) { // Only show items in the action bar relevant to this screen // if the drawer is not showing. Otherwise, let the drawer // decide what to show in the action bar. getMenuInflater().inflate(R.menu.navigation, menu); restoreActionBar(); return true; } return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement switch (id) { case R.id.action_reset: try { mwBoard.getModule(Debug.class).resetDevice(); Toast.makeText(this, R.string.message_soft_reset, Toast.LENGTH_LONG).show(); } catch (UnsupportedModuleException e) { Toast.makeText(this, R.string.error_soft_reset, Toast.LENGTH_SHORT).show(); } return true; case R.id.action_disconnect: mwBoard.setConnectionStateHandler(null); mwBoard.disconnect(); finish(); return true; } return super.onOptionsItemSelected(item); } @Override public BluetoothDevice getBtDevice() { return btDevice; } @Override public void resetConnectionStateHandler(long delay) { mwBoard.setConnectionStateHandler(connectionHandler); attemptReconnect(delay); } @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { mwBoard = ((MetaWearBleService.LocalBinder) iBinder).getMetaWearBoard(btDevice); mwBoard.setConnectionStateHandler(connectionHandler); } @Override public void onServiceDisconnected(ComponentName componentName) { } }