mirror of
https://github.com/aljazceru/Android-nRF-Toolbox.git
synced 2025-12-20 16:04:22 +01:00
Migration to BLE Library 2.2.0-alpha05
Getting rid of hungarian notation
This commit is contained in:
@@ -57,7 +57,7 @@ dependencies {
|
||||
|
||||
// Import the BLE Common Library.
|
||||
// The BLE Common Library depends on BLE Library. It is enough to include the first one.
|
||||
implementation 'no.nordicsemi.android:ble-common:2.1.1'
|
||||
implementation 'no.nordicsemi.android:ble-common:2.2.0-alpha05'
|
||||
// The BLE Common Library may be included from jcenter. If you want to modify the code,
|
||||
// clone both projects from GitHub and replace the line above with the following
|
||||
// (and also the according lines in the settings.gradle):
|
||||
|
||||
@@ -57,19 +57,23 @@ public class AppHelpFragment extends DialogFragment {
|
||||
@Override
|
||||
@NonNull
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Bundle args = getArguments();
|
||||
final Bundle args = requireArguments();
|
||||
final StringBuilder text = new StringBuilder(getString(args.getInt(ARG_TEXT)));
|
||||
|
||||
final boolean appendVersion = args.getBoolean(ARG_VERSION);
|
||||
if (appendVersion) {
|
||||
try {
|
||||
final String version = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0).versionName;
|
||||
final String version = requireContext().getPackageManager()
|
||||
.getPackageInfo(requireContext().getPackageName(), 0).versionName;
|
||||
text.append(getString(R.string.about_version, version));
|
||||
} catch (final NameNotFoundException e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
return new AlertDialog.Builder(getActivity()).setTitle(R.string.about_title).setMessage(text)
|
||||
.setPositiveButton(R.string.ok, null).create();
|
||||
return new AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.about_title)
|
||||
.setMessage(text)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.create();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,12 +61,12 @@ public class FeaturesActivity extends AppCompatActivity {
|
||||
private static final String NRF_CONNECT_CLASS = NRF_CONNECT_PACKAGE + ".DeviceListActivity";
|
||||
private static final String NRF_CONNECT_MARKET_URI = "market://details?id=no.nordicsemi.android.mcp";
|
||||
|
||||
// Extras that can be passed from NFC (see SplashscreenActivity)
|
||||
// Extras that can be passed from NFC (see SplashScreenActivity)
|
||||
public static final String EXTRA_APP = "application/vnd.no.nordicsemi.type.app";
|
||||
public static final String EXTRA_ADDRESS = "application/vnd.no.nordicsemi.type.address";
|
||||
|
||||
private DrawerLayout mDrawerLayout;
|
||||
private ActionBarDrawerToggle mDrawerToggle;
|
||||
private DrawerLayout drawerLayout;
|
||||
private ActionBarDrawerToggle drawerToggle;
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
@@ -80,18 +80,18 @@ public class FeaturesActivity extends AppCompatActivity {
|
||||
if (!ensureBLEExists())
|
||||
finish();
|
||||
|
||||
final DrawerLayout drawer = mDrawerLayout = findViewById(R.id.drawer_layout);
|
||||
final DrawerLayout drawer = drawerLayout = findViewById(R.id.drawer_layout);
|
||||
drawer.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
|
||||
|
||||
// Set the drawer toggle as the DrawerListener
|
||||
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.drawer_open, R.string.drawer_close) {
|
||||
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close) {
|
||||
@Override
|
||||
public void onDrawerSlide(final View drawerView, final float slideOffset) {
|
||||
// Disable the Hamburger icon animation
|
||||
super.onDrawerSlide(drawerView, 0);
|
||||
}
|
||||
};
|
||||
drawer.addDrawerListener(mDrawerToggle);
|
||||
drawer.addDrawerListener(drawerToggle);
|
||||
|
||||
// setup plug-ins in the drawer
|
||||
setupPluginsInDrawer(drawer.findViewById(R.id.plugin_container));
|
||||
@@ -130,23 +130,24 @@ public class FeaturesActivity extends AppCompatActivity {
|
||||
protected void onPostCreate(final Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
// Sync the toggle state after onRestoreInstanceState has occurred.
|
||||
mDrawerToggle.syncState();
|
||||
drawerToggle.syncState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull final Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
mDrawerToggle.onConfigurationChanged(newConfig);
|
||||
drawerToggle.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
|
||||
// Pass the event to ActionBarDrawerToggle, if it returns
|
||||
// true, then it has handled the app icon touch event
|
||||
if (mDrawerToggle.onOptionsItemSelected(item)) {
|
||||
if (drawerToggle.onOptionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//noinspection SwitchStatementWithTooFewBranches
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_about:
|
||||
final AppHelpFragment fragment = AppHelpFragment.getInstance(R.string.about_text, true);
|
||||
@@ -185,7 +186,7 @@ public class FeaturesActivity extends AppCompatActivity {
|
||||
} catch (final ActivityNotFoundException e) {
|
||||
Toast.makeText(FeaturesActivity.this, R.string.no_application_play, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
mDrawerLayout.closeDrawers();
|
||||
drawerLayout.closeDrawers();
|
||||
});
|
||||
|
||||
// look for other plug-ins
|
||||
@@ -206,7 +207,7 @@ public class FeaturesActivity extends AppCompatActivity {
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
mDrawerLayout.closeDrawers();
|
||||
drawerLayout.closeDrawers();
|
||||
});
|
||||
container.addView(item);
|
||||
}
|
||||
|
||||
@@ -32,27 +32,27 @@ public class PermissionRationaleFragment extends DialogFragment {
|
||||
private static final String ARG_PERMISSION = "ARG_PERMISSION";
|
||||
private static final String ARG_TEXT = "ARG_TEXT";
|
||||
|
||||
private PermissionDialogListener mListener;
|
||||
private PermissionDialogListener listener;
|
||||
|
||||
public interface PermissionDialogListener {
|
||||
void onRequestPermission(final String permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(final Context context) {
|
||||
public void onAttach(@NonNull final Context context) {
|
||||
super.onAttach(context);
|
||||
|
||||
if (context instanceof PermissionDialogListener) {
|
||||
mListener = (PermissionDialogListener) context;
|
||||
listener = (PermissionDialogListener) context;
|
||||
} else {
|
||||
throw new IllegalArgumentException("The parent activity must impelemnt PermissionDialogListener");
|
||||
throw new IllegalArgumentException("The parent activity must implement PermissionDialogListener");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
mListener = null;
|
||||
listener = null;
|
||||
}
|
||||
|
||||
public static PermissionRationaleFragment getInstance(final int aboutResId, final String permission) {
|
||||
@@ -69,10 +69,10 @@ public class PermissionRationaleFragment extends DialogFragment {
|
||||
@Override
|
||||
@NonNull
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Bundle args = getArguments();
|
||||
final Bundle args = requireArguments();
|
||||
final StringBuilder text = new StringBuilder(getString(args.getInt(ARG_TEXT)));
|
||||
return new AlertDialog.Builder(getActivity()).setTitle(R.string.permission_title).setMessage(text)
|
||||
return new AlertDialog.Builder(requireContext()).setTitle(R.string.permission_title).setMessage(text)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.ok, (dialog, which) -> mListener.onRequestPermission(args.getString(ARG_PERMISSION))).create();
|
||||
.setPositiveButton(R.string.ok, (dialog, which) -> listener.onRequestPermission(args.getString(ARG_PERMISSION))).create();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,27 +37,29 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
|
||||
public class AppAdapter extends BaseAdapter {
|
||||
private static final String CATEGORY = "no.nordicsemi.android.nrftoolbox.LAUNCHER";
|
||||
private static final String NRF_CONNECT_PACKAGE = "no.nordicsemi.android.mcp";
|
||||
|
||||
private final Context mContext;
|
||||
private final PackageManager mPackageManager;
|
||||
private final LayoutInflater mInflater;
|
||||
private final List<ResolveInfo> mApplications;
|
||||
private final Context context;
|
||||
private final PackageManager packageManager;
|
||||
private final LayoutInflater inflater;
|
||||
private final List<ResolveInfo> applications;
|
||||
|
||||
public AppAdapter(final Context context) {
|
||||
mContext = context;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
public AppAdapter(@NonNull final Context context) {
|
||||
this.context = context;
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
|
||||
// get nRF installed app plugins from package manager
|
||||
final PackageManager pm = mPackageManager = context.getPackageManager();
|
||||
final PackageManager pm = packageManager = context.getPackageManager();
|
||||
final Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.addCategory(CATEGORY);
|
||||
|
||||
final List<ResolveInfo> appList = mApplications = pm.queryIntentActivities(intent, 0);
|
||||
final List<ResolveInfo> appList = applications = pm.queryIntentActivities(intent, 0);
|
||||
// TODO remove the following loop after some time, when there will be no more MCP 1.1 at the market.
|
||||
for (final ResolveInfo info : appList) {
|
||||
if (NRF_CONNECT_PACKAGE.equals(info.activityInfo.packageName)) {
|
||||
@@ -70,24 +72,24 @@ public class AppAdapter extends BaseAdapter {
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mApplications.size();
|
||||
return applications.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return mApplications.get(position);
|
||||
public Object getItem(final int position) {
|
||||
return applications.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
public long getItemId(final int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
public View getView(final int position, @Nullable final View convertView, @NonNull final ViewGroup parent) {
|
||||
View view = convertView;
|
||||
if (view == null) {
|
||||
view = mInflater.inflate(R.layout.feature_icon, parent, false);
|
||||
view = inflater.inflate(R.layout.feature_icon, parent, false);
|
||||
|
||||
final ViewHolder holder = new ViewHolder();
|
||||
holder.view = view;
|
||||
@@ -96,8 +98,8 @@ public class AppAdapter extends BaseAdapter {
|
||||
view.setTag(holder);
|
||||
}
|
||||
|
||||
final ResolveInfo info = mApplications.get(position);
|
||||
final PackageManager pm = mPackageManager;
|
||||
final ResolveInfo info = applications.get(position);
|
||||
final PackageManager pm = packageManager;
|
||||
|
||||
final ViewHolder holder = (ViewHolder) view.getTag();
|
||||
holder.icon.setImageDrawable(info.loadIcon(pm));
|
||||
@@ -106,7 +108,7 @@ public class AppAdapter extends BaseAdapter {
|
||||
final Intent intent = new Intent();
|
||||
intent.setComponent(new ComponentName(info.activityInfo.packageName, info.activityInfo.name));
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
mContext.startActivity(intent);
|
||||
context.startActivity(intent);
|
||||
});
|
||||
|
||||
return view;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package no.nordicsemi.android.nrftoolbox.app;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
@@ -133,13 +134,15 @@ import no.nordicsemi.android.nrftoolbox.R;
|
||||
* @see #setListAdapter
|
||||
* @see android.widget.ExpandableListView
|
||||
*/
|
||||
@SuppressLint("Registered")
|
||||
@SuppressWarnings("unused")
|
||||
public class ExpandableListActivity extends AppCompatActivity implements
|
||||
OnCreateContextMenuListener,
|
||||
ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener,
|
||||
ExpandableListView.OnGroupExpandListener {
|
||||
ExpandableListAdapter mAdapter;
|
||||
ExpandableListView mList;
|
||||
boolean mFinishedStart = false;
|
||||
ExpandableListAdapter adapter;
|
||||
ExpandableListView list;
|
||||
boolean finishedStart = false;
|
||||
|
||||
/**
|
||||
* Override this to populate the context menu when an item is long pressed. menuInfo will contain an
|
||||
@@ -196,34 +199,34 @@ public class ExpandableListActivity extends AppCompatActivity implements
|
||||
@Override
|
||||
public void onContentChanged() {
|
||||
super.onContentChanged();
|
||||
View emptyView = findViewById(R.id.empty);
|
||||
mList = findViewById(R.id.list);
|
||||
if (mList == null) {
|
||||
final View emptyView = findViewById(R.id.empty);
|
||||
list = findViewById(R.id.list);
|
||||
if (list == null) {
|
||||
throw new RuntimeException(
|
||||
"Your content must have a ExpandableListView whose id attribute is " +
|
||||
"'R.id.list'");
|
||||
}
|
||||
if (emptyView != null) {
|
||||
mList.setEmptyView(emptyView);
|
||||
list.setEmptyView(emptyView);
|
||||
}
|
||||
mList.setOnChildClickListener(this);
|
||||
mList.setOnGroupExpandListener(this);
|
||||
mList.setOnGroupCollapseListener(this);
|
||||
list.setOnChildClickListener(this);
|
||||
list.setOnGroupExpandListener(this);
|
||||
list.setOnGroupCollapseListener(this);
|
||||
|
||||
if (mFinishedStart) {
|
||||
setListAdapter(mAdapter);
|
||||
if (finishedStart) {
|
||||
setListAdapter(adapter);
|
||||
}
|
||||
mFinishedStart = true;
|
||||
finishedStart = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the adapter for the expandable list.
|
||||
*/
|
||||
public void setListAdapter(ExpandableListAdapter adapter) {
|
||||
public void setListAdapter(final ExpandableListAdapter adapter) {
|
||||
synchronized (this) {
|
||||
ensureList();
|
||||
mAdapter = adapter;
|
||||
mList.setAdapter(adapter);
|
||||
this.adapter = adapter;
|
||||
list.setAdapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,18 +237,18 @@ public class ExpandableListActivity extends AppCompatActivity implements
|
||||
*/
|
||||
public ExpandableListView getExpandableListView() {
|
||||
ensureList();
|
||||
return mList;
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ExpandableListAdapter associated with this activity's ExpandableListView.
|
||||
*/
|
||||
public ExpandableListAdapter getExpandableListAdapter() {
|
||||
return mAdapter;
|
||||
return adapter;
|
||||
}
|
||||
|
||||
private void ensureList() {
|
||||
if (mList != null) {
|
||||
if (list != null) {
|
||||
return;
|
||||
}
|
||||
setContentView(R.layout.expandable_list_content);
|
||||
@@ -257,7 +260,7 @@ public class ExpandableListActivity extends AppCompatActivity implements
|
||||
* @return The ID of the currently selected group or child.
|
||||
*/
|
||||
public long getSelectedId() {
|
||||
return mList.getSelectedId();
|
||||
return list.getSelectedId();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -267,7 +270,7 @@ public class ExpandableListActivity extends AppCompatActivity implements
|
||||
* @return A packed position representation containing the currently selected group or child's position and type.
|
||||
*/
|
||||
public long getSelectedPosition() {
|
||||
return mList.getSelectedPosition();
|
||||
return list.getSelectedPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -282,8 +285,8 @@ public class ExpandableListActivity extends AppCompatActivity implements
|
||||
* Whether the child's group should be expanded if it is collapsed.
|
||||
* @return Whether the selection was successfully set on the child.
|
||||
*/
|
||||
public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) {
|
||||
return mList.setSelectedChild(groupPosition, childPosition, shouldExpandGroup);
|
||||
public boolean setSelectedChild(final int groupPosition, final int childPosition, final boolean shouldExpandGroup) {
|
||||
return list.setSelectedChild(groupPosition, childPosition, shouldExpandGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,8 +295,8 @@ public class ExpandableListActivity extends AppCompatActivity implements
|
||||
* @param groupPosition
|
||||
* The position of the group that should be selected.
|
||||
*/
|
||||
public void setSelectedGroup(int groupPosition) {
|
||||
mList.setSelectedGroup(groupPosition);
|
||||
public void setSelectedGroup(final int groupPosition) {
|
||||
list.setSelectedGroup(groupPosition);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.bluetooth.BluetoothGattService;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -23,16 +25,15 @@ import no.nordicsemi.android.nrftoolbox.profile.LoggableBleManager;
|
||||
* @param <T> The profile callbacks type.
|
||||
* @see BleManager
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends LoggableBleManager<T> {
|
||||
/** Battery Service UUID. */
|
||||
private final static UUID BATTERY_SERVICE_UUID = UUID.fromString("0000180F-0000-1000-8000-00805f9b34fb");
|
||||
/** Battery Level characteristic UUID. */
|
||||
private final static UUID BATTERY_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A19-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private BluetoothGattCharacteristic mBatteryLevelCharacteristic;
|
||||
private BluetoothGattCharacteristic batteryLevelCharacteristic;
|
||||
/** Last received Battery Level value. */
|
||||
private Integer mBatteryLevel;
|
||||
private Integer batteryLevel;
|
||||
|
||||
/**
|
||||
* The manager constructor.
|
||||
@@ -43,12 +44,13 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
|
||||
super(context);
|
||||
}
|
||||
|
||||
private DataReceivedCallback mBatteryLevelDataCallback = new BatteryLevelDataCallback() {
|
||||
private DataReceivedCallback batteryLevelDataCallback = new BatteryLevelDataCallback() {
|
||||
@Override
|
||||
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) {
|
||||
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device,
|
||||
@IntRange(from = 0, to = 100) final int batteryLevel) {
|
||||
log(LogContract.Log.Level.APPLICATION,"Battery Level received: " + batteryLevel + "%");
|
||||
mBatteryLevel = batteryLevel;
|
||||
mCallbacks.onBatteryLevelChanged(device, batteryLevel);
|
||||
BatteryManager.this.batteryLevel = batteryLevel;
|
||||
callbacks.onBatteryLevelChanged(device, batteryLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,8 +61,8 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
|
||||
|
||||
public void readBatteryLevelCharacteristic() {
|
||||
if (isConnected()) {
|
||||
readCharacteristic(mBatteryLevelCharacteristic)
|
||||
.with(mBatteryLevelDataCallback)
|
||||
readCharacteristic(batteryLevelCharacteristic)
|
||||
.with(batteryLevelDataCallback)
|
||||
.fail((device, status) -> log(Log.WARN,"Battery Level characteristic not found"))
|
||||
.enqueue();
|
||||
}
|
||||
@@ -69,9 +71,9 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
|
||||
public void enableBatteryLevelCharacteristicNotifications() {
|
||||
if (isConnected()) {
|
||||
// If the Battery Level characteristic is null, the request will be ignored
|
||||
setNotificationCallback(mBatteryLevelCharacteristic)
|
||||
.with(mBatteryLevelDataCallback);
|
||||
enableNotifications(mBatteryLevelCharacteristic)
|
||||
setNotificationCallback(batteryLevelCharacteristic)
|
||||
.with(batteryLevelDataCallback);
|
||||
enableNotifications(batteryLevelCharacteristic)
|
||||
.done(device -> log(Log.INFO, "Battery Level notifications enabled"))
|
||||
.fail((device, status) -> log(Log.WARN, "Battery Level characteristic not found"))
|
||||
.enqueue();
|
||||
@@ -83,7 +85,7 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
|
||||
*/
|
||||
public void disableBatteryLevelCharacteristicNotifications() {
|
||||
if (isConnected()) {
|
||||
disableNotifications(mBatteryLevelCharacteristic)
|
||||
disableNotifications(batteryLevelCharacteristic)
|
||||
.done(device -> log(Log.INFO, "Battery Level notifications disabled"))
|
||||
.enqueue();
|
||||
}
|
||||
@@ -95,7 +97,7 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
|
||||
* @return Battery Level value, in percent.
|
||||
*/
|
||||
public Integer getBatteryLevel() {
|
||||
return mBatteryLevel;
|
||||
return batteryLevel;
|
||||
}
|
||||
|
||||
protected abstract class BatteryManagerGattCallback extends BleManagerGattCallback {
|
||||
@@ -110,15 +112,15 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
|
||||
protected boolean isOptionalServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(BATTERY_SERVICE_UUID);
|
||||
if (service != null) {
|
||||
mBatteryLevelCharacteristic = service.getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID);
|
||||
batteryLevelCharacteristic = service.getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID);
|
||||
}
|
||||
return mBatteryLevelCharacteristic != null;
|
||||
return batteryLevelCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeviceDisconnected() {
|
||||
mBatteryLevelCharacteristic = null;
|
||||
mBatteryLevel = null;
|
||||
batteryLevelCharacteristic = null;
|
||||
batteryLevel = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,15 +41,15 @@ public class BPMActivity extends BleProfileActivity implements BPMManagerCallbac
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = "BPMActivity";
|
||||
|
||||
private TextView mSystolicView;
|
||||
private TextView mSystolicUnitView;
|
||||
private TextView mDiastolicView;
|
||||
private TextView mDiastolicUnitView;
|
||||
private TextView mMeanAPView;
|
||||
private TextView mMeanAPUnitView;
|
||||
private TextView mPulseView;
|
||||
private TextView mTimestampView;
|
||||
private TextView mBatteryLevelView;
|
||||
private TextView systolicView;
|
||||
private TextView systolicUnitView;
|
||||
private TextView diastolicView;
|
||||
private TextView diastolicUnitView;
|
||||
private TextView meanAPView;
|
||||
private TextView meanAPUnitView;
|
||||
private TextView pulseView;
|
||||
private TextView timestampView;
|
||||
private TextView batteryLevelView;
|
||||
|
||||
@Override
|
||||
protected void onCreateView(final Bundle savedInstanceState) {
|
||||
@@ -58,15 +58,15 @@ public class BPMActivity extends BleProfileActivity implements BPMManagerCallbac
|
||||
}
|
||||
|
||||
private void setGUI() {
|
||||
mSystolicView = findViewById(R.id.systolic);
|
||||
mSystolicUnitView = findViewById(R.id.systolic_unit);
|
||||
mDiastolicView = findViewById(R.id.diastolic);
|
||||
mDiastolicUnitView = findViewById(R.id.diastolic_unit);
|
||||
mMeanAPView = findViewById(R.id.mean_ap);
|
||||
mMeanAPUnitView = findViewById(R.id.mean_ap_unit);
|
||||
mPulseView = findViewById(R.id.pulse);
|
||||
mTimestampView = findViewById(R.id.timestamp);
|
||||
mBatteryLevelView = findViewById(R.id.battery);
|
||||
systolicView = findViewById(R.id.systolic);
|
||||
systolicUnitView = findViewById(R.id.systolic_unit);
|
||||
diastolicView = findViewById(R.id.diastolic);
|
||||
diastolicUnitView = findViewById(R.id.diastolic_unit);
|
||||
meanAPView = findViewById(R.id.mean_ap);
|
||||
meanAPUnitView = findViewById(R.id.mean_ap_unit);
|
||||
pulseView = findViewById(R.id.pulse);
|
||||
timestampView = findViewById(R.id.timestamp);
|
||||
batteryLevelView = findViewById(R.id.battery);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,21 +92,21 @@ public class BPMActivity extends BleProfileActivity implements BPMManagerCallbac
|
||||
@Override
|
||||
protected LoggableBleManager<BPMManagerCallbacks> initializeManager() {
|
||||
final BPMManager manager = BPMManager.getBPMManager(getApplicationContext());
|
||||
manager.setGattCallbacks(this);
|
||||
manager.setManagerCallbacks(this);
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setDefaultUI() {
|
||||
mSystolicView.setText(R.string.not_available_value);
|
||||
mSystolicUnitView.setText(null);
|
||||
mDiastolicView.setText(R.string.not_available_value);
|
||||
mDiastolicUnitView.setText(null);
|
||||
mMeanAPView.setText(R.string.not_available_value);
|
||||
mMeanAPUnitView.setText(null);
|
||||
mPulseView.setText(R.string.not_available_value);
|
||||
mTimestampView.setText(R.string.not_available);
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
systolicView.setText(R.string.not_available_value);
|
||||
systolicUnitView.setText(null);
|
||||
diastolicView.setText(R.string.not_available_value);
|
||||
diastolicUnitView.setText(null);
|
||||
meanAPView.setText(R.string.not_available_value);
|
||||
meanAPUnitView.setText(null);
|
||||
pulseView.setText(R.string.not_available_value);
|
||||
timestampView.setText(R.string.not_available);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,7 +122,7 @@ public class BPMActivity extends BleProfileActivity implements BPMManagerCallbac
|
||||
@Override
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
runOnUiThread(() -> mBatteryLevelView.setText(R.string.not_available));
|
||||
runOnUiThread(() -> batteryLevelView.setText(R.string.not_available));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -131,21 +131,21 @@ public class BPMActivity extends BleProfileActivity implements BPMManagerCallbac
|
||||
@Nullable final Float pulseRate, @Nullable final Integer userID,
|
||||
@Nullable final BPMStatus status, @Nullable final Calendar calendar) {
|
||||
runOnUiThread(() -> {
|
||||
mSystolicView.setText(String.valueOf(systolic));
|
||||
mDiastolicView.setText(String.valueOf(diastolic));
|
||||
mMeanAPView.setText(String.valueOf(meanArterialPressure));
|
||||
systolicView.setText(String.valueOf(systolic));
|
||||
diastolicView.setText(String.valueOf(diastolic));
|
||||
meanAPView.setText(String.valueOf(meanArterialPressure));
|
||||
if (pulseRate != null)
|
||||
mPulseView.setText(String.valueOf(pulseRate));
|
||||
pulseView.setText(String.valueOf(pulseRate));
|
||||
else
|
||||
mPulseView.setText(R.string.not_available_value);
|
||||
pulseView.setText(R.string.not_available_value);
|
||||
if (calendar != null)
|
||||
mTimestampView.setText(getString(R.string.bpm_timestamp, calendar));
|
||||
timestampView.setText(getString(R.string.bpm_timestamp, calendar));
|
||||
else
|
||||
mTimestampView.setText(R.string.not_available);
|
||||
timestampView.setText(R.string.not_available);
|
||||
|
||||
mSystolicUnitView.setText(unit == BloodPressureMeasurementCallback.UNIT_mmHg ? R.string.bpm_unit_mmhg : R.string.bpm_unit_kpa);
|
||||
mDiastolicUnitView.setText(unit == BloodPressureMeasurementCallback.UNIT_mmHg ? R.string.bpm_unit_mmhg : R.string.bpm_unit_kpa);
|
||||
mMeanAPUnitView.setText(unit == BloodPressureMeasurementCallback.UNIT_mmHg ? R.string.bpm_unit_mmhg : R.string.bpm_unit_kpa);
|
||||
systolicUnitView.setText(unit == BloodPressureMeasurementCallback.UNIT_mmHg ? R.string.bpm_unit_mmhg : R.string.bpm_unit_kpa);
|
||||
diastolicUnitView.setText(unit == BloodPressureMeasurementCallback.UNIT_mmHg ? R.string.bpm_unit_mmhg : R.string.bpm_unit_kpa);
|
||||
meanAPUnitView.setText(unit == BloodPressureMeasurementCallback.UNIT_mmHg ? R.string.bpm_unit_mmhg : R.string.bpm_unit_kpa);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -154,26 +154,26 @@ public class BPMActivity extends BleProfileActivity implements BPMManagerCallbac
|
||||
@Nullable final Float pulseRate, @Nullable final Integer userID,
|
||||
@Nullable final BPMStatus status, @Nullable final Calendar calendar) {
|
||||
runOnUiThread(() -> {
|
||||
mSystolicView.setText(String.valueOf(cuffPressure));
|
||||
mDiastolicView.setText(R.string.not_available_value);
|
||||
mMeanAPView.setText(R.string.not_available_value);
|
||||
systolicView.setText(String.valueOf(cuffPressure));
|
||||
diastolicView.setText(R.string.not_available_value);
|
||||
meanAPView.setText(R.string.not_available_value);
|
||||
if (pulseRate != null)
|
||||
mPulseView.setText(String.valueOf(pulseRate));
|
||||
pulseView.setText(String.valueOf(pulseRate));
|
||||
else
|
||||
mPulseView.setText(R.string.not_available_value);
|
||||
pulseView.setText(R.string.not_available_value);
|
||||
if (calendar != null)
|
||||
mTimestampView.setText(getString(R.string.bpm_timestamp, calendar));
|
||||
timestampView.setText(getString(R.string.bpm_timestamp, calendar));
|
||||
else
|
||||
mTimestampView.setText(R.string.not_available);
|
||||
timestampView.setText(R.string.not_available);
|
||||
|
||||
mSystolicUnitView.setText(unit == IntermediateCuffPressureCallback.UNIT_mmHg ? R.string.bpm_unit_mmhg : R.string.bpm_unit_kpa);
|
||||
mDiastolicUnitView.setText(null);
|
||||
mMeanAPUnitView.setText(null);
|
||||
systolicUnitView.setText(unit == IntermediateCuffPressureCallback.UNIT_mmHg ? R.string.bpm_unit_mmhg : R.string.bpm_unit_kpa);
|
||||
diastolicUnitView.setText(null);
|
||||
meanAPUnitView.setText(null);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) {
|
||||
runOnUiThread(() -> mBatteryLevelView.setText(getString(R.string.battery, batteryLevel)));
|
||||
runOnUiThread(() -> batteryLevelView.setText(getString(R.string.battery, batteryLevel)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class BPMManager extends BatteryManager<BPMManagerCallbacks> {
|
||||
/** Intermediate Cuff Pressure characteristic UUID. */
|
||||
private static final UUID ICP_CHARACTERISTIC_UUID = UUID.fromString("00002A36-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private BluetoothGattCharacteristic mBPMCharacteristic, mICPCharacteristic;
|
||||
private BluetoothGattCharacteristic bpmCharacteristic, icpCharacteristic;
|
||||
|
||||
private static BPMManager managerInstance = null;
|
||||
|
||||
@@ -71,20 +71,20 @@ public class BPMManager extends BatteryManager<BPMManagerCallbacks> {
|
||||
@NonNull
|
||||
@Override
|
||||
protected BatteryManagerGattCallback getGattCallback() {
|
||||
return mGattCallback;
|
||||
return gattCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* BluetoothGatt callbacks for connection/disconnection, service discovery,
|
||||
* receiving notification, etc.
|
||||
*/
|
||||
private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
|
||||
private final BatteryManagerGattCallback gattCallback = new BatteryManagerGattCallback() {
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
super.initialize();
|
||||
|
||||
setNotificationCallback(mICPCharacteristic)
|
||||
setNotificationCallback(icpCharacteristic)
|
||||
.with(new IntermediateCuffPressureDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||
@@ -99,7 +99,7 @@ public class BPMManager extends BatteryManager<BPMManagerCallbacks> {
|
||||
final float cuffPressure, final int unit,
|
||||
@Nullable final Float pulseRate, @Nullable final Integer userID,
|
||||
@Nullable final BPMStatus status, @Nullable final Calendar calendar) {
|
||||
mCallbacks.onIntermediateCuffPressureReceived(device, cuffPressure, unit, pulseRate, userID, status, calendar);
|
||||
callbacks.onIntermediateCuffPressureReceived(device, cuffPressure, unit, pulseRate, userID, status, calendar);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,7 +107,7 @@ public class BPMManager extends BatteryManager<BPMManagerCallbacks> {
|
||||
log(Log.WARN, "Invalid ICP data received: " + data);
|
||||
}
|
||||
});
|
||||
setIndicationCallback(mBPMCharacteristic)
|
||||
setIndicationCallback(bpmCharacteristic)
|
||||
.with(new BloodPressureMeasurementDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||
@@ -123,7 +123,7 @@ public class BPMManager extends BatteryManager<BPMManagerCallbacks> {
|
||||
final int unit, @Nullable final Float pulseRate,
|
||||
@Nullable final Integer userID, @Nullable final BPMStatus status,
|
||||
@Nullable final Calendar calendar) {
|
||||
mCallbacks.onBloodPressureMeasurementReceived(device, systolic, diastolic,
|
||||
callbacks.onBloodPressureMeasurementReceived(device, systolic, diastolic,
|
||||
meanArterialPressure, unit, pulseRate, userID, status, calendar);
|
||||
}
|
||||
|
||||
@@ -133,33 +133,33 @@ public class BPMManager extends BatteryManager<BPMManagerCallbacks> {
|
||||
}
|
||||
});
|
||||
|
||||
enableNotifications(mICPCharacteristic)
|
||||
enableNotifications(icpCharacteristic)
|
||||
.fail((device, status) -> log(Log.WARN,
|
||||
"Intermediate Cuff Pressure characteristic not found"))
|
||||
.enqueue();
|
||||
enableIndications(mBPMCharacteristic).enqueue();
|
||||
enableIndications(bpmCharacteristic).enqueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(BP_SERVICE_UUID);
|
||||
if (service != null) {
|
||||
mBPMCharacteristic = service.getCharacteristic(BPM_CHARACTERISTIC_UUID);
|
||||
mICPCharacteristic = service.getCharacteristic(ICP_CHARACTERISTIC_UUID);
|
||||
bpmCharacteristic = service.getCharacteristic(BPM_CHARACTERISTIC_UUID);
|
||||
icpCharacteristic = service.getCharacteristic(ICP_CHARACTERISTIC_UUID);
|
||||
}
|
||||
return mBPMCharacteristic != null;
|
||||
return bpmCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isOptionalServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||
super.isOptionalServiceSupported(gatt); // ignore the result of this
|
||||
return mICPCharacteristic != null;
|
||||
return icpCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeviceDisconnected() {
|
||||
mICPCharacteristic = null;
|
||||
mBPMCharacteristic = null;
|
||||
icpCharacteristic = null;
|
||||
bpmCharacteristic = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import android.util.SparseArray;
|
||||
import android.view.MenuInflater;
|
||||
@@ -45,13 +47,13 @@ import no.nordicsemi.android.nrftoolbox.profile.BleProfileServiceReadyActivity;
|
||||
import no.nordicsemi.android.nrftoolbox.proximity.ProximityService;
|
||||
|
||||
public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMSBinder> implements PopupMenu.OnMenuItemClickListener {
|
||||
private View mControlPanelStd;
|
||||
private View mControlPanelAbort;
|
||||
private ListView mRecordsListView;
|
||||
private TextView mBatteryLevelView;
|
||||
private CGMSRecordsAdapter mCgmsRecordsAdapter;
|
||||
private View controlPanelStd;
|
||||
private View controlPanelAbort;
|
||||
private ListView recordsListView;
|
||||
private TextView batteryLevelView;
|
||||
private CGMSRecordsAdapter cgmsRecordsAdapter;
|
||||
|
||||
private CGMService.CGMSBinder mBinder;
|
||||
private CGMService.CGMSBinder binder;
|
||||
|
||||
@Override
|
||||
protected void onCreateView(Bundle savedInstanceState) {
|
||||
@@ -61,32 +63,32 @@ public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMS
|
||||
|
||||
@Override
|
||||
protected void onInitialize(Bundle savedInstanceState) {
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, makeIntentFilter());
|
||||
}
|
||||
|
||||
private void setGUI() {
|
||||
mRecordsListView = findViewById(R.id.list);
|
||||
mControlPanelStd = findViewById(R.id.cgms_control_std);
|
||||
mControlPanelAbort = findViewById(R.id.cgms_control_abort);
|
||||
mBatteryLevelView = findViewById(R.id.battery);
|
||||
recordsListView = findViewById(R.id.list);
|
||||
controlPanelStd = findViewById(R.id.cgms_control_std);
|
||||
controlPanelAbort = findViewById(R.id.cgms_control_abort);
|
||||
batteryLevelView = findViewById(R.id.battery);
|
||||
|
||||
findViewById(R.id.action_last).setOnClickListener(v -> {
|
||||
clearRecords();
|
||||
if (mBinder != null) {
|
||||
mBinder.clear();
|
||||
mBinder.getLastRecord();
|
||||
if (binder != null) {
|
||||
binder.clear();
|
||||
binder.getLastRecord();
|
||||
}
|
||||
});
|
||||
findViewById(R.id.action_all).setOnClickListener(v -> {
|
||||
clearRecords();
|
||||
if (mBinder != null) {
|
||||
if (binder != null) {
|
||||
clearRecords();
|
||||
mBinder.getAllRecords();
|
||||
binder.getAllRecords();
|
||||
}
|
||||
});
|
||||
findViewById(R.id.action_abort).setOnClickListener(v -> {
|
||||
if (mBinder != null) {
|
||||
mBinder.abort();
|
||||
if (binder != null) {
|
||||
binder.abort();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -101,27 +103,27 @@ public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMS
|
||||
}
|
||||
|
||||
private void loadAdapter(SparseArray<CGMSRecord> records) {
|
||||
mCgmsRecordsAdapter.clear();
|
||||
cgmsRecordsAdapter.clear();
|
||||
for (int i = 0; i < records.size(); i++) {
|
||||
mCgmsRecordsAdapter.addItem(records.valueAt(i));
|
||||
cgmsRecordsAdapter.addItem(records.valueAt(i));
|
||||
}
|
||||
mCgmsRecordsAdapter.notifyDataSetChanged();
|
||||
cgmsRecordsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onServiceBound(final CGMService.CGMSBinder binder) {
|
||||
mBinder = binder;
|
||||
this.binder = binder;
|
||||
final SparseArray<CGMSRecord> cgmsRecords = binder.getRecords();
|
||||
if (cgmsRecords != null && cgmsRecords.size() > 0) {
|
||||
if (mCgmsRecordsAdapter == null) {
|
||||
mCgmsRecordsAdapter = new CGMSRecordsAdapter(CGMSActivity.this);
|
||||
mRecordsListView.setAdapter(mCgmsRecordsAdapter);
|
||||
if (cgmsRecordsAdapter == null) {
|
||||
cgmsRecordsAdapter = new CGMSRecordsAdapter(CGMSActivity.this);
|
||||
recordsListView.setAdapter(cgmsRecordsAdapter);
|
||||
}
|
||||
loadAdapter(cgmsRecords);
|
||||
}
|
||||
@@ -129,7 +131,7 @@ public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMS
|
||||
|
||||
@Override
|
||||
protected void onServiceUnbound() {
|
||||
mBinder = null;
|
||||
binder = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -158,31 +160,31 @@ public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMS
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(@NonNull final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// this may notify user or show some views
|
||||
}
|
||||
|
||||
private void setOperationInProgress(final boolean progress) {
|
||||
runOnUiThread(() -> {
|
||||
// setSupportProgressBarIndeterminateVisibility(progress);
|
||||
mControlPanelStd.setVisibility(!progress ? View.VISIBLE : View.GONE);
|
||||
mControlPanelAbort.setVisibility(progress ? View.VISIBLE : View.GONE);
|
||||
controlPanelStd.setVisibility(!progress ? View.VISIBLE : View.GONE);
|
||||
controlPanelAbort.setVisibility(progress ? View.VISIBLE : View.GONE);
|
||||
});
|
||||
}
|
||||
|
||||
public void onBatteryLevelChanged(final BluetoothDevice device, final int value) {
|
||||
mBatteryLevelView.setText(getString(R.string.battery, value));
|
||||
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int value) {
|
||||
batteryLevelView.setText(getString(R.string.battery, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
setOperationInProgress(false);
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
|
||||
public void onError(@NonNull final BluetoothDevice device, @NonNull final String message, final int errorCode) {
|
||||
super.onError(device, message, errorCode);
|
||||
setOperationInProgress(false);
|
||||
}
|
||||
@@ -190,40 +192,40 @@ public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMS
|
||||
@Override
|
||||
protected void setDefaultUI() {
|
||||
clearRecords();
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.action_refresh:
|
||||
if(mBinder != null)
|
||||
mBinder.refreshRecords();
|
||||
if(binder != null)
|
||||
binder.refreshRecords();
|
||||
break;
|
||||
case R.id.action_first:
|
||||
if (mBinder != null)
|
||||
mBinder.getFirstRecord();
|
||||
if (binder != null)
|
||||
binder.getFirstRecord();
|
||||
break;
|
||||
case R.id.action_clear:
|
||||
if (mBinder != null)
|
||||
mBinder.clear();
|
||||
if (binder != null)
|
||||
binder.clear();
|
||||
break;
|
||||
case R.id.action_delete_all:
|
||||
if (mBinder != null)
|
||||
mBinder.deleteAllRecords();
|
||||
if (binder != null)
|
||||
binder.deleteAllRecords();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void clearRecords() {
|
||||
if (mCgmsRecordsAdapter != null) {
|
||||
mCgmsRecordsAdapter.clear();
|
||||
mCgmsRecordsAdapter.notifyDataSetChanged();
|
||||
if (cgmsRecordsAdapter != null) {
|
||||
cgmsRecordsAdapter.clear();
|
||||
cgmsRecordsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
@@ -232,12 +234,12 @@ public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMS
|
||||
switch (action) {
|
||||
case CGMService.BROADCAST_NEW_CGMS_VALUE: {
|
||||
CGMSRecord cgmsRecord = intent.getExtras().getParcelable(CGMService.EXTRA_CGMS_RECORD);
|
||||
if (mCgmsRecordsAdapter == null) {
|
||||
mCgmsRecordsAdapter = new CGMSRecordsAdapter(CGMSActivity.this);
|
||||
mRecordsListView.setAdapter(mCgmsRecordsAdapter);
|
||||
if (cgmsRecordsAdapter == null) {
|
||||
cgmsRecordsAdapter = new CGMSRecordsAdapter(CGMSActivity.this);
|
||||
recordsListView.setAdapter(cgmsRecordsAdapter);
|
||||
}
|
||||
mCgmsRecordsAdapter.addItem(cgmsRecord);
|
||||
mCgmsRecordsAdapter.notifyDataSetChanged();
|
||||
cgmsRecordsAdapter.addItem(cgmsRecord);
|
||||
cgmsRecordsAdapter.notifyDataSetChanged();
|
||||
break;
|
||||
}
|
||||
case CGMService.BROADCAST_DATA_SET_CLEAR:
|
||||
|
||||
@@ -22,18 +22,19 @@
|
||||
|
||||
package no.nordicsemi.android.nrftoolbox.cgms;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.bluetooth.BluetoothGattService;
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import no.nordicsemi.android.ble.common.callback.RecordAccessControlPointDataCallback;
|
||||
import no.nordicsemi.android.ble.common.callback.cgm.CGMFeatureDataCallback;
|
||||
import no.nordicsemi.android.ble.common.callback.cgm.CGMSpecificOpsControlPointDataCallback;
|
||||
@@ -48,9 +49,9 @@ import no.nordicsemi.android.nrftoolbox.parser.CGMMeasurementParser;
|
||||
import no.nordicsemi.android.nrftoolbox.parser.CGMSpecificOpsControlPointParser;
|
||||
import no.nordicsemi.android.nrftoolbox.parser.RecordAccessControlPointParser;
|
||||
|
||||
public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
/** Cycling Speed and Cadence service UUID. */
|
||||
public static final UUID CGMS_UUID = UUID.fromString("0000181F-0000-1000-8000-00805f9b34fb");
|
||||
static final UUID CGMS_UUID = UUID.fromString("0000181F-0000-1000-8000-00805f9b34fb");
|
||||
private static final UUID CGM_STATUS_UUID = UUID.fromString("00002AA9-0000-1000-8000-00805f9b34fb");
|
||||
private static final UUID CGM_FEATURE_UUID = UUID.fromString("00002AA8-0000-1000-8000-00805f9b34fb");
|
||||
private static final UUID CGM_MEASUREMENT_UUID = UUID.fromString("00002AA7-0000-1000-8000-00805f9b34fb");
|
||||
@@ -58,26 +59,26 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
/** Record Access Control Point characteristic UUID. */
|
||||
private static final UUID RACP_UUID = UUID.fromString("00002A52-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private BluetoothGattCharacteristic mCGMStatusCharacteristic;
|
||||
private BluetoothGattCharacteristic mCGMFeatureCharacteristic;
|
||||
private BluetoothGattCharacteristic mCGMMeasurementCharacteristic;
|
||||
private BluetoothGattCharacteristic mCGMSpecificOpsControlPointCharacteristic;
|
||||
private BluetoothGattCharacteristic mRecordAccessControlPointCharacteristic;
|
||||
private BluetoothGattCharacteristic cgmStatusCharacteristic;
|
||||
private BluetoothGattCharacteristic cgmFeatureCharacteristic;
|
||||
private BluetoothGattCharacteristic cgmMeasurementCharacteristic;
|
||||
private BluetoothGattCharacteristic cgmSpecificOpsControlPointCharacteristic;
|
||||
private BluetoothGattCharacteristic recordAccessControlPointCharacteristic;
|
||||
|
||||
private SparseArray<CGMSRecord> mRecords = new SparseArray<>();
|
||||
private SparseArray<CGMSRecord> records = new SparseArray<>();
|
||||
|
||||
/** A flag set to true if the remote device supports E2E CRC. */
|
||||
private boolean mSecured;
|
||||
private boolean secured;
|
||||
/**
|
||||
* A flag set when records has been requested using RACP. This is to distinguish CGM packets
|
||||
* received as continuous measurements or requested.
|
||||
*/
|
||||
private boolean mRecordAccessRequestInProgress;
|
||||
private boolean recordAccessRequestInProgress;
|
||||
/**
|
||||
* The timestamp when the session has started. This is needed to display the user facing
|
||||
* times of samples.
|
||||
*/
|
||||
private long mSessionStartTime;
|
||||
private long sessionStartTime;
|
||||
|
||||
CGMSManager(final Context context) {
|
||||
super(context);
|
||||
@@ -86,14 +87,14 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
@NonNull
|
||||
@Override
|
||||
protected BatteryManagerGattCallback getGattCallback() {
|
||||
return mGattCallback;
|
||||
return gattCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* BluetoothGatt callbacks for connection/disconnection, service discovery,
|
||||
* receiving notification, etc.
|
||||
*/
|
||||
private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
|
||||
private final BatteryManagerGattCallback gattCallback = new BatteryManagerGattCallback() {
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
@@ -102,25 +103,25 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
|
||||
// Read CGM Feature characteristic, mainly to see if the device supports E2E CRC.
|
||||
// This is not supported in the experimental CGMS from the SDK.
|
||||
readCharacteristic(mCGMFeatureCharacteristic)
|
||||
readCharacteristic(cgmFeatureCharacteristic)
|
||||
.with(new CGMFeatureDataCallback() {
|
||||
@Override
|
||||
public void onContinuousGlucoseMonitorFeaturesReceived(@NonNull final BluetoothDevice device, @NonNull final CGMFeatures features,
|
||||
final int type, final int sampleLocation, final boolean secured) {
|
||||
mSecured = features.e2eCrcSupported;
|
||||
log(LogContract.Log.Level.APPLICATION, "E2E CRC feature " + (mSecured ? "supported" : "not supported"));
|
||||
CGMSManager.this.secured = features.e2eCrcSupported;
|
||||
log(LogContract.Log.Level.APPLICATION, "E2E CRC feature " + (CGMSManager.this.secured ? "supported" : "not supported"));
|
||||
}
|
||||
})
|
||||
.fail((device, status) -> log(Log.WARN, "Could not read CGM Feature characteristic"))
|
||||
.enqueue();
|
||||
|
||||
// Check if the session is already started. This is not supported in the experimental CGMS from the SDK.
|
||||
readCharacteristic(mCGMStatusCharacteristic)
|
||||
readCharacteristic(cgmStatusCharacteristic)
|
||||
.with(new CGMStatusDataCallback() {
|
||||
@Override
|
||||
public void onContinuousGlucoseMonitorStatusChanged(@NonNull final BluetoothDevice device, @NonNull final CGMStatus status, final int timeOffset, final boolean secured) {
|
||||
if (!status.sessionStopped) {
|
||||
mSessionStartTime = System.currentTimeMillis() - timeOffset * 60000L;
|
||||
sessionStartTime = System.currentTimeMillis() - timeOffset * 60000L;
|
||||
log(LogContract.Log.Level.APPLICATION, "Session already started");
|
||||
}
|
||||
}
|
||||
@@ -129,7 +130,7 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
.enqueue();
|
||||
|
||||
// Set notification and indication callbacks
|
||||
setNotificationCallback(mCGMMeasurementCharacteristic)
|
||||
setNotificationCallback(cgmMeasurementCharacteristic)
|
||||
.with(new ContinuousGlucoseMeasurementDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||
@@ -147,16 +148,16 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
final boolean secured) {
|
||||
// If the CGM Status characteristic has not been read and the session was already started before,
|
||||
// estimate the Session Start Time by subtracting timeOffset minutes from the current timestamp.
|
||||
if (mSessionStartTime == 0 && !mRecordAccessRequestInProgress) {
|
||||
mSessionStartTime = System.currentTimeMillis() - timeOffset * 60000L;
|
||||
if (sessionStartTime == 0 && !recordAccessRequestInProgress) {
|
||||
sessionStartTime = System.currentTimeMillis() - timeOffset * 60000L;
|
||||
}
|
||||
|
||||
// Calculate the sample timestamp based on the Session Start Time
|
||||
final long timestamp = mSessionStartTime + (timeOffset * 60000L); // Sequence number is in minutes since Start Session
|
||||
final long timestamp = sessionStartTime + (timeOffset * 60000L); // Sequence number is in minutes since Start Session
|
||||
|
||||
final CGMSRecord record = new CGMSRecord(timeOffset, glucoseConcentration, timestamp);
|
||||
mRecords.put(record.sequenceNumber, record);
|
||||
mCallbacks.onCGMValueReceived(device, record);
|
||||
records.put(record.sequenceNumber, record);
|
||||
callbacks.onCGMValueReceived(device, record);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,7 +167,7 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
}
|
||||
});
|
||||
|
||||
setIndicationCallback(mCGMSpecificOpsControlPointCharacteristic)
|
||||
setIndicationCallback(cgmSpecificOpsControlPointCharacteristic)
|
||||
.with(new CGMSpecificOpsControlPointDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||
@@ -174,23 +175,27 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
super.onDataReceived(device, data);
|
||||
}
|
||||
|
||||
@SuppressLint("SwitchIntDef")
|
||||
@Override
|
||||
public void onCGMSpecificOpsOperationCompleted(@NonNull final BluetoothDevice device,
|
||||
final int requestCode, final boolean secured) {
|
||||
@CGMOpCode final int requestCode,
|
||||
final boolean secured) {
|
||||
switch (requestCode) {
|
||||
case CGM_OP_CODE_START_SESSION:
|
||||
mSessionStartTime = System.currentTimeMillis();
|
||||
sessionStartTime = System.currentTimeMillis();
|
||||
break;
|
||||
case CGM_OP_CODE_STOP_SESSION:
|
||||
mSessionStartTime = 0;
|
||||
sessionStartTime = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SwitchIntDef")
|
||||
@SuppressWarnings("StatementWithEmptyBody")
|
||||
@Override
|
||||
public void onCGMSpecificOpsOperationError(@NonNull final BluetoothDevice device,
|
||||
final int requestCode, final int errorCode,
|
||||
@CGMOpCode final int requestCode,
|
||||
@CGMErrorCode final int errorCode,
|
||||
final boolean secured) {
|
||||
switch (requestCode) {
|
||||
case CGM_OP_CODE_START_SESSION:
|
||||
@@ -202,7 +207,7 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
// packet is received based on it's Time Offset.
|
||||
}
|
||||
case CGM_OP_CODE_STOP_SESSION:
|
||||
mSessionStartTime = 0;
|
||||
sessionStartTime = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -214,7 +219,7 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
}
|
||||
});
|
||||
|
||||
setIndicationCallback(mRecordAccessControlPointCharacteristic)
|
||||
setIndicationCallback(recordAccessControlPointCharacteristic)
|
||||
.with(new RecordAccessControlPointDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||
@@ -222,72 +227,76 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
super.onDataReceived(device, data);
|
||||
}
|
||||
|
||||
@SuppressLint("SwitchIntDef")
|
||||
@Override
|
||||
public void onRecordAccessOperationCompleted(@NonNull final BluetoothDevice device, final int requestCode) {
|
||||
public void onRecordAccessOperationCompleted(@NonNull final BluetoothDevice device,
|
||||
@RACPOpCode final int requestCode) {
|
||||
//noinspection SwitchStatementWithTooFewBranches
|
||||
switch (requestCode) {
|
||||
case RACP_OP_CODE_ABORT_OPERATION:
|
||||
mCallbacks.onOperationAborted(device);
|
||||
callbacks.onOperationAborted(device);
|
||||
break;
|
||||
default:
|
||||
mRecordAccessRequestInProgress = false;
|
||||
mCallbacks.onOperationCompleted(device);
|
||||
recordAccessRequestInProgress = false;
|
||||
callbacks.onOperationCompleted(device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecordAccessOperationCompletedWithNoRecordsFound(@NonNull final BluetoothDevice device,
|
||||
final int requestCode) {
|
||||
mRecordAccessRequestInProgress = false;
|
||||
mCallbacks.onOperationCompleted(device);
|
||||
@RACPOpCode final int requestCode) {
|
||||
recordAccessRequestInProgress = false;
|
||||
callbacks.onOperationCompleted(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNumberOfRecordsReceived(@NonNull final BluetoothDevice device, final int numberOfRecords) {
|
||||
mCallbacks.onNumberOfRecordsRequested(device, numberOfRecords);
|
||||
callbacks.onNumberOfRecordsRequested(device, numberOfRecords);
|
||||
if (numberOfRecords > 0) {
|
||||
if (mRecords.size() > 0) {
|
||||
final int sequenceNumber = mRecords.keyAt(mRecords.size() - 1) + 1;
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic,
|
||||
if (records.size() > 0) {
|
||||
final int sequenceNumber = records.keyAt(records.size() - 1) + 1;
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic,
|
||||
RecordAccessControlPointData.reportStoredRecordsGreaterThenOrEqualTo(sequenceNumber))
|
||||
.enqueue();
|
||||
} else {
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic,
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic,
|
||||
RecordAccessControlPointData.reportAllStoredRecords())
|
||||
.enqueue();
|
||||
}
|
||||
} else {
|
||||
mRecordAccessRequestInProgress = false;
|
||||
mCallbacks.onOperationCompleted(device);
|
||||
recordAccessRequestInProgress = false;
|
||||
callbacks.onOperationCompleted(device);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecordAccessOperationError(@NonNull final BluetoothDevice device,
|
||||
final int requestCode, final int errorCode) {
|
||||
@RACPOpCode final int requestCode,
|
||||
@RACPErrorCode final int errorCode) {
|
||||
log(Log.WARN, "Record Access operation failed (error " + errorCode + ")");
|
||||
if (errorCode == RACP_ERROR_OP_CODE_NOT_SUPPORTED) {
|
||||
mCallbacks.onOperationNotSupported(device);
|
||||
callbacks.onOperationNotSupported(device);
|
||||
} else {
|
||||
mCallbacks.onOperationFailed(device);
|
||||
callbacks.onOperationFailed(device);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Enable notifications and indications
|
||||
enableNotifications(mCGMMeasurementCharacteristic)
|
||||
enableNotifications(cgmMeasurementCharacteristic)
|
||||
.fail((device, status) -> log(Log.WARN, "Failed to enable Continuous Glucose Measurement notifications (" + status + ")"))
|
||||
.enqueue();
|
||||
enableIndications(mCGMSpecificOpsControlPointCharacteristic)
|
||||
enableIndications(cgmSpecificOpsControlPointCharacteristic)
|
||||
.fail((device, status) -> log(Log.WARN, "Failed to enable CGM Specific Ops Control Point indications notifications (" + status + ")"))
|
||||
.enqueue();
|
||||
enableIndications(mRecordAccessControlPointCharacteristic)
|
||||
enableIndications(recordAccessControlPointCharacteristic)
|
||||
.fail((device, status) -> log(Log.WARN, "Failed to enabled Record Access Control Point indications (error " + status + ")"))
|
||||
.enqueue();
|
||||
|
||||
// Start Continuous Glucose session if hasn't been started before
|
||||
if (mSessionStartTime == 0L) {
|
||||
writeCharacteristic(mCGMSpecificOpsControlPointCharacteristic, CGMSpecificOpsControlPointData.startSession(mSecured))
|
||||
if (sessionStartTime == 0L) {
|
||||
writeCharacteristic(cgmSpecificOpsControlPointCharacteristic, CGMSpecificOpsControlPointData.startSession(secured))
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + CGMSpecificOpsControlPointParser.parse(data) + "\" sent"))
|
||||
.fail((device, status) -> log(LogContract.Log.Level.ERROR, "Failed to start session (error " + status + ")"))
|
||||
.enqueue();
|
||||
@@ -298,41 +307,41 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
protected boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(CGMS_UUID);
|
||||
if (service != null) {
|
||||
mCGMStatusCharacteristic = service.getCharacteristic(CGM_STATUS_UUID);
|
||||
mCGMFeatureCharacteristic = service.getCharacteristic(CGM_FEATURE_UUID);
|
||||
mCGMMeasurementCharacteristic = service.getCharacteristic(CGM_MEASUREMENT_UUID);
|
||||
mCGMSpecificOpsControlPointCharacteristic = service.getCharacteristic(CGM_OPS_CONTROL_POINT_UUID);
|
||||
mRecordAccessControlPointCharacteristic = service.getCharacteristic(RACP_UUID);
|
||||
cgmStatusCharacteristic = service.getCharacteristic(CGM_STATUS_UUID);
|
||||
cgmFeatureCharacteristic = service.getCharacteristic(CGM_FEATURE_UUID);
|
||||
cgmMeasurementCharacteristic = service.getCharacteristic(CGM_MEASUREMENT_UUID);
|
||||
cgmSpecificOpsControlPointCharacteristic = service.getCharacteristic(CGM_OPS_CONTROL_POINT_UUID);
|
||||
recordAccessControlPointCharacteristic = service.getCharacteristic(RACP_UUID);
|
||||
}
|
||||
return mCGMMeasurementCharacteristic != null
|
||||
&& mCGMSpecificOpsControlPointCharacteristic != null
|
||||
&& mRecordAccessControlPointCharacteristic != null;
|
||||
return cgmMeasurementCharacteristic != null
|
||||
&& cgmSpecificOpsControlPointCharacteristic != null
|
||||
&& recordAccessControlPointCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeviceDisconnected() {
|
||||
super.onDeviceDisconnected();
|
||||
mCGMStatusCharacteristic = null;
|
||||
mCGMFeatureCharacteristic = null;
|
||||
mCGMMeasurementCharacteristic = null;
|
||||
mCGMSpecificOpsControlPointCharacteristic = null;
|
||||
mRecordAccessControlPointCharacteristic = null;
|
||||
cgmStatusCharacteristic = null;
|
||||
cgmFeatureCharacteristic = null;
|
||||
cgmMeasurementCharacteristic = null;
|
||||
cgmSpecificOpsControlPointCharacteristic = null;
|
||||
recordAccessControlPointCharacteristic = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a list of CGM records obtained from this device. The key in the array is the
|
||||
*/
|
||||
public SparseArray<CGMSRecord> getRecords() {
|
||||
return mRecords;
|
||||
SparseArray<CGMSRecord> getRecords() {
|
||||
return records;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the records list locally
|
||||
*/
|
||||
public void clear() {
|
||||
mRecords.clear();
|
||||
mCallbacks.onDatasetCleared(getBluetoothDevice());
|
||||
void clear() {
|
||||
records.clear();
|
||||
callbacks.onDataSetCleared(getBluetoothDevice());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -340,14 +349,14 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
* The data will be returned to Glucose Measurement characteristic as a notification followed by
|
||||
* Record Access Control Point indication with status code Success or other in case of error.
|
||||
*/
|
||||
public void getLastRecord() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
void getLastRecord() {
|
||||
if (recordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted(getBluetoothDevice());
|
||||
mRecordAccessRequestInProgress = true;
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportLastStoredRecord())
|
||||
callbacks.onOperationStarted(getBluetoothDevice());
|
||||
recordAccessRequestInProgress = true;
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportLastStoredRecord())
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
|
||||
.enqueue();
|
||||
}
|
||||
@@ -357,14 +366,14 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
* The data will be returned to Glucose Measurement characteristic as a notification followed by
|
||||
* Record Access Control Point indication with status code Success or other in case of error.
|
||||
*/
|
||||
public void getFirstRecord() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
void getFirstRecord() {
|
||||
if (recordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted(getBluetoothDevice());
|
||||
mRecordAccessRequestInProgress = true;
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportFirstStoredRecord())
|
||||
callbacks.onOperationStarted(getBluetoothDevice());
|
||||
recordAccessRequestInProgress = true;
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportFirstStoredRecord())
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
|
||||
.enqueue();
|
||||
}
|
||||
@@ -372,11 +381,11 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
/**
|
||||
* Sends abort operation signal to the device.
|
||||
*/
|
||||
public void abort() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
void abort() {
|
||||
if (recordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.abortOperation())
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.abortOperation())
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
|
||||
.enqueue();
|
||||
}
|
||||
@@ -387,14 +396,14 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
* The data will be returned to Glucose Measurement characteristic as a notification followed by
|
||||
* Record Access Control Point indication with status code Success or other in case of error.
|
||||
*/
|
||||
public void getAllRecords() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
void getAllRecords() {
|
||||
if (recordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted(getBluetoothDevice());
|
||||
mRecordAccessRequestInProgress = true;
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportNumberOfAllStoredRecords())
|
||||
callbacks.onOperationStarted(getBluetoothDevice());
|
||||
recordAccessRequestInProgress = true;
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportNumberOfAllStoredRecords())
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
|
||||
.enqueue();
|
||||
}
|
||||
@@ -405,19 +414,19 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
* The data will be returned to Glucose Measurement characteristic as a notification followed by
|
||||
* Record Access Control Point indication with status code Success or other in case of error.
|
||||
*/
|
||||
public void refreshRecords() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
void refreshRecords() {
|
||||
if (recordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
if (mRecords.size() == 0) {
|
||||
if (records.size() == 0) {
|
||||
getAllRecords();
|
||||
} else {
|
||||
mCallbacks.onOperationStarted(getBluetoothDevice());
|
||||
callbacks.onOperationStarted(getBluetoothDevice());
|
||||
|
||||
// Obtain the last sequence number
|
||||
final int sequenceNumber = mRecords.keyAt(mRecords.size() - 1) + 1;
|
||||
mRecordAccessRequestInProgress = true;
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportStoredRecordsGreaterThenOrEqualTo(sequenceNumber))
|
||||
final int sequenceNumber = records.keyAt(records.size() - 1) + 1;
|
||||
recordAccessRequestInProgress = true;
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportStoredRecordsGreaterThenOrEqualTo(sequenceNumber))
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
|
||||
.enqueue();
|
||||
// Info:
|
||||
@@ -431,13 +440,13 @@ public class CGMSManager extends BatteryManager<CGMSManagerCallbacks> {
|
||||
* This feature is not supported by the CGMS sample from the SDK, so monitor will answer with
|
||||
* the Op Code Not Supported error.
|
||||
*/
|
||||
public void deleteAllRecords() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
void deleteAllRecords() {
|
||||
if (recordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted(getBluetoothDevice());
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.deleteAllStoredRecords())
|
||||
callbacks.onOperationStarted(getBluetoothDevice());
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.deleteAllStoredRecords())
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
|
||||
.enqueue();
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ import androidx.annotation.NonNull;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.battery.BatteryManagerCallbacks;
|
||||
|
||||
public interface CGMSManagerCallbacks extends BatteryManagerCallbacks {
|
||||
interface CGMSManagerCallbacks extends BatteryManagerCallbacks {
|
||||
|
||||
void onCGMValueReceived(@NonNull final BluetoothDevice device, final CGMSRecord record);
|
||||
void onCGMValueReceived(@NonNull final BluetoothDevice device, @NonNull final CGMSRecord record);
|
||||
|
||||
void onOperationStarted(final @NonNull BluetoothDevice device);
|
||||
|
||||
@@ -41,7 +41,7 @@ public interface CGMSManagerCallbacks extends BatteryManagerCallbacks {
|
||||
|
||||
void onOperationNotSupported(final @NonNull BluetoothDevice device);
|
||||
|
||||
void onDatasetCleared(final @NonNull BluetoothDevice device);
|
||||
void onDataSetCleared(final @NonNull BluetoothDevice device);
|
||||
|
||||
void onNumberOfRecordsRequested(final @NonNull BluetoothDevice device, final int value);
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@ import android.os.Parcelable;
|
||||
|
||||
class CGMSRecord implements Parcelable{
|
||||
/** Record sequence number. */
|
||||
protected int sequenceNumber;
|
||||
int sequenceNumber;
|
||||
/** The base time of the measurement (start time + sequenceNumber of minutes). */
|
||||
protected long timestamp;
|
||||
long timestamp;
|
||||
/** The glucose concentration in mg/dL. */
|
||||
protected float glucoseConcentration;
|
||||
float glucoseConcentration;
|
||||
|
||||
CGMSRecord(final int sequenceNumber, final float glucoseConcentration, final long timestamp) {
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
|
||||
@@ -13,62 +13,65 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
|
||||
public class CGMSRecordsAdapter extends BaseAdapter {
|
||||
private final static SimpleDateFormat mTimeFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm", Locale.US);
|
||||
class CGMSRecordsAdapter extends BaseAdapter {
|
||||
private final static SimpleDateFormat timeFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm", Locale.US);
|
||||
|
||||
private List<CGMSRecord> mRecords;
|
||||
private LayoutInflater mInflater;
|
||||
private List<CGMSRecord> records;
|
||||
private LayoutInflater inflater;
|
||||
|
||||
public CGMSRecordsAdapter(final Context context) {
|
||||
mRecords = new ArrayList<>();
|
||||
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
CGMSRecordsAdapter(@NonNull final Context context) {
|
||||
records = new ArrayList<>();
|
||||
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mRecords.size();
|
||||
return records.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int i) {
|
||||
public Object getItem(final int i) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int i) {
|
||||
public long getItemId(final int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
public View getView(final int position, @Nullable final View convertView, @NonNull final ViewGroup parent) {
|
||||
ViewHolder viewHolder;
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.activity_feature_cgms_item, parent, false);
|
||||
View view = convertView;
|
||||
if (view == null) {
|
||||
view = inflater.inflate(R.layout.activity_feature_cgms_item, parent, false);
|
||||
viewHolder = new ViewHolder();
|
||||
viewHolder.concentration = convertView.findViewById(R.id.cgms_concentration);
|
||||
viewHolder.time = convertView.findViewById(R.id.time);
|
||||
viewHolder.details = convertView.findViewById(R.id.details);
|
||||
convertView.setTag(viewHolder);
|
||||
viewHolder.concentration = view.findViewById(R.id.cgms_concentration);
|
||||
viewHolder.time = view.findViewById(R.id.time);
|
||||
viewHolder.details = view.findViewById(R.id.details);
|
||||
view.setTag(viewHolder);
|
||||
} else {
|
||||
viewHolder = (ViewHolder) convertView.getTag();
|
||||
viewHolder = (ViewHolder) view.getTag();
|
||||
}
|
||||
|
||||
final CGMSRecord cgmsRecord = mRecords.get(position);
|
||||
final CGMSRecord cgmsRecord = records.get(position);
|
||||
viewHolder.concentration.setText(String.valueOf(cgmsRecord.glucoseConcentration));
|
||||
viewHolder.details.setText(viewHolder.details.getResources().getString(R.string.cgms_details, cgmsRecord.sequenceNumber));
|
||||
viewHolder.time.setText(mTimeFormat.format(new Date(cgmsRecord.timestamp)));
|
||||
viewHolder.time.setText(timeFormat.format(new Date(cgmsRecord.timestamp)));
|
||||
|
||||
return convertView;
|
||||
return view;
|
||||
}
|
||||
|
||||
public void addItem(final CGMSRecord record) {
|
||||
mRecords.add(record);
|
||||
void addItem(final CGMSRecord record) {
|
||||
records.add(record);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
mRecords.clear();
|
||||
void clear() {
|
||||
records.clear();
|
||||
}
|
||||
|
||||
private static class ViewHolder {
|
||||
|
||||
@@ -42,29 +42,29 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
private final static int OPEN_ACTIVITY_REQ = 0;
|
||||
private final static int DISCONNECT_REQ = 1;
|
||||
|
||||
private CGMSManager mManager;
|
||||
private final LocalBinder mBinder = new CGMSBinder();
|
||||
private CGMSManager manager;
|
||||
private final LocalBinder binder = new CGMSBinder();
|
||||
|
||||
/**
|
||||
* This local binder is an interface for the bonded activity to operate with the RSC sensor
|
||||
*/
|
||||
|
||||
public class CGMSBinder extends LocalBinder {
|
||||
class CGMSBinder extends LocalBinder {
|
||||
/**
|
||||
* Returns all records as a sparse array where sequence number is the key.
|
||||
*
|
||||
* @return the records list
|
||||
*/
|
||||
public SparseArray<CGMSRecord> getRecords() {
|
||||
return mManager.getRecords();
|
||||
SparseArray<CGMSRecord> getRecords() {
|
||||
return manager.getRecords();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the records list locally
|
||||
*/
|
||||
public void clear() {
|
||||
if (mManager != null)
|
||||
mManager.clear();
|
||||
void clear() {
|
||||
if (manager != null)
|
||||
manager.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,9 +72,9 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
* The data will be returned to Glucose Measurement characteristic as a notification followed by Record Access Control
|
||||
* Point indication with status code ({@link CGMSManager# RESPONSE_SUCCESS} or other in case of error.
|
||||
*/
|
||||
public void getFirstRecord() {
|
||||
if (mManager != null)
|
||||
mManager.getFirstRecord();
|
||||
void getFirstRecord() {
|
||||
if (manager != null)
|
||||
manager.getFirstRecord();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,9 +82,9 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
* The data will be returned to Glucose Measurement characteristic as a notification followed by Record Access
|
||||
* Control Point indication with status code Success or other in case of error.
|
||||
*/
|
||||
public void getLastRecord() {
|
||||
if (mManager != null)
|
||||
mManager.getLastRecord();
|
||||
void getLastRecord() {
|
||||
if (manager != null)
|
||||
manager.getLastRecord();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,9 +93,9 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
* The data will be returned to Glucose Measurement characteristic as a series of notifications followed
|
||||
* by Record Access Control Point indication with status code Success or other in case of error.
|
||||
*/
|
||||
public void getAllRecords() {
|
||||
if (mManager != null)
|
||||
mManager.getAllRecords();
|
||||
void getAllRecords() {
|
||||
if (manager != null)
|
||||
manager.getAllRecords();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,36 +104,36 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
* characteristic as a series of notifications followed by Record Access Control Point
|
||||
* indication with status code Success or other in case of error.
|
||||
*/
|
||||
public void refreshRecords() {
|
||||
if (mManager != null)
|
||||
mManager.refreshRecords();
|
||||
void refreshRecords() {
|
||||
if (manager != null)
|
||||
manager.refreshRecords();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends abort operation signal to the device
|
||||
*/
|
||||
public void abort() {
|
||||
if (mManager != null)
|
||||
mManager.abort();
|
||||
void abort() {
|
||||
if (manager != null)
|
||||
manager.abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Delete op code with All stored records parameter. This method may not be supported by the SDK sample.
|
||||
*/
|
||||
public void deleteAllRecords() {
|
||||
if (mManager != null)
|
||||
mManager.deleteAllRecords();
|
||||
void deleteAllRecords() {
|
||||
if (manager != null)
|
||||
manager.deleteAllRecords();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocalBinder getBinder() {
|
||||
return mBinder;
|
||||
return binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggableBleManager<CGMSManagerCallbacks> initializeManager() {
|
||||
return mManager = new CGMSManager(this);
|
||||
return manager = new CGMSManager(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -142,14 +142,14 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
super.onCreate();
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_DISCONNECT);
|
||||
registerReceiver(mDisconnectActionBroadcastReceiver, filter);
|
||||
registerReceiver(disconnectActionBroadcastReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
// when user has disconnected from the sensor, we have to cancel the notification that we've created some milliseconds before using unbindService
|
||||
stopForegroundService();
|
||||
unregisterReceiver(mDisconnectActionBroadcastReceiver);
|
||||
unregisterReceiver(disconnectActionBroadcastReceiver);
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
@@ -199,6 +199,7 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
* f.e. <code><string name="name">%s is connected</string></code>
|
||||
* @param defaults signals that will be used to notify the user
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private Notification createNotification(final int messageResId, final int defaults) {
|
||||
final Intent parentIntent = new Intent(this, FeaturesActivity.class);
|
||||
parentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
@@ -230,7 +231,7 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
/**
|
||||
* This broadcast receiver listens for {@link #ACTION_DISCONNECT} that may be fired by pressing Disconnect action button on the notification.
|
||||
*/
|
||||
private final BroadcastReceiver mDisconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver disconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
Logger.i(getLogSession(), "[Notification] Disconnect action pressed");
|
||||
@@ -242,7 +243,7 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCGMValueReceived(@NonNull final BluetoothDevice device, final CGMSRecord record) {
|
||||
public void onCGMValueReceived(@NonNull final BluetoothDevice device, @NonNull final CGMSRecord record) {
|
||||
final Intent broadcast = new Intent(BROADCAST_NEW_CGMS_VALUE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_CGMS_RECORD, record);
|
||||
@@ -290,7 +291,7 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDatasetCleared(@NonNull final BluetoothDevice device) {
|
||||
public void onDataSetCleared(@NonNull final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_DATA_SET_CLEAR);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
@@ -30,6 +30,8 @@ import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import android.view.Menu;
|
||||
import android.widget.TextView;
|
||||
@@ -44,15 +46,15 @@ import no.nordicsemi.android.nrftoolbox.profile.BleProfileService;
|
||||
import no.nordicsemi.android.nrftoolbox.profile.BleProfileServiceReadyActivity;
|
||||
|
||||
public class CSCActivity extends BleProfileServiceReadyActivity<CSCService.CSCBinder> {
|
||||
private TextView mSpeedView;
|
||||
private TextView mSpeedUnitView;
|
||||
private TextView mCadenceView;
|
||||
private TextView mDistanceView;
|
||||
private TextView mDistanceUnitView;
|
||||
private TextView mTotalDistanceView;
|
||||
private TextView mTotalDistanceUnitView;
|
||||
private TextView mGearRatioView;
|
||||
private TextView mBatteryLevelView;
|
||||
private TextView speedView;
|
||||
private TextView speedUnitView;
|
||||
private TextView cadenceView;
|
||||
private TextView distanceView;
|
||||
private TextView distanceUnitView;
|
||||
private TextView totalDistanceView;
|
||||
private TextView totalDistanceUnitView;
|
||||
private TextView gearRatioView;
|
||||
private TextView batteryLevelView;
|
||||
|
||||
@Override
|
||||
protected void onCreateView(final Bundle savedInstanceState) {
|
||||
@@ -62,25 +64,25 @@ public class CSCActivity extends BleProfileServiceReadyActivity<CSCService.CSCBi
|
||||
|
||||
@Override
|
||||
protected void onInitialize(final Bundle savedInstanceState) {
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, makeIntentFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
|
||||
}
|
||||
|
||||
private void setGui() {
|
||||
mSpeedView = findViewById(R.id.speed);
|
||||
mSpeedUnitView = findViewById(R.id.speed_unit);
|
||||
mCadenceView = findViewById(R.id.cadence);
|
||||
mDistanceView = findViewById(R.id.distance);
|
||||
mDistanceUnitView = findViewById(R.id.distance_unit);
|
||||
mTotalDistanceView = findViewById(R.id.distance_total);
|
||||
mTotalDistanceUnitView = findViewById(R.id.distance_total_unit);
|
||||
mGearRatioView = findViewById(R.id.ratio);
|
||||
mBatteryLevelView = findViewById(R.id.battery);
|
||||
speedView = findViewById(R.id.speed);
|
||||
speedUnitView = findViewById(R.id.speed_unit);
|
||||
cadenceView = findViewById(R.id.cadence);
|
||||
distanceView = findViewById(R.id.distance);
|
||||
distanceUnitView = findViewById(R.id.distance_unit);
|
||||
totalDistanceView = findViewById(R.id.distance_total);
|
||||
totalDistanceUnitView = findViewById(R.id.distance_total_unit);
|
||||
gearRatioView = findViewById(R.id.ratio);
|
||||
batteryLevelView = findViewById(R.id.battery);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,12 +93,12 @@ public class CSCActivity extends BleProfileServiceReadyActivity<CSCService.CSCBi
|
||||
|
||||
@Override
|
||||
protected void setDefaultUI() {
|
||||
mSpeedView.setText(R.string.not_available_value);
|
||||
mCadenceView.setText(R.string.not_available_value);
|
||||
mDistanceView.setText(R.string.not_available_value);
|
||||
mTotalDistanceView.setText(R.string.not_available_value);
|
||||
mGearRatioView.setText(R.string.not_available_value);
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
speedView.setText(R.string.not_available_value);
|
||||
cadenceView.setText(R.string.not_available_value);
|
||||
distanceView.setText(R.string.not_available_value);
|
||||
totalDistanceView.setText(R.string.not_available_value);
|
||||
gearRatioView.setText(R.string.not_available_value);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
|
||||
setUnits();
|
||||
}
|
||||
@@ -107,19 +109,19 @@ public class CSCActivity extends BleProfileServiceReadyActivity<CSCService.CSCBi
|
||||
|
||||
switch (unit) {
|
||||
case SettingsFragment.SETTINGS_UNIT_M_S: // [m/s]
|
||||
mSpeedUnitView.setText(R.string.csc_speed_unit_m_s);
|
||||
mDistanceUnitView.setText(R.string.csc_distance_unit_m);
|
||||
mTotalDistanceUnitView.setText(R.string.csc_total_distance_unit_km);
|
||||
speedUnitView.setText(R.string.csc_speed_unit_m_s);
|
||||
distanceUnitView.setText(R.string.csc_distance_unit_m);
|
||||
totalDistanceUnitView.setText(R.string.csc_total_distance_unit_km);
|
||||
break;
|
||||
case SettingsFragment.SETTINGS_UNIT_KM_H: // [km/h]
|
||||
mSpeedUnitView.setText(R.string.csc_speed_unit_km_h);
|
||||
mDistanceUnitView.setText(R.string.csc_distance_unit_m);
|
||||
mTotalDistanceUnitView.setText(R.string.csc_total_distance_unit_km);
|
||||
speedUnitView.setText(R.string.csc_speed_unit_km_h);
|
||||
distanceUnitView.setText(R.string.csc_distance_unit_m);
|
||||
totalDistanceUnitView.setText(R.string.csc_total_distance_unit_km);
|
||||
break;
|
||||
case SettingsFragment.SETTINGS_UNIT_MPH: // [mph]
|
||||
mSpeedUnitView.setText(R.string.csc_speed_unit_mph);
|
||||
mDistanceUnitView.setText(R.string.csc_distance_unit_yd);
|
||||
mTotalDistanceUnitView.setText(R.string.csc_total_distance_unit_mile);
|
||||
speedUnitView.setText(R.string.csc_speed_unit_mph);
|
||||
distanceUnitView.setText(R.string.csc_distance_unit_yd);
|
||||
totalDistanceUnitView.setText(R.string.csc_total_distance_unit_mile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -177,14 +179,14 @@ public class CSCActivity extends BleProfileServiceReadyActivity<CSCService.CSCBi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(@NonNull final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// not used
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
}
|
||||
|
||||
private void onMeasurementReceived(final BluetoothDevice device, float speed, float distance, float totalDistance) {
|
||||
@@ -197,42 +199,42 @@ public class CSCActivity extends BleProfileServiceReadyActivity<CSCService.CSCBi
|
||||
// pass through intended
|
||||
case SettingsFragment.SETTINGS_UNIT_M_S:
|
||||
if (distance < 1000) { // 1 km in m
|
||||
mDistanceView.setText(String.format(Locale.US, "%.0f", distance));
|
||||
mDistanceUnitView.setText(R.string.csc_distance_unit_m);
|
||||
distanceView.setText(String.format(Locale.US, "%.0f", distance));
|
||||
distanceUnitView.setText(R.string.csc_distance_unit_m);
|
||||
} else {
|
||||
mDistanceView.setText(String.format(Locale.US, "%.2f", distance / 1000.0f));
|
||||
mDistanceUnitView.setText(R.string.csc_distance_unit_km);
|
||||
distanceView.setText(String.format(Locale.US, "%.2f", distance / 1000.0f));
|
||||
distanceUnitView.setText(R.string.csc_distance_unit_km);
|
||||
}
|
||||
|
||||
mTotalDistanceView.setText(String.format(Locale.US, "%.2f", totalDistance / 1000.0f));
|
||||
totalDistanceView.setText(String.format(Locale.US, "%.2f", totalDistance / 1000.0f));
|
||||
break;
|
||||
case SettingsFragment.SETTINGS_UNIT_MPH:
|
||||
speed = speed * 2.2369f;
|
||||
if (distance < 1760) { // 1 mile in yrs
|
||||
mDistanceView.setText(String.format(Locale.US, "%.0f", distance));
|
||||
mDistanceUnitView.setText(R.string.csc_distance_unit_yd);
|
||||
distanceView.setText(String.format(Locale.US, "%.0f", distance));
|
||||
distanceUnitView.setText(R.string.csc_distance_unit_yd);
|
||||
} else {
|
||||
mDistanceView.setText(String.format(Locale.US, "%.2f", distance / 1760.0f));
|
||||
mDistanceUnitView.setText(R.string.csc_distance_unit_mile);
|
||||
distanceView.setText(String.format(Locale.US, "%.2f", distance / 1760.0f));
|
||||
distanceUnitView.setText(R.string.csc_distance_unit_mile);
|
||||
}
|
||||
|
||||
mTotalDistanceView.setText(String.format(Locale.US, "%.2f", totalDistance / 1609.31f));
|
||||
totalDistanceView.setText(String.format(Locale.US, "%.2f", totalDistance / 1609.31f));
|
||||
break;
|
||||
}
|
||||
|
||||
mSpeedView.setText(String.format(Locale.US, "%.1f", speed));
|
||||
speedView.setText(String.format(Locale.US, "%.1f", speed));
|
||||
}
|
||||
|
||||
private void onGearRatioUpdate(final BluetoothDevice device, final int cadence, final float ratio) {
|
||||
mCadenceView.setText(String.format(Locale.US, "%d", cadence));
|
||||
mGearRatioView.setText(String.format(Locale.US, "%.1f", ratio));
|
||||
cadenceView.setText(String.format(Locale.US, "%d", cadence));
|
||||
gearRatioView.setText(String.format(Locale.US, "%.1f", ratio));
|
||||
}
|
||||
|
||||
public void onBatteryLevelChanged(final BluetoothDevice device, final int value) {
|
||||
mBatteryLevelView.setText(getString(R.string.battery, value));
|
||||
batteryLevelView.setText(getString(R.string.battery, value));
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
|
||||
@@ -29,6 +29,8 @@ import android.bluetooth.BluetoothGattService;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import androidx.annotation.FloatRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -43,12 +45,12 @@ import no.nordicsemi.android.nrftoolbox.parser.CSCMeasurementParser;
|
||||
|
||||
public class CSCManager extends BatteryManager<CSCManagerCallbacks> {
|
||||
/** Cycling Speed and Cadence service UUID. */
|
||||
public final static UUID CYCLING_SPEED_AND_CADENCE_SERVICE_UUID = UUID.fromString("00001816-0000-1000-8000-00805f9b34fb");
|
||||
final static UUID CYCLING_SPEED_AND_CADENCE_SERVICE_UUID = UUID.fromString("00001816-0000-1000-8000-00805f9b34fb");
|
||||
/** Cycling Speed and Cadence Measurement characteristic UUID. */
|
||||
private final static UUID CSC_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A5B-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private final SharedPreferences preferences;
|
||||
private BluetoothGattCharacteristic mCSCMeasurementCharacteristic;
|
||||
private BluetoothGattCharacteristic cscMeasurementCharacteristic;
|
||||
|
||||
CSCManager(final Context context) {
|
||||
super(context);
|
||||
@@ -58,21 +60,21 @@ public class CSCManager extends BatteryManager<CSCManagerCallbacks> {
|
||||
@NonNull
|
||||
@Override
|
||||
protected BatteryManagerGattCallback getGattCallback() {
|
||||
return mGattCallback;
|
||||
return gattCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* BluetoothGatt callbacks for connection/disconnection, service discovery,
|
||||
* receiving indication, etc.
|
||||
*/
|
||||
private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
|
||||
private final BatteryManagerGattCallback gattCallback = new BatteryManagerGattCallback() {
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
super.initialize();
|
||||
|
||||
// CSC characteristic is required
|
||||
setNotificationCallback(mCSCMeasurementCharacteristic)
|
||||
setNotificationCallback(cscMeasurementCharacteristic)
|
||||
.with(new CyclingSpeedAndCadenceMeasurementDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, final @NonNull Data data) {
|
||||
@@ -90,38 +92,41 @@ public class CSCManager extends BatteryManager<CSCManagerCallbacks> {
|
||||
|
||||
@Override
|
||||
public void onDistanceChanged(@NonNull final BluetoothDevice device,
|
||||
final float totalDistance, final float distance, final float speed) {
|
||||
mCallbacks.onDistanceChanged(device, totalDistance, distance, speed);
|
||||
@FloatRange(from = 0) final float totalDistance,
|
||||
@FloatRange(from = 0) final float distance,
|
||||
@FloatRange(from = 0) final float speed) {
|
||||
callbacks.onDistanceChanged(device, totalDistance, distance, speed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrankDataChanged(@NonNull final BluetoothDevice device,
|
||||
final float crankCadence, final float gearRatio) {
|
||||
mCallbacks.onCrankDataChanged(device, crankCadence, gearRatio);
|
||||
@FloatRange(from = 0) final float crankCadence,
|
||||
final float gearRatio) {
|
||||
callbacks.onCrankDataChanged(device, crankCadence, gearRatio);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInvalidDataReceived(@NonNull final BluetoothDevice device,
|
||||
final @NonNull Data data) {
|
||||
@NonNull final Data data) {
|
||||
log(Log.WARN, "Invalid CSC Measurement data received: " + data);
|
||||
}
|
||||
});
|
||||
enableNotifications(mCSCMeasurementCharacteristic).enqueue();
|
||||
enableNotifications(cscMeasurementCharacteristic).enqueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(CYCLING_SPEED_AND_CADENCE_SERVICE_UUID);
|
||||
if (service != null) {
|
||||
mCSCMeasurementCharacteristic = service.getCharacteristic(CSC_MEASUREMENT_CHARACTERISTIC_UUID);
|
||||
cscMeasurementCharacteristic = service.getCharacteristic(CSC_MEASUREMENT_CHARACTERISTIC_UUID);
|
||||
}
|
||||
return mCSCMeasurementCharacteristic != null;
|
||||
return cscMeasurementCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeviceDisconnected() {
|
||||
super.onDeviceDisconnected();
|
||||
mCSCMeasurementCharacteristic = null;
|
||||
cscMeasurementCharacteristic = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -73,8 +73,8 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
|
||||
private final static int OPEN_ACTIVITY_REQ = 0;
|
||||
private final static int DISCONNECT_REQ = 1;
|
||||
|
||||
private final LocalBinder mBinder = new CSCBinder();
|
||||
private CSCManager mManager;
|
||||
private final LocalBinder binder = new CSCBinder();
|
||||
private CSCManager manager;
|
||||
|
||||
/**
|
||||
* This local binder is an interface for the bonded activity to operate with the RSC sensor
|
||||
@@ -85,12 +85,12 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
|
||||
|
||||
@Override
|
||||
protected LocalBinder getBinder() {
|
||||
return mBinder;
|
||||
return binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggableBleManager<CSCManagerCallbacks> initializeManager() {
|
||||
return mManager = new CSCManager(this);
|
||||
return manager = new CSCManager(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,14 +99,14 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
|
||||
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_DISCONNECT);
|
||||
registerReceiver(mDisconnectActionBroadcastReceiver, filter);
|
||||
registerReceiver(disconnectActionBroadcastReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
// when user has disconnected from the sensor, we have to cancel the notification that we've created some milliseconds before using unbindService
|
||||
cancelNotification();
|
||||
unregisterReceiver(mDisconnectActionBroadcastReceiver);
|
||||
unregisterReceiver(disconnectActionBroadcastReceiver);
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
@@ -118,7 +118,7 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
|
||||
if (isConnected()) {
|
||||
// This method will read the Battery Level value, if possible and then try to enable battery notifications (if it has NOTIFY property).
|
||||
// If the Battery Level characteristic has only the NOTIFY property, it will only try to enable notifications.
|
||||
mManager.readBatteryLevelCharacteristic();
|
||||
manager.readBatteryLevelCharacteristic();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
|
||||
// When we are connected, but the application is not open, we are not really interested in battery level notifications.
|
||||
// But we will still be receiving other values, if enabled.
|
||||
if (isConnected())
|
||||
mManager.disableBatteryLevelCharacteristicNotifications();
|
||||
manager.disableBatteryLevelCharacteristicNotifications();
|
||||
startForegroundService();
|
||||
}
|
||||
|
||||
@@ -193,6 +193,7 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
|
||||
* f.e. <code><string name="name">%s is connected</string></code>
|
||||
* @param defaults
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private Notification createNotification(final int messageResId, final int defaults) {
|
||||
final Intent parentIntent = new Intent(this, FeaturesActivity.class);
|
||||
parentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
@@ -224,7 +225,7 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
|
||||
/**
|
||||
* This broadcast receiver listens for {@link #ACTION_DISCONNECT} that may be fired by pressing Disconnect action button on the notification.
|
||||
*/
|
||||
private final BroadcastReceiver mDisconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver disconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
Logger.i(getLogSession(), "[Notification] Disconnect action pressed");
|
||||
|
||||
@@ -111,33 +111,33 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
private static final int SELECT_FILE_REQ = 1;
|
||||
private static final int SELECT_INIT_FILE_REQ = 2;
|
||||
|
||||
private TextView mDeviceNameView;
|
||||
private TextView mFileNameView;
|
||||
private TextView mFileTypeView;
|
||||
private TextView mFileScopeView;
|
||||
private TextView mFileSizeView;
|
||||
private TextView mFileStatusView;
|
||||
private TextView mTextPercentage;
|
||||
private TextView mTextUploading;
|
||||
private ProgressBar mProgressBar;
|
||||
private TextView deviceNameView;
|
||||
private TextView fileNameView;
|
||||
private TextView fileTypeView;
|
||||
private TextView fileScopeView;
|
||||
private TextView fileSizeView;
|
||||
private TextView fileStatusView;
|
||||
private TextView textPercentage;
|
||||
private TextView textUploading;
|
||||
private ProgressBar progressBar;
|
||||
|
||||
private Button mSelectFileButton, mUploadButton, mConnectButton;
|
||||
private Button selectFileButton, uploadButton, connectButton;
|
||||
|
||||
private BluetoothDevice mSelectedDevice;
|
||||
private String mFilePath;
|
||||
private Uri mFileStreamUri;
|
||||
private String mInitFilePath;
|
||||
private Uri mInitFileStreamUri;
|
||||
private int mFileType;
|
||||
private int mFileTypeTmp; // This value is being used when user is selecting a file not to overwrite the old value (in case he/she will cancel selecting file)
|
||||
private Integer mScope;
|
||||
private boolean mStatusOk;
|
||||
private BluetoothDevice selectedDevice;
|
||||
private String filePath;
|
||||
private Uri fileStreamUri;
|
||||
private String initFilePath;
|
||||
private Uri initFileStreamUri;
|
||||
private int fileType;
|
||||
private int fileTypeTmp; // This value is being used when user is selecting a file not to overwrite the old value (in case he/she will cancel selecting file)
|
||||
private Integer scope;
|
||||
private boolean statusOk;
|
||||
/** Flag set to true in {@link #onRestart()} and to false in {@link #onPause()}. */
|
||||
private boolean mResumed;
|
||||
/** Flag set to true if DFU operation was completed while {@link #mResumed} was false. */
|
||||
private boolean mDfuCompleted;
|
||||
/** The error message received from DFU service while {@link #mResumed} was false. */
|
||||
private String mDfuError;
|
||||
private boolean resumed;
|
||||
/** Flag set to true if DFU operation was completed while {@link #resumed} was false. */
|
||||
private boolean dfuCompleted;
|
||||
/** The error message received from DFU service while {@link #resumed} was false. */
|
||||
private String dfuError;
|
||||
|
||||
/**
|
||||
* The progress listener receives events from the DFU Service.
|
||||
@@ -146,41 +146,41 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
* correct information after user comes back to the activity and this information can't be read from the service
|
||||
* as it might have been killed already (DFU completed or finished with error).
|
||||
*/
|
||||
private final DfuProgressListener mDfuProgressListener = new DfuProgressListenerAdapter() {
|
||||
private final DfuProgressListener dfuProgressListener = new DfuProgressListenerAdapter() {
|
||||
@Override
|
||||
public void onDeviceConnecting(final String deviceAddress) {
|
||||
mProgressBar.setIndeterminate(true);
|
||||
mTextPercentage.setText(R.string.dfu_status_connecting);
|
||||
public void onDeviceConnecting(@NonNull final String deviceAddress) {
|
||||
progressBar.setIndeterminate(true);
|
||||
textPercentage.setText(R.string.dfu_status_connecting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDfuProcessStarting(final String deviceAddress) {
|
||||
mProgressBar.setIndeterminate(true);
|
||||
mTextPercentage.setText(R.string.dfu_status_starting);
|
||||
public void onDfuProcessStarting(@NonNull final String deviceAddress) {
|
||||
progressBar.setIndeterminate(true);
|
||||
textPercentage.setText(R.string.dfu_status_starting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnablingDfuMode(final String deviceAddress) {
|
||||
mProgressBar.setIndeterminate(true);
|
||||
mTextPercentage.setText(R.string.dfu_status_switching_to_dfu);
|
||||
public void onEnablingDfuMode(@NonNull final String deviceAddress) {
|
||||
progressBar.setIndeterminate(true);
|
||||
textPercentage.setText(R.string.dfu_status_switching_to_dfu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFirmwareValidating(final String deviceAddress) {
|
||||
mProgressBar.setIndeterminate(true);
|
||||
mTextPercentage.setText(R.string.dfu_status_validating);
|
||||
public void onFirmwareValidating(@NonNull final String deviceAddress) {
|
||||
progressBar.setIndeterminate(true);
|
||||
textPercentage.setText(R.string.dfu_status_validating);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting(final String deviceAddress) {
|
||||
mProgressBar.setIndeterminate(true);
|
||||
mTextPercentage.setText(R.string.dfu_status_disconnecting);
|
||||
public void onDeviceDisconnecting(@NonNull final String deviceAddress) {
|
||||
progressBar.setIndeterminate(true);
|
||||
textPercentage.setText(R.string.dfu_status_disconnecting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDfuCompleted(final String deviceAddress) {
|
||||
mTextPercentage.setText(R.string.dfu_status_completed);
|
||||
if (mResumed) {
|
||||
public void onDfuCompleted(@NonNull final String deviceAddress) {
|
||||
textPercentage.setText(R.string.dfu_status_completed);
|
||||
if (resumed) {
|
||||
// let's wait a bit until we cancel the notification. When canceled immediately it will be recreated by service again.
|
||||
new Handler().postDelayed(() -> {
|
||||
onTransferCompleted();
|
||||
@@ -191,13 +191,13 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
}, 200);
|
||||
} else {
|
||||
// Save that the DFU process has finished
|
||||
mDfuCompleted = true;
|
||||
dfuCompleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDfuAborted(final String deviceAddress) {
|
||||
mTextPercentage.setText(R.string.dfu_status_aborted);
|
||||
public void onDfuAborted(@NonNull final String deviceAddress) {
|
||||
textPercentage.setText(R.string.dfu_status_aborted);
|
||||
// let's wait a bit until we cancel the notification. When canceled immediately it will be recreated by service again.
|
||||
new Handler().postDelayed(() -> {
|
||||
onUploadCanceled();
|
||||
@@ -209,19 +209,21 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(final String deviceAddress, final int percent, final float speed, final float avgSpeed, final int currentPart, final int partsTotal) {
|
||||
mProgressBar.setIndeterminate(false);
|
||||
mProgressBar.setProgress(percent);
|
||||
mTextPercentage.setText(getString(R.string.dfu_uploading_percentage, percent));
|
||||
public void onProgressChanged(@NonNull final String deviceAddress, final int percent,
|
||||
final float speed, final float avgSpeed,
|
||||
final int currentPart, final int partsTotal) {
|
||||
progressBar.setIndeterminate(false);
|
||||
progressBar.setProgress(percent);
|
||||
textPercentage.setText(getString(R.string.dfu_uploading_percentage, percent));
|
||||
if (partsTotal > 1)
|
||||
mTextUploading.setText(getString(R.string.dfu_status_uploading_part, currentPart, partsTotal));
|
||||
textUploading.setText(getString(R.string.dfu_status_uploading_part, currentPart, partsTotal));
|
||||
else
|
||||
mTextUploading.setText(R.string.dfu_status_uploading);
|
||||
textUploading.setText(R.string.dfu_status_uploading);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final String deviceAddress, final int error, final int errorType, final String message) {
|
||||
if (mResumed) {
|
||||
public void onError(@NonNull final String deviceAddress, final int error, final int errorType, final String message) {
|
||||
if (resumed) {
|
||||
showErrorMessage(message);
|
||||
|
||||
// We have to wait a bit before canceling notification. This is called before DfuService creates the last notification.
|
||||
@@ -231,7 +233,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
manager.cancel(DfuService.NOTIFICATION_ID);
|
||||
}, 200);
|
||||
} else {
|
||||
mDfuError = message;
|
||||
dfuError = message;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -257,45 +259,45 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
}
|
||||
|
||||
// restore saved state
|
||||
mFileType = DfuService.TYPE_AUTO; // Default
|
||||
fileType = DfuService.TYPE_AUTO; // Default
|
||||
if (savedInstanceState != null) {
|
||||
mFileType = savedInstanceState.getInt(DATA_FILE_TYPE);
|
||||
mFileTypeTmp = savedInstanceState.getInt(DATA_FILE_TYPE_TMP);
|
||||
mFilePath = savedInstanceState.getString(DATA_FILE_PATH);
|
||||
mFileStreamUri = savedInstanceState.getParcelable(DATA_FILE_STREAM);
|
||||
mInitFilePath = savedInstanceState.getString(DATA_INIT_FILE_PATH);
|
||||
mInitFileStreamUri = savedInstanceState.getParcelable(DATA_INIT_FILE_STREAM);
|
||||
mSelectedDevice = savedInstanceState.getParcelable(DATA_DEVICE);
|
||||
mStatusOk = mStatusOk || savedInstanceState.getBoolean(DATA_STATUS);
|
||||
mScope = savedInstanceState.containsKey(DATA_SCOPE) ? savedInstanceState.getInt(DATA_SCOPE) : null;
|
||||
mUploadButton.setEnabled(mSelectedDevice != null && mStatusOk);
|
||||
mDfuCompleted = savedInstanceState.getBoolean(DATA_DFU_COMPLETED);
|
||||
mDfuError = savedInstanceState.getString(DATA_DFU_ERROR);
|
||||
fileType = savedInstanceState.getInt(DATA_FILE_TYPE);
|
||||
fileTypeTmp = savedInstanceState.getInt(DATA_FILE_TYPE_TMP);
|
||||
filePath = savedInstanceState.getString(DATA_FILE_PATH);
|
||||
fileStreamUri = savedInstanceState.getParcelable(DATA_FILE_STREAM);
|
||||
initFilePath = savedInstanceState.getString(DATA_INIT_FILE_PATH);
|
||||
initFileStreamUri = savedInstanceState.getParcelable(DATA_INIT_FILE_STREAM);
|
||||
selectedDevice = savedInstanceState.getParcelable(DATA_DEVICE);
|
||||
statusOk = statusOk || savedInstanceState.getBoolean(DATA_STATUS);
|
||||
scope = savedInstanceState.containsKey(DATA_SCOPE) ? savedInstanceState.getInt(DATA_SCOPE) : null;
|
||||
uploadButton.setEnabled(selectedDevice != null && statusOk);
|
||||
dfuCompleted = savedInstanceState.getBoolean(DATA_DFU_COMPLETED);
|
||||
dfuError = savedInstanceState.getString(DATA_DFU_ERROR);
|
||||
}
|
||||
|
||||
DfuServiceListenerHelper.registerProgressListener(this, mDfuProgressListener);
|
||||
DfuServiceListenerHelper.registerProgressListener(this, dfuProgressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
DfuServiceListenerHelper.unregisterProgressListener(this, mDfuProgressListener);
|
||||
DfuServiceListenerHelper.unregisterProgressListener(this, dfuProgressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(final Bundle outState) {
|
||||
protected void onSaveInstanceState(@NonNull final Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt(DATA_FILE_TYPE, mFileType);
|
||||
outState.putInt(DATA_FILE_TYPE_TMP, mFileTypeTmp);
|
||||
outState.putString(DATA_FILE_PATH, mFilePath);
|
||||
outState.putParcelable(DATA_FILE_STREAM, mFileStreamUri);
|
||||
outState.putString(DATA_INIT_FILE_PATH, mInitFilePath);
|
||||
outState.putParcelable(DATA_INIT_FILE_STREAM, mInitFileStreamUri);
|
||||
outState.putParcelable(DATA_DEVICE, mSelectedDevice);
|
||||
outState.putBoolean(DATA_STATUS, mStatusOk);
|
||||
if (mScope != null) outState.putInt(DATA_SCOPE, mScope);
|
||||
outState.putBoolean(DATA_DFU_COMPLETED, mDfuCompleted);
|
||||
outState.putString(DATA_DFU_ERROR, mDfuError);
|
||||
outState.putInt(DATA_FILE_TYPE, fileType);
|
||||
outState.putInt(DATA_FILE_TYPE_TMP, fileTypeTmp);
|
||||
outState.putString(DATA_FILE_PATH, filePath);
|
||||
outState.putParcelable(DATA_FILE_STREAM, fileStreamUri);
|
||||
outState.putString(DATA_INIT_FILE_PATH, initFilePath);
|
||||
outState.putParcelable(DATA_INIT_FILE_STREAM, initFileStreamUri);
|
||||
outState.putParcelable(DATA_DEVICE, selectedDevice);
|
||||
outState.putBoolean(DATA_STATUS, statusOk);
|
||||
if (scope != null) outState.putInt(DATA_SCOPE, scope);
|
||||
outState.putBoolean(DATA_DFU_COMPLETED, dfuCompleted);
|
||||
outState.putString(DATA_DFU_ERROR, dfuError);
|
||||
}
|
||||
|
||||
private void setGUI() {
|
||||
@@ -303,29 +305,29 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
mDeviceNameView = findViewById(R.id.device_name);
|
||||
mFileNameView = findViewById(R.id.file_name);
|
||||
mFileTypeView = findViewById(R.id.file_type);
|
||||
mFileScopeView = findViewById(R.id.file_scope);
|
||||
mFileSizeView = findViewById(R.id.file_size);
|
||||
mFileStatusView = findViewById(R.id.file_status);
|
||||
mSelectFileButton = findViewById(R.id.action_select_file);
|
||||
mUploadButton = findViewById(R.id.action_upload);
|
||||
mConnectButton = findViewById(R.id.action_connect);
|
||||
mTextPercentage = findViewById(R.id.textviewProgress);
|
||||
mTextUploading = findViewById(R.id.textviewUploading);
|
||||
mProgressBar = findViewById(R.id.progressbar_file);
|
||||
deviceNameView = findViewById(R.id.device_name);
|
||||
fileNameView = findViewById(R.id.file_name);
|
||||
fileTypeView = findViewById(R.id.file_type);
|
||||
fileScopeView = findViewById(R.id.file_scope);
|
||||
fileSizeView = findViewById(R.id.file_size);
|
||||
fileStatusView = findViewById(R.id.file_status);
|
||||
selectFileButton = findViewById(R.id.action_select_file);
|
||||
uploadButton = findViewById(R.id.action_upload);
|
||||
connectButton = findViewById(R.id.action_connect);
|
||||
textPercentage = findViewById(R.id.textviewProgress);
|
||||
textUploading = findViewById(R.id.textviewUploading);
|
||||
progressBar = findViewById(R.id.progressbar_file);
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
if (isDfuServiceRunning()) {
|
||||
// Restore image file information
|
||||
mDeviceNameView.setText(preferences.getString(PREFS_DEVICE_NAME, ""));
|
||||
mFileNameView.setText(preferences.getString(PREFS_FILE_NAME, ""));
|
||||
mFileTypeView.setText(preferences.getString(PREFS_FILE_TYPE, ""));
|
||||
mFileScopeView.setText(preferences.getString(PREFS_FILE_SCOPE, ""));
|
||||
mFileSizeView.setText(preferences.getString(PREFS_FILE_SIZE, ""));
|
||||
mFileStatusView.setText(R.string.dfu_file_status_ok);
|
||||
mStatusOk = true;
|
||||
deviceNameView.setText(preferences.getString(PREFS_DEVICE_NAME, ""));
|
||||
fileNameView.setText(preferences.getString(PREFS_FILE_NAME, ""));
|
||||
fileTypeView.setText(preferences.getString(PREFS_FILE_TYPE, ""));
|
||||
fileScopeView.setText(preferences.getString(PREFS_FILE_SCOPE, ""));
|
||||
fileSizeView.setText(preferences.getString(PREFS_FILE_SIZE, ""));
|
||||
fileStatusView.setText(R.string.dfu_file_status_ok);
|
||||
statusOk = true;
|
||||
showProgressBar();
|
||||
}
|
||||
}
|
||||
@@ -333,24 +335,24 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mResumed = true;
|
||||
if (mDfuCompleted)
|
||||
resumed = true;
|
||||
if (dfuCompleted)
|
||||
onTransferCompleted();
|
||||
if (mDfuError != null)
|
||||
showErrorMessage(mDfuError);
|
||||
if (mDfuCompleted || mDfuError != null) {
|
||||
if (dfuError != null)
|
||||
showErrorMessage(dfuError);
|
||||
if (dfuCompleted || dfuError != null) {
|
||||
// if this activity is still open and upload process was completed, cancel the notification
|
||||
final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
manager.cancel(DfuService.NOTIFICATION_ID);
|
||||
mDfuCompleted = false;
|
||||
mDfuError = null;
|
||||
dfuCompleted = false;
|
||||
dfuError = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mResumed = false;
|
||||
resumed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -429,9 +431,9 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
switch (requestCode) {
|
||||
case SELECT_FILE_REQ: {
|
||||
// clear previous data
|
||||
mFileType = mFileTypeTmp;
|
||||
mFilePath = null;
|
||||
mFileStreamUri = null;
|
||||
fileType = fileTypeTmp;
|
||||
filePath = null;
|
||||
fileStreamUri = null;
|
||||
|
||||
// and read new one
|
||||
final Uri uri = data.getData();
|
||||
@@ -443,17 +445,17 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
// the direct path to the file has been returned
|
||||
final String path = uri.getPath();
|
||||
final File file = new File(path);
|
||||
mFilePath = path;
|
||||
filePath = path;
|
||||
|
||||
updateFileInfo(file.getName(), file.length(), mFileType);
|
||||
updateFileInfo(file.getName(), file.length(), fileType);
|
||||
} else if (uri.getScheme().equals("content")) {
|
||||
// an Uri has been returned
|
||||
mFileStreamUri = uri;
|
||||
fileStreamUri = uri;
|
||||
// if application returned Uri for streaming, let's us it. Does it works?
|
||||
// FIXME both Uris works with Google Drive app. Why both? What's the difference? How about other apps like DropBox?
|
||||
final Bundle extras = data.getExtras();
|
||||
if (extras != null && extras.containsKey(Intent.EXTRA_STREAM))
|
||||
mFileStreamUri = extras.getParcelable(Intent.EXTRA_STREAM);
|
||||
fileStreamUri = extras.getParcelable(Intent.EXTRA_STREAM);
|
||||
|
||||
// file name and size must be obtained from Content Provider
|
||||
final Bundle bundle = new Bundle();
|
||||
@@ -463,8 +465,8 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
break;
|
||||
}
|
||||
case SELECT_INIT_FILE_REQ: {
|
||||
mInitFilePath = null;
|
||||
mInitFileStreamUri = null;
|
||||
initFilePath = null;
|
||||
initFileStreamUri = null;
|
||||
|
||||
// and read new one
|
||||
final Uri uri = data.getData();
|
||||
@@ -474,17 +476,17 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
*/
|
||||
if (uri.getScheme().equals("file")) {
|
||||
// the direct path to the file has been returned
|
||||
mInitFilePath = uri.getPath();
|
||||
mFileStatusView.setText(R.string.dfu_file_status_ok_with_init);
|
||||
initFilePath = uri.getPath();
|
||||
fileStatusView.setText(R.string.dfu_file_status_ok_with_init);
|
||||
} else if (uri.getScheme().equals("content")) {
|
||||
// an Uri has been returned
|
||||
mInitFileStreamUri = uri;
|
||||
initFileStreamUri = uri;
|
||||
// if application returned Uri for streaming, let's us it. Does it works?
|
||||
// FIXME both Uris works with Google Drive app. Why both? What's the difference? How about other apps like DropBox?
|
||||
final Bundle extras = data.getExtras();
|
||||
if (extras != null && extras.containsKey(Intent.EXTRA_STREAM))
|
||||
mInitFileStreamUri = extras.getParcelable(Intent.EXTRA_STREAM);
|
||||
mFileStatusView.setText(R.string.dfu_file_status_ok_with_init);
|
||||
initFileStreamUri = extras.getParcelable(Intent.EXTRA_STREAM);
|
||||
fileStatusView.setText(R.string.dfu_file_status_ok_with_init);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -506,12 +508,12 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(final Loader<Cursor> loader) {
|
||||
mFileNameView.setText(null);
|
||||
mFileTypeView.setText(null);
|
||||
mFileSizeView.setText(null);
|
||||
mFilePath = null;
|
||||
mFileStreamUri = null;
|
||||
mStatusOk = false;
|
||||
fileNameView.setText(null);
|
||||
fileTypeView.setText(null);
|
||||
fileSizeView.setText(null);
|
||||
filePath = null;
|
||||
fileStreamUri = null;
|
||||
statusOk = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -527,17 +529,17 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
if (dataIndex != -1)
|
||||
filePath = data.getString(dataIndex /* 2 DATA */);
|
||||
if (!TextUtils.isEmpty(filePath))
|
||||
mFilePath = filePath;
|
||||
this.filePath = filePath;
|
||||
|
||||
updateFileInfo(fileName, fileSize, mFileType);
|
||||
updateFileInfo(fileName, fileSize, fileType);
|
||||
} else {
|
||||
mFileNameView.setText(null);
|
||||
mFileTypeView.setText(null);
|
||||
mFileSizeView.setText(null);
|
||||
mFilePath = null;
|
||||
mFileStreamUri = null;
|
||||
mFileStatusView.setText(R.string.dfu_file_status_error);
|
||||
mStatusOk = false;
|
||||
fileNameView.setText(null);
|
||||
fileTypeView.setText(null);
|
||||
fileSizeView.setText(null);
|
||||
filePath = null;
|
||||
fileStreamUri = null;
|
||||
fileStatusView.setText(R.string.dfu_file_status_error);
|
||||
statusOk = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,37 +550,37 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
* @param fileSize file length
|
||||
*/
|
||||
private void updateFileInfo(final String fileName, final long fileSize, final int fileType) {
|
||||
mFileNameView.setText(fileName);
|
||||
fileNameView.setText(fileName);
|
||||
switch (fileType) {
|
||||
case DfuService.TYPE_AUTO:
|
||||
mFileTypeView.setText(getResources().getStringArray(R.array.dfu_file_type)[0]);
|
||||
fileTypeView.setText(getResources().getStringArray(R.array.dfu_file_type)[0]);
|
||||
break;
|
||||
case DfuService.TYPE_SOFT_DEVICE:
|
||||
mFileTypeView.setText(getResources().getStringArray(R.array.dfu_file_type)[1]);
|
||||
fileTypeView.setText(getResources().getStringArray(R.array.dfu_file_type)[1]);
|
||||
break;
|
||||
case DfuService.TYPE_BOOTLOADER:
|
||||
mFileTypeView.setText(getResources().getStringArray(R.array.dfu_file_type)[2]);
|
||||
fileTypeView.setText(getResources().getStringArray(R.array.dfu_file_type)[2]);
|
||||
break;
|
||||
case DfuService.TYPE_APPLICATION:
|
||||
mFileTypeView.setText(getResources().getStringArray(R.array.dfu_file_type)[3]);
|
||||
fileTypeView.setText(getResources().getStringArray(R.array.dfu_file_type)[3]);
|
||||
break;
|
||||
}
|
||||
mFileSizeView.setText(getString(R.string.dfu_file_size_text, fileSize));
|
||||
mFileScopeView.setText(getString(R.string.not_available));
|
||||
final String extension = mFileType == DfuService.TYPE_AUTO ? "(?i)ZIP" : "(?i)HEX|BIN"; // (?i) = case insensitive
|
||||
final boolean statusOk = mStatusOk = MimeTypeMap.getFileExtensionFromUrl(fileName).matches(extension);
|
||||
mFileStatusView.setText(statusOk ? R.string.dfu_file_status_ok : R.string.dfu_file_status_invalid);
|
||||
mUploadButton.setEnabled(mSelectedDevice != null && statusOk);
|
||||
fileSizeView.setText(getString(R.string.dfu_file_size_text, fileSize));
|
||||
fileScopeView.setText(getString(R.string.not_available));
|
||||
final String extension = this.fileType == DfuService.TYPE_AUTO ? "(?i)ZIP" : "(?i)HEX|BIN"; // (?i) = case insensitive
|
||||
final boolean statusOk = this.statusOk = MimeTypeMap.getFileExtensionFromUrl(fileName).matches(extension);
|
||||
fileStatusView.setText(statusOk ? R.string.dfu_file_status_ok : R.string.dfu_file_status_invalid);
|
||||
uploadButton.setEnabled(selectedDevice != null && statusOk);
|
||||
|
||||
// Ask the user for the Init packet file if HEX or BIN files are selected. In case of a ZIP file the Init packets should be included in the ZIP.
|
||||
if (statusOk) {
|
||||
if (fileType != DfuService.TYPE_AUTO) {
|
||||
mScope = null;
|
||||
mFileScopeView.setText(getString(R.string.not_available));
|
||||
scope = null;
|
||||
fileScopeView.setText(getString(R.string.not_available));
|
||||
new AlertDialog.Builder(this).setTitle(R.string.dfu_file_init_title).setMessage(R.string.dfu_file_init_message)
|
||||
.setNegativeButton(R.string.no, (dialog, which) -> {
|
||||
mInitFilePath = null;
|
||||
mInitFileStreamUri = null;
|
||||
initFilePath = null;
|
||||
initFileStreamUri = null;
|
||||
}).setPositiveButton(R.string.yes, (dialog, which) -> {
|
||||
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.setType(DfuService.MIME_TYPE_OCTET_STREAM);
|
||||
@@ -590,25 +592,25 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
.setSingleChoiceItems(R.array.dfu_file_scope, 0, (dialog, which) -> {
|
||||
switch (which) {
|
||||
case 0:
|
||||
mScope = null;
|
||||
scope = null;
|
||||
break;
|
||||
case 1:
|
||||
mScope = DfuServiceInitiator.SCOPE_SYSTEM_COMPONENTS;
|
||||
scope = DfuServiceInitiator.SCOPE_SYSTEM_COMPONENTS;
|
||||
break;
|
||||
case 2:
|
||||
mScope = DfuServiceInitiator.SCOPE_APPLICATION;
|
||||
scope = DfuServiceInitiator.SCOPE_APPLICATION;
|
||||
break;
|
||||
}
|
||||
}).setPositiveButton(R.string.ok, (dialogInterface, i) -> {
|
||||
int index;
|
||||
if (mScope == null) {
|
||||
if (scope == null) {
|
||||
index = 0;
|
||||
} else if (mScope == DfuServiceInitiator.SCOPE_SYSTEM_COMPONENTS) {
|
||||
} else if (scope == DfuServiceInitiator.SCOPE_SYSTEM_COMPONENTS) {
|
||||
index = 1;
|
||||
} else {
|
||||
index = 2;
|
||||
}
|
||||
mFileScopeView.setText(getResources().getStringArray(R.array.dfu_file_scope)[index]);
|
||||
fileScopeView.setText(getResources().getStringArray(R.array.dfu_file_scope)[index]);
|
||||
}).show();
|
||||
}
|
||||
}
|
||||
@@ -630,9 +632,9 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
* @param view a button that was pressed
|
||||
*/
|
||||
public void onSelectFileClicked(final View view) {
|
||||
mFileTypeTmp = mFileType;
|
||||
fileTypeTmp = fileType;
|
||||
int index = 0;
|
||||
switch (mFileType) {
|
||||
switch (fileType) {
|
||||
case DfuService.TYPE_AUTO:
|
||||
index = 0;
|
||||
break;
|
||||
@@ -651,16 +653,16 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
.setSingleChoiceItems(R.array.dfu_file_type, index, (dialog, which) -> {
|
||||
switch (which) {
|
||||
case 0:
|
||||
mFileTypeTmp = DfuService.TYPE_AUTO;
|
||||
fileTypeTmp = DfuService.TYPE_AUTO;
|
||||
break;
|
||||
case 1:
|
||||
mFileTypeTmp = DfuService.TYPE_SOFT_DEVICE;
|
||||
fileTypeTmp = DfuService.TYPE_SOFT_DEVICE;
|
||||
break;
|
||||
case 2:
|
||||
mFileTypeTmp = DfuService.TYPE_BOOTLOADER;
|
||||
fileTypeTmp = DfuService.TYPE_BOOTLOADER;
|
||||
break;
|
||||
case 3:
|
||||
mFileTypeTmp = DfuService.TYPE_APPLICATION;
|
||||
fileTypeTmp = DfuService.TYPE_APPLICATION;
|
||||
break;
|
||||
}
|
||||
}).setPositiveButton(R.string.ok, (dialog, which) -> openFileChooser()).setNeutralButton(R.string.dfu_file_info, (dialog, which) -> {
|
||||
@@ -671,7 +673,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
|
||||
private void openFileChooser() {
|
||||
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.setType(mFileTypeTmp == DfuService.TYPE_AUTO ? DfuService.MIME_TYPE_ZIP : DfuService.MIME_TYPE_OCTET_STREAM);
|
||||
intent.setType(fileTypeTmp == DfuService.TYPE_AUTO ? DfuService.MIME_TYPE_ZIP : DfuService.MIME_TYPE_OCTET_STREAM);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
if (intent.resolveActivity(getPackageManager()) != null) {
|
||||
// file browser has been found on the device
|
||||
@@ -705,7 +707,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
}
|
||||
|
||||
// Check whether the selected file is a HEX file (we are just checking the extension)
|
||||
if (!mStatusOk) {
|
||||
if (!statusOk) {
|
||||
Toast.makeText(this, R.string.dfu_file_status_invalid_message, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
@@ -713,11 +715,11 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
// Save current state in order to restore it if user quit the Activity
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
final SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putString(PREFS_DEVICE_NAME, mSelectedDevice.getName());
|
||||
editor.putString(PREFS_FILE_NAME, mFileNameView.getText().toString());
|
||||
editor.putString(PREFS_FILE_TYPE, mFileTypeView.getText().toString());
|
||||
editor.putString(PREFS_FILE_SCOPE, mFileScopeView.getText().toString());
|
||||
editor.putString(PREFS_FILE_SIZE, mFileSizeView.getText().toString());
|
||||
editor.putString(PREFS_DEVICE_NAME, selectedDevice.getName());
|
||||
editor.putString(PREFS_FILE_NAME, fileNameView.getText().toString());
|
||||
editor.putString(PREFS_FILE_TYPE, fileTypeView.getText().toString());
|
||||
editor.putString(PREFS_FILE_SCOPE, fileScopeView.getText().toString());
|
||||
editor.putString(PREFS_FILE_SIZE, fileSizeView.getText().toString());
|
||||
editor.apply();
|
||||
|
||||
showProgressBar();
|
||||
@@ -733,19 +735,19 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
numberOfPackets = DfuServiceInitiator.DEFAULT_PRN_VALUE;
|
||||
}
|
||||
|
||||
final DfuServiceInitiator starter = new DfuServiceInitiator(mSelectedDevice.getAddress())
|
||||
.setDeviceName(mSelectedDevice.getName())
|
||||
final DfuServiceInitiator starter = new DfuServiceInitiator(selectedDevice.getAddress())
|
||||
.setDeviceName(selectedDevice.getName())
|
||||
.setKeepBond(keepBond)
|
||||
.setForceDfu(forceDfu)
|
||||
.setPacketsReceiptNotificationsEnabled(enablePRNs)
|
||||
.setPacketsReceiptNotificationsValue(numberOfPackets)
|
||||
.setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true);
|
||||
if (mFileType == DfuService.TYPE_AUTO) {
|
||||
starter.setZip(mFileStreamUri, mFilePath);
|
||||
if (mScope != null)
|
||||
starter.setScope(mScope);
|
||||
if (fileType == DfuService.TYPE_AUTO) {
|
||||
starter.setZip(fileStreamUri, filePath);
|
||||
if (scope != null)
|
||||
starter.setScope(scope);
|
||||
} else {
|
||||
starter.setBinOrHex(mFileType, mFileStreamUri, mFilePath).setInitFile(mInitFileStreamUri, mInitFilePath);
|
||||
starter.setBinOrHex(fileType, fileStreamUri, filePath).setInitFile(initFileStreamUri, initFilePath);
|
||||
}
|
||||
starter.start(this, DfuService.class);
|
||||
}
|
||||
@@ -772,10 +774,10 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceSelected(final BluetoothDevice device, final String name) {
|
||||
mSelectedDevice = device;
|
||||
mUploadButton.setEnabled(mStatusOk);
|
||||
mDeviceNameView.setText(name != null ? name : getString(R.string.not_available));
|
||||
public void onDeviceSelected(@NonNull final BluetoothDevice device, final String name) {
|
||||
selectedDevice = device;
|
||||
uploadButton.setEnabled(statusOk);
|
||||
deviceNameView.setText(name != null ? name : getString(R.string.not_available));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -784,15 +786,15 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
}
|
||||
|
||||
private void showProgressBar() {
|
||||
mProgressBar.setVisibility(View.VISIBLE);
|
||||
mTextPercentage.setVisibility(View.VISIBLE);
|
||||
mTextPercentage.setText(null);
|
||||
mTextUploading.setText(R.string.dfu_status_uploading);
|
||||
mTextUploading.setVisibility(View.VISIBLE);
|
||||
mConnectButton.setEnabled(false);
|
||||
mSelectFileButton.setEnabled(false);
|
||||
mUploadButton.setEnabled(true);
|
||||
mUploadButton.setText(R.string.dfu_action_upload_cancel);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
textPercentage.setVisibility(View.VISIBLE);
|
||||
textPercentage.setText(null);
|
||||
textUploading.setText(R.string.dfu_status_uploading);
|
||||
textUploading.setVisibility(View.VISIBLE);
|
||||
connectButton.setEnabled(false);
|
||||
selectFileButton.setEnabled(false);
|
||||
uploadButton.setEnabled(true);
|
||||
uploadButton.setText(R.string.dfu_action_upload_cancel);
|
||||
}
|
||||
|
||||
private void onTransferCompleted() {
|
||||
@@ -807,9 +809,9 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
|
||||
@Override
|
||||
public void onCancelUpload() {
|
||||
mProgressBar.setIndeterminate(true);
|
||||
mTextUploading.setText(R.string.dfu_status_aborting);
|
||||
mTextPercentage.setText(null);
|
||||
progressBar.setIndeterminate(true);
|
||||
textUploading.setText(R.string.dfu_status_aborting);
|
||||
textPercentage.setText(null);
|
||||
}
|
||||
|
||||
private void showErrorMessage(final String message) {
|
||||
@@ -818,28 +820,28 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
|
||||
}
|
||||
|
||||
private void clearUI(final boolean clearDevice) {
|
||||
mProgressBar.setVisibility(View.INVISIBLE);
|
||||
mTextPercentage.setVisibility(View.INVISIBLE);
|
||||
mTextUploading.setVisibility(View.INVISIBLE);
|
||||
mConnectButton.setEnabled(true);
|
||||
mSelectFileButton.setEnabled(true);
|
||||
mUploadButton.setEnabled(false);
|
||||
mUploadButton.setText(R.string.dfu_action_upload);
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
textPercentage.setVisibility(View.INVISIBLE);
|
||||
textUploading.setVisibility(View.INVISIBLE);
|
||||
connectButton.setEnabled(true);
|
||||
selectFileButton.setEnabled(true);
|
||||
uploadButton.setEnabled(false);
|
||||
uploadButton.setText(R.string.dfu_action_upload);
|
||||
if (clearDevice) {
|
||||
mSelectedDevice = null;
|
||||
mDeviceNameView.setText(R.string.dfu_default_name);
|
||||
selectedDevice = null;
|
||||
deviceNameView.setText(R.string.dfu_default_name);
|
||||
}
|
||||
// Application may have lost the right to these files if Activity was closed during upload (grant uri permission). Clear file related values.
|
||||
mFileNameView.setText(null);
|
||||
mFileTypeView.setText(null);
|
||||
mFileScopeView.setText(null);
|
||||
mFileSizeView.setText(null);
|
||||
mFileStatusView.setText(R.string.dfu_file_status_no_file);
|
||||
mFilePath = null;
|
||||
mFileStreamUri = null;
|
||||
mInitFilePath = null;
|
||||
mInitFileStreamUri = null;
|
||||
mStatusOk = false;
|
||||
fileNameView.setText(null);
|
||||
fileTypeView.setText(null);
|
||||
fileScopeView.setText(null);
|
||||
fileSizeView.setText(null);
|
||||
fileStatusView.setText(R.string.dfu_file_status_no_file);
|
||||
filePath = null;
|
||||
fileStreamUri = null;
|
||||
initFilePath = null;
|
||||
initFileStreamUri = null;
|
||||
statusOk = false;
|
||||
}
|
||||
|
||||
private void showToast(final int messageResId) {
|
||||
|
||||
@@ -25,6 +25,8 @@ package no.nordicsemi.android.nrftoolbox.dfu;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
@@ -52,7 +54,7 @@ public class DfuInitiatorActivity extends AppCompatActivity implements ScannerFr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceSelected(final BluetoothDevice device, final String name) {
|
||||
public void onDeviceSelected(@NonNull final BluetoothDevice device, final String name) {
|
||||
final Intent intent = getIntent();
|
||||
final String overwrittenName = intent.getStringExtra(DfuService.EXTRA_DEVICE_NAME);
|
||||
final String path = intent.getStringExtra(DfuService.EXTRA_FILE_PATH);
|
||||
|
||||
@@ -39,7 +39,8 @@ public class NotificationActivity extends Activity {
|
||||
final Intent parentIntent = new Intent(this, FeaturesActivity.class);
|
||||
parentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
final Intent startAppIntent = new Intent(this, DfuActivity.class);
|
||||
startAppIntent.putExtras(getIntent().getExtras());
|
||||
if (getIntent() != null && getIntent().getExtras() != null)
|
||||
startAppIntent.putExtras(getIntent().getExtras());
|
||||
startActivities(new Intent[] { parentIntent, startAppIntent });
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
|
||||
/**
|
||||
@@ -36,38 +38,38 @@ import no.nordicsemi.android.nrftoolbox.R;
|
||||
* URLs are specified in res/values/strings_dfu.xml.
|
||||
*/
|
||||
public class FileBrowserAppsAdapter extends BaseAdapter {
|
||||
private final LayoutInflater mInflater;
|
||||
private final Resources mResources;
|
||||
private final LayoutInflater inflater;
|
||||
private final Resources resources;
|
||||
|
||||
public FileBrowserAppsAdapter(final Context context) {
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mResources = context.getResources();
|
||||
inflater = LayoutInflater.from(context);
|
||||
resources = context.getResources();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mResources.getStringArray(R.array.dfu_app_file_browser).length;
|
||||
return resources.getStringArray(R.array.dfu_app_file_browser).length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return mResources.getStringArray(R.array.dfu_app_file_browser_action)[position];
|
||||
public Object getItem(final int position) {
|
||||
return resources.getStringArray(R.array.dfu_app_file_browser_action)[position];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
public long getItemId(final int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
public View getView(final int position, @Nullable final View convertView, @NonNull final ViewGroup parent) {
|
||||
View view = convertView;
|
||||
if (view == null) {
|
||||
view = mInflater.inflate(R.layout.app_file_browser_item, parent, false);
|
||||
view = inflater.inflate(R.layout.app_file_browser_item, parent, false);
|
||||
}
|
||||
|
||||
final TextView item = (TextView) view;
|
||||
item.setText(mResources.getStringArray(R.array.dfu_app_file_browser)[position]);
|
||||
item.setText(resources.getStringArray(R.array.dfu_app_file_browser)[position]);
|
||||
item.getCompoundDrawablesRelative()[0].setLevel(position);
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -21,17 +21,17 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.dfu.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
import no.nordicsemi.android.nrftoolbox.dfu.DfuService;
|
||||
|
||||
@@ -41,7 +41,7 @@ import no.nordicsemi.android.nrftoolbox.dfu.DfuService;
|
||||
public class UploadCancelFragment extends DialogFragment {
|
||||
private static final String TAG = "UploadCancelFragment";
|
||||
|
||||
private CancelFragmentListener mListener;
|
||||
private CancelFragmentListener listener;
|
||||
|
||||
public interface CancelFragmentListener {
|
||||
void onCancelUpload();
|
||||
@@ -52,11 +52,11 @@ public class UploadCancelFragment extends DialogFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(final Activity activity) {
|
||||
super.onAttach(activity);
|
||||
public void onAttach(@NonNull final Context context) {
|
||||
super.onAttach(context);
|
||||
|
||||
try {
|
||||
mListener = (CancelFragmentListener) activity;
|
||||
listener = (CancelFragmentListener) context;
|
||||
} catch (final ClassCastException e) {
|
||||
Log.d(TAG, "The parent Activity must implement CancelFragmentListener interface");
|
||||
}
|
||||
@@ -65,20 +65,20 @@ public class UploadCancelFragment extends DialogFragment {
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
return new AlertDialog.Builder(getActivity()).setTitle(R.string.dfu_confirmation_dialog_title).setMessage(R.string.dfu_upload_dialog_cancel_message).setCancelable(false)
|
||||
return new AlertDialog.Builder(requireContext()).setTitle(R.string.dfu_confirmation_dialog_title).setMessage(R.string.dfu_upload_dialog_cancel_message).setCancelable(false)
|
||||
.setPositiveButton(R.string.yes, (dialog, whichButton) -> {
|
||||
final LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
|
||||
final LocalBroadcastManager manager = LocalBroadcastManager.getInstance(requireContext());
|
||||
final Intent pauseAction = new Intent(DfuService.BROADCAST_ACTION);
|
||||
pauseAction.putExtra(DfuService.EXTRA_ACTION, DfuService.ACTION_ABORT);
|
||||
manager.sendBroadcast(pauseAction);
|
||||
|
||||
mListener.onCancelUpload();
|
||||
listener.onCancelUpload();
|
||||
}).setNegativeButton(R.string.no, (dialog, which) -> dialog.cancel()).create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(final DialogInterface dialog) {
|
||||
final LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getActivity());
|
||||
public void onCancel(@NonNull final DialogInterface dialog) {
|
||||
final LocalBroadcastManager manager = LocalBroadcastManager.getInstance(requireContext());
|
||||
final Intent pauseAction = new Intent(DfuService.BROADCAST_ACTION);
|
||||
pauseAction.putExtra(DfuService.EXTRA_ACTION, DfuService.ACTION_RESUME);
|
||||
manager.sendBroadcast(pauseAction);
|
||||
|
||||
@@ -36,7 +36,12 @@ public class ZipInfoFragment extends DialogFragment {
|
||||
@Override
|
||||
@NonNull
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_zip_info, null);
|
||||
return new AlertDialog.Builder(getActivity()).setView(view).setTitle(R.string.dfu_file_info).setPositiveButton(R.string.ok, null).create();
|
||||
final View view = LayoutInflater.from(requireContext())
|
||||
.inflate(R.layout.fragment_zip_info, null);
|
||||
return new AlertDialog.Builder(requireContext())
|
||||
.setView(view)
|
||||
.setTitle(R.string.dfu_file_info)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.create();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class AboutDfuPreference extends Preference {
|
||||
protected void onClick() {
|
||||
final Context context = getContext();
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW,
|
||||
Uri.parse("https://www.nordicsemi.com/DocLib/Content/SDK_Doc/nRF5_SDK/v15-3-0/ble_sdk_app_dfu_bootloader"));
|
||||
Uri.parse("https://infocenter.nordicsemi.com/topic/sdk_nrf5_v16.0.0/examples_bootloader.html?cp=7_1_4_4"));
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
|
||||
@@ -34,44 +34,44 @@ import android.widget.TextView;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
|
||||
public class ExpandableRecordAdapter extends BaseExpandableListAdapter {;
|
||||
private final GlucoseManager mGlucoseManager;
|
||||
private final LayoutInflater mInflater;
|
||||
private final Context mContext;
|
||||
private SparseArray<GlucoseRecord> mRecords;
|
||||
private final GlucoseManager glucoseManager;
|
||||
private final LayoutInflater inflater;
|
||||
private final Context context;
|
||||
private SparseArray<GlucoseRecord> records;
|
||||
|
||||
public ExpandableRecordAdapter(final Context context, final GlucoseManager manager) {
|
||||
mGlucoseManager = manager;
|
||||
mContext = context;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mRecords = manager.getRecords().clone();
|
||||
glucoseManager = manager;
|
||||
this.context = context;
|
||||
inflater = LayoutInflater.from(context);
|
||||
records = manager.getRecords().clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDataSetChanged() {
|
||||
mRecords = mGlucoseManager.getRecords().clone();
|
||||
records = glucoseManager.getRecords().clone();
|
||||
super.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGroupCount() {
|
||||
return mRecords.size();
|
||||
return records.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGroup(final int groupPosition) {
|
||||
return mRecords.valueAt(groupPosition);
|
||||
return records.valueAt(groupPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getGroupId(final int groupPosition) {
|
||||
return mRecords.keyAt(groupPosition);
|
||||
return records.keyAt(groupPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getGroupView(final int position, boolean isExpanded, final View convertView, final ViewGroup parent) {
|
||||
View view = convertView;
|
||||
if (view == null) {
|
||||
view = mInflater.inflate(R.layout.activity_feature_gls_item, parent, false);
|
||||
view = inflater.inflate(R.layout.activity_feature_gls_item, parent, false);
|
||||
|
||||
final GroupViewHolder holder = new GroupViewHolder();
|
||||
holder.time = view.findViewById(R.id.time);
|
||||
@@ -83,16 +83,16 @@ public class ExpandableRecordAdapter extends BaseExpandableListAdapter {;
|
||||
if (record == null)
|
||||
return view; // this may happen during closing the activity
|
||||
final GroupViewHolder holder = (GroupViewHolder) view.getTag();
|
||||
holder.time.setText(mContext.getString(R.string.gls_timestamp, record.time));
|
||||
holder.time.setText(context.getString(R.string.gls_timestamp, record.time));
|
||||
try {
|
||||
holder.details.setText(mContext.getResources().getStringArray(R.array.gls_type)[record.type]);
|
||||
holder.details.setText(context.getResources().getStringArray(R.array.gls_type)[record.type]);
|
||||
} catch (final ArrayIndexOutOfBoundsException e) {
|
||||
holder.details.setText(mContext.getResources().getStringArray(R.array.gls_type)[0]);
|
||||
holder.details.setText(context.getResources().getStringArray(R.array.gls_type)[0]);
|
||||
}
|
||||
if (record.unit == GlucoseRecord.UNIT_kgpl) {
|
||||
holder.concentration.setText(mContext.getString(R.string.gls_value, record.glucoseConcentration * 100000.0f));
|
||||
holder.concentration.setText(context.getString(R.string.gls_value, record.glucoseConcentration * 100000.0f));
|
||||
} else {
|
||||
holder.concentration.setText(mContext.getString(R.string.gls_value, record.glucoseConcentration * 1000.0f));
|
||||
holder.concentration.setText(context.getString(R.string.gls_value, record.glucoseConcentration * 1000.0f));
|
||||
}
|
||||
return view;
|
||||
}
|
||||
@@ -123,7 +123,7 @@ public class ExpandableRecordAdapter extends BaseExpandableListAdapter {;
|
||||
|
||||
@Override
|
||||
public Object getChild(final int groupPosition, final int childPosition) {
|
||||
final Resources resources = mContext.getResources();
|
||||
final Resources resources = context.getResources();
|
||||
final GlucoseRecord record = (GlucoseRecord) getGroup(groupPosition);
|
||||
String tmp;
|
||||
switch (childIdToItemId(childPosition, record)) {
|
||||
@@ -226,7 +226,7 @@ public class ExpandableRecordAdapter extends BaseExpandableListAdapter {;
|
||||
public View getChildView(final int groupPosition, final int childPosition, final boolean isLastChild, final View convertView, final ViewGroup parent) {
|
||||
View view = convertView;
|
||||
if (view == null) {
|
||||
view = mInflater.inflate(R.layout.activity_feature_gls_subitem, parent, false);
|
||||
view = inflater.inflate(R.layout.activity_feature_gls_subitem, parent, false);
|
||||
final ChildViewHolder holder = new ChildViewHolder();
|
||||
holder.title = view.findViewById(android.R.id.text1);
|
||||
holder.details = view.findViewById(android.R.id.text2);
|
||||
|
||||
@@ -43,13 +43,13 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = "GlucoseActivity";
|
||||
|
||||
private BaseExpandableListAdapter mAdapter;
|
||||
private GlucoseManager mGlucoseManager;
|
||||
private BaseExpandableListAdapter adapter;
|
||||
private GlucoseManager glucoseManager;
|
||||
|
||||
private View mControlPanelStd;
|
||||
private View mControlPanelAbort;
|
||||
private TextView mUnitView;
|
||||
private TextView mBatteryLevelView;
|
||||
private View controlPanelStd;
|
||||
private View controlPanelAbort;
|
||||
private TextView unitView;
|
||||
private TextView batteryLevelView;
|
||||
|
||||
@Override
|
||||
protected void onCreateView(final Bundle savedInstanceState) {
|
||||
@@ -58,14 +58,14 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
|
||||
}
|
||||
|
||||
private void setGUI() {
|
||||
mUnitView = findViewById(R.id.unit);
|
||||
mControlPanelStd = findViewById(R.id.gls_control_std);
|
||||
mControlPanelAbort = findViewById(R.id.gls_control_abort);
|
||||
mBatteryLevelView = findViewById(R.id.battery);
|
||||
unitView = findViewById(R.id.unit);
|
||||
controlPanelStd = findViewById(R.id.gls_control_std);
|
||||
controlPanelAbort = findViewById(R.id.gls_control_abort);
|
||||
batteryLevelView = findViewById(R.id.battery);
|
||||
|
||||
findViewById(R.id.action_last).setOnClickListener(v -> mGlucoseManager.getLastRecord());
|
||||
findViewById(R.id.action_all).setOnClickListener(v -> mGlucoseManager.getAllRecords());
|
||||
findViewById(R.id.action_abort).setOnClickListener(v -> mGlucoseManager.abort());
|
||||
findViewById(R.id.action_last).setOnClickListener(v -> glucoseManager.getLastRecord());
|
||||
findViewById(R.id.action_all).setOnClickListener(v -> glucoseManager.getAllRecords());
|
||||
findViewById(R.id.action_abort).setOnClickListener(v -> glucoseManager.abort());
|
||||
|
||||
// create popup menu attached to the button More
|
||||
findViewById(R.id.action_more).setOnClickListener(v -> {
|
||||
@@ -76,12 +76,12 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
|
||||
menu.show();
|
||||
});
|
||||
|
||||
setListAdapter(mAdapter = new ExpandableRecordAdapter(this, mGlucoseManager));
|
||||
setListAdapter(adapter = new ExpandableRecordAdapter(this, glucoseManager));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggableBleManager<GlucoseManagerCallbacks> initializeManager() {
|
||||
GlucoseManager manager = mGlucoseManager = GlucoseManager.getGlucoseManager(getApplicationContext());
|
||||
GlucoseManager manager = glucoseManager = GlucoseManager.getGlucoseManager(getApplicationContext());
|
||||
manager.setGattCallbacks(this);
|
||||
return manager;
|
||||
}
|
||||
@@ -90,16 +90,16 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
|
||||
public boolean onMenuItemClick(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_refresh:
|
||||
mGlucoseManager.refreshRecords();
|
||||
glucoseManager.refreshRecords();
|
||||
break;
|
||||
case R.id.action_first:
|
||||
mGlucoseManager.getFirstRecord();
|
||||
glucoseManager.getFirstRecord();
|
||||
break;
|
||||
case R.id.action_clear:
|
||||
mGlucoseManager.clear();
|
||||
glucoseManager.clear();
|
||||
break;
|
||||
case R.id.action_delete_all:
|
||||
mGlucoseManager.deleteAllRecords();
|
||||
glucoseManager.deleteAllRecords();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
@@ -127,14 +127,14 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
|
||||
|
||||
@Override
|
||||
protected void setDefaultUI() {
|
||||
mGlucoseManager.clear();
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
glucoseManager.clear();
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
}
|
||||
|
||||
private void setOperationInProgress(final boolean progress) {
|
||||
runOnUiThread(() -> {
|
||||
mControlPanelStd.setVisibility(!progress ? View.VISIBLE : View.GONE);
|
||||
mControlPanelAbort.setVisibility(progress ? View.VISIBLE : View.GONE);
|
||||
controlPanelStd.setVisibility(!progress ? View.VISIBLE : View.GONE);
|
||||
controlPanelAbort.setVisibility(progress ? View.VISIBLE : View.GONE);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -142,55 +142,55 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
setOperationInProgress(false);
|
||||
runOnUiThread(() -> mBatteryLevelView.setText(R.string.not_available));
|
||||
runOnUiThread(() -> batteryLevelView.setText(R.string.not_available));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationStarted(final BluetoothDevice device) {
|
||||
public void onOperationStarted(@NonNull final BluetoothDevice device) {
|
||||
setOperationInProgress(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationCompleted(final BluetoothDevice device) {
|
||||
public void onOperationCompleted(@NonNull final BluetoothDevice device) {
|
||||
setOperationInProgress(false);
|
||||
|
||||
runOnUiThread(() -> {
|
||||
final SparseArray<GlucoseRecord> records = mGlucoseManager.getRecords();
|
||||
final SparseArray<GlucoseRecord> records = glucoseManager.getRecords();
|
||||
if (records.size() > 0) {
|
||||
final int unit = records.valueAt(0).unit;
|
||||
mUnitView.setVisibility(View.VISIBLE);
|
||||
mUnitView.setText(unit == GlucoseRecord.UNIT_kgpl ? R.string.gls_unit_mgpdl : R.string.gls_unit_mmolpl);
|
||||
unitView.setVisibility(View.VISIBLE);
|
||||
unitView.setText(unit == GlucoseRecord.UNIT_kgpl ? R.string.gls_unit_mgpdl : R.string.gls_unit_mmolpl);
|
||||
} else {
|
||||
mUnitView.setVisibility(View.GONE);
|
||||
unitView.setVisibility(View.GONE);
|
||||
}
|
||||
mAdapter.notifyDataSetChanged();
|
||||
adapter.notifyDataSetChanged();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationAborted(final BluetoothDevice device) {
|
||||
public void onOperationAborted(@NonNull final BluetoothDevice device) {
|
||||
setOperationInProgress(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationNotSupported(final BluetoothDevice device) {
|
||||
public void onOperationNotSupported(@NonNull final BluetoothDevice device) {
|
||||
setOperationInProgress(false);
|
||||
showToast(R.string.gls_operation_not_supported);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOperationFailed(final BluetoothDevice device) {
|
||||
public void onOperationFailed(@NonNull final BluetoothDevice device) {
|
||||
setOperationInProgress(false);
|
||||
showToast(R.string.gls_operation_failed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDatasetChanged(final BluetoothDevice device) {
|
||||
public void onDataSetChanged(@NonNull final BluetoothDevice device) {
|
||||
// Do nothing. Refreshing the list is done in onOperationCompleted
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNumberOfRecordsRequested(final BluetoothDevice device, final int value) {
|
||||
public void onNumberOfRecordsRequested(@NonNull final BluetoothDevice device, final int value) {
|
||||
if (value == 0)
|
||||
showToast(R.string.gls_progress_zero);
|
||||
else
|
||||
@@ -199,6 +199,6 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
|
||||
|
||||
@Override
|
||||
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) {
|
||||
runOnUiThread(() -> mBatteryLevelView.setText(getString(R.string.battery, batteryLevel)));
|
||||
runOnUiThread(() -> batteryLevelView.setText(getString(R.string.battery, batteryLevel)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.gls;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
@@ -52,7 +53,7 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
private static final String TAG = "GlucoseManager";
|
||||
|
||||
/** Glucose service UUID */
|
||||
public final static UUID GLS_SERVICE_UUID = UUID.fromString("00001808-0000-1000-8000-00805f9b34fb");
|
||||
final static UUID GLS_SERVICE_UUID = UUID.fromString("00001808-0000-1000-8000-00805f9b34fb");
|
||||
/** Glucose Measurement characteristic UUID */
|
||||
private final static UUID GM_CHARACTERISTIC = UUID.fromString("00002A18-0000-1000-8000-00805f9b34fb");
|
||||
/** Glucose Measurement Context characteristic UUID */
|
||||
@@ -62,39 +63,39 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
/** Record Access Control Point characteristic UUID */
|
||||
private final static UUID RACP_CHARACTERISTIC = UUID.fromString("00002A52-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private BluetoothGattCharacteristic mGlucoseMeasurementCharacteristic;
|
||||
private BluetoothGattCharacteristic mGlucoseMeasurementContextCharacteristic;
|
||||
private BluetoothGattCharacteristic mRecordAccessControlPointCharacteristic;
|
||||
private BluetoothGattCharacteristic glucoseMeasurementCharacteristic;
|
||||
private BluetoothGattCharacteristic glucoseMeasurementContextCharacteristic;
|
||||
private BluetoothGattCharacteristic recordAccessControlPointCharacteristic;
|
||||
|
||||
private final SparseArray<GlucoseRecord> mRecords = new SparseArray<>();
|
||||
private Handler mHandler;
|
||||
private static GlucoseManager mInstance;
|
||||
private final SparseArray<GlucoseRecord> records = new SparseArray<>();
|
||||
private Handler handler;
|
||||
private static GlucoseManager instance;
|
||||
|
||||
/**
|
||||
* Returns the singleton implementation of GlucoseManager.
|
||||
*/
|
||||
public static GlucoseManager getGlucoseManager(final Context context) {
|
||||
if (mInstance == null)
|
||||
mInstance = new GlucoseManager(context);
|
||||
return mInstance;
|
||||
static GlucoseManager getGlucoseManager(@NonNull final Context context) {
|
||||
if (instance == null)
|
||||
instance = new GlucoseManager(context);
|
||||
return instance;
|
||||
}
|
||||
|
||||
private GlucoseManager(final Context context) {
|
||||
super(context);
|
||||
mHandler = new Handler();
|
||||
handler = new Handler();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected BatteryManagerGattCallback getGattCallback() {
|
||||
return mGattCallback;
|
||||
return gattCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* BluetoothGatt callbacks for connection/disconnection, service discovery,
|
||||
* receiving notification, etc.
|
||||
*/
|
||||
private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
|
||||
private final BatteryManagerGattCallback gattCallback = new BatteryManagerGattCallback() {
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
@@ -111,13 +112,13 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
// However... the original approach works for the Battery Level CCCD, which makes it
|
||||
// even weirder.
|
||||
/*
|
||||
gatt.setCharacteristicNotification(mGlucoseMeasurementCharacteristic, true);
|
||||
if (mGlucoseMeasurementContextCharacteristic != null) {
|
||||
device.setCharacteristicNotification(mGlucoseMeasurementContextCharacteristic, true);
|
||||
gatt.setCharacteristicNotification(glucoseMeasurementCharacteristic, true);
|
||||
if (glucoseMeasurementContextCharacteristic != null) {
|
||||
device.setCharacteristicNotification(glucoseMeasurementContextCharacteristic, true);
|
||||
}
|
||||
device.setCharacteristicNotification(mRecordAccessControlPointCharacteristic, true);
|
||||
device.setCharacteristicNotification(recordAccessControlPointCharacteristic, true);
|
||||
*/
|
||||
setNotificationCallback(mGlucoseMeasurementCharacteristic)
|
||||
setNotificationCallback(glucoseMeasurementContextCharacteristic)
|
||||
.with(new GlucoseMeasurementDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||
@@ -141,17 +142,17 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
record.status = status != null ? status.value : 0;
|
||||
|
||||
// insert the new record to storage
|
||||
mRecords.put(record.sequenceNumber, record);
|
||||
mHandler.post(() -> {
|
||||
records.put(record.sequenceNumber, record);
|
||||
handler.post(() -> {
|
||||
// if there is no context information following the measurement data,
|
||||
// notify callback about the new record
|
||||
if (!contextInformationFollows)
|
||||
mCallbacks.onDatasetChanged(device);
|
||||
callbacks.onDataSetChanged(device);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
setNotificationCallback(mGlucoseMeasurementContextCharacteristic)
|
||||
setNotificationCallback(glucoseMeasurementContextCharacteristic)
|
||||
.with(new GlucoseMeasurementContextDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||
@@ -167,7 +168,7 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
@Nullable final Integer exerciseIntensity, @Nullable final Medication medication,
|
||||
@Nullable final Float medicationAmount, @Nullable final Integer medicationUnit,
|
||||
@Nullable final Float HbA1c) {
|
||||
final GlucoseRecord record = mRecords.get(sequenceNumber);
|
||||
final GlucoseRecord record = records.get(sequenceNumber);
|
||||
if (record == null) {
|
||||
DebugLogger.w(TAG, "Context information with unknown sequence number: " + sequenceNumber);
|
||||
return;
|
||||
@@ -186,14 +187,14 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
context.medicationUnit = medicationUnit != null ? medicationUnit : UNIT_mg;
|
||||
context.HbA1c = HbA1c != null ? HbA1c : 0;
|
||||
|
||||
mHandler.post(() -> {
|
||||
handler.post(() -> {
|
||||
// notify callback about the new record
|
||||
mCallbacks.onDatasetChanged(device);
|
||||
callbacks.onDataSetChanged(device);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
setIndicationCallback(mRecordAccessControlPointCharacteristic)
|
||||
setIndicationCallback(recordAccessControlPointCharacteristic)
|
||||
.with(new RecordAccessControlPointDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||
@@ -201,57 +202,62 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
super.onDataReceived(device, data);
|
||||
}
|
||||
|
||||
@SuppressLint("SwitchIntDef")
|
||||
@Override
|
||||
public void onRecordAccessOperationCompleted(@NonNull final BluetoothDevice device, final int requestCode) {
|
||||
public void onRecordAccessOperationCompleted(@NonNull final BluetoothDevice device,
|
||||
@RACPOpCode final int requestCode) {
|
||||
//noinspection SwitchStatementWithTooFewBranches
|
||||
switch (requestCode) {
|
||||
case RACP_OP_CODE_ABORT_OPERATION:
|
||||
mCallbacks.onOperationAborted(device);
|
||||
callbacks.onOperationAborted(device);
|
||||
break;
|
||||
default:
|
||||
mCallbacks.onOperationCompleted(device);
|
||||
callbacks.onOperationCompleted(device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecordAccessOperationCompletedWithNoRecordsFound(@NonNull final BluetoothDevice device, final int requestCode) {
|
||||
mCallbacks.onOperationCompleted(device);
|
||||
public void onRecordAccessOperationCompletedWithNoRecordsFound(@NonNull final BluetoothDevice device,
|
||||
@RACPOpCode final int requestCode) {
|
||||
callbacks.onOperationCompleted(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNumberOfRecordsReceived(@NonNull final BluetoothDevice device, final int numberOfRecords) {
|
||||
mCallbacks.onNumberOfRecordsRequested(device, numberOfRecords);
|
||||
callbacks.onNumberOfRecordsRequested(device, numberOfRecords);
|
||||
if (numberOfRecords > 0) {
|
||||
if (mRecords.size() > 0) {
|
||||
final int sequenceNumber = mRecords.keyAt(mRecords.size() - 1) + 1;
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic,
|
||||
if (records.size() > 0) {
|
||||
final int sequenceNumber = records.keyAt(records.size() - 1) + 1;
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic,
|
||||
RecordAccessControlPointData.reportStoredRecordsGreaterThenOrEqualTo(sequenceNumber))
|
||||
.enqueue();
|
||||
} else {
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic,
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic,
|
||||
RecordAccessControlPointData.reportAllStoredRecords())
|
||||
.enqueue();
|
||||
}
|
||||
} else {
|
||||
mCallbacks.onOperationCompleted(device);
|
||||
callbacks.onOperationCompleted(device);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecordAccessOperationError(@NonNull final BluetoothDevice device,
|
||||
final int requestCode, final int errorCode) {
|
||||
@RACPOpCode final int requestCode,
|
||||
@RACPErrorCode final int errorCode) {
|
||||
log(Log.WARN, "Record Access operation failed (error " + errorCode + ")");
|
||||
if (errorCode == RACP_ERROR_OP_CODE_NOT_SUPPORTED) {
|
||||
mCallbacks.onOperationNotSupported(device);
|
||||
callbacks.onOperationNotSupported(device);
|
||||
} else {
|
||||
mCallbacks.onOperationFailed(device);
|
||||
callbacks.onOperationFailed(device);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
enableNotifications(mGlucoseMeasurementCharacteristic).enqueue();
|
||||
enableNotifications(mGlucoseMeasurementContextCharacteristic).enqueue();
|
||||
enableIndications(mRecordAccessControlPointCharacteristic)
|
||||
enableNotifications(glucoseMeasurementContextCharacteristic).enqueue();
|
||||
enableNotifications(glucoseMeasurementContextCharacteristic).enqueue();
|
||||
enableIndications(recordAccessControlPointCharacteristic)
|
||||
.fail((device, status) -> log(Log.WARN, "Failed to enabled Record Access Control Point indications (error " + status + ")"))
|
||||
.enqueue();
|
||||
}
|
||||
@@ -260,24 +266,24 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
public boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(GLS_SERVICE_UUID);
|
||||
if (service != null) {
|
||||
mGlucoseMeasurementCharacteristic = service.getCharacteristic(GM_CHARACTERISTIC);
|
||||
mGlucoseMeasurementContextCharacteristic = service.getCharacteristic(GM_CONTEXT_CHARACTERISTIC);
|
||||
mRecordAccessControlPointCharacteristic = service.getCharacteristic(RACP_CHARACTERISTIC);
|
||||
glucoseMeasurementCharacteristic = service.getCharacteristic(GM_CHARACTERISTIC);
|
||||
glucoseMeasurementContextCharacteristic = service.getCharacteristic(GM_CONTEXT_CHARACTERISTIC);
|
||||
recordAccessControlPointCharacteristic = service.getCharacteristic(RACP_CHARACTERISTIC);
|
||||
}
|
||||
return mGlucoseMeasurementCharacteristic != null && mRecordAccessControlPointCharacteristic != null;
|
||||
return glucoseMeasurementCharacteristic != null && recordAccessControlPointCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isOptionalServiceSupported(@NonNull BluetoothGatt gatt) {
|
||||
super.isOptionalServiceSupported(gatt);
|
||||
return mGlucoseMeasurementContextCharacteristic != null;
|
||||
return glucoseMeasurementContextCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeviceDisconnected() {
|
||||
mGlucoseMeasurementCharacteristic = null;
|
||||
mGlucoseMeasurementContextCharacteristic = null;
|
||||
mRecordAccessControlPointCharacteristic = null;
|
||||
glucoseMeasurementCharacteristic = null;
|
||||
glucoseMeasurementContextCharacteristic = null;
|
||||
recordAccessControlPointCharacteristic = null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -286,16 +292,16 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
*
|
||||
* @return the records list.
|
||||
*/
|
||||
public SparseArray<GlucoseRecord> getRecords() {
|
||||
return mRecords;
|
||||
SparseArray<GlucoseRecord> getRecords() {
|
||||
return records;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the records list locally.
|
||||
*/
|
||||
public void clear() {
|
||||
mRecords.clear();
|
||||
mCallbacks.onOperationCompleted(getBluetoothDevice());
|
||||
records.clear();
|
||||
callbacks.onOperationCompleted(getBluetoothDevice());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,13 +309,13 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
* be returned to Glucose Measurement characteristic as a notification followed by Record Access
|
||||
* Control Point indication with status code Success or other in case of error.
|
||||
*/
|
||||
public void getLastRecord() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
void getLastRecord() {
|
||||
if (recordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted(getBluetoothDevice());
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportLastStoredRecord())
|
||||
callbacks.onOperationStarted(getBluetoothDevice());
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportLastStoredRecord())
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
|
||||
.enqueue();
|
||||
}
|
||||
@@ -319,13 +325,13 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
* returned to Glucose Measurement characteristic as a notification followed by Record Access
|
||||
* Control Point indication with status code Success or other in case of error.
|
||||
*/
|
||||
public void getFirstRecord() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
void getFirstRecord() {
|
||||
if (recordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted(getBluetoothDevice());
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportFirstStoredRecord())
|
||||
callbacks.onOperationStarted(getBluetoothDevice());
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportFirstStoredRecord())
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
|
||||
.enqueue();
|
||||
}
|
||||
@@ -336,13 +342,13 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
* will be returned to Glucose Measurement characteristic as a notification followed by
|
||||
* Record Access Control Point indication with status code Success or other in case of error.
|
||||
*/
|
||||
public void getAllRecords() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
void getAllRecords() {
|
||||
if (recordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted(getBluetoothDevice());
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.reportNumberOfAllStoredRecords())
|
||||
callbacks.onOperationStarted(getBluetoothDevice());
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportNumberOfAllStoredRecords())
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
|
||||
.enqueue();
|
||||
}
|
||||
@@ -357,19 +363,19 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
* E.g. if you have pressed Last and then Refresh, than it will try to get only newer records.
|
||||
* However if there are no records, it will download all existing (using {@link #getAllRecords()}).
|
||||
*/
|
||||
public void refreshRecords() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
void refreshRecords() {
|
||||
if (recordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
if (mRecords.size() == 0) {
|
||||
if (records.size() == 0) {
|
||||
getAllRecords();
|
||||
} else {
|
||||
mCallbacks.onOperationStarted(getBluetoothDevice());
|
||||
callbacks.onOperationStarted(getBluetoothDevice());
|
||||
|
||||
// obtain the last sequence number
|
||||
final int sequenceNumber = mRecords.keyAt(mRecords.size() - 1) + 1;
|
||||
final int sequenceNumber = records.keyAt(records.size() - 1) + 1;
|
||||
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic,
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic,
|
||||
RecordAccessControlPointData.reportStoredRecordsGreaterThenOrEqualTo(sequenceNumber))
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
|
||||
.enqueue();
|
||||
@@ -381,11 +387,11 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
/**
|
||||
* Sends abort operation signal to the device.
|
||||
*/
|
||||
public void abort() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
void abort() {
|
||||
if (recordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.abortOperation())
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.abortOperation())
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
|
||||
.enqueue();
|
||||
}
|
||||
@@ -394,13 +400,13 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
|
||||
* Sends the request to delete all data from the device. A Record Access Control Point
|
||||
* indication with status code Success (or other in case of error) will be send.
|
||||
*/
|
||||
public void deleteAllRecords() {
|
||||
if (mRecordAccessControlPointCharacteristic == null)
|
||||
void deleteAllRecords() {
|
||||
if (recordAccessControlPointCharacteristic == null)
|
||||
return;
|
||||
|
||||
clear();
|
||||
mCallbacks.onOperationStarted(getBluetoothDevice());
|
||||
writeCharacteristic(mRecordAccessControlPointCharacteristic, RecordAccessControlPointData.deleteAllStoredRecords())
|
||||
callbacks.onOperationStarted(getBluetoothDevice());
|
||||
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.deleteAllStoredRecords())
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
|
||||
.enqueue();
|
||||
}
|
||||
|
||||
@@ -23,22 +23,23 @@ package no.nordicsemi.android.nrftoolbox.gls;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import no.nordicsemi.android.ble.BleManagerCallbacks;
|
||||
import no.nordicsemi.android.nrftoolbox.battery.BatteryManagerCallbacks;
|
||||
|
||||
public interface GlucoseManagerCallbacks extends BatteryManagerCallbacks {
|
||||
|
||||
void onOperationStarted(final BluetoothDevice device);
|
||||
void onOperationStarted(@NonNull final BluetoothDevice device);
|
||||
|
||||
void onOperationCompleted(final BluetoothDevice device);
|
||||
void onOperationCompleted(@NonNull final BluetoothDevice device);
|
||||
|
||||
void onOperationFailed(final BluetoothDevice device);
|
||||
void onOperationFailed(@NonNull final BluetoothDevice device);
|
||||
|
||||
void onOperationAborted(final BluetoothDevice device);
|
||||
void onOperationAborted(@NonNull final BluetoothDevice device);
|
||||
|
||||
void onOperationNotSupported(final BluetoothDevice device);
|
||||
void onOperationNotSupported(@NonNull final BluetoothDevice device);
|
||||
|
||||
void onDatasetChanged(final BluetoothDevice device);
|
||||
void onDataSetChanged(@NonNull final BluetoothDevice device);
|
||||
|
||||
void onNumberOfRecordsRequested(final BluetoothDevice device, final int value);
|
||||
void onNumberOfRecordsRequested(@NonNull final BluetoothDevice device, final int value);
|
||||
}
|
||||
|
||||
@@ -23,32 +23,34 @@ package no.nordicsemi.android.nrftoolbox.gls;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class GlucoseRecord {
|
||||
public static final int UNIT_kgpl = 0;
|
||||
public static final int UNIT_molpl = 1;
|
||||
static final int UNIT_kgpl = 0;
|
||||
private static final int UNIT_molpl = 1;
|
||||
|
||||
/** Record sequence number */
|
||||
protected int sequenceNumber;
|
||||
int sequenceNumber;
|
||||
/** The base time of the measurement */
|
||||
protected Calendar time;
|
||||
Calendar time;
|
||||
/** Time offset of the record */
|
||||
protected int timeOffset;
|
||||
int timeOffset;
|
||||
/** The glucose concentration. 0 if not present */
|
||||
protected float glucoseConcentration;
|
||||
float glucoseConcentration;
|
||||
/** Concentration unit. One of the following: {@link GlucoseRecord#UNIT_kgpl}, {@link GlucoseRecord#UNIT_molpl} */
|
||||
protected int unit;
|
||||
int unit;
|
||||
/** The type of the record. 0 if not present */
|
||||
protected int type;
|
||||
int type;
|
||||
/** The sample location. 0 if unknown */
|
||||
protected int sampleLocation;
|
||||
int sampleLocation;
|
||||
/** Sensor status annunciation flags. 0 if not present */
|
||||
protected int status;
|
||||
int status;
|
||||
|
||||
protected MeasurementContext context;
|
||||
|
||||
public static class MeasurementContext {
|
||||
public static final int UNIT_kg = 0;
|
||||
public static final int UNIT_l = 1;
|
||||
@SuppressWarnings("unused")
|
||||
static class MeasurementContext {
|
||||
static final int UNIT_kg = 0;
|
||||
static final int UNIT_l = 1;
|
||||
|
||||
/**
|
||||
* One of the following:<br/>
|
||||
@@ -61,9 +63,9 @@ public class GlucoseRecord {
|
||||
* 6 Supper<br/>
|
||||
* 7 Brunch
|
||||
*/
|
||||
protected int carbohydrateId;
|
||||
int carbohydrateId;
|
||||
/** Number of kilograms of carbohydrate */
|
||||
protected float carbohydrateUnits;
|
||||
float carbohydrateUnits;
|
||||
/**
|
||||
* One of the following:<br/>
|
||||
* 0 Not present<br/>
|
||||
@@ -73,7 +75,7 @@ public class GlucoseRecord {
|
||||
* 4 Casual (snacks, drinks, etc.)<br/>
|
||||
* 5 Bedtime
|
||||
*/
|
||||
protected int meal;
|
||||
int meal;
|
||||
/**
|
||||
* One of the following:<br/>
|
||||
* 0 Not present<br/>
|
||||
@@ -82,7 +84,7 @@ public class GlucoseRecord {
|
||||
* 3 Lab test<br/>
|
||||
* 15 Tester value not available
|
||||
*/
|
||||
protected int tester;
|
||||
int tester;
|
||||
/**
|
||||
* One of the following:<br/>
|
||||
* 0 Not present<br/>
|
||||
@@ -93,11 +95,11 @@ public class GlucoseRecord {
|
||||
* 5 No health issues<br/>
|
||||
* 15 Tester value not available
|
||||
*/
|
||||
protected int health;
|
||||
int health;
|
||||
/** Exercise duration in seconds. 0 if not present */
|
||||
protected int exerciseDuration;
|
||||
int exerciseDuration;
|
||||
/** Exercise intensity in percent. 0 if not present */
|
||||
protected int exerciseIntensity;
|
||||
int exerciseIntensity;
|
||||
/**
|
||||
* One of the following:<br/>
|
||||
* 0 Not present<br/>
|
||||
@@ -107,12 +109,12 @@ public class GlucoseRecord {
|
||||
* 4 Long acting insulin<br/>
|
||||
* 5 Pre-mixed insulin
|
||||
*/
|
||||
protected int medicationId;
|
||||
int medicationId;
|
||||
/** Quantity of medication. See {@link #medicationUnit} for the unit. */
|
||||
protected float medicationQuantity;
|
||||
float medicationQuantity;
|
||||
/** One of the following: {@link GlucoseRecord.MeasurementContext#UNIT_kg}, {@link GlucoseRecord.MeasurementContext#UNIT_l}. */
|
||||
protected int medicationUnit;
|
||||
int medicationUnit;
|
||||
/** HbA1c value. 0 if not present */
|
||||
protected float HbA1c;
|
||||
float HbA1c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import android.content.Intent;
|
||||
import android.graphics.Point;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.view.ViewGroup;
|
||||
@@ -57,17 +59,17 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
||||
|
||||
private final static int REFRESH_INTERVAL = 1000; // 1 second interval
|
||||
|
||||
private Handler mHandler = new Handler();
|
||||
private Handler handler = new Handler();
|
||||
|
||||
private boolean isGraphInProgress = false;
|
||||
|
||||
private GraphicalView mGraphView;
|
||||
private LineGraphView mLineGraph;
|
||||
private TextView mHRSValue, mHRSPosition;
|
||||
private TextView mBatteryLevelView;
|
||||
private GraphicalView graphView;
|
||||
private LineGraphView lineGraph;
|
||||
private TextView hrValueView, hrLocationView;
|
||||
private TextView batteryLevelView;
|
||||
|
||||
private int mHrmValue = 0;
|
||||
private int mCounter = 0;
|
||||
private int hrValue = 0;
|
||||
private int counter = 0;
|
||||
|
||||
@Override
|
||||
protected void onCreateView(final Bundle savedInstanceState) {
|
||||
@@ -76,17 +78,17 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
||||
}
|
||||
|
||||
private void setGUI() {
|
||||
mLineGraph = LineGraphView.getLineGraphView();
|
||||
mHRSValue = findViewById(R.id.text_hrs_value);
|
||||
mHRSPosition = findViewById(R.id.text_hrs_position);
|
||||
mBatteryLevelView = findViewById(R.id.battery);
|
||||
lineGraph = LineGraphView.getLineGraphView();
|
||||
hrValueView = findViewById(R.id.text_hrs_value);
|
||||
hrLocationView = findViewById(R.id.text_hrs_position);
|
||||
batteryLevelView = findViewById(R.id.battery);
|
||||
showGraph();
|
||||
}
|
||||
|
||||
private void showGraph() {
|
||||
mGraphView = mLineGraph.getView(this);
|
||||
graphView = lineGraph.getView(this);
|
||||
ViewGroup layout = findViewById(R.id.graph_hrs);
|
||||
layout.addView(mGraphView);
|
||||
layout.addView(graphView);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,20 +111,20 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
|
||||
isGraphInProgress = savedInstanceState.getBoolean(GRAPH_STATUS);
|
||||
mCounter = savedInstanceState.getInt(GRAPH_COUNTER);
|
||||
mHrmValue = savedInstanceState.getInt(HR_VALUE);
|
||||
counter = savedInstanceState.getInt(GRAPH_COUNTER);
|
||||
hrValue = savedInstanceState.getInt(HR_VALUE);
|
||||
|
||||
if (isGraphInProgress)
|
||||
startShowGraph();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(final Bundle outState) {
|
||||
protected void onSaveInstanceState(@NonNull final Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putBoolean(GRAPH_STATUS, isGraphInProgress);
|
||||
outState.putInt(GRAPH_COUNTER, mCounter);
|
||||
outState.putInt(HR_VALUE, mHrmValue);
|
||||
outState.putInt(GRAPH_COUNTER, counter);
|
||||
outState.putInt(HR_VALUE, hrValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,35 +155,35 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
||||
}
|
||||
|
||||
private void updateGraph(final int hrmValue) {
|
||||
mCounter++;
|
||||
mLineGraph.addValue(new Point(mCounter, hrmValue));
|
||||
mGraphView.repaint();
|
||||
counter++;
|
||||
lineGraph.addValue(new Point(counter, hrmValue));
|
||||
graphView.repaint();
|
||||
}
|
||||
|
||||
private Runnable mRepeatTask = new Runnable() {
|
||||
private Runnable repeatTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mHrmValue > 0)
|
||||
updateGraph(mHrmValue);
|
||||
if (hrValue > 0)
|
||||
updateGraph(hrValue);
|
||||
if (isGraphInProgress)
|
||||
mHandler.postDelayed(mRepeatTask, REFRESH_INTERVAL);
|
||||
handler.postDelayed(repeatTask, REFRESH_INTERVAL);
|
||||
}
|
||||
};
|
||||
|
||||
void startShowGraph() {
|
||||
isGraphInProgress = true;
|
||||
mRepeatTask.run();
|
||||
repeatTask.run();
|
||||
}
|
||||
|
||||
void stopShowGraph() {
|
||||
isGraphInProgress = false;
|
||||
mHandler.removeCallbacks(mRepeatTask);
|
||||
handler.removeCallbacks(repeatTask);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggableBleManager<HRSManagerCallbacks> initializeManager() {
|
||||
final HRSManager manager = HRSManager.getInstance(getApplicationContext());
|
||||
manager.setGattCallbacks(this);
|
||||
manager.setManagerCallbacks(this);
|
||||
return manager;
|
||||
}
|
||||
|
||||
@@ -197,52 +199,53 @@ public class HRSActivity extends BleProfileActivity implements HRSManagerCallbac
|
||||
|
||||
@Override
|
||||
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) {
|
||||
runOnUiThread(() -> mBatteryLevelView.setText(getString(R.string.battery, batteryLevel)));
|
||||
runOnUiThread(() -> this.batteryLevelView.setText(getString(R.string.battery, batteryLevel)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBodySensorLocationReceived(@NonNull final BluetoothDevice device, final int sensorLocation) {
|
||||
runOnUiThread(() -> {
|
||||
if (sensorLocation >= SENSOR_LOCATION_FIRST && sensorLocation <= SENSOR_LOCATION_LAST) {
|
||||
mHRSPosition.setText(getResources().getStringArray(R.array.hrs_locations)[sensorLocation]);
|
||||
hrLocationView.setText(getResources().getStringArray(R.array.hrs_locations)[sensorLocation]);
|
||||
} else {
|
||||
mHRSPosition.setText(R.string.hrs_location_other);
|
||||
hrLocationView.setText(R.string.hrs_location_other);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHeartRateMeasurementReceived(@NonNull final BluetoothDevice device, final int heartRate,
|
||||
public void onHeartRateMeasurementReceived(@NonNull final BluetoothDevice device,
|
||||
@IntRange(from = 0) final int heartRate,
|
||||
@Nullable final Boolean contactDetected,
|
||||
@Nullable final Integer energyExpanded,
|
||||
@Nullable @IntRange(from = 0) final Integer energyExpanded,
|
||||
@Nullable final List<Integer> rrIntervals) {
|
||||
mHrmValue = heartRate;
|
||||
runOnUiThread(() -> mHRSValue.setText(getString(R.string.hrs_value, heartRate)));
|
||||
hrValue = heartRate;
|
||||
runOnUiThread(() -> hrValueView.setText(getString(R.string.hrs_value, heartRate)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
runOnUiThread(() -> {
|
||||
mHRSValue.setText(R.string.not_available_value);
|
||||
mHRSPosition.setText(R.string.not_available);
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
hrValueView.setText(R.string.not_available_value);
|
||||
hrLocationView.setText(R.string.not_available);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
stopShowGraph();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setDefaultUI() {
|
||||
mHRSValue.setText(R.string.not_available_value);
|
||||
mHRSPosition.setText(R.string.not_available);
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
hrValueView.setText(R.string.not_available_value);
|
||||
hrLocationView.setText(R.string.not_available);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
clearGraph();
|
||||
}
|
||||
|
||||
private void clearGraph() {
|
||||
mLineGraph.clearGraph();
|
||||
mGraphView.repaint();
|
||||
mCounter = 0;
|
||||
mHrmValue = 0;
|
||||
lineGraph.clearGraph();
|
||||
graphView.repaint();
|
||||
counter = 0;
|
||||
hrValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.bluetooth.BluetoothGattService;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
@@ -35,6 +37,7 @@ import java.util.UUID;
|
||||
|
||||
import no.nordicsemi.android.ble.common.callback.hr.BodySensorLocationDataCallback;
|
||||
import no.nordicsemi.android.ble.common.callback.hr.HeartRateMeasurementDataCallback;
|
||||
import no.nordicsemi.android.ble.common.profile.hr.BodySensorLocation;
|
||||
import no.nordicsemi.android.ble.data.Data;
|
||||
import no.nordicsemi.android.log.LogContract;
|
||||
import no.nordicsemi.android.nrftoolbox.battery.BatteryManager;
|
||||
@@ -52,7 +55,7 @@ public class HRSManager extends BatteryManager<HRSManagerCallbacks> {
|
||||
private static final UUID BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID = UUID.fromString("00002A38-0000-1000-8000-00805f9b34fb");
|
||||
private static final UUID HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A37-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private BluetoothGattCharacteristic mHeartRateCharacteristic, mBodySensorLocationCharacteristic;
|
||||
private BluetoothGattCharacteristic heartRateCharacteristic, bodySensorLocationCharacteristic;
|
||||
|
||||
private static HRSManager managerInstance = null;
|
||||
|
||||
@@ -73,19 +76,19 @@ public class HRSManager extends BatteryManager<HRSManagerCallbacks> {
|
||||
@NonNull
|
||||
@Override
|
||||
protected BatteryManagerGattCallback getGattCallback() {
|
||||
return mGattCallback;
|
||||
return gattCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* BluetoothGatt callbacks for connection/disconnection, service discovery,
|
||||
* receiving notification, etc.
|
||||
*/
|
||||
private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
|
||||
private final BatteryManagerGattCallback gattCallback = new BatteryManagerGattCallback() {
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
super.initialize();
|
||||
readCharacteristic(mBodySensorLocationCharacteristic)
|
||||
readCharacteristic(bodySensorLocationCharacteristic)
|
||||
.with(new BodySensorLocationDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||
@@ -95,13 +98,13 @@ public class HRSManager extends BatteryManager<HRSManagerCallbacks> {
|
||||
|
||||
@Override
|
||||
public void onBodySensorLocationReceived(@NonNull final BluetoothDevice device,
|
||||
final int sensorLocation) {
|
||||
mCallbacks.onBodySensorLocationReceived(device, sensorLocation);
|
||||
@BodySensorLocation final int sensorLocation) {
|
||||
callbacks.onBodySensorLocationReceived(device, sensorLocation);
|
||||
}
|
||||
})
|
||||
.fail((device, status) -> log(Log.WARN, "Body Sensor Location characteristic not found"))
|
||||
.enqueue();
|
||||
setNotificationCallback(mHeartRateCharacteristic)
|
||||
setNotificationCallback(heartRateCharacteristic)
|
||||
.with(new HeartRateMeasurementDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||
@@ -111,23 +114,23 @@ public class HRSManager extends BatteryManager<HRSManagerCallbacks> {
|
||||
|
||||
@Override
|
||||
public void onHeartRateMeasurementReceived(@NonNull final BluetoothDevice device,
|
||||
final int heartRate,
|
||||
@IntRange(from = 0) final int heartRate,
|
||||
@Nullable final Boolean contactDetected,
|
||||
@Nullable final Integer energyExpanded,
|
||||
@Nullable @IntRange(from = 0) final Integer energyExpanded,
|
||||
@Nullable final List<Integer> rrIntervals) {
|
||||
mCallbacks.onHeartRateMeasurementReceived(device, heartRate, contactDetected, energyExpanded, rrIntervals);
|
||||
callbacks.onHeartRateMeasurementReceived(device, heartRate, contactDetected, energyExpanded, rrIntervals);
|
||||
}
|
||||
});
|
||||
enableNotifications(mHeartRateCharacteristic).enqueue();
|
||||
enableNotifications(heartRateCharacteristic).enqueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(HR_SERVICE_UUID);
|
||||
if (service != null) {
|
||||
mHeartRateCharacteristic = service.getCharacteristic(HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID);
|
||||
heartRateCharacteristic = service.getCharacteristic(HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID);
|
||||
}
|
||||
return mHeartRateCharacteristic != null;
|
||||
return heartRateCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -135,16 +138,16 @@ public class HRSManager extends BatteryManager<HRSManagerCallbacks> {
|
||||
super.isOptionalServiceSupported(gatt);
|
||||
final BluetoothGattService service = gatt.getService(HR_SERVICE_UUID);
|
||||
if (service != null) {
|
||||
mBodySensorLocationCharacteristic = service.getCharacteristic(BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID);
|
||||
bodySensorLocationCharacteristic = service.getCharacteristic(BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID);
|
||||
}
|
||||
return mBodySensorLocationCharacteristic != null;
|
||||
return bodySensorLocationCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeviceDisconnected() {
|
||||
super.onDeviceDisconnected();
|
||||
mBodySensorLocationCharacteristic = null;
|
||||
mHeartRateCharacteristic = null;
|
||||
bodySensorLocationCharacteristic = null;
|
||||
heartRateCharacteristic = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -34,34 +34,37 @@ import org.achartengine.model.XYMultipleSeriesDataset;
|
||||
import org.achartengine.renderer.XYMultipleSeriesRenderer;
|
||||
import org.achartengine.renderer.XYSeriesRenderer;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* This class uses external library AChartEngine to show dynamic real time line graph for HR values
|
||||
*/
|
||||
public class LineGraphView {
|
||||
class LineGraphView {
|
||||
//TimeSeries will hold the data in x,y format for single chart
|
||||
private TimeSeries mSeries = new TimeSeries("Heart Rate");
|
||||
private TimeSeries series = new TimeSeries("Heart Rate");
|
||||
//XYMultipleSeriesDataset will contain all the TimeSeries
|
||||
private XYMultipleSeriesDataset mDataset = new XYMultipleSeriesDataset();
|
||||
private XYMultipleSeriesDataset dataSet = new XYMultipleSeriesDataset();
|
||||
//XYMultipleSeriesRenderer will contain all XYSeriesRenderer and it can be used to set the properties of whole Graph
|
||||
private XYMultipleSeriesRenderer mMultiRenderer = new XYMultipleSeriesRenderer();
|
||||
private static LineGraphView mInstance = null;
|
||||
private XYMultipleSeriesRenderer multiRenderer = new XYMultipleSeriesRenderer();
|
||||
private static LineGraphView instance = null;
|
||||
|
||||
/**
|
||||
* singleton implementation of LineGraphView class
|
||||
* Singleton implementation of LineGraphView class
|
||||
*/
|
||||
public static synchronized LineGraphView getLineGraphView() {
|
||||
if (mInstance == null) {
|
||||
mInstance = new LineGraphView();
|
||||
@NonNull
|
||||
static synchronized LineGraphView getLineGraphView() {
|
||||
if (instance == null) {
|
||||
instance = new LineGraphView();
|
||||
}
|
||||
return mInstance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor will set some properties of single chart and some properties of whole graph
|
||||
*/
|
||||
public LineGraphView() {
|
||||
//add single line chart mSeries
|
||||
mDataset.addSeries(mSeries);
|
||||
private LineGraphView() {
|
||||
//add single line chart series
|
||||
dataSet.addSeries(series);
|
||||
|
||||
//XYSeriesRenderer is used to set the properties like chart color, style of each point, etc. of single chart
|
||||
final XYSeriesRenderer seriesRenderer = new XYSeriesRenderer();
|
||||
@@ -71,7 +74,7 @@ public class LineGraphView {
|
||||
seriesRenderer.setPointStyle(PointStyle.SQUARE);
|
||||
seriesRenderer.setFillPoints(true);
|
||||
|
||||
final XYMultipleSeriesRenderer renderer = mMultiRenderer;
|
||||
final XYMultipleSeriesRenderer renderer = multiRenderer;
|
||||
//set whole graph background color to transparent color
|
||||
renderer.setBackgroundColor(Color.TRANSPARENT);
|
||||
renderer.setMargins(new int[] { 50, 65, 40, 5 }); // top, left, bottom, right
|
||||
@@ -99,23 +102,22 @@ public class LineGraphView {
|
||||
/**
|
||||
* return graph view to activity
|
||||
*/
|
||||
public GraphicalView getView(Context context) {
|
||||
final GraphicalView graphView = ChartFactory.getLineChartView(context, mDataset, mMultiRenderer);
|
||||
return graphView;
|
||||
GraphicalView getView(@NonNull final Context context) {
|
||||
return ChartFactory.getLineChartView(context, dataSet, multiRenderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* add new x,y value to chart
|
||||
*/
|
||||
public void addValue(Point p) {
|
||||
mSeries.add(p.x, p.y);
|
||||
void addValue(@NonNull final Point p) {
|
||||
series.add(p.x, p.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* clear all previous values of chart
|
||||
*/
|
||||
public void clearGraph() {
|
||||
mSeries.clear();
|
||||
void clearGraph() {
|
||||
series.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import android.view.Menu;
|
||||
import android.widget.TextView;
|
||||
@@ -50,9 +52,9 @@ public class HTSActivity extends BleProfileServiceReadyActivity<HTSService.HTSBi
|
||||
@SuppressWarnings("unused")
|
||||
private final String TAG = "HTSActivity";
|
||||
|
||||
private TextView mTempValue;
|
||||
private TextView mUnit;
|
||||
private TextView mBatteryLevelView;
|
||||
private TextView tempValueView;
|
||||
private TextView unitView;
|
||||
private TextView batteryLevelView;
|
||||
|
||||
@Override
|
||||
protected void onCreateView(final Bundle savedInstanceState) {
|
||||
@@ -62,19 +64,19 @@ public class HTSActivity extends BleProfileServiceReadyActivity<HTSService.HTSBi
|
||||
|
||||
@Override
|
||||
protected void onInitialize(final Bundle savedInstanceState) {
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, makeIntentFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
|
||||
}
|
||||
|
||||
private void setGUI() {
|
||||
mTempValue = findViewById(R.id.text_hts_value);
|
||||
mUnit = findViewById(R.id.text_hts_unit);
|
||||
mBatteryLevelView = findViewById(R.id.battery);
|
||||
tempValueView = findViewById(R.id.text_hts_value);
|
||||
unitView = findViewById(R.id.text_hts_unit);
|
||||
batteryLevelView = findViewById(R.id.battery);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,8 +87,8 @@ public class HTSActivity extends BleProfileServiceReadyActivity<HTSService.HTSBi
|
||||
|
||||
@Override
|
||||
protected void setDefaultUI() {
|
||||
mTempValue.setText(R.string.not_available_value);
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
tempValueView.setText(R.string.not_available_value);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
|
||||
setUnits();
|
||||
}
|
||||
@@ -97,13 +99,13 @@ public class HTSActivity extends BleProfileServiceReadyActivity<HTSService.HTSBi
|
||||
|
||||
switch (unit) {
|
||||
case SettingsFragment.SETTINGS_UNIT_C:
|
||||
mUnit.setText(R.string.hts_unit_celsius);
|
||||
this.unitView.setText(R.string.hts_unit_celsius);
|
||||
break;
|
||||
case SettingsFragment.SETTINGS_UNIT_F:
|
||||
mUnit.setText(R.string.hts_unit_fahrenheit);
|
||||
this.unitView.setText(R.string.hts_unit_fahrenheit);
|
||||
break;
|
||||
case SettingsFragment.SETTINGS_UNIT_K:
|
||||
mUnit.setText(R.string.hts_unit_kelvin);
|
||||
this.unitView.setText(R.string.hts_unit_kelvin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -161,14 +163,14 @@ public class HTSActivity extends BleProfileServiceReadyActivity<HTSService.HTSBi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final BluetoothDevice device, boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(@NonNull final BluetoothDevice device, boolean optionalServicesFound) {
|
||||
// this may notify user or show some views
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
}
|
||||
|
||||
private void onTemperatureMeasurementReceived(Float value) {
|
||||
@@ -187,17 +189,17 @@ public class HTSActivity extends BleProfileServiceReadyActivity<HTSService.HTSBi
|
||||
case SettingsFragment.SETTINGS_UNIT_C:
|
||||
break;
|
||||
}
|
||||
mTempValue.setText(getString(R.string.hts_value, value));
|
||||
tempValueView.setText(getString(R.string.hts_value, value));
|
||||
} else {
|
||||
mTempValue.setText(R.string.not_available_value);
|
||||
tempValueView.setText(R.string.not_available_value);
|
||||
}
|
||||
}
|
||||
|
||||
public void onBatteryLevelChanged(final int value) {
|
||||
mBatteryLevelView.setText(getString(R.string.battery, value));
|
||||
batteryLevelView.setText(getString(R.string.battery, value));
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
|
||||
@@ -33,6 +33,8 @@ import java.util.Calendar;
|
||||
import java.util.UUID;
|
||||
|
||||
import no.nordicsemi.android.ble.common.callback.ht.TemperatureMeasurementDataCallback;
|
||||
import no.nordicsemi.android.ble.common.profile.ht.TemperatureType;
|
||||
import no.nordicsemi.android.ble.common.profile.ht.TemperatureUnit;
|
||||
import no.nordicsemi.android.ble.data.Data;
|
||||
import no.nordicsemi.android.log.LogContract;
|
||||
import no.nordicsemi.android.nrftoolbox.battery.BatteryManager;
|
||||
@@ -46,11 +48,11 @@ import no.nordicsemi.android.nrftoolbox.parser.TemperatureMeasurementParser;
|
||||
*/
|
||||
public class HTSManager extends BatteryManager<HTSManagerCallbacks> {
|
||||
/** Health Thermometer service UUID */
|
||||
public final static UUID HT_SERVICE_UUID = UUID.fromString("00001809-0000-1000-8000-00805f9b34fb");
|
||||
final static UUID HT_SERVICE_UUID = UUID.fromString("00001809-0000-1000-8000-00805f9b34fb");
|
||||
/** Health Thermometer Measurement characteristic UUID */
|
||||
private static final UUID HT_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private BluetoothGattCharacteristic mHTCharacteristic;
|
||||
private BluetoothGattCharacteristic htCharacteristic;
|
||||
|
||||
HTSManager(final Context context) {
|
||||
super(context);
|
||||
@@ -59,18 +61,18 @@ public class HTSManager extends BatteryManager<HTSManagerCallbacks> {
|
||||
@NonNull
|
||||
@Override
|
||||
protected BatteryManagerGattCallback getGattCallback() {
|
||||
return mGattCallback;
|
||||
return gattCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* BluetoothGatt callbacks for connection/disconnection, service discovery,
|
||||
* receiving indication, etc..
|
||||
*/
|
||||
private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
|
||||
private final BatteryManagerGattCallback gattCallback = new BatteryManagerGattCallback() {
|
||||
@Override
|
||||
protected void initialize() {
|
||||
super.initialize();
|
||||
setIndicationCallback(mHTCharacteristic)
|
||||
setIndicationCallback(htCharacteristic)
|
||||
.with(new TemperatureMeasurementDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||
@@ -80,28 +82,28 @@ public class HTSManager extends BatteryManager<HTSManagerCallbacks> {
|
||||
|
||||
@Override
|
||||
public void onTemperatureMeasurementReceived(@NonNull final BluetoothDevice device,
|
||||
final float temperature, final int unit,
|
||||
final float temperature, @TemperatureUnit final int unit,
|
||||
@Nullable final Calendar calendar,
|
||||
@Nullable final Integer type) {
|
||||
mCallbacks.onTemperatureMeasurementReceived(device, temperature, unit, calendar, type);
|
||||
@Nullable @TemperatureType final Integer type) {
|
||||
callbacks.onTemperatureMeasurementReceived(device, temperature, unit, calendar, type);
|
||||
}
|
||||
});
|
||||
enableIndications(mHTCharacteristic).enqueue();
|
||||
enableIndications(htCharacteristic).enqueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(HT_SERVICE_UUID);
|
||||
if (service != null) {
|
||||
mHTCharacteristic = service.getCharacteristic(HT_MEASUREMENT_CHARACTERISTIC_UUID);
|
||||
htCharacteristic = service.getCharacteristic(HT_MEASUREMENT_CHARACTERISTIC_UUID);
|
||||
}
|
||||
return mHTCharacteristic != null;
|
||||
return htCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeviceDisconnected() {
|
||||
super.onDeviceDisconnected();
|
||||
mHTCharacteristic = null;
|
||||
htCharacteristic = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import java.util.Calendar;
|
||||
|
||||
import no.nordicsemi.android.ble.common.profile.ht.TemperatureMeasurementCallback;
|
||||
import no.nordicsemi.android.ble.common.profile.ht.TemperatureType;
|
||||
import no.nordicsemi.android.ble.common.profile.ht.TemperatureUnit;
|
||||
import no.nordicsemi.android.log.Logger;
|
||||
import no.nordicsemi.android.nrftoolbox.FeaturesActivity;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
@@ -61,12 +63,12 @@ public class HTSService extends BleProfileService implements HTSManagerCallbacks
|
||||
private final static int OPEN_ACTIVITY_REQ = 0;
|
||||
private final static int DISCONNECT_REQ = 1;
|
||||
/** The last received temperature value in Celsius degrees. */
|
||||
private Float mTemp;
|
||||
private Float temp;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private HTSManager mManager;
|
||||
private HTSManager manager;
|
||||
|
||||
private final LocalBinder mBinder = new HTSBinder();
|
||||
private final LocalBinder minder = new HTSBinder();
|
||||
|
||||
/**
|
||||
* This local binder is an interface for the bonded activity to operate with the HTS sensor
|
||||
@@ -78,18 +80,18 @@ public class HTSService extends BleProfileService implements HTSManagerCallbacks
|
||||
* @return Temperature value in Celsius.
|
||||
*/
|
||||
Float getTemperature() {
|
||||
return mTemp;
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocalBinder getBinder() {
|
||||
return mBinder;
|
||||
return minder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggableBleManager<HTSManagerCallbacks> initializeManager() {
|
||||
return mManager = new HTSManager(this);
|
||||
return manager = new HTSManager(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -98,14 +100,14 @@ public class HTSService extends BleProfileService implements HTSManagerCallbacks
|
||||
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_DISCONNECT);
|
||||
registerReceiver(mDisconnectActionBroadcastReceiver, filter);
|
||||
registerReceiver(disconnectActionBroadcastReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
// when user has disconnected from the sensor, we have to cancel the notification that we've created some milliseconds before using unbindService
|
||||
cancelNotification();
|
||||
unregisterReceiver(mDisconnectActionBroadcastReceiver);
|
||||
unregisterReceiver(disconnectActionBroadcastReceiver);
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
@@ -121,25 +123,25 @@ public class HTSService extends BleProfileService implements HTSManagerCallbacks
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
mTemp = null;
|
||||
temp = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTemperatureMeasurementReceived(@NonNull final BluetoothDevice device,
|
||||
final float temperature, final int unit,
|
||||
final float temperature, @TemperatureUnit final int unit,
|
||||
@Nullable final Calendar calendar,
|
||||
@Nullable final Integer type) {
|
||||
mTemp = TemperatureMeasurementCallback.toCelsius(temperature, unit);
|
||||
@Nullable @TemperatureType final Integer type) {
|
||||
temp = TemperatureMeasurementCallback.toCelsius(temperature, unit);
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_HTS_MEASUREMENT);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_TEMPERATURE, mTemp);
|
||||
broadcast.putExtra(EXTRA_TEMPERATURE, temp);
|
||||
// ignore the rest
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
if (!mBound) {
|
||||
if (!bound) {
|
||||
// Here we may update the notification to display the current temperature.
|
||||
// TODO modify the notification here
|
||||
}
|
||||
@@ -188,6 +190,7 @@ public class HTSService extends BleProfileService implements HTSManagerCallbacks
|
||||
* f.e. <code><string name="name">%s is connected</string></code>
|
||||
* @param defaults
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private Notification createNotification(final int messageResId, final int defaults) {
|
||||
final Intent parentIntent = new Intent(this, FeaturesActivity.class);
|
||||
parentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
@@ -219,7 +222,7 @@ public class HTSService extends BleProfileService implements HTSManagerCallbacks
|
||||
/**
|
||||
* This broadcast receiver listens for {@link #ACTION_DISCONNECT} that may be fired by pressing Disconnect action button on the notification.
|
||||
*/
|
||||
private final BroadcastReceiver mDisconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver disconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
Logger.i(getLogSession(), "[Notification] Disconnect action pressed");
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
@@ -58,17 +59,17 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
private static final String SIS_DEVICE_NAME = "device_name";
|
||||
protected static final int REQUEST_ENABLE_BT = 2;
|
||||
|
||||
private LoggableBleManager<? extends BleManagerCallbacks> mBleManager;
|
||||
private LoggableBleManager<? extends BleManagerCallbacks> bleManager;
|
||||
|
||||
private TextView mDeviceNameView;
|
||||
private Button mConnectButton;
|
||||
private ILogSession mLogSession;
|
||||
private TextView deviceNameView;
|
||||
private Button connectButton;
|
||||
private ILogSession logSession;
|
||||
|
||||
private boolean mDeviceConnected = false;
|
||||
private String mDeviceName;
|
||||
private boolean deviceConnected = false;
|
||||
private String deviceName;
|
||||
|
||||
@Override
|
||||
protected final void onCreate(final Bundle savedInstanceState) {
|
||||
protected final void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
ensureBLESupported();
|
||||
@@ -82,7 +83,7 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
* Services. The Service should implement ManagerCallbacks interface. The application Activity may communicate with such Service using binding,
|
||||
* broadcast listeners, local broadcast listeners (see support.v4 library), or messages. See the Proximity profile for Service approach.
|
||||
*/
|
||||
mBleManager = initializeManager();
|
||||
bleManager = initializeManager();
|
||||
|
||||
// In onInitialize method a final class may register local broadcast receivers that will listen for events from the service
|
||||
onInitialize(savedInstanceState);
|
||||
@@ -101,7 +102,7 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
/**
|
||||
* You may do some initialization here. This method is called from {@link #onCreate(Bundle)} before the view was created.
|
||||
*/
|
||||
protected void onInitialize(final Bundle savedInstanceState) {
|
||||
protected void onInitialize(@Nullable final Bundle savedInstanceState) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@@ -112,7 +113,7 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}.
|
||||
* Note: <b>Otherwise it is null</b>.
|
||||
*/
|
||||
protected abstract void onCreateView(final Bundle savedInstanceState);
|
||||
protected abstract void onCreateView(@Nullable final Bundle savedInstanceState);
|
||||
|
||||
/**
|
||||
* Called after the view has been created.
|
||||
@@ -120,7 +121,7 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}.
|
||||
* Note: <b>Otherwise it is null</b>.
|
||||
*/
|
||||
protected void onViewCreated(final Bundle savedInstanceState) {
|
||||
protected void onViewCreated(@Nullable final Bundle savedInstanceState) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@@ -130,33 +131,33 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
protected final void setUpView() {
|
||||
// set GUI
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
mConnectButton = findViewById(R.id.action_connect);
|
||||
mDeviceNameView = findViewById(R.id.device_name);
|
||||
connectButton = findViewById(R.id.action_connect);
|
||||
deviceNameView = findViewById(R.id.device_name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
mBleManager.disconnect().enqueue();
|
||||
bleManager.disconnect().enqueue();
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(final Bundle outState) {
|
||||
protected void onSaveInstanceState(@NonNull final Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(SIS_CONNECTION_STATUS, mDeviceConnected);
|
||||
outState.putString(SIS_DEVICE_NAME, mDeviceName);
|
||||
outState.putBoolean(SIS_CONNECTION_STATUS, deviceConnected);
|
||||
outState.putString(SIS_DEVICE_NAME, deviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(final @NonNull Bundle savedInstanceState) {
|
||||
protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
mDeviceConnected = savedInstanceState.getBoolean(SIS_CONNECTION_STATUS);
|
||||
mDeviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
|
||||
deviceConnected = savedInstanceState.getBoolean(SIS_CONNECTION_STATUS);
|
||||
deviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
|
||||
|
||||
if (mDeviceConnected) {
|
||||
mConnectButton.setText(R.string.action_disconnect);
|
||||
if (deviceConnected) {
|
||||
connectButton.setText(R.string.action_disconnect);
|
||||
} else {
|
||||
mConnectButton.setText(R.string.action_connect);
|
||||
connectButton.setText(R.string.action_connect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +179,7 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
|
||||
final int id = item.getItemId();
|
||||
switch (id) {
|
||||
case android.R.id.home:
|
||||
@@ -199,11 +200,11 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
*/
|
||||
public void onConnectClicked(final View view) {
|
||||
if (isBLEEnabled()) {
|
||||
if (!mDeviceConnected) {
|
||||
if (!deviceConnected) {
|
||||
setDefaultUI();
|
||||
showDeviceScanningDialog(getFilterUUID());
|
||||
} else {
|
||||
mBleManager.disconnect().enqueue();
|
||||
bleManager.disconnect().enqueue();
|
||||
}
|
||||
} else {
|
||||
showBLEDialog();
|
||||
@@ -238,18 +239,18 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceSelected(final BluetoothDevice device, final String name) {
|
||||
public void onDeviceSelected(@NonNull final BluetoothDevice device, final String name) {
|
||||
final int titleId = getLoggerProfileTitle();
|
||||
if (titleId > 0) {
|
||||
mLogSession = Logger.newSession(getApplicationContext(), getString(titleId), device.getAddress(), name);
|
||||
logSession = Logger.newSession(getApplicationContext(), getString(titleId), device.getAddress(), name);
|
||||
// If nRF Logger is not installed we may want to use local logger
|
||||
if (mLogSession == null && getLocalAuthorityLogger() != null) {
|
||||
mLogSession = LocalLogSession.newSession(getApplicationContext(), getLocalAuthorityLogger(), device.getAddress(), name);
|
||||
if (logSession == null && getLocalAuthorityLogger() != null) {
|
||||
logSession = LocalLogSession.newSession(getApplicationContext(), getLocalAuthorityLogger(), device.getAddress(), name);
|
||||
}
|
||||
}
|
||||
mDeviceName = name;
|
||||
mBleManager.setLogger(mLogSession);
|
||||
mBleManager.connect(device)
|
||||
deviceName = name;
|
||||
bleManager.setLogger(logSession);
|
||||
bleManager.connect(device)
|
||||
.useAutoConnect(shouldAutoConnect())
|
||||
.retry(3, 100)
|
||||
.enqueue();
|
||||
@@ -263,35 +264,35 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
@Override
|
||||
public void onDeviceConnecting(@NonNull final BluetoothDevice device) {
|
||||
runOnUiThread(() -> {
|
||||
mDeviceNameView.setText(mDeviceName != null ? mDeviceName : getString(R.string.not_available));
|
||||
mConnectButton.setText(R.string.action_connecting);
|
||||
deviceNameView.setText(deviceName != null ? deviceName : getString(R.string.not_available));
|
||||
connectButton.setText(R.string.action_connecting);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnected(@NonNull final BluetoothDevice device) {
|
||||
mDeviceConnected = true;
|
||||
runOnUiThread(() -> mConnectButton.setText(R.string.action_disconnect));
|
||||
deviceConnected = true;
|
||||
runOnUiThread(() -> connectButton.setText(R.string.action_disconnect));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting(@NonNull final BluetoothDevice device) {
|
||||
runOnUiThread(() -> mConnectButton.setText(R.string.action_disconnecting));
|
||||
runOnUiThread(() -> connectButton.setText(R.string.action_disconnecting));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
mDeviceConnected = false;
|
||||
mBleManager.close();
|
||||
deviceConnected = false;
|
||||
bleManager.close();
|
||||
runOnUiThread(() -> {
|
||||
mConnectButton.setText(R.string.action_connect);
|
||||
mDeviceNameView.setText(getDefaultDeviceName());
|
||||
connectButton.setText(R.string.action_connect);
|
||||
deviceNameView.setText(getDefaultDeviceName());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinkLossOccurred(@NonNull final BluetoothDevice device) {
|
||||
mDeviceConnected = false;
|
||||
deviceConnected = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -352,14 +353,14 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
* Returns <code>true</code> if the device is connected. Services may not have been discovered yet.
|
||||
*/
|
||||
protected boolean isDeviceConnected() {
|
||||
return mDeviceConnected;
|
||||
return deviceConnected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the device that the phone is currently connected to or was connected last time
|
||||
*/
|
||||
protected String getDeviceName() {
|
||||
return mDeviceName;
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -417,7 +418,7 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
|
||||
* @return the logger session or <code>null</code>
|
||||
*/
|
||||
protected ILogSession getLogSession() {
|
||||
return mLogSession;
|
||||
return logSession;
|
||||
}
|
||||
|
||||
private void ensureBLESupported() {
|
||||
|
||||
@@ -58,14 +58,14 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
private static final String SIS_DEVICE_NAME = "device_name";
|
||||
protected static final int REQUEST_ENABLE_BT = 2;
|
||||
|
||||
private LoggableBleManager<? extends BleManagerCallbacks> mBleManager;
|
||||
private LoggableBleManager<? extends BleManagerCallbacks> bleManager;
|
||||
|
||||
private TextView mDeviceNameView;
|
||||
private Button mConnectButton;
|
||||
private ILogSession mLogSession;
|
||||
private TextView deviceNameView;
|
||||
private Button connectButton;
|
||||
private ILogSession logSession;
|
||||
|
||||
private boolean mDeviceConnected = false;
|
||||
private String mDeviceName;
|
||||
private boolean deviceConnected = false;
|
||||
private String deviceName;
|
||||
|
||||
@Override
|
||||
protected final void onCreate(final Bundle savedInstanceState) {
|
||||
@@ -82,7 +82,7 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
* Services. The Service should implement ManagerCallbacks interface. The application Activity may communicate with such Service using binding,
|
||||
* broadcast listeners, local broadcast listeners (see support.v4 library), or messages. See the Proximity profile for Service approach.
|
||||
*/
|
||||
mBleManager = initializeManager();
|
||||
bleManager = initializeManager();
|
||||
|
||||
// In onInitialize method a final class may register local broadcast receivers that will listen for events from the service
|
||||
onInitialize(savedInstanceState);
|
||||
@@ -132,33 +132,33 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
protected final void setUpView() {
|
||||
// set GUI
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
mConnectButton = findViewById(R.id.action_connect);
|
||||
mDeviceNameView = findViewById(R.id.device_name);
|
||||
connectButton = findViewById(R.id.action_connect);
|
||||
deviceNameView = findViewById(R.id.device_name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
mBleManager.disconnect().enqueue();
|
||||
bleManager.disconnect().enqueue();
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(final Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(SIS_CONNECTION_STATUS, mDeviceConnected);
|
||||
outState.putString(SIS_DEVICE_NAME, mDeviceName);
|
||||
outState.putBoolean(SIS_CONNECTION_STATUS, deviceConnected);
|
||||
outState.putString(SIS_DEVICE_NAME, deviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(final @NonNull Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
mDeviceConnected = savedInstanceState.getBoolean(SIS_CONNECTION_STATUS);
|
||||
mDeviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
|
||||
deviceConnected = savedInstanceState.getBoolean(SIS_CONNECTION_STATUS);
|
||||
deviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
|
||||
|
||||
if (mDeviceConnected) {
|
||||
mConnectButton.setText(R.string.action_disconnect);
|
||||
if (deviceConnected) {
|
||||
connectButton.setText(R.string.action_disconnect);
|
||||
} else {
|
||||
mConnectButton.setText(R.string.action_connect);
|
||||
connectButton.setText(R.string.action_connect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,11 +202,11 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
*/
|
||||
public void onConnectClicked(final View view) {
|
||||
if (isBLEEnabled()) {
|
||||
if (!mDeviceConnected) {
|
||||
if (!deviceConnected) {
|
||||
setDefaultUI();
|
||||
showDeviceScanningDialog(getFilterUUID());
|
||||
} else {
|
||||
mBleManager.disconnect().enqueue();
|
||||
bleManager.disconnect().enqueue();
|
||||
}
|
||||
} else {
|
||||
showBLEDialog();
|
||||
@@ -241,18 +241,18 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceSelected(final BluetoothDevice device, final String name) {
|
||||
public void onDeviceSelected(@NonNull final BluetoothDevice device, final String name) {
|
||||
final int titleId = getLoggerProfileTitle();
|
||||
if (titleId > 0) {
|
||||
mLogSession = Logger.newSession(getApplicationContext(), getString(titleId), device.getAddress(), name);
|
||||
logSession = Logger.newSession(getApplicationContext(), getString(titleId), device.getAddress(), name);
|
||||
// If nRF Logger is not installed we may want to use local logger
|
||||
if (mLogSession == null && getLocalAuthorityLogger() != null) {
|
||||
mLogSession = LocalLogSession.newSession(getApplicationContext(), getLocalAuthorityLogger(), device.getAddress(), name);
|
||||
if (logSession == null && getLocalAuthorityLogger() != null) {
|
||||
logSession = LocalLogSession.newSession(getApplicationContext(), getLocalAuthorityLogger(), device.getAddress(), name);
|
||||
}
|
||||
}
|
||||
mDeviceName = name;
|
||||
mBleManager.setLogger(mLogSession);
|
||||
mBleManager.connect(device)
|
||||
deviceName = name;
|
||||
bleManager.setLogger(logSession);
|
||||
bleManager.connect(device)
|
||||
.useAutoConnect(shouldAutoConnect())
|
||||
.retry(3, 100)
|
||||
.enqueue();
|
||||
@@ -266,35 +266,35 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
@Override
|
||||
public void onDeviceConnecting(@NonNull final BluetoothDevice device) {
|
||||
runOnUiThread(() -> {
|
||||
mDeviceNameView.setText(mDeviceName != null ? mDeviceName : getString(R.string.not_available));
|
||||
mConnectButton.setText(R.string.action_connecting);
|
||||
deviceNameView.setText(deviceName != null ? deviceName : getString(R.string.not_available));
|
||||
connectButton.setText(R.string.action_connecting);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnected(@NonNull final BluetoothDevice device) {
|
||||
mDeviceConnected = true;
|
||||
runOnUiThread(() -> mConnectButton.setText(R.string.action_disconnect));
|
||||
deviceConnected = true;
|
||||
runOnUiThread(() -> connectButton.setText(R.string.action_disconnect));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting(@NonNull final BluetoothDevice device) {
|
||||
runOnUiThread(() -> mConnectButton.setText(R.string.action_disconnecting));
|
||||
runOnUiThread(() -> connectButton.setText(R.string.action_disconnecting));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
mDeviceConnected = false;
|
||||
mBleManager.close();
|
||||
deviceConnected = false;
|
||||
bleManager.close();
|
||||
runOnUiThread(() -> {
|
||||
mConnectButton.setText(R.string.action_connect);
|
||||
mDeviceNameView.setText(getDefaultDeviceName());
|
||||
connectButton.setText(R.string.action_connect);
|
||||
deviceNameView.setText(getDefaultDeviceName());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinkLossOccurred(@NonNull final BluetoothDevice device) {
|
||||
mDeviceConnected = false;
|
||||
deviceConnected = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -355,14 +355,14 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
* Returns <code>true</code> if the device is connected. Services may not have been discovered yet.
|
||||
*/
|
||||
protected boolean isDeviceConnected() {
|
||||
return mDeviceConnected;
|
||||
return deviceConnected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the device that the phone is currently connected to or was connected last time
|
||||
*/
|
||||
protected String getDeviceName() {
|
||||
return mDeviceName;
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -420,7 +420,7 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
|
||||
* @return the logger session or <code>null</code>
|
||||
*/
|
||||
protected ILogSession getLogSession() {
|
||||
return mLogSession;
|
||||
return logSession;
|
||||
}
|
||||
|
||||
private void ensureBLESupported() {
|
||||
|
||||
@@ -83,16 +83,16 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
public static final int STATE_CONNECTING = 2;
|
||||
public static final int STATE_DISCONNECTING = 3;
|
||||
|
||||
private LoggableBleManager<BleManagerCallbacks> mBleManager;
|
||||
private Handler mHandler;
|
||||
private LoggableBleManager<BleManagerCallbacks> bleManager;
|
||||
private Handler handler;
|
||||
|
||||
protected boolean mBound;
|
||||
private boolean mActivityIsChangingConfiguration;
|
||||
private BluetoothDevice mBluetoothDevice;
|
||||
private String mDeviceName;
|
||||
private ILogSession mLogSession;
|
||||
protected boolean bound;
|
||||
private boolean activityIsChangingConfiguration;
|
||||
private BluetoothDevice bluetoothDevice;
|
||||
private String deviceName;
|
||||
private ILogSession logSession;
|
||||
|
||||
private final BroadcastReceiver mBluetoothStateBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver bluetoothStateBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
|
||||
@@ -133,14 +133,14 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* Disconnects from the sensor.
|
||||
*/
|
||||
public final void disconnect() {
|
||||
final int state = mBleManager.getConnectionState();
|
||||
final int state = bleManager.getConnectionState();
|
||||
if (state == BluetoothGatt.STATE_DISCONNECTED || state == BluetoothGatt.STATE_DISCONNECTING) {
|
||||
mBleManager.close();
|
||||
onDeviceDisconnected(mBluetoothDevice);
|
||||
bleManager.close();
|
||||
onDeviceDisconnected(bluetoothDevice);
|
||||
return;
|
||||
}
|
||||
|
||||
mBleManager.disconnect().enqueue();
|
||||
bleManager.disconnect().enqueue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,7 +150,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @param changing true if the bound activity is finishing
|
||||
*/
|
||||
public void setActivityIsChangingConfiguration(final boolean changing) {
|
||||
mActivityIsChangingConfiguration = changing;
|
||||
activityIsChangingConfiguration = changing;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,7 +159,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return device address
|
||||
*/
|
||||
public String getDeviceAddress() {
|
||||
return mBluetoothDevice.getAddress();
|
||||
return bluetoothDevice.getAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,7 +168,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return the device name
|
||||
*/
|
||||
public String getDeviceName() {
|
||||
return mDeviceName;
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,7 +177,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return the Bluetooth device
|
||||
*/
|
||||
public BluetoothDevice getBluetoothDevice() {
|
||||
return mBluetoothDevice;
|
||||
return bluetoothDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,7 +186,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
return mBleManager.isConnected();
|
||||
return bleManager.isConnected();
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return the connection state, as in {@link BleManager#getConnectionState()}.
|
||||
*/
|
||||
public int getConnectionState() {
|
||||
return mBleManager.getConnectionState();
|
||||
return bleManager.getConnectionState();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,17 +207,17 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return the log session
|
||||
*/
|
||||
public ILogSession getLogSession() {
|
||||
return mLogSession;
|
||||
return logSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(final int level, @NonNull final String message) {
|
||||
Logger.log(mLogSession, level, message);
|
||||
Logger.log(logSession, level, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(final int level, final @StringRes int messageRes, final Object... params) {
|
||||
Logger.log(mLogSession, level, messageRes, params);
|
||||
Logger.log(logSession, level, messageRes, params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* The handler may be used to postpone execution of some operations or to run them in UI thread.
|
||||
*/
|
||||
protected Handler getHandler() {
|
||||
return mHandler;
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,15 +241,15 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
|
||||
@Override
|
||||
public IBinder onBind(final Intent intent) {
|
||||
mBound = true;
|
||||
bound = true;
|
||||
return getBinder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onRebind(final Intent intent) {
|
||||
mBound = true;
|
||||
bound = true;
|
||||
|
||||
if (!mActivityIsChangingConfiguration)
|
||||
if (!activityIsChangingConfiguration)
|
||||
onRebind();
|
||||
}
|
||||
|
||||
@@ -264,9 +264,9 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
|
||||
@Override
|
||||
public final boolean onUnbind(final Intent intent) {
|
||||
mBound = false;
|
||||
bound = false;
|
||||
|
||||
if (!mActivityIsChangingConfiguration)
|
||||
if (!activityIsChangingConfiguration)
|
||||
onUnbind();
|
||||
|
||||
// We want the onRebind method be called if anything else binds to it again
|
||||
@@ -286,14 +286,14 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
mHandler = new Handler();
|
||||
handler = new Handler();
|
||||
|
||||
// Initialize the manager
|
||||
mBleManager = initializeManager();
|
||||
mBleManager.setGattCallbacks(this);
|
||||
bleManager = initializeManager();
|
||||
bleManager.setGattCallbacks(this);
|
||||
|
||||
// Register broadcast receivers
|
||||
registerReceiver(mBluetoothStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
|
||||
registerReceiver(bluetoothStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
|
||||
|
||||
// Service has now been created
|
||||
onServiceCreated();
|
||||
@@ -335,18 +335,18 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
throw new UnsupportedOperationException("No device address at EXTRA_DEVICE_ADDRESS key");
|
||||
|
||||
final Uri logUri = intent.getParcelableExtra(EXTRA_LOG_URI);
|
||||
mLogSession = Logger.openSession(getApplicationContext(), logUri);
|
||||
mDeviceName = intent.getStringExtra(EXTRA_DEVICE_NAME);
|
||||
logSession = Logger.openSession(getApplicationContext(), logUri);
|
||||
deviceName = intent.getStringExtra(EXTRA_DEVICE_NAME);
|
||||
|
||||
Logger.i(mLogSession, "Service started");
|
||||
Logger.i(logSession, "Service started");
|
||||
|
||||
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
final String deviceAddress = intent.getStringExtra(EXTRA_DEVICE_ADDRESS);
|
||||
mBluetoothDevice = adapter.getRemoteDevice(deviceAddress);
|
||||
bluetoothDevice = adapter.getRemoteDevice(deviceAddress);
|
||||
|
||||
mBleManager.setLogger(mLogSession);
|
||||
bleManager.setLogger(logSession);
|
||||
onServiceStarted();
|
||||
mBleManager.connect(mBluetoothDevice)
|
||||
bleManager.connect(bluetoothDevice)
|
||||
.useAutoConnect(shouldAutoConnect())
|
||||
.retry(3, 100)
|
||||
.enqueue();
|
||||
@@ -374,16 +374,16 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
// Unregister broadcast receivers
|
||||
unregisterReceiver(mBluetoothStateBroadcastReceiver);
|
||||
unregisterReceiver(bluetoothStateBroadcastReceiver);
|
||||
|
||||
// shutdown the manager
|
||||
mBleManager.close();
|
||||
Logger.i(mLogSession, "Service destroyed");
|
||||
mBleManager = null;
|
||||
mBluetoothDevice = null;
|
||||
mDeviceName = null;
|
||||
mLogSession = null;
|
||||
mHandler = null;
|
||||
bleManager.close();
|
||||
Logger.i(logSession, "Service destroyed");
|
||||
bleManager = null;
|
||||
bluetoothDevice = null;
|
||||
deviceName = null;
|
||||
logSession = null;
|
||||
handler = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -405,7 +405,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
@Override
|
||||
public void onDeviceConnecting(@NonNull final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTING);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
@@ -414,8 +414,8 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
public void onDeviceConnected(@NonNull final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE_NAME, mDeviceName);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE_NAME, deviceName);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@@ -423,7 +423,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
public void onDeviceDisconnecting(@NonNull final BluetoothDevice device) {
|
||||
// Notify user about changing the state to DISCONNECTING
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTING);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
@@ -447,7 +447,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
// disconnects due to a link loss, the onLinkLossOccurred(BluetoothDevice) method will be called instead.
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTED);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
@@ -457,14 +457,14 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
|
||||
protected void stopService() {
|
||||
// user requested disconnection. We must stop the service
|
||||
Logger.v(mLogSession, "Stopping service...");
|
||||
Logger.v(logSession, "Stopping service...");
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinkLossOccurred(@NonNull final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_LINK_LOSS);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
@@ -472,7 +472,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
@Override
|
||||
public void onServicesDiscovered(@NonNull final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
final Intent broadcast = new Intent(BROADCAST_SERVICES_DISCOVERED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_SERVICE_PRIMARY, true);
|
||||
broadcast.putExtra(EXTRA_SERVICE_SECONDARY, optionalServicesFound);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
@@ -481,14 +481,14 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
@Override
|
||||
public void onDeviceReady(@NonNull final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_DEVICE_READY);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceNotSupported(@NonNull final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_SERVICES_DISCOVERED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_SERVICE_PRIMARY, false);
|
||||
broadcast.putExtra(EXTRA_SERVICE_SECONDARY, false);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
@@ -499,7 +499,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
@Override
|
||||
public void onBatteryValueReceived(@NonNull final BluetoothDevice device, final int value) {
|
||||
final Intent broadcast = new Intent(BROADCAST_BATTERY_LEVEL);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_BATTERY_LEVEL, value);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
@@ -509,7 +509,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
showToast(no.nordicsemi.android.nrftoolbox.common.R.string.bonding);
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
@@ -519,7 +519,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
showToast(no.nordicsemi.android.nrftoolbox.common.R.string.bonded);
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
@@ -529,7 +529,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
showToast(no.nordicsemi.android.nrftoolbox.common.R.string.bonding_failed);
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
@@ -537,7 +537,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
@Override
|
||||
public void onError(@NonNull final BluetoothDevice device, @NonNull final String message, final int errorCode) {
|
||||
final Intent broadcast = new Intent(BROADCAST_ERROR);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_ERROR_MESSAGE, message);
|
||||
broadcast.putExtra(EXTRA_ERROR_CODE, errorCode);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
@@ -549,7 +549,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @param messageResId an resource id of the message to be shown
|
||||
*/
|
||||
protected void showToast(final int messageResId) {
|
||||
mHandler.post(() -> Toast.makeText(BleProfileService.this, messageResId, Toast.LENGTH_SHORT).show());
|
||||
handler.post(() -> Toast.makeText(BleProfileService.this, messageResId, Toast.LENGTH_SHORT).show());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -558,7 +558,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @param message a message to be shown
|
||||
*/
|
||||
protected void showToast(final String message) {
|
||||
mHandler.post(() -> Toast.makeText(BleProfileService.this, message, Toast.LENGTH_SHORT).show());
|
||||
handler.post(() -> Toast.makeText(BleProfileService.this, message, Toast.LENGTH_SHORT).show());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -568,7 +568,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return the log session
|
||||
*/
|
||||
protected ILogSession getLogSession() {
|
||||
return mLogSession;
|
||||
return logSession;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -577,7 +577,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return device address
|
||||
*/
|
||||
protected String getDeviceAddress() {
|
||||
return mBluetoothDevice.getAddress();
|
||||
return bluetoothDevice.getAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -586,7 +586,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return bluetooth device
|
||||
*/
|
||||
protected BluetoothDevice getBluetoothDevice() {
|
||||
return mBluetoothDevice;
|
||||
return bluetoothDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -595,7 +595,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return the device name
|
||||
*/
|
||||
protected String getDeviceName() {
|
||||
return mDeviceName;
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -604,6 +604,6 @@ public abstract class BleProfileService extends Service implements BleManagerCal
|
||||
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
|
||||
*/
|
||||
protected boolean isConnected() {
|
||||
return mBleManager != null && mBleManager.isConnected();
|
||||
return bleManager != null && bleManager.isConnected();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,16 +79,16 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
private static final String LOG_URI = "log_uri";
|
||||
protected static final int REQUEST_ENABLE_BT = 2;
|
||||
|
||||
private E mService;
|
||||
private E service;
|
||||
|
||||
private TextView mDeviceNameView;
|
||||
private Button mConnectButton;
|
||||
private TextView deviceNameView;
|
||||
private Button connectButton;
|
||||
|
||||
private ILogSession mLogSession;
|
||||
private BluetoothDevice mBluetoothDevice;
|
||||
private String mDeviceName;
|
||||
private ILogSession logSession;
|
||||
private BluetoothDevice bluetoothDevice;
|
||||
private String deviceName;
|
||||
|
||||
private final BroadcastReceiver mCommonBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver commonBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
// Check if the broadcast applies the connected device
|
||||
@@ -96,6 +96,9 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
return;
|
||||
|
||||
final BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BleProfileService.EXTRA_DEVICE);
|
||||
if (bluetoothDevice == null)
|
||||
return;
|
||||
|
||||
final String action = intent.getAction();
|
||||
switch (action) {
|
||||
case BleProfileService.BROADCAST_CONNECTION_STATE: {
|
||||
@@ -103,13 +106,13 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
|
||||
switch (state) {
|
||||
case BleProfileService.STATE_CONNECTED: {
|
||||
mDeviceName = intent.getStringExtra(BleProfileService.EXTRA_DEVICE_NAME);
|
||||
deviceName = intent.getStringExtra(BleProfileService.EXTRA_DEVICE_NAME);
|
||||
onDeviceConnected(bluetoothDevice);
|
||||
break;
|
||||
}
|
||||
case BleProfileService.STATE_DISCONNECTED: {
|
||||
onDeviceDisconnected(bluetoothDevice);
|
||||
mDeviceName = null;
|
||||
deviceName = null;
|
||||
break;
|
||||
}
|
||||
case BleProfileService.STATE_LINK_LOSS: {
|
||||
@@ -167,28 +170,28 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
}
|
||||
};
|
||||
|
||||
private ServiceConnection mServiceConnection = new ServiceConnection() {
|
||||
private ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName name, final IBinder service) {
|
||||
final E bleService = mService = (E) service;
|
||||
mBluetoothDevice = bleService.getBluetoothDevice();
|
||||
mLogSession = mService.getLogSession();
|
||||
Logger.d(mLogSession, "Activity bound to the service");
|
||||
final E bleService = BleProfileServiceReadyActivity.this.service = (E) service;
|
||||
bluetoothDevice = bleService.getBluetoothDevice();
|
||||
logSession = bleService.getLogSession();
|
||||
Logger.d(logSession, "Activity bound to the service");
|
||||
onServiceBound(bleService);
|
||||
|
||||
// Update UI
|
||||
mDeviceName = bleService.getDeviceName();
|
||||
mDeviceNameView.setText(mDeviceName);
|
||||
mConnectButton.setText(R.string.action_disconnect);
|
||||
deviceName = bleService.getDeviceName();
|
||||
deviceNameView.setText(deviceName);
|
||||
connectButton.setText(R.string.action_disconnect);
|
||||
|
||||
// And notify user if device is connected
|
||||
if (bleService.isConnected()) {
|
||||
onDeviceConnected(mBluetoothDevice);
|
||||
onDeviceConnected(bluetoothDevice);
|
||||
} else {
|
||||
// If the device is not connected it means that either it is still connecting,
|
||||
// or the link was lost and service is trying to connect to it (autoConnect=true).
|
||||
onDeviceConnecting(mBluetoothDevice);
|
||||
onDeviceConnecting(bluetoothDevice);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,14 +201,14 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
// not when it stops itself or is stopped by the activity.
|
||||
// It will be called only when there is critically low memory, in practice never
|
||||
// when the activity is in foreground.
|
||||
Logger.d(mLogSession, "Activity disconnected from the service");
|
||||
mDeviceNameView.setText(getDefaultDeviceName());
|
||||
mConnectButton.setText(R.string.action_connect);
|
||||
Logger.d(logSession, "Activity disconnected from the service");
|
||||
deviceNameView.setText(getDefaultDeviceName());
|
||||
connectButton.setText(R.string.action_connect);
|
||||
|
||||
mService = null;
|
||||
mDeviceName = null;
|
||||
mBluetoothDevice = null;
|
||||
mLogSession = null;
|
||||
service = null;
|
||||
deviceName = null;
|
||||
bluetoothDevice = null;
|
||||
logSession = null;
|
||||
onServiceUnbound();
|
||||
}
|
||||
};
|
||||
@@ -222,7 +225,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
// Restore the old log session
|
||||
if (savedInstanceState != null) {
|
||||
final Uri logUri = savedInstanceState.getParcelable(LOG_URI);
|
||||
mLogSession = Logger.openSession(getApplicationContext(), logUri);
|
||||
logSession = Logger.openSession(getApplicationContext(), logUri);
|
||||
}
|
||||
|
||||
// In onInitialize method a final class may register local broadcast receivers that will listen for events from the service
|
||||
@@ -238,7 +241,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
// View is ready to be used
|
||||
onViewCreated(savedInstanceState);
|
||||
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mCommonBroadcastReceiver, makeIntentFilter());
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(commonBroadcastReceiver, makeIntentFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -247,16 +250,16 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
|
||||
/*
|
||||
* If the service has not been started before, the following lines will not start it.
|
||||
* However, if it's running, the Activity will bind to it and notified via mServiceConnection.
|
||||
* However, if it's running, the Activity will bind to it and notified via serviceConnection.
|
||||
*/
|
||||
final Intent service = new Intent(this, getServiceClass());
|
||||
// We pass 0 as a flag so the service will not be created if not exists.
|
||||
bindService(service, mServiceConnection, 0);
|
||||
bindService(service, serviceConnection, 0);
|
||||
|
||||
/*
|
||||
* When user exited the UARTActivity while being connected, the log session is kept in
|
||||
* the service. We may not get it before binding to it so in this case this event will
|
||||
* not be logged (mLogSession is null until onServiceConnected(..) is called).
|
||||
* not be logged (logSession is null until onServiceConnected(..) is called).
|
||||
* It will, however, be logged after the orientation changes.
|
||||
*/
|
||||
}
|
||||
@@ -270,17 +273,17 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
// in the service if we are just rotating the screen. However, when the activity will
|
||||
// disappear, we may want to disable some device features to reduce the battery
|
||||
// consumption.
|
||||
if (mService != null)
|
||||
mService.setActivityIsChangingConfiguration(isChangingConfigurations());
|
||||
if (service != null)
|
||||
service.setActivityIsChangingConfiguration(isChangingConfigurations());
|
||||
|
||||
unbindService(mServiceConnection);
|
||||
mService = null;
|
||||
unbindService(serviceConnection);
|
||||
service = null;
|
||||
|
||||
Logger.d(mLogSession, "Activity unbound from the service");
|
||||
Logger.d(logSession, "Activity unbound from the service");
|
||||
onServiceUnbound();
|
||||
mDeviceName = null;
|
||||
mBluetoothDevice = null;
|
||||
mLogSession = null;
|
||||
deviceName = null;
|
||||
bluetoothDevice = null;
|
||||
logSession = null;
|
||||
} catch (final IllegalArgumentException e) {
|
||||
// do nothing, we were not connected to the sensor
|
||||
}
|
||||
@@ -290,7 +293,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mCommonBroadcastReceiver);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(commonBroadcastReceiver);
|
||||
}
|
||||
|
||||
private static IntentFilter makeIntentFilter() {
|
||||
@@ -329,7 +332,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
* @return the service binder or <code>null</code>
|
||||
*/
|
||||
protected E getService() {
|
||||
return mService;
|
||||
return service;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -364,24 +367,24 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
protected final void setUpView() {
|
||||
// set GUI
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
mConnectButton = findViewById(R.id.action_connect);
|
||||
mDeviceNameView = findViewById(R.id.device_name);
|
||||
connectButton = findViewById(R.id.action_connect);
|
||||
deviceNameView = findViewById(R.id.device_name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(final Bundle outState) {
|
||||
protected void onSaveInstanceState(@NonNull final Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString(SIS_DEVICE_NAME, mDeviceName);
|
||||
outState.putParcelable(SIS_DEVICE, mBluetoothDevice);
|
||||
if (mLogSession != null)
|
||||
outState.putParcelable(LOG_URI, mLogSession.getSessionUri());
|
||||
outState.putString(SIS_DEVICE_NAME, deviceName);
|
||||
outState.putParcelable(SIS_DEVICE, bluetoothDevice);
|
||||
if (logSession != null)
|
||||
outState.putParcelable(LOG_URI, logSession.getSessionUri());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(final @NonNull Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
mDeviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
|
||||
mBluetoothDevice = savedInstanceState.getParcelable(SIS_DEVICE);
|
||||
deviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
|
||||
bluetoothDevice = savedInstanceState.getParcelable(SIS_DEVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -423,11 +426,11 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
*/
|
||||
public void onConnectClicked(final View view) {
|
||||
if (isBLEEnabled()) {
|
||||
if (mService == null) {
|
||||
if (service == null) {
|
||||
setDefaultUI();
|
||||
showDeviceScanningDialog(getFilterUUID());
|
||||
} else {
|
||||
mService.disconnect();
|
||||
service.disconnect();
|
||||
}
|
||||
} else {
|
||||
showBLEDialog();
|
||||
@@ -453,28 +456,28 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceSelected(final BluetoothDevice device, final String name) {
|
||||
public void onDeviceSelected(@NonNull final BluetoothDevice device, final String name) {
|
||||
final int titleId = getLoggerProfileTitle();
|
||||
if (titleId > 0) {
|
||||
mLogSession = Logger.newSession(getApplicationContext(), getString(titleId), device.getAddress(), name);
|
||||
logSession = Logger.newSession(getApplicationContext(), getString(titleId), device.getAddress(), name);
|
||||
// If nRF Logger is not installed we may want to use local logger
|
||||
if (mLogSession == null && getLocalAuthorityLogger() != null) {
|
||||
mLogSession = LocalLogSession.newSession(getApplicationContext(), getLocalAuthorityLogger(), device.getAddress(), name);
|
||||
if (logSession == null && getLocalAuthorityLogger() != null) {
|
||||
logSession = LocalLogSession.newSession(getApplicationContext(), getLocalAuthorityLogger(), device.getAddress(), name);
|
||||
}
|
||||
}
|
||||
mBluetoothDevice = device;
|
||||
mDeviceName = name;
|
||||
bluetoothDevice = device;
|
||||
deviceName = name;
|
||||
|
||||
// The device may not be in the range but the service will try to connect to it if it reach it
|
||||
Logger.d(mLogSession, "Creating service...");
|
||||
Logger.d(logSession, "Creating service...");
|
||||
final Intent service = new Intent(this, getServiceClass());
|
||||
service.putExtra(BleProfileService.EXTRA_DEVICE_ADDRESS, device.getAddress());
|
||||
service.putExtra(BleProfileService.EXTRA_DEVICE_NAME, name);
|
||||
if (mLogSession != null)
|
||||
service.putExtra(BleProfileService.EXTRA_LOG_URI, mLogSession.getSessionUri());
|
||||
if (logSession != null)
|
||||
service.putExtra(BleProfileService.EXTRA_LOG_URI, logSession.getSessionUri());
|
||||
startService(service);
|
||||
Logger.d(mLogSession, "Binding to the service...");
|
||||
bindService(service, mServiceConnection, 0);
|
||||
Logger.d(logSession, "Binding to the service...");
|
||||
bindService(service, serviceConnection, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -483,80 +486,80 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnecting(final BluetoothDevice device) {
|
||||
mDeviceNameView.setText(mDeviceName != null ? mDeviceName : getString(R.string.not_available));
|
||||
mConnectButton.setText(R.string.action_connecting);
|
||||
public void onDeviceConnecting(@NonNull final BluetoothDevice device) {
|
||||
deviceNameView.setText(deviceName != null ? deviceName : getString(R.string.not_available));
|
||||
connectButton.setText(R.string.action_connecting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnected(final BluetoothDevice device) {
|
||||
mDeviceNameView.setText(mDeviceName);
|
||||
mConnectButton.setText(R.string.action_disconnect);
|
||||
public void onDeviceConnected(@NonNull final BluetoothDevice device) {
|
||||
deviceNameView.setText(deviceName);
|
||||
connectButton.setText(R.string.action_disconnect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting(final BluetoothDevice device) {
|
||||
mConnectButton.setText(R.string.action_disconnecting);
|
||||
public void onDeviceDisconnecting(@NonNull final BluetoothDevice device) {
|
||||
connectButton.setText(R.string.action_disconnecting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
mConnectButton.setText(R.string.action_connect);
|
||||
mDeviceNameView.setText(getDefaultDeviceName());
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
connectButton.setText(R.string.action_connect);
|
||||
deviceNameView.setText(getDefaultDeviceName());
|
||||
|
||||
try {
|
||||
Logger.d(mLogSession, "Unbinding from the service...");
|
||||
unbindService(mServiceConnection);
|
||||
mService = null;
|
||||
Logger.d(logSession, "Unbinding from the service...");
|
||||
unbindService(serviceConnection);
|
||||
service = null;
|
||||
|
||||
Logger.d(mLogSession, "Activity unbound from the service");
|
||||
Logger.d(logSession, "Activity unbound from the service");
|
||||
onServiceUnbound();
|
||||
mDeviceName = null;
|
||||
mBluetoothDevice = null;
|
||||
mLogSession = null;
|
||||
deviceName = null;
|
||||
bluetoothDevice = null;
|
||||
logSession = null;
|
||||
} catch (final IllegalArgumentException e) {
|
||||
// do nothing. This should never happen but does...
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinkLossOccurred(final BluetoothDevice device) {
|
||||
public void onLinkLossOccurred(@NonNull final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(@NonNull final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceReady(final BluetoothDevice device) {
|
||||
public void onDeviceReady(@NonNull final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBondingRequired(final BluetoothDevice device) {
|
||||
public void onBondingRequired(@NonNull final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBonded(final BluetoothDevice device) {
|
||||
public void onBonded(@NonNull final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBondingFailed(final BluetoothDevice device) {
|
||||
public void onBondingFailed(@NonNull final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
|
||||
public void onError(@NonNull final BluetoothDevice device, @NonNull final String message, final int errorCode) {
|
||||
DebugLogger.e(TAG, "Error occurred: " + message + ", error code: " + errorCode);
|
||||
showToast(message + " (" + errorCode + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceNotSupported(final BluetoothDevice device) {
|
||||
public void onDeviceNotSupported(@NonNull final BluetoothDevice device) {
|
||||
showToast(R.string.not_supported);
|
||||
}
|
||||
|
||||
@@ -582,14 +585,14 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
* Returns <code>true</code> if the device is connected. Services may not have been discovered yet.
|
||||
*/
|
||||
protected boolean isDeviceConnected() {
|
||||
return mService != null && mService.isConnected();
|
||||
return service != null && service.isConnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the device that the phone is currently connected to or was connected last time
|
||||
*/
|
||||
protected String getDeviceName() {
|
||||
return mDeviceName;
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -627,7 +630,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
*/
|
||||
protected boolean isBroadcastForThisDevice(final Intent intent) {
|
||||
final BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BleProfileService.EXTRA_DEVICE);
|
||||
return mBluetoothDevice != null && mBluetoothDevice.equals(bluetoothDevice);
|
||||
return bluetoothDevice != null && bluetoothDevice.equals(bluetoothDevice);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -648,7 +651,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
* @return the logger session or <code>null</code>
|
||||
*/
|
||||
protected ILogSession getLogSession() {
|
||||
return mLogSession;
|
||||
return logSession;
|
||||
}
|
||||
|
||||
private void ensureBLESupported() {
|
||||
@@ -659,8 +662,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
|
||||
}
|
||||
|
||||
protected boolean isBLEEnabled() {
|
||||
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
|
||||
final BluetoothAdapter adapter = bluetoothManager.getAdapter();
|
||||
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
return adapter != null && adapter.isEnabled();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@ import no.nordicsemi.android.log.Logger;
|
||||
* @param <T> the callbacks class.
|
||||
*/
|
||||
public abstract class LoggableBleManager<T extends BleManagerCallbacks> extends BleManager<T> {
|
||||
private ILogSession mLogSession;
|
||||
private ILogSession logSession;
|
||||
|
||||
/**
|
||||
* The manager constructor.
|
||||
* <p>
|
||||
* After constructing the manager, the callbacks object must be set with
|
||||
* {@link #setGattCallbacks(BleManagerCallbacks)}.
|
||||
* {@link #setManagerCallbacks(BleManagerCallbacks)}.
|
||||
*
|
||||
* @param context the context.
|
||||
*/
|
||||
@@ -37,12 +37,12 @@ public abstract class LoggableBleManager<T extends BleManagerCallbacks> extends
|
||||
* @param session nRF Logger log session to log inti, or null, if nRF Logger is not installed.
|
||||
*/
|
||||
public void setLogger(@Nullable final ILogSession session) {
|
||||
mLogSession = session;
|
||||
logSession = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(final int priority, @NonNull final String message) {
|
||||
Logger.log(mLogSession, LogContract.Log.Level.fromPriority(priority), message);
|
||||
Logger.log(logSession, LogContract.Log.Level.fromPriority(priority), message);
|
||||
Log.println(priority, "BleManager", message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,14 +77,14 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
public static final int STATE_CONNECTING = 2;
|
||||
public static final int STATE_DISCONNECTING = 3;
|
||||
|
||||
private HashMap<BluetoothDevice, LoggableBleManager<BleManagerCallbacks>> mBleManagers;
|
||||
private List<BluetoothDevice> mManagedDevices;
|
||||
private Handler mHandler;
|
||||
private HashMap<BluetoothDevice, LoggableBleManager<BleManagerCallbacks>> bleManagers;
|
||||
private List<BluetoothDevice> managedDevices;
|
||||
private Handler handler;
|
||||
|
||||
protected boolean mBound;
|
||||
private boolean mActivityIsChangingConfiguration;
|
||||
protected boolean bound;
|
||||
private boolean activityIsChangingConfiguration;
|
||||
|
||||
private final BroadcastReceiver mBluetoothStateBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver bluetoothStateBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
|
||||
@@ -95,7 +95,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
// On older phones (tested on Nexus 4 with Android 5.0.1) the Bluetooth requires some time
|
||||
// after it has been enabled before some operations can start. Starting the GATT server here
|
||||
// without a delay is very likely to cause a DeadObjectException from BluetoothManager#openGattServer(...).
|
||||
mHandler.postDelayed(() -> onBluetoothEnabled(), 600);
|
||||
handler.postDelayed(() -> onBluetoothEnabled(), 600);
|
||||
break;
|
||||
case BluetoothAdapter.STATE_TURNING_OFF:
|
||||
case BluetoothAdapter.STATE_OFF:
|
||||
@@ -114,7 +114,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* @return unmodifiable list of devices managed by the service
|
||||
*/
|
||||
public final List<BluetoothDevice> getManagedDevices() {
|
||||
return Collections.unmodifiableList(mManagedDevices);
|
||||
return Collections.unmodifiableList(managedDevices);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,26 +134,25 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
public void connect(final BluetoothDevice device, final ILogSession session) {
|
||||
// If a device is in managed devices it means that it's already connected, or was connected
|
||||
// using autoConnect and the link was lost but Android is already trying to connect to it.
|
||||
if (mManagedDevices.contains(device))
|
||||
if (managedDevices.contains(device))
|
||||
return;
|
||||
mManagedDevices.add(device);
|
||||
managedDevices.add(device);
|
||||
|
||||
LoggableBleManager<BleManagerCallbacks> manager = mBleManagers.get(device);
|
||||
if (manager != null) {
|
||||
if (session != null)
|
||||
manager.setLogger(session);
|
||||
manager.connect(device).enqueue();
|
||||
} else {
|
||||
mBleManagers.put(device, manager = initializeManager());
|
||||
manager.setGattCallbacks(BleMulticonnectProfileService.this);
|
||||
manager.setLogger(session);
|
||||
manager.connect(device)
|
||||
.fail((d, status) -> {
|
||||
mManagedDevices.remove(device);
|
||||
mBleManagers.remove(device);
|
||||
})
|
||||
.enqueue(10000);
|
||||
LoggableBleManager<BleManagerCallbacks> manager = bleManagers.get(device);
|
||||
if (manager == null) {
|
||||
bleManagers.put(device, manager = initializeManager());
|
||||
manager.setManagerCallbacks(BleMulticonnectProfileService.this);
|
||||
}
|
||||
manager.setLogger(session);
|
||||
manager.connect(device)
|
||||
.retry(2, 100)
|
||||
.useAutoConnect(shouldAutoConnect())
|
||||
.timeout(10000)
|
||||
.fail((d, status) -> {
|
||||
managedDevices.remove(device);
|
||||
bleManagers.remove(device);
|
||||
})
|
||||
.enqueue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,11 +162,11 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* @param device target device to disconnect and forget
|
||||
*/
|
||||
public void disconnect(final BluetoothDevice device) {
|
||||
final BleManager<BleManagerCallbacks> manager = mBleManagers.get(device);
|
||||
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
|
||||
if (manager != null && manager.isConnected()) {
|
||||
manager.disconnect().enqueue();
|
||||
}
|
||||
mManagedDevices.remove(device);
|
||||
managedDevices.remove(device);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,7 +175,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
|
||||
*/
|
||||
public final boolean isConnected(final BluetoothDevice device) {
|
||||
final BleManager<BleManagerCallbacks> manager = mBleManagers.get(device);
|
||||
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
|
||||
return manager != null && manager.isConnected();
|
||||
}
|
||||
|
||||
@@ -187,7 +186,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* initializing. False otherwise.
|
||||
*/
|
||||
public final boolean isReady(final BluetoothDevice device) {
|
||||
final BleManager<BleManagerCallbacks> manager = mBleManagers.get(device);
|
||||
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
|
||||
return manager != null && manager.isReady();
|
||||
}
|
||||
|
||||
@@ -196,8 +195,9 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* @param device the target device
|
||||
* @return the connection state, as in {@link BleManager#getConnectionState()}.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public final int getConnectionState(final BluetoothDevice device) {
|
||||
final BleManager<BleManagerCallbacks> manager = mBleManagers.get(device);
|
||||
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
|
||||
return manager != null ? manager.getConnectionState() : BluetoothGatt.STATE_DISCONNECTED;
|
||||
}
|
||||
|
||||
@@ -207,10 +207,13 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* @return battery value or -1 if no value was received or Battery Level characteristic was not found
|
||||
* @deprecated Keep battery value in your manager instead.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
public int getBatteryValue(final BluetoothDevice device) {
|
||||
final BleManager<BleManagerCallbacks> manager = mBleManagers.get(device);
|
||||
return manager.getBatteryValue();
|
||||
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
|
||||
if (manager != null)
|
||||
return manager.getBatteryValue();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,33 +221,34 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* If <code>false</code>, we will turn off battery level notifications in onUnbind(..) method below.
|
||||
* @param changing true if the bound activity is finishing
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public final void setActivityIsChangingConfiguration(final boolean changing) {
|
||||
mActivityIsChangingConfiguration = changing;
|
||||
activityIsChangingConfiguration = changing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(final BluetoothDevice device, final int level, final String message) {
|
||||
final BleManager<BleManagerCallbacks> manager = mBleManagers.get(device);
|
||||
public void log(@NonNull final BluetoothDevice device, final int level, final String message) {
|
||||
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
|
||||
if (manager != null)
|
||||
manager.log(level, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(final BluetoothDevice device, final int level, @StringRes final int messageRes, final Object... params) {
|
||||
final BleManager<BleManagerCallbacks> manager = mBleManagers.get(device);
|
||||
public void log(@NonNull final BluetoothDevice device, final int level, @StringRes final int messageRes, final Object... params) {
|
||||
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
|
||||
if (manager != null)
|
||||
manager.log(level, messageRes, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(final int level, @NonNull final String message) {
|
||||
for (final BleManager<BleManagerCallbacks> manager : mBleManagers.values())
|
||||
for (final BleManager<BleManagerCallbacks> manager : bleManagers.values())
|
||||
manager.log(level, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(final int level, @StringRes final int messageRes, final Object... params) {
|
||||
for (final BleManager<BleManagerCallbacks> manager : mBleManagers.values())
|
||||
for (final BleManager<BleManagerCallbacks> manager : bleManagers.values())
|
||||
manager.log(level, messageRes, params);
|
||||
}
|
||||
}
|
||||
@@ -254,7 +258,16 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* The handler may be used to postpone execution of some operations or to run them in UI thread.
|
||||
*/
|
||||
protected Handler getHandler() {
|
||||
return mHandler;
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns whether autoConnect option should be used.
|
||||
*
|
||||
* @return true to use autoConnect feature, false (default) otherwise.
|
||||
*/
|
||||
protected boolean shouldAutoConnect() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,15 +282,15 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
|
||||
@Override
|
||||
public IBinder onBind(final Intent intent) {
|
||||
mBound = true;
|
||||
bound = true;
|
||||
return getBinder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onRebind(final Intent intent) {
|
||||
mBound = true;
|
||||
bound = true;
|
||||
|
||||
if (!mActivityIsChangingConfiguration) {
|
||||
if (!activityIsChangingConfiguration) {
|
||||
onRebind();
|
||||
}
|
||||
}
|
||||
@@ -293,10 +306,10 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
|
||||
@Override
|
||||
public final boolean onUnbind(final Intent intent) {
|
||||
mBound = false;
|
||||
bound = false;
|
||||
|
||||
if (!mActivityIsChangingConfiguration) {
|
||||
if (!mManagedDevices.isEmpty()) {
|
||||
if (!activityIsChangingConfiguration) {
|
||||
if (!managedDevices.isEmpty()) {
|
||||
onUnbind();
|
||||
} else {
|
||||
// The last activity has disconnected from the service and there are no devices to manage. The service may be stopped.
|
||||
@@ -320,14 +333,14 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
mHandler = new Handler();
|
||||
handler = new Handler();
|
||||
|
||||
// Initialize the map of BLE managers
|
||||
mBleManagers = new HashMap<>();
|
||||
mManagedDevices = new ArrayList<>();
|
||||
bleManagers = new HashMap<>();
|
||||
managedDevices = new ArrayList<>();
|
||||
|
||||
// Register broadcast receivers
|
||||
registerReceiver(mBluetoothStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
|
||||
registerReceiver(bluetoothStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
|
||||
|
||||
// Service has now been created
|
||||
onServiceCreated();
|
||||
@@ -381,7 +394,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
onServiceStopped();
|
||||
mHandler = null;
|
||||
handler = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -389,18 +402,18 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
*/
|
||||
protected void onServiceStopped() {
|
||||
// Unregister broadcast receivers
|
||||
unregisterReceiver(mBluetoothStateBroadcastReceiver);
|
||||
unregisterReceiver(bluetoothStateBroadcastReceiver);
|
||||
|
||||
// The managers map may not be empty if the service was killed by the system
|
||||
for (final BleManager<BleManagerCallbacks> manager : mBleManagers.values()) {
|
||||
for (final BleManager<BleManagerCallbacks> manager : bleManagers.values()) {
|
||||
// Service is being destroyed, no need to disconnect manually.
|
||||
manager.close();
|
||||
manager.log(Log.INFO, "Service destroyed");
|
||||
}
|
||||
mBleManagers.clear();
|
||||
mManagedDevices.clear();
|
||||
mBleManagers = null;
|
||||
mManagedDevices = null;
|
||||
bleManagers.clear();
|
||||
managedDevices.clear();
|
||||
bleManagers = null;
|
||||
managedDevices = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -418,15 +431,15 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* devices that were connected before the Bluetooth was turned off.
|
||||
*/
|
||||
protected void onBluetoothEnabled() {
|
||||
for (final BluetoothDevice device : mManagedDevices) {
|
||||
final BleManager<BleManagerCallbacks> manager = mBleManagers.get(device);
|
||||
if (!manager.isConnected())
|
||||
for (final BluetoothDevice device : managedDevices) {
|
||||
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
|
||||
if (manager != null && !manager.isConnected())
|
||||
manager.connect(device).enqueue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnecting(final BluetoothDevice device) {
|
||||
public void onDeviceConnecting(@NonNull final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, device);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTING);
|
||||
@@ -434,7 +447,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnected(final BluetoothDevice device) {
|
||||
public void onDeviceConnected(@NonNull final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, device);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTED);
|
||||
@@ -442,7 +455,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting(final BluetoothDevice device) {
|
||||
public void onDeviceDisconnecting(@NonNull final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, device);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTING);
|
||||
@@ -450,15 +463,15 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
// Note: if BleManager#shouldAutoConnect() for this device returned true, this callback will be
|
||||
// invoked ONLY when user requested disconnection (using Disconnect button). If the device
|
||||
// disconnects due to a link loss, the onLinkLossOccurred(BluetoothDevice) method will be called instead.
|
||||
|
||||
// We no longer want to keep the device in the service
|
||||
mManagedDevices.remove(device);
|
||||
managedDevices.remove(device);
|
||||
// The BleManager is not removed from the HashMap in order to keep the device's log session.
|
||||
// mBleManagers.remove(device);
|
||||
// bleManagers.remove(device);
|
||||
|
||||
// Do not use the device argument here unless you change calling onDeviceDisconnected from the binder above
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
@@ -467,13 +480,13 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
// When user disconnected the last device while the activity was not bound the service can be stopped
|
||||
if (!mBound && mManagedDevices.isEmpty()) {
|
||||
if (!bound && managedDevices.isEmpty()) {
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinkLossOccurred(final BluetoothDevice device) {
|
||||
public void onLinkLossOccurred(@NonNull final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, device);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_LINK_LOSS);
|
||||
@@ -481,7 +494,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(@NonNull final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
final Intent broadcast = new Intent(BROADCAST_SERVICES_DISCOVERED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, device);
|
||||
broadcast.putExtra(EXTRA_SERVICE_PRIMARY, true);
|
||||
@@ -490,17 +503,17 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceReady(final BluetoothDevice device) {
|
||||
public void onDeviceReady(@NonNull final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_DEVICE_READY);
|
||||
broadcast.putExtra(EXTRA_DEVICE, device);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceNotSupported(final BluetoothDevice device) {
|
||||
public void onDeviceNotSupported(@NonNull final BluetoothDevice device) {
|
||||
// We don't like this device, remove it from both collections
|
||||
mManagedDevices.remove(device);
|
||||
mBleManagers.remove(device);
|
||||
managedDevices.remove(device);
|
||||
bleManagers.remove(device);
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_SERVICES_DISCOVERED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, device);
|
||||
@@ -511,8 +524,9 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
// no need for disconnecting, it will be disconnected by the manager automatically
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onBatteryValueReceived(final BluetoothDevice device, final int value) {
|
||||
public void onBatteryValueReceived(@NonNull final BluetoothDevice device, final int value) {
|
||||
final Intent broadcast = new Intent(BROADCAST_BATTERY_LEVEL);
|
||||
broadcast.putExtra(EXTRA_DEVICE, device);
|
||||
broadcast.putExtra(EXTRA_BATTERY_LEVEL, value);
|
||||
@@ -520,7 +534,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBondingRequired(final BluetoothDevice device) {
|
||||
public void onBondingRequired(@NonNull final BluetoothDevice device) {
|
||||
showToast(no.nordicsemi.android.nrftoolbox.common.R.string.bonding);
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
|
||||
@@ -530,7 +544,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBonded(final BluetoothDevice device) {
|
||||
public void onBonded(@NonNull final BluetoothDevice device) {
|
||||
showToast(no.nordicsemi.android.nrftoolbox.common.R.string.bonded);
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
|
||||
@@ -540,7 +554,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBondingFailed(final BluetoothDevice device) {
|
||||
public void onBondingFailed(@NonNull final BluetoothDevice device) {
|
||||
showToast(no.nordicsemi.android.nrftoolbox.common.R.string.bonding_failed);
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
|
||||
@@ -550,7 +564,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
|
||||
public void onError(@NonNull final BluetoothDevice device, @NonNull final String message, final int errorCode) {
|
||||
final Intent broadcast = new Intent(BROADCAST_ERROR);
|
||||
broadcast.putExtra(EXTRA_DEVICE, device);
|
||||
broadcast.putExtra(EXTRA_ERROR_MESSAGE, message);
|
||||
@@ -565,7 +579,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* an resource id of the message to be shown
|
||||
*/
|
||||
protected void showToast(final int messageResId) {
|
||||
mHandler.post(() -> Toast.makeText(BleMulticonnectProfileService.this, messageResId, Toast.LENGTH_SHORT).show());
|
||||
handler.post(() -> Toast.makeText(BleMulticonnectProfileService.this, messageResId, Toast.LENGTH_SHORT).show());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -575,7 +589,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* a message to be shown
|
||||
*/
|
||||
protected void showToast(final String message) {
|
||||
mHandler.post(() -> Toast.makeText(BleMulticonnectProfileService.this, message, Toast.LENGTH_SHORT).show());
|
||||
handler.post(() -> Toast.makeText(BleMulticonnectProfileService.this, message, Toast.LENGTH_SHORT).show());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -585,7 +599,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* @return the BleManager or null
|
||||
*/
|
||||
protected BleManager<? extends BleManagerCallbacks> getBleManager(final BluetoothDevice device) {
|
||||
return mBleManagers.get(device);
|
||||
return bleManagers.get(device);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -593,7 +607,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* @return list of managed devices
|
||||
*/
|
||||
protected List<BluetoothDevice> getManagedDevices() {
|
||||
return Collections.unmodifiableList(mManagedDevices);
|
||||
return Collections.unmodifiableList(managedDevices);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -602,8 +616,9 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
*/
|
||||
protected List<BluetoothDevice> getConnectedDevices() {
|
||||
final List<BluetoothDevice> list = new ArrayList<>();
|
||||
for (BluetoothDevice device : mManagedDevices) {
|
||||
if (mBleManagers.get(device).isConnected())
|
||||
for (BluetoothDevice device : managedDevices) {
|
||||
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
|
||||
if (manager != null && manager.isConnected())
|
||||
list.add(device);
|
||||
}
|
||||
return Collections.unmodifiableList(list);
|
||||
@@ -615,7 +630,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
|
||||
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
|
||||
*/
|
||||
protected boolean isConnected(final BluetoothDevice device) {
|
||||
final BleManager<BleManagerCallbacks> manager = mBleManagers.get(device);
|
||||
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
|
||||
return manager != null && manager.isConnected();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ package no.nordicsemi.android.nrftoolbox.profile.multiconnect;
|
||||
import android.app.Service;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -35,9 +34,6 @@ import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@@ -49,6 +45,10 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import no.nordicsemi.android.ble.BleManagerCallbacks;
|
||||
import no.nordicsemi.android.log.ILogSession;
|
||||
import no.nordicsemi.android.log.LocalLogSession;
|
||||
@@ -71,19 +71,24 @@ import no.nordicsemi.android.nrftoolbox.utility.DebugLogger;
|
||||
* listens for updates from them. When entering back to the activity, activity will to bind to the service and refresh UI.
|
||||
* </p>
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMulticonnectProfileService.LocalBinder> extends AppCompatActivity implements
|
||||
ScannerFragment.OnDeviceSelectedListener, BleManagerCallbacks {
|
||||
private static final String TAG = "BleMulticonnectProfileServiceReadyActivity";
|
||||
|
||||
protected static final int REQUEST_ENABLE_BT = 2;
|
||||
|
||||
private E mService;
|
||||
private List<BluetoothDevice> mManagedDevices;
|
||||
private E service;
|
||||
private List<BluetoothDevice> managedDevices;
|
||||
|
||||
private final BroadcastReceiver mCommonBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver commonBroadcastReceiver = new BroadcastReceiver() {
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BleMulticonnectProfileService.EXTRA_DEVICE);
|
||||
if (bluetoothDevice == null)
|
||||
return;
|
||||
|
||||
final String action = intent.getAction();
|
||||
switch (action) {
|
||||
case BleMulticonnectProfileService.BROADCAST_CONNECTION_STATE: {
|
||||
@@ -159,17 +164,17 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
}
|
||||
};
|
||||
|
||||
private ServiceConnection mServiceConnection = new ServiceConnection() {
|
||||
private ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName name, final IBinder service) {
|
||||
final E bleService = mService = (E) service;
|
||||
final E bleService = BleMulticonnectProfileServiceReadyActivity.this.service = (E) service;
|
||||
bleService.log(Log.DEBUG, "Activity bound to the service");
|
||||
mManagedDevices.addAll(bleService.getManagedDevices());
|
||||
managedDevices.addAll(bleService.getManagedDevices());
|
||||
onServiceBound(bleService);
|
||||
|
||||
// and notify user if device is connected
|
||||
for (final BluetoothDevice device : mManagedDevices) {
|
||||
for (final BluetoothDevice device : managedDevices) {
|
||||
if (bleService.isConnected(device))
|
||||
onDeviceConnected(device);
|
||||
}
|
||||
@@ -177,7 +182,7 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName name) {
|
||||
mService = null;
|
||||
service = null;
|
||||
onServiceUnbound();
|
||||
}
|
||||
};
|
||||
@@ -185,7 +190,7 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
@Override
|
||||
protected final void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mManagedDevices = new ArrayList<>();
|
||||
managedDevices = new ArrayList<>();
|
||||
|
||||
ensureBLESupported();
|
||||
if (!isBLEEnabled()) {
|
||||
@@ -205,7 +210,7 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
// View is ready to be used
|
||||
onViewCreated(savedInstanceState);
|
||||
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mCommonBroadcastReceiver, makeIntentFilter());
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(commonBroadcastReceiver, makeIntentFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -214,29 +219,29 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
|
||||
/*
|
||||
* In comparison to BleProfileServiceReadyActivity this activity always starts the service when started.
|
||||
* Connecting to a device is done by calling mService.connect(BluetoothDevice) method, not startService(...) like there.
|
||||
* Connecting to a device is done by calling service.connect(BluetoothDevice) method, not startService(...) like there.
|
||||
* The service will stop itself when all devices it manages were disconnected and unmanaged and the last activity unbinds from it.
|
||||
*/
|
||||
final Intent service = new Intent(this, getServiceClass());
|
||||
startService(service);
|
||||
bindService(service, mServiceConnection, 0);
|
||||
bindService(service, serviceConnection, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
if (mService != null) {
|
||||
if (service != null) {
|
||||
// We don't want to perform some operations (e.g. disable Battery Level notifications) in the service if we are just rotating the screen.
|
||||
// However, when the activity will disappear, we may want to disable some device features to reduce the battery consumption.
|
||||
mService.setActivityIsChangingConfiguration(isChangingConfigurations());
|
||||
service.setActivityIsChangingConfiguration(isChangingConfigurations());
|
||||
// Log it here as there is no callback when the service gets unbound
|
||||
// and the mService will not be available later (the activity doesn't keep log sessions)
|
||||
mService.log(Log.DEBUG, "Activity unbound from the service");
|
||||
// and the service will not be available later (the activity doesn't keep log sessions)
|
||||
service.log(Log.DEBUG, "Activity unbound from the service");
|
||||
}
|
||||
|
||||
unbindService(mServiceConnection);
|
||||
mService = null;
|
||||
unbindService(serviceConnection);
|
||||
service = null;
|
||||
|
||||
onServiceUnbound();
|
||||
}
|
||||
@@ -245,7 +250,7 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mCommonBroadcastReceiver);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(commonBroadcastReceiver);
|
||||
}
|
||||
|
||||
private static IntentFilter makeIntentFilter() {
|
||||
@@ -284,7 +289,7 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
* @return the service binder or <code>null</code>
|
||||
*/
|
||||
protected E getService() {
|
||||
return mService;
|
||||
return service;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,7 +314,7 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}.
|
||||
* Note: <b>Otherwise it is null</b>.
|
||||
*/
|
||||
protected void onViewCreated(final Bundle savedInstanceState) {
|
||||
protected void onViewCreated(@SuppressWarnings("unused") final Bundle savedInstanceState) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@@ -333,7 +338,7 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
* @param itemId the menu item id
|
||||
* @return <code>true</code> if action has been handled
|
||||
*/
|
||||
protected boolean onOptionsItemSelected(final int itemId) {
|
||||
protected boolean onOptionsItemSelected(@SuppressWarnings("unused") final int itemId) {
|
||||
// Overwrite when using menu other than R.menu.help
|
||||
return false;
|
||||
}
|
||||
@@ -385,7 +390,7 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceSelected(final BluetoothDevice device, final String name) {
|
||||
public void onDeviceSelected(@NonNull final BluetoothDevice device, final String name) {
|
||||
final int titleId = getLoggerProfileTitle();
|
||||
ILogSession logSession = null;
|
||||
if (titleId > 0) {
|
||||
@@ -396,7 +401,7 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
}
|
||||
}
|
||||
|
||||
mService.connect(device, logSession);
|
||||
service.connect(device, logSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -405,64 +410,66 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnecting(final BluetoothDevice device) {
|
||||
public void onDeviceConnecting(@NonNull final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting(final BluetoothDevice device) {
|
||||
public void onDeviceDisconnecting(@NonNull final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinkLossOccurred(final BluetoothDevice device) {
|
||||
public void onLinkLossOccurred(@NonNull final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(@NonNull final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceReady(final BluetoothDevice device) {
|
||||
public void onDeviceReady(@NonNull final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBondingRequired(final BluetoothDevice device) {
|
||||
public void onBondingRequired(@NonNull final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBonded(final BluetoothDevice device) {
|
||||
public void onBonded(@NonNull final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBondingFailed(final BluetoothDevice device) {
|
||||
public void onBondingFailed(@NonNull final BluetoothDevice device) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceNotSupported(final BluetoothDevice device) {
|
||||
public void onDeviceNotSupported(@NonNull final BluetoothDevice device) {
|
||||
showToast(R.string.not_supported);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public final boolean shouldEnableBatteryLevelNotifications(final BluetoothDevice device) {
|
||||
public final boolean shouldEnableBatteryLevelNotifications(@NonNull final BluetoothDevice device) {
|
||||
// This method will never be called.
|
||||
// Please see BleMulticonnectProfileService#shouldEnableBatteryLevelNotifications(BluetoothDevice) instead.
|
||||
throw new UnsupportedOperationException("This method should not be called");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onBatteryValueReceived(final BluetoothDevice device, final int value) {
|
||||
public void onBatteryValueReceived(@NonNull final BluetoothDevice device, final int value) {
|
||||
// empty default implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
|
||||
public void onError(@NonNull final BluetoothDevice device, @NonNull final String message, final int errorCode) {
|
||||
DebugLogger.e(TAG, "Error occurred: " + message + ", error code: " + errorCode);
|
||||
showToast(message + " (" + errorCode + ")");
|
||||
}
|
||||
@@ -506,7 +513,7 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
* @return unmodifiable list of managed devices
|
||||
*/
|
||||
protected List<BluetoothDevice> getManagedDevices() {
|
||||
return Collections.unmodifiableList(mManagedDevices);
|
||||
return Collections.unmodifiableList(managedDevices);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -514,7 +521,7 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
* @param device the device to check if it's connected
|
||||
*/
|
||||
protected boolean isDeviceConnected(final BluetoothDevice device) {
|
||||
return mService != null && mService.isConnected(device);
|
||||
return service != null && service.isConnected(device);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -537,8 +544,7 @@ public abstract class BleMulticonnectProfileServiceReadyActivity<E extends BleMu
|
||||
}
|
||||
|
||||
protected boolean isBLEEnabled() {
|
||||
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
|
||||
final BluetoothAdapter adapter = bluetoothManager.getAdapter();
|
||||
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
return adapter != null && adapter.isEnabled();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
package no.nordicsemi.android.nrftoolbox.profile.multiconnect;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
public interface IDeviceLogger {
|
||||
@@ -32,7 +34,7 @@ public interface IDeviceLogger {
|
||||
* @param level the log level
|
||||
* @param message the message to be logged
|
||||
*/
|
||||
void log(final BluetoothDevice device, final int level, final String message);
|
||||
void log(@NonNull final BluetoothDevice device, final int level, final String message);
|
||||
|
||||
/**
|
||||
* Logs the given message with given log level into the device's log session.
|
||||
@@ -41,5 +43,5 @@ public interface IDeviceLogger {
|
||||
* @param messageRes string resource id
|
||||
* @param params additional (optional) parameters used to fill the message
|
||||
*/
|
||||
void log(final BluetoothDevice device, final int level, @StringRes final int messageRes, final Object... params);
|
||||
void log(@NonNull final BluetoothDevice device, final int level, @StringRes final int messageRes, final Object... params);
|
||||
}
|
||||
|
||||
@@ -38,12 +38,12 @@ import java.util.List;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
|
||||
public class DeviceAdapter extends RecyclerView.Adapter<DeviceAdapter.ViewHolder> {
|
||||
private final ProximityService.ProximityBinder mService;
|
||||
private final List<BluetoothDevice> mDevices;
|
||||
private final ProximityService.ProximityBinder service;
|
||||
private final List<BluetoothDevice> devices;
|
||||
|
||||
DeviceAdapter(final ProximityService.ProximityBinder binder) {
|
||||
mService = binder;
|
||||
mDevices = mService.getManagedDevices();
|
||||
service = binder;
|
||||
devices = service.getManagedDevices();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -55,18 +55,18 @@ public class DeviceAdapter extends RecyclerView.Adapter<DeviceAdapter.ViewHolder
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
|
||||
holder.bind(mDevices.get(position));
|
||||
holder.bind(devices.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mDevices.size();
|
||||
return devices.size();
|
||||
}
|
||||
|
||||
public void onDeviceAdded(final BluetoothDevice device) {
|
||||
final int position = mDevices.indexOf(device);
|
||||
final int position = devices.indexOf(device);
|
||||
if (position == -1) {
|
||||
notifyItemInserted(mDevices.size() - 1);
|
||||
notifyItemInserted(devices.size() - 1);
|
||||
} else {
|
||||
// This may happen when Bluetooth adapter was switched off and on again
|
||||
// while there were devices on the list.
|
||||
@@ -79,13 +79,13 @@ public class DeviceAdapter extends RecyclerView.Adapter<DeviceAdapter.ViewHolder
|
||||
}
|
||||
|
||||
public void onDeviceStateChanged(final BluetoothDevice device) {
|
||||
final int position = mDevices.indexOf(device);
|
||||
final int position = devices.indexOf(device);
|
||||
if (position >= 0)
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
|
||||
public void onBatteryValueReceived(final BluetoothDevice device) {
|
||||
final int position = mDevices.indexOf(device);
|
||||
final int position = devices.indexOf(device);
|
||||
if (position >= 0)
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
@@ -109,22 +109,22 @@ public class DeviceAdapter extends RecyclerView.Adapter<DeviceAdapter.ViewHolder
|
||||
// Configure FIND / SILENT button
|
||||
actionButton.setOnClickListener(v -> {
|
||||
final int position = getAdapterPosition();
|
||||
final BluetoothDevice device = mDevices.get(position);
|
||||
mService.toggleImmediateAlert(device);
|
||||
final BluetoothDevice device = devices.get(position);
|
||||
service.toggleImmediateAlert(device);
|
||||
});
|
||||
|
||||
// Configure Disconnect button
|
||||
itemView.findViewById(R.id.action_disconnect).setOnClickListener(v -> {
|
||||
final int position = getAdapterPosition();
|
||||
final BluetoothDevice device = mDevices.get(position);
|
||||
mService.disconnect(device);
|
||||
final BluetoothDevice device = devices.get(position);
|
||||
service.disconnect(device);
|
||||
// The device might have not been connected, so there will be no callback
|
||||
onDeviceRemoved(device);
|
||||
});
|
||||
}
|
||||
|
||||
private void bind(final BluetoothDevice device) {
|
||||
final boolean ready = mService.isReady(device);
|
||||
final boolean ready = service.isReady(device);
|
||||
|
||||
String name = device.getName();
|
||||
if (TextUtils.isEmpty(name))
|
||||
@@ -132,12 +132,12 @@ public class DeviceAdapter extends RecyclerView.Adapter<DeviceAdapter.ViewHolder
|
||||
nameView.setText(name);
|
||||
addressView.setText(device.getAddress());
|
||||
|
||||
final boolean on = mService.isImmediateAlertOn(device);
|
||||
final boolean on = service.isImmediateAlertOn(device);
|
||||
actionButton.setImageResource(on ? R.drawable.ic_stat_notify_proximity_silent : R.drawable.ic_stat_notify_proximity_find);
|
||||
actionButton.setVisibility(ready ? View.VISIBLE : View.GONE);
|
||||
progress.setVisibility(ready ? View.GONE : View.VISIBLE);
|
||||
|
||||
final Integer batteryValue = mService.getBatteryLevel(device);
|
||||
final Integer batteryValue = service.getBatteryLevel(device);
|
||||
if (batteryValue != null) {
|
||||
batteryView.getCompoundDrawables()[0 /*left*/].setLevel(batteryValue);
|
||||
batteryView.setVisibility(View.VISIBLE);
|
||||
|
||||
@@ -32,7 +32,7 @@ import no.nordicsemi.android.nrftoolbox.R;
|
||||
public class LinkLossFragment extends DialogFragment {
|
||||
private static final String ARG_NAME = "name";
|
||||
|
||||
private String mName;
|
||||
private String name;
|
||||
|
||||
public static LinkLossFragment getInstance(String name) {
|
||||
final LinkLossFragment fragment = new LinkLossFragment();
|
||||
@@ -48,7 +48,7 @@ public class LinkLossFragment extends DialogFragment {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mName = getArguments().getString(ARG_NAME);
|
||||
name = getArguments().getString(ARG_NAME);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -56,7 +56,7 @@ public class LinkLossFragment extends DialogFragment {
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return new AlertDialog.Builder(requireContext())
|
||||
.setTitle(getString(R.string.app_name))
|
||||
.setMessage(getString(R.string.proximity_notification_link_loss_alert, mName))
|
||||
.setMessage(getString(R.string.proximity_notification_link_loss_alert, name))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.create();
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
@@ -40,8 +42,8 @@ import no.nordicsemi.android.nrftoolbox.profile.multiconnect.BleMulticonnectProf
|
||||
import no.nordicsemi.android.nrftoolbox.widget.DividerItemDecoration;
|
||||
|
||||
public class ProximityActivity extends BleMulticonnectProfileServiceReadyActivity<ProximityService.ProximityBinder> {
|
||||
private RecyclerView mDevicesView;
|
||||
private DeviceAdapter mAdapter;
|
||||
private RecyclerView devicesView;
|
||||
private DeviceAdapter adapter;
|
||||
|
||||
@Override
|
||||
protected void onCreateView(final Bundle savedInstanceState) {
|
||||
@@ -51,17 +53,17 @@ public class ProximityActivity extends BleMulticonnectProfileServiceReadyActivit
|
||||
|
||||
@Override
|
||||
protected void onInitialize(final Bundle savedInstanceState) {
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, makeIntentFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
|
||||
}
|
||||
|
||||
private void setGUI() {
|
||||
final RecyclerView recyclerView = mDevicesView = findViewById(android.R.id.list);
|
||||
final RecyclerView recyclerView = devicesView = findViewById(android.R.id.list);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
|
||||
}
|
||||
@@ -73,12 +75,12 @@ public class ProximityActivity extends BleMulticonnectProfileServiceReadyActivit
|
||||
|
||||
@Override
|
||||
protected void onServiceBound(final ProximityService.ProximityBinder binder) {
|
||||
mDevicesView.setAdapter(mAdapter = new DeviceAdapter(binder));
|
||||
devicesView.setAdapter(adapter = new DeviceAdapter(binder));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onServiceUnbound() {
|
||||
mDevicesView.setAdapter(mAdapter = null);
|
||||
devicesView.setAdapter(adapter = null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -97,46 +99,46 @@ public class ProximityActivity extends BleMulticonnectProfileServiceReadyActivit
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnecting(final BluetoothDevice device) {
|
||||
if (mAdapter != null)
|
||||
mAdapter.onDeviceAdded(device);
|
||||
public void onDeviceConnecting(@NonNull final BluetoothDevice device) {
|
||||
if (adapter != null)
|
||||
adapter.onDeviceAdded(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnected(final BluetoothDevice device) {
|
||||
if (mAdapter != null)
|
||||
mAdapter.onDeviceStateChanged(device);
|
||||
if (adapter != null)
|
||||
adapter.onDeviceStateChanged(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceReady(final BluetoothDevice device) {
|
||||
if (mAdapter != null)
|
||||
mAdapter.onDeviceStateChanged(device);
|
||||
public void onDeviceReady(@NonNull final BluetoothDevice device) {
|
||||
if (adapter != null)
|
||||
adapter.onDeviceStateChanged(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnecting(final BluetoothDevice device) {
|
||||
if (mAdapter != null)
|
||||
mAdapter.onDeviceStateChanged(device);
|
||||
public void onDeviceDisconnecting(@NonNull final BluetoothDevice device) {
|
||||
if (adapter != null)
|
||||
adapter.onDeviceStateChanged(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
if (mAdapter != null)
|
||||
mAdapter.onDeviceRemoved(device);
|
||||
if (adapter != null)
|
||||
adapter.onDeviceRemoved(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceNotSupported(final BluetoothDevice device) {
|
||||
public void onDeviceNotSupported(@NonNull final BluetoothDevice device) {
|
||||
super.onDeviceNotSupported(device);
|
||||
if (mAdapter != null)
|
||||
mAdapter.onDeviceRemoved(device);
|
||||
if (adapter != null)
|
||||
adapter.onDeviceRemoved(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinkLossOccurred(final BluetoothDevice device) {
|
||||
if (mAdapter != null)
|
||||
mAdapter.onDeviceStateChanged(device);
|
||||
public void onLinkLossOccurred(@NonNull final BluetoothDevice device) {
|
||||
if (adapter != null)
|
||||
adapter.onDeviceStateChanged(device);
|
||||
|
||||
// The link loss may also be called when Bluetooth adapter was disabled
|
||||
if (BluetoothAdapter.getDefaultAdapter().isEnabled())
|
||||
@@ -145,14 +147,14 @@ public class ProximityActivity extends BleMulticonnectProfileServiceReadyActivit
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void onBatteryLevelChanged(final BluetoothDevice device, final int batteryLevel) {
|
||||
if (mAdapter != null)
|
||||
mAdapter.onBatteryValueReceived(device); // Value will be obtained from the service
|
||||
if (adapter != null)
|
||||
adapter.onBatteryValueReceived(device); // Value will be obtained from the service
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void onRemoteAlarmSwitched(final BluetoothDevice device, final boolean on) {
|
||||
if (mAdapter != null)
|
||||
mAdapter.onDeviceStateChanged(device); // Value will be obtained from the service
|
||||
if (adapter != null)
|
||||
adapter.onDeviceStateChanged(device); // Value will be obtained from the service
|
||||
}
|
||||
|
||||
private void showLinkLossDialog(final String name) {
|
||||
@@ -164,7 +166,7 @@ public class ProximityActivity extends BleMulticonnectProfileServiceReadyActivit
|
||||
}
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
|
||||
@@ -21,8 +21,10 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.proximity;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.bluetooth.BluetoothGattServer;
|
||||
import android.bluetooth.BluetoothGattService;
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -31,6 +33,7 @@ import android.util.Log;
|
||||
import java.util.UUID;
|
||||
|
||||
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||
import no.nordicsemi.android.ble.common.callback.alert.AlertLevelDataCallback;
|
||||
import no.nordicsemi.android.ble.common.data.alert.AlertLevelData;
|
||||
import no.nordicsemi.android.ble.error.GattError;
|
||||
import no.nordicsemi.android.log.LogContract;
|
||||
@@ -42,50 +45,67 @@ class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
|
||||
/** Link Loss service UUID. */
|
||||
final static UUID LINK_LOSS_SERVICE_UUID = UUID.fromString("00001803-0000-1000-8000-00805f9b34fb");
|
||||
/** Immediate Alert service UUID. */
|
||||
private final static UUID IMMEDIATE_ALERT_SERVICE_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb");
|
||||
final static UUID IMMEDIATE_ALERT_SERVICE_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb");
|
||||
/** Alert Level characteristic UUID. */
|
||||
private static final UUID ALERT_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A06-0000-1000-8000-00805f9b34fb");
|
||||
final static UUID ALERT_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A06-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private BluetoothGattCharacteristic mAlertLevelCharacteristic, mLinkLossCharacteristic;
|
||||
private boolean mAlertOn;
|
||||
// Client characteristics.
|
||||
private BluetoothGattCharacteristic alertLevelCharacteristic, linkLossCharacteristic;
|
||||
// Server characteristics.
|
||||
private BluetoothGattCharacteristic localAlertLevelCharacteristic;
|
||||
/** A flag indicating whether the alarm on the connected proximity tag has been activated. */
|
||||
private boolean alertOn;
|
||||
|
||||
ProximityManager(final Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldAutoConnect() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected BatteryManagerGattCallback getGattCallback() {
|
||||
return mGattCallback;
|
||||
return gattCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* BluetoothGatt callbacks for connection/disconnection, service discovery,
|
||||
* receiving indication, etc.
|
||||
*/
|
||||
private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
|
||||
private final BatteryManagerGattCallback gattCallback = new BatteryManagerGattCallback() {
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
super.initialize();
|
||||
writeCharacteristic(mLinkLossCharacteristic, AlertLevelData.highAlert())
|
||||
// This callback will be called whenever local Alert Level char is written
|
||||
// by a connected proximity tag.
|
||||
setWriteCallback(localAlertLevelCharacteristic)
|
||||
.with(new AlertLevelDataCallback() {
|
||||
@Override
|
||||
public void onAlertLevelChanged(@NonNull final BluetoothDevice device, final int level) {
|
||||
callbacks.onLocalAlarmSwitched(device, level != ALERT_NONE);
|
||||
}
|
||||
});
|
||||
// After connection, set the Link Loss behaviour on the tag.
|
||||
writeCharacteristic(linkLossCharacteristic, AlertLevelData.highAlert())
|
||||
.done(device -> log(Log.INFO, "Link loss alert level set"))
|
||||
.fail((device, status) -> log(Log.WARN, "Failed to set link loss level: " + status))
|
||||
.enqueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onServerReady(@NonNull final BluetoothGattServer server) {
|
||||
final BluetoothGattService immediateAlertService = server.getService(IMMEDIATE_ALERT_SERVICE_UUID);
|
||||
if (immediateAlertService != null) {
|
||||
localAlertLevelCharacteristic = immediateAlertService.getCharacteristic(ALERT_LEVEL_CHARACTERISTIC_UUID);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||
final BluetoothGattService llService = gatt.getService(LINK_LOSS_SERVICE_UUID);
|
||||
if (llService != null) {
|
||||
mLinkLossCharacteristic = llService.getCharacteristic(ALERT_LEVEL_CHARACTERISTIC_UUID);
|
||||
linkLossCharacteristic = llService.getCharacteristic(ALERT_LEVEL_CHARACTERISTIC_UUID);
|
||||
}
|
||||
return mLinkLossCharacteristic != null;
|
||||
return linkLossCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,18 +113,19 @@ class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
|
||||
super.isOptionalServiceSupported(gatt);
|
||||
final BluetoothGattService iaService = gatt.getService(IMMEDIATE_ALERT_SERVICE_UUID);
|
||||
if (iaService != null) {
|
||||
mAlertLevelCharacteristic = iaService.getCharacteristic(ALERT_LEVEL_CHARACTERISTIC_UUID);
|
||||
alertLevelCharacteristic = iaService.getCharacteristic(ALERT_LEVEL_CHARACTERISTIC_UUID);
|
||||
}
|
||||
return mAlertLevelCharacteristic != null;
|
||||
return alertLevelCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeviceDisconnected() {
|
||||
super.onDeviceDisconnected();
|
||||
mAlertLevelCharacteristic = null;
|
||||
mLinkLossCharacteristic = null;
|
||||
alertLevelCharacteristic = null;
|
||||
linkLossCharacteristic = null;
|
||||
localAlertLevelCharacteristic = null;
|
||||
// Reset the alert flag
|
||||
mAlertOn = false;
|
||||
alertOn = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -112,7 +133,7 @@ class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
|
||||
* Toggles the immediate alert on the target device.
|
||||
*/
|
||||
public void toggleImmediateAlert() {
|
||||
writeImmediateAlert(!mAlertOn);
|
||||
writeImmediateAlert(!alertOn);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,14 +145,14 @@ class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
|
||||
if (!isConnected())
|
||||
return;
|
||||
|
||||
writeCharacteristic(mAlertLevelCharacteristic, on ? AlertLevelData.highAlert() : AlertLevelData.noAlert())
|
||||
writeCharacteristic(alertLevelCharacteristic, on ? AlertLevelData.highAlert() : AlertLevelData.noAlert())
|
||||
.before(device -> log(Log.VERBOSE,
|
||||
on ? "Setting alarm to HIGH..." : "Disabling alarm..."))
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
|
||||
"\"" + AlertLevelParser.parse(data) + "\" sent"))
|
||||
.done(device -> {
|
||||
mAlertOn = on;
|
||||
mCallbacks.onRemoteAlarmSwitched(device, on);
|
||||
alertOn = on;
|
||||
callbacks.onRemoteAlarmSwitched(device, on);
|
||||
})
|
||||
.fail((device, status) -> log(Log.WARN,
|
||||
status == FailCallback.REASON_NULL_ATTRIBUTE ?
|
||||
@@ -144,6 +165,6 @@ class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
|
||||
* Returns true if the alert has been enabled on the proximity tag, false otherwise.
|
||||
*/
|
||||
boolean isAlertEnabled() {
|
||||
return mAlertOn;
|
||||
return alertOn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import androidx.annotation.NonNull;
|
||||
import no.nordicsemi.android.nrftoolbox.battery.BatteryManagerCallbacks;
|
||||
|
||||
interface ProximityManagerCallbacks extends BatteryManagerCallbacks {
|
||||
// No additional methods
|
||||
void onRemoteAlarmSwitched(@NonNull final BluetoothDevice device, final boolean on);
|
||||
|
||||
void onLocalAlarmSwitched(@NonNull final BluetoothDevice device, final boolean on);
|
||||
}
|
||||
|
||||
@@ -21,366 +21,46 @@
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.proximity;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.bluetooth.BluetoothGattDescriptor;
|
||||
import android.bluetooth.BluetoothGattServer;
|
||||
import android.bluetooth.BluetoothGattServerCallback;
|
||||
import android.bluetooth.BluetoothGattService;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import no.nordicsemi.android.error.GattError;
|
||||
import no.nordicsemi.android.log.LogContract;
|
||||
import no.nordicsemi.android.nrftoolbox.parser.AlertLevelParser;
|
||||
import no.nordicsemi.android.nrftoolbox.profile.multiconnect.IDeviceLogger;
|
||||
import no.nordicsemi.android.nrftoolbox.utility.ParserUtils;
|
||||
import androidx.annotation.NonNull;
|
||||
import no.nordicsemi.android.ble.BleServerManager;
|
||||
import no.nordicsemi.android.ble.common.data.alert.AlertLevelData;
|
||||
|
||||
class ProximityServerManager {
|
||||
private final String TAG = "ProximityServerManager";
|
||||
class ProximityServerManager extends BleServerManager {
|
||||
|
||||
/** Immediate Alert service UUID */
|
||||
final static UUID IMMEDIATE_ALERT_SERVICE_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb");
|
||||
/** Linkloss service UUID */
|
||||
final static UUID LINKLOSS_SERVICE_UUID = UUID.fromString("00001803-0000-1000-8000-00805f9b34fb");
|
||||
/** Alert Level characteristic UUID */
|
||||
private static final UUID ALERT_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A06-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private final static byte[] HIGH_ALERT = { 0x02 };
|
||||
private final static byte[] MILD_ALERT = { 0x01 };
|
||||
private final static byte[] NO_ALERT = { 0x00 };
|
||||
|
||||
private BluetoothGattServer mBluetoothGattServer;
|
||||
private ProximityServerManagerCallbacks mCallbacks;
|
||||
private IDeviceLogger mLogger;
|
||||
private Handler mHandler;
|
||||
private OnServerOpenCallback mOnServerOpenCallback;
|
||||
private boolean mServerReady;
|
||||
|
||||
public interface OnServerOpenCallback {
|
||||
/**
|
||||
* Method called when the GATT server was created and all services were added successfully.
|
||||
*/
|
||||
void onGattServerOpen();
|
||||
/**
|
||||
* Method called when the GATT server failed to open and initialize services.
|
||||
* -1 is returned when the server failed to start.
|
||||
*/
|
||||
void onGattServerFailed(final int error);
|
||||
ProximityServerManager(@NonNull final Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
ProximityServerManager(final ProximityServerManagerCallbacks callbacks) {
|
||||
mHandler = new Handler();
|
||||
mCallbacks = callbacks;
|
||||
@Override
|
||||
public void log(final int priority, @NonNull final String message) {
|
||||
Log.println(priority, "BleManager", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logger object. Logger is used to create logs in nRF Logger application.
|
||||
*
|
||||
* @param logger the logger object
|
||||
*/
|
||||
public void setLogger(final IDeviceLogger logger) {
|
||||
mLogger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens GATT server and creates 2 services: Link Loss Service and Immediate Alert Service.
|
||||
* The callback is called when initialization is complete.
|
||||
*
|
||||
* @param context the context.
|
||||
* @param callback optional callback notifying when all services has been added.
|
||||
*/
|
||||
public void openGattServer(final Context context, final OnServerOpenCallback callback) {
|
||||
// Is the server already open?
|
||||
if (mBluetoothGattServer != null) {
|
||||
if (callback != null)
|
||||
callback.onGattServerOpen();
|
||||
return;
|
||||
}
|
||||
|
||||
mOnServerOpenCallback = callback;
|
||||
|
||||
final BluetoothManager manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
|
||||
mBluetoothGattServer = manager.openGattServer(context, mGattServerCallbacks);
|
||||
if (mBluetoothGattServer != null) {
|
||||
// Start adding services one by one. The onServiceAdded method will be called when it completes.
|
||||
addImmediateAlertService();
|
||||
} else {
|
||||
if (callback != null)
|
||||
callback.onGattServerFailed(-1);
|
||||
mOnServerOpenCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if GATT server was opened and configured correctly.
|
||||
* False if hasn't been opened, was closed, of failed to start.
|
||||
*/
|
||||
public boolean isServerReady() {
|
||||
return mServerReady;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the GATT server. It will also disconnect all existing connections.
|
||||
* If the service has already been closed, or hasn't been open, this method does nothing.
|
||||
*/
|
||||
public void closeGattServer() {
|
||||
if (mBluetoothGattServer != null) {
|
||||
mBluetoothGattServer.close();
|
||||
mBluetoothGattServer = null;
|
||||
mOnServerOpenCallback = null;
|
||||
mServerReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method notifies the Android that the Proximity profile will use the server connection
|
||||
* to given device. If the server hasn't been open this method does nothing.
|
||||
* The {@link #cancelConnection(BluetoothDevice)} method should be called when the connection
|
||||
* is no longer used.
|
||||
*
|
||||
* @param device the target device.
|
||||
*/
|
||||
public void openConnection(final BluetoothDevice device) {
|
||||
if (mBluetoothGattServer != null) {
|
||||
mLogger.log(device, LogContract.Log.Level.VERBOSE, "[Server] Creating server connection...");
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG, "server.connect(device, autoConnect = true)");
|
||||
mBluetoothGattServer.connect(device, true); // In proximity the autoConnect is true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the connection to the given device. This notifies Android that this profile will
|
||||
* no longer use this connection and it can be disconnected. In practice, this method does
|
||||
* not disconnect, so if the remote device decides still to use the phone's GATT server it
|
||||
* will be able to do so.
|
||||
* <p>
|
||||
* This bug/feature can be tested using a proximity tag that does not release its connection
|
||||
* when it got disconnected:
|
||||
* <ol>
|
||||
* <li>Connect to your Proximity Tag.</li>
|
||||
* <li>Verify that the bidirectional connection works - test the FIND ME button in
|
||||
* nRF Toolbox and the FIND PHONE button on the tag.</li>
|
||||
* <li>Disconnect from the tag</li>
|
||||
* <li>When the device disappear from the list of devices click the FIND PHONE button on
|
||||
* the tag. Your phone should still trigger an alarm, as the connection tag->phone
|
||||
* is still active.</li>
|
||||
* </ol>
|
||||
* In order to avoid this issue make sure that your tag disconnects gently from phone when it
|
||||
* got disconnected itself.
|
||||
*
|
||||
* @param device the device that will no longer be used.
|
||||
*/
|
||||
public void cancelConnection(final BluetoothDevice device) {
|
||||
if (mBluetoothGattServer != null) {
|
||||
mLogger.log(device, LogContract.Log.Level.VERBOSE, "[Server] Cancelling server connection...");
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG, "server.cancelConnection(device)");
|
||||
mBluetoothGattServer.cancelConnection(device);
|
||||
}
|
||||
}
|
||||
|
||||
private void addImmediateAlertService() {
|
||||
/*
|
||||
* This method must be called in UI thread. It works fine on Nexus devices but if called
|
||||
* from other thread (e.g. from onServiceAdded in gatt server callback) it hangs the app.
|
||||
*/
|
||||
final BluetoothGattCharacteristic alertLevel =
|
||||
new BluetoothGattCharacteristic(ALERT_LEVEL_CHARACTERISTIC_UUID,
|
||||
BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE,
|
||||
BluetoothGattCharacteristic.PERMISSION_WRITE);
|
||||
alertLevel.setValue(NO_ALERT);
|
||||
final BluetoothGattService immediateAlertService =
|
||||
new BluetoothGattService(IMMEDIATE_ALERT_SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
|
||||
immediateAlertService.addCharacteristic(alertLevel);
|
||||
mBluetoothGattServer.addService(immediateAlertService);
|
||||
}
|
||||
|
||||
private void addLinkLossService() {
|
||||
/*
|
||||
* This method must be called in UI thread. It works fine on Nexus devices but if called
|
||||
* from other thread (e.g. from onServiceAdded in gatt server callback) it hangs the app.
|
||||
*/
|
||||
final BluetoothGattCharacteristic linkLossAlertLevel =
|
||||
new BluetoothGattCharacteristic(ALERT_LEVEL_CHARACTERISTIC_UUID,
|
||||
BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_READ,
|
||||
BluetoothGattCharacteristic.PERMISSION_WRITE | BluetoothGattCharacteristic.PERMISSION_READ);
|
||||
linkLossAlertLevel.setValue(HIGH_ALERT);
|
||||
final BluetoothGattService linkLossService =
|
||||
new BluetoothGattService(LINKLOSS_SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
|
||||
linkLossService.addCharacteristic(linkLossAlertLevel);
|
||||
mBluetoothGattServer.addService(linkLossService);
|
||||
}
|
||||
|
||||
private final BluetoothGattServerCallback mGattServerCallbacks = new BluetoothGattServerCallback() {
|
||||
@Override
|
||||
public void onServiceAdded(final int status, final BluetoothGattService service) {
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
// Adding another service from callback thread fails on Samsung S4 with Android 4.3
|
||||
mHandler.post(() -> {
|
||||
if (IMMEDIATE_ALERT_SERVICE_UUID.equals(service.getUuid())) {
|
||||
addLinkLossService();
|
||||
} else {
|
||||
mServerReady = true;
|
||||
// Both services has been added
|
||||
if (mOnServerOpenCallback != null)
|
||||
mOnServerOpenCallback.onGattServerOpen();
|
||||
mOnServerOpenCallback = null;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Log.e(TAG, "GATT Server failed to add service, status: " + status);
|
||||
if (mOnServerOpenCallback != null)
|
||||
mOnServerOpenCallback.onGattServerFailed(status);
|
||||
mOnServerOpenCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionStateChange(final BluetoothDevice device, final int status, final int newState) {
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG,
|
||||
"[Server callback] Connection state changed with status: " + status
|
||||
+ " and new state: " + newState + " (" + stateToString(newState) + ")");
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
if (newState == BluetoothGatt.STATE_CONNECTED) {
|
||||
mLogger.log(device, LogContract.Log.Level.INFO,
|
||||
"[Server] Device with address " + device.getAddress() + " connected");
|
||||
} else {
|
||||
mLogger.log(device, LogContract.Log.Level.INFO, "[Server] Device disconnected");
|
||||
mCallbacks.onAlarmStopped(device);
|
||||
}
|
||||
} else {
|
||||
mLogger.log(device, LogContract.Log.Level.ERROR, "[Server] Error " + status +
|
||||
" (0x" + Integer.toHexString(status) + "): " + GattError.parseConnectionError(status));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCharacteristicReadRequest(final BluetoothDevice device, final int requestId,
|
||||
final int offset, final BluetoothGattCharacteristic characteristic) {
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG,
|
||||
"[Server callback] Read request for characteristic " + characteristic.getUuid()
|
||||
+ " (requestId=" + requestId + ", offset=" + offset + ")");
|
||||
mLogger.log(device, LogContract.Log.Level.INFO,
|
||||
"[Server] READ request for characteristic " + characteristic.getUuid() + " received");
|
||||
|
||||
byte[] value = characteristic.getValue();
|
||||
if (value != null && offset > 0) {
|
||||
byte[] offsetValue = new byte[value.length - offset];
|
||||
System.arraycopy(value, offset, offsetValue, 0, offsetValue.length);
|
||||
value = offsetValue;
|
||||
}
|
||||
if (value != null) {
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG,
|
||||
"server.sendResponse(GATT_SUCCESS, value=" + ParserUtils.parseDebug(value) + ")");
|
||||
} else {
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG, "server.sendResponse(GATT_SUCCESS, value=null)");
|
||||
}
|
||||
mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
|
||||
mLogger.log(device, LogContract.Log.Level.VERBOSE, "[Server] Response sent");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCharacteristicWriteRequest(final BluetoothDevice device, final int requestId,
|
||||
final BluetoothGattCharacteristic characteristic, final boolean preparedWrite,
|
||||
final boolean responseNeeded, final int offset, final byte[] value) {
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG, "[Server callback] Write request to characteristic " + characteristic.getUuid()
|
||||
+ " (requestId=" + requestId + ", prepareWrite=" + preparedWrite + ", responseNeeded=" + responseNeeded
|
||||
+ ", offset=" + offset + ", value=" + ParserUtils.parseDebug(value) + ")");
|
||||
final String writeType = !responseNeeded ? "WRITE NO RESPONSE" : "WRITE COMMAND";
|
||||
mLogger.log(device, LogContract.Log.Level.INFO, "[Server] " + writeType
|
||||
+ " request for characteristic " + characteristic.getUuid() + " received, value: " + ParserUtils.parse(value));
|
||||
|
||||
if (offset == 0) {
|
||||
characteristic.setValue(value);
|
||||
} else {
|
||||
final byte[] currentValue = characteristic.getValue();
|
||||
final byte[] newValue = new byte[currentValue.length + value.length];
|
||||
System.arraycopy(currentValue, 0, newValue, 0, currentValue.length);
|
||||
System.arraycopy(value, 0, newValue, offset, value.length);
|
||||
characteristic.setValue(newValue);
|
||||
}
|
||||
|
||||
if (!preparedWrite && value != null && value.length == 1) { // small validation
|
||||
if (value[0] != NO_ALERT[0]) {
|
||||
mLogger.log(device, LogContract.Log.Level.APPLICATION,
|
||||
"[Server] Immediate alarm request received: " + AlertLevelParser.parse(characteristic));
|
||||
mCallbacks.onAlarmTriggered(device);
|
||||
} else {
|
||||
mLogger.log(device, LogContract.Log.Level.APPLICATION,
|
||||
"[Server] Immediate alarm request received: OFF");
|
||||
mCallbacks.onAlarmStopped(device);
|
||||
}
|
||||
}
|
||||
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG, "server.sendResponse(GATT_SUCCESS, offset="
|
||||
+ offset + ", value=" + ParserUtils.parseDebug(value) + ")");
|
||||
mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, null);
|
||||
mLogger.log(device, LogContract.Log.Level.VERBOSE, "[Server] Response sent");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDescriptorReadRequest(final BluetoothDevice device, final int requestId,
|
||||
final int offset, final BluetoothGattDescriptor descriptor) {
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG,
|
||||
"[Server callback] Write request to descriptor " + descriptor.getUuid() + " (requestId=" + requestId + ", offset=" + offset + ")");
|
||||
mLogger.log(device, LogContract.Log.Level.INFO,
|
||||
"[Server] READ request for descriptor " + descriptor.getUuid() + " received");
|
||||
// This method is not supported
|
||||
mLogger.log(device, LogContract.Log.Level.WARNING, "[Server] Operation not supported");
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG, "[Server] server.sendResponse(GATT_REQUEST_NOT_SUPPORTED)");
|
||||
mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED, offset, null);
|
||||
mLogger.log(device, LogContract.Log.Level.VERBOSE, "[Server] Response sent");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDescriptorWriteRequest(final BluetoothDevice device, final int requestId,
|
||||
final BluetoothGattDescriptor descriptor, final boolean preparedWrite,
|
||||
final boolean responseNeeded, final int offset, final byte[] value) {
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG, "[Server callback] Write request to descriptor " + descriptor.getUuid()
|
||||
+ " (requestId=" + requestId + ", prepareWrite=" + preparedWrite + ", responseNeeded=" + responseNeeded
|
||||
+ ", offset=" + offset + ", value=" + ParserUtils.parse(value) + ")");
|
||||
mLogger.log(device, LogContract.Log.Level.INFO, "[Server] READ request for descriptor " + descriptor.getUuid() + " received");
|
||||
// This method is not supported
|
||||
mLogger.log(device, LogContract.Log.Level.WARNING, "[Server] Operation not supported");
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG, "[Server] server.sendResponse(GATT_REQUEST_NOT_SUPPORTED)");
|
||||
mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED, offset, null);
|
||||
mLogger.log(device, LogContract.Log.Level.VERBOSE, "[Server] Response sent");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExecuteWrite(final BluetoothDevice device, final int requestId, final boolean execute) {
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG,
|
||||
"[Server callback] Execute write request (requestId=" + requestId + ", execute=" + execute + ")");
|
||||
// This method is not supported
|
||||
mLogger.log(device, LogContract.Log.Level.WARNING, "[Server] Operation not supported");
|
||||
mLogger.log(device, LogContract.Log.Level.DEBUG, "[Server] server.sendResponse(GATT_REQUEST_NOT_SUPPORTED)");
|
||||
mBluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED, 0, null);
|
||||
mLogger.log(device, LogContract.Log.Level.VERBOSE, "[Server] Response sent");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts the connection state to String value.
|
||||
*
|
||||
* @param state the connection state.
|
||||
* @return The state as String.
|
||||
*/
|
||||
private String stateToString(final int state) {
|
||||
switch (state) {
|
||||
case BluetoothProfile.STATE_CONNECTED:
|
||||
return "CONNECTED";
|
||||
case BluetoothProfile.STATE_CONNECTING:
|
||||
return "CONNECTING";
|
||||
case BluetoothProfile.STATE_DISCONNECTING:
|
||||
return "DISCONNECTING";
|
||||
default:
|
||||
return "DISCONNECTED";
|
||||
}
|
||||
@NonNull
|
||||
@Override
|
||||
protected List<BluetoothGattService> initializeServer() {
|
||||
final List<BluetoothGattService> services = new ArrayList<>();
|
||||
services.add(
|
||||
service(ProximityManager.IMMEDIATE_ALERT_SERVICE_UUID,
|
||||
characteristic(ProximityManager.ALERT_LEVEL_CHARACTERISTIC_UUID,
|
||||
BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE,
|
||||
BluetoothGattCharacteristic.PERMISSION_WRITE))
|
||||
);
|
||||
services.add(
|
||||
service(ProximityManager.LINK_LOSS_SERVICE_UUID,
|
||||
characteristic(ProximityManager.ALERT_LEVEL_CHARACTERISTIC_UUID,
|
||||
BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_READ,
|
||||
BluetoothGattCharacteristic.PERMISSION_WRITE | BluetoothGattCharacteristic.PERMISSION_READ,
|
||||
AlertLevelData.highAlert()))
|
||||
);
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package no.nordicsemi.android.nrftoolbox.proximity;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public interface ProximityServerManagerCallbacks {
|
||||
void onAlarmTriggered(@NonNull final BluetoothDevice device);
|
||||
|
||||
void onAlarmStopped(@NonNull final BluetoothDevice device);
|
||||
}
|
||||
@@ -47,6 +47,7 @@ import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import no.nordicsemi.android.ble.BleServerManagerCallbacks;
|
||||
import no.nordicsemi.android.log.LogContract;
|
||||
import no.nordicsemi.android.nrftoolbox.FeaturesActivity;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
@@ -54,7 +55,7 @@ import no.nordicsemi.android.nrftoolbox.ToolboxApplication;
|
||||
import no.nordicsemi.android.nrftoolbox.profile.LoggableBleManager;
|
||||
import no.nordicsemi.android.nrftoolbox.profile.multiconnect.BleMulticonnectProfileService;
|
||||
|
||||
public class ProximityService extends BleMulticonnectProfileService implements ProximityManagerCallbacks, ProximityServerManagerCallbacks {
|
||||
public class ProximityService extends BleMulticonnectProfileService implements ProximityManagerCallbacks, BleServerManagerCallbacks {
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = "ProximityService";
|
||||
|
||||
@@ -75,30 +76,27 @@ public class ProximityService extends BleMulticonnectProfileService implements P
|
||||
private final static int FIND_REQ = 2;
|
||||
private final static int SILENT_REQ = 3;
|
||||
|
||||
private final ProximityBinder mBinder = new ProximityBinder();
|
||||
private ProximityServerManager mServerManager;
|
||||
private MediaPlayer mMediaPlayer;
|
||||
private int mOriginalVolume;
|
||||
private final ProximityBinder binder = new ProximityBinder();
|
||||
private ProximityServerManager serverManager;
|
||||
private MediaPlayer mediaPlayer;
|
||||
private int originalVolume;
|
||||
/**
|
||||
* When a device starts an alarm on the phone it is added to this list.
|
||||
* Alarm is disabled when this list is empty.
|
||||
*/
|
||||
private List<BluetoothDevice> mDevicesWithAlarm;
|
||||
|
||||
private int mAttempt;
|
||||
private final static int MAX_ATTEMPTS = 1;
|
||||
private List<BluetoothDevice> devicesWithAlarm;
|
||||
|
||||
/**
|
||||
* This local binder is an interface for the bonded activity to operate with the proximity
|
||||
* sensor.
|
||||
*/
|
||||
public class ProximityBinder extends LocalBinder {
|
||||
class ProximityBinder extends LocalBinder {
|
||||
/**
|
||||
* Toggles the Immediate Alert on given remote device.
|
||||
*
|
||||
* @param device the connected device.
|
||||
*/
|
||||
public void toggleImmediateAlert(final BluetoothDevice device) {
|
||||
void toggleImmediateAlert(final BluetoothDevice device) {
|
||||
final ProximityManager manager = (ProximityManager) getBleManager(device);
|
||||
manager.toggleImmediateAlert();
|
||||
}
|
||||
@@ -110,7 +108,7 @@ public class ProximityService extends BleMulticonnectProfileService implements P
|
||||
* @param device the connected device.
|
||||
* @return True if alarm has been enabled, false if disabled.
|
||||
*/
|
||||
public boolean isImmediateAlertOn(final BluetoothDevice device) {
|
||||
boolean isImmediateAlertOn(final BluetoothDevice device) {
|
||||
final ProximityManager manager = (ProximityManager) getBleManager(device);
|
||||
return manager.isAlertEnabled();
|
||||
}
|
||||
@@ -122,7 +120,7 @@ public class ProximityService extends BleMulticonnectProfileService implements P
|
||||
* @return Battery value or null if no value was received or Battery Level characteristic
|
||||
* was not found, or the device is disconnected.
|
||||
*/
|
||||
public Integer getBatteryLevel(final BluetoothDevice device) {
|
||||
Integer getBatteryLevel(final BluetoothDevice device) {
|
||||
final ProximityManager manager = (ProximityManager) getBleManager(device);
|
||||
return manager.getBatteryLevel();
|
||||
}
|
||||
@@ -130,24 +128,31 @@ public class ProximityService extends BleMulticonnectProfileService implements P
|
||||
|
||||
@Override
|
||||
protected LocalBinder getBinder() {
|
||||
return mBinder;
|
||||
return binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggableBleManager<ProximityManagerCallbacks> initializeManager() {
|
||||
return new ProximityManager(this);
|
||||
final ProximityManager manager = new ProximityManager(this);
|
||||
manager.useServer(serverManager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldAutoConnect() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This broadcast receiver listens for {@link #ACTION_DISCONNECT} that may be fired by pressing
|
||||
* Disconnect action button on the notification.
|
||||
*/
|
||||
private final BroadcastReceiver mDisconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver disconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final BluetoothDevice device = intent.getParcelableExtra(EXTRA_DEVICE);
|
||||
mBinder.log(device, LogContract.Log.Level.INFO, "[Notification] DISCONNECT action pressed");
|
||||
mBinder.disconnect(device);
|
||||
binder.log(device, LogContract.Log.Level.INFO, "[Notification] DISCONNECT action pressed");
|
||||
binder.disconnect(device);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -155,34 +160,34 @@ public class ProximityService extends BleMulticonnectProfileService implements P
|
||||
* This broadcast receiver listens for {@link #ACTION_FIND} or {@link #ACTION_SILENT} that may
|
||||
* be fired by pressing Find me action button on the notification.
|
||||
*/
|
||||
private final BroadcastReceiver mToggleAlarmActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver toggleAlarmActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final BluetoothDevice device = intent.getParcelableExtra(EXTRA_DEVICE);
|
||||
switch (intent.getAction()) {
|
||||
case ACTION_FIND:
|
||||
mBinder.log(device, LogContract.Log.Level.INFO, "[Notification] FIND action pressed");
|
||||
binder.log(device, LogContract.Log.Level.INFO, "[Notification] FIND action pressed");
|
||||
break;
|
||||
case ACTION_SILENT:
|
||||
mBinder.log(device, LogContract.Log.Level.INFO, "[Notification] SILENT action pressed");
|
||||
binder.log(device, LogContract.Log.Level.INFO, "[Notification] SILENT action pressed");
|
||||
break;
|
||||
}
|
||||
mBinder.toggleImmediateAlert(device);
|
||||
binder.toggleImmediateAlert(device);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onServiceCreated() {
|
||||
mServerManager = new ProximityServerManager(this);
|
||||
mServerManager.setLogger(mBinder);
|
||||
serverManager = new ProximityServerManager(this);
|
||||
serverManager.setManagerCallbacks(this);
|
||||
|
||||
initializeAlarm();
|
||||
|
||||
registerReceiver(mDisconnectActionBroadcastReceiver, new IntentFilter(ACTION_DISCONNECT));
|
||||
registerReceiver(disconnectActionBroadcastReceiver, new IntentFilter(ACTION_DISCONNECT));
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_FIND);
|
||||
filter.addAction(ACTION_SILENT);
|
||||
registerReceiver(mToggleAlarmActionBroadcastReceiver, filter);
|
||||
registerReceiver(toggleAlarmActionBroadcastReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -190,55 +195,34 @@ public class ProximityService extends BleMulticonnectProfileService implements P
|
||||
cancelNotifications();
|
||||
|
||||
// Close the GATT server. If it hasn't been opened this method does nothing
|
||||
mServerManager.closeGattServer();
|
||||
serverManager.close();
|
||||
serverManager = null;
|
||||
|
||||
releaseAlarm();
|
||||
|
||||
unregisterReceiver(mDisconnectActionBroadcastReceiver);
|
||||
unregisterReceiver(mToggleAlarmActionBroadcastReceiver);
|
||||
unregisterReceiver(disconnectActionBroadcastReceiver);
|
||||
unregisterReceiver(toggleAlarmActionBroadcastReceiver);
|
||||
|
||||
super.onServiceStopped();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBluetoothEnabled() {
|
||||
mAttempt = 0;
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Runnable that = this;
|
||||
// Start the GATT Server only if Bluetooth is enabled
|
||||
mServerManager.openGattServer(ProximityService.this,
|
||||
new ProximityServerManager.OnServerOpenCallback() {
|
||||
@Override
|
||||
public void onGattServerOpen() {
|
||||
// We are now ready to reconnect devices
|
||||
ProximityService.super.onBluetoothEnabled();
|
||||
}
|
||||
// First, open the server. onServerReady() will be called when all services were added.
|
||||
serverManager.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGattServerFailed(final int error) {
|
||||
mServerManager.closeGattServer();
|
||||
|
||||
if (mAttempt < MAX_ATTEMPTS) {
|
||||
mAttempt++;
|
||||
getHandler().postDelayed(that, 2000);
|
||||
} else {
|
||||
showToast(getString(R.string.proximity_server_error, error));
|
||||
// GATT server failed to start, but we may connect as a client
|
||||
ProximityService.super.onBluetoothEnabled();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onServerReady() {
|
||||
// This will start reconnecting to devices that will previously connected.
|
||||
super.onBluetoothEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBluetoothDisabled() {
|
||||
super.onBluetoothDisabled();
|
||||
// Close the GATT server
|
||||
mServerManager.closeGattServer();
|
||||
serverManager.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -270,27 +254,25 @@ public class ProximityService extends BleMulticonnectProfileService implements P
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnected(final BluetoothDevice device) {
|
||||
public void onDeviceConnected(@NonNull final BluetoothDevice device) {
|
||||
super.onDeviceConnected(device);
|
||||
|
||||
if (!mBound) {
|
||||
if (!bound) {
|
||||
createBackgroundNotification();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
super.onServicesDiscovered(device, optionalServicesFound);
|
||||
mServerManager.openConnection(device);
|
||||
public void onDeviceConnectedToServer(@NonNull final BluetoothDevice device) {
|
||||
binder.log(Log.INFO, device.getAddress() + " connected to server");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLinkLossOccurred(final BluetoothDevice device) {
|
||||
mServerManager.cancelConnection(device);
|
||||
public void onLinkLossOccurred(@NonNull final BluetoothDevice device) {
|
||||
stopAlarm(device);
|
||||
super.onLinkLossOccurred(device);
|
||||
|
||||
if (!mBound) {
|
||||
if (!bound) {
|
||||
createBackgroundNotification();
|
||||
if (BluetoothAdapter.getDefaultAdapter().isEnabled())
|
||||
createLinkLossNotification(device);
|
||||
@@ -300,25 +282,19 @@ public class ProximityService extends BleMulticonnectProfileService implements P
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
mServerManager.cancelConnection(device);
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
stopAlarm(device);
|
||||
super.onDeviceDisconnected(device);
|
||||
|
||||
if (!mBound) {
|
||||
if (!bound) {
|
||||
cancelNotification(device);
|
||||
createBackgroundNotification();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAlarmTriggered(@NonNull final BluetoothDevice device) {
|
||||
playAlarm(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAlarmStopped(@NonNull final BluetoothDevice device) {
|
||||
stopAlarm(device);
|
||||
public void onDeviceDisconnectedFromServer(@NonNull final BluetoothDevice device) {
|
||||
binder.log(Log.INFO, device.getAddress() + " disconnected from server");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -328,11 +304,19 @@ public class ProximityService extends BleMulticonnectProfileService implements P
|
||||
broadcast.putExtra(EXTRA_ALARM_STATE, on);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
if (!mBound) {
|
||||
if (!bound) {
|
||||
createBackgroundNotification();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocalAlarmSwitched(@NonNull final BluetoothDevice device, final boolean on) {
|
||||
if (on)
|
||||
playAlarm(device);
|
||||
else
|
||||
stopAlarm(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) {
|
||||
final Intent broadcast = new Intent(BROADCAST_BATTERY_LEVEL);
|
||||
@@ -537,36 +521,36 @@ public class ProximityService extends BleMulticonnectProfileService implements P
|
||||
}
|
||||
|
||||
private void initializeAlarm() {
|
||||
mDevicesWithAlarm = new LinkedList<>();
|
||||
mMediaPlayer = new MediaPlayer();
|
||||
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
|
||||
mMediaPlayer.setLooping(true);
|
||||
mMediaPlayer.setVolume(1.0f, 1.0f);
|
||||
devicesWithAlarm = new LinkedList<>();
|
||||
mediaPlayer = new MediaPlayer();
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
|
||||
mediaPlayer.setLooping(true);
|
||||
mediaPlayer.setVolume(1.0f, 1.0f);
|
||||
try {
|
||||
mMediaPlayer.setDataSource(this, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM));
|
||||
mediaPlayer.setDataSource(this, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM));
|
||||
} catch (final IOException e) {
|
||||
Log.e(TAG, "Initialize Alarm failed: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseAlarm() {
|
||||
mMediaPlayer.release();
|
||||
mMediaPlayer = null;
|
||||
mediaPlayer.release();
|
||||
mediaPlayer = null;
|
||||
}
|
||||
|
||||
private void playAlarm(final BluetoothDevice device) {
|
||||
final boolean alarmPlaying = !mDevicesWithAlarm.isEmpty();
|
||||
if (!mDevicesWithAlarm.contains(device))
|
||||
mDevicesWithAlarm.add(device);
|
||||
final boolean alarmPlaying = !devicesWithAlarm.isEmpty();
|
||||
if (!devicesWithAlarm.contains(device))
|
||||
devicesWithAlarm.add(device);
|
||||
|
||||
if (!alarmPlaying) {
|
||||
// Save the current alarm volume and set it to max
|
||||
final AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
||||
mOriginalVolume = am.getStreamVolume(AudioManager.STREAM_ALARM);
|
||||
originalVolume = am.getStreamVolume(AudioManager.STREAM_ALARM);
|
||||
am.setStreamVolume(AudioManager.STREAM_ALARM, am.getStreamMaxVolume(AudioManager.STREAM_ALARM), AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
|
||||
try {
|
||||
mMediaPlayer.prepare();
|
||||
mMediaPlayer.start();
|
||||
mediaPlayer.prepare();
|
||||
mediaPlayer.start();
|
||||
} catch (final IOException e) {
|
||||
Log.e(TAG, "Prepare Alarm failed: ", e);
|
||||
}
|
||||
@@ -574,12 +558,12 @@ public class ProximityService extends BleMulticonnectProfileService implements P
|
||||
}
|
||||
|
||||
private void stopAlarm(final BluetoothDevice device) {
|
||||
mDevicesWithAlarm.remove(device);
|
||||
if (mDevicesWithAlarm.isEmpty() && mMediaPlayer.isPlaying()) {
|
||||
mMediaPlayer.stop();
|
||||
devicesWithAlarm.remove(device);
|
||||
if (devicesWithAlarm.isEmpty() && mediaPlayer.isPlaying()) {
|
||||
mediaPlayer.stop();
|
||||
// Restore original volume
|
||||
final AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
||||
am.setStreamVolume(AudioManager.STREAM_ALARM, mOriginalVolume, 0);
|
||||
am.setStreamVolume(AudioManager.STREAM_ALARM, originalVolume, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import android.view.Menu;
|
||||
import android.widget.TextView;
|
||||
@@ -44,16 +46,16 @@ import no.nordicsemi.android.nrftoolbox.rsc.settings.SettingsActivity;
|
||||
import no.nordicsemi.android.nrftoolbox.rsc.settings.SettingsFragment;
|
||||
|
||||
public class RSCActivity extends BleProfileServiceReadyActivity<RSCService.RSCBinder> {
|
||||
private TextView mSpeedView;
|
||||
private TextView mSpeedUnitView;
|
||||
private TextView mCadenceView;
|
||||
private TextView mDistanceView;
|
||||
private TextView mDistanceUnitView;
|
||||
private TextView mTotalDistanceView;
|
||||
private TextView mTotalDistanceUnitView;
|
||||
private TextView mStridesCountView;
|
||||
private TextView mActivityView;
|
||||
private TextView mBatteryLevelView;
|
||||
private TextView speedView;
|
||||
private TextView speedUnitView;
|
||||
private TextView cadenceView;
|
||||
private TextView distanceView;
|
||||
private TextView distanceUnitView;
|
||||
private TextView totalDistanceView;
|
||||
private TextView totalDistanceUnitView;
|
||||
private TextView stridesCountView;
|
||||
private TextView activityView;
|
||||
private TextView batteryLevelView;
|
||||
|
||||
@Override
|
||||
protected void onCreateView(final Bundle savedInstanceState) {
|
||||
@@ -63,26 +65,26 @@ public class RSCActivity extends BleProfileServiceReadyActivity<RSCService.RSCBi
|
||||
|
||||
@Override
|
||||
protected void onInitialize(final Bundle savedInstanceState) {
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, makeIntentFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
|
||||
}
|
||||
|
||||
private void setGui() {
|
||||
mSpeedView = findViewById(R.id.speed);
|
||||
mSpeedUnitView = findViewById(R.id.speed_unit);
|
||||
mCadenceView = findViewById(R.id.cadence);
|
||||
mDistanceView = findViewById(R.id.distance);
|
||||
mDistanceUnitView = findViewById(R.id.distance_unit);
|
||||
mTotalDistanceView = findViewById(R.id.total_distance);
|
||||
mTotalDistanceUnitView = findViewById(R.id.total_distance_unit);
|
||||
mStridesCountView = findViewById(R.id.strides);
|
||||
mActivityView = findViewById(R.id.activity);
|
||||
mBatteryLevelView = findViewById(R.id.battery);
|
||||
speedView = findViewById(R.id.speed);
|
||||
speedUnitView = findViewById(R.id.speed_unit);
|
||||
cadenceView = findViewById(R.id.cadence);
|
||||
distanceView = findViewById(R.id.distance);
|
||||
distanceUnitView = findViewById(R.id.distance_unit);
|
||||
totalDistanceView = findViewById(R.id.total_distance);
|
||||
totalDistanceUnitView = findViewById(R.id.total_distance_unit);
|
||||
stridesCountView = findViewById(R.id.strides);
|
||||
activityView = findViewById(R.id.activity);
|
||||
batteryLevelView = findViewById(R.id.battery);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,13 +95,13 @@ public class RSCActivity extends BleProfileServiceReadyActivity<RSCService.RSCBi
|
||||
|
||||
@Override
|
||||
protected void setDefaultUI() {
|
||||
mSpeedView.setText(R.string.not_available_value);
|
||||
mCadenceView.setText(R.string.not_available_value);
|
||||
mDistanceView.setText(R.string.not_available_value);
|
||||
mTotalDistanceView.setText(R.string.not_available_value);
|
||||
mStridesCountView.setText(R.string.not_available_value);
|
||||
mActivityView.setText(R.string.not_available);
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
speedView.setText(R.string.not_available_value);
|
||||
cadenceView.setText(R.string.not_available_value);
|
||||
distanceView.setText(R.string.not_available_value);
|
||||
totalDistanceView.setText(R.string.not_available_value);
|
||||
stridesCountView.setText(R.string.not_available_value);
|
||||
activityView.setText(R.string.not_available);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
|
||||
setUnits();
|
||||
}
|
||||
@@ -110,19 +112,19 @@ public class RSCActivity extends BleProfileServiceReadyActivity<RSCService.RSCBi
|
||||
|
||||
switch (unit) {
|
||||
case SettingsFragment.SETTINGS_UNIT_M_S: // [m/s]
|
||||
mSpeedUnitView.setText(R.string.rsc_speed_unit_m_s);
|
||||
mDistanceUnitView.setText(R.string.rsc_distance_unit_m);
|
||||
mTotalDistanceUnitView.setText(R.string.rsc_total_distance_unit_km);
|
||||
speedUnitView.setText(R.string.rsc_speed_unit_m_s);
|
||||
distanceUnitView.setText(R.string.rsc_distance_unit_m);
|
||||
totalDistanceUnitView.setText(R.string.rsc_total_distance_unit_km);
|
||||
break;
|
||||
case SettingsFragment.SETTINGS_UNIT_KM_H: // [km/h]
|
||||
mSpeedUnitView.setText(R.string.rsc_speed_unit_km_h);
|
||||
mDistanceUnitView.setText(R.string.rsc_distance_unit_m);
|
||||
mTotalDistanceUnitView.setText(R.string.rsc_total_distance_unit_km);
|
||||
speedUnitView.setText(R.string.rsc_speed_unit_km_h);
|
||||
distanceUnitView.setText(R.string.rsc_distance_unit_m);
|
||||
totalDistanceUnitView.setText(R.string.rsc_total_distance_unit_km);
|
||||
break;
|
||||
case SettingsFragment.SETTINGS_UNIT_MPH: // [mph]
|
||||
mSpeedUnitView.setText(R.string.rsc_speed_unit_mph);
|
||||
mDistanceUnitView.setText(R.string.rsc_distance_unit_yd);
|
||||
mTotalDistanceUnitView.setText(R.string.rsc_total_distance_unit_mile);
|
||||
speedUnitView.setText(R.string.rsc_speed_unit_mph);
|
||||
distanceUnitView.setText(R.string.rsc_distance_unit_yd);
|
||||
totalDistanceUnitView.setText(R.string.rsc_total_distance_unit_mile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -180,14 +182,14 @@ public class RSCActivity extends BleProfileServiceReadyActivity<RSCService.RSCBi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(@NonNull final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// not used
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
}
|
||||
|
||||
private void onMeasurementReceived(float speed, int cadence, long totalDistance, final boolean running) {
|
||||
@@ -200,34 +202,34 @@ public class RSCActivity extends BleProfileServiceReadyActivity<RSCService.RSCBi
|
||||
// pass through intended
|
||||
case SettingsFragment.SETTINGS_UNIT_M_S:
|
||||
if (totalDistance == -1) {
|
||||
mTotalDistanceView.setText(R.string.not_available);
|
||||
mTotalDistanceUnitView.setText(null);
|
||||
totalDistanceView.setText(R.string.not_available);
|
||||
totalDistanceUnitView.setText(null);
|
||||
} else {
|
||||
mTotalDistanceView.setText(String.format(Locale.US, "%.2f", totalDistance / 1000.0f)); // 1 km in m
|
||||
mTotalDistanceUnitView.setText(R.string.rsc_total_distance_unit_km);
|
||||
totalDistanceView.setText(String.format(Locale.US, "%.2f", totalDistance / 1000.0f)); // 1 km in m
|
||||
totalDistanceUnitView.setText(R.string.rsc_total_distance_unit_km);
|
||||
}
|
||||
break;
|
||||
case SettingsFragment.SETTINGS_UNIT_MPH:
|
||||
speed = speed * 2.2369f;
|
||||
if (totalDistance == -1) {
|
||||
mTotalDistanceView.setText(R.string.not_available);
|
||||
mTotalDistanceUnitView.setText(null);
|
||||
totalDistanceView.setText(R.string.not_available);
|
||||
totalDistanceUnitView.setText(null);
|
||||
} else {
|
||||
mTotalDistanceView.setText(String.format(Locale.US, "%.2f", totalDistance / 1609.31f)); // 1 mile in m
|
||||
mTotalDistanceUnitView.setText(R.string.rsc_total_distance_unit_mile);
|
||||
totalDistanceView.setText(String.format(Locale.US, "%.2f", totalDistance / 1609.31f)); // 1 mile in m
|
||||
totalDistanceUnitView.setText(R.string.rsc_total_distance_unit_mile);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
mSpeedView.setText(String.format(Locale.US, "%.1f", speed));
|
||||
mCadenceView.setText(String.format(Locale.US, "%d", cadence));
|
||||
mActivityView.setText(running ? R.string.rsc_running : R.string.rsc_walking);
|
||||
speedView.setText(String.format(Locale.US, "%.1f", speed));
|
||||
cadenceView.setText(String.format(Locale.US, "%d", cadence));
|
||||
activityView.setText(running ? R.string.rsc_running : R.string.rsc_walking);
|
||||
}
|
||||
|
||||
private void onStripesUpdate(final long distance, final int strides) {
|
||||
if (distance == -1) {
|
||||
mDistanceView.setText(R.string.not_available);
|
||||
mDistanceUnitView.setText(R.string.rsc_distance_unit_m);
|
||||
distanceView.setText(R.string.not_available);
|
||||
distanceUnitView.setText(R.string.rsc_distance_unit_m);
|
||||
} else {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
final int unit = Integer.parseInt(preferences.getString(SettingsFragment.SETTINGS_UNIT, String.valueOf(SettingsFragment.SETTINGS_UNIT_DEFAULT)));
|
||||
@@ -236,29 +238,29 @@ public class RSCActivity extends BleProfileServiceReadyActivity<RSCService.RSCBi
|
||||
case SettingsFragment.SETTINGS_UNIT_KM_H:
|
||||
case SettingsFragment.SETTINGS_UNIT_M_S:
|
||||
if (distance < 100000L) { // 1 km in cm
|
||||
mDistanceView.setText(String.format(Locale.US, "%.1f", distance / 100.0f));
|
||||
mDistanceUnitView.setText(R.string.rsc_distance_unit_m);
|
||||
distanceView.setText(String.format(Locale.US, "%.1f", distance / 100.0f));
|
||||
distanceUnitView.setText(R.string.rsc_distance_unit_m);
|
||||
} else {
|
||||
mDistanceView.setText(String.format(Locale.US, "%.2f", distance / 100000.0f));
|
||||
mDistanceUnitView.setText(R.string.rsc_distance_unit_km);
|
||||
distanceView.setText(String.format(Locale.US, "%.2f", distance / 100000.0f));
|
||||
distanceUnitView.setText(R.string.rsc_distance_unit_km);
|
||||
}
|
||||
break;
|
||||
case SettingsFragment.SETTINGS_UNIT_MPH:
|
||||
if (distance < 160931L) { // 1 mile in cm
|
||||
mDistanceView.setText(String.format(Locale.US, "%.1f", distance / 91.4392f));
|
||||
mDistanceUnitView.setText(R.string.rsc_distance_unit_yd);
|
||||
distanceView.setText(String.format(Locale.US, "%.1f", distance / 91.4392f));
|
||||
distanceUnitView.setText(R.string.rsc_distance_unit_yd);
|
||||
} else {
|
||||
mDistanceView.setText(String.format(Locale.US, "%.2f", distance / 160931.23f));
|
||||
mDistanceUnitView.setText(R.string.rsc_distance_unit_mile);
|
||||
distanceView.setText(String.format(Locale.US, "%.2f", distance / 160931.23f));
|
||||
distanceUnitView.setText(R.string.rsc_distance_unit_mile);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mStridesCountView.setText(String.valueOf(strides));
|
||||
stridesCountView.setText(String.valueOf(strides));
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
|
||||
@@ -40,11 +40,11 @@ import no.nordicsemi.android.nrftoolbox.parser.RSCMeasurementParser;
|
||||
|
||||
public class RSCManager extends BatteryManager<RSCManagerCallbacks> {
|
||||
/** Running Speed and Cadence Measurement service UUID */
|
||||
public static final UUID RUNNING_SPEED_AND_CADENCE_SERVICE_UUID = UUID.fromString("00001814-0000-1000-8000-00805f9b34fb");
|
||||
static final UUID RUNNING_SPEED_AND_CADENCE_SERVICE_UUID = UUID.fromString("00001814-0000-1000-8000-00805f9b34fb");
|
||||
/** Running Speed and Cadence Measurement characteristic UUID */
|
||||
private static final UUID RSC_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A53-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private BluetoothGattCharacteristic mRSCMeasurementCharacteristic;
|
||||
private BluetoothGattCharacteristic rscMeasurementCharacteristic;
|
||||
|
||||
RSCManager(final Context context) {
|
||||
super(context);
|
||||
@@ -53,19 +53,19 @@ public class RSCManager extends BatteryManager<RSCManagerCallbacks> {
|
||||
@NonNull
|
||||
@Override
|
||||
protected BatteryManagerGattCallback getGattCallback() {
|
||||
return mGattCallback;
|
||||
return gattCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* BluetoothGatt callbacks for connection/disconnection, service discovery,
|
||||
* receiving indication, etc.
|
||||
*/
|
||||
private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
|
||||
private final BatteryManagerGattCallback gattCallback = new BatteryManagerGattCallback() {
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
super.initialize();
|
||||
setNotificationCallback(mRSCMeasurementCharacteristic)
|
||||
setNotificationCallback(rscMeasurementCharacteristic)
|
||||
.with(new RunningSpeedAndCadenceMeasurementDataCallback() {
|
||||
@Override
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||
@@ -78,26 +78,26 @@ public class RSCManager extends BatteryManager<RSCManagerCallbacks> {
|
||||
final float instantaneousSpeed, final int instantaneousCadence,
|
||||
@Nullable final Integer strideLength,
|
||||
@Nullable final Long totalDistance) {
|
||||
mCallbacks.onRSCMeasurementReceived(device, running, instantaneousSpeed,
|
||||
callbacks.onRSCMeasurementReceived(device, running, instantaneousSpeed,
|
||||
instantaneousCadence, strideLength, totalDistance);
|
||||
}
|
||||
});
|
||||
enableNotifications(mRSCMeasurementCharacteristic).enqueue();
|
||||
enableNotifications(rscMeasurementCharacteristic).enqueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(RUNNING_SPEED_AND_CADENCE_SERVICE_UUID);
|
||||
if (service != null) {
|
||||
mRSCMeasurementCharacteristic = service.getCharacteristic(RSC_MEASUREMENT_CHARACTERISTIC_UUID);
|
||||
rscMeasurementCharacteristic = service.getCharacteristic(RSC_MEASUREMENT_CHARACTERISTIC_UUID);
|
||||
}
|
||||
return mRSCMeasurementCharacteristic != null;
|
||||
return rscMeasurementCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeviceDisconnected() {
|
||||
super.onDeviceDisconnected();
|
||||
mRSCMeasurementCharacteristic = null;
|
||||
rscMeasurementCharacteristic = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import no.nordicsemi.android.nrftoolbox.profile.BleProfileService;
|
||||
import no.nordicsemi.android.nrftoolbox.profile.LoggableBleManager;
|
||||
|
||||
public class RSCService extends BleProfileService implements RSCManagerCallbacks {
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = "RSCService";
|
||||
|
||||
public static final String BROADCAST_RSC_MEASUREMENT = "no.nordicsemi.android.nrftoolbox.rsc.BROADCAST_RSC_MEASUREMENT";
|
||||
@@ -63,32 +64,32 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks
|
||||
|
||||
private final static String ACTION_DISCONNECT = "no.nordicsemi.android.nrftoolbox.rsc.ACTION_DISCONNECT";
|
||||
|
||||
private RSCManager mManager;
|
||||
private RSCManager manager;
|
||||
|
||||
/**
|
||||
* The last value of a cadence
|
||||
*/
|
||||
private float mCadence;
|
||||
private float cadence;
|
||||
/**
|
||||
* Trip distance in cm
|
||||
*/
|
||||
private long mDistance;
|
||||
private long distance;
|
||||
/**
|
||||
* Stride length in cm
|
||||
*/
|
||||
private Integer mStrideLength;
|
||||
private Integer strideLength;
|
||||
/**
|
||||
* Number of steps in the trip
|
||||
*/
|
||||
private int mStepsNumber;
|
||||
private boolean mTaskInProgress;
|
||||
private final Handler mHandler = new Handler();
|
||||
private int stepsNumber;
|
||||
private boolean taskInProgress;
|
||||
private final Handler handler = new Handler();
|
||||
|
||||
private final static int NOTIFICATION_ID = 200;
|
||||
private final static int OPEN_ACTIVITY_REQ = 0;
|
||||
private final static int DISCONNECT_REQ = 1;
|
||||
|
||||
private final LocalBinder mBinder = new RSCBinder();
|
||||
private final LocalBinder binder = new RSCBinder();
|
||||
|
||||
/**
|
||||
* This local binder is an interface for the bound activity to operate with the RSC sensor.
|
||||
@@ -99,12 +100,12 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks
|
||||
|
||||
@Override
|
||||
protected LocalBinder getBinder() {
|
||||
return mBinder;
|
||||
return binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggableBleManager<RSCManagerCallbacks> initializeManager() {
|
||||
return mManager = new RSCManager(this);
|
||||
return manager = new RSCManager(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,14 +114,14 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks
|
||||
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_DISCONNECT);
|
||||
registerReceiver(mDisconnectActionBroadcastReceiver, filter);
|
||||
registerReceiver(disconnectActionBroadcastReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
// when user has disconnected from the sensor, we have to cancel the notification that we've created some milliseconds before using unbindService
|
||||
stopForegroundService();
|
||||
unregisterReceiver(mDisconnectActionBroadcastReceiver);
|
||||
unregisterReceiver(disconnectActionBroadcastReceiver);
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
@@ -132,7 +133,7 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks
|
||||
if (isConnected()) {
|
||||
// This method will read the Battery Level value, if possible and then try to enable battery notifications (if it has NOTIFY property).
|
||||
// If the Battery Level characteristic has only the NOTIFY property, it will only try to enable notifications.
|
||||
mManager.readBatteryLevelCharacteristic();
|
||||
manager.readBatteryLevelCharacteristic();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,29 +142,29 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks
|
||||
// When we are connected, but the application is not open, we are not really interested in battery level notifications.
|
||||
// But we will still be receiving other values, if enabled.
|
||||
if (isConnected())
|
||||
mManager.disableBatteryLevelCharacteristicNotifications();
|
||||
manager.disableBatteryLevelCharacteristicNotifications();
|
||||
|
||||
startForegroundService();
|
||||
}
|
||||
|
||||
private final Runnable mUpdateStridesTask = new Runnable() {
|
||||
private final Runnable updateStridesTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isConnected())
|
||||
return;
|
||||
|
||||
mStepsNumber++;
|
||||
mDistance += mStrideLength; // [cm]
|
||||
stepsNumber++;
|
||||
distance += strideLength; // [cm]
|
||||
final Intent broadcast = new Intent(BROADCAST_STRIDES_UPDATE);
|
||||
broadcast.putExtra(EXTRA_STRIDES, mStepsNumber);
|
||||
broadcast.putExtra(EXTRA_DISTANCE, mDistance);
|
||||
broadcast.putExtra(EXTRA_STRIDES, stepsNumber);
|
||||
broadcast.putExtra(EXTRA_DISTANCE, distance);
|
||||
LocalBroadcastManager.getInstance(RSCService.this).sendBroadcast(broadcast);
|
||||
|
||||
if (mCadence > 0) {
|
||||
final long interval = (long) (1000.0f * 60.0f / mCadence);
|
||||
mHandler.postDelayed(mUpdateStridesTask, interval);
|
||||
if (cadence > 0) {
|
||||
final long interval = (long) (1000.0f * 60.0f / cadence);
|
||||
handler.postDelayed(updateStridesTask, interval);
|
||||
} else {
|
||||
mTaskInProgress = false;
|
||||
taskInProgress = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -183,15 +184,15 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
// Start strides counter if not in progress
|
||||
mCadence = instantaneousCadence;
|
||||
cadence = instantaneousCadence;
|
||||
if (strideLength != null) {
|
||||
mStrideLength = strideLength;
|
||||
this.strideLength = strideLength;
|
||||
}
|
||||
if (!mTaskInProgress && strideLength != null && instantaneousCadence > 0) {
|
||||
mTaskInProgress = true;
|
||||
if (!taskInProgress && strideLength != null && instantaneousCadence > 0) {
|
||||
taskInProgress = true;
|
||||
|
||||
final long interval = (long) (1000.0f * 60.0f / mCadence);
|
||||
mHandler.postDelayed(mUpdateStridesTask, interval);
|
||||
final long interval = (long) (1000.0f * 60.0f / cadence);
|
||||
handler.postDelayed(updateStridesTask, interval);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,6 +239,7 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks
|
||||
* f.e. <code><string name="name">%s is connected</string></code>
|
||||
* @param defaults
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private Notification createNotification(final int messageResId, final int defaults) {
|
||||
final Intent parentIntent = new Intent(this, FeaturesActivity.class);
|
||||
parentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
@@ -269,7 +271,7 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks
|
||||
/**
|
||||
* This broadcast receiver listens for {@link #ACTION_DISCONNECT} that may be fired by pressing Disconnect action button on the notification.
|
||||
*/
|
||||
private final BroadcastReceiver mDisconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver disconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
Logger.i(getLogSession(), "[Notification] Disconnect action pressed");
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
package no.nordicsemi.android.nrftoolbox.scanner;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -34,33 +33,32 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
import no.nordicsemi.android.support.v18.scanner.ScanResult;
|
||||
|
||||
/**
|
||||
* DeviceListAdapter class is list adapter for showing scanned Devices name, address and RSSI image based on RSSI values.
|
||||
*/
|
||||
public class DeviceListAdapter extends BaseAdapter {
|
||||
class DeviceListAdapter extends BaseAdapter {
|
||||
private static final int TYPE_TITLE = 0;
|
||||
private static final int TYPE_ITEM = 1;
|
||||
private static final int TYPE_EMPTY = 2;
|
||||
|
||||
private final ArrayList<ExtendedBluetoothDevice> mListBondedValues = new ArrayList<>();
|
||||
private final ArrayList<ExtendedBluetoothDevice> mListValues = new ArrayList<>();
|
||||
private final Context mContext;
|
||||
private final ArrayList<ExtendedBluetoothDevice> listBondedValues = new ArrayList<>();
|
||||
private final ArrayList<ExtendedBluetoothDevice> listValues = new ArrayList<>();
|
||||
|
||||
public DeviceListAdapter(final Context context) {
|
||||
mContext = context;
|
||||
DeviceListAdapter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a list of bonded devices.
|
||||
* @param devices list of bonded devices.
|
||||
*/
|
||||
public void addBondedDevices(final Set<BluetoothDevice> devices) {
|
||||
final List<ExtendedBluetoothDevice> bondedDevices = mListBondedValues;
|
||||
void addBondedDevices(@NonNull final Set<BluetoothDevice> devices) {
|
||||
for (BluetoothDevice device : devices) {
|
||||
bondedDevices.add(new ExtendedBluetoothDevice(device));
|
||||
listBondedValues.add(new ExtendedBluetoothDevice(device));
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
@@ -69,11 +67,11 @@ public class DeviceListAdapter extends BaseAdapter {
|
||||
* Updates the list of not bonded devices.
|
||||
* @param results list of results from the scanner
|
||||
*/
|
||||
public void update(final List<ScanResult> results) {
|
||||
public void update(@NonNull final List<ScanResult> results) {
|
||||
for (final ScanResult result : results) {
|
||||
final ExtendedBluetoothDevice device = findDevice(result);
|
||||
if (device == null) {
|
||||
mListValues.add(new ExtendedBluetoothDevice(result));
|
||||
listValues.add(new ExtendedBluetoothDevice(result));
|
||||
} else {
|
||||
device.name = result.getScanRecord() != null ? result.getScanRecord().getDeviceName() : null;
|
||||
device.rssi = result.getRssi();
|
||||
@@ -82,46 +80,46 @@ public class DeviceListAdapter extends BaseAdapter {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private ExtendedBluetoothDevice findDevice(final ScanResult result) {
|
||||
for (final ExtendedBluetoothDevice device : mListBondedValues)
|
||||
private ExtendedBluetoothDevice findDevice(@NonNull final ScanResult result) {
|
||||
for (final ExtendedBluetoothDevice device : listBondedValues)
|
||||
if (device.matches(result))
|
||||
return device;
|
||||
for (final ExtendedBluetoothDevice device : mListValues)
|
||||
for (final ExtendedBluetoothDevice device : listValues)
|
||||
if (device.matches(result))
|
||||
return device;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void clearDevices() {
|
||||
mListValues.clear();
|
||||
void clearDevices() {
|
||||
listValues.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
final int bondedCount = mListBondedValues.size() + 1; // 1 for the title
|
||||
final int availableCount = mListValues.isEmpty() ? 2 : mListValues.size() + 1; // 1 for title, 1 for empty text
|
||||
final int bondedCount = listBondedValues.size() + 1; // 1 for the title
|
||||
final int availableCount = listValues.isEmpty() ? 2 : listValues.size() + 1; // 1 for title, 1 for empty text
|
||||
if (bondedCount == 1)
|
||||
return availableCount;
|
||||
return bondedCount + availableCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
final int bondedCount = mListBondedValues.size() + 1; // 1 for the title
|
||||
if (mListBondedValues.isEmpty()) {
|
||||
public Object getItem(final int position) {
|
||||
final int bondedCount = listBondedValues.size() + 1; // 1 for the title
|
||||
if (listBondedValues.isEmpty()) {
|
||||
if (position == 0)
|
||||
return R.string.scanner_subtitle_not_bonded;
|
||||
else
|
||||
return mListValues.get(position - 1);
|
||||
return listValues.get(position - 1);
|
||||
} else {
|
||||
if (position == 0)
|
||||
return R.string.scanner_subtitle_bonded;
|
||||
if (position < bondedCount)
|
||||
return mListBondedValues.get(position - 1);
|
||||
return listBondedValues.get(position - 1);
|
||||
if (position == bondedCount)
|
||||
return R.string.scanner_subtitle_not_bonded;
|
||||
return mListValues.get(position - bondedCount - 1);
|
||||
return listValues.get(position - bondedCount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,32 +134,32 @@ public class DeviceListAdapter extends BaseAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
public boolean isEnabled(final int position) {
|
||||
return getItemViewType(position) == TYPE_ITEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
public int getItemViewType(final int position) {
|
||||
if (position == 0)
|
||||
return TYPE_TITLE;
|
||||
|
||||
if (!mListBondedValues.isEmpty() && position == mListBondedValues.size() + 1)
|
||||
if (!listBondedValues.isEmpty() && position == listBondedValues.size() + 1)
|
||||
return TYPE_TITLE;
|
||||
|
||||
if (position == getCount() - 1 && mListValues.isEmpty())
|
||||
if (position == getCount() - 1 && listValues.isEmpty())
|
||||
return TYPE_EMPTY;
|
||||
|
||||
return TYPE_ITEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
public long getItemId(final int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View oldView, ViewGroup parent) {
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
public View getView(final int position, @Nullable final View oldView, @NonNull final ViewGroup parent) {
|
||||
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
final int type = getItemViewType(position);
|
||||
|
||||
View view = oldView;
|
||||
@@ -191,7 +189,7 @@ public class DeviceListAdapter extends BaseAdapter {
|
||||
final ExtendedBluetoothDevice device = (ExtendedBluetoothDevice) getItem(position);
|
||||
final ViewHolder holder = (ViewHolder) view.getTag();
|
||||
final String name = device.name;
|
||||
holder.name.setText(name != null ? name : mContext.getString(R.string.not_available));
|
||||
holder.name.setText(name != null ? name : parent.getContext().getString(R.string.not_available));
|
||||
holder.address.setText(device.device.getAddress());
|
||||
if (!device.isBonded || device.rssi != ExtendedBluetoothDevice.NO_RSSI) {
|
||||
final int rssiPercent = (int) (100.0f * (127.0f + device.rssi) / (127.0f + 20.0f));
|
||||
|
||||
@@ -23,8 +23,10 @@ package no.nordicsemi.android.nrftoolbox.scanner;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import no.nordicsemi.android.support.v18.scanner.ScanResult;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class ExtendedBluetoothDevice {
|
||||
/* package */ static final int NO_RSSI = -1000;
|
||||
public final BluetoothDevice device;
|
||||
@@ -33,21 +35,21 @@ public class ExtendedBluetoothDevice {
|
||||
public int rssi;
|
||||
public boolean isBonded;
|
||||
|
||||
public ExtendedBluetoothDevice(final ScanResult scanResult) {
|
||||
public ExtendedBluetoothDevice(@NonNull final ScanResult scanResult) {
|
||||
this.device = scanResult.getDevice();
|
||||
this.name = scanResult.getScanRecord() != null ? scanResult.getScanRecord().getDeviceName() : null;
|
||||
this.rssi = scanResult.getRssi();
|
||||
this.isBonded = false;
|
||||
}
|
||||
|
||||
public ExtendedBluetoothDevice(final BluetoothDevice device) {
|
||||
public ExtendedBluetoothDevice(@NonNull final BluetoothDevice device) {
|
||||
this.device = device;
|
||||
this.name = device.getName();
|
||||
this.rssi = NO_RSSI;
|
||||
this.isBonded = true;
|
||||
}
|
||||
|
||||
public boolean matches(final ScanResult scanResult) {
|
||||
public boolean matches(@NonNull final ScanResult scanResult) {
|
||||
return device.getAddress().equals(scanResult.getDevice().getAddress());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.ParcelUuid;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.core.content.ContextCompat;
|
||||
@@ -70,17 +71,17 @@ public class ScannerFragment extends DialogFragment {
|
||||
|
||||
private final static int REQUEST_PERMISSION_REQ_CODE = 34; // any 8-bit number
|
||||
|
||||
private BluetoothAdapter mBluetoothAdapter;
|
||||
private OnDeviceSelectedListener mListener;
|
||||
private DeviceListAdapter mAdapter;
|
||||
private final Handler mHandler = new Handler();
|
||||
private Button mScanButton;
|
||||
private BluetoothAdapter bluetoothAdapter;
|
||||
private OnDeviceSelectedListener listener;
|
||||
private DeviceListAdapter adapter;
|
||||
private final Handler handler = new Handler();
|
||||
private Button scanButton;
|
||||
|
||||
private View mPermissionRationale;
|
||||
private View permissionRationale;
|
||||
|
||||
private ParcelUuid mUuid;
|
||||
private ParcelUuid uuid;
|
||||
|
||||
private boolean mIsScanning = false;
|
||||
private boolean scanning = false;
|
||||
|
||||
public static ScannerFragment getInstance(final UUID uuid) {
|
||||
final ScannerFragment fragment = new ScannerFragment();
|
||||
@@ -106,7 +107,7 @@ public class ScannerFragment extends DialogFragment {
|
||||
* always returns <code>null</code>, i.e. Sony Xperia Z1 (C6903) with Android 4.3.
|
||||
* The name has to be parsed manually form the Advertisement packet.
|
||||
*/
|
||||
void onDeviceSelected(final BluetoothDevice device, final String name);
|
||||
void onDeviceSelected(@NonNull final BluetoothDevice device, @Nullable final String name);
|
||||
|
||||
/**
|
||||
* Fired when scanner dialog has been cancelled without selecting a device.
|
||||
@@ -118,10 +119,10 @@ public class ScannerFragment extends DialogFragment {
|
||||
* This will make sure that {@link OnDeviceSelectedListener} interface is implemented by activity.
|
||||
*/
|
||||
@Override
|
||||
public void onAttach(final Context context) {
|
||||
public void onAttach(@NonNull final Context context) {
|
||||
super.onAttach(context);
|
||||
try {
|
||||
this.mListener = (OnDeviceSelectedListener) context;
|
||||
this.listener = (OnDeviceSelectedListener) context;
|
||||
} catch (final ClassCastException e) {
|
||||
throw new ClassCastException(context.toString() + " must implement OnDeviceSelectedListener");
|
||||
}
|
||||
@@ -133,12 +134,12 @@ public class ScannerFragment extends DialogFragment {
|
||||
|
||||
final Bundle args = getArguments();
|
||||
if (args != null && args.containsKey(PARAM_UUID)) {
|
||||
mUuid = args.getParcelable(PARAM_UUID);
|
||||
uuid = args.getParcelable(PARAM_UUID);
|
||||
}
|
||||
|
||||
final BluetoothManager manager = (BluetoothManager) requireContext().getSystemService(Context.BLUETOOTH_SERVICE);
|
||||
if (manager != null) {
|
||||
mBluetoothAdapter = manager.getAdapter();
|
||||
bluetoothAdapter = manager.getAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,27 +153,28 @@ public class ScannerFragment extends DialogFragment {
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
|
||||
final View dialogView = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_device_selection, null);
|
||||
final View dialogView = LayoutInflater.from(requireContext())
|
||||
.inflate(R.layout.fragment_device_selection, null);
|
||||
final ListView listview = dialogView.findViewById(android.R.id.list);
|
||||
|
||||
listview.setEmptyView(dialogView.findViewById(android.R.id.empty));
|
||||
listview.setAdapter(mAdapter = new DeviceListAdapter(getActivity()));
|
||||
listview.setAdapter(adapter = new DeviceListAdapter());
|
||||
|
||||
builder.setTitle(R.string.scanner_title);
|
||||
final AlertDialog dialog = builder.setView(dialogView).create();
|
||||
listview.setOnItemClickListener((parent, view, position, id) -> {
|
||||
stopScan();
|
||||
dialog.dismiss();
|
||||
final ExtendedBluetoothDevice d = (ExtendedBluetoothDevice) mAdapter.getItem(position);
|
||||
mListener.onDeviceSelected(d.device, d.name);
|
||||
final ExtendedBluetoothDevice d = (ExtendedBluetoothDevice) adapter.getItem(position);
|
||||
listener.onDeviceSelected(d.device, d.name);
|
||||
});
|
||||
|
||||
mPermissionRationale = dialogView.findViewById(R.id.permission_rationale); // this is not null only on API23+
|
||||
permissionRationale = dialogView.findViewById(R.id.permission_rationale); // this is not null only on API23+
|
||||
|
||||
mScanButton = dialogView.findViewById(R.id.action_cancel);
|
||||
mScanButton.setOnClickListener(v -> {
|
||||
scanButton = dialogView.findViewById(R.id.action_cancel);
|
||||
scanButton.setOnClickListener(v -> {
|
||||
if (v.getId() == R.id.action_cancel) {
|
||||
if (mIsScanning) {
|
||||
if (scanning) {
|
||||
dialog.cancel();
|
||||
} else {
|
||||
startScan();
|
||||
@@ -187,10 +189,10 @@ public class ScannerFragment extends DialogFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
public void onCancel(@NonNull DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
|
||||
mListener.onDialogCanceled();
|
||||
listener.onDialogCanceled();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -201,7 +203,7 @@ public class ScannerFragment extends DialogFragment {
|
||||
// We have been granted the Manifest.permission.ACCESS_FINE_LOCATION permission. Now we may proceed with scanning.
|
||||
startScan();
|
||||
} else {
|
||||
mPermissionRationale.setVisibility(View.VISIBLE);
|
||||
permissionRationale.setVisibility(View.VISIBLE);
|
||||
Toast.makeText(getActivity(), R.string.no_required_permission, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
break;
|
||||
@@ -210,7 +212,7 @@ public class ScannerFragment extends DialogFragment {
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan for 5 seconds and then stop scanning when a BluetoothLE device is found then mLEScanCallback
|
||||
* Scan for 5 seconds and then stop scanning when a BluetoothLE device is found then lEScanCallback
|
||||
* is activated This will perform regular scan for custom BLE Service UUID and then filter out.
|
||||
* using class ScannerServiceParser
|
||||
*/
|
||||
@@ -220,8 +222,8 @@ public class ScannerFragment extends DialogFragment {
|
||||
// On API older than Marshmallow the following code does nothing.
|
||||
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
// When user pressed Deny and still wants to use this functionality, show the rationale
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(requireActivity(), Manifest.permission.ACCESS_FINE_LOCATION) && mPermissionRationale.getVisibility() == View.GONE) {
|
||||
mPermissionRationale.setVisibility(View.VISIBLE);
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(requireActivity(), Manifest.permission.ACCESS_FINE_LOCATION) && permissionRationale.getVisibility() == View.GONE) {
|
||||
permissionRationale.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -230,23 +232,23 @@ public class ScannerFragment extends DialogFragment {
|
||||
}
|
||||
|
||||
// Hide the rationale message, we don't need it anymore.
|
||||
if (mPermissionRationale != null)
|
||||
mPermissionRationale.setVisibility(View.GONE);
|
||||
if (permissionRationale != null)
|
||||
permissionRationale.setVisibility(View.GONE);
|
||||
|
||||
mAdapter.clearDevices();
|
||||
mScanButton.setText(R.string.scanner_action_cancel);
|
||||
adapter.clearDevices();
|
||||
scanButton.setText(R.string.scanner_action_cancel);
|
||||
|
||||
final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
|
||||
final ScanSettings settings = new ScanSettings.Builder()
|
||||
.setLegacy(false)
|
||||
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).setReportDelay(1000).setUseHardwareBatchingIfSupported(false).build();
|
||||
final List<ScanFilter> filters = new ArrayList<>();
|
||||
filters.add(new ScanFilter.Builder().setServiceUuid(mUuid).build());
|
||||
filters.add(new ScanFilter.Builder().setServiceUuid(uuid).build());
|
||||
scanner.startScan(filters, settings, scanCallback);
|
||||
|
||||
mIsScanning = true;
|
||||
mHandler.postDelayed(() -> {
|
||||
if (mIsScanning) {
|
||||
scanning = true;
|
||||
handler.postDelayed(() -> {
|
||||
if (scanning) {
|
||||
stopScan();
|
||||
}
|
||||
}, SCAN_DURATION);
|
||||
@@ -256,25 +258,25 @@ public class ScannerFragment extends DialogFragment {
|
||||
* Stop scan if user tap Cancel button
|
||||
*/
|
||||
private void stopScan() {
|
||||
if (mIsScanning) {
|
||||
mScanButton.setText(R.string.scanner_action_scan);
|
||||
if (scanning) {
|
||||
scanButton.setText(R.string.scanner_action_scan);
|
||||
|
||||
final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
|
||||
scanner.stopScan(scanCallback);
|
||||
|
||||
mIsScanning = false;
|
||||
scanning = false;
|
||||
}
|
||||
}
|
||||
|
||||
private ScanCallback scanCallback = new ScanCallback() {
|
||||
@Override
|
||||
public void onScanResult(final int callbackType, final ScanResult result) {
|
||||
public void onScanResult(final int callbackType, @NonNull final ScanResult result) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBatchScanResults(final List<ScanResult> results) {
|
||||
mAdapter.update(results);
|
||||
public void onBatchScanResults(@NonNull final List<ScanResult> results) {
|
||||
adapter.update(results);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -284,7 +286,7 @@ public class ScannerFragment extends DialogFragment {
|
||||
};
|
||||
|
||||
private void addBoundDevices() {
|
||||
final Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
|
||||
mAdapter.addBondedDevices(devices);
|
||||
final Set<BluetoothDevice> devices = bluetoothAdapter.getBondedDevices();
|
||||
adapter.addBondedDevices(devices);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ public class TemplateActivity extends BleProfileServiceReadyActivity<TemplateSer
|
||||
private final String TAG = "TemplateActivity";
|
||||
|
||||
// TODO change view references to match your need
|
||||
private TextView mValueView;
|
||||
private TextView mBatteryLevelView;
|
||||
private TextView valueView;
|
||||
private TextView batteryLevelView;
|
||||
|
||||
@Override
|
||||
protected void onCreateView(final Bundle savedInstanceState) {
|
||||
@@ -59,8 +59,8 @@ public class TemplateActivity extends BleProfileServiceReadyActivity<TemplateSer
|
||||
|
||||
private void setGUI() {
|
||||
// TODO assign your views to fields
|
||||
mValueView = findViewById(R.id.value);
|
||||
mBatteryLevelView = findViewById(R.id.battery);
|
||||
valueView = findViewById(R.id.value);
|
||||
batteryLevelView = findViewById(R.id.battery);
|
||||
|
||||
findViewById(R.id.action_set_name).setOnClickListener(v -> {
|
||||
if (isDeviceConnected()) {
|
||||
@@ -71,20 +71,20 @@ public class TemplateActivity extends BleProfileServiceReadyActivity<TemplateSer
|
||||
|
||||
@Override
|
||||
protected void onInitialize(final Bundle savedInstanceState) {
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, makeIntentFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setDefaultUI() {
|
||||
// TODO clear your UI
|
||||
mValueView.setText(R.string.not_available_value);
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
valueView.setText(R.string.not_available_value);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -142,29 +142,29 @@ public class TemplateActivity extends BleProfileServiceReadyActivity<TemplateSer
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(@NonNull final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// this may notify user or show some views
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
public void onDeviceDisconnected(@NonNull final BluetoothDevice device) {
|
||||
super.onDeviceDisconnected(device);
|
||||
mBatteryLevelView.setText(R.string.not_available);
|
||||
batteryLevelView.setText(R.string.not_available);
|
||||
}
|
||||
|
||||
// Handling updates from the device
|
||||
@SuppressWarnings("unused")
|
||||
private void setValueOnView(@NonNull final BluetoothDevice device, final int value) {
|
||||
// TODO assign the value to a view
|
||||
mValueView.setText(String.valueOf(value));
|
||||
valueView.setText(String.valueOf(value));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int value) {
|
||||
mBatteryLevelView.setText(getString(R.string.battery, value));
|
||||
batteryLevelView.setText(getString(R.string.battery, value));
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
|
||||
@@ -69,7 +69,7 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
|
||||
private static final UUID WRITABLE_CHARACTERISTIC_UUID = UUID.fromString("00002A00-0000-1000-8000-00805f9b34fb"); // Device Name
|
||||
|
||||
// TODO Add more services and characteristics references.
|
||||
private BluetoothGattCharacteristic mRequiredCharacteristic, mDeviceNameCharacteristic, mOptionalCharacteristic;
|
||||
private BluetoothGattCharacteristic requiredCharacteristic, deviceNameCharacteristic, optionalCharacteristic;
|
||||
|
||||
public TemplateManager(final Context context) {
|
||||
super(context);
|
||||
@@ -78,14 +78,14 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
|
||||
@NonNull
|
||||
@Override
|
||||
protected BatteryManagerGattCallback getGattCallback() {
|
||||
return mGattCallback;
|
||||
return gattCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* BluetoothGatt callbacks for connection/disconnection, service discovery,
|
||||
* receiving indication, etc.
|
||||
*/
|
||||
private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
|
||||
private final BatteryManagerGattCallback gattCallback = new BatteryManagerGattCallback() {
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
@@ -111,7 +111,7 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
|
||||
.enqueue();
|
||||
|
||||
// Set notification callback
|
||||
setNotificationCallback(mRequiredCharacteristic)
|
||||
setNotificationCallback(requiredCharacteristic)
|
||||
// This callback will be called each time the notification is received
|
||||
.with(new TemplateDataCallback() {
|
||||
@Override
|
||||
@@ -123,7 +123,7 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
|
||||
@Override
|
||||
public void onSampleValueReceived(@NonNull final BluetoothDevice device, final int value) {
|
||||
// Let's lass received data to the service
|
||||
mCallbacks.onSampleValueReceived(device, value);
|
||||
callbacks.onSampleValueReceived(device, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,7 +133,7 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
|
||||
});
|
||||
|
||||
// Enable notifications
|
||||
enableNotifications(mRequiredCharacteristic)
|
||||
enableNotifications(requiredCharacteristic)
|
||||
// Method called after the data were sent (data will contain 0x0100 in this case)
|
||||
.with((device, data) -> log(Log.DEBUG, "Data sent: " + data))
|
||||
// Method called when the request finished successfully. This will be called after .with(..) callback
|
||||
@@ -149,13 +149,13 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
|
||||
// It should return true if all has been discovered (that is that device is supported).
|
||||
final BluetoothGattService service = gatt.getService(SERVICE_UUID);
|
||||
if (service != null) {
|
||||
mRequiredCharacteristic = service.getCharacteristic(MEASUREMENT_CHARACTERISTIC_UUID);
|
||||
requiredCharacteristic = service.getCharacteristic(MEASUREMENT_CHARACTERISTIC_UUID);
|
||||
}
|
||||
final BluetoothGattService otherService = gatt.getService(OTHER_SERVICE_UUID);
|
||||
if (otherService != null) {
|
||||
mDeviceNameCharacteristic = otherService.getCharacteristic(WRITABLE_CHARACTERISTIC_UUID);
|
||||
deviceNameCharacteristic = otherService.getCharacteristic(WRITABLE_CHARACTERISTIC_UUID);
|
||||
}
|
||||
return mRequiredCharacteristic != null && mDeviceNameCharacteristic != null;
|
||||
return requiredCharacteristic != null && deviceNameCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,9 +166,9 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
|
||||
// TODO If there are some optional characteristics, initialize them there.
|
||||
final BluetoothGattService service = gatt.getService(SERVICE_UUID);
|
||||
if (service != null) {
|
||||
mOptionalCharacteristic = service.getCharacteristic(READABLE_CHARACTERISTIC_UUID);
|
||||
optionalCharacteristic = service.getCharacteristic(READABLE_CHARACTERISTIC_UUID);
|
||||
}
|
||||
return mOptionalCharacteristic != null;
|
||||
return optionalCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -177,9 +177,9 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
|
||||
super.onDeviceDisconnected();
|
||||
|
||||
// TODO Release references to your characteristics.
|
||||
mRequiredCharacteristic = null;
|
||||
mDeviceNameCharacteristic = null;
|
||||
mOptionalCharacteristic = null;
|
||||
requiredCharacteristic = null;
|
||||
deviceNameCharacteristic = null;
|
||||
optionalCharacteristic = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -192,7 +192,7 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
|
||||
|
||||
// Device is ready, let's read something here. Usually there is nothing else to be done
|
||||
// here, as all had been done during initialization.
|
||||
readCharacteristic(mOptionalCharacteristic)
|
||||
readCharacteristic(optionalCharacteristic)
|
||||
.with((device, data) -> {
|
||||
// Characteristic value has been read
|
||||
// Let's do some magic with it.
|
||||
@@ -217,7 +217,7 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
|
||||
void performAction(final String parameter) {
|
||||
log(Log.VERBOSE, "Changing device name to \"" + parameter + "\"");
|
||||
// Write some data to the characteristic.
|
||||
writeCharacteristic(mDeviceNameCharacteristic, Data.from(parameter))
|
||||
writeCharacteristic(deviceNameCharacteristic, Data.from(parameter))
|
||||
// If data are longer than MTU-3, they will be chunked into multiple packets.
|
||||
// Check out other split options, with .split(...).
|
||||
.split()
|
||||
|
||||
@@ -55,9 +55,9 @@ public class TemplateService extends BleProfileService implements TemplateManage
|
||||
private final static int OPEN_ACTIVITY_REQ = 0;
|
||||
private final static int DISCONNECT_REQ = 1;
|
||||
|
||||
private TemplateManager mManager;
|
||||
private TemplateManager manager;
|
||||
|
||||
private final LocalBinder mBinder = new TemplateBinder();
|
||||
private final LocalBinder binder = new TemplateBinder();
|
||||
|
||||
/**
|
||||
* This local binder is an interface for the bound activity to operate with the sensor.
|
||||
@@ -70,19 +70,19 @@ public class TemplateService extends BleProfileService implements TemplateManage
|
||||
*
|
||||
* @param parameter some parameter.
|
||||
*/
|
||||
public void performAction(final String parameter) {
|
||||
mManager.performAction(parameter);
|
||||
void performAction(final String parameter) {
|
||||
manager.performAction(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocalBinder getBinder() {
|
||||
return mBinder;
|
||||
return binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggableBleManager<TemplateManagerCallbacks> initializeManager() {
|
||||
return mManager = new TemplateManager(this);
|
||||
return manager = new TemplateManager(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,14 +91,14 @@ public class TemplateService extends BleProfileService implements TemplateManage
|
||||
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_DISCONNECT);
|
||||
registerReceiver(mDisconnectActionBroadcastReceiver, filter);
|
||||
registerReceiver(disconnectActionBroadcastReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
// when user has disconnected from the sensor, we have to cancel the notification that we've created some milliseconds before using unbindService
|
||||
stopForegroundService();
|
||||
unregisterReceiver(mDisconnectActionBroadcastReceiver);
|
||||
unregisterReceiver(disconnectActionBroadcastReceiver);
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
@@ -120,7 +120,7 @@ public class TemplateService extends BleProfileService implements TemplateManage
|
||||
broadcast.putExtra(EXTRA_DATA, value);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
if (!mBound) {
|
||||
if (!bound) {
|
||||
// Here we may update the notification to display the current value.
|
||||
// TODO modify the notification here
|
||||
}
|
||||
@@ -166,6 +166,7 @@ public class TemplateService extends BleProfileService implements TemplateManage
|
||||
* f.e. <code><string name="name">%s is connected</string></code>
|
||||
* @param defaults signals that will be used to notify the user
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private Notification createNotification(final int messageResId, final int defaults) {
|
||||
final Intent parentIntent = new Intent(this, FeaturesActivity.class);
|
||||
parentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
@@ -197,7 +198,7 @@ public class TemplateService extends BleProfileService implements TemplateManage
|
||||
/**
|
||||
* This broadcast receiver listens for {@link #ACTION_DISCONNECT} that may be fired by pressing Disconnect action button on the notification.
|
||||
*/
|
||||
private final BroadcastReceiver mDisconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver disconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
Logger.i(getLogSession(), "[Notification] Disconnect action pressed");
|
||||
|
||||
@@ -115,28 +115,28 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
private final static int SELECT_FILE_REQ = 2678; // random
|
||||
private final static int PERMISSION_REQ = 24; // random, 8-bit
|
||||
|
||||
UARTConfigurationSynchronizer mWearableSynchronizer;
|
||||
UARTConfigurationSynchronizer wearableSynchronizer;
|
||||
|
||||
/** The current configuration. */
|
||||
private UartConfiguration mConfiguration;
|
||||
private DatabaseHelper mDatabaseHelper;
|
||||
private SharedPreferences mPreferences;
|
||||
private UARTConfigurationsAdapter mConfigurationsAdapter;
|
||||
private ClosableSpinner mConfigurationSpinner;
|
||||
private SlidingPaneLayout mSlider;
|
||||
private View mContainer;
|
||||
private UARTService.UARTBinder mServiceBinder;
|
||||
private ConfigurationListener mConfigurationListener;
|
||||
private boolean mEditMode;
|
||||
private UartConfiguration configuration;
|
||||
private DatabaseHelper databaseHelper;
|
||||
private SharedPreferences preferences;
|
||||
private UARTConfigurationsAdapter configurationsAdapter;
|
||||
private ClosableSpinner configurationSpinner;
|
||||
private SlidingPaneLayout slider;
|
||||
private View container;
|
||||
private UARTService.UARTBinder serviceBinder;
|
||||
private ConfigurationListener configurationListener;
|
||||
private boolean editMode;
|
||||
|
||||
public interface ConfigurationListener {
|
||||
void onConfigurationModified();
|
||||
void onConfigurationChanged(final UartConfiguration configuration);
|
||||
void onConfigurationChanged(@NonNull final UartConfiguration configuration);
|
||||
void setEditMode(final boolean editMode);
|
||||
}
|
||||
|
||||
public void setConfigurationListener(final ConfigurationListener listener) {
|
||||
mConfigurationListener = listener;
|
||||
configurationListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,23 +161,23 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
|
||||
@Override
|
||||
protected void onServiceBound(final UARTService.UARTBinder binder) {
|
||||
mServiceBinder = binder;
|
||||
serviceBinder = binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onServiceUnbound() {
|
||||
mServiceBinder = null;
|
||||
serviceBinder = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialize(final Bundle savedInstanceState) {
|
||||
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
mDatabaseHelper = new DatabaseHelper(this);
|
||||
ensureFirstConfiguration(mDatabaseHelper);
|
||||
mConfigurationsAdapter = new UARTConfigurationsAdapter(this, this, mDatabaseHelper.getConfigurationsNames());
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
databaseHelper = new DatabaseHelper(this);
|
||||
ensureFirstConfiguration(databaseHelper);
|
||||
configurationsAdapter = new UARTConfigurationsAdapter(this, this, databaseHelper.getConfigurationsNames());
|
||||
|
||||
// Initialize Wearable synchronizer
|
||||
mWearableSynchronizer = UARTConfigurationSynchronizer.from(this, this);
|
||||
wearableSynchronizer = UARTConfigurationSynchronizer.from(this, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,12 +186,12 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
@Override
|
||||
public void onConnected(final Bundle bundle) {
|
||||
// Ensure the Wearable API was connected
|
||||
if (!mWearableSynchronizer.hasConnectedApi())
|
||||
if (!wearableSynchronizer.hasConnectedApi())
|
||||
return;
|
||||
|
||||
if (!mPreferences.getBoolean(PREFS_WEAR_SYNCED, false)) {
|
||||
if (!preferences.getBoolean(PREFS_WEAR_SYNCED, false)) {
|
||||
new Thread(() -> {
|
||||
final Cursor cursor = mDatabaseHelper.getConfigurations();
|
||||
final Cursor cursor = databaseHelper.getConfigurations();
|
||||
try {
|
||||
while (cursor.moveToNext()) {
|
||||
final long id = cursor.getLong(0 /* _ID */);
|
||||
@@ -200,12 +200,12 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
final Format format = new Format(new HyphenStyle());
|
||||
final Serializer serializer = new Persister(format);
|
||||
final UartConfiguration configuration = serializer.read(UartConfiguration.class, xml);
|
||||
mWearableSynchronizer.onConfigurationAddedOrEdited(id, configuration).await();
|
||||
wearableSynchronizer.onConfigurationAddedOrEdited(id, configuration).await();
|
||||
} catch (final Exception e) {
|
||||
Log.w(TAG, "Deserializing configuration with id " + id + " failed", e);
|
||||
}
|
||||
}
|
||||
mPreferences.edit().putBoolean(PREFS_WEAR_SYNCED, true).apply();
|
||||
preferences.edit().putBoolean(PREFS_WEAR_SYNCED, true).apply();
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
@@ -225,16 +225,16 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mWearableSynchronizer.close();
|
||||
wearableSynchronizer.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreateView(final Bundle savedInstanceState) {
|
||||
setContentView(R.layout.activity_feature_uart);
|
||||
|
||||
mContainer = findViewById(R.id.container);
|
||||
container = findViewById(R.id.container);
|
||||
// Setup the sliding pane if it exists
|
||||
final SlidingPaneLayout slidingPane = mSlider = findViewById(R.id.sliding_pane);
|
||||
final SlidingPaneLayout slidingPane = slider = findViewById(R.id.sliding_pane);
|
||||
if (slidingPane != null) {
|
||||
slidingPane.setSliderFadeColor(Color.TRANSPARENT);
|
||||
slidingPane.setShadowResourceLeft(R.drawable.shadow_r);
|
||||
@@ -253,34 +253,34 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
protected void onViewCreated(final Bundle savedInstanceState) {
|
||||
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
||||
|
||||
final ClosableSpinner configurationSpinner = mConfigurationSpinner = findViewById(R.id.toolbar_spinner);
|
||||
final ClosableSpinner configurationSpinner = this.configurationSpinner = findViewById(R.id.toolbar_spinner);
|
||||
configurationSpinner.setOnItemSelectedListener(this);
|
||||
configurationSpinner.setAdapter(mConfigurationsAdapter);
|
||||
configurationSpinner.setSelection(mConfigurationsAdapter.getItemPosition(mPreferences.getLong(PREFS_CONFIGURATION, 0)));
|
||||
configurationSpinner.setAdapter(configurationsAdapter);
|
||||
configurationSpinner.setSelection(configurationsAdapter.getItemPosition(preferences.getLong(PREFS_CONFIGURATION, 0)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(final @NonNull Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
|
||||
mEditMode = savedInstanceState.getBoolean(SIS_EDIT_MODE);
|
||||
setEditMode(mEditMode, false);
|
||||
editMode = savedInstanceState.getBoolean(SIS_EDIT_MODE);
|
||||
setEditMode(editMode, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(final Bundle outState) {
|
||||
public void onSaveInstanceState(@NonNull final Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putBoolean(SIS_EDIT_MODE, mEditMode);
|
||||
outState.putBoolean(SIS_EDIT_MODE, editMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
public void onServicesDiscovered(@NonNull final BluetoothDevice device, final boolean optionalServicesFound) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceSelected(final BluetoothDevice device, final String name) {
|
||||
public void onDeviceSelected(@NonNull final BluetoothDevice device, final String name) {
|
||||
// The super method starts the service
|
||||
super.onDeviceSelected(device, name);
|
||||
|
||||
@@ -306,8 +306,8 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
|
||||
@Override
|
||||
public void send(final String text) {
|
||||
if (mServiceBinder != null)
|
||||
mServiceBinder.send(text);
|
||||
if (serviceBinder != null)
|
||||
serviceBinder.send(text);
|
||||
}
|
||||
|
||||
public void setEditMode(final boolean editMode) {
|
||||
@@ -317,11 +317,11 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (mSlider != null && mSlider.isOpen()) {
|
||||
mSlider.closePane();
|
||||
if (slider != null && slider.isOpen()) {
|
||||
slider.closePane();
|
||||
return;
|
||||
}
|
||||
if (mEditMode) {
|
||||
if (editMode) {
|
||||
setEditMode(false);
|
||||
return;
|
||||
}
|
||||
@@ -331,31 +331,31 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.uart_menu_configurations, menu);
|
||||
getMenuInflater().inflate(mEditMode ? R.menu.uart_menu_config : R.menu.uart_menu, menu);
|
||||
getMenuInflater().inflate(editMode ? R.menu.uart_menu_config : R.menu.uart_menu, menu);
|
||||
|
||||
final int configurationsCount = mDatabaseHelper.getConfigurationsCount();
|
||||
final int configurationsCount = databaseHelper.getConfigurationsCount();
|
||||
menu.findItem(R.id.action_remove).setVisible(configurationsCount > 1);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onOptionsItemSelected(int itemId) {
|
||||
final String name = mConfiguration.getName();
|
||||
final String name = configuration.getName();
|
||||
switch (itemId) {
|
||||
case R.id.action_configure:
|
||||
setEditMode(!mEditMode);
|
||||
setEditMode(!editMode);
|
||||
return true;
|
||||
case R.id.action_show_log:
|
||||
mSlider.openPane();
|
||||
slider.openPane();
|
||||
return true;
|
||||
case R.id.action_share: {
|
||||
final String xml = mDatabaseHelper.getConfiguration(mConfigurationSpinner.getSelectedItemId());
|
||||
final String xml = databaseHelper.getConfiguration(configurationSpinner.getSelectedItemId());
|
||||
|
||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setType("text/xml");
|
||||
intent.putExtra(Intent.EXTRA_TEXT, xml);
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, mConfiguration.getName());
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, configuration.getName());
|
||||
try {
|
||||
startActivity(intent);
|
||||
} catch (final ActivityNotFoundException e) {
|
||||
@@ -384,17 +384,17 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
return true;
|
||||
}
|
||||
case R.id.action_remove: {
|
||||
mDatabaseHelper.removeDeletedServerConfigurations(); // just to be sure nothing has left
|
||||
final UartConfiguration removedConfiguration = mConfiguration;
|
||||
final long id = mDatabaseHelper.deleteConfiguration(name);
|
||||
databaseHelper.removeDeletedServerConfigurations(); // just to be sure nothing has left
|
||||
final UartConfiguration removedConfiguration = configuration;
|
||||
final long id = databaseHelper.deleteConfiguration(name);
|
||||
if (id >= 0)
|
||||
mWearableSynchronizer.onConfigurationDeleted(id);
|
||||
wearableSynchronizer.onConfigurationDeleted(id);
|
||||
refreshConfigurations();
|
||||
|
||||
final Snackbar snackbar = Snackbar.make(mContainer, R.string.uart_configuration_deleted, Snackbar.LENGTH_INDEFINITE).setAction(R.string.uart_action_undo, v -> {
|
||||
final long id1 = mDatabaseHelper.restoreDeletedServerConfiguration(name);
|
||||
final Snackbar snackbar = Snackbar.make(container, R.string.uart_configuration_deleted, Snackbar.LENGTH_INDEFINITE).setAction(R.string.uart_action_undo, v -> {
|
||||
final long id1 = databaseHelper.restoreDeletedServerConfiguration(name);
|
||||
if (id1 >= 0)
|
||||
mWearableSynchronizer.onConfigurationAddedOrEdited(id1, removedConfiguration);
|
||||
wearableSynchronizer.onConfigurationAddedOrEdited(id1, removedConfiguration);
|
||||
refreshConfigurations();
|
||||
});
|
||||
snackbar.setDuration(5000); // This is not an error
|
||||
@@ -425,11 +425,11 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
public void onItemSelected(final AdapterView<?> parent, final View view, final int position, final long id) {
|
||||
if (position > 0) { // FIXME this is called twice after rotation.
|
||||
try {
|
||||
final String xml = mDatabaseHelper.getConfiguration(id);
|
||||
final String xml = databaseHelper.getConfiguration(id);
|
||||
final Format format = new Format(new HyphenStyle());
|
||||
final Serializer serializer = new Persister(format);
|
||||
mConfiguration = serializer.read(UartConfiguration.class, xml);
|
||||
mConfigurationListener.onConfigurationChanged(mConfiguration);
|
||||
configuration = serializer.read(UartConfiguration.class, xml);
|
||||
configurationListener.onConfigurationChanged(configuration);
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "Selecting configuration failed", e);
|
||||
|
||||
@@ -441,11 +441,11 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
else
|
||||
message = "Unknown error";
|
||||
final String msg = message;
|
||||
Snackbar.make(mContainer, R.string.uart_configuration_loading_failed, Snackbar.LENGTH_INDEFINITE).setAction(R.string.uart_action_details, v -> new AlertDialog.Builder(UARTActivity.this).setMessage(msg).setTitle(R.string.uart_action_details).setPositiveButton(R.string.ok, null).show()).show();
|
||||
Snackbar.make(container, R.string.uart_configuration_loading_failed, Snackbar.LENGTH_INDEFINITE).setAction(R.string.uart_action_details, v -> new AlertDialog.Builder(UARTActivity.this).setMessage(msg).setTitle(R.string.uart_action_details).setPositiveButton(R.string.ok, null).show()).show();
|
||||
return;
|
||||
}
|
||||
|
||||
mPreferences.edit().putLong(PREFS_CONFIGURATION, id).apply();
|
||||
preferences.edit().putLong(PREFS_CONFIGURATION, id).apply();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,7 +457,7 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
@Override
|
||||
public void onNewConfigurationClick() {
|
||||
// No item has been selected. We must close the spinner manually.
|
||||
mConfigurationSpinner.close();
|
||||
configurationSpinner.close();
|
||||
|
||||
// Open the dialog
|
||||
final DialogFragment fragment = UARTNewConfigurationDialogFragment.getInstance(null, false);
|
||||
@@ -469,7 +469,7 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
@Override
|
||||
public void onImportClick() {
|
||||
// No item has been selected. We must close the spinner manually.
|
||||
mConfigurationSpinner.close();
|
||||
configurationSpinner.close();
|
||||
|
||||
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.setType("text/xml");
|
||||
@@ -542,25 +542,25 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
}
|
||||
|
||||
public void onCommandChanged(final int index, final String message, final boolean active, final int eol, final int iconIndex) {
|
||||
final Command command = mConfiguration.getCommands()[index];
|
||||
final Command command = configuration.getCommands()[index];
|
||||
|
||||
command.setCommand(message);
|
||||
command.setActive(active);
|
||||
command.setEol(eol);
|
||||
command.setIconIndex(iconIndex);
|
||||
mConfigurationListener.onConfigurationModified();
|
||||
configurationListener.onConfigurationModified();
|
||||
saveConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewConfiguration(final String name, final boolean duplicate) {
|
||||
final boolean exists = mDatabaseHelper.configurationExists(name);
|
||||
final boolean exists = databaseHelper.configurationExists(name);
|
||||
if (exists) {
|
||||
Toast.makeText(this, R.string.uart_configuration_name_already_taken, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
UartConfiguration configuration = mConfiguration;
|
||||
UartConfiguration configuration = this.configuration;
|
||||
if (!duplicate)
|
||||
configuration = new UartConfiguration();
|
||||
configuration.setName(name);
|
||||
@@ -573,10 +573,10 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
serializer.write(configuration, writer);
|
||||
final String xml = writer.toString();
|
||||
|
||||
final long id = mDatabaseHelper.addConfiguration(name, xml);
|
||||
mWearableSynchronizer.onConfigurationAddedOrEdited(id, configuration);
|
||||
final long id = databaseHelper.addConfiguration(name, xml);
|
||||
wearableSynchronizer.onConfigurationAddedOrEdited(id, configuration);
|
||||
refreshConfigurations();
|
||||
selectConfiguration(mConfigurationsAdapter.getItemPosition(id));
|
||||
selectConfiguration(configurationsAdapter.getItemPosition(id));
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "Error while creating a new configuration", e);
|
||||
}
|
||||
@@ -584,25 +584,25 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
|
||||
@Override
|
||||
public void onRenameConfiguration(final String newName) {
|
||||
final boolean exists = mDatabaseHelper.configurationExists(newName);
|
||||
final boolean exists = databaseHelper.configurationExists(newName);
|
||||
if (exists) {
|
||||
Toast.makeText(this, R.string.uart_configuration_name_already_taken, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
final String oldName = mConfiguration.getName();
|
||||
mConfiguration.setName(newName);
|
||||
final String oldName = configuration.getName();
|
||||
configuration.setName(newName);
|
||||
|
||||
try {
|
||||
final Format format = new Format(new HyphenStyle());
|
||||
final Strategy strategy = new VisitorStrategy(new CommentVisitor());
|
||||
final Serializer serializer = new Persister(strategy, format);
|
||||
final StringWriter writer = new StringWriter();
|
||||
serializer.write(mConfiguration, writer);
|
||||
serializer.write(configuration, writer);
|
||||
final String xml = writer.toString();
|
||||
|
||||
mDatabaseHelper.renameConfiguration(oldName, newName, xml);
|
||||
mWearableSynchronizer.onConfigurationAddedOrEdited(mPreferences.getLong(PREFS_CONFIGURATION, 0), mConfiguration);
|
||||
databaseHelper.renameConfiguration(oldName, newName, xml);
|
||||
wearableSynchronizer.onConfigurationAddedOrEdited(preferences.getLong(PREFS_CONFIGURATION, 0), configuration);
|
||||
refreshConfigurations();
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "Error while renaming configuration", e);
|
||||
@@ -610,13 +610,13 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
}
|
||||
|
||||
private void refreshConfigurations() {
|
||||
mConfigurationsAdapter.swapCursor(mDatabaseHelper.getConfigurationsNames());
|
||||
mConfigurationsAdapter.notifyDataSetChanged();
|
||||
configurationsAdapter.swapCursor(databaseHelper.getConfigurationsNames());
|
||||
configurationsAdapter.notifyDataSetChanged();
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
private void selectConfiguration(final int position) {
|
||||
mConfigurationSpinner.setSelection(position);
|
||||
configurationSpinner.setSelection(position);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -629,8 +629,8 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
private void setEditMode(final boolean editMode, final boolean change) {
|
||||
mEditMode = editMode;
|
||||
mConfigurationListener.setEditMode(editMode);
|
||||
this.editMode = editMode;
|
||||
configurationListener.setEditMode(editMode);
|
||||
if (!change) {
|
||||
final ColorDrawable color = new ColorDrawable();
|
||||
int darkColor = 0;
|
||||
@@ -664,8 +664,8 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
anim.start();
|
||||
}
|
||||
|
||||
if (mSlider != null && editMode) {
|
||||
mSlider.closePane();
|
||||
if (slider != null && editMode) {
|
||||
slider.closePane();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -674,7 +674,7 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
* Saves the given configuration in the database.
|
||||
*/
|
||||
private void saveConfiguration() {
|
||||
final UartConfiguration configuration = mConfiguration;
|
||||
final UartConfiguration configuration = this.configuration;
|
||||
try {
|
||||
final Format format = new Format(new HyphenStyle());
|
||||
final Strategy strategy = new VisitorStrategy(new CommentVisitor());
|
||||
@@ -683,8 +683,8 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
serializer.write(configuration, writer);
|
||||
final String xml = writer.toString();
|
||||
|
||||
mDatabaseHelper.updateConfiguration(configuration.getName(), xml);
|
||||
mWearableSynchronizer.onConfigurationAddedOrEdited(mPreferences.getLong(PREFS_CONFIGURATION, 0), configuration);
|
||||
databaseHelper.updateConfiguration(configuration.getName(), xml);
|
||||
wearableSynchronizer.onConfigurationAddedOrEdited(preferences.getLong(PREFS_CONFIGURATION, 0), configuration);
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "Error while creating a new configuration", e);
|
||||
}
|
||||
@@ -708,11 +708,11 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
final UartConfiguration configuration = serializer.read(UartConfiguration.class, xml);
|
||||
|
||||
final String name = configuration.getName();
|
||||
if (!mDatabaseHelper.configurationExists(name)) {
|
||||
final long id = mDatabaseHelper.addConfiguration(name, xml);
|
||||
mWearableSynchronizer.onConfigurationAddedOrEdited(id, configuration);
|
||||
if (!databaseHelper.configurationExists(name)) {
|
||||
final long id = databaseHelper.addConfiguration(name, xml);
|
||||
wearableSynchronizer.onConfigurationAddedOrEdited(id, configuration);
|
||||
refreshConfigurations();
|
||||
new Handler().post(() -> selectConfiguration(mConfigurationsAdapter.getItemPosition(id)));
|
||||
new Handler().post(() -> selectConfiguration(configurationsAdapter.getItemPosition(id)));
|
||||
} else {
|
||||
Toast.makeText(this, R.string.uart_configuration_name_already_taken, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
@@ -727,7 +727,7 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
else
|
||||
message = "Unknown error";
|
||||
final String msg = message;
|
||||
Snackbar.make(mContainer, R.string.uart_configuration_loading_failed, Snackbar.LENGTH_INDEFINITE).setAction(R.string.uart_action_details, v -> new AlertDialog.Builder(UARTActivity.this).setMessage(msg).setTitle(R.string.uart_action_details).setPositiveButton(R.string.ok, null).show()).show();
|
||||
Snackbar.make(container, R.string.uart_configuration_loading_failed, Snackbar.LENGTH_INDEFINITE).setAction(R.string.uart_action_details, v -> new AlertDialog.Builder(UARTActivity.this).setMessage(msg).setTitle(R.string.uart_action_details).setPositiveButton(R.string.ok, null).show()).show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -740,13 +740,13 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
if (!serverFolder.exists())
|
||||
serverFolder.mkdir();
|
||||
|
||||
final String fileName = mConfiguration.getName() + ".xml";
|
||||
final String fileName = configuration.getName() + ".xml";
|
||||
final File file = new File(serverFolder, fileName);
|
||||
try {
|
||||
file.createNewFile();
|
||||
final FileOutputStream fos = new FileOutputStream(file);
|
||||
final OutputStreamWriter writer = new OutputStreamWriter(fos);
|
||||
writer.append(mDatabaseHelper.getConfiguration(mConfigurationSpinner.getSelectedItemId()));
|
||||
writer.append(databaseHelper.getConfiguration(configurationSpinner.getSelectedItemId()));
|
||||
writer.close();
|
||||
|
||||
// Notify user about the file
|
||||
@@ -768,21 +768,21 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
* Converts the old configuration, stored in preferences, into the first XML configuration and saves it to the database.
|
||||
* If there is already any configuration in the database this method does nothing.
|
||||
*/
|
||||
private void ensureFirstConfiguration(final DatabaseHelper mDatabaseHelper) {
|
||||
private void ensureFirstConfiguration(final DatabaseHelper databaseHelper) {
|
||||
// This method ensures that the "old", single configuration has been saved to the database.
|
||||
if (mDatabaseHelper.getConfigurationsCount() == 0) {
|
||||
if (databaseHelper.getConfigurationsCount() == 0) {
|
||||
final UartConfiguration configuration = new UartConfiguration();
|
||||
configuration.setName("First configuration");
|
||||
final Command[] commands = configuration.getCommands();
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
final String cmd = mPreferences.getString(PREFS_BUTTON_COMMAND + i, null);
|
||||
final String cmd = preferences.getString(PREFS_BUTTON_COMMAND + i, null);
|
||||
if (cmd != null) {
|
||||
final Command command = new Command();
|
||||
command.setCommand(cmd);
|
||||
command.setActive(mPreferences.getBoolean(PREFS_BUTTON_ENABLED + i, false));
|
||||
command.setActive(preferences.getBoolean(PREFS_BUTTON_ENABLED + i, false));
|
||||
command.setEol(0); // default one
|
||||
command.setIconIndex(mPreferences.getInt(PREFS_BUTTON_ICON + i, 0));
|
||||
command.setIconIndex(preferences.getInt(PREFS_BUTTON_ICON + i, 0));
|
||||
commands[i] = command;
|
||||
}
|
||||
}
|
||||
@@ -795,7 +795,7 @@ public class UARTActivity extends BleProfileServiceReadyActivity<UARTService.UAR
|
||||
serializer.write(configuration, writer);
|
||||
final String xml = writer.toString();
|
||||
|
||||
mDatabaseHelper.addConfiguration(configuration.getName(), xml);
|
||||
databaseHelper.addConfiguration(configuration.getName(), xml);
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "Error while creating default configuration", e);
|
||||
}
|
||||
|
||||
@@ -28,36 +28,38 @@ import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
import no.nordicsemi.android.nrftoolbox.uart.domain.Command;
|
||||
import no.nordicsemi.android.nrftoolbox.uart.domain.UartConfiguration;
|
||||
|
||||
public class UARTButtonAdapter extends BaseAdapter {
|
||||
private UartConfiguration mConfiguration;
|
||||
private boolean mEditMode;
|
||||
private UartConfiguration configuration;
|
||||
private boolean editMode;
|
||||
|
||||
public UARTButtonAdapter(final UartConfiguration configuration) {
|
||||
mConfiguration = configuration;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
public void setEditMode(final boolean editMode) {
|
||||
mEditMode = editMode;
|
||||
this.editMode = editMode;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setConfiguration(final UartConfiguration configuration) {
|
||||
mConfiguration = configuration;
|
||||
this.configuration = configuration;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mConfiguration != null ? mConfiguration.getCommands().length : 0;
|
||||
return configuration != null ? configuration.getCommands().length : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(final int position) {
|
||||
return mConfiguration.getCommands()[position];
|
||||
return configuration.getCommands()[position];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,20 +78,20 @@ public class UARTButtonAdapter extends BaseAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
public boolean isEnabled(final int position) {
|
||||
final Command command = (Command) getItem(position);
|
||||
return mEditMode || (command != null && command.isActive());
|
||||
return editMode || (command != null && command.isActive());
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int position, final View convertView, final ViewGroup parent) {
|
||||
public View getView(final int position, @Nullable final View convertView, @NonNull final ViewGroup parent) {
|
||||
View view = convertView;
|
||||
if (view == null) {
|
||||
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
view = inflater.inflate(R.layout.feature_uart_button, parent, false);
|
||||
}
|
||||
view.setEnabled(isEnabled(position));
|
||||
view.setActivated(mEditMode);
|
||||
view.setActivated(editMode);
|
||||
|
||||
// Update image
|
||||
final Command command = (Command) getItem(position);
|
||||
|
||||
@@ -30,21 +30,23 @@ import android.view.ViewGroup;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
|
||||
public class UARTConfigurationsAdapter extends CursorAdapter {
|
||||
final Context mContext;
|
||||
final ActionListener mListener;
|
||||
final Context context;
|
||||
final ActionListener listener;
|
||||
|
||||
public interface ActionListener {
|
||||
void onNewConfigurationClick();
|
||||
void onImportClick();
|
||||
}
|
||||
|
||||
public UARTConfigurationsAdapter(final Context context, final ActionListener listener, final Cursor c) {
|
||||
public UARTConfigurationsAdapter(@NonNull final Context context, final ActionListener listener, final Cursor c) {
|
||||
super(context, c, 0);
|
||||
mContext = context;
|
||||
mListener = listener;
|
||||
this.context = context;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -83,7 +85,7 @@ public class UARTConfigurationsAdapter extends CursorAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int position, final View convertView, final ViewGroup parent) {
|
||||
public View getView(final int position, @Nullable final View convertView, @NonNull final ViewGroup parent) {
|
||||
if (position == 0) {
|
||||
// This empty view should never be visible. Only positions 1+ are valid. Position 0 is reserved for action buttons.
|
||||
// It is only created temporally when activity is created.
|
||||
@@ -93,9 +95,9 @@ public class UARTConfigurationsAdapter extends CursorAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getDropDownView(final int position, final View convertView, final ViewGroup parent) {
|
||||
public View getDropDownView(final int position, @Nullable final View convertView, @NonNull final ViewGroup parent) {
|
||||
if (position == 0) {
|
||||
return newToolbarView(mContext, parent);
|
||||
return newToolbarView(context, parent);
|
||||
}
|
||||
if (convertView instanceof ViewGroup)
|
||||
return super.getDropDownView(position - 1, null, parent);
|
||||
@@ -104,18 +106,18 @@ public class UARTConfigurationsAdapter extends CursorAdapter {
|
||||
|
||||
@Override
|
||||
public View newView(final Context context, final Cursor cursor, final ViewGroup parent) {
|
||||
return LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_spinner_item, parent, false);
|
||||
return LayoutInflater.from(context).inflate(android.R.layout.simple_spinner_item, parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newDropDownView(final Context context, final Cursor cursor, final ViewGroup parent) {
|
||||
return LayoutInflater.from(mContext).inflate(R.layout.feature_uart_dropdown_item, parent, false);
|
||||
return LayoutInflater.from(context).inflate(R.layout.feature_uart_dropdown_item, parent, false);
|
||||
}
|
||||
|
||||
public View newToolbarView(final Context context, final ViewGroup parent) {
|
||||
final View view = LayoutInflater.from(context).inflate(R.layout.feature_uart_dropdown_title, parent, false);
|
||||
view.findViewById(R.id.action_add).setOnClickListener(v -> mListener.onNewConfigurationClick());
|
||||
view.findViewById(R.id.action_import).setOnClickListener(v -> mListener.onImportClick());
|
||||
view.findViewById(R.id.action_add).setOnClickListener(v -> listener.onNewConfigurationClick());
|
||||
view.findViewById(R.id.action_import).setOnClickListener(v -> listener.onImportClick());
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ package no.nordicsemi.android.nrftoolbox.uart;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -40,12 +42,12 @@ public class UARTControlFragment extends Fragment implements GridView.OnItemClic
|
||||
private final static String TAG = "UARTControlFragment";
|
||||
private final static String SIS_EDIT_MODE = "sis_edit_mode";
|
||||
|
||||
private UartConfiguration mConfiguration;
|
||||
private UARTButtonAdapter mAdapter;
|
||||
private boolean mEditMode;
|
||||
private UartConfiguration configuration;
|
||||
private UARTButtonAdapter adapter;
|
||||
private boolean editMode;
|
||||
|
||||
@Override
|
||||
public void onAttach(final Context context) {
|
||||
public void onAttach(@NonNull final Context context) {
|
||||
super.onAttach(context);
|
||||
|
||||
try {
|
||||
@@ -60,19 +62,19 @@ public class UARTControlFragment extends Fragment implements GridView.OnItemClic
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mEditMode = savedInstanceState.getBoolean(SIS_EDIT_MODE);
|
||||
editMode = savedInstanceState.getBoolean(SIS_EDIT_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
((UARTActivity)getActivity()).setConfigurationListener(null);
|
||||
((UARTActivity)requireActivity()).setConfigurationListener(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(final Bundle outState) {
|
||||
outState.putBoolean(SIS_EDIT_MODE, mEditMode);
|
||||
outState.putBoolean(SIS_EDIT_MODE, editMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,23 +82,23 @@ public class UARTControlFragment extends Fragment implements GridView.OnItemClic
|
||||
final View view = inflater.inflate(R.layout.fragment_feature_uart_control, container, false);
|
||||
|
||||
final GridView grid = view.findViewById(R.id.grid);
|
||||
grid.setAdapter(mAdapter = new UARTButtonAdapter(mConfiguration));
|
||||
grid.setAdapter(adapter = new UARTButtonAdapter(configuration));
|
||||
grid.setOnItemClickListener(this);
|
||||
mAdapter.setEditMode(mEditMode);
|
||||
adapter.setEditMode(editMode);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
|
||||
if (mEditMode) {
|
||||
Command command = mConfiguration.getCommands()[position];
|
||||
if (editMode) {
|
||||
Command command = configuration.getCommands()[position];
|
||||
if (command == null)
|
||||
mConfiguration.getCommands()[position] = command = new Command();
|
||||
configuration.getCommands()[position] = command = new Command();
|
||||
final UARTEditDialog dialog = UARTEditDialog.getInstance(position, command);
|
||||
dialog.show(getChildFragmentManager(), null);
|
||||
} else {
|
||||
final Command command = (Command)mAdapter.getItem(position);
|
||||
final Command command = (Command)adapter.getItem(position);
|
||||
final Command.Eol eol = command.getEol();
|
||||
String text = command.getCommand();
|
||||
if (text == null)
|
||||
@@ -109,25 +111,25 @@ public class UARTControlFragment extends Fragment implements GridView.OnItemClic
|
||||
text = text.replaceAll("\n", "\r");
|
||||
break;
|
||||
}
|
||||
final UARTInterface uart = (UARTInterface) getActivity();
|
||||
final UARTInterface uart = (UARTInterface) requireActivity();
|
||||
uart.send(text);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationModified() {
|
||||
mAdapter.notifyDataSetChanged();
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(final UartConfiguration configuration) {
|
||||
mConfiguration = configuration;
|
||||
mAdapter.setConfiguration(configuration);
|
||||
public void onConfigurationChanged(@NonNull final UartConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
adapter.setConfiguration(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEditMode(final boolean editMode) {
|
||||
mEditMode = editMode;
|
||||
mAdapter.setEditMode(mEditMode);
|
||||
this.editMode = editMode;
|
||||
adapter.setEditMode(editMode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ package no.nordicsemi.android.nrftoolbox.uart;
|
||||
import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -47,12 +48,12 @@ public class UARTEditDialog extends DialogFragment implements View.OnClickListen
|
||||
private final static String ARG_COMMAND = "command";
|
||||
private final static String ARG_EOL = "eol";
|
||||
private final static String ARG_ICON_INDEX = "iconIndex";
|
||||
private int mActiveIcon;
|
||||
private int activeIcon;
|
||||
|
||||
private EditText mField;
|
||||
private CheckBox mActiveCheckBox;
|
||||
private RadioGroup mEOLGroup;
|
||||
private IconAdapter mIconAdapter;
|
||||
private EditText field;
|
||||
private CheckBox activeCheckBox;
|
||||
private RadioGroup eolGroup;
|
||||
private IconAdapter iconAdapter;
|
||||
|
||||
public static UARTEditDialog getInstance(final int index, final Command command) {
|
||||
final UARTEditDialog fragment = new UARTEditDialog();
|
||||
@@ -73,27 +74,27 @@ public class UARTEditDialog extends DialogFragment implements View.OnClickListen
|
||||
final LayoutInflater inflater = LayoutInflater.from(getActivity());
|
||||
|
||||
// Read button configuration
|
||||
final Bundle args = getArguments();
|
||||
final Bundle args = requireArguments();
|
||||
final int index = args.getInt(ARG_INDEX);
|
||||
final String command = args.getString(ARG_COMMAND);
|
||||
final int eol = args.getInt(ARG_EOL);
|
||||
final int iconIndex = args.getInt(ARG_ICON_INDEX);
|
||||
final boolean active = true; // change to active by default
|
||||
mActiveIcon = iconIndex;
|
||||
activeIcon = iconIndex;
|
||||
|
||||
// Create view
|
||||
final View view = inflater.inflate(R.layout.feature_uart_dialog_edit, null);
|
||||
final EditText field = mField = view.findViewById(R.id.field);
|
||||
final EditText field = this.field = view.findViewById(R.id.field);
|
||||
final GridView grid = view.findViewById(R.id.grid);
|
||||
final CheckBox checkBox = mActiveCheckBox = view.findViewById(R.id.active);
|
||||
final CheckBox checkBox = activeCheckBox = view.findViewById(R.id.active);
|
||||
checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
field.setEnabled(isChecked);
|
||||
grid.setEnabled(isChecked);
|
||||
if (mIconAdapter != null)
|
||||
mIconAdapter.notifyDataSetChanged();
|
||||
if (iconAdapter != null)
|
||||
iconAdapter.notifyDataSetChanged();
|
||||
});
|
||||
|
||||
final RadioGroup eolGroup = mEOLGroup = view.findViewById(R.id.uart_eol);
|
||||
final RadioGroup eolGroup = this.eolGroup = view.findViewById(R.id.uart_eol);
|
||||
switch (Command.Eol.values()[eol]) {
|
||||
case CR_LF:
|
||||
eolGroup.check(R.id.uart_eol_cr_lf);
|
||||
@@ -112,11 +113,16 @@ public class UARTEditDialog extends DialogFragment implements View.OnClickListen
|
||||
checkBox.setChecked(active);
|
||||
grid.setOnItemClickListener(this);
|
||||
grid.setEnabled(active);
|
||||
grid.setAdapter(mIconAdapter = new IconAdapter());
|
||||
grid.setAdapter(iconAdapter = new IconAdapter());
|
||||
|
||||
// As we want to have some validation we can't user the DialogInterface.OnClickListener as it's always dismissing the dialog.
|
||||
final AlertDialog dialog = new AlertDialog.Builder(getActivity()).setCancelable(false).setTitle(R.string.uart_edit_title).setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null).setView(view).show();
|
||||
final AlertDialog dialog = new AlertDialog.Builder(requireContext())
|
||||
.setCancelable(false)
|
||||
.setTitle(R.string.uart_edit_title)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setView(view)
|
||||
.show();
|
||||
final Button okButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
okButton.setOnClickListener(this);
|
||||
return dialog;
|
||||
@@ -124,11 +130,11 @@ public class UARTEditDialog extends DialogFragment implements View.OnClickListen
|
||||
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final boolean active = mActiveCheckBox.isChecked();
|
||||
final String command = mField.getText().toString();
|
||||
final boolean active = activeCheckBox.isChecked();
|
||||
final String command = field.getText().toString();
|
||||
int eol;
|
||||
|
||||
switch (mEOLGroup.getCheckedRadioButtonId()) {
|
||||
switch (eolGroup.getCheckedRadioButtonId()) {
|
||||
case R.id.uart_eol_cr_lf:
|
||||
eol = Command.Eol.CR_LF.index;
|
||||
break;
|
||||
@@ -142,18 +148,18 @@ public class UARTEditDialog extends DialogFragment implements View.OnClickListen
|
||||
}
|
||||
|
||||
// Save values
|
||||
final Bundle args = getArguments();
|
||||
final Bundle args = requireArguments();
|
||||
final int index = args.getInt(ARG_INDEX);
|
||||
|
||||
dismiss();
|
||||
final UARTActivity parent = (UARTActivity) getActivity();
|
||||
parent.onCommandChanged(index, command, active, eol, mActiveIcon);
|
||||
final UARTActivity parent = (UARTActivity) requireActivity();
|
||||
parent.onCommandChanged(index, command, active, eol, activeIcon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
|
||||
mActiveIcon = position;
|
||||
mIconAdapter.notifyDataSetChanged();
|
||||
activeIcon = position;
|
||||
iconAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private class IconAdapter extends BaseAdapter {
|
||||
@@ -175,14 +181,15 @@ public class UARTEditDialog extends DialogFragment implements View.OnClickListen
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int position, final View convertView, final ViewGroup parent) {
|
||||
public View getView(final int position, @Nullable final View convertView, @NonNull final ViewGroup parent) {
|
||||
View view = convertView;
|
||||
if (view == null) {
|
||||
view = LayoutInflater.from(getActivity()).inflate(R.layout.feature_uart_dialog_edit_icon, parent, false);
|
||||
view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.feature_uart_dialog_edit_icon, parent, false);
|
||||
}
|
||||
final ImageView image = (ImageView) view;
|
||||
image.setImageLevel(position);
|
||||
image.setActivated(position == mActiveIcon && mActiveCheckBox.isChecked());
|
||||
image.setActivated(position == activeIcon && activeCheckBox.isChecked());
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,15 +39,15 @@ import no.nordicsemi.android.log.LogContract.Log.Level;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
|
||||
public class UARTLogAdapter extends CursorAdapter {
|
||||
private static final SparseIntArray mColors = new SparseIntArray();
|
||||
private static final SparseIntArray colors = new SparseIntArray();
|
||||
|
||||
static {
|
||||
mColors.put(Level.DEBUG, 0xFF009CDE);
|
||||
mColors.put(Level.VERBOSE, 0xFFB8B056);
|
||||
mColors.put(Level.INFO, Color.BLACK);
|
||||
mColors.put(Level.APPLICATION, 0xFF238C0F);
|
||||
mColors.put(Level.WARNING, 0xFFD77926);
|
||||
mColors.put(Level.ERROR, Color.RED);
|
||||
colors.put(Level.DEBUG, 0xFF009CDE);
|
||||
colors.put(Level.VERBOSE, 0xFFB8B056);
|
||||
colors.put(Level.INFO, Color.BLACK);
|
||||
colors.put(Level.APPLICATION, 0xFF238C0F);
|
||||
colors.put(Level.WARNING, 0xFFD77926);
|
||||
colors.put(Level.ERROR, Color.RED);
|
||||
}
|
||||
|
||||
UARTLogAdapter(@NonNull final Context context) {
|
||||
@@ -74,7 +74,7 @@ public class UARTLogAdapter extends CursorAdapter {
|
||||
|
||||
final int level = cursor.getInt(2 /* LEVEL */);
|
||||
holder.data.setText(cursor.getString(3 /* DATA */));
|
||||
holder.data.setTextColor(mColors.get(level));
|
||||
holder.data.setTextColor(colors.get(level));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -63,28 +63,28 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
/**
|
||||
* The service UART interface that may be used to send data to the target.
|
||||
*/
|
||||
private UARTInterface mUARTInterface;
|
||||
private UARTInterface uartInterface;
|
||||
/**
|
||||
* The adapter used to populate the list with log entries.
|
||||
*/
|
||||
private CursorAdapter mLogAdapter;
|
||||
private CursorAdapter logAdapter;
|
||||
/**
|
||||
* The log session created to log events related with the target device.
|
||||
*/
|
||||
private ILogSession mLogSession;
|
||||
private ILogSession logSession;
|
||||
|
||||
private EditText mField;
|
||||
private Button mSendButton;
|
||||
private EditText field;
|
||||
private Button sendButton;
|
||||
|
||||
/**
|
||||
* The last list view position.
|
||||
*/
|
||||
private int mLogScrollPosition;
|
||||
private int logScrollPosition;
|
||||
|
||||
/**
|
||||
* The receiver that listens for {@link BleProfileService#BROADCAST_CONNECTION_STATE} action.
|
||||
*/
|
||||
private final BroadcastReceiver mCommonBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver commonBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
// This receiver listens only for the BleProfileService.BROADCAST_CONNECTION_STATE action, no need to check it.
|
||||
@@ -109,15 +109,15 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
}
|
||||
};
|
||||
|
||||
private ServiceConnection mServiceConnection = new ServiceConnection() {
|
||||
private ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName name, final IBinder service) {
|
||||
final UARTService.UARTBinder bleService = (UARTService.UARTBinder) service;
|
||||
mUARTInterface = bleService;
|
||||
mLogSession = bleService.getLogSession();
|
||||
uartInterface = bleService;
|
||||
logSession = bleService.getLogSession();
|
||||
|
||||
// Start the loader
|
||||
if (mLogSession != null) {
|
||||
if (logSession != null) {
|
||||
getLoaderManager().restartLoader(LOG_REQUEST_ID, null, UARTLogFragment.this);
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName name) {
|
||||
onDeviceDisconnected();
|
||||
mUARTInterface = null;
|
||||
uartInterface = null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -137,11 +137,11 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
LocalBroadcastManager.getInstance(requireContext()).registerReceiver(mCommonBroadcastReceiver, makeIntentFilter());
|
||||
LocalBroadcastManager.getInstance(requireContext()).registerReceiver(commonBroadcastReceiver, makeIntentFilter());
|
||||
|
||||
// Load the last log list view scroll position
|
||||
if (savedInstanceState != null) {
|
||||
mLogScrollPosition = savedInstanceState.getInt(SIS_LOG_SCROLL_POSITION);
|
||||
logScrollPosition = savedInstanceState.getInt(SIS_LOG_SCROLL_POSITION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,10 +151,10 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
|
||||
/*
|
||||
* If the service has not been started before the following lines will not start it. However, if it's running, the Activity will be bound to it
|
||||
* and notified via mServiceConnection.
|
||||
* and notified via serviceConnection.
|
||||
*/
|
||||
final Intent service = new Intent(getActivity(), UARTService.class);
|
||||
requireActivity().bindService(service, mServiceConnection, 0); // we pass 0 as a flag so the service will not be created if not exists
|
||||
requireActivity().bindService(service, serviceConnection, 0); // we pass 0 as a flag so the service will not be created if not exists
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -162,8 +162,8 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
super.onStop();
|
||||
|
||||
try {
|
||||
requireActivity().unbindService(mServiceConnection);
|
||||
mUARTInterface = null;
|
||||
requireActivity().unbindService(serviceConnection);
|
||||
uartInterface = null;
|
||||
} catch (final IllegalArgumentException e) {
|
||||
// do nothing, we were not connected to the sensor
|
||||
}
|
||||
@@ -181,7 +181,7 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
LocalBroadcastManager.getInstance(requireContext()).unregisterReceiver(mCommonBroadcastReceiver);
|
||||
LocalBroadcastManager.getInstance(requireContext()).unregisterReceiver(commonBroadcastReceiver);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
|
||||
final View view = inflater.inflate(R.layout.fragment_feature_uart_log, container, false);
|
||||
|
||||
final EditText field = mField = view.findViewById(R.id.field);
|
||||
final EditText field = this.field = view.findViewById(R.id.field);
|
||||
field.setOnEditorActionListener((v, actionId, event) -> {
|
||||
if (actionId == EditorInfo.IME_ACTION_SEND) {
|
||||
onSendClicked();
|
||||
@@ -198,7 +198,7 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
return false;
|
||||
});
|
||||
|
||||
final Button sendButton = mSendButton = view.findViewById(R.id.action_send);
|
||||
final Button sendButton = this.sendButton = view.findViewById(R.id.action_send);
|
||||
sendButton.setOnClickListener(v -> onSendClicked());
|
||||
return view;
|
||||
}
|
||||
@@ -208,8 +208,8 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
// Create the log adapter, initially with null cursor
|
||||
mLogAdapter = new UARTLogAdapter(requireContext());
|
||||
setListAdapter(mLogAdapter);
|
||||
logAdapter = new UARTLogAdapter(requireContext());
|
||||
setListAdapter(logAdapter);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -217,7 +217,7 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
|
||||
switch (id) {
|
||||
case LOG_REQUEST_ID: {
|
||||
return new CursorLoader(requireContext(), mLogSession.getSessionEntriesUri(), LOG_PROJECTION, null, null, LogContract.Log.TIME);
|
||||
return new CursorLoader(requireContext(), logSession.getSessionEntriesUri(), LOG_PROJECTION, null, null, LogContract.Log.TIME);
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException("Could not create loader with ID " + id);
|
||||
@@ -227,10 +227,10 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
public void onLoadFinished(@NonNull final Loader<Cursor> loader, final Cursor data) {
|
||||
// Here we have to restore the old saved scroll position, or scroll to the bottom if before adding new events it was scrolled to the bottom.
|
||||
final ListView list = getListView();
|
||||
final int position = mLogScrollPosition;
|
||||
final int position = logScrollPosition;
|
||||
final boolean scrolledToBottom = position == LOG_SCROLLED_TO_BOTTOM || (list.getCount() > 0 && list.getLastVisiblePosition() == list.getCount() - 1);
|
||||
|
||||
mLogAdapter.swapCursor(data);
|
||||
logAdapter.swapCursor(data);
|
||||
|
||||
if (position > LOG_SCROLL_NULL) {
|
||||
list.setSelectionFromTop(position, 0);
|
||||
@@ -238,21 +238,21 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
if (scrolledToBottom)
|
||||
list.setSelection(list.getCount() - 1);
|
||||
}
|
||||
mLogScrollPosition = LOG_SCROLL_NULL;
|
||||
logScrollPosition = LOG_SCROLL_NULL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(@NonNull final Loader<Cursor> loader) {
|
||||
mLogAdapter.swapCursor(null);
|
||||
logAdapter.swapCursor(null);
|
||||
}
|
||||
|
||||
private void onSendClicked() {
|
||||
final String text = mField.getText().toString();
|
||||
final String text = field.getText().toString();
|
||||
|
||||
mUARTInterface.send(text);
|
||||
uartInterface.send(text);
|
||||
|
||||
mField.setText(null);
|
||||
mField.requestFocus();
|
||||
field.setText(null);
|
||||
field.requestFocus();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -262,7 +262,7 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
public void onServiceStarted() {
|
||||
// The service has been started, bind to it
|
||||
final Intent service = new Intent(getActivity(), UARTService.class);
|
||||
requireActivity().bindService(service, mServiceConnection, 0);
|
||||
requireActivity().bindService(service, serviceConnection, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,7 +271,7 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
public void onFragmentHidden() {
|
||||
final InputMethodManager imm = (InputMethodManager) requireContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
if (imm != null) {
|
||||
imm.hideSoftInputFromWindow(mField.getWindowToken(), 0);
|
||||
imm.hideSoftInputFromWindow(field.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,16 +279,16 @@ public class UARTLogFragment extends ListFragment implements LoaderManager.Loade
|
||||
* Method called when the target device has connected.
|
||||
*/
|
||||
protected void onDeviceConnected() {
|
||||
mField.setEnabled(true);
|
||||
mSendButton.setEnabled(true);
|
||||
field.setEnabled(true);
|
||||
sendButton.setEnabled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called when user disconnected from the target UART device or the connection was lost.
|
||||
*/
|
||||
protected void onDeviceDisconnected() {
|
||||
mField.setEnabled(false);
|
||||
mSendButton.setEnabled(false);
|
||||
field.setEnabled(false);
|
||||
sendButton.setEnabled(false);
|
||||
}
|
||||
|
||||
private static IntentFilter makeIntentFilter() {
|
||||
|
||||
@@ -43,7 +43,7 @@ public class UARTManager extends LoggableBleManager<UARTManagerCallbacks> {
|
||||
/** TX characteristic UUID */
|
||||
private final static UUID UART_TX_CHARACTERISTIC_UUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
|
||||
|
||||
private BluetoothGattCharacteristic mRXCharacteristic, mTXCharacteristic;
|
||||
private BluetoothGattCharacteristic rxCharacteristic, txCharacteristic;
|
||||
/**
|
||||
* A flag indicating whether Long Write can be used. It's set to false if the UART RX
|
||||
* characteristic has only PROPERTY_WRITE_NO_RESPONSE property and no PROPERTY_WRITE.
|
||||
@@ -51,7 +51,7 @@ public class UARTManager extends LoggableBleManager<UARTManagerCallbacks> {
|
||||
*
|
||||
* TODO change this flag if you don't want to use Long Write even with Write Request.
|
||||
*/
|
||||
private boolean mUseLongWrite = true;
|
||||
private boolean useLongWrite = true;
|
||||
|
||||
UARTManager(final Context context) {
|
||||
super(context);
|
||||
@@ -60,39 +60,39 @@ public class UARTManager extends LoggableBleManager<UARTManagerCallbacks> {
|
||||
@NonNull
|
||||
@Override
|
||||
protected BleManagerGattCallback getGattCallback() {
|
||||
return mGattCallback;
|
||||
return gattCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* BluetoothGatt callbacks for connection/disconnection, service discovery,
|
||||
* receiving indication, etc.
|
||||
*/
|
||||
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
|
||||
private final BleManagerGattCallback gattCallback = new BleManagerGattCallback() {
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
setNotificationCallback(mTXCharacteristic)
|
||||
setNotificationCallback(txCharacteristic)
|
||||
.with((device, data) -> {
|
||||
final String text = data.getStringValue(0);
|
||||
log(LogContract.Log.Level.APPLICATION, "\"" + text + "\" received");
|
||||
mCallbacks.onDataReceived(device, text);
|
||||
callbacks.onDataReceived(device, text);
|
||||
});
|
||||
requestMtu(260).enqueue();
|
||||
enableNotifications(mTXCharacteristic).enqueue();
|
||||
enableNotifications(txCharacteristic).enqueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(UART_SERVICE_UUID);
|
||||
if (service != null) {
|
||||
mRXCharacteristic = service.getCharacteristic(UART_RX_CHARACTERISTIC_UUID);
|
||||
mTXCharacteristic = service.getCharacteristic(UART_TX_CHARACTERISTIC_UUID);
|
||||
rxCharacteristic = service.getCharacteristic(UART_RX_CHARACTERISTIC_UUID);
|
||||
txCharacteristic = service.getCharacteristic(UART_TX_CHARACTERISTIC_UUID);
|
||||
}
|
||||
|
||||
boolean writeRequest = false;
|
||||
boolean writeCommand = false;
|
||||
if (mRXCharacteristic != null) {
|
||||
final int rxProperties = mRXCharacteristic.getProperties();
|
||||
if (rxCharacteristic != null) {
|
||||
final int rxProperties = rxCharacteristic.getProperties();
|
||||
writeRequest = (rxProperties & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0;
|
||||
writeCommand = (rxProperties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0;
|
||||
|
||||
@@ -101,19 +101,19 @@ public class UARTManager extends LoggableBleManager<UARTManagerCallbacks> {
|
||||
// In case there is no WRITE REQUEST property, this manager will divide texts
|
||||
// longer then MTU-3 bytes into up to MTU-3 bytes chunks.
|
||||
if (writeRequest)
|
||||
mRXCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
|
||||
rxCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
|
||||
else
|
||||
mUseLongWrite = false;
|
||||
useLongWrite = false;
|
||||
}
|
||||
|
||||
return mRXCharacteristic != null && mTXCharacteristic != null && (writeRequest || writeCommand);
|
||||
return rxCharacteristic != null && txCharacteristic != null && (writeRequest || writeCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeviceDisconnected() {
|
||||
mRXCharacteristic = null;
|
||||
mTXCharacteristic = null;
|
||||
mUseLongWrite = true;
|
||||
rxCharacteristic = null;
|
||||
txCharacteristic = null;
|
||||
useLongWrite = true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -130,14 +130,14 @@ public class UARTManager extends LoggableBleManager<UARTManagerCallbacks> {
|
||||
*/
|
||||
public void send(final String text) {
|
||||
// Are we connected?
|
||||
if (mRXCharacteristic == null)
|
||||
if (rxCharacteristic == null)
|
||||
return;
|
||||
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
final WriteRequest request = writeCharacteristic(mRXCharacteristic, text.getBytes())
|
||||
final WriteRequest request = writeCharacteristic(rxCharacteristic, text.getBytes())
|
||||
.with((device, data) -> log(LogContract.Log.Level.APPLICATION,
|
||||
"\"" + data.getStringValue(0) + "\" sent"));
|
||||
if (!mUseLongWrite) {
|
||||
if (!useLongWrite) {
|
||||
// This will automatically split the long data into MTU-3-byte long packets.
|
||||
request.split();
|
||||
}
|
||||
|
||||
@@ -24,11 +24,12 @@ package no.nordicsemi.android.nrftoolbox.uart;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import no.nordicsemi.android.ble.BleManagerCallbacks;
|
||||
|
||||
public interface UARTManagerCallbacks extends BleManagerCallbacks {
|
||||
|
||||
void onDataReceived(final BluetoothDevice device, final String data);
|
||||
void onDataReceived(@NonNull final BluetoothDevice device, final String data);
|
||||
|
||||
void onDataSent(final BluetoothDevice device, final String data);
|
||||
void onDataSent(@NonNull final BluetoothDevice device, final String data);
|
||||
}
|
||||
|
||||
@@ -40,9 +40,9 @@ public class UARTNewConfigurationDialogFragment extends DialogFragment implement
|
||||
private static final String NAME = "name";
|
||||
private static final String DUPLICATE = "duplicate";
|
||||
|
||||
private EditText mEditText;
|
||||
private EditText editText;
|
||||
|
||||
private NewConfigurationDialogListener mListener;
|
||||
private NewConfigurationDialogListener listener;
|
||||
|
||||
public interface NewConfigurationDialogListener {
|
||||
/**
|
||||
@@ -60,11 +60,11 @@ public class UARTNewConfigurationDialogFragment extends DialogFragment implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(final Context context) {
|
||||
public void onAttach(@NonNull final Context context) {
|
||||
super.onAttach(context);
|
||||
|
||||
if (context instanceof NewConfigurationDialogListener) {
|
||||
mListener = (NewConfigurationDialogListener) context;
|
||||
listener = (NewConfigurationDialogListener) context;
|
||||
} else {
|
||||
throw new IllegalArgumentException("The parent activity must implement NewConfigurationDialogListener");
|
||||
}
|
||||
@@ -73,7 +73,7 @@ public class UARTNewConfigurationDialogFragment extends DialogFragment implement
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
mListener = null;
|
||||
listener = null;
|
||||
}
|
||||
|
||||
public static DialogFragment getInstance(final String name, final boolean duplicate) {
|
||||
@@ -90,22 +90,25 @@ public class UARTNewConfigurationDialogFragment extends DialogFragment implement
|
||||
@Override
|
||||
@NonNull
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context context = getActivity();
|
||||
|
||||
final Bundle args = getArguments();
|
||||
final Bundle args = requireArguments();
|
||||
final String oldName = args.getString(NAME);
|
||||
final boolean duplicate = args.getBoolean(DUPLICATE);
|
||||
final int titleResId = duplicate || oldName == null ? R.string.uart_new_configuration_title : R.string.uart_rename_configuration_title;
|
||||
|
||||
final LayoutInflater inflater = LayoutInflater.from(getActivity());
|
||||
final LayoutInflater inflater = LayoutInflater.from(requireContext());
|
||||
final View view = inflater.inflate(R.layout.feature_uart_dialog_new_configuration, null);
|
||||
final EditText editText = mEditText = view.findViewById(R.id.name);
|
||||
final EditText editText = this.editText = view.findViewById(R.id.name);
|
||||
editText.setText(args.getString(NAME));
|
||||
final View actionClear = view.findViewById(R.id.action_clear);
|
||||
actionClear.setOnClickListener(v -> editText.setText(null));
|
||||
|
||||
final AlertDialog dialog = new AlertDialog.Builder(context).setTitle(titleResId).setView(view).setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.ok, null).setCancelable(false).show(); // this must be show() or the getButton() below will return null.
|
||||
final AlertDialog dialog = new AlertDialog.Builder(requireContext())
|
||||
.setTitle(titleResId)
|
||||
.setView(view)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setCancelable(false)
|
||||
.show(); // this must be show() or the getButton() below will return null.
|
||||
|
||||
final Button okButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
okButton.setOnClickListener(this);
|
||||
@@ -115,19 +118,20 @@ public class UARTNewConfigurationDialogFragment extends DialogFragment implement
|
||||
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final String newName = mEditText.getText().toString().trim();
|
||||
final String newName = editText.getText().toString().trim();
|
||||
if (TextUtils.isEmpty(newName)) {
|
||||
mEditText.setError(getString(R.string.uart_empty_name_error));
|
||||
editText.setError(getString(R.string.uart_empty_name_error));
|
||||
return;
|
||||
}
|
||||
|
||||
final String oldName = getArguments().getString(NAME);
|
||||
final boolean duplicate = getArguments().getBoolean(DUPLICATE);
|
||||
final Bundle args = requireArguments();
|
||||
final String oldName = args.getString(NAME);
|
||||
final boolean duplicate = args.getBoolean(DUPLICATE);
|
||||
|
||||
if (duplicate || TextUtils.isEmpty(oldName))
|
||||
mListener.onNewConfiguration(newName, duplicate);
|
||||
listener.onNewConfiguration(newName, duplicate);
|
||||
else {
|
||||
mListener.onRenameConfiguration(newName);
|
||||
listener.onRenameConfiguration(newName);
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
|
||||
@@ -82,26 +82,26 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
|
||||
private final static int OPEN_ACTIVITY_REQ = 67; // random
|
||||
private final static int DISCONNECT_REQ = 97; // random
|
||||
|
||||
private GoogleApiClient mGoogleApiClient;
|
||||
private UARTManager mManager;
|
||||
private GoogleApiClient googleApiClient;
|
||||
private UARTManager manager;
|
||||
|
||||
private final LocalBinder mBinder = new UARTBinder();
|
||||
private final LocalBinder binder = new UARTBinder();
|
||||
|
||||
public class UARTBinder extends LocalBinder implements UARTInterface {
|
||||
@Override
|
||||
public void send(final String text) {
|
||||
mManager.send(text);
|
||||
manager.send(text);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocalBinder getBinder() {
|
||||
return mBinder;
|
||||
return binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggableBleManager<UARTManagerCallbacks> initializeManager() {
|
||||
return mManager = new UARTManager(this);
|
||||
return manager = new UARTManager(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,23 +113,23 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
registerReceiver(mDisconnectActionBroadcastReceiver, new IntentFilter(ACTION_DISCONNECT));
|
||||
registerReceiver(mIntentBroadcastReceiver, new IntentFilter(ACTION_SEND));
|
||||
registerReceiver(disconnectActionBroadcastReceiver, new IntentFilter(ACTION_DISCONNECT));
|
||||
registerReceiver(intentBroadcastReceiver, new IntentFilter(ACTION_SEND));
|
||||
|
||||
mGoogleApiClient = new GoogleApiClient.Builder(this)
|
||||
googleApiClient = new GoogleApiClient.Builder(this)
|
||||
.addApi(Wearable.API)
|
||||
.build();
|
||||
mGoogleApiClient.connect();
|
||||
googleApiClient.connect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
// when user has disconnected from the sensor, we have to cancel the notification that we've created some milliseconds before using unbindService
|
||||
stopForegroundService();
|
||||
unregisterReceiver(mDisconnectActionBroadcastReceiver);
|
||||
unregisterReceiver(mIntentBroadcastReceiver);
|
||||
unregisterReceiver(disconnectActionBroadcastReceiver);
|
||||
unregisterReceiver(intentBroadcastReceiver);
|
||||
|
||||
mGoogleApiClient.disconnect();
|
||||
googleApiClient.disconnect();
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
@@ -174,7 +174,7 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataReceived(final BluetoothDevice device, final String data) {
|
||||
public void onDataReceived(@NonNull final BluetoothDevice device, final String data) {
|
||||
final Intent broadcast = new Intent(BROADCAST_UART_RX);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_DATA, data);
|
||||
@@ -188,7 +188,7 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataSent(final BluetoothDevice device, final String data) {
|
||||
public void onDataSent(@NonNull final BluetoothDevice device, final String data) {
|
||||
final Intent broadcast = new Intent(BROADCAST_UART_TX);
|
||||
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice());
|
||||
broadcast.putExtra(EXTRA_DATA, data);
|
||||
@@ -201,13 +201,13 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
|
||||
* @param path message path
|
||||
* @param message the message
|
||||
*/
|
||||
private void sendMessageToWearables(final @NonNull String path, final @NonNull String message) {
|
||||
if (mGoogleApiClient.isConnected()) {
|
||||
private void sendMessageToWearables(@NonNull final String path, @NonNull final String message) {
|
||||
if (googleApiClient.isConnected()) {
|
||||
new Thread(() -> {
|
||||
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
|
||||
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
|
||||
for (Node node : nodes.getNodes()) {
|
||||
Logger.v(getLogSession(), "[WEAR] Sending message '" + path + "' to " + node.getDisplayName());
|
||||
final MessageApi.SendMessageResult result = Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), path, message.getBytes()).await();
|
||||
final MessageApi.SendMessageResult result = Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), path, message.getBytes()).await();
|
||||
if (result.getStatus().isSuccess()) {
|
||||
Logger.i(getLogSession(), "[WEAR] Message sent");
|
||||
} else {
|
||||
@@ -259,6 +259,7 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
|
||||
* f.e. <code><string name="name">%s is connected</string></code>
|
||||
* @param defaults signals that will be used to notify the user
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
protected Notification createNotification(final int messageResId, final int defaults) {
|
||||
final Intent parentIntent = new Intent(this, FeaturesActivity.class);
|
||||
parentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
@@ -291,7 +292,7 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
|
||||
/**
|
||||
* This broadcast receiver listens for {@link #ACTION_DISCONNECT} that may be fired by pressing Disconnect action button on the notification.
|
||||
*/
|
||||
private final BroadcastReceiver mDisconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver disconnectActionBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final int source = intent.getIntExtra(EXTRA_SOURCE, SOURCE_NOTIFICATION);
|
||||
@@ -314,7 +315,7 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
|
||||
* Broadcast receiver that listens for {@link #ACTION_SEND} from other apps. Sends the String or int content of the {@link Intent#EXTRA_TEXT} extra to the remote device.
|
||||
* The integer content will be sent as String (65 -> "65", not 65 -> "A").
|
||||
*/
|
||||
private BroadcastReceiver mIntentBroadcastReceiver = new BroadcastReceiver() {
|
||||
private BroadcastReceiver intentBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final boolean hasMessage = intent.hasExtra(Intent.EXTRA_TEXT);
|
||||
@@ -337,7 +338,7 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
|
||||
Logger.i(getLogSession(), "[Broadcast] " + ACTION_SEND + " broadcast received with data: \"" + message + "\"");
|
||||
break;
|
||||
}
|
||||
mManager.send(message);
|
||||
manager.send(message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
public class DatabaseHelper {
|
||||
/** Database file name */
|
||||
private static final String DATABASE_NAME = "toolbox_uart.db";
|
||||
@@ -41,23 +42,27 @@ public class DatabaseHelper {
|
||||
|
||||
private static final String[] ID_PROJECTION = new String[] { BaseColumns._ID };
|
||||
private static final String[] NAME_PROJECTION = new String[] { BaseColumns._ID, NameColumns.NAME };
|
||||
private static final String[] XML_PROJECTION = new String[] { BaseColumns._ID, ConfigurationContract.Configuration.XML };
|
||||
private static final String[] CONFIGURATION_PROJECTION = new String[] { BaseColumns._ID, NameColumns.NAME, ConfigurationContract.Configuration.XML };
|
||||
private static final String[] XML_PROJECTION = new String[] {
|
||||
BaseColumns._ID, ConfigurationContract.Configuration.XML
|
||||
};
|
||||
private static final String[] CONFIGURATION_PROJECTION = new String[] {
|
||||
BaseColumns._ID, NameColumns.NAME, ConfigurationContract.Configuration.XML
|
||||
};
|
||||
|
||||
private static final String ID_SELECTION = BaseColumns._ID + "=?";
|
||||
private static final String NAME_SELECTION = NameColumns.NAME + "=?";
|
||||
private static final String DELETED_SELECTION = UndoColumns.DELETED + "=1";
|
||||
private static final String NOT_DELETED_SELECTION = UndoColumns.DELETED + "=0";
|
||||
|
||||
private static SQLiteHelper mDatabaseHelper;
|
||||
private static SQLiteDatabase mDatabase;
|
||||
private final ContentValues mValues = new ContentValues();
|
||||
private final String[] mSingleArg = new String[1];
|
||||
private static SQLiteHelper databaseHelper;
|
||||
private static SQLiteDatabase database;
|
||||
private final ContentValues values = new ContentValues();
|
||||
private final String[] singleArg = new String[1];
|
||||
|
||||
public DatabaseHelper(final Context context) {
|
||||
if (mDatabaseHelper == null) {
|
||||
mDatabaseHelper = new SQLiteHelper(context);
|
||||
mDatabase = mDatabaseHelper.getWritableDatabase();
|
||||
if (databaseHelper == null) {
|
||||
databaseHelper = new SQLiteHelper(context);
|
||||
database = databaseHelper.getWritableDatabase();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,11 +70,9 @@ public class DatabaseHelper {
|
||||
* Returns number of saved configurations.
|
||||
*/
|
||||
public int getConfigurationsCount() {
|
||||
final Cursor cursor = mDatabase.query(Tables.CONFIGURATIONS, ID_PROJECTION, NOT_DELETED_SELECTION, null, null, null, null);
|
||||
try {
|
||||
try (Cursor cursor = database.query(Tables.CONFIGURATIONS, ID_PROJECTION, NOT_DELETED_SELECTION,
|
||||
null, null, null, null)) {
|
||||
return cursor.getCount();
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,91 +81,95 @@ public class DatabaseHelper {
|
||||
* @return cursor
|
||||
*/
|
||||
public Cursor getConfigurations() {
|
||||
return mDatabase.query(Tables.CONFIGURATIONS, CONFIGURATION_PROJECTION, NOT_DELETED_SELECTION, null, null, null, ConfigurationContract.Configuration.NAME + " ASC");
|
||||
return database.query(Tables.CONFIGURATIONS, CONFIGURATION_PROJECTION, NOT_DELETED_SELECTION,
|
||||
null, null, null, ConfigurationContract.Configuration.NAME + " ASC");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of names of all saved configurations.
|
||||
*
|
||||
* @return cursor
|
||||
*/
|
||||
public Cursor getConfigurationsNames() {
|
||||
return mDatabase.query(Tables.CONFIGURATIONS, NAME_PROJECTION, NOT_DELETED_SELECTION, null, null, null, ConfigurationContract.Configuration.NAME + " ASC");
|
||||
return database.query(Tables.CONFIGURATIONS, NAME_PROJECTION, NOT_DELETED_SELECTION,
|
||||
null, null, null, ConfigurationContract.Configuration.NAME + " ASC");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the XML wth the configuration by id.
|
||||
*
|
||||
* @param id the configuration id in the DB
|
||||
* @return the XML with configuration or null
|
||||
*/
|
||||
public String getConfiguration(final long id) {
|
||||
mSingleArg[0] = String.valueOf(id);
|
||||
singleArg[0] = String.valueOf(id);
|
||||
|
||||
final Cursor cursor = mDatabase.query(Tables.CONFIGURATIONS, XML_PROJECTION, ID_SELECTION, mSingleArg, null, null, null);
|
||||
try {
|
||||
try (Cursor cursor = database.query(Tables.CONFIGURATIONS, XML_PROJECTION, ID_SELECTION,
|
||||
singleArg, null, null, null)) {
|
||||
if (cursor.moveToNext())
|
||||
return cursor.getString(1 /* XML */);
|
||||
return null;
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new configuration to the database.
|
||||
*
|
||||
* @param name the configuration name
|
||||
* @param configuration the XML
|
||||
* @return the id or -1 if error occurred
|
||||
*/
|
||||
public long addConfiguration(final String name, final String configuration) {
|
||||
final ContentValues values = mValues;
|
||||
final ContentValues values = this.values;
|
||||
values.clear();
|
||||
values.put(ConfigurationContract.Configuration.NAME, name);
|
||||
values.put(ConfigurationContract.Configuration.XML, configuration);
|
||||
values.put(ConfigurationContract.Configuration.DELETED, 0);
|
||||
return mDatabase.replace(Tables.CONFIGURATIONS, null, values);
|
||||
return database.replace(Tables.CONFIGURATIONS, null, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the configuration with the given name with the new XML
|
||||
* Updates the configuration with the given name with the new XML.
|
||||
*
|
||||
* @param name the configuration name to be updated
|
||||
* @param configuration the new XML with configuration
|
||||
* @return number of rows updated
|
||||
*/
|
||||
public int updateConfiguration(final String name, final String configuration) {
|
||||
mSingleArg[0] = name;
|
||||
singleArg[0] = name;
|
||||
|
||||
final ContentValues values = mValues;
|
||||
final ContentValues values = this.values;
|
||||
values.clear();
|
||||
values.put(ConfigurationContract.Configuration.XML, configuration);
|
||||
values.put(ConfigurationContract.Configuration.DELETED, 0);
|
||||
return mDatabase.update(Tables.CONFIGURATIONS, values, NAME_SELECTION, mSingleArg);
|
||||
return database.update(Tables.CONFIGURATIONS, values, NAME_SELECTION, singleArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the configuration with given name as deleted. If may be restored or removed permanently afterwards.
|
||||
* Marks the configuration with given name as deleted. If may be restored or removed permanently
|
||||
* afterwards.
|
||||
*
|
||||
* @param name the configuration name
|
||||
* @return id of the deleted configuration
|
||||
*/
|
||||
public long deleteConfiguration(final String name) {
|
||||
mSingleArg[0] = name;
|
||||
singleArg[0] = name;
|
||||
|
||||
final ContentValues values = mValues;
|
||||
final ContentValues values = this.values;
|
||||
values.clear();
|
||||
values.put(ConfigurationContract.Configuration.DELETED, 1);
|
||||
mDatabase.update(Tables.CONFIGURATIONS, values, NAME_SELECTION, mSingleArg);
|
||||
database.update(Tables.CONFIGURATIONS, values, NAME_SELECTION, singleArg);
|
||||
|
||||
final Cursor cursor = mDatabase.query(Tables.CONFIGURATIONS, ID_PROJECTION, NAME_SELECTION, mSingleArg, null, null, null);
|
||||
try {
|
||||
try (Cursor cursor = database.query(Tables.CONFIGURATIONS, ID_PROJECTION, NAME_SELECTION,
|
||||
singleArg, null, null, null)) {
|
||||
if (cursor.moveToNext())
|
||||
return cursor.getLong(0 /* _ID */);
|
||||
return -1;
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
public int removeDeletedServerConfigurations() {
|
||||
return mDatabase.delete(Tables.CONFIGURATIONS, DELETED_SELECTION, null);
|
||||
return database.delete(Tables.CONFIGURATIONS, DELETED_SELECTION, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,20 +177,18 @@ public class DatabaseHelper {
|
||||
* @return the DI of the restored configuration.
|
||||
*/
|
||||
public long restoreDeletedServerConfiguration(final String name) {
|
||||
mSingleArg[0] = name;
|
||||
singleArg[0] = name;
|
||||
|
||||
final ContentValues values = mValues;
|
||||
final ContentValues values = this.values;
|
||||
values.clear();
|
||||
values.put(ConfigurationContract.Configuration.DELETED, 0);
|
||||
mDatabase.update(Tables.CONFIGURATIONS, values, NAME_SELECTION, mSingleArg);
|
||||
database.update(Tables.CONFIGURATIONS, values, NAME_SELECTION, singleArg);
|
||||
|
||||
final Cursor cursor = mDatabase.query(Tables.CONFIGURATIONS, ID_PROJECTION, NAME_SELECTION, mSingleArg, null, null, null);
|
||||
try {
|
||||
try (Cursor cursor = database.query(Tables.CONFIGURATIONS, ID_PROJECTION, NAME_SELECTION, singleArg,
|
||||
null, null, null)) {
|
||||
if (cursor.moveToNext())
|
||||
return cursor.getLong(0 /* _ID */);
|
||||
return -1;
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,13 +200,13 @@ public class DatabaseHelper {
|
||||
* @return number of rows affected
|
||||
*/
|
||||
public int renameConfiguration(final String oldName, final String newName, final String configuration) {
|
||||
mSingleArg[0] = oldName;
|
||||
singleArg[0] = oldName;
|
||||
|
||||
final ContentValues values = mValues;
|
||||
final ContentValues values = this.values;
|
||||
values.clear();
|
||||
values.put(ConfigurationContract.Configuration.NAME, newName);
|
||||
values.put(ConfigurationContract.Configuration.XML, configuration);
|
||||
return mDatabase.update(Tables.CONFIGURATIONS, values, NAME_SELECTION, mSingleArg);
|
||||
return database.update(Tables.CONFIGURATIONS, values, NAME_SELECTION, singleArg);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,13 +215,11 @@ public class DatabaseHelper {
|
||||
* @return true if such name exists, false otherwise
|
||||
*/
|
||||
public boolean configurationExists(final String name) {
|
||||
mSingleArg[0] = name;
|
||||
singleArg[0] = name;
|
||||
|
||||
final Cursor cursor = mDatabase.query(Tables.CONFIGURATIONS, NAME_PROJECTION, NAME_SELECTION + " AND " + NOT_DELETED_SELECTION, mSingleArg, null, null, null);
|
||||
try {
|
||||
try (Cursor cursor = database.query(Tables.CONFIGURATIONS, NAME_PROJECTION, NAME_SELECTION
|
||||
+ " AND " + NOT_DELETED_SELECTION, singleArg, null, null, null)) {
|
||||
return cursor.getCount() > 0;
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,12 +236,13 @@ public class DatabaseHelper {
|
||||
* ----------------------------------------------------------------------------
|
||||
* </pre>
|
||||
*/
|
||||
private static final String CREATE_CONFIGURATIONS = "CREATE TABLE " + Tables.CONFIGURATIONS+ "(" + ConfigurationContract.Configuration._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
+ ConfigurationContract.Configuration.NAME + " TEXT UNIQUE NOT NULL, " + ConfigurationContract.Configuration.XML + " TEXT NOT NULL, " + ConfigurationContract.Configuration.DELETED +" INTEGER NOT NULL DEFAULT(0))";
|
||||
private static final String CREATE_CONFIGURATIONS = "CREATE TABLE " + Tables.CONFIGURATIONS
|
||||
+ "(" + ConfigurationContract.Configuration._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
+ ConfigurationContract.Configuration.NAME + " TEXT UNIQUE NOT NULL, "
|
||||
+ ConfigurationContract.Configuration.XML + " TEXT NOT NULL, "
|
||||
+ ConfigurationContract.Configuration.DELETED +" INTEGER NOT NULL DEFAULT(0))";
|
||||
|
||||
private static final String DROP_IF_EXISTS = "DROP TABLE IF EXISTS ";
|
||||
|
||||
public SQLiteHelper(Context context) {
|
||||
SQLiteHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@@ -250,6 +254,7 @@ public class DatabaseHelper {
|
||||
@Override
|
||||
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
||||
// This method does nothing for now.
|
||||
//noinspection SwitchStatementWithTooFewBranches
|
||||
switch (oldVersion) {
|
||||
case 1:
|
||||
// do nothing
|
||||
|
||||
@@ -42,8 +42,8 @@ import no.nordicsemi.android.nrftoolbox.wearable.common.Constants;
|
||||
public class UARTConfigurationSynchronizer {
|
||||
private static final String WEAR_URI_PREFIX = "wear:"; // no / at the end as the path already has it
|
||||
|
||||
private static UARTConfigurationSynchronizer mInstance;
|
||||
private GoogleApiClient mGoogleApiClient;
|
||||
private static UARTConfigurationSynchronizer instance;
|
||||
private GoogleApiClient googleApiClient;
|
||||
|
||||
/**
|
||||
* Initializes the synchronizer.
|
||||
@@ -51,11 +51,11 @@ public class UARTConfigurationSynchronizer {
|
||||
* @param listener the connection callbacks listener
|
||||
*/
|
||||
public static UARTConfigurationSynchronizer from(final Context context, final GoogleApiClient.ConnectionCallbacks listener) {
|
||||
if (mInstance == null)
|
||||
mInstance = new UARTConfigurationSynchronizer();
|
||||
if (instance == null)
|
||||
instance = new UARTConfigurationSynchronizer();
|
||||
|
||||
mInstance.init(context, listener);
|
||||
return mInstance;
|
||||
instance.init(context, listener);
|
||||
return instance;
|
||||
}
|
||||
|
||||
private UARTConfigurationSynchronizer() {
|
||||
@@ -63,30 +63,31 @@ public class UARTConfigurationSynchronizer {
|
||||
}
|
||||
|
||||
private void init(final Context context, final GoogleApiClient.ConnectionCallbacks listener) {
|
||||
if (mGoogleApiClient != null)
|
||||
if (googleApiClient != null)
|
||||
return;
|
||||
|
||||
mGoogleApiClient = new GoogleApiClient.Builder(context)
|
||||
googleApiClient = new GoogleApiClient.Builder(context)
|
||||
.addApiIfAvailable(Wearable.API)
|
||||
.addConnectionCallbacks(listener)
|
||||
.build();
|
||||
mGoogleApiClient.connect();
|
||||
googleApiClient.connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the synchronizer.
|
||||
*/
|
||||
public void close() {
|
||||
if (mGoogleApiClient != null)
|
||||
mGoogleApiClient.disconnect();
|
||||
mGoogleApiClient = null;
|
||||
if (googleApiClient != null)
|
||||
googleApiClient.disconnect();
|
||||
googleApiClient = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if Wearable API has been connected.
|
||||
*/
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean hasConnectedApi() {
|
||||
return mGoogleApiClient != null && mGoogleApiClient.isConnected() && mGoogleApiClient.hasConnectedApi(Wearable.API);
|
||||
return googleApiClient != null && googleApiClient.isConnected() && googleApiClient.hasConnectedApi(Wearable.API);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,7 +114,7 @@ public class UARTConfigurationSynchronizer {
|
||||
}
|
||||
map.putDataMapArrayList(Constants.UART.Configuration.COMMANDS, commands);
|
||||
final PutDataRequest request = mapRequest.asPutDataRequest();
|
||||
return Wearable.DataApi.putDataItem(mGoogleApiClient, request);
|
||||
return Wearable.DataApi.putDataItem(googleApiClient, request);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,10 +122,11 @@ public class UARTConfigurationSynchronizer {
|
||||
* Call this when configuration has been deleted.
|
||||
* @return pending result
|
||||
*/
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
public PendingResult<DataApi.DeleteDataItemsResult> onConfigurationDeleted(final long id) {
|
||||
if (!hasConnectedApi())
|
||||
return null;
|
||||
return Wearable.DataApi.deleteDataItems(mGoogleApiClient, id2Uri(id));
|
||||
return Wearable.DataApi.deleteDataItems(googleApiClient, id2Uri(id));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,6 +42,7 @@ public class MainWearableListenerService extends WearableListenerService {
|
||||
// A disconnect message was sent. The information which profile should be disconnected is in the data.
|
||||
final String profile = new String(messageEvent.getData());
|
||||
|
||||
//noinspection SwitchStatementWithTooFewBranches
|
||||
switch (profile) {
|
||||
// Currently only UART profile has Wear support
|
||||
case Constants.UART.PROFILE: {
|
||||
|
||||
@@ -41,13 +41,13 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration {
|
||||
|
||||
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
|
||||
|
||||
private Drawable mDivider;
|
||||
private Drawable divider;
|
||||
|
||||
private int mOrientation;
|
||||
private int orientation;
|
||||
|
||||
public DividerItemDecoration(Context context, int orientation) {
|
||||
final TypedArray a = context.obtainStyledAttributes(ATTRS);
|
||||
mDivider = a.getDrawable(0);
|
||||
divider = a.getDrawable(0);
|
||||
a.recycle();
|
||||
setOrientation(orientation);
|
||||
}
|
||||
@@ -56,12 +56,12 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration {
|
||||
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
|
||||
throw new IllegalArgumentException("invalid orientation");
|
||||
}
|
||||
mOrientation = orientation;
|
||||
orientation = orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
|
||||
if (mOrientation == VERTICAL_LIST) {
|
||||
if (orientation == VERTICAL_LIST) {
|
||||
drawVertical(c, parent);
|
||||
} else {
|
||||
drawHorizontal(c, parent);
|
||||
@@ -78,9 +78,9 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration {
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
|
||||
.getLayoutParams();
|
||||
final int top = child.getBottom() + params.bottomMargin;
|
||||
final int bottom = top + mDivider.getIntrinsicHeight();
|
||||
mDivider.setBounds(left, top, right, bottom);
|
||||
mDivider.draw(c);
|
||||
final int bottom = top + divider.getIntrinsicHeight();
|
||||
divider.setBounds(left, top, right, bottom);
|
||||
divider.draw(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,18 +94,18 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration {
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
|
||||
.getLayoutParams();
|
||||
final int left = child.getRight() + params.rightMargin;
|
||||
final int right = left + mDivider.getIntrinsicHeight();
|
||||
mDivider.setBounds(left, top, right, bottom);
|
||||
mDivider.draw(c);
|
||||
final int right = left + divider.getIntrinsicHeight();
|
||||
divider.setBounds(left, top, right, bottom);
|
||||
divider.draw(c);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
|
||||
if (mOrientation == VERTICAL_LIST) {
|
||||
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
|
||||
if (orientation == VERTICAL_LIST) {
|
||||
outRect.set(0, 0, 0, divider.getIntrinsicHeight());
|
||||
} else {
|
||||
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
|
||||
outRect.set(0, 0, divider.getIntrinsicWidth(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,9 +38,9 @@ import no.nordicsemi.android.nrftoolbox.R;
|
||||
|
||||
public class ForegroundLinearLayout extends LinearLayout {
|
||||
|
||||
private Drawable mForegroundSelector;
|
||||
private Rect mRectPadding;
|
||||
private boolean mUseBackgroundPadding = false;
|
||||
private Drawable foregroundSelector;
|
||||
private Rect rectPadding;
|
||||
private boolean useBackgroundPadding = false;
|
||||
|
||||
public ForegroundLinearLayout(Context context) {
|
||||
super(context);
|
||||
@@ -65,9 +65,9 @@ public class ForegroundLinearLayout extends LinearLayout {
|
||||
|
||||
if (this.getBackground() instanceof NinePatchDrawable) {
|
||||
final NinePatchDrawable npd = (NinePatchDrawable) this.getBackground();
|
||||
mRectPadding = new Rect();
|
||||
if (npd.getPadding(mRectPadding)) {
|
||||
mUseBackgroundPadding = true;
|
||||
rectPadding = new Rect();
|
||||
if (npd.getPadding(rectPadding)) {
|
||||
useBackgroundPadding = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,8 +76,8 @@ public class ForegroundLinearLayout extends LinearLayout {
|
||||
protected void drawableStateChanged() {
|
||||
super.drawableStateChanged();
|
||||
|
||||
if (mForegroundSelector != null && mForegroundSelector.isStateful()) {
|
||||
mForegroundSelector.setState(getDrawableState());
|
||||
if (foregroundSelector != null && foregroundSelector.isStateful()) {
|
||||
foregroundSelector.setState(getDrawableState());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,11 +85,11 @@ public class ForegroundLinearLayout extends LinearLayout {
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
|
||||
if (mForegroundSelector != null) {
|
||||
if (mUseBackgroundPadding) {
|
||||
mForegroundSelector.setBounds(mRectPadding.left, mRectPadding.top, w - mRectPadding.right, h - mRectPadding.bottom);
|
||||
if (foregroundSelector != null) {
|
||||
if (useBackgroundPadding) {
|
||||
foregroundSelector.setBounds(rectPadding.left, rectPadding.top, w - rectPadding.right, h - rectPadding.bottom);
|
||||
} else {
|
||||
mForegroundSelector.setBounds(0, 0, w, h);
|
||||
foregroundSelector.setBounds(0, 0, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,30 +98,30 @@ public class ForegroundLinearLayout extends LinearLayout {
|
||||
protected void dispatchDraw(@NonNull Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
|
||||
if (mForegroundSelector != null) {
|
||||
mForegroundSelector.draw(canvas);
|
||||
if (foregroundSelector != null) {
|
||||
foregroundSelector.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean verifyDrawable(Drawable who) {
|
||||
return super.verifyDrawable(who) || (who == mForegroundSelector);
|
||||
return super.verifyDrawable(who) || (who == foregroundSelector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jumpDrawablesToCurrentState() {
|
||||
super.jumpDrawablesToCurrentState();
|
||||
if (mForegroundSelector != null) mForegroundSelector.jumpToCurrentState();
|
||||
if (foregroundSelector != null) foregroundSelector.jumpToCurrentState();
|
||||
}
|
||||
|
||||
public void setForeground(Drawable drawable) {
|
||||
if (mForegroundSelector != drawable) {
|
||||
if (mForegroundSelector != null) {
|
||||
mForegroundSelector.setCallback(null);
|
||||
unscheduleDrawable(mForegroundSelector);
|
||||
if (foregroundSelector != drawable) {
|
||||
if (foregroundSelector != null) {
|
||||
foregroundSelector.setCallback(null);
|
||||
unscheduleDrawable(foregroundSelector);
|
||||
}
|
||||
|
||||
mForegroundSelector = drawable;
|
||||
foregroundSelector = drawable;
|
||||
|
||||
if (drawable != null) {
|
||||
setWillNotDraw(false);
|
||||
@@ -141,8 +141,8 @@ public class ForegroundLinearLayout extends LinearLayout {
|
||||
@Override
|
||||
public void drawableHotspotChanged(float x, float y) {
|
||||
super.drawableHotspotChanged(x, y);
|
||||
if (mForegroundSelector != null) {
|
||||
mForegroundSelector.setHotspot(x, y);
|
||||
if (foregroundSelector != null) {
|
||||
foregroundSelector.setHotspot(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,9 +38,9 @@ import no.nordicsemi.android.nrftoolbox.R;
|
||||
|
||||
public class ForegroundRelativeLayout extends RelativeLayout {
|
||||
|
||||
private Drawable mForegroundSelector;
|
||||
private Rect mRectPadding;
|
||||
private boolean mUseBackgroundPadding = false;
|
||||
private Drawable foregroundSelector;
|
||||
private Rect rectPadding;
|
||||
private boolean useBackgroundPadding = false;
|
||||
|
||||
public ForegroundRelativeLayout(Context context) {
|
||||
super(context);
|
||||
@@ -65,9 +65,9 @@ public class ForegroundRelativeLayout extends RelativeLayout {
|
||||
|
||||
if (this.getBackground() instanceof NinePatchDrawable) {
|
||||
final NinePatchDrawable npd = (NinePatchDrawable) this.getBackground();
|
||||
mRectPadding = new Rect();
|
||||
if (npd.getPadding(mRectPadding)) {
|
||||
mUseBackgroundPadding = true;
|
||||
rectPadding = new Rect();
|
||||
if (npd.getPadding(rectPadding)) {
|
||||
useBackgroundPadding = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,8 +76,8 @@ public class ForegroundRelativeLayout extends RelativeLayout {
|
||||
protected void drawableStateChanged() {
|
||||
super.drawableStateChanged();
|
||||
|
||||
if (mForegroundSelector != null && mForegroundSelector.isStateful()) {
|
||||
mForegroundSelector.setState(getDrawableState());
|
||||
if (foregroundSelector != null && foregroundSelector.isStateful()) {
|
||||
foregroundSelector.setState(getDrawableState());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,11 +85,11 @@ public class ForegroundRelativeLayout extends RelativeLayout {
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
|
||||
if (mForegroundSelector != null) {
|
||||
if (mUseBackgroundPadding) {
|
||||
mForegroundSelector.setBounds(mRectPadding.left, mRectPadding.top, w - mRectPadding.right, h - mRectPadding.bottom);
|
||||
if (foregroundSelector != null) {
|
||||
if (useBackgroundPadding) {
|
||||
foregroundSelector.setBounds(rectPadding.left, rectPadding.top, w - rectPadding.right, h - rectPadding.bottom);
|
||||
} else {
|
||||
mForegroundSelector.setBounds(0, 0, w, h);
|
||||
foregroundSelector.setBounds(0, 0, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,30 +98,30 @@ public class ForegroundRelativeLayout extends RelativeLayout {
|
||||
protected void dispatchDraw(@NonNull Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
|
||||
if (mForegroundSelector != null) {
|
||||
mForegroundSelector.draw(canvas);
|
||||
if (foregroundSelector != null) {
|
||||
foregroundSelector.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean verifyDrawable(Drawable who) {
|
||||
return super.verifyDrawable(who) || (who == mForegroundSelector);
|
||||
return super.verifyDrawable(who) || (who == foregroundSelector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jumpDrawablesToCurrentState() {
|
||||
super.jumpDrawablesToCurrentState();
|
||||
if (mForegroundSelector != null) mForegroundSelector.jumpToCurrentState();
|
||||
if (foregroundSelector != null) foregroundSelector.jumpToCurrentState();
|
||||
}
|
||||
|
||||
public void setForeground(Drawable drawable) {
|
||||
if (mForegroundSelector != drawable) {
|
||||
if (mForegroundSelector != null) {
|
||||
mForegroundSelector.setCallback(null);
|
||||
unscheduleDrawable(mForegroundSelector);
|
||||
if (foregroundSelector != drawable) {
|
||||
if (foregroundSelector != null) {
|
||||
foregroundSelector.setCallback(null);
|
||||
unscheduleDrawable(foregroundSelector);
|
||||
}
|
||||
|
||||
mForegroundSelector = drawable;
|
||||
foregroundSelector = drawable;
|
||||
|
||||
if (drawable != null) {
|
||||
setWillNotDraw(false);
|
||||
@@ -141,8 +141,8 @@ public class ForegroundRelativeLayout extends RelativeLayout {
|
||||
@Override
|
||||
public void drawableHotspotChanged(float x, float y) {
|
||||
super.drawableHotspotChanged(x, y);
|
||||
if (mForegroundSelector != null) {
|
||||
mForegroundSelector.setHotspot(x, y);
|
||||
if (foregroundSelector != null) {
|
||||
foregroundSelector.setHotspot(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,19 +41,19 @@ public class DeviceItemLayout extends RelativeLayout implements WearableListView
|
||||
private static final float SHRINK_LABEL_ALPHA = .5f;
|
||||
private static final float EXPAND_LABEL_ALPHA = 1f;
|
||||
|
||||
private float mExpandCircleRadius;
|
||||
private float mShrinkCircleRadius;
|
||||
private float expandCircleRadius;
|
||||
private float shrinkCircleRadius;
|
||||
|
||||
private ObjectAnimator mExpandCircleAnimator;
|
||||
private ObjectAnimator mFadeInLabelAnimator;
|
||||
private AnimatorSet mExpandAnimator;
|
||||
private ObjectAnimator expandCircleAnimator;
|
||||
private ObjectAnimator fadeInLabelAnimator;
|
||||
private AnimatorSet expandAnimator;
|
||||
|
||||
private ObjectAnimator mShrinkCircleAnimator;
|
||||
private ObjectAnimator mFadeOutLabelAnimator;
|
||||
private AnimatorSet mShrinkAnimator;
|
||||
private ObjectAnimator shrinkCircleAnimator;
|
||||
private ObjectAnimator fadeOutLabelAnimator;
|
||||
private AnimatorSet shrinkAnimator;
|
||||
|
||||
private TextView mName;
|
||||
private CircledImageView mIcon;
|
||||
private TextView name;
|
||||
private CircledImageView icon;
|
||||
|
||||
public DeviceItemLayout(final Context context) {
|
||||
this(context, null, 0);
|
||||
@@ -71,51 +71,51 @@ public class DeviceItemLayout extends RelativeLayout implements WearableListView
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mName = findViewById(R.id.name);
|
||||
mIcon = findViewById(R.id.icon);
|
||||
mExpandCircleRadius = mIcon.getCircleRadius();
|
||||
mShrinkCircleRadius = mExpandCircleRadius * SHRINK_CIRCLE_RATIO;
|
||||
name = findViewById(R.id.name);
|
||||
icon = findViewById(R.id.icon);
|
||||
expandCircleRadius = icon.getCircleRadius();
|
||||
shrinkCircleRadius = expandCircleRadius * SHRINK_CIRCLE_RATIO;
|
||||
|
||||
mShrinkCircleAnimator = ObjectAnimator.ofFloat(mIcon, "circleRadius", mExpandCircleRadius, mShrinkCircleRadius);
|
||||
mFadeOutLabelAnimator = ObjectAnimator.ofFloat(mName, "alpha", EXPAND_LABEL_ALPHA, SHRINK_LABEL_ALPHA);
|
||||
mShrinkAnimator = new AnimatorSet().setDuration(ANIMATION_DURATION_MS);
|
||||
mShrinkAnimator.playTogether(mShrinkCircleAnimator, mFadeOutLabelAnimator);
|
||||
shrinkCircleAnimator = ObjectAnimator.ofFloat(icon, "circleRadius", expandCircleRadius, shrinkCircleRadius);
|
||||
fadeOutLabelAnimator = ObjectAnimator.ofFloat(name, "alpha", EXPAND_LABEL_ALPHA, SHRINK_LABEL_ALPHA);
|
||||
shrinkAnimator = new AnimatorSet().setDuration(ANIMATION_DURATION_MS);
|
||||
shrinkAnimator.playTogether(shrinkCircleAnimator, fadeOutLabelAnimator);
|
||||
|
||||
mExpandCircleAnimator = ObjectAnimator.ofFloat(mIcon, "circleRadius", mShrinkCircleRadius, mExpandCircleRadius);
|
||||
mFadeInLabelAnimator = ObjectAnimator.ofFloat(mName, "alpha", SHRINK_LABEL_ALPHA, EXPAND_LABEL_ALPHA);
|
||||
mExpandAnimator = new AnimatorSet().setDuration(ANIMATION_DURATION_MS);
|
||||
mExpandAnimator.playTogether(mExpandCircleAnimator, mFadeInLabelAnimator);
|
||||
expandCircleAnimator = ObjectAnimator.ofFloat(icon, "circleRadius", shrinkCircleRadius, expandCircleRadius);
|
||||
fadeInLabelAnimator = ObjectAnimator.ofFloat(name, "alpha", SHRINK_LABEL_ALPHA, EXPAND_LABEL_ALPHA);
|
||||
expandAnimator = new AnimatorSet().setDuration(ANIMATION_DURATION_MS);
|
||||
expandAnimator.playTogether(expandCircleAnimator, fadeInLabelAnimator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCenterPosition(final boolean animate) {
|
||||
if (animate) {
|
||||
mShrinkAnimator.cancel();
|
||||
if (!mExpandAnimator.isRunning()) {
|
||||
mExpandCircleAnimator.setFloatValues(mIcon.getCircleRadius(), mExpandCircleRadius);
|
||||
mFadeInLabelAnimator.setFloatValues(mName.getAlpha(), EXPAND_LABEL_ALPHA);
|
||||
mExpandAnimator.start();
|
||||
shrinkAnimator.cancel();
|
||||
if (!expandAnimator.isRunning()) {
|
||||
expandCircleAnimator.setFloatValues(icon.getCircleRadius(), expandCircleRadius);
|
||||
fadeInLabelAnimator.setFloatValues(name.getAlpha(), EXPAND_LABEL_ALPHA);
|
||||
expandAnimator.start();
|
||||
}
|
||||
} else {
|
||||
mExpandAnimator.cancel();
|
||||
mIcon.setCircleRadius(mExpandCircleRadius);
|
||||
mName.setAlpha(EXPAND_LABEL_ALPHA);
|
||||
expandAnimator.cancel();
|
||||
icon.setCircleRadius(expandCircleRadius);
|
||||
name.setAlpha(EXPAND_LABEL_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNonCenterPosition(final boolean animate) {
|
||||
if (animate) {
|
||||
mExpandAnimator.cancel();
|
||||
if (!mShrinkAnimator.isRunning()) {
|
||||
mShrinkCircleAnimator.setFloatValues(mIcon.getCircleRadius(), mShrinkCircleRadius);
|
||||
mFadeOutLabelAnimator.setFloatValues(mName.getAlpha(), SHRINK_LABEL_ALPHA);
|
||||
mShrinkAnimator.start();
|
||||
expandAnimator.cancel();
|
||||
if (!shrinkAnimator.isRunning()) {
|
||||
shrinkCircleAnimator.setFloatValues(icon.getCircleRadius(), shrinkCircleRadius);
|
||||
fadeOutLabelAnimator.setFloatValues(name.getAlpha(), SHRINK_LABEL_ALPHA);
|
||||
shrinkAnimator.start();
|
||||
}
|
||||
} else {
|
||||
mShrinkAnimator.cancel();
|
||||
mIcon.setCircleRadius(mShrinkCircleRadius);
|
||||
mName.setAlpha(SHRINK_LABEL_ALPHA);
|
||||
shrinkAnimator.cancel();
|
||||
icon.setCircleRadius(shrinkCircleRadius);
|
||||
name.setAlpha(SHRINK_LABEL_ALPHA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,127 +48,127 @@ public class DevicesAdapter extends WearableListView.Adapter {
|
||||
|
||||
private final static long SCAN_DURATION = 5000;
|
||||
|
||||
private final List<BluetoothDevice> mDevices = new ArrayList<>();
|
||||
private final LayoutInflater mInflater;
|
||||
private final Handler mHandler;
|
||||
private final WearableListView mListView;
|
||||
private final String mNotAvailable;
|
||||
private final String mConnectingText;
|
||||
private final String mAvailableText;
|
||||
private final String mBondedText;
|
||||
private final String mBondingText;
|
||||
private final List<BluetoothDevice> devices = new ArrayList<>();
|
||||
private final LayoutInflater inflater;
|
||||
private final Handler handler;
|
||||
private final WearableListView listView;
|
||||
private final String notAvailable;
|
||||
private final String connectingText;
|
||||
private final String availableText;
|
||||
private final String bondedText;
|
||||
private final String bondingText;
|
||||
/** A position of a device that the activity is currently connecting to. */
|
||||
private int mConnectingPosition = -1;
|
||||
private int connectingPosition = -1;
|
||||
/** Flag set to true when scanner is active. */
|
||||
private boolean mScanning;
|
||||
private boolean scanning;
|
||||
|
||||
public DevicesAdapter(final WearableListView listView) {
|
||||
final Context context = listView.getContext();
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mNotAvailable = context.getString(R.string.not_available);
|
||||
mConnectingText = context.getString(R.string.state_connecting);
|
||||
mAvailableText = context.getString(R.string.devices_list_available);
|
||||
mBondedText = context.getString(R.string.devices_list_bonded);
|
||||
mBondingText = context.getString(R.string.devices_list_bonding);
|
||||
mListView = listView;
|
||||
mHandler = new Handler();
|
||||
inflater = LayoutInflater.from(context);
|
||||
notAvailable = context.getString(R.string.not_available);
|
||||
connectingText = context.getString(R.string.state_connecting);
|
||||
availableText = context.getString(R.string.devices_list_available);
|
||||
bondedText = context.getString(R.string.devices_list_bonded);
|
||||
bondingText = context.getString(R.string.devices_list_bonding);
|
||||
this.listView = listView;
|
||||
handler = new Handler();
|
||||
|
||||
final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (bluetoothAdapter != null)
|
||||
mDevices.addAll(bluetoothAdapter.getBondedDevices());
|
||||
devices.addAll(bluetoothAdapter.getBondedDevices());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public WearableListView.ViewHolder onCreateViewHolder(@NonNull final ViewGroup viewGroup, final int position) {
|
||||
return new ItemViewHolder(mInflater.inflate(R.layout.device_item, viewGroup, false));
|
||||
return new ItemViewHolder(inflater.inflate(R.layout.device_item, viewGroup, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final WearableListView.ViewHolder holder, final int position) {
|
||||
final ItemViewHolder viewHolder = (ItemViewHolder) holder;
|
||||
|
||||
if (position < mDevices.size()) {
|
||||
final BluetoothDevice device = mDevices.get(position);
|
||||
if (position < devices.size()) {
|
||||
final BluetoothDevice device = devices.get(position);
|
||||
|
||||
viewHolder.mDevice = device;
|
||||
viewHolder.mName.setText(TextUtils.isEmpty(device.getName()) ? mNotAvailable : device.getName());
|
||||
viewHolder.mAddress.setText(getState(device, position));
|
||||
viewHolder.mIcon.showIndeterminateProgress(position == mConnectingPosition);
|
||||
viewHolder.device = device;
|
||||
viewHolder.name.setText(TextUtils.isEmpty(device.getName()) ? notAvailable : device.getName());
|
||||
viewHolder.address.setText(getState(device, position));
|
||||
viewHolder.icon.showIndeterminateProgress(position == connectingPosition);
|
||||
} else {
|
||||
viewHolder.mDevice = null;
|
||||
viewHolder.mName.setText(mScanning ? R.string.devices_list_scanning : R.string.devices_list_start_scan);
|
||||
viewHolder.mAddress.setText(null);
|
||||
viewHolder.mIcon.showIndeterminateProgress(mScanning);
|
||||
viewHolder.device = null;
|
||||
viewHolder.name.setText(scanning ? R.string.devices_list_scanning : R.string.devices_list_start_scan);
|
||||
viewHolder.address.setText(null);
|
||||
viewHolder.icon.showIndeterminateProgress(scanning);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mDevices.size() + (mConnectingPosition == -1 ? 1 : 0);
|
||||
return devices.size() + (connectingPosition == -1 ? 1 : 0);
|
||||
}
|
||||
|
||||
public void setConnectingPosition(final int connectingPosition) {
|
||||
final int oldPosition = mConnectingPosition;
|
||||
this.mConnectingPosition = connectingPosition;
|
||||
final int oldPosition = connectingPosition;
|
||||
this.connectingPosition = connectingPosition;
|
||||
if (connectingPosition >= 0) {
|
||||
// The "Scan for nearby device' item is removed
|
||||
notifyItemChanged(connectingPosition);
|
||||
notifyItemRemoved(mDevices.size());
|
||||
notifyItemRemoved(devices.size());
|
||||
} else {
|
||||
if (oldPosition >= 0)
|
||||
notifyItemChanged(oldPosition);
|
||||
notifyItemInserted(mDevices.size());
|
||||
notifyItemInserted(devices.size());
|
||||
}
|
||||
}
|
||||
|
||||
public void startLeScan() {
|
||||
// Scanning is disabled when we are connecting or connected.
|
||||
if (mConnectingPosition >= 0)
|
||||
if (connectingPosition >= 0)
|
||||
return;
|
||||
|
||||
if (mScanning) {
|
||||
if (scanning) {
|
||||
// Extend scanning for some time more
|
||||
mHandler.removeCallbacks(mStopScanTask);
|
||||
mHandler.postDelayed(mStopScanTask, SCAN_DURATION);
|
||||
handler.removeCallbacks(stopScanTask);
|
||||
handler.postDelayed(stopScanTask, SCAN_DURATION);
|
||||
return;
|
||||
}
|
||||
|
||||
final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
|
||||
final ScanSettings settings = new ScanSettings.Builder().setReportDelay(1000).setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
|
||||
scanner.startScan(null, settings, mScanCallback);
|
||||
scanner.startScan(null, settings, scanCallback);
|
||||
|
||||
// Setup timer that will stop scanning
|
||||
mHandler.postDelayed(mStopScanTask, SCAN_DURATION);
|
||||
mScanning = true;
|
||||
notifyItemChanged(mDevices.size());
|
||||
handler.postDelayed(stopScanTask, SCAN_DURATION);
|
||||
scanning = true;
|
||||
notifyItemChanged(devices.size());
|
||||
}
|
||||
|
||||
public void stopLeScan() {
|
||||
if (!mScanning)
|
||||
if (!scanning)
|
||||
return;
|
||||
|
||||
final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
|
||||
scanner.stopScan(mScanCallback);
|
||||
scanner.stopScan(scanCallback);
|
||||
|
||||
mHandler.removeCallbacks(mStopScanTask);
|
||||
mScanning = false;
|
||||
notifyItemChanged(mDevices.size());
|
||||
handler.removeCallbacks(stopScanTask);
|
||||
scanning = false;
|
||||
notifyItemChanged(devices.size());
|
||||
}
|
||||
|
||||
private String getState(final BluetoothDevice device, final int position) {
|
||||
if (mConnectingPosition == position)
|
||||
return mConnectingText;
|
||||
if (connectingPosition == position)
|
||||
return connectingText;
|
||||
else if (device.getBondState() == BluetoothDevice.BOND_BONDED)
|
||||
return mBondedText;
|
||||
return bondedText;
|
||||
else if (device.getBondState() == BluetoothDevice.BOND_BONDING)
|
||||
return mBondingText;
|
||||
return mAvailableText;
|
||||
return bondingText;
|
||||
return availableText;
|
||||
}
|
||||
|
||||
private Runnable mStopScanTask = this::stopLeScan;
|
||||
private Runnable stopScanTask = this::stopLeScan;
|
||||
|
||||
private ScanCallback mScanCallback = new ScanCallback() {
|
||||
private ScanCallback scanCallback = new ScanCallback() {
|
||||
@Override
|
||||
public void onScanResult(final int callbackType, @NonNull final ScanResult result) {
|
||||
// empty
|
||||
@@ -176,16 +176,16 @@ public class DevicesAdapter extends WearableListView.Adapter {
|
||||
|
||||
@Override
|
||||
public void onBatchScanResults(final List<ScanResult> results) {
|
||||
final int size = mDevices.size();
|
||||
final int size = devices.size();
|
||||
for (final ScanResult result : results) {
|
||||
final BluetoothDevice device = result.getDevice();
|
||||
if (!mDevices.contains(device))
|
||||
mDevices.add(device);
|
||||
if (!devices.contains(device))
|
||||
devices.add(device);
|
||||
}
|
||||
if (size != mDevices.size()) {
|
||||
notifyItemRangeInserted(size, mDevices.size() - size);
|
||||
if (size != devices.size()) {
|
||||
notifyItemRangeInserted(size, devices.size() - size);
|
||||
if (size == 0)
|
||||
mListView.scrollToPosition(0);
|
||||
listView.scrollToPosition(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,22 +196,22 @@ public class DevicesAdapter extends WearableListView.Adapter {
|
||||
};
|
||||
|
||||
public static class ItemViewHolder extends WearableListView.ViewHolder {
|
||||
private CircledImageView mIcon;
|
||||
private TextView mName;
|
||||
private TextView mAddress;
|
||||
private BluetoothDevice mDevice;
|
||||
private CircledImageView icon;
|
||||
private TextView name;
|
||||
private TextView address;
|
||||
private BluetoothDevice device;
|
||||
|
||||
public ItemViewHolder(final View itemView) {
|
||||
super(itemView);
|
||||
|
||||
mIcon = itemView.findViewById(R.id.icon);
|
||||
mName = itemView.findViewById(R.id.name);
|
||||
mAddress = itemView.findViewById(R.id.state);
|
||||
icon = itemView.findViewById(R.id.icon);
|
||||
name = itemView.findViewById(R.id.name);
|
||||
address = itemView.findViewById(R.id.state);
|
||||
}
|
||||
|
||||
/** Returns the Bluetooth device for that holder, or null for "Scanning for nearby devices" row. */
|
||||
public BluetoothDevice getDevice() {
|
||||
return mDevice;
|
||||
return device;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,10 +45,10 @@ public class ScannerActivity extends Activity {
|
||||
|
||||
private static final int PERMISSION_REQUEST_LOCATION = 1;
|
||||
|
||||
private DevicesAdapter mDeviceAdapter;
|
||||
private View mHeader;
|
||||
private DevicesAdapter deviceAdapter;
|
||||
private View header;
|
||||
|
||||
private BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
|
||||
private BroadcastReceiver serviceBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
@@ -57,7 +57,7 @@ public class ScannerActivity extends Activity {
|
||||
case BleProfileService.BROADCAST_CONNECTION_STATE: {
|
||||
final int state = intent.getIntExtra(BleProfileService.EXTRA_CONNECTION_STATE, BleProfileService.STATE_DISCONNECTED);
|
||||
if (state == BleProfileService.STATE_DISCONNECTED)
|
||||
mDeviceAdapter.setConnectingPosition(-1);
|
||||
deviceAdapter.setConnectingPosition(-1);
|
||||
break;
|
||||
}
|
||||
case BleProfileService.BROADCAST_DEVICE_READY: {
|
||||
@@ -68,7 +68,7 @@ public class ScannerActivity extends Activity {
|
||||
}
|
||||
case BleProfileService.BROADCAST_DEVICE_NOT_SUPPORTED: {
|
||||
Toast.makeText(ScannerActivity.this, R.string.devices_list_device_not_supported, Toast.LENGTH_SHORT).show();
|
||||
mDeviceAdapter.setConnectingPosition(-1);
|
||||
deviceAdapter.setConnectingPosition(-1);
|
||||
break;
|
||||
}
|
||||
case BleProfileService.BROADCAST_ERROR: {
|
||||
@@ -79,7 +79,7 @@ public class ScannerActivity extends Activity {
|
||||
break;
|
||||
}
|
||||
case BleProfileService.BROADCAST_BOND_STATE: {
|
||||
mDeviceAdapter.notifyDataSetChanged(); // TODO check this. Bonding was never tested.
|
||||
deviceAdapter.notifyDataSetChanged(); // TODO check this. Bonding was never tested.
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -93,21 +93,21 @@ public class ScannerActivity extends Activity {
|
||||
|
||||
// Get the list component from the layout of the activity
|
||||
final WearableListView listView = findViewById(R.id.devices_list);
|
||||
listView.setAdapter(mDeviceAdapter = new DevicesAdapter(listView));
|
||||
listView.setClickListener(mOnRowClickListener);
|
||||
listView.addOnScrollListener(mOnScrollListener);
|
||||
listView.setAdapter(deviceAdapter = new DevicesAdapter(listView));
|
||||
listView.setClickListener(onRowClickListener);
|
||||
listView.addOnScrollListener(onScrollListener);
|
||||
|
||||
// The header will be moved as the list is scrolled
|
||||
mHeader = findViewById(R.id.header);
|
||||
header = findViewById(R.id.header);
|
||||
|
||||
// Register a broadcast receiver that will listen for events from the service.
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mServiceBroadcastReceiver, BleProfileService.makeIntentFilter());
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(serviceBroadcastReceiver, BleProfileService.makeIntentFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mServiceBroadcastReceiver);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(serviceBroadcastReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,7 +115,7 @@ public class ScannerActivity extends Activity {
|
||||
switch (requestCode) {
|
||||
case PERMISSION_REQUEST_LOCATION:
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
mDeviceAdapter.startLeScan();
|
||||
deviceAdapter.startLeScan();
|
||||
} else {
|
||||
Toast.makeText(ScannerActivity.this, "Location permission required", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
@@ -134,32 +134,32 @@ public class ScannerActivity extends Activity {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mDeviceAdapter.startLeScan();
|
||||
deviceAdapter.startLeScan();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mDeviceAdapter.stopLeScan();
|
||||
deviceAdapter.stopLeScan();
|
||||
}
|
||||
|
||||
/** List click listener. */
|
||||
private WearableListView.ClickListener mOnRowClickListener = new WearableListView.ClickListener() {
|
||||
private WearableListView.ClickListener onRowClickListener = new WearableListView.ClickListener() {
|
||||
@Override
|
||||
public void onClick(final WearableListView.ViewHolder holder) {
|
||||
final DevicesAdapter.ItemViewHolder viewHolder = (DevicesAdapter.ItemViewHolder) holder;
|
||||
final BluetoothDevice device = viewHolder.getDevice();
|
||||
|
||||
if (device != null) {
|
||||
mDeviceAdapter.stopLeScan();
|
||||
mDeviceAdapter.setConnectingPosition(holder.getAdapterPosition());
|
||||
deviceAdapter.stopLeScan();
|
||||
deviceAdapter.setConnectingPosition(holder.getAdapterPosition());
|
||||
|
||||
// Start the service that will connect to selected device
|
||||
final Intent service = new Intent(ScannerActivity.this, BleProfileService.class);
|
||||
service.putExtra(BleProfileService.EXTRA_DEVICE_ADDRESS, device.getAddress());
|
||||
startService(service);
|
||||
} else {
|
||||
mDeviceAdapter.startLeScan();
|
||||
deviceAdapter.startLeScan();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,13 +170,13 @@ public class ScannerActivity extends Activity {
|
||||
};
|
||||
|
||||
/** The following code ensures that the title scrolls as the user scrolls up or down the list/ */
|
||||
private WearableListView.OnScrollListener mOnScrollListener = new WearableListView.OnScrollListener() {
|
||||
private WearableListView.OnScrollListener onScrollListener = new WearableListView.OnScrollListener() {
|
||||
@Override
|
||||
public void onAbsoluteScrollChange(final int i) {
|
||||
if (i > 0)
|
||||
mHeader.setY(-i);
|
||||
header.setY(-i);
|
||||
else
|
||||
mHeader.setY(0);
|
||||
header.setY(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -76,37 +76,37 @@ public class BleManager implements BleProfileApi {
|
||||
private final static UUID GENERIC_ATTRIBUTE_SERVICE = UUID.fromString("00001801-0000-1000-8000-00805f9b34fb");
|
||||
private final static UUID SERVICE_CHANGED_CHARACTERISTIC = UUID.fromString("00002A05-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private final Object lock = new Object();
|
||||
|
||||
protected final BleManagerCallbacks mCallbacks;
|
||||
private final Context mContext;
|
||||
private final Handler mHandler;
|
||||
protected BluetoothDevice mBluetoothDevice;
|
||||
protected BleProfile mProfile;
|
||||
private BluetoothGatt mBluetoothGatt;
|
||||
private BleManagerGattCallback mGattCallback;
|
||||
protected final BleManagerCallbacks callbacks;
|
||||
private final Context context;
|
||||
private final Handler handler;
|
||||
protected BluetoothDevice bluetoothDevice;
|
||||
protected BleProfile profile;
|
||||
private BluetoothGatt bluetoothGatt;
|
||||
private BleManagerGattCallback gattCallback;
|
||||
/**
|
||||
* This flag is set to false only when the {@link #shouldAutoConnect()} method returns true and the device got disconnected without calling {@link #disconnect()} method.
|
||||
* If {@link #shouldAutoConnect()} returns false (default) this is always set to true.
|
||||
*/
|
||||
private boolean mUserDisconnected;
|
||||
private boolean userDisconnected;
|
||||
/**
|
||||
* Flag set to true when {@link #shouldAutoConnect()} method returned <code>true</code>. The first connection attempt is done with <code>autoConnect</code>
|
||||
* flag set to false (to make the first connection quick) but on connection lost the manager will call {@link #connect(BluetoothDevice)} again.
|
||||
* This time this method will call {@link BluetoothGatt#connect()} which always uses <code>autoConnect</code> equal true.
|
||||
*/
|
||||
private boolean mInitialConnection;
|
||||
private boolean initialConnection;
|
||||
/** Flag set to true when the device is connected. */
|
||||
private boolean mConnected;
|
||||
private int mConnectionState = BluetoothGatt.STATE_DISCONNECTED;
|
||||
private boolean connected;
|
||||
private int connectionState = BluetoothGatt.STATE_DISCONNECTED;
|
||||
/** Last received battery value or -1 if value wasn't received. */
|
||||
private int mBatteryValue = -1;
|
||||
private int batteryValue = -1;
|
||||
/**
|
||||
* The current MTU (Maximum Transfer Unit). The maximum number of bytes that can be sent in a single packet is MTU-3.
|
||||
*/
|
||||
private int mMtu = 23;
|
||||
private int mtu = 23;
|
||||
|
||||
private final BroadcastReceiver mBluetoothStateBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver bluetoothStateBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
|
||||
@@ -115,9 +115,9 @@ public class BleManager implements BleProfileApi {
|
||||
switch (state) {
|
||||
case BluetoothAdapter.STATE_TURNING_OFF:
|
||||
case BluetoothAdapter.STATE_OFF:
|
||||
if (mConnected && previousState != BluetoothAdapter.STATE_TURNING_OFF && previousState != BluetoothAdapter.STATE_OFF) {
|
||||
if (connected && previousState != BluetoothAdapter.STATE_TURNING_OFF && previousState != BluetoothAdapter.STATE_OFF) {
|
||||
// The connection is killed by the system, no need to gently disconnect
|
||||
mGattCallback.notifyDeviceDisconnected(mBluetoothDevice);
|
||||
gattCallback.notifyDeviceDisconnected(bluetoothDevice);
|
||||
}
|
||||
close();
|
||||
break;
|
||||
@@ -125,7 +125,7 @@ public class BleManager implements BleProfileApi {
|
||||
}
|
||||
};
|
||||
|
||||
private BroadcastReceiver mBondingBroadcastReceiver = new BroadcastReceiver() {
|
||||
private BroadcastReceiver bondingBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
@@ -133,40 +133,40 @@ public class BleManager implements BleProfileApi {
|
||||
final int previousBondState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1);
|
||||
|
||||
// Skip other devices
|
||||
if (mBluetoothGatt == null || !device.getAddress().equals(mBluetoothGatt.getDevice().getAddress()))
|
||||
if (bluetoothGatt == null || !device.getAddress().equals(bluetoothGatt.getDevice().getAddress()))
|
||||
return;
|
||||
|
||||
DebugLogger.i(TAG, "Bond state changed for: " + device.getName() + " new state: " + bondState + " previous: " + previousBondState);
|
||||
|
||||
switch (bondState) {
|
||||
case BluetoothDevice.BOND_BONDING:
|
||||
mCallbacks.onBondingRequired(device);
|
||||
callbacks.onBondingRequired(device);
|
||||
break;
|
||||
case BluetoothDevice.BOND_BONDED:
|
||||
mCallbacks.onBonded(device);
|
||||
callbacks.onBonded(device);
|
||||
|
||||
// Start initializing again.
|
||||
// In fact, bonding forces additional, internal service discovery (at least on Nexus devices), so this method may safely be used to start this process again.
|
||||
mBluetoothGatt.discoverServices();
|
||||
bluetoothGatt.discoverServices();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public BleManager(final Context context, final BleManagerCallbacks callbacks) {
|
||||
mCallbacks = callbacks;
|
||||
mContext = context;
|
||||
mHandler = new Handler();
|
||||
this.callbacks = callbacks;
|
||||
this.context = context;
|
||||
this.handler = new Handler();
|
||||
|
||||
// Register bonding broadcast receiver
|
||||
context.registerReceiver(mBondingBroadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
|
||||
context.registerReceiver(bondingBroadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Profile API. Profile may be null if service discovery has not been performed or the device does not match any profile.
|
||||
*/
|
||||
public BleProfile getProfile() {
|
||||
return mProfile;
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,7 +176,7 @@ public class BleManager implements BleProfileApi {
|
||||
*/
|
||||
@Override
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,11 +207,11 @@ public class BleManager implements BleProfileApi {
|
||||
* @param device a device to connect to
|
||||
*/
|
||||
public void connect(final BluetoothDevice device) {
|
||||
if (mConnected)
|
||||
if (connected)
|
||||
return;
|
||||
|
||||
synchronized (mLock) {
|
||||
if (mBluetoothGatt != null) {
|
||||
synchronized (lock) {
|
||||
if (bluetoothGatt != null) {
|
||||
// There are 2 ways of reconnecting to the same device:
|
||||
// 1. Reusing the same BluetoothGatt object and calling connect() - this will force the autoConnect flag to true
|
||||
// 2. Closing it and reopening a new instance of BluetoothGatt object.
|
||||
@@ -219,9 +219,9 @@ public class BleManager implements BleProfileApi {
|
||||
// device.connectGatt(...) can't be called immediately or service discovery
|
||||
// may never finish on some older devices (Nexus 4, Android 5.0.1).
|
||||
// If shouldAutoConnect() method returned false we can't call gatt.connect() and have to close gatt and open it again.
|
||||
if (!mInitialConnection) {
|
||||
mBluetoothGatt.close();
|
||||
mBluetoothGatt = null;
|
||||
if (!initialConnection) {
|
||||
bluetoothGatt.close();
|
||||
bluetoothGatt = null;
|
||||
try {
|
||||
Thread.sleep(200); // Is 200 ms enough?
|
||||
} catch (final InterruptedException e) {
|
||||
@@ -230,29 +230,29 @@ public class BleManager implements BleProfileApi {
|
||||
} else {
|
||||
// Instead, the gatt.connect() method will be used to reconnect to the same device.
|
||||
// This method forces autoConnect = true even if the gatt was created with this flag set to false.
|
||||
mInitialConnection = false;
|
||||
mConnectionState = BluetoothGatt.STATE_CONNECTING;
|
||||
mCallbacks.onDeviceConnecting(device);
|
||||
mBluetoothGatt.connect();
|
||||
initialConnection = false;
|
||||
connectionState = BluetoothGatt.STATE_CONNECTING;
|
||||
callbacks.onDeviceConnecting(device);
|
||||
bluetoothGatt.connect();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Register bonding broadcast receiver
|
||||
mContext.registerReceiver(mBluetoothStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
|
||||
mContext.registerReceiver(mBondingBroadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
|
||||
context.registerReceiver(bluetoothStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
|
||||
context.registerReceiver(bondingBroadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
|
||||
}
|
||||
}
|
||||
|
||||
final boolean shouldAutoConnect = shouldAutoConnect();
|
||||
mUserDisconnected = !shouldAutoConnect; // We will receive Linkloss events only when the device is connected with autoConnect=true
|
||||
userDisconnected = !shouldAutoConnect; // We will receive Linkloss events only when the device is connected with autoConnect=true
|
||||
// The first connection will always be done with autoConnect = false to make the connection quick.
|
||||
// If the shouldAutoConnect() method returned true, the manager will automatically try to reconnect to this device on link loss.
|
||||
if (shouldAutoConnect)
|
||||
mInitialConnection = true;
|
||||
mBluetoothDevice = device;
|
||||
mConnectionState = BluetoothGatt.STATE_CONNECTING;
|
||||
mCallbacks.onDeviceConnecting(device);
|
||||
mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback = new BleManagerGattCallback());
|
||||
initialConnection = true;
|
||||
bluetoothDevice = device;
|
||||
connectionState = BluetoothGatt.STATE_CONNECTING;
|
||||
callbacks.onDeviceConnecting(device);
|
||||
bluetoothGatt = device.connectGatt(context, false, gattCallback = new BleManagerGattCallback());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,19 +260,19 @@ public class BleManager implements BleProfileApi {
|
||||
* @return true if device is to be disconnected. False if it was already disconnected.
|
||||
*/
|
||||
public boolean disconnect() {
|
||||
mUserDisconnected = true;
|
||||
mInitialConnection = false;
|
||||
userDisconnected = true;
|
||||
initialConnection = false;
|
||||
|
||||
if (mBluetoothGatt != null) {
|
||||
mConnectionState = BluetoothGatt.STATE_DISCONNECTING;
|
||||
mCallbacks.onDeviceDisconnecting(mBluetoothGatt.getDevice());
|
||||
final boolean wasConnected = mConnected;
|
||||
mBluetoothGatt.disconnect();
|
||||
if (bluetoothGatt != null) {
|
||||
connectionState = BluetoothGatt.STATE_DISCONNECTING;
|
||||
callbacks.onDeviceDisconnecting(bluetoothGatt.getDevice());
|
||||
final boolean wasConnected = connected;
|
||||
bluetoothGatt.disconnect();
|
||||
|
||||
if (!wasConnected) {
|
||||
// There will be no callback, the connection attempt will be stopped
|
||||
mConnectionState = BluetoothGatt.STATE_DISCONNECTED;
|
||||
mCallbacks.onDeviceDisconnected(mBluetoothGatt.getDevice());
|
||||
connectionState = BluetoothGatt.STATE_DISCONNECTED;
|
||||
callbacks.onDeviceDisconnected(bluetoothGatt.getDevice());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -283,7 +283,7 @@ public class BleManager implements BleProfileApi {
|
||||
* This method returns true if the device is connected. Services could have not been discovered yet.
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
return mConnected;
|
||||
return connected;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,7 +295,7 @@ public class BleManager implements BleProfileApi {
|
||||
* @return the connection state
|
||||
*/
|
||||
public int getConnectionState() {
|
||||
return mConnectionState;
|
||||
return connectionState;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,7 +303,7 @@ public class BleManager implements BleProfileApi {
|
||||
* @return the last battery level value in percent
|
||||
*/
|
||||
public int getBatteryValue() {
|
||||
return mBatteryValue;
|
||||
return batteryValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,21 +311,21 @@ public class BleManager implements BleProfileApi {
|
||||
*/
|
||||
public void close() {
|
||||
try {
|
||||
mContext.unregisterReceiver(mBluetoothStateBroadcastReceiver);
|
||||
mContext.unregisterReceiver(mBondingBroadcastReceiver);
|
||||
context.unregisterReceiver(bluetoothStateBroadcastReceiver);
|
||||
context.unregisterReceiver(bondingBroadcastReceiver);
|
||||
} catch (Exception e) {
|
||||
// the receiver must have been not registered or unregistered before
|
||||
}
|
||||
synchronized (mLock) {
|
||||
if (mBluetoothGatt != null) {
|
||||
mBluetoothGatt.close();
|
||||
mBluetoothGatt = null;
|
||||
synchronized (lock) {
|
||||
if (bluetoothGatt != null) {
|
||||
bluetoothGatt.close();
|
||||
bluetoothGatt = null;
|
||||
}
|
||||
mConnected = false;
|
||||
mInitialConnection = false;
|
||||
mConnectionState = BluetoothGatt.STATE_DISCONNECTED;
|
||||
mGattCallback = null;
|
||||
mBluetoothDevice = null;
|
||||
connected = false;
|
||||
initialConnection = false;
|
||||
connectionState = BluetoothGatt.STATE_DISCONNECTED;
|
||||
gattCallback = null;
|
||||
bluetoothDevice = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,7 +341,7 @@ public class BleManager implements BleProfileApi {
|
||||
* @return true if pairing has started, false if it was already paired or an immediate error occur.
|
||||
*/
|
||||
private boolean internalCreateBond() {
|
||||
final BluetoothDevice device = mBluetoothDevice;
|
||||
final BluetoothDevice device = bluetoothDevice;
|
||||
if (device == null)
|
||||
return false;
|
||||
|
||||
@@ -359,7 +359,7 @@ public class BleManager implements BleProfileApi {
|
||||
* the Service Changed characteristic or this characteristic does not have the CCCD.
|
||||
*/
|
||||
private boolean ensureServiceChangedEnabled() {
|
||||
final BluetoothGatt gatt = mBluetoothGatt;
|
||||
final BluetoothGatt gatt = bluetoothGatt;
|
||||
if (gatt == null)
|
||||
return false;
|
||||
|
||||
@@ -385,7 +385,7 @@ public class BleManager implements BleProfileApi {
|
||||
}
|
||||
|
||||
private boolean internalEnableNotifications(final BluetoothGattCharacteristic characteristic) {
|
||||
final BluetoothGatt gatt = mBluetoothGatt;
|
||||
final BluetoothGatt gatt = bluetoothGatt;
|
||||
if (gatt == null || characteristic == null)
|
||||
return false;
|
||||
|
||||
@@ -409,7 +409,7 @@ public class BleManager implements BleProfileApi {
|
||||
}
|
||||
|
||||
private boolean internalEnableIndications(final BluetoothGattCharacteristic characteristic) {
|
||||
final BluetoothGatt gatt = mBluetoothGatt;
|
||||
final BluetoothGatt gatt = bluetoothGatt;
|
||||
if (gatt == null || characteristic == null)
|
||||
return false;
|
||||
|
||||
@@ -433,7 +433,7 @@ public class BleManager implements BleProfileApi {
|
||||
}
|
||||
|
||||
private boolean internalReadCharacteristic(final BluetoothGattCharacteristic characteristic) {
|
||||
final BluetoothGatt gatt = mBluetoothGatt;
|
||||
final BluetoothGatt gatt = bluetoothGatt;
|
||||
if (gatt == null || characteristic == null)
|
||||
return false;
|
||||
|
||||
@@ -451,7 +451,7 @@ public class BleManager implements BleProfileApi {
|
||||
}
|
||||
|
||||
private boolean internalWriteCharacteristic(final BluetoothGattCharacteristic characteristic) {
|
||||
final BluetoothGatt gatt = mBluetoothGatt;
|
||||
final BluetoothGatt gatt = bluetoothGatt;
|
||||
if (gatt == null || characteristic == null)
|
||||
return false;
|
||||
|
||||
@@ -469,7 +469,7 @@ public class BleManager implements BleProfileApi {
|
||||
}
|
||||
|
||||
private boolean internalReadDescriptor(final BluetoothGattDescriptor descriptor) {
|
||||
final BluetoothGatt gatt = mBluetoothGatt;
|
||||
final BluetoothGatt gatt = bluetoothGatt;
|
||||
if (gatt == null || descriptor == null)
|
||||
return false;
|
||||
|
||||
@@ -482,7 +482,7 @@ public class BleManager implements BleProfileApi {
|
||||
}
|
||||
|
||||
private boolean internalWriteDescriptor(final BluetoothGattDescriptor descriptor) {
|
||||
final BluetoothGatt gatt = mBluetoothGatt;
|
||||
final BluetoothGatt gatt = bluetoothGatt;
|
||||
if (gatt == null || descriptor == null)
|
||||
return false;
|
||||
|
||||
@@ -495,7 +495,7 @@ public class BleManager implements BleProfileApi {
|
||||
}
|
||||
|
||||
private boolean internalReadBatteryLevel() {
|
||||
final BluetoothGatt gatt = mBluetoothGatt;
|
||||
final BluetoothGatt gatt = bluetoothGatt;
|
||||
if (gatt == null)
|
||||
return false;
|
||||
|
||||
@@ -524,7 +524,7 @@ public class BleManager implements BleProfileApi {
|
||||
}
|
||||
|
||||
private boolean internalSetBatteryNotifications(final boolean enable) {
|
||||
final BluetoothGatt gatt = mBluetoothGatt;
|
||||
final BluetoothGatt gatt = bluetoothGatt;
|
||||
if (gatt == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -566,7 +566,7 @@ public class BleManager implements BleProfileApi {
|
||||
* @return the result of {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor)}
|
||||
*/
|
||||
private boolean internalWriteDescriptorWorkaround(final BluetoothGattDescriptor descriptor) {
|
||||
final BluetoothGatt gatt = mBluetoothGatt;
|
||||
final BluetoothGatt gatt = bluetoothGatt;
|
||||
if (gatt == null || descriptor == null)
|
||||
return false;
|
||||
|
||||
@@ -585,18 +585,19 @@ public class BleManager implements BleProfileApi {
|
||||
|
||||
@Override
|
||||
public final int getMtu() {
|
||||
return mMtu;
|
||||
return mtu;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void overrideMtu(final int mtu) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
||||
mMtu = mtu;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
BleManager.this.mtu = mtu;
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
private boolean internalRequestMtu(final int mtu) {
|
||||
final BluetoothGatt gatt = mBluetoothGatt;
|
||||
final BluetoothGatt gatt = bluetoothGatt;
|
||||
if (gatt == null)
|
||||
return false;
|
||||
|
||||
@@ -605,12 +606,13 @@ public class BleManager implements BleProfileApi {
|
||||
|
||||
@Override
|
||||
public final boolean requestConnectionPriority(final int priority) {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && enqueue(Request.newConnectionPriorityRequest(priority));
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
||||
&& enqueue(Request.newConnectionPriorityRequest(priority));
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
private boolean internalRequestConnectionPriority(final int priority) {
|
||||
final BluetoothGatt gatt = mBluetoothGatt;
|
||||
final BluetoothGatt gatt = bluetoothGatt;
|
||||
if (gatt == null)
|
||||
return false;
|
||||
|
||||
@@ -619,10 +621,10 @@ public class BleManager implements BleProfileApi {
|
||||
|
||||
@Override
|
||||
public boolean enqueue(final Request request) {
|
||||
if (mGattCallback != null) {
|
||||
if (gattCallback != null) {
|
||||
// Add the new task to the end of the queue
|
||||
mGattCallback.mTaskQueue.add(request);
|
||||
mGattCallback.nextRequest();
|
||||
gattCallback.taskQueue.add(request);
|
||||
gattCallback.nextRequest();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -639,10 +641,10 @@ public class BleManager implements BleProfileApi {
|
||||
private final static String ERROR_MTU_REQUEST = "Error on mtu request";
|
||||
private final static String ERROR_CONNECTION_PRIORITY_REQUEST = "Error on connection priority request";
|
||||
|
||||
private final Queue<Request> mTaskQueue = new LinkedList<>();
|
||||
private Deque<Request> mInitQueue;
|
||||
private boolean mInitInProgress;
|
||||
private boolean mOperationInProgress = true;
|
||||
private final Queue<Request> taskQueue = new LinkedList<>();
|
||||
private Deque<Request> initQueue;
|
||||
private boolean initInProgress;
|
||||
private boolean operationInProgress = true;
|
||||
/**
|
||||
* This flag is required to resume operations after the connection priority request was made.
|
||||
* It is used only on Android Oreo and newer, as only there there is onConnectionUpdated callback.
|
||||
@@ -650,36 +652,36 @@ public class BleManager implements BleProfileApi {
|
||||
* when such request wasn't made, this flag ensures the nextRequest() method won't be called
|
||||
* during another operation.
|
||||
*/
|
||||
private boolean mConnectionPriorityOperationInProgress = false;
|
||||
private boolean connectionPriorityOperationInProgress = false;
|
||||
|
||||
private void notifyDeviceDisconnected(final BluetoothDevice device) {
|
||||
mConnected = false;
|
||||
mConnectionState = BluetoothGatt.STATE_DISCONNECTED;
|
||||
if (mUserDisconnected) {
|
||||
mCallbacks.onDeviceDisconnected(device);
|
||||
connected = false;
|
||||
connectionState = BluetoothGatt.STATE_DISCONNECTED;
|
||||
if (userDisconnected) {
|
||||
callbacks.onDeviceDisconnected(device);
|
||||
close();
|
||||
} else {
|
||||
mCallbacks.onLinklossOccurred(device);
|
||||
callbacks.onLinklossOccurred(device);
|
||||
// We are not closing the connection here as the device should try to reconnect automatically.
|
||||
// This may be only called when the shouldAutoConnect() method returned true.
|
||||
}
|
||||
if (mProfile != null)
|
||||
mProfile.release();
|
||||
if (profile != null)
|
||||
profile.release();
|
||||
}
|
||||
|
||||
private void onError(final BluetoothDevice device, final String message, final int errorCode) {
|
||||
mCallbacks.onError(device, message, errorCode);
|
||||
if (mProfile != null)
|
||||
mProfile.onError(message, errorCode);
|
||||
callbacks.onError(device, message, errorCode);
|
||||
if (profile != null)
|
||||
profile.onError(message, errorCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) {
|
||||
if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
// Notify the parent activity/service
|
||||
mConnected = true;
|
||||
mConnectionState = BluetoothGatt.STATE_CONNECTED;
|
||||
mCallbacks.onDeviceConnected(gatt.getDevice());
|
||||
connected = true;
|
||||
connectionState = BluetoothGatt.STATE_CONNECTED;
|
||||
callbacks.onDeviceConnected(gatt.getDevice());
|
||||
|
||||
/*
|
||||
* The onConnectionStateChange event is triggered just after the Android connects to a device.
|
||||
@@ -699,7 +701,7 @@ public class BleManager implements BleProfileApi {
|
||||
*/
|
||||
final boolean bonded = gatt.getDevice().getBondState() == BluetoothDevice.BOND_BONDED;
|
||||
final int delay = bonded ? 1600 : 0; // around 1600 ms is required when connection interval is ~45ms.
|
||||
mHandler.postDelayed(() -> {
|
||||
handler.postDelayed(() -> {
|
||||
// Some proximity tags (e.g. nRF PROXIMITY) initialize bonding automatically when connected.
|
||||
if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_BONDING) {
|
||||
gatt.discoverServices();
|
||||
@@ -707,16 +709,16 @@ public class BleManager implements BleProfileApi {
|
||||
}, delay);
|
||||
} else {
|
||||
if (newState == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
mOperationInProgress = true; // no more calls are possible
|
||||
mInitQueue = null;
|
||||
mTaskQueue.clear();
|
||||
final boolean wasConnected = mConnected;
|
||||
// if (mConnected) { // Checking mConnected prevents from calling onDeviceDisconnected if connection attempt failed. This check is not necessary
|
||||
notifyDeviceDisconnected(gatt.getDevice()); // This sets the mConnected flag to false
|
||||
operationInProgress = true; // no more calls are possible
|
||||
initQueue = null;
|
||||
taskQueue.clear();
|
||||
final boolean wasConnected = connected;
|
||||
// if (connected) { // Checking connected prevents from calling onDeviceDisconnected if connection attempt failed. This check is not necessary
|
||||
notifyDeviceDisconnected(gatt.getDevice()); // This sets the connected flag to false
|
||||
// }
|
||||
// Try to reconnect if the initial connection was lost because of a link loss or timeout, and shouldAutoConnect() returned true during connection attempt.
|
||||
// This time it will set the autoConnect flag to true (gatt.connect() forces autoConnect true)
|
||||
if (mInitialConnection) {
|
||||
if (initialConnection) {
|
||||
connect(gatt.getDevice());
|
||||
}
|
||||
|
||||
@@ -725,7 +727,7 @@ public class BleManager implements BleProfileApi {
|
||||
}
|
||||
|
||||
// TODO Should the disconnect method be called or the connection is still valid? Does this ever happen?
|
||||
mProfile.onError(ERROR_CONNECTION_STATE_CHANGE, status);
|
||||
profile.onError(ERROR_CONNECTION_STATE_CHANGE, status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,31 +737,31 @@ public class BleManager implements BleProfileApi {
|
||||
final BleProfile profile = BleProfileProvider.findProfile(gatt);
|
||||
if (profile != null) {
|
||||
profile.setApi(BleManager.this);
|
||||
mProfile = profile;
|
||||
BleManager.this.profile = profile;
|
||||
|
||||
// Obtain the queue of initialization requests
|
||||
mInitInProgress = true;
|
||||
mInitQueue = profile.initGatt(gatt);
|
||||
initInProgress = true;
|
||||
initQueue = profile.initGatt(gatt);
|
||||
|
||||
// Before we start executing the initialization queue some other tasks need to be done.
|
||||
if (mInitQueue == null)
|
||||
mInitQueue = new LinkedList<>();
|
||||
if (initQueue == null)
|
||||
initQueue = new LinkedList<>();
|
||||
|
||||
// Note, that operations are added in reverse order to the front of the queue.
|
||||
|
||||
// 3. Enable Battery Level notifications if required (if this char. does not exist, this operation will be skipped)
|
||||
if (mCallbacks.shouldEnableBatteryLevelNotifications(gatt.getDevice()))
|
||||
mInitQueue.addFirst(Request.newEnableBatteryLevelNotificationsRequest());
|
||||
if (callbacks.shouldEnableBatteryLevelNotifications(gatt.getDevice()))
|
||||
initQueue.addFirst(Request.newEnableBatteryLevelNotificationsRequest());
|
||||
// 2. Read Battery Level characteristic (if such does not exist, this will be skipped)
|
||||
mInitQueue.addFirst(Request.newReadBatteryLevelRequest());
|
||||
initQueue.addFirst(Request.newReadBatteryLevelRequest());
|
||||
// 1. On devices running Android 4.3-6.0 the Service Changed characteristic needs to be enabled by the app (for bonded devices)
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
|
||||
mInitQueue.addFirst(Request.newEnableServiceChangedIndicationsRequest());
|
||||
initQueue.addFirst(Request.newEnableServiceChangedIndicationsRequest());
|
||||
|
||||
mOperationInProgress = false;
|
||||
operationInProgress = false;
|
||||
nextRequest();
|
||||
} else {
|
||||
mCallbacks.onDeviceNotSupported(gatt.getDevice());
|
||||
callbacks.onDeviceNotSupported(gatt.getDevice());
|
||||
disconnect();
|
||||
}
|
||||
} else {
|
||||
@@ -773,13 +775,13 @@ public class BleManager implements BleProfileApi {
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
if (isBatteryLevelCharacteristic(characteristic)) {
|
||||
final int batteryValue = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
|
||||
mBatteryValue = batteryValue;
|
||||
mProfile.onBatteryValueReceived(gatt, batteryValue);
|
||||
BleManager.this.batteryValue = batteryValue;
|
||||
profile.onBatteryValueReceived(gatt, batteryValue);
|
||||
} else {
|
||||
// The value has been read. Notify the profile and proceed with the initialization queue.
|
||||
mProfile.onCharacteristicRead(gatt, characteristic);
|
||||
profile.onCharacteristicRead(gatt, characteristic);
|
||||
}
|
||||
mOperationInProgress = false;
|
||||
operationInProgress = false;
|
||||
nextRequest();
|
||||
} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
|
||||
if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) {
|
||||
@@ -797,8 +799,8 @@ public class BleManager implements BleProfileApi {
|
||||
public final void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final int status) {
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
// The value has been written. Notify the profile and proceed with the initialization queue.
|
||||
mProfile.onCharacteristicWrite(gatt, characteristic);
|
||||
mOperationInProgress = false;
|
||||
profile.onCharacteristicWrite(gatt, characteristic);
|
||||
operationInProgress = false;
|
||||
nextRequest();
|
||||
} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
|
||||
if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) {
|
||||
@@ -816,8 +818,8 @@ public class BleManager implements BleProfileApi {
|
||||
public void onDescriptorRead(final BluetoothGatt gatt, final BluetoothGattDescriptor descriptor, final int status) {
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
// The value has been read. Notify the profile and proceed with the initialization queue.
|
||||
mProfile.onDescriptorRead(gatt, descriptor);
|
||||
mOperationInProgress = false;
|
||||
profile.onDescriptorRead(gatt, descriptor);
|
||||
operationInProgress = false;
|
||||
nextRequest();
|
||||
} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
|
||||
if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) {
|
||||
@@ -835,8 +837,8 @@ public class BleManager implements BleProfileApi {
|
||||
public final void onDescriptorWrite(final BluetoothGatt gatt, final BluetoothGattDescriptor descriptor, final int status) {
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
// The value has been written. Notify the profile and proceed with the initialization queue.
|
||||
mProfile.onDescriptorWrite(gatt, descriptor);
|
||||
mOperationInProgress = false;
|
||||
profile.onDescriptorWrite(gatt, descriptor);
|
||||
operationInProgress = false;
|
||||
nextRequest();
|
||||
} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
|
||||
if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) {
|
||||
@@ -854,16 +856,16 @@ public class BleManager implements BleProfileApi {
|
||||
public final void onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
if (isBatteryLevelCharacteristic(characteristic)) {
|
||||
final int batteryValue = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
|
||||
mBatteryValue = batteryValue;
|
||||
mProfile.onBatteryValueReceived(gatt, batteryValue);
|
||||
BleManager.this.batteryValue = batteryValue;
|
||||
profile.onBatteryValueReceived(gatt, batteryValue);
|
||||
} else {
|
||||
final BluetoothGattDescriptor cccd = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID);
|
||||
final boolean notifications = cccd == null || cccd.getValue() == null || cccd.getValue().length != 2 || cccd.getValue()[0] == 0x01;
|
||||
|
||||
if (notifications) {
|
||||
mProfile.onCharacteristicNotified(gatt, characteristic);
|
||||
profile.onCharacteristicNotified(gatt, characteristic);
|
||||
} else { // indications
|
||||
mProfile.onCharacteristicIndicated(gatt, characteristic);
|
||||
profile.onCharacteristicIndicated(gatt, characteristic);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -871,12 +873,12 @@ public class BleManager implements BleProfileApi {
|
||||
@Override
|
||||
public void onMtuChanged(final BluetoothGatt gatt, final int mtu, final int status) {
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
mProfile.onMtuChanged(mtu);
|
||||
profile.onMtuChanged(mtu);
|
||||
} else {
|
||||
DebugLogger.e(TAG, "onMtuChanged error: " + status + ", mtu: " + mtu);
|
||||
onError(gatt.getDevice(), ERROR_MTU_REQUEST, status);
|
||||
}
|
||||
mOperationInProgress = false;
|
||||
operationInProgress = false;
|
||||
nextRequest();
|
||||
}
|
||||
|
||||
@@ -896,16 +898,16 @@ public class BleManager implements BleProfileApi {
|
||||
*/
|
||||
public void onConnectionUpdated(final BluetoothGatt gatt, final int interval, final int latency, final int timeout, final int status) {
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
mProfile.onConnectionUpdated(interval, latency, timeout);
|
||||
profile.onConnectionUpdated(interval, latency, timeout);
|
||||
} else if (status == 0x3b) { // HCI_ERR_UNACCEPT_CONN_INTERVAL
|
||||
DebugLogger.e(TAG, "onConnectionUpdated received status: Unacceptable connection interval, interval: " + interval + ", latency: " + latency + ", timeout: " + timeout);
|
||||
} else {
|
||||
DebugLogger.e(TAG, "onConnectionUpdated received status: " + status + ", interval: " + interval + ", latency: " + latency + ", timeout: " + timeout);
|
||||
mCallbacks.onError(gatt.getDevice(), ERROR_CONNECTION_PRIORITY_REQUEST, status);
|
||||
callbacks.onError(gatt.getDevice(), ERROR_CONNECTION_PRIORITY_REQUEST, status);
|
||||
}
|
||||
if (mConnectionPriorityOperationInProgress) {
|
||||
mConnectionPriorityOperationInProgress = false;
|
||||
mOperationInProgress = false;
|
||||
if (connectionPriorityOperationInProgress) {
|
||||
connectionPriorityOperationInProgress = false;
|
||||
operationInProgress = false;
|
||||
nextRequest();
|
||||
}
|
||||
}
|
||||
@@ -915,28 +917,28 @@ public class BleManager implements BleProfileApi {
|
||||
* the {@link BleManagerCallbacks#onDeviceReady(BluetoothDevice)} callback is called.
|
||||
*/
|
||||
private void nextRequest() {
|
||||
if (mOperationInProgress)
|
||||
if (operationInProgress)
|
||||
return;
|
||||
|
||||
// Get the first request from the init queue
|
||||
Request request = mInitQueue != null ? mInitQueue.poll() : null;
|
||||
Request request = initQueue != null ? initQueue.poll() : null;
|
||||
|
||||
// Are we done with initializing?
|
||||
if (request == null) {
|
||||
if (mInitInProgress) {
|
||||
mInitQueue = null; // release the queue
|
||||
mInitInProgress = false;
|
||||
mCallbacks.onDeviceReady(mBluetoothDevice);
|
||||
if (initInProgress) {
|
||||
initQueue = null; // release the queue
|
||||
initInProgress = false;
|
||||
callbacks.onDeviceReady(bluetoothDevice);
|
||||
}
|
||||
// If so, we can continue with the task queue
|
||||
request = mTaskQueue.poll();
|
||||
request = taskQueue.poll();
|
||||
if (request == null) {
|
||||
// Nothing to be done for now
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mOperationInProgress = true;
|
||||
operationInProgress = true;
|
||||
boolean result = false;
|
||||
switch (request.type) {
|
||||
case CREATE_BOND: {
|
||||
@@ -994,15 +996,15 @@ public class BleManager implements BleProfileApi {
|
||||
}
|
||||
case REQUEST_CONNECTION_PRIORITY: {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
mConnectionPriorityOperationInProgress = true;
|
||||
connectionPriorityOperationInProgress = true;
|
||||
result = internalRequestConnectionPriority(request.value);
|
||||
} else {
|
||||
result = internalRequestConnectionPriority(request.value);
|
||||
// There is no callback for requestConnectionPriority(...) before Android Oreo.\
|
||||
// Let's give it some time to finish as the request is an asynchronous operation.
|
||||
if (result) {
|
||||
mHandler.postDelayed(() -> {
|
||||
mOperationInProgress = false;
|
||||
handler.postDelayed(() -> {
|
||||
operationInProgress = false;
|
||||
nextRequest();
|
||||
}, 100);
|
||||
}
|
||||
@@ -1013,8 +1015,8 @@ public class BleManager implements BleProfileApi {
|
||||
// The result may be false if given characteristic or descriptor were not found on the device.
|
||||
// In that case, proceed with next operation and ignore the one that failed.
|
||||
if (!result) {
|
||||
mConnectionPriorityOperationInProgress = false;
|
||||
mOperationInProgress = false;
|
||||
connectionPriorityOperationInProgress = false;
|
||||
operationInProgress = false;
|
||||
nextRequest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,19 +32,19 @@ import android.os.Build;
|
||||
import java.util.Deque;
|
||||
|
||||
public abstract class BleProfile {
|
||||
private Context mContext;
|
||||
private BleProfileApi mApi;
|
||||
private Context context;
|
||||
private BleProfileApi api;
|
||||
|
||||
/* package */ void setApi(final BleProfileApi api) {
|
||||
this.mContext = api.getContext();
|
||||
this.mApi = api;
|
||||
this.context = api.getContext();
|
||||
this.api = api;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the BLE API for sending data to the remote device.
|
||||
*/
|
||||
public BleProfileApi getApi() {
|
||||
return mApi;
|
||||
return api;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +52,7 @@ public abstract class BleProfile {
|
||||
* @return the context
|
||||
*/
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -62,15 +62,15 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
public static final int STATE_CONNECTING = 2;
|
||||
public static final int STATE_DISCONNECTING = 3;
|
||||
|
||||
private BleManager mBleManager;
|
||||
private Handler mHandler;
|
||||
private BleManager bleManager;
|
||||
private Handler handler;
|
||||
|
||||
protected boolean mBound;
|
||||
private boolean mConnected;
|
||||
private BluetoothDevice mBluetoothDevice;
|
||||
private String mDeviceName;
|
||||
protected boolean bound;
|
||||
private boolean connected;
|
||||
private BluetoothDevice bluetoothDevice;
|
||||
private String deviceName;
|
||||
|
||||
private final BroadcastReceiver mBluetoothStateBroadcastReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver bluetoothStateBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
|
||||
@@ -92,13 +92,13 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
* Disconnects from the sensor.
|
||||
*/
|
||||
public void disconnect() {
|
||||
if (!mConnected) {
|
||||
mBleManager.close();
|
||||
onDeviceDisconnected(mBluetoothDevice);
|
||||
if (!connected) {
|
||||
bleManager.close();
|
||||
onDeviceDisconnected(bluetoothDevice);
|
||||
return;
|
||||
}
|
||||
|
||||
mBleManager.disconnect();
|
||||
bleManager.disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +107,7 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
* @return device address
|
||||
*/
|
||||
public final String getDeviceAddress() {
|
||||
return mBluetoothDevice.getAddress();
|
||||
return bluetoothDevice.getAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,7 +116,7 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
* @return the device name
|
||||
*/
|
||||
public final String getDeviceName() {
|
||||
return mDeviceName;
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,7 +125,7 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
* @return the Bluetooth device
|
||||
*/
|
||||
public final BluetoothDevice getBluetoothDevice() {
|
||||
return mBluetoothDevice;
|
||||
return bluetoothDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,14 +134,14 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
|
||||
*/
|
||||
public final boolean isConnected() {
|
||||
return mConnected;
|
||||
return connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Profile API. Profile may be null if service discovery has not been performed or the device does not match any profile.
|
||||
*/
|
||||
public final BleProfile getProfile() {
|
||||
return mBleManager.getProfile();
|
||||
return bleManager.getProfile();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,18 +157,18 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
|
||||
@Override
|
||||
public IBinder onBind(final Intent intent) {
|
||||
mBound = true;
|
||||
bound = true;
|
||||
return getBinder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onRebind(final Intent intent) {
|
||||
mBound = true;
|
||||
bound = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onUnbind(final Intent intent) {
|
||||
mBound = false;
|
||||
bound = false;
|
||||
|
||||
// We want the onRebind method be called if anything else binds to it again
|
||||
return true;
|
||||
@@ -179,13 +179,13 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
mHandler = new Handler();
|
||||
handler = new Handler();
|
||||
|
||||
// initialize the manager
|
||||
mBleManager = new BleManager(this, this);
|
||||
bleManager = new BleManager(this, this);
|
||||
|
||||
// Register broadcast receivers
|
||||
registerReceiver(mBluetoothStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
|
||||
registerReceiver(bluetoothStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
|
||||
|
||||
// Service has now been created
|
||||
onServiceCreated();
|
||||
@@ -209,15 +209,15 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
if (intent == null || !intent.hasExtra(EXTRA_DEVICE_ADDRESS))
|
||||
throw new UnsupportedOperationException("No device address at EXTRA_DEVICE_ADDRESS key");
|
||||
|
||||
mDeviceName = intent.getStringExtra(EXTRA_DEVICE_NAME);
|
||||
deviceName = intent.getStringExtra(EXTRA_DEVICE_NAME);
|
||||
|
||||
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
|
||||
final BluetoothAdapter adapter = bluetoothManager.getAdapter();
|
||||
final String deviceAddress = intent.getStringExtra(EXTRA_DEVICE_ADDRESS);
|
||||
mBluetoothDevice = adapter.getRemoteDevice(deviceAddress);
|
||||
bluetoothDevice = adapter.getRemoteDevice(deviceAddress);
|
||||
onServiceStarted();
|
||||
|
||||
mBleManager.connect(mBluetoothDevice);
|
||||
bleManager.connect(bluetoothDevice);
|
||||
return START_REDELIVER_INTENT;
|
||||
}
|
||||
|
||||
@@ -232,14 +232,14 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
// Unregister broadcast receivers
|
||||
unregisterReceiver(mBluetoothStateBroadcastReceiver);
|
||||
unregisterReceiver(bluetoothStateBroadcastReceiver);
|
||||
|
||||
// shutdown the manager
|
||||
mBleManager.close();
|
||||
mBleManager = null;
|
||||
mBluetoothDevice = null;
|
||||
mDeviceName = null;
|
||||
mConnected = false;
|
||||
bleManager.close();
|
||||
bleManager = null;
|
||||
bluetoothDevice = null;
|
||||
deviceName = null;
|
||||
connected = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,25 +261,25 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
@Override
|
||||
public boolean shouldEnableBatteryLevelNotifications(final BluetoothDevice device) {
|
||||
// By default the Battery Level notifications will be enabled only the activity is bound.
|
||||
return mBound;
|
||||
return bound;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnecting(final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTING);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceConnected(final BluetoothDevice device) {
|
||||
mConnected = true;
|
||||
connected = true;
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE_NAME, mDeviceName);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE_NAME, deviceName);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@@ -287,14 +287,14 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
public void onDeviceDisconnecting(final BluetoothDevice device) {
|
||||
// Notify user about changing the state to DISCONNECTING
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTING);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceDisconnected(final BluetoothDevice device) {
|
||||
mConnected = false;
|
||||
connected = false;
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTED);
|
||||
@@ -305,10 +305,10 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
|
||||
@Override
|
||||
public void onLinklossOccurred(final BluetoothDevice device) {
|
||||
mConnected = false;
|
||||
connected = false;
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_LINK_LOSS);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
@@ -316,14 +316,14 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
@Override
|
||||
public void onDeviceReady(final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_DEVICE_READY);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceNotSupported(final BluetoothDevice device) {
|
||||
final Intent broadcast = new Intent(BROADCAST_DEVICE_NOT_SUPPORTED);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
// no need for disconnecting, it will be disconnected by the manager automatically
|
||||
@@ -334,7 +334,7 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
showToast(no.nordicsemi.android.nrftoolbox.common.R.string.bonding);
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
@@ -344,7 +344,7 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
showToast(no.nordicsemi.android.nrftoolbox.common.R.string.bonded);
|
||||
|
||||
final Intent broadcast = new Intent(BROADCAST_BOND_STATE);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
@@ -352,14 +352,14 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
@Override
|
||||
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
|
||||
final Intent broadcast = new Intent(BROADCAST_ERROR);
|
||||
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice);
|
||||
broadcast.putExtra(EXTRA_ERROR_MESSAGE, message);
|
||||
broadcast.putExtra(EXTRA_ERROR_CODE, errorCode);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
|
||||
// After receiving an error the device will be automatically disconnected.
|
||||
// Replace it with other implementation if necessary.
|
||||
mBleManager.disconnect();
|
||||
bleManager.disconnect();
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
@@ -370,7 +370,7 @@ public class BleProfileService extends Service implements BleManagerCallbacks {
|
||||
* an resource id of the message to be shown
|
||||
*/
|
||||
private void showToast(final int messageResId) {
|
||||
mHandler.post(() -> Toast.makeText(BleProfileService.this, messageResId, Toast.LENGTH_SHORT).show());
|
||||
handler.post(() -> Toast.makeText(BleProfileService.this, messageResId, Toast.LENGTH_SHORT).show());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,12 +65,12 @@ public class UARTCommandsActivity extends Activity implements UARTCommandsAdapte
|
||||
|
||||
public static final String CONFIGURATION = "configuration";
|
||||
|
||||
private GoogleApiClient mGoogleApiClient;
|
||||
private UARTCommandsAdapter mAdapter;
|
||||
private UARTProfile mProfile;
|
||||
private long mConfigurationId;
|
||||
private GoogleApiClient googleApiClient;
|
||||
private UARTCommandsAdapter adapter;
|
||||
private UARTProfile profile;
|
||||
private long configurationId;
|
||||
|
||||
private BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
|
||||
private BroadcastReceiver serviceBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
@@ -100,16 +100,16 @@ public class UARTCommandsActivity extends Activity implements UARTCommandsAdapte
|
||||
}
|
||||
};
|
||||
|
||||
private ServiceConnection mServiceConnection = new ServiceConnection() {
|
||||
private ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName name, final IBinder service) {
|
||||
final BleProfileService.LocalBinder binder = (BleProfileService.LocalBinder) service;
|
||||
mProfile = (UARTProfile) binder.getProfile();
|
||||
profile = (UARTProfile) binder.getProfile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName name) {
|
||||
mProfile = null;
|
||||
profile = null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -120,22 +120,22 @@ public class UARTCommandsActivity extends Activity implements UARTCommandsAdapte
|
||||
|
||||
final Intent intent = getIntent();
|
||||
final UartConfiguration configuration = intent.getParcelableExtra(CONFIGURATION);
|
||||
mConfigurationId = configuration.getId();
|
||||
configurationId = configuration.getId();
|
||||
|
||||
// Check if the WEAR device is connected to the UART device itself, or by the phone.
|
||||
// Binding will fail if we are using phone as proxy as the service has not been started before.
|
||||
final Intent service = new Intent(this, BleProfileService.class);
|
||||
bindService(service, mServiceConnection, 0);
|
||||
bindService(service, serviceConnection, 0);
|
||||
|
||||
// Set up tht grid
|
||||
final GridViewPager pager = findViewById(R.id.pager);
|
||||
pager.setAdapter(mAdapter = new UARTCommandsAdapter(configuration, this));
|
||||
pager.setAdapter(adapter = new UARTCommandsAdapter(configuration, this));
|
||||
|
||||
final DotsPageIndicator dotsPageIndicator = findViewById(R.id.page_indicator);
|
||||
dotsPageIndicator.setPager(pager);
|
||||
|
||||
// Configure Google API client
|
||||
mGoogleApiClient = new GoogleApiClient.Builder(this)
|
||||
googleApiClient = new GoogleApiClient.Builder(this)
|
||||
.addApi(Wearable.API)
|
||||
.addConnectionCallbacks(this)
|
||||
.addOnConnectionFailedListener(this)
|
||||
@@ -146,39 +146,39 @@ public class UARTCommandsActivity extends Activity implements UARTCommandsAdapte
|
||||
filter.addAction(BleProfileService.BROADCAST_CONNECTION_STATE);
|
||||
filter.addAction(BleProfileService.BROADCAST_ERROR);
|
||||
filter.addAction(UARTProfile.BROADCAST_DATA_RECEIVED);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mServiceBroadcastReceiver, filter);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(serviceBroadcastReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mGoogleApiClient.unregisterConnectionCallbacks(this);
|
||||
mGoogleApiClient.unregisterConnectionFailedListener(this);
|
||||
mGoogleApiClient = null;
|
||||
googleApiClient.unregisterConnectionCallbacks(this);
|
||||
googleApiClient.unregisterConnectionFailedListener(this);
|
||||
googleApiClient = null;
|
||||
|
||||
// unbind if we were bound to the service.
|
||||
unbindService(mServiceConnection);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mServiceBroadcastReceiver);
|
||||
unbindService(serviceConnection);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(serviceBroadcastReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mGoogleApiClient.connect();
|
||||
googleApiClient.connect();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
Wearable.MessageApi.removeListener(mGoogleApiClient, this);
|
||||
Wearable.DataApi.removeListener(mGoogleApiClient, this);
|
||||
mGoogleApiClient.disconnect();
|
||||
Wearable.MessageApi.removeListener(googleApiClient, this);
|
||||
Wearable.DataApi.removeListener(googleApiClient, this);
|
||||
googleApiClient.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(final Bundle bundle) {
|
||||
Wearable.DataApi.addListener(mGoogleApiClient, this);
|
||||
Wearable.MessageApi.addListener(mGoogleApiClient, this);
|
||||
Wearable.DataApi.addListener(googleApiClient, this);
|
||||
Wearable.MessageApi.addListener(googleApiClient, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -198,7 +198,7 @@ public class UARTCommandsActivity extends Activity implements UARTCommandsAdapte
|
||||
final long id = ContentUris.parseId(item.getUri());
|
||||
|
||||
// Update the configuration only if ID matches
|
||||
if (id != mConfigurationId)
|
||||
if (id != configurationId)
|
||||
continue;
|
||||
|
||||
// Configuration added or edited
|
||||
@@ -207,12 +207,12 @@ public class UARTCommandsActivity extends Activity implements UARTCommandsAdapte
|
||||
final UartConfiguration configuration = new UartConfiguration(dataMap, id);
|
||||
|
||||
// Update UI on UI thread
|
||||
runOnUiThread(() -> mAdapter.setConfiguration(configuration));
|
||||
runOnUiThread(() -> adapter.setConfiguration(configuration));
|
||||
} else if (event.getType() == DataEvent.TYPE_DELETED) {
|
||||
// Configuration removed
|
||||
|
||||
// Update UI on UI thread
|
||||
runOnUiThread(() -> mAdapter.setConfiguration(null));
|
||||
runOnUiThread(() -> adapter.setConfiguration(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,7 +220,7 @@ public class UARTCommandsActivity extends Activity implements UARTCommandsAdapte
|
||||
@Override
|
||||
public void onMessageReceived(final MessageEvent messageEvent) {
|
||||
// If the activity is bound to service it means that it has connected directly to the device. We ignore messages from the handheld.
|
||||
if (mProfile != null)
|
||||
if (profile != null)
|
||||
return;
|
||||
|
||||
switch (messageEvent.getPath()) {
|
||||
@@ -246,8 +246,8 @@ public class UARTCommandsActivity extends Activity implements UARTCommandsAdapte
|
||||
break;
|
||||
}
|
||||
|
||||
if (mProfile != null)
|
||||
mProfile.send(text);
|
||||
if (profile != null)
|
||||
profile.send(text);
|
||||
else
|
||||
sendMessageToHandheld(this, text);
|
||||
}
|
||||
|
||||
@@ -34,21 +34,21 @@ import no.nordicsemi.android.nrftoolbox.uart.domain.Command;
|
||||
import no.nordicsemi.android.nrftoolbox.uart.domain.UartConfiguration;
|
||||
|
||||
public class UARTCommandsAdapter extends GridPagerAdapter {
|
||||
private final OnCommandSelectedListener mListener;
|
||||
private UartConfiguration mConfiguration;
|
||||
private final OnCommandSelectedListener listener;
|
||||
private UartConfiguration configuration;
|
||||
|
||||
public interface OnCommandSelectedListener {
|
||||
void onCommandSelected(final Command command);
|
||||
}
|
||||
|
||||
public UARTCommandsAdapter(final UartConfiguration configuration, final OnCommandSelectedListener listener) {
|
||||
this.mConfiguration = configuration;
|
||||
this.mListener = listener;
|
||||
this.configuration = configuration;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void setConfiguration(final UartConfiguration configuration) {
|
||||
// Configuration is null when it has been deleted on the handheld
|
||||
this.mConfiguration = configuration;
|
||||
this.configuration = configuration;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public class UARTCommandsAdapter extends GridPagerAdapter {
|
||||
|
||||
@Override
|
||||
public int getColumnCount(final int row) {
|
||||
final int count = mConfiguration != null ? mConfiguration.getCommands().length : 0;
|
||||
final int count = configuration != null ? configuration.getCommands().length : 0;
|
||||
return count > 0 ? count : 1; // Empty view
|
||||
}
|
||||
|
||||
@@ -68,13 +68,13 @@ public class UARTCommandsAdapter extends GridPagerAdapter {
|
||||
final View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.action_item, viewGroup, false);
|
||||
viewGroup.addView(view);
|
||||
|
||||
final Command[] commands = mConfiguration != null ? mConfiguration.getCommands() : null;
|
||||
final Command[] commands = configuration != null ? configuration.getCommands() : null;
|
||||
if (commands != null && commands.length > 0) {
|
||||
final Command command = commands[column];
|
||||
|
||||
final CircularButton icon = view.findViewById(R.id.icon);
|
||||
icon.getImageDrawable().setLevel(command.getIconIndex());
|
||||
icon.setOnClickListener(v -> mListener.onCommandSelected(command));
|
||||
icon.setOnClickListener(v -> listener.onCommandSelected(command));
|
||||
} else {
|
||||
// Hide the icon
|
||||
view.findViewById(R.id.icon).setVisibility(View.GONE);
|
||||
|
||||
@@ -43,19 +43,19 @@ public class UARTConfigurationItemLayout extends LinearLayout implements Wearabl
|
||||
private static final float SHRINK_LABEL_ALPHA = .5f;
|
||||
private static final float EXPAND_LABEL_ALPHA = 1f;
|
||||
|
||||
private float mExpandCircleRadius;
|
||||
private float mShrinkCircleRadius;
|
||||
private float expandCircleRadius;
|
||||
private float shrinkCircleRadius;
|
||||
|
||||
private ObjectAnimator mExpandCircleAnimator;
|
||||
private ObjectAnimator mFadeInLabelAnimator;
|
||||
private AnimatorSet mExpandAnimator;
|
||||
private ObjectAnimator expandCircleAnimator;
|
||||
private ObjectAnimator fadeInLabelAnimator;
|
||||
private AnimatorSet expandAnimator;
|
||||
|
||||
private ObjectAnimator mShrinkCircleAnimator;
|
||||
private ObjectAnimator mFadeOutLabelAnimator;
|
||||
private AnimatorSet mShrinkAnimator;
|
||||
private ObjectAnimator shrinkCircleAnimator;
|
||||
private ObjectAnimator fadeOutLabelAnimator;
|
||||
private AnimatorSet shrinkAnimator;
|
||||
|
||||
private TextView mName;
|
||||
private CircledImageView mIcon;
|
||||
private TextView name;
|
||||
private CircledImageView icon;
|
||||
|
||||
public UARTConfigurationItemLayout(final Context context) {
|
||||
this(context, null, 0);
|
||||
@@ -73,53 +73,53 @@ public class UARTConfigurationItemLayout extends LinearLayout implements Wearabl
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mName = findViewById(R.id.name);
|
||||
mIcon = findViewById(R.id.icon);
|
||||
mExpandCircleRadius = mIcon.getCircleRadius();
|
||||
mShrinkCircleRadius = mExpandCircleRadius * SHRINK_CIRCLE_RATIO;
|
||||
name = findViewById(R.id.name);
|
||||
icon = findViewById(R.id.icon);
|
||||
expandCircleRadius = icon.getCircleRadius();
|
||||
shrinkCircleRadius = expandCircleRadius * SHRINK_CIRCLE_RATIO;
|
||||
|
||||
mShrinkCircleAnimator = ObjectAnimator.ofFloat(mIcon, "circleRadius", mExpandCircleRadius, mShrinkCircleRadius);
|
||||
mFadeOutLabelAnimator = ObjectAnimator.ofFloat(mName, "alpha", EXPAND_LABEL_ALPHA, SHRINK_LABEL_ALPHA);
|
||||
mShrinkAnimator = new AnimatorSet().setDuration(ANIMATION_DURATION_MS);
|
||||
mShrinkAnimator.playTogether(mShrinkCircleAnimator, mFadeOutLabelAnimator);
|
||||
shrinkCircleAnimator = ObjectAnimator.ofFloat(icon, "circleRadius", expandCircleRadius, shrinkCircleRadius);
|
||||
fadeOutLabelAnimator = ObjectAnimator.ofFloat(name, "alpha", EXPAND_LABEL_ALPHA, SHRINK_LABEL_ALPHA);
|
||||
shrinkAnimator = new AnimatorSet().setDuration(ANIMATION_DURATION_MS);
|
||||
shrinkAnimator.playTogether(shrinkCircleAnimator, fadeOutLabelAnimator);
|
||||
|
||||
mExpandCircleAnimator = ObjectAnimator.ofFloat(mIcon, "circleRadius", mShrinkCircleRadius, mExpandCircleRadius);
|
||||
mFadeInLabelAnimator = ObjectAnimator.ofFloat(mName, "alpha", SHRINK_LABEL_ALPHA, EXPAND_LABEL_ALPHA);
|
||||
mExpandAnimator = new AnimatorSet().setDuration(ANIMATION_DURATION_MS);
|
||||
mExpandAnimator.playTogether(mExpandCircleAnimator, mFadeInLabelAnimator);
|
||||
expandCircleAnimator = ObjectAnimator.ofFloat(icon, "circleRadius", shrinkCircleRadius, expandCircleRadius);
|
||||
fadeInLabelAnimator = ObjectAnimator.ofFloat(name, "alpha", SHRINK_LABEL_ALPHA, EXPAND_LABEL_ALPHA);
|
||||
expandAnimator = new AnimatorSet().setDuration(ANIMATION_DURATION_MS);
|
||||
expandAnimator.playTogether(expandCircleAnimator, fadeInLabelAnimator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCenterPosition(final boolean animate) {
|
||||
if (animate) {
|
||||
mShrinkAnimator.cancel();
|
||||
if (!mExpandAnimator.isRunning()) {
|
||||
mExpandCircleAnimator.setFloatValues(mIcon.getCircleRadius(), mExpandCircleRadius);
|
||||
mFadeInLabelAnimator.setFloatValues(mName.getAlpha(), EXPAND_LABEL_ALPHA);
|
||||
mExpandAnimator.start();
|
||||
shrinkAnimator.cancel();
|
||||
if (!expandAnimator.isRunning()) {
|
||||
expandCircleAnimator.setFloatValues(icon.getCircleRadius(), expandCircleRadius);
|
||||
fadeInLabelAnimator.setFloatValues(name.getAlpha(), EXPAND_LABEL_ALPHA);
|
||||
expandAnimator.start();
|
||||
}
|
||||
} else {
|
||||
mExpandAnimator.cancel();
|
||||
mIcon.setCircleRadius(mExpandCircleRadius);
|
||||
mName.setAlpha(EXPAND_LABEL_ALPHA);
|
||||
expandAnimator.cancel();
|
||||
icon.setCircleRadius(expandCircleRadius);
|
||||
name.setAlpha(EXPAND_LABEL_ALPHA);
|
||||
}
|
||||
mIcon.setEnabled(true);
|
||||
icon.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNonCenterPosition(final boolean animate) {
|
||||
if (animate) {
|
||||
mExpandAnimator.cancel();
|
||||
if (!mShrinkAnimator.isRunning()) {
|
||||
mShrinkCircleAnimator.setFloatValues(mIcon.getCircleRadius(), mShrinkCircleRadius);
|
||||
mFadeOutLabelAnimator.setFloatValues(mName.getAlpha(), SHRINK_LABEL_ALPHA);
|
||||
mShrinkAnimator.start();
|
||||
expandAnimator.cancel();
|
||||
if (!shrinkAnimator.isRunning()) {
|
||||
shrinkCircleAnimator.setFloatValues(icon.getCircleRadius(), shrinkCircleRadius);
|
||||
fadeOutLabelAnimator.setFloatValues(name.getAlpha(), SHRINK_LABEL_ALPHA);
|
||||
shrinkAnimator.start();
|
||||
}
|
||||
} else {
|
||||
mShrinkAnimator.cancel();
|
||||
mIcon.setCircleRadius(mShrinkCircleRadius);
|
||||
mName.setAlpha(SHRINK_LABEL_ALPHA);
|
||||
shrinkAnimator.cancel();
|
||||
icon.setCircleRadius(shrinkCircleRadius);
|
||||
name.setAlpha(SHRINK_LABEL_ALPHA);
|
||||
}
|
||||
mIcon.setEnabled(false);
|
||||
icon.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,11 +60,11 @@ import no.nordicsemi.android.nrftoolbox.uart.domain.UartConfiguration;
|
||||
|
||||
public class UARTConfigurationsActivity extends Activity implements GoogleApiClient.ConnectionCallbacks,
|
||||
DataApi.DataListener, GoogleApiClient.OnConnectionFailedListener, WearableListView.ClickListener, MessageApi.MessageListener {
|
||||
private UARTConfigurationsAdapter mAdapter;
|
||||
private GoogleApiClient mGoogleApiClient;
|
||||
private BleProfileService.LocalBinder mBinder;
|
||||
private UARTConfigurationsAdapter adapter;
|
||||
private GoogleApiClient googleApiClient;
|
||||
private BleProfileService.LocalBinder binder;
|
||||
|
||||
private BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
|
||||
private BroadcastReceiver serviceBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
@@ -87,15 +87,15 @@ public class UARTConfigurationsActivity extends Activity implements GoogleApiCli
|
||||
}
|
||||
};
|
||||
|
||||
private ServiceConnection mServiceConnection = new ServiceConnection() {
|
||||
private ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName name, final IBinder service) {
|
||||
mBinder = (BleProfileService.LocalBinder) service;
|
||||
binder = (BleProfileService.LocalBinder) service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName name) {
|
||||
mBinder = null;
|
||||
binder = null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -107,13 +107,13 @@ public class UARTConfigurationsActivity extends Activity implements GoogleApiCli
|
||||
// Check if the WEAR device is connected to the UART device itself, or by the phone.
|
||||
// Binding will fail if we are using phone as proxy as the service has not been started before.
|
||||
final Intent service = new Intent(this, BleProfileService.class);
|
||||
bindService(service, mServiceConnection, 0);
|
||||
bindService(service, serviceConnection, 0);
|
||||
|
||||
final WearableListView listView = findViewById(R.id.list);
|
||||
listView.setClickListener(this);
|
||||
listView.setAdapter(mAdapter = new UARTConfigurationsAdapter(this));
|
||||
listView.setAdapter(adapter = new UARTConfigurationsAdapter(this));
|
||||
|
||||
mGoogleApiClient = new GoogleApiClient.Builder(this)
|
||||
googleApiClient = new GoogleApiClient.Builder(this)
|
||||
.addApi(Wearable.API)
|
||||
.addConnectionCallbacks(this)
|
||||
.addOnConnectionFailedListener(this)
|
||||
@@ -124,48 +124,48 @@ public class UARTConfigurationsActivity extends Activity implements GoogleApiCli
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(BleProfileService.BROADCAST_CONNECTION_STATE);
|
||||
filter.addAction(BleProfileService.BROADCAST_ERROR);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mServiceBroadcastReceiver, filter);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(serviceBroadcastReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mGoogleApiClient.unregisterConnectionCallbacks(this);
|
||||
mGoogleApiClient.unregisterConnectionFailedListener(this);
|
||||
mGoogleApiClient = null;
|
||||
googleApiClient.unregisterConnectionCallbacks(this);
|
||||
googleApiClient.unregisterConnectionFailedListener(this);
|
||||
googleApiClient = null;
|
||||
|
||||
// If we were bound to the service, disconnect and unbind. The service will terminate itself when disconnected.
|
||||
if (mBinder != null) {
|
||||
mBinder.disconnect();
|
||||
if (binder != null) {
|
||||
binder.disconnect();
|
||||
}
|
||||
unbindService(mServiceConnection);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mServiceBroadcastReceiver);
|
||||
unbindService(serviceConnection);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(serviceBroadcastReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mGoogleApiClient.connect();
|
||||
googleApiClient.connect();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
Wearable.MessageApi.removeListener(mGoogleApiClient, this);
|
||||
Wearable.DataApi.removeListener(mGoogleApiClient, this);
|
||||
mGoogleApiClient.disconnect();
|
||||
Wearable.MessageApi.removeListener(googleApiClient, this);
|
||||
Wearable.DataApi.removeListener(googleApiClient, this);
|
||||
googleApiClient.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(final Bundle bundle) {
|
||||
Wearable.DataApi.addListener(mGoogleApiClient, this);
|
||||
Wearable.MessageApi.addListener(mGoogleApiClient, this);
|
||||
Wearable.DataApi.addListener(googleApiClient, this);
|
||||
Wearable.MessageApi.addListener(googleApiClient, this);
|
||||
populateConfigurations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionSuspended(final int cause) {
|
||||
Wearable.DataApi.removeListener(mGoogleApiClient, this);
|
||||
Wearable.DataApi.removeListener(googleApiClient, this);
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ public class UARTConfigurationsActivity extends Activity implements GoogleApiCli
|
||||
@Override
|
||||
public void onMessageReceived(final MessageEvent messageEvent) {
|
||||
// If the activity is bound to service it means that it has connected directly to the device. We ignore messages from the handheld.
|
||||
if (mBinder != null)
|
||||
if (binder != null)
|
||||
return;
|
||||
|
||||
switch (messageEvent.getPath()) {
|
||||
@@ -215,8 +215,8 @@ public class UARTConfigurationsActivity extends Activity implements GoogleApiCli
|
||||
* This method read the UART configurations from the DataApi and populates the adapter with them.
|
||||
*/
|
||||
private void populateConfigurations() {
|
||||
if (mGoogleApiClient.isConnected()) {
|
||||
final PendingResult<DataItemBuffer> results = Wearable.DataApi.getDataItems(mGoogleApiClient, Uri.parse("wear:" + Constants.UART.CONFIGURATIONS), DataApi.FILTER_PREFIX);
|
||||
if (googleApiClient.isConnected()) {
|
||||
final PendingResult<DataItemBuffer> results = Wearable.DataApi.getDataItems(googleApiClient, Uri.parse("wear:" + Constants.UART.CONFIGURATIONS), DataApi.FILTER_PREFIX);
|
||||
results.setResultCallback(dataItems -> {
|
||||
final List<UartConfiguration> configurations = new ArrayList<>(dataItems.getCount());
|
||||
for (int i = 0; i < dataItems.getCount(); ++i) {
|
||||
@@ -226,7 +226,7 @@ public class UARTConfigurationsActivity extends Activity implements GoogleApiCli
|
||||
final UartConfiguration configuration = new UartConfiguration(dataMap, id);
|
||||
configurations.add(configuration);
|
||||
}
|
||||
mAdapter.setConfigurations(configurations);
|
||||
adapter.setConfigurations(configurations);
|
||||
dataItems.release();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -31,58 +31,60 @@ import android.widget.TextView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import no.nordicsemi.android.nrftoolbox.R;
|
||||
import no.nordicsemi.android.nrftoolbox.uart.domain.UartConfiguration;
|
||||
|
||||
public class UARTConfigurationsAdapter extends WearableListView.Adapter {
|
||||
private final LayoutInflater mInflater;
|
||||
private List<UartConfiguration> mConfigurations;
|
||||
private final LayoutInflater inflater;
|
||||
private List<UartConfiguration> configurations;
|
||||
|
||||
public UARTConfigurationsAdapter(final Context context) {
|
||||
mInflater = LayoutInflater.from(context);
|
||||
inflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the adapter with list of configurations.
|
||||
*/
|
||||
public void setConfigurations(final List<UartConfiguration> configurations) {
|
||||
mConfigurations = configurations;
|
||||
this.configurations = configurations;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public WearableListView.ViewHolder onCreateViewHolder(final ViewGroup viewGroup, final int viewType) {
|
||||
return new ConfigurationViewHolder(mInflater.inflate(R.layout.configuration_item, viewGroup, false));
|
||||
public WearableListView.ViewHolder onCreateViewHolder(@NonNull final ViewGroup viewGroup, final int viewType) {
|
||||
return new ConfigurationViewHolder(inflater.inflate(R.layout.configuration_item, viewGroup, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(final WearableListView.ViewHolder holder, final int position) {
|
||||
public void onBindViewHolder(@NonNull final WearableListView.ViewHolder holder, final int position) {
|
||||
final ConfigurationViewHolder viewHolder = (ConfigurationViewHolder) holder;
|
||||
viewHolder.setConfiguration(mConfigurations.get(position));
|
||||
viewHolder.setConfiguration(configurations.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mConfigurations != null ? mConfigurations.size() : 0;
|
||||
return configurations != null ? configurations.size() : 0;
|
||||
}
|
||||
|
||||
public static class ConfigurationViewHolder extends WearableListView.ViewHolder {
|
||||
private UartConfiguration mConfiguration;
|
||||
private TextView mName;
|
||||
private UartConfiguration configuration;
|
||||
private TextView name;
|
||||
|
||||
public ConfigurationViewHolder(final View itemView) {
|
||||
super(itemView);
|
||||
|
||||
mName = itemView.findViewById(R.id.name);
|
||||
name = itemView.findViewById(R.id.name);
|
||||
}
|
||||
|
||||
private void setConfiguration(final UartConfiguration configuration) {
|
||||
mConfiguration = configuration;
|
||||
mName.setText(configuration.getName());
|
||||
this.configuration = configuration;
|
||||
name.setText(configuration.getName());
|
||||
}
|
||||
|
||||
public UartConfiguration getConfiguration() {
|
||||
return mConfiguration;
|
||||
return configuration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,36 +59,36 @@ public class UARTProfile extends BleProfile {
|
||||
return service != null && service.getCharacteristic(UART_TX_CHARACTERISTIC_UUID) != null && service.getCharacteristic(UART_RX_CHARACTERISTIC_UUID) != null;
|
||||
}
|
||||
|
||||
private BluetoothGattCharacteristic mTXCharacteristic;
|
||||
private BluetoothGattCharacteristic mRXCharacteristic;
|
||||
private byte[] mOutgoingBuffer;
|
||||
private int mBufferOffset;
|
||||
private BluetoothGattCharacteristic tXCharacteristic;
|
||||
private BluetoothGattCharacteristic rXCharacteristic;
|
||||
private byte[] outgoingBuffer;
|
||||
private int bufferOffset;
|
||||
|
||||
@Override
|
||||
protected Deque<BleManager.Request> initGatt(final BluetoothGatt gatt) {
|
||||
final BluetoothGattService service = gatt.getService(UART_SERVICE_UUID);
|
||||
mTXCharacteristic = service.getCharacteristic(UART_TX_CHARACTERISTIC_UUID);
|
||||
mRXCharacteristic = service.getCharacteristic(UART_RX_CHARACTERISTIC_UUID);
|
||||
tXCharacteristic = service.getCharacteristic(UART_TX_CHARACTERISTIC_UUID);
|
||||
rXCharacteristic = service.getCharacteristic(UART_RX_CHARACTERISTIC_UUID);
|
||||
|
||||
final int rxProperties = mRXCharacteristic.getProperties();
|
||||
final int rxProperties = rXCharacteristic.getProperties();
|
||||
boolean writeRequest = (rxProperties & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0;
|
||||
|
||||
// Set the WRITE REQUEST type when the characteristic supports it. This will allow to send long write (also if the characteristic support it).
|
||||
// In case there is no WRITE REQUEST property, this manager will divide texts longer then 20 bytes into up to 20 bytes chunks.
|
||||
if (writeRequest)
|
||||
mRXCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
|
||||
rXCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
|
||||
|
||||
// We don't want to enable notifications on TX characteristic as we are not showing them here. A watch may be just used to send data. At least now.
|
||||
// final LinkedList<BleProfileApi.Request> requests = new LinkedList<>();
|
||||
// requests.add(BleProfileApi.Request.newEnableNotificationsRequest(mTXCharacteristic));
|
||||
// requests.add(BleProfileApi.Request.newEnableNotificationsRequest(tXCharacteristic));
|
||||
// return requests;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void release() {
|
||||
mTXCharacteristic = null;
|
||||
mRXCharacteristic = null;
|
||||
tXCharacteristic = null;
|
||||
rXCharacteristic = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,13 +102,13 @@ public class UARTProfile extends BleProfile {
|
||||
@Override
|
||||
protected void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
|
||||
// When the whole buffer has been sent
|
||||
final byte[] buffer = mOutgoingBuffer;
|
||||
if (mBufferOffset == buffer.length) {
|
||||
mOutgoingBuffer = null;
|
||||
final byte[] buffer = outgoingBuffer;
|
||||
if (bufferOffset == buffer.length) {
|
||||
outgoingBuffer = null;
|
||||
} else { // Otherwise...
|
||||
final int length = Math.min(buffer.length - mBufferOffset, MAX_PACKET_SIZE);
|
||||
getApi().enqueue(BleProfileApi.Request.newWriteRequest(mRXCharacteristic, buffer, mBufferOffset, length));
|
||||
mBufferOffset += length;
|
||||
final int length = Math.min(buffer.length - bufferOffset, MAX_PACKET_SIZE);
|
||||
getApi().enqueue(BleProfileApi.Request.newWriteRequest(rXCharacteristic, buffer, bufferOffset, length));
|
||||
bufferOffset += length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,25 +118,25 @@ public class UARTProfile extends BleProfile {
|
||||
*/
|
||||
public void send(final String text) {
|
||||
// Are we connected?
|
||||
if (mRXCharacteristic == null)
|
||||
if (rXCharacteristic == null)
|
||||
return;
|
||||
|
||||
// An outgoing buffer may not be null if there is already another packet being sent. We do nothing in this case.
|
||||
if (!TextUtils.isEmpty(text) && mOutgoingBuffer == null) {
|
||||
final byte[] buffer = mOutgoingBuffer = text.getBytes();
|
||||
mBufferOffset = 0;
|
||||
if (!TextUtils.isEmpty(text) && outgoingBuffer == null) {
|
||||
final byte[] buffer = outgoingBuffer = text.getBytes();
|
||||
bufferOffset = 0;
|
||||
|
||||
// Depending on whether the characteristic has the WRITE REQUEST property or not, we will either send it as it is (hoping the long write is implemented),
|
||||
// or divide it into up to 20 bytes chunks and send them one by one.
|
||||
final boolean writeRequest = (mRXCharacteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0;
|
||||
final boolean writeRequest = (rXCharacteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0;
|
||||
|
||||
if (!writeRequest) { // no WRITE REQUEST property
|
||||
final int length = Math.min(buffer.length, MAX_PACKET_SIZE);
|
||||
mBufferOffset += length;
|
||||
getApi().enqueue(BleProfileApi.Request.newWriteRequest(mRXCharacteristic, buffer, 0, length));
|
||||
bufferOffset += length;
|
||||
getApi().enqueue(BleProfileApi.Request.newWriteRequest(rXCharacteristic, buffer, 0, length));
|
||||
} else { // there is WRITE REQUEST property, let's try Long Write
|
||||
mBufferOffset = buffer.length;
|
||||
getApi().enqueue(BleProfileApi.Request.newWriteRequest(mRXCharacteristic, buffer, 0, buffer.length));
|
||||
bufferOffset = buffer.length;
|
||||
getApi().enqueue(BleProfileApi.Request.newWriteRequest(rXCharacteristic, buffer, 0, buffer.length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user