package com.javispedro.rempe; import android.content.SharedPreferences; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.ListUpdateCallback; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.dsi.ant.plugins.antplus.pcc.AntPlusEnvironmentPcc; import com.dsi.ant.plugins.antplus.pcc.defines.DeviceState; import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult; import com.dsi.ant.plugins.antplus.pccbase.AntPluginPcc; import com.dsi.ant.plugins.antplus.pccbase.PccReleaseHandle; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.snackbar.Snackbar; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private final static String TAG = "MainActivity"; private SharedPreferences mPrefs = null; private final ArrayList mDeviceNumbers = new ArrayList(); private final ArrayList mDevices = new ArrayList(); private DeviceListRecyclerViewListAdapter mDeviceListAdapter; private SwipeRefreshLayout mSrlList; private RecyclerView mList; private PccReleaseHandle mPccSearchHandle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mPrefs = PreferenceManager.getDefaultSharedPreferences(this); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = findViewById(R.id.fabAddDevice); fab.setOnClickListener(view -> onConnectButtonClicked()); mSrlList = findViewById(R.id.srlList); mSrlList.setOnRefreshListener(() -> onListRefresh()); mList = findViewById(R.id.list); mList.setLayoutManager(new LinearLayoutManager(mList.getContext())); mDeviceListAdapter = new DeviceListRecyclerViewListAdapter(); mList.setAdapter(mDeviceListAdapter); new ItemTouchHelper(mItemTouchHelperCallback).attachToRecyclerView(mList); refreshDevices(); } @Override protected void onDestroy() { disconnectAll(); mPrefs = null; mDeviceListAdapter = null; mSrlList = null; super.onDestroy(); } @Override public void onResume() { super.onResume(); mPrefs.registerOnSharedPreferenceChangeListener(mPrefsListener); connectToDevices(); } @Override public void onPause() { disconnectAll(); mPrefs.unregisterOnSharedPreferenceChangeListener(mPrefsListener); super.onPause(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); switch (id) { case R.id.action_settings: return true; } return super.onOptionsItemSelected(item); } private void onConnectButtonClicked() { searchForNewDevice(); } private void onListRefresh() { connectToDevices(); mSrlList.setRefreshing(false); } private final ItemTouchHelper.Callback mItemTouchHelperCallback = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { @Override public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { final int from = viewHolder.getAdapterPosition(); final int to = viewHolder.getAdapterPosition(); Log.d(TAG, "onMove from=" + from + " to=" + to); return false; } @Override public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { final int position = viewHolder.getAdapterPosition(); removeDeviceByPosition(position); } }; private final SharedPreferences.OnSharedPreferenceChangeListener mPrefsListener = new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { switch (key) { case Preferences.PREFS_DEVICES: refreshDevices(); break; } } }; public void searchForNewDevice() { Log.d(TAG, "searchForNewDevice"); if (mPccSearchHandle != null) { mPccSearchHandle.close(); mPccSearchHandle = null; } mPccSearchHandle = AntPlusEnvironmentPcc.requestAccess(this, this, mResultReceiver, mDeviceStateChangeReceiver); } private final AntPluginPcc.IPluginAccessResultReceiver mResultReceiver = new AntPluginPcc.IPluginAccessResultReceiver() { @Override public void onResultReceived(AntPlusEnvironmentPcc result, RequestAccessResult resultCode, DeviceState initialDeviceState) { Log.d(TAG, "onResultReceived resultCode=" + resultCode); if (resultCode == RequestAccessResult.SUCCESS) { int deviceNumber = result.getAntDeviceNumber(); result.releaseAccess(); runOnUiThread(() -> addDevice(result.getAntDeviceNumber())); } else if (resultCode != RequestAccessResult.USER_CANCELLED) { runOnUiThread(() -> { final String resultText = Device.connectionRequestAccessResultToString(MainActivity.this, resultCode); Snackbar.make(findViewById(R.id.fabAddDevice), getString(R.string.add_device_failed, resultText), Snackbar.LENGTH_INDEFINITE).show(); }); } mPccSearchHandle.close(); mPccSearchHandle = null; } }; private final AntPluginPcc.IDeviceStateChangeReceiver mDeviceStateChangeReceiver = new AntPluginPcc.IDeviceStateChangeReceiver() { @Override public void onDeviceStateChange(DeviceState newDeviceState) { Log.d(TAG, "onDeviceStateChange newDeviceState=" + newDeviceState); } }; public void addDevice(int deviceNumber) { Log.d(TAG, "addDevice " + deviceNumber); List list = Preferences.getDeviceNumbers(mPrefs); if (list.contains(deviceNumber)) { Snackbar.make(findViewById(R.id.fabAddDevice), getString(R.string.add_device_already), Snackbar.LENGTH_INDEFINITE).show(); return; } list.add(deviceNumber); Preferences.saveDeviceNumbers(mPrefs, list); } public void removeDeviceByPosition(int position) { Log.d(TAG, "removeDeviceByPosition position=" + position); List list = Preferences.getDeviceNumbers(mPrefs); try { list.remove(position); } catch (IndexOutOfBoundsException ex) { Log.w(TAG, ex); } Snackbar.make(mList, getString(R.string.remove_device_done), Snackbar.LENGTH_SHORT).show(); Preferences.saveDeviceNumbers(mPrefs, list); } public void refreshDevices() { Log.d(TAG, "refreshDevices"); setDeviceNumberList(Preferences.getDeviceNumbers(mPrefs)); } public void connectToDevices() { Log.d(TAG, "connectToDevices"); for (Device dev : mDevices) { if (!dev.isOpen()) { dev.connect(this); } } } public void disconnectAll() { Log.d(TAG, "disconnectAll"); for (Device dev : mDevices) { dev.close(); } } void setDeviceNumberList(List newDeviceNumbers) { DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffUtil.Callback() { @Override public int getOldListSize() { return mDeviceNumbers.size(); } @Override public int getNewListSize() { return newDeviceNumbers.size(); } @Override public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { return mDeviceNumbers.get(oldItemPosition).equals(newDeviceNumbers.get(newItemPosition)); } @Override public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { return areItemsTheSame(oldItemPosition, newItemPosition); } }); diff.dispatchUpdatesTo(new ListUpdateCallback() { @Override public void onInserted(int position, int count) { for (int i = 0; i < count; ++i) { final int deviceNumber = newDeviceNumbers.get(position + i); Device device = new Device(deviceNumber); mDeviceNumbers.add(position + i, deviceNumber); mDevices.add(position + i, device); } } @Override public void onRemoved(int position, int count) { for (int i = 0; i < count; ++i) { mDevices.get(position + i).close(); } mDevices.subList(position, position + count).clear(); mDeviceNumbers.subList(position, position + count).clear(); } @Override public void onMoved(int fromPosition, int toPosition) { mDevices.set(toPosition, mDevices.get(fromPosition)); mDevices.set(fromPosition, null); mDeviceNumbers.set(toPosition, mDeviceNumbers.get(fromPosition)); mDeviceNumbers.set(fromPosition, 0); } @Override public void onChanged(int position, int count, @Nullable Object payload) { // Nothing to be done } }); if (mDeviceListAdapter != null) { mDeviceListAdapter.setDeviceList(mDevices); diff.dispatchUpdatesTo(mDeviceListAdapter); } } public List getDeviceNumberList() { return mDeviceNumbers; } }