Demo MMDI UI Simplification – Update

I was doing further simplification of the MMDI Demo app and I have made it so that Bluetooth is automatically turned on when the application starts, if it is not already on. Before, the user had to be prompted to enable Bluetooth but I found commented-out code that someone else had written in Java that I uncommented to make use of.

I also got rid of the need for the Refresh button I had earlier (I removed it) by creating an additional start screen at the beginning and placing a Start button there which essentially called the same function that Refresh did. This was because I was unable to find a way to have the application automatically retrieve the list of paired devices AFTER Bluetooth was enabled and that list was accessible in the case of Bluetooth not being enabled on startup. This initial start screen worked as a workaround.

I was attempting to allow the application to make the phone automatically enter discoverable mode without prompting the user, however I noticed that the library function which turns on discoverable mode (and is supposed to be equivalent to the enable function for Bluetooth which did work) did not actually enable discoverable mode. I tested this by temporarily inserting code in the Java function indirectly called by the Ready button which gave a popup stating whether or not the device was in discoverable. In the “automatic scenario”, it popped up false, and in the case where the user was prompted and I tapped Yes, it popped up true. More importantly, I was never able to retrieve data (nor was I even ever prompted for a PIN) from either medical device which was the reason I inserted the test code in the first place.

While I was thinking of a solution (I still have yet to allow discoverable mode without user prompt), I changed it so that the Ready button when clicked says “Pairing…” instead of “Retriving Data…” in the event the user chooses to pair to a new device. I am also in the middle of moving the About button to the home page and making it so that the about information is displayed on a separate screen.

Advertisements

Pedometer Working now…

This week Thursday and Friday I spent my time improving the Pedometer component.  At first the pedometer service was giving problems starting and stopping because of receiver registration issues.  Although much time was spent during the previous week analyzing the problem, the time was not wasted in vain.  One week gave me time to think things over and I realized yesterday as I went over the code what the problems were.  NULL POINTER EXCEPTIONS can be solved in more ways than one!  The corrections required aggressive programming techniques and by the end of the day the Service was running OK.  Next I was able to implement a Web SQL database to save the steps counted.  Now when the user stops and starts counting steps, their previous reading is saved.  While the pedometer is counting the user also has the option for steps counted and distance measure to be read aloud.  After this I started bringing the project into the bigger scheme of things.  I have started tidying up my code.  Next week I will continue doing so as well.  All the files must be added to the repository and pushed.  Another part includes launching the Pedometer activity from the actual demo.  I am starting to see where this may be done from.  Thanks for your time.

Weekly Work Update

Firstly, I Picked up the bluglu device and successfully run its Android sample application and the glucose simulator program, making things ready for further development of the integration of bluglu device.

The other part work is about ProGuard. One medical device vendor had expressed the concern about the protect of the sensitive code in our open source project. The sensitive code is mainly related to the process of receiving and parsing Bluetooth communication packets. This is actually a general issue because we usually sign the NDAs for obtaining Bluetooth protocol documents of most medical devices. It’s the ProGuard that can be used to address the issue.

ProGuard is a software tool used to shrink, optimize, and obfuscate Java bytecode by removing unused code and renaming classes, fields, and methods with semantically obscure names. ProGuard has been integrated into the Android build system and using it can result a smaller sized .apk file that is more difficult to reverse engineer. I’ve look into how to obfuscate an android project. The easy way is that , after configuring the project for ProGuard, build the application in release mode, then the .apk file or the jar file within the .apk file is optimized and obfuscated. It’s possible to use Ant task to do this process but it currently doesn’t work. Also, I attempted to take the Bluetooth packet parser package out of the MMDI project and build it into another independent project as a library project. Through using ProGuard on the Library project, we can create a obfuscated jar file which can be used by the MMDI project. There are still issues on this attempt. For example, the generic class ParcetParse cannot be recognized by its caller after the jar fie is optimized and obfuscated.

Finally, my current direction is on how to apply the vendor-provided Android jar file, which contains the service of communicating with medical devices, directly into the native code of our PhoneGap project.  The successful implementation will significantly facilitate our health research project, such as simplifying the develop process and ignoring the code obfuscation.

Demo MMDI UI Simplification – Update

I managed to find a temporary solution to the fact that I could not retrieve data from any medical device or proceed to the third screen when I pressed “Ready” on the second screen. I realized that for now, I could simply add temporary, hard-coded arguments for type and serial respectively in the connect() function.

connect: function() {

// ,type: “weight” // temporary hard-coded argument
// ,serial: “5090250438” // temporary hard-coded argument
,type: “blood pressure” // temporary hard-coded argument
,serial: “5090651014” // temporary hard-coded argument

}

Those arguments were originally in the code before I started simplifying the UI but they were dynamic values that were based on the choices the user selected when they specified the device type and entered its serial number. Since that part of the UI was removed, the values were likely either null or incorrect.

This actually worked when I attempted to retrieve data from the medical devices.

blood pressure

weight

The only thing left to do regarding simplification of the UI is to allow the application to connect to new devices again as it was able to per previous implementations beforehand.

Accessing Fitbit’s Web API

After learning how to send HTTP requests and receive JSON objects in an Android app,
I started working on getting OAuth authentication and access set up so I can access Withings and Fitbit’s web APIs.

So far I have only been COMPLETELY successful with Fitbit’s API, so I am going to outline how I did it below.

I chose to use a Java library called Scribe, which simplifies OAuth access,
since I was able to find a few tutorials on how to implement it in an Android app.
The library can be found here: https://github.com/fernandezpablo85/scribe-java

Scribe defines API objects that outline important URLs needed for an API’s OAuth authentication process.
The Fitbit API access class I made looks like this:

public class FitbitApi extends DefaultApi10a{
private static final String AUTHORIZE_URL = "https://www.fitbit.com/oauth/authorize?oauth_token=%s";

public String getAccessTokenEndpoint(){
return "https://api.fitbit.com/oauth/access_token";
}
public String getRequestTokenEndpoint(){
return "https://api.fitbit.com/oauth/request_token";
}
public String getAuthorizationUrl(Token requestToken){
return String.format(AUTHORIZE_URL, requestToken.getToken());
}
}

Scribe also uses a service object and serviceBuilder object that contains additional information regarding the API such as:

  • Api Key – A key obtained from the API provider after registering an application
  • API Secret – A value obtained from the API provider after registering an application
  • Callback – A URL that the API will send the user to after they have been authorized

The service for Fitbit looked like:


OAuthService service = new ServiceBuilder()
.provider(FitbitApi.class)
.apiKey("*") //replaced my app key with * for security
.apiSecret("*") //replace my app secret with * for security
.callback(getString(R.string.FitbitCallback)) //arbitary value. I used http://fitbit.com/oauth/callback which isn't a valid address
.debug() //for more verbose messages while testing
.build();

With that complete, all the setup for the Fitbit API is complete.
Now the OAuth requests begin.
The first thing that handles is a request for a Request Token.

final Token requestToken = service.getRequestToken();

With the request token successfully retrieved, the usr is sent to authorize the app by signing into their account with the API provider.


final String authURL = service.getAuthorizationUrl(requestToken);
webview.loadUrl(authURL);

This will load the sign-in page in the web-view i have defined for the Android app.
Once they sign in and choose to allow the app access to their account, they will be sent to the pre-defined callback URL.
I used http://fitbit.com/oauth/callback, but it doesn’t actually matter. This is only used for intercepting the user after the have been authorized.
The webview’s URL loading is modified to execute custom code when the callback URL is the target URL.


public boolean shouldOverrideUrlLoading(WebView view, String url)
{
//check for our custom callback protocol
if(url.startsWith(getString(R.string.FitbitCallback)))
{
//custom code
}
//otherwise use default behavior
return super.shouldOverrideUrlLoading(view, url);
}

The custom code finished the OAuth verification process.
First it gets a verifier value that will be passed from the API as a paramter in the callback URL.


Uri uri = Uri.parse(url);
String verifier = uri.getQueryParameter("oauth_verifier");
Verifier v = new Verifier(verifier);

This verifier can then be used to get an OAuth access token, the final step to getting the app authenticated for API access.


Token accessToken = service.getAccessToken(requestToken, v);

The app is now ready to make API calls. As a test, I was able to successfully request my own personal Fitbit profile information like so:


OAuthRequest request = new OAuthRequest(Verb.POST, PROTECTED_RESOURCE_URL);
service.signRequest(accessToken, request);
Response response = request.send();
System.out.println(response.getBody());

The request returned:


{"user":
{
"avatar":"http://www.fitbit.com/images/profile/defaultProfile_100_male.gif",
"avatar150":"http://www.fitbit.com/images/profile/defaultProfile_150_male.gif",
"country":"CA",
"dateOfBirth":"1992-08-29",
"displayName":"Dylan",
"distanceUnit":"en_US",
"encodedId":"27BYDD",
"foodsLocale":"en_US",
"fullName":"Dylan Segna",
"gender":"MALE",
"glucoseUnit":"METRIC",
"height":0,
"heightUnit":"en_US",
"locale":"en_US",
"memberSince":"2013-09-11",
"offsetFromUTCMillis":-14400000,
"strideLengthRunning":0,
"strideLengthWalking":0,
"timezone":"America/New_York",
"waterUnit":"en_US",
"weight":78.7,
"weightUnit":"en_US"
}
}

Demo MMDI UI Simplification – Update

From what I was doing before, I have added the third screen into the Demo MMDI application which works as intended. I have also added an “X” button at the top-right corner of the application (not bound to any screen) for the user to exit the application since the back button does not always exit the application upon first press.

Screen1

Screen2

Screen3

The medical information shown on the third screen is a result of a simulated connection (I temporarily placed this.emit(‘connection’, undefined, “test123”); ) at the top of the function in medicalDevicePlugin.js which calls ‘connection’ (these two functions were previously implemented by someone else) in mmdi.demo.js. This was so I could temporarily see the third screen. When I attempt to connect to the weight scale after using it by clicking “Ready” on the second screen, I am prompted to enter the PIN after about 45 seconds to a minute. After I enter the PIN, even after several minutes, I do not end up retrieving data from the device (the application stays on the second screen despite putting a line of code underneath the previously implemented code in ‘connection’ to display that data). When I place a test alert message at the top of the aforementioned function in medicalDevicePlugin.js, it pops up in the application when I press Ready, however, if I put a test alert at the top of ‘connection’, it will not pop up unless I manually call it with this.emit(‘connection’, undefined, “test123”);

Demo MMDI – New Interface – Update

Hi, I have once again made slight changes to the new UI ideas as follows:

– first, automatically enable Bluetooth and retrieve paired devices, then go to the initial screen
— the buttons regarding enabling/disable bluetooth or checking if its enabled can be removed from implementation
– on the initial screen, ask the user to select a paired device or to pair to a new one
— make the rest of the interface hidden for now
— place the “Request for Supported Devices” button under the list and rename it to “Refresh Device List”
— convert the “Request for Discoverable” button into the Next button for this screen
– on the next screen, prompt the user to turn the medical device on and to click a “Ready” button when they want to retrieve their medical data
— the “Ready” button is the “Connect to Medical Device” button renamed
— when the user clicks on the “Ready” button, it is changed to “Retrieving Data…” which will not perform any task if clicked
— there should be a Back button in case the user changes their mind on the device they wish to connect to
—– if the Ready button had already been clicked, it should ask the user if they’re sure they want to go back and if they are, then disconnect from discoverable mode
– as per previous implementations, the user will naturally be prompted for the PIN at this point
– once the data has been retrieved, it will be displayed on the next screen
— there will also be a button that says “Connect Again” which will ask the user if they’re sure they want to start over since the data would disappear, then re-request the page if they select yes
— below this button will be the About button

“Screens” will be implemented by hiding what is currently on the interface and revealing the next set of elements to the user.

Implementation-wise, I have completed the initial screen under the assumption the user never disables Bluetooth while Demo MMDI is running (which I had done/mentioned before), but the second screen is also nearly finished. I have to still have the user transferred to the third screen after receiving the data. In addition, there is a graphical bug where the Ready button on the second screen shrinks just enough to fit the text in it. Going back to the initial screen does not solve this (in fact, pressing the Back button also shrinks the Ready button). This is because they both edit the Ready button’s text through the jQuery text() function which shrinks the text. Although this does not affect the functionality of the program, it is still a bug because it would be confusing to the user. Here are some screenshots:

Screen1  Screen 1

Screen2 Screen 2

ShrunkButton This is what should and does happen when the Ready button is pressed with the exception that the button should not shrink.

ShrunkReadyButton Going to the initial screen with Back then coming here again results in a shrunken “Ready” whether or not I pressed the Ready button.