Java tutorial
/* HealthCareDeviceSettingsFragment Copyright (c) 2015 NTT DOCOMO,INC. Released under the MIT license http://opensource.org/licenses/mit-license.php */ package org.deviceconnect.android.deviceplugin.health.fragment; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.content.Context; import android.content.DialogInterface; import android.content.res.Resources; import android.os.Bundle; import android.os.Handler; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.ListView; import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; import org.deviceconnect.android.deviceplugin.health.HealthCareApplication; import org.deviceconnect.android.deviceplugin.health.HealthCareManager; import org.deviceconnect.android.deviceplugin.health.R; import org.deviceconnect.android.deviceplugin.health.activity.HealthCareDeviceSettingsActivity; import org.deviceconnect.android.deviceplugin.health.data.HealthCareDevice; import org.deviceconnect.android.deviceplugin.health.fragment.dialog.ErrorDialogFragment; import org.deviceconnect.android.deviceplugin.health.fragment.dialog.ProgressDialogFragment; import org.deviceconnect.android.util.LogUtil; import java.util.ArrayList; import java.util.List; import java.util.Set; import static org.deviceconnect.android.deviceplugin.health.HealthCareManager.OnDeviceDiscoveryListener; /** * This fragment do setting of the connection to the ble device. * @author NTT DOCOMO, INC. */ public class HealthCareDeviceSettingsFragment extends Fragment { /** * Adapter. */ private DeviceAdapter mDeviceAdapter; /** * Manager. */ private HealthCareManager mManager; /** * Error Dialog. */ private ErrorDialogFragment mErrorDialogFragment; /** * Progress Dialog. */ private ProgressDialogFragment mProgressDialogFragment; /** * Handler. */ private Handler mHandler = new Handler(); /** * Bluetooth ON/OFF? */ BluetoothAdapter mBluetoothAdapter = null; View mRootView; /** * Bluetooth ON/OFF??? */ Switch mBluetoothSwitch = null; /** * ?? */ View mFooterView = null; /** * */ boolean mIsScanning = false; /** * Supported Product List (Not Used) */ String[] productNames = { "PS-100", // EPSON PULSENSE "PS-500", // EPSON PULSENSE "UT201BLE", // A&D BLE Thermometer "UA-651BLE", // A&D BLE Blood Pressure "UC-352BLE" // A&D BLE Weight Scale }; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { mDeviceAdapter = new DeviceAdapter(getActivity(), createDeviceContainers()); mRootView = inflater.inflate(R.layout.fragment_heart_rate_device_settings, null); final ListView listView = (ListView) mRootView.findViewById(R.id.device_list_view); mFooterView = inflater.inflate(R.layout.bluetooth_list_footer_view, null); // ??????? View headerView = inflater.inflate(R.layout.bluetooth_list_header_view, null); Button button = (Button) headerView.findViewById(R.id.button_scan); if (getManager().isScanning()) { button.setText(R.string.heart_rate_setting_button_stop); } button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { onClickScanButton(); } }); listView.addHeaderView(headerView); listView.setAdapter(mDeviceAdapter); // Bluetooth?????ON/OFF? mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter != null) { mBluetoothSwitch = (Switch) mRootView.findViewById(R.id.switch_bluetooth); if (mBluetoothSwitch != null) { if (mBluetoothAdapter.isEnabled()) { mBluetoothSwitch.setChecked(true); mRootView.findViewById(R.id.text_bluetooth_settings).setVisibility(View.GONE); mRootView.findViewById(R.id.device_list_view).setVisibility(View.VISIBLE); } else { mBluetoothSwitch.setChecked(false); mRootView.findViewById(R.id.text_bluetooth_settings).setVisibility(View.VISIBLE); mRootView.findViewById(R.id.device_list_view).setVisibility(View.GONE); } } mBluetoothSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { if (b) { mBluetoothAdapter.enable(); mBluetoothSwitch.setEnabled(false); } else { mBluetoothAdapter.disable(); mBluetoothSwitch.setEnabled(false); } } }); getManager().setOnBluetoothStateChangedListener(mBLEListener); } return mRootView; } private void onClickScanButton() { final ListView listView = (ListView) mRootView.findViewById(R.id.device_list_view); Button button = (Button) mRootView.findViewById(R.id.button_scan); if (mIsScanning) { getManager().stopScanBle(); button.setText(R.string.heart_rate_setting_button_start); listView.removeFooterView(mFooterView); mIsScanning = false; } else { getManager().startScanBle(); button.setText(R.string.heart_rate_setting_button_stop); listView.addFooterView(mFooterView); mIsScanning = true; } } @Override public void onResume() { super.onResume(); getManager().setOnDeviceDiscoveryListener(mEvtListener); } @Override public void onPause() { super.onPause(); getManager().setOnDeviceDiscoveryListener(null); getManager().stopScanBle(); dismissProgressDialog(); dismissErrorDialog(); } /** * Connect to the BLE device that have heart rate service. * @param device BLE device that have heart rate service. */ private void connectDevice(final DeviceContainer device) { getManager().connectBleDevice(device.getAddress()); showProgressDialog(device.getName()); connectingName = device.getAddress(); } private String connectingName; /** * Disconnect to the BLE device that have heart rate service. * @param device BLE device that have heart rate service. */ private void disconnectDevice(final DeviceContainer device) { getManager().disconnectBleDevice(device.getAddress()); getManager().setRegisterFlag(device.getAddress(), false); getActivity().runOnUiThread(new Runnable() { @Override public void run() { DeviceContainer container = findDeviceContainerByAddress(device.getAddress()); if (container != null) { container.setRegisterFlag(false); mDeviceAdapter.notifyDataSetChanged(); } } }); } /** * ?? * @param device ? */ private void registerDevice(final DeviceContainer device) { getManager().setRegisterFlag(device.getAddress(), true); getActivity().runOnUiThread(new Runnable() { @Override public void run() { DeviceContainer container = findDeviceContainerByAddress(device.getAddress()); if (container != null) { container.setRegisterFlag(true); mDeviceAdapter.notifyDataSetChanged(); } } }); } /** * Display the dialog of connecting a ble device. * @param name device name */ private void showProgressDialog(final String name) { dismissProgressDialog(); Resources res = getActivity().getResources(); String title = res.getString(R.string.heart_rate_setting_connecting_title); String message = res.getString(R.string.heart_rate_setting_connecting_message, name); mProgressDialogFragment = ProgressDialogFragment.newInstance(title, message); mProgressDialogFragment.show(getFragmentManager(), "dialog"); } /** * Dismiss the dialog of connecting a ble device. */ private void dismissProgressDialog() { if (mProgressDialogFragment != null) { mProgressDialogFragment.dismiss(); mProgressDialogFragment = null; } } /** * Display the error dialog. * @param name device name * @param status error reason. */ private void showErrorDialog(String name, final int status) { dismissErrorDialog(); Resources res = getActivity().getResources(); String title = res.getString(R.string.heart_rate_setting_dialog_error_title); if (name == null) { name = getString(R.string.heart_rate_setting_default_name); } String message; if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) { message = res.getString(R.string.heart_rate_setting_dialog_need_auth, name); } else { message = res.getString(R.string.heart_rate_setting_dialog_error_message, name); } mErrorDialogFragment = ErrorDialogFragment.newInstance(title, message); mErrorDialogFragment.show(getFragmentManager(), "error_dialog"); mErrorDialogFragment.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { mErrorDialogFragment = null; } }); } /** * Dismiss the error dialog. */ private void dismissErrorDialog() { if (mErrorDialogFragment != null) { mErrorDialogFragment.dismiss(); mErrorDialogFragment = null; } } /** * Gets a instance of HealthCareManager. * @return HealthCareManager */ private HealthCareManager getManager() { return mManager; } private OnDeviceDiscoveryListener mEvtListener = new OnDeviceDiscoveryListener() { @Override public void onDiscovery(final List<BluetoothDevice> devices) { if (mDeviceAdapter == null) { return; } LogUtil.d("BleDeviceDiscoveryListener#onDiscovery: " + devices.size()); if (getActivity() == null) { return; } for (BluetoothDevice device : devices) { int count = mDeviceAdapter.getCount(); boolean isMatched = false; for (int i = 0; i < count; i++) { DeviceContainer adapterDevice = mDeviceAdapter.getItem(i); if (device.getAddress().equals(adapterDevice.getAddress())) { isMatched = true; break; } } if (!isMatched) { mDeviceAdapter.add(createContainer(device)); } } } @Override public void onDisconnected(final BluetoothDevice device, final int status) { LogUtil.d("ConnectEventListener#onDisconnected: [" + device + "]"); if (getActivity() == null) { return; } if (connectingName == null || !connectingName.equals(device.getAddress())) { return; } connectingName = null; getActivity().runOnUiThread(new Runnable() { @Override public void run() { DeviceContainer container = findDeviceContainerByAddress(device.getAddress()); if (container != null) { mDeviceAdapter.notifyDataSetChanged(); } dismissProgressDialog(); showErrorDialog(device.getName(), status); } }); } @Override public void onRegistered(final BluetoothDevice device) { LogUtil.d("ConnectEventListener#onRegistered: [" + device + "]"); if (getActivity() == null) { return; } if (connectingName == null || !connectingName.equals(device.getAddress())) { return; } connectingName = null; getActivity().runOnUiThread(new Runnable() { @Override public void run() { DeviceContainer container = findDeviceContainerByAddress(device.getAddress()); if (container != null) { HealthCareDevice healthCareDevice = getManager().getRegisteredDevice(device.getAddress()); if (healthCareDevice == null) { container.setProfileType(HealthCareDevice.PROFILE_TYPE_UNCONFIRMED); } else { container.setProfileType(healthCareDevice.getProfileType()); if (healthCareDevice .getProfileType() == HealthCareDevice.PROFILE_TYPE_HEALTH_THERMOMETER || healthCareDevice.getProfileType() == HealthCareDevice.PROFILE_TYPE_HEART_RATE || healthCareDevice .getProfileType() == HealthCareDevice.PROFILE_TYPE_HEALTH_BLOOD_PRESSURE || healthCareDevice .getProfileType() == HealthCareDevice.PROFILE_TYPE_HEALTH_WEIGHT_SCALE) { // ??? getManager().setRegisterFlag(device.getAddress(), true); container.setRegisterFlag(true); } } mDeviceAdapter.notifyDataSetChanged(); } dismissProgressDialog(); } }); } }; /** * Create a list of device. * @return list of device */ private List<DeviceContainer> createDeviceContainers() { List<DeviceContainer> containers = new ArrayList<>(); List<HealthCareDevice> devices = getManager().getAllDevices(); for (HealthCareDevice device : devices) { containers.add(createContainer(device)); } // MEMO: add of device that are paired to smart phone. Set<BluetoothDevice> pairing = getManager().getBondedDevices(); if (pairing != null) { for (BluetoothDevice device : pairing) { String name = device.getName(); LogUtil.d("name is " + name); if (name != null && (name.contains("PS-100") || name.contains("UT201BLE") || name.contains("UA-651BLE") || name.contains("UC-352BLE")) && !containAddressForList(containers, device.getAddress())) { containers.add(createContainer(device)); } if (name != null && !containAddressForList(containers, device.getAddress())) { containers.add(createContainer(device)); } } } return containers; } /** * Returns true if this address contains the list of device. * @param containers list of device * @param address address of device * @return true if address is an element of this List, false otherwise */ private boolean containAddressForList(final List<DeviceContainer> containers, final String address) { for (DeviceContainer container : containers) { if (container.getAddress().equalsIgnoreCase(address)) { return true; } } return false; } /** * Look for a DeviceContainer with the given address. * @param address address of device * @return The DeviceContainer that has the given address or null */ private DeviceContainer findDeviceContainerByAddress(final String address) { int size = mDeviceAdapter.getCount(); for (int i = 0; i < size; i++) { DeviceContainer container = mDeviceAdapter.getItem(i); if (container.getAddress().equalsIgnoreCase(address)) { return container; } } return null; } /** * Create a DeviceContainer from BluetoothDevice. * @param device Instance of BluetoothDevice * @return Instance of DeviceContainer */ private DeviceContainer createContainer(final BluetoothDevice device) { DeviceContainer container = new DeviceContainer(); container.setName(device.getName()); container.setAddress(device.getAddress()); return container; } /** * Create a DeviceContainer from HealthCareDevice. * @param device Instance of HealthCareDevice * @return Instance of DeviceContainer */ private DeviceContainer createContainer(final HealthCareDevice device) { DeviceContainer container = new DeviceContainer(); container.setName(device.getName()); container.setAddress(device.getAddress()); container.setRegisterFlag(device.isRegisterFlag()); container.setProfileType(device.getProfileType()); return container; } /** * ?????? */ private class DeviceContainer { private String mName; private String mAddress; private int mProfileType; private boolean mRegisterFlag; public String getName() { return mName; } public void setName(final String name) { if (name == null) { mName = getActivity().getResources().getString(R.string.heart_rate_setting_default_name); } else { mName = name; } } public String getAddress() { return mAddress; } public void setAddress(final String address) { mAddress = address; } public boolean isRegisterFlag() { return mRegisterFlag; } public void setRegisterFlag(boolean registerFlag) { mRegisterFlag = registerFlag; } public void setProfileType(int type) { mProfileType = type; } public int getProfileType() { return mProfileType; } } /** * ??? */ private class DeviceAdapter extends ArrayAdapter<DeviceContainer> { private LayoutInflater mInflater; /** * * @param context Context * @param objects DeviceContainer? */ public DeviceAdapter(final Context context, final List<DeviceContainer> objects) { super(context, 0, objects); mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View getView(final int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(R.layout.item_heart_rate_device, null); } // ????? final DeviceContainer device = getItem(position); ImageView imageView = (ImageView) convertView.findViewById(R.id.device_type_image); switch (device.getProfileType()) { case HealthCareDevice.PROFILE_TYPE_NOT_SUPPORTED: imageView.setImageResource(R.drawable.not_supported); break; case HealthCareDevice.PROFILE_TYPE_HEART_RATE: imageView.setImageResource(R.drawable.heart_rate); break; case HealthCareDevice.PROFILE_TYPE_HEALTH_THERMOMETER: imageView.setImageResource(R.drawable.health_thermometer); break; case HealthCareDevice.PROFILE_TYPE_HEALTH_BLOOD_PRESSURE: imageView.setImageResource(R.drawable.health_thermometer); break; case HealthCareDevice.PROFILE_TYPE_HEALTH_WEIGHT_SCALE: imageView.setImageResource(R.drawable.health_thermometer); break; default: imageView.setImageResource(R.drawable.unconfirmed); break; } // ????. TextView nameView = (TextView) convertView.findViewById(R.id.device_name); nameView.setText(device.getName()); // ??MAC ADDRESS? TextView addressView = (TextView) convertView.findViewById(R.id.device_address); addressView.setText(device.getAddress()); // ???? Button btn = (Button) convertView.findViewById(R.id.btn_connect_device); if (device.isRegisterFlag()) { btn.setBackgroundResource(R.drawable.button_red); btn.setText(R.string.heart_rate_setting_unregister); } else { btn.setBackgroundResource(R.drawable.button_blue); btn.setText(R.string.heart_rate_setting_register); } if (device.getProfileType() == HealthCareDevice.PROFILE_TYPE_NOT_SUPPORTED) { btn.setEnabled(false); } else { btn.setEnabled(true); } btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { if (device.isRegisterFlag()) { // ????????? disconnectDevice(device); } else { HealthCareDevice hcDevice = getManager().getRegisteredDevice(device.getAddress()); if (hcDevice != null && hcDevice.isDeviceInformationRegistered()) { // ??????????????? registerDevice(device); } else { // ??????????? // ? connectDevice(device); } } } }); return convertView; } } /** * Bluetooth / ???. */ private HealthCareManager.OnBluetoothStateChangedListener mBLEListener = new HealthCareManager.OnBluetoothStateChangedListener() { @Override public void onStateChanged(final int state) { mHandler.post(new Runnable() { @Override public void run() { stateChanged(state); } }); } }; /** * ?????. * @param state Bluetooth??. */ public void stateChanged(int state) { if (mBluetoothSwitch != null) { if (state == BluetoothAdapter.STATE_ON) { mBluetoothSwitch.setChecked(true); mBluetoothSwitch.setEnabled(true); } else if (state == BluetoothAdapter.STATE_OFF) { mBluetoothSwitch.setChecked(false); mBluetoothSwitch.setEnabled(true); } } if (state == BluetoothAdapter.STATE_ON) { // ???? mRootView.findViewById(R.id.text_bluetooth_settings).setVisibility(View.GONE); mRootView.findViewById(R.id.device_list_view).setVisibility(View.VISIBLE); } else if (state == BluetoothAdapter.STATE_TURNING_OFF) { if (mIsScanning) { onClickScanButton(); } // Bluetooth OFF? mRootView.findViewById(R.id.text_bluetooth_settings).setVisibility(View.VISIBLE); mRootView.findViewById(R.id.device_list_view).setVisibility(View.GONE); } } /** * HealthCareManager? * @param manager */ public void setHealthCareManager(HealthCareManager manager) { mManager = manager; } }