diff --git a/app/build.gradle b/app/build.gradle index 321863d615cb36775b630d58e4edd1721a5f7a06..9e758c65829d8146f4c010207d6503460287bed2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,7 +56,7 @@ def getBugfenderApiKey() { android { compileSdkVersion 23 buildToolsVersion "23.0.3" - // FIXME - replace with URLConnection. This is used in GetHmacAndKeyActivity. + // FIXME - replace with URLConnection. This is used in ManageCNLActivity. useLibrary 'org.apache.http.legacy' applicationVariants.all { variant -> diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f7d7185b04799440fc232b3ffd10ef632e76220c..4f075c37ba2f7387d322e3ed95c22c04eb2b6368 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -63,10 +63,8 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> - <activity - android:name=".medtronic.GetHmacAndKeyActivity" - android:label="@string/title_activity_login" - android:theme="@style/SettingsTheme" /> + + <activity android:name=".medtronic.ManageCNLActivity"/> <activity android:name=".medtronic.StatusActivity" /> diff --git a/app/src/main/java/info/nightscout/android/medtronic/GetHmacAndKeyActivity.java b/app/src/main/java/info/nightscout/android/medtronic/GetHmacAndKeyActivity.java deleted file mode 100644 index dfd43740a7f4ce86fafde82fc746d661476fd109..0000000000000000000000000000000000000000 --- a/app/src/main/java/info/nightscout/android/medtronic/GetHmacAndKeyActivity.java +++ /dev/null @@ -1,130 +0,0 @@ -package info.nightscout.android.medtronic; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.annotation.TargetApi; -import android.app.LoaderManager.LoaderCallbacks; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Loader; -import android.database.Cursor; -import android.graphics.Color; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; -import android.support.v7.app.AlertDialog; -import android.support.v7.app.AppCompatActivity; -import android.text.Html; -import android.text.TextUtils; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputMethodManager; -import android.widget.EditText; -import android.widget.TextView; - -import com.mikepenz.google_material_typeface_library.GoogleMaterial; -import com.mikepenz.iconics.IconicsDrawable; - -import org.apache.commons.lang3.ArrayUtils; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.util.EntityUtils; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.ArrayList; -import java.util.List; - -import info.nightscout.android.R; -import info.nightscout.android.medtronic.message.MessageUtils; -import info.nightscout.android.model.medtronicNg.ContourNextLinkInfo; -import io.realm.Realm; -import io.realm.RealmResults; -import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper; - -/** - * A login screen that offers login via username/password. - */ -public class GetHmacAndKeyActivity extends AppCompatActivity implements LoaderCallbacks<Cursor> { - - // UI references. - private TextView mRegisteredStickView; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_login); - - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setTitle("Registered Devices"); - - mRegisteredStickView = (TextView) findViewById(R.id.registered_usb_devices); - - showRegisteredSticks(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - break; - } - return true; - } - - @Override - protected void attachBaseContext(Context newBase) { - super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase)); - } - - private void showRegisteredSticks() { - Realm realm = Realm.getDefaultInstance(); - - RealmResults<ContourNextLinkInfo> results = realm.where(ContourNextLinkInfo.class).findAll(); - - String deviceTableHtml = ""; - - for (ContourNextLinkInfo info : results) { - String longSerial = info.getSerialNumber(); - String key = info.getKey(); - - deviceTableHtml += String.format("<b>Serial Number:</b> %s %s<br/>", longSerial, key == null ? "✘" : "✔"); - } - - mRegisteredStickView.setText(Html.fromHtml(deviceTableHtml)); - } - - @Override - public Loader<Cursor> onCreateLoader(int id, Bundle args) { - return null; - } - - @Override - public void onLoadFinished(Loader<Cursor> loader, Cursor data) { - } - - @Override - public void onLoaderReset(Loader<Cursor> loader) { - } -} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java index 271992f8e578b03584070677f8335bb47d50f6fa..c7eae6e812f07531849b4842a71feb4bcac4cf20 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java +++ b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java @@ -276,24 +276,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc return true; } - private boolean hasDetectedCnl() { - if (mRealm.where(ContourNextLinkInfo.class).count() == 0) { - new AlertDialog.Builder(this, R.style.AppTheme) - .setTitle("No registered Contour Next Link devices") - .setMessage("To register a Contour Next Link you must first plug it in, and get a reading from the pump.") - .setCancelable(false) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }) - .setIcon(android.R.drawable.ic_dialog_alert) - .show(); - return false; - } - return true; - } - private boolean hasUsbPermission() { UsbManager usbManager = (UsbManager) this.getSystemService(Context.USB_SERVICE); UsbDevice cnlDevice = UsbHidDriver.getUsbDevice(usbManager, MedtronicCnlIntentService.USB_VID, MedtronicCnlIntentService.USB_PID); @@ -447,10 +429,8 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc } public void openUsbRegistration() { - if (hasDetectedCnl()) { - Intent loginIntent = new Intent(this, GetHmacAndKeyActivity.class); - startActivity(loginIntent); - } + Intent manageCNLIntent = new Intent(this, ManageCNLActivity.class); + startActivity(manageCNLIntent); } private String renderTrendHtml(PumpStatusEvent.CGM_TREND trend) { diff --git a/app/src/main/java/info/nightscout/android/medtronic/ManageCNLActivity.java b/app/src/main/java/info/nightscout/android/medtronic/ManageCNLActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..b995c0d92f014672185beb3e0f4812da02682aaa --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/ManageCNLActivity.java @@ -0,0 +1,156 @@ +package info.nightscout.android.medtronic; + +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Color; +import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.Button; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.TextView; + +import com.mikepenz.google_material_typeface_library.GoogleMaterial; +import com.mikepenz.iconics.IconicsDrawable; + +import java.util.ArrayList; + +import info.nightscout.android.R; +import info.nightscout.android.model.medtronicNg.ContourNextLinkInfo; +import io.realm.Realm; +import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper; + +/** + * A login screen that offers login via username/password. + */ +public class ManageCNLActivity extends AppCompatActivity { + private Realm mRealm; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_manage_cnl); + + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + + if (toolbar != null) { + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setHomeAsUpIndicator( + new IconicsDrawable(this) + .icon(GoogleMaterial.Icon.gmd_arrow_back) + .color(Color.WHITE) + .sizeDp(24) + ); + getSupportActionBar().setElevation(0); + getSupportActionBar().setTitle("Manage your devices"); + } + + mRealm = Realm.getDefaultInstance(); + + //generate list + ArrayList<ContourNextLinkInfo> list = new ArrayList<ContourNextLinkInfo>(); + + list.addAll(mRealm.where(ContourNextLinkInfo.class).findAll()); + + //instantiate custom adapter + CNLAdapter adapter = new CNLAdapter(list, this); + + //handle listview and assign adapter + ListView lView = (ListView) findViewById(R.id.cnl_list); + lView.setAdapter(adapter); + lView.addHeaderView(getLayoutInflater().inflate(R.layout.manage_cnl_listview_header, null)); + lView.setEmptyView(findViewById(R.id.manage_cnl_listview_empty)); //getLayoutInflater().inflate(R.layout.manage_cnl_listview_empty, null)); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + // avoid memory leaks + mRealm = null; + finish(); + break; + } + return true; + } + + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase)); + } + + private class CNLAdapter extends BaseAdapter implements ListAdapter { + private ArrayList<ContourNextLinkInfo> list = new ArrayList<>(); + private Context context; + + public CNLAdapter(ArrayList<ContourNextLinkInfo> list, Context context) { + this.list = list; + this.context = context; + } + + @Override + public int getCount() { + return list.size(); + } + + @Override + public Object getItem(int pos) { + return list.get(pos); + } + + @Override + public long getItemId(int pos) { + return pos; //list.get(pos).getSerialNumber(); + //just return 0 if your list items do not have an Id variable. + } + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + View view = convertView; + if (view == null) { + LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + view = inflater.inflate(R.layout.cnl_item, null); + } + + //Handle TextView and display string from your list + TextView listItemText = (TextView) view.findViewById(R.id.cnl_mac); + listItemText.setText(list.get(position).getSerialNumber()); + + //Handle buttons and add onClickListeners + Button deleteBtn = (Button) view.findViewById(R.id.delete_btn); + + deleteBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // deleting CNL form database + mRealm.executeTransaction(new Realm.Transaction() { + @Override + public void execute(Realm realm) { + ContourNextLinkInfo cnlToDelete = Realm.getDefaultInstance().where(ContourNextLinkInfo.class).equalTo("serialNumber", list.get(position).getSerialNumber()).findFirst(); + cnlToDelete.deleteFromRealm(); + list.remove(position); + notifyDataSetChanged(); + } + }); + + } + }); + + return view; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusResponseMessage.java index 377a651f6ca99d25254702a974fad53482437a97..67802a3cba0db138e3e5366f8b948b3714e36071 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusResponseMessage.java @@ -105,7 +105,6 @@ public class PumpStatusResponseMessage extends MedtronicSendMessageResponseMessa // Active insulin long rawActiveInsulin = statusBuffer.getShort(0x33) & 0x0000ffff; activeInsulin = new BigDecimal(rawActiveInsulin / 10000f).setScale(3, BigDecimal.ROUND_HALF_UP).floatValue(); - ; // CGM SGV sgv = (statusBuffer.getShort(0x35) & 0x0000ffff); // In mg/DL. 0 means no CGM reading diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml deleted file mode 100644 index 84cc07b2b8603da6a558869fe53fa029ae140bcd..0000000000000000000000000000000000000000 --- a/app/src/main/res/layout/activity_login.xml +++ /dev/null @@ -1,32 +0,0 @@ -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:gravity="center_horizontal" - android:orientation="vertical" - android:paddingBottom="@dimen/activity_vertical_margin" - android:paddingLeft="@dimen/activity_horizontal_margin" - android:paddingRight="@dimen/activity_horizontal_margin" - android:paddingTop="@dimen/activity_vertical_margin" - tools:context=".medtronic.GetHmacAndKeyActivity"> - - <!-- Login progress --> - - <ScrollView - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <LinearLayout - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:id="@+id/registered_usb_devices" /> - - </LinearLayout> - </ScrollView> - -</LinearLayout> diff --git a/app/src/main/res/layout/activity_manage_cnl.xml b/app/src/main/res/layout/activity_manage_cnl.xml new file mode 100644 index 0000000000000000000000000000000000000000..41cbee62fa6656797f97d05135d44ba4d57341ab --- /dev/null +++ b/app/src/main/res/layout/activity_manage_cnl.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + + tools:context=".medtronic.ManageCNLActivity"> + + <android.support.design.widget.AppBarLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> + + <android.support.v7.widget.Toolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" + app:layout_scrollFlags="scroll|enterAlways" + app:popupTheme="@style/ThemeOverlay.AppCompat.Light"> + + </android.support.v7.widget.Toolbar> + + </android.support.design.widget.AppBarLayout> + + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="10sp" + android:layout_marginTop="10sp" + android:baselineAligned="true" + android:gravity="bottom" + android:orientation="vertical"> + + <ListView + android:id="@+id/cnl_list" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + </LinearLayout> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/manage_cnl_listview_empty" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" + android:layout_marginLeft="10sp" + android:layout_marginRight="10sp" + android:visibility="gone"> + + <TextView + android:id="@+id/manage_cnl_listview_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/no_registered_contour_next_link_devices" + android:layout_marginBottom="10sp" + android:textSize="@dimen/materialize_typography_headline" + android:textStyle="bold" /> + + <TextView + android:id="@+id/manage_cnl_listview_text2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/to_register_a_contour_next_link_you_must_first_plug_it_in_and_get_a_reading_from_the_pump" /> + </LinearLayout> +</LinearLayout> diff --git a/app/src/main/res/layout/activity_status.xml b/app/src/main/res/layout/activity_status.xml index eff1081d8b651ab4bebcaae0eab44e4fb08dea67..5a7529d14946eef094b6b350374771d6c953c670 100644 --- a/app/src/main/res/layout/activity_status.xml +++ b/app/src/main/res/layout/activity_status.xml @@ -1,9 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - xmlns:app="http://schemas.android.com/apk/res-auto" + tools:context="info.nightscout.android.medtronic.StatusActivity" android:orientation="vertical"> @@ -28,7 +29,7 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/status_scroll_view" - android:fillViewport="true" > + android:fillViewport="true"> <LinearLayout android:orientation="vertical" diff --git a/app/src/main/res/layout/cnl_item.xml b/app/src/main/res/layout/cnl_item.xml new file mode 100644 index 0000000000000000000000000000000000000000..5ce73b2c268c0bfb9e233f7504435b64cc1c06d1 --- /dev/null +++ b/app/src/main/res/layout/cnl_item.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" > + + <TextView + android:id="@+id/cnl_mac" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_alignParentLeft="true" + android:paddingLeft="8dp" + android:textSize="18sp" + android:textStyle="bold" /> + + <Button + android:id="@+id/delete_btn" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_centerVertical="true" + android:layout_marginRight="5dp" + android:text="Delete" /> +</RelativeLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/manage_cnl_listview_header.xml b/app/src/main/res/layout/manage_cnl_listview_header.xml new file mode 100644 index 0000000000000000000000000000000000000000..163219fc423a3780d9375dfe9ad022b088b5600e --- /dev/null +++ b/app/src/main/res/layout/manage_cnl_listview_header.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/manage_cnl_listview_header" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="10sp" + android:text="@string/serial_number" + android:layout_marginLeft="10sp" /> + +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 65beeaa82185934f50c924838a501d2f4e794365..5833c20d33506c1cbb1d357cf8781ccd9ea78d12 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,7 +16,7 @@ <item>Info</item> <item>Debug</item> </string-array> - <string name="title_activity_login">CareLink login</string> + <string name="title_activity_manage_cnl">Manage your Contour Next Link devices</string> <!-- Strings related to login --> <string name="prompt_username">CareLink Username</string> @@ -54,4 +54,7 @@ <string name="preferences_poll_interval">poll interval</string> <string name="preferences_low_battery_poll_interval">poll interval on low pump battery</string> + <string name="no_registered_contour_next_link_devices">No registered Contour Next Link devices</string> + <string name="to_register_a_contour_next_link_you_must_first_plug_it_in_and_get_a_reading_from_the_pump">To register a Contour Next Link you must first plug it in, and get a reading from the pump.</string> + <string name="serial_number">Serial number</string> </resources>