diff options
author | Javier <dev.git@javispedro.com> | 2021-03-20 23:57:51 +0100 |
---|---|---|
committer | Javier <dev.git@javispedro.com> | 2021-03-20 23:58:23 +0100 |
commit | 5dfa37788c7f039eff00b27cc0ca8b9b9a71f60e (patch) | |
tree | 6aea7cd13dc6a8cbb771ec1b510a5ac3cf8200f0 /app/src/main/java/com/javispedro/rempe | |
download | rempe-5dfa37788c7f039eff00b27cc0ca8b9b9a71f60e.tar.gz rempe-5dfa37788c7f039eff00b27cc0ca8b9b9a71f60e.zip |
Initial import
Diffstat (limited to 'app/src/main/java/com/javispedro/rempe')
6 files changed, 717 insertions, 0 deletions
diff --git a/app/src/main/java/com/javispedro/rempe/Device.java b/app/src/main/java/com/javispedro/rempe/Device.java new file mode 100644 index 0000000..4622eed --- /dev/null +++ b/app/src/main/java/com/javispedro/rempe/Device.java @@ -0,0 +1,231 @@ +package com.javispedro.rempe; + +import android.content.Context; +import android.util.Log; + +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.EventFlag; +import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult; +import com.dsi.ant.plugins.antplus.pccbase.AntPluginPcc; +import com.dsi.ant.plugins.antplus.pccbase.AntPlusCommonPcc; +import com.dsi.ant.plugins.antplus.pccbase.PccReleaseHandle; + +import java.math.BigDecimal; +import java.util.EnumSet; + +public class Device { + private final static String TAG = "Device"; + + private final int mDeviceNumber; + + private PccReleaseHandle<AntPlusEnvironmentPcc> mEnvPccHandle; + private AntPlusEnvironmentPcc mEnvPcc; + + private String mDeviceName; + + private final Reading mLastReading = new Reading(); + private int mLastRssi; + private RequestAccessResult mConnectResult; + private DeviceState mCurState; + + public interface DeviceObserver { + void onDeviceInfoChanged(); + void onDeviceStateChanged(); + void onDeviceNewReading(); + void onDeviceRssiChanged(); + } + private DeviceObserver mObserver; + + public Device(int deviceNumber) { + mDeviceNumber = deviceNumber; + mDeviceName = "dev-" + deviceNumber; + mConnectResult = RequestAccessResult.SUCCESS; + mCurState = DeviceState.DEAD; + } + + public void connect(Context context) { + Log.d(TAG, "connect (" + mDeviceNumber + ")"); + if (mEnvPccHandle != null) { + Log.w(TAG, "Already connected"); + } + mConnectResult = RequestAccessResult.SUCCESS; // Clear old connect result + mCurState = DeviceState.SEARCHING; + if (mObserver != null) { + mObserver.onDeviceStateChanged(); + } + mEnvPccHandle = AntPlusEnvironmentPcc.requestAccess(context, mDeviceNumber, 0, mResultReceiver, mDeviceStateChangeReceiver); + } + + public void close() { + Log.d(TAG, "close (" + mDeviceNumber + ")"); + if (mEnvPccHandle != null) { + mEnvPccHandle.close(); + mEnvPccHandle = null; + } + if (mEnvPcc != null) { + mEnvPcc = null; + } + mConnectResult = RequestAccessResult.SUCCESS; + mCurState = DeviceState.DEAD; + if (mObserver != null) { + mObserver.onDeviceStateChanged(); + } + } + + public void setObserver(DeviceObserver observer) { + mObserver = observer; + } + + public boolean isOpen() { + return mEnvPccHandle != null; + } + + @Override + public String toString() { + return super.toString() + "(" + mDeviceNumber + ")"; + } + + private void setEnvPcc(AntPlusEnvironmentPcc envPcc) { + if (mEnvPcc != null) { + mEnvPcc.releaseAccess(); + mEnvPcc = null; + } + mEnvPcc = envPcc; + final String deviceName = mEnvPcc.getDeviceName(); + final int deviceNumber = mEnvPcc.getAntDeviceNumber(); + Log.d(TAG, "handleConnection deviceName=" + deviceName + " deviceNumber=" + deviceNumber); + if (deviceNumber != mDeviceNumber) { + Log.e(TAG, "device number mismatch"); + } + mDeviceName = deviceName; + mEnvPcc.subscribeTemperatureDataEvent(mTemperatureDataReceiver); + mEnvPcc.subscribeRssiEvent(mRssiReceiver); + if (mObserver != null) { + mObserver.onDeviceInfoChanged(); + } + } + + public String getDeviceName() { + return mDeviceName; + } + + public Reading getLastReading() { + return mLastReading; + } + + public int getLastRssi() { + return mLastRssi; + } + + public DeviceState getCurrentDeviceState() { + return mCurState; + } + + public RequestAccessResult getConnectResult() { + return mConnectResult; + } + + private AntPluginPcc.IPluginAccessResultReceiver<AntPlusEnvironmentPcc> mResultReceiver = new AntPluginPcc.IPluginAccessResultReceiver<AntPlusEnvironmentPcc>() { + @Override + public void onResultReceived(AntPlusEnvironmentPcc result, RequestAccessResult resultCode, DeviceState initialDeviceState) { + Log.d(TAG, "onResultReceived resultCode=" + resultCode + " initialDeviceState=" + initialDeviceState); + mConnectResult = resultCode; + mCurState = initialDeviceState; + if (resultCode.equals(RequestAccessResult.SUCCESS)) { + setEnvPcc(result); + } + if (mObserver != null) { + mObserver.onDeviceStateChanged(); + } + + if (resultCode.equals(RequestAccessResult.SEARCH_TIMEOUT)) { + Log.d(TAG, "timeout"); + } + } + }; + + private AntPluginPcc.IDeviceStateChangeReceiver mDeviceStateChangeReceiver = new AntPluginPcc.IDeviceStateChangeReceiver() { + @Override + public void onDeviceStateChange(DeviceState newDeviceState) { + Log.d(TAG, "onDeviceStateChange newDeviceState=" + newDeviceState); + mCurState = newDeviceState; + if (mObserver != null) { + mObserver.onDeviceStateChanged(); + } + } + }; + + private final AntPlusEnvironmentPcc.ITemperatureDataReceiver mTemperatureDataReceiver = new AntPlusEnvironmentPcc.ITemperatureDataReceiver() { + @Override + public void onNewTemperatureData(long estTimestamp, EnumSet<EventFlag> eventFlags, BigDecimal currentTemperature, long eventCount, BigDecimal lowLast24Hours, BigDecimal highLast24Hours) { + Log.d(TAG, "onNewTemperatureData"); + mLastReading.timestamp = estTimestamp; + mLastReading.temperature = currentTemperature; + mLastReading.highLast24Hours = highLast24Hours; + mLastReading.lowLast24Hours = lowLast24Hours; + if (mObserver != null) { + mObserver.onDeviceNewReading(); + } + } + }; + + private final AntPlusCommonPcc.IRssiReceiver mRssiReceiver = new AntPlusCommonPcc.IRssiReceiver() { + @Override + public void onRssiData(long estTimestamp, EnumSet<EventFlag> eventFlags, int rssi) { + Log.d(TAG, "onRssiData rssi=" + rssi); + mLastRssi = rssi; + if (mObserver != null) { + mObserver.onDeviceRssiChanged(); + } + } + }; + + public static String deviceStateToString(Context context, DeviceState state) { + switch (state) { + case DEAD: + return context.getString(R.string.state_dead); + case CLOSED: + return context.getString(R.string.state_closed); + case SEARCHING: + return context.getString(R.string.state_searching); + case TRACKING: + return context.getString(R.string.state_tracking); + case PROCESSING_REQUEST: + return context.getString(R.string.state_processing); + case UNRECOGNIZED: + return context.getString(R.string.state_unrecognized); + default: + return context.getString(R.string.state_unknown); + } + } + + public static String connectionRequestAccessResultToString(Context context, RequestAccessResult result) { + switch (result) { + case SUCCESS: + return context.getString(R.string.connection_result_success); + case USER_CANCELLED: + return context.getString(R.string.connection_result_user_cancelled); + case CHANNEL_NOT_AVAILABLE: + return context.getString(R.string.connection_result_channel_not_available); + case OTHER_FAILURE: + return context.getString(R.string.connection_result_other_failure); + case DEPENDENCY_NOT_INSTALLED: + return context.getString(R.string.connection_result_dependency_not_installed); + case DEVICE_ALREADY_IN_USE: + return context.getString(R.string.connection_result_device_already_in_use); + case SEARCH_TIMEOUT: + return context.getString(R.string.connection_result_search_timeout); + case ALREADY_SUBSCRIBED: + return context.getString(R.string.connection_result_already_subscribed); + case BAD_PARAMS: + return context.getString(R.string.connection_result_bad_params); + case ADAPTER_NOT_DETECTED: + return context.getString(R.string.connection_result_adapter_not_detected); + case UNRECOGNIZED: + return context.getString(R.string.connection_result_unrecognized); + default: + return context.getString(R.string.connection_result_unknown); + } + } +}
\ No newline at end of file diff --git a/app/src/main/java/com/javispedro/rempe/DeviceListRecyclerViewListAdapter.java b/app/src/main/java/com/javispedro/rempe/DeviceListRecyclerViewListAdapter.java new file mode 100644 index 0000000..2288f20 --- /dev/null +++ b/app/src/main/java/com/javispedro/rempe/DeviceListRecyclerViewListAdapter.java @@ -0,0 +1,44 @@ +package com.javispedro.rempe; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.List; + +/** + * {@link RecyclerView.Adapter} that can display a {@link Device}. + */ +public class DeviceListRecyclerViewListAdapter extends RecyclerView.Adapter<DeviceViewHolder> { + + private List<Device> mList; + + @Override + @NonNull + public DeviceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.fragment_device, parent, false); + return new DeviceViewHolder(view); + } + + @Override + public void onBindViewHolder(final DeviceViewHolder holder, int position) { + holder.setDevice(mList.get(position)); + } + + @Override + public int getItemCount() { + if (mList != null) { + return mList.size(); + } else { + return 0; + } + } + + public void setDeviceList(List<Device> list) { + mList = list; + } +}
\ No newline at end of file diff --git a/app/src/main/java/com/javispedro/rempe/DeviceViewHolder.java b/app/src/main/java/com/javispedro/rempe/DeviceViewHolder.java new file mode 100644 index 0000000..9731471 --- /dev/null +++ b/app/src/main/java/com/javispedro/rempe/DeviceViewHolder.java @@ -0,0 +1,123 @@ +package com.javispedro.rempe; + +import android.content.Context; +import android.view.View; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult; + +import java.math.BigDecimal; + +public class DeviceViewHolder extends RecyclerView.ViewHolder implements Device.DeviceObserver { + private static final String TAG = "DeviceViewHolder"; + + private final View mView; + private final Context mContext; + + private final TextView mTemperatureView; + private final TextView mMinTemperatureView; + private final TextView mMaxTemperatureView; + private final TextView mNameView; + private final TextView mStatusView; + private final ProgressBar mSignalBar; + private final TextView mSignalLabel; + + private Device mDevice; + + public DeviceViewHolder(View view) { + super(view); + mView = view; + mContext = view.getContext(); + mNameView = view.findViewById(R.id.nameView); + mStatusView = view.findViewById(R.id.statusView); + mTemperatureView = view.findViewById(R.id.temperatureView); + mMinTemperatureView = view.findViewById(R.id.minTemperatureView); + mMaxTemperatureView = view.findViewById(R.id.maxTemperatureView); + mSignalBar = view.findViewById(R.id.signalBar); + mSignalLabel = view.findViewById(R.id.signalLabel); + } + + @Override + public String toString() { + return super.toString() + " '" + mNameView.getText() + "'"; + } + + public void setDevice(Device device) { + resetDisplay(); + if (mDevice != null) { + mDevice.setObserver(null); + } + mDevice = device; + if (mDevice != null) { + mNameView.setText(mDevice.getDeviceName()); + mDevice.setObserver(this); + } + } + + private void runOnUiThread(Runnable r) { + mView.post(r); + } + + private void resetDisplay() { + mTemperatureView.setText(mContext.getString(R.string.temperature_nothing)); + mMinTemperatureView.setText(mContext.getString(R.string.temperature_nothing)); + mMaxTemperatureView.setText(mContext.getString(R.string.temperature_nothing)); + mNameView.setText(""); + mStatusView.setText(""); + mSignalBar.setProgress(0); + mSignalLabel.setVisibility(View.INVISIBLE); + } + + private String formatTemperature(BigDecimal temp) { + final String value = temp.setScale(1, BigDecimal.ROUND_HALF_EVEN).toPlainString(); + return mContext.getString(R.string.temperature_celsius, value); + } + + @Override + public void onDeviceInfoChanged() { + runOnUiThread(() -> { + mNameView.setText(mDevice.getDeviceName()); + }); + } + + @Override + public void onDeviceStateChanged() { + runOnUiThread(() -> { + if (mDevice.getConnectResult() != RequestAccessResult.SUCCESS) { + mStatusView.setText(Device.connectionRequestAccessResultToString(mContext, mDevice.getConnectResult())); + } else { + mStatusView.setText(Device.deviceStateToString(mContext, mDevice.getCurrentDeviceState())); + } + }); + } + + @Override + public void onDeviceNewReading() { + runOnUiThread(() -> { + final Reading reading = mDevice.getLastReading(); + mTemperatureView.setText(formatTemperature(reading.temperature)); + mMinTemperatureView.setText(formatTemperature(reading.lowLast24Hours)); + mMaxTemperatureView.setText(formatTemperature(reading.highLast24Hours)); + }); + } + + private int rssiToMeterValue(float rssi) { + final float minThreshold = -100; + final float maxThreshold = 0; + + final float step = (maxThreshold - minThreshold) / 100; + + return Math.round((rssi - minThreshold) / step); + } + + @Override + public void onDeviceRssiChanged() { + runOnUiThread(() -> { + mSignalBar.setProgress(rssiToMeterValue(mDevice.getLastRssi())); + mSignalLabel.setVisibility(View.VISIBLE); + }); + } +} diff --git a/app/src/main/java/com/javispedro/rempe/MainActivity.java b/app/src/main/java/com/javispedro/rempe/MainActivity.java new file mode 100644 index 0000000..e458468 --- /dev/null +++ b/app/src/main/java/com/javispedro/rempe/MainActivity.java @@ -0,0 +1,264 @@ +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.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.preference.PreferenceManager; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.ListUpdateCallback; +import androidx.recyclerview.widget.RecyclerView; + +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 SharedPreferences.OnSharedPreferenceChangeListener mPrefsListener = new SharedPreferences.OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + switch (key) { + case Preferences.PREFS_DEVICES: + refreshDevices(); + break; + } + } + }; + + private final ArrayList<Integer> mDeviceNumbers = new ArrayList<Integer>(); + private final ArrayList<Device> mDevices = new ArrayList<Device>(); + + private DeviceListRecyclerViewListAdapter mDeviceListAdapter; + + private PccReleaseHandle<AntPlusEnvironmentPcc> 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()); + + RecyclerView list = findViewById(R.id.list); + list.setLayoutManager(new LinearLayoutManager(list.getContext())); + mDeviceListAdapter = new DeviceListRecyclerViewListAdapter(); + list.setAdapter(mDeviceListAdapter); + + refreshDevices(); + } + + @Override + protected void onDestroy() { + disconnectAll(); + mPrefs = null; + mDeviceListAdapter = 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_remove_all: + removeAllDevices(); + return true; + case R.id.action_settings: + return true; + } + + return super.onOptionsItemSelected(item); + } + + private void onConnectButtonClicked() { + searchForNewDevice(); + } + + public void searchForNewDevice() { + Log.d(TAG, "searchForNewDevice"); + if (mPccSearchHandle != null) { + mPccSearchHandle.close(); + mPccSearchHandle = null; + } + mPccSearchHandle = AntPlusEnvironmentPcc.requestAccess(this, this, mResultReceiver, mDeviceStateChangeReceiver); + } + + private AntPluginPcc.IPluginAccessResultReceiver<AntPlusEnvironmentPcc> mResultReceiver = new AntPluginPcc.IPluginAccessResultReceiver<AntPlusEnvironmentPcc>() { + @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 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<Integer> 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 removeAllDevices() { + List<Integer> list = new ArrayList<Integer>(); + 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<Integer> 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<Integer> getDeviceNumberList() { + return mDeviceNumbers; + } +}
\ No newline at end of file diff --git a/app/src/main/java/com/javispedro/rempe/Preferences.java b/app/src/main/java/com/javispedro/rempe/Preferences.java new file mode 100644 index 0000000..41c943c --- /dev/null +++ b/app/src/main/java/com/javispedro/rempe/Preferences.java @@ -0,0 +1,43 @@ +package com.javispedro.rempe; + +import android.content.SharedPreferences; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import static android.content.ContentValues.TAG; + +class Preferences { + public final static String PREFS_DEVICES = "devices"; + + public static List<Integer> getDeviceNumbers(SharedPreferences prefs) { + ArrayList<Integer> result = new ArrayList<Integer>(); + + try { + StringTokenizer st = new StringTokenizer(prefs.getString(PREFS_DEVICES, ""), ","); + while (st.hasMoreTokens()) { + result.add(Integer.parseInt(st.nextToken())); + } + } catch (java.lang.Exception ex) { + // Ensure that at least we can recover from a corrupted preferences situation... + Log.e(TAG, ex.toString()); + } + + return result; + } + + public static void saveDeviceNumbers(SharedPreferences prefs, List<Integer> list) { + StringBuilder sb = new StringBuilder(); + for (Integer i : list) { + sb.append(i.toString()); + sb.append(","); + } + final String pref = sb.toString(); + Log.d(TAG, "saveDeviceNumbers: " + pref); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(PREFS_DEVICES, pref); + editor.apply(); + } +} diff --git a/app/src/main/java/com/javispedro/rempe/Reading.java b/app/src/main/java/com/javispedro/rempe/Reading.java new file mode 100644 index 0000000..a49e29a --- /dev/null +++ b/app/src/main/java/com/javispedro/rempe/Reading.java @@ -0,0 +1,12 @@ +package com.javispedro.rempe; + +import java.math.BigDecimal; + +public class Reading { + public long timestamp; + + public BigDecimal temperature; + + public BigDecimal lowLast24Hours; + public BigDecimal highLast24Hours; +} |