part-cw / LNhealth

Health-related apps using the LambdaNative framework
http://lnhealth.lambdanative.org
Other
22 stars 3 forks source link

Source code for ShareVitalSigns library #7

Open ddunsmuir opened 5 years ago

ddunsmuir commented 5 years ago

I have been having some issues with using this library. Making a second request of an app (RRate) does not work, but instead goes to a black screen with the breathing noises playing again from your previous run of RRate.

The issue appears to be on the RRate side as a version of RRate I built on July 24th currently works fine with my app, but it is unknown if the bug is due to something in LNHealth or some change in Lambdanative or else where.

Anyways, one thing I did notice is that the sharevitalsigns.jar file was updated in this repository in commit 213e3a4 on Aug 27, and yet there are no commits to the sharevitalsigns repository since July 5th (when the jar file was also updated). So I am wondering what the changes were and can we have these committed to that repository?

ionathanch commented 5 years ago

I might've forgotten to commit the changes to sharevitalsigns, but looking at the Aug 27th commit the only changes should have been adding POFILES and POWITHFILES, so something like adding

public static final int MEASURE_POFILES = 128;
public static final int MEASURE_POWITHFILES = MEASURE_PO | MEASURE_POFILES;
...
public static final String N_POFILES = "POFILES";
public static final String N_POWITHFILES = "POWITHFILES";
...
public static final String V_POFILES = libraryclassname + "Value_POFILES";
public static final String V_POWITHFILES = libraryclassname + "Value_POWITHFILES";
...

public static final String C_POFILES = libraryclassname + "Confidence_POFILES";
public static final String C_POWITHFILES = libraryclassname + "Confidence_POWITHFILES";
...
public static final String[] V_NAMELIST = {V_HR, V_RR, V_SPO2, V_TEMP, V_BPSYS, V_BPDIA, V_RRTAPS, V_POFILES};
public static final String[] C_NAMELIST = {C_HR, C_RR, C_SPO2, C_TEMP, C_BPSYS, C_BPDIA, C_RRTAPS, C_POFILES};
public static final String[] N_NAMELIST = {N_HR, N_RR, N_SPO2, N_TEMP, N_BPSYS, N_BPDIA, N_RRTAPS, N_POFILES};

I'll add them in and test it by next Saturday (if you haven't already by then).

mgorges commented 5 years ago

I have added the files as requested (in both the master and the androidstudio) branches. However, I don't know how to test/redeploy this.

mgorges commented 5 years ago

@ionathanch - the file I found (and added) didn't have the N_POWITHFILES; V_POWITHFILES, and C_POWITHFILES in them, as I guess they were not needed?

ddunsmuir commented 5 years ago

Building a .jar file with the commit @mgorges made to the sharevitalsigns repository allows me to get back the pulse ox values, but does not fix this black screen issue when requesting a second time. When I have access to another computer, I may try the android studio branch and building with android studio, since when I build the jar it is MUCH bigger than the currently checked in jar file.

ionathanch commented 5 years ago

@mgorges Yeah, the namelists are for individual vital signs, so there's no POWITHFILES (or BP or PO or RRATE).

@ddunsmuir I can successfully build the .jar file on Android studio using the Gradle task (as described in #4) but I don't have anything to request for RRATE (no access to HybridPocketDoc) so I think you'll have to look into the black screen issue. I suspect it might have to do with finish() not terminating the app properly...?

ddunsmuir commented 5 years ago

@ionathanch I have added an app DemoRRateRequestor with buttons to call RRate with the two different states. You can see that if you use this with a current build of RRate, then after you come back from RRate and then press either of the buttons again it goes to a black screen with the breathing noises.

If I use this app with an old version of RRate (built using lambdanative 525e863 and LNhealth 89c27d3) then you do not have this problem and everything works great. Thus, the problem is on the provider side, not the requestor side. Additionally, it is with the library as I have the same issue with another app.

You may be right, that it has to do with finish().

ddunsmuir commented 5 years ago

On Android, the following occurs when making the initial request. This is independent of the black screen problem. It occurs even with an older version of RRate, but I have included the current message here, to match correct current line numbers.

W/Bundle (25227): Key ShareVitalSignsMeasure expected String but value was a java.lang.Integer. The default value was returned. W/Bundle (25227): Attempt to cast generated internal exception: W/Bundle (25227): java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String W/Bundle (25227): at android.os.BaseBundle.getString(BaseBundle.java:921) W/Bundle (25227): at android.content.Intent.getStringExtra(Intent.java:5258) W/Bundle (25227): at org.ecemgroup.sharevitalsigns.library.ShareVitalSigns.chkIntent(ShareVitalSigns.java:391) W/Bundle (25227): at org.ecemgroup.rrate.RRate.registerVitalSigns(RRate.java:475) W/Bundle (25227): at org.ecemgroup.rrate.myRenderer.nativeEvent(Native Method) W/Bundle (25227): at org.ecemgroup.rrate.xGLSurfaceView.onResume(RRate.java:686) W/Bundle (25227): at org.ecemgroup.rrate.RRate.onResume(RRate.java:339) W/Bundle (25227): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1267) W/Bundle (25227): at android.app.Activity.performResume(Activity.java:6195) W/Bundle (25227): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3211) W/Bundle (25227): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3257) W/Bundle (25227): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2600) W/Bundle (25227): at android.app.ActivityThread.access$800(ActivityThread.java:178) W/Bundle (25227): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1470) W/Bundle (25227): at android.os.Handler.dispatchMessage(Handler.java:111) W/Bundle (25227): at android.os.Looper.loop(Looper.java:194) W/Bundle (25227): at android.app.ActivityThread.main(ActivityThread.java:5624) W/Bundle (25227): at java.lang.reflect.Method.invoke(Native Method) W/Bundle (25227): at java.lang.reflect.Method.invoke(Method.java:372) W/Bundle (25227): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959) W/Bundle (25227): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754) W/Bundle (25227): Key ShareVitalSignsMeasure expected String but value was a java.lang.Integer. The default value was returned. W/Bundle (25227): Attempt to cast generated internal exception: W/Bundle (25227): java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String W/Bundle (25227): at android.os.BaseBundle.getString(BaseBundle.java:921) W/Bundle (25227): at android.content.Intent.getStringExtra(Intent.java:5258) W/Bundle (25227): at org.ecemgroup.sharevitalsigns.library.ShareVitalSigns.getVitalSignsRequested(ShareVitalSigns.java:417) W/Bundle (25227): at org.ecemgroup.rrate.RRate.getVitalSign(RRate.java:462) W/Bundle (25227): at org.ecemgroup.rrate.RRate.registerVitalSigns(RRate.java:486) W/Bundle (25227): at org.ecemgroup.rrate.myRenderer.nativeEvent(Native Method) W/Bundle (25227): at org.ecemgroup.rrate.xGLSurfaceView.onResume(RRate.java:686) W/Bundle (25227): at org.ecemgroup.rrate.RRate.onResume(RRate.java:339) W/Bundle (25227): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1267) W/Bundle (25227): at android.app.Activity.performResume(Activity.java:6195) W/Bundle (25227): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3211) W/Bundle (25227): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3257) W/Bundle (25227): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2600) W/Bundle (25227): at android.app.ActivityThread.access$800(ActivityThread.java:178) W/Bundle (25227): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1470) W/Bundle (25227): at android.os.Handler.dispatchMessage(Handler.java:111) W/Bundle (25227): at android.os.Looper.loop(Looper.java:194) W/Bundle (25227): at android.app.ActivityThread.main(ActivityThread.java:5624) W/Bundle (25227): at java.lang.reflect.Method.invoke(Native Method) W/Bundle (25227): at java.lang.reflect.Method.invoke(Method.java:372) W/Bundle (25227): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959) W/Bundle (25227): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754) D/VitalSign(25227): reading vital requested:2 D/NotificationService( 734): Show pkg=org.ecemgroup.rrate callback=android.app.ITransientNotification$Stub$Proxy@ce803e8 W/Bundle (25227): Key ShareVitalSignsMeasure expected String but value was a java.lang.Integer. The default value was returned. W/Bundle (25227): Attempt to cast generated internal exception: W/Bundle (25227): java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String W/Bundle (25227): at android.os.BaseBundle.getString(BaseBundle.java:921) W/Bundle (25227): at android.content.Intent.getStringExtra(Intent.java:5258) W/Bundle (25227): at org.ecemgroup.sharevitalsigns.library.ShareVitalSigns.getVitalSignsRequested(ShareVitalSigns.java:417) W/Bundle (25227): at org.ecemgroup.rrate.RRate.getVitalSign(RRate.java:462) W/Bundle (25227): at org.ecemgroup.rrate.myRenderer.nativeEvent(Native Method) W/Bundle (25227): at org.ecemgroup.rrate.xGLSurfaceView.onResume(RRate.java:686) W/Bundle (25227): at org.ecemgroup.rrate.RRate.onResume(RRate.java:339) W/Bundle (25227): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1267) W/Bundle (25227): at android.app.Activity.performResume(Activity.java:6195) W/Bundle (25227): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3211) W/Bundle (25227): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3257) W/Bundle (25227): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2600) W/Bundle (25227): at android.app.ActivityThread.access$800(ActivityThread.java:178) W/Bundle (25227): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1470) W/Bundle (25227): at android.os.Handler.dispatchMessage(Handler.java:111) W/Bundle (25227): at android.os.Looper.loop(Looper.java:194) W/Bundle (25227): at android.app.ActivityThread.main(ActivityThread.java:5624) W/Bundle (25227): at java.lang.reflect.Method.invoke(Native Method) W/Bundle (25227): at java.lang.reflect.Method.invoke(Method.java:372) W/Bundle (25227): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959) W/Bundle (25227): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754) D/VitalSign(25227): reading vital requested:2

When you then go to request RRate again (current build):

11-05 13:52:36.540: E/InputDispatcher(734): channel '1b41cdc2 org.ecemgroup.rrate/org.ecemgroup.rrate.RRate (server)' ~ Channel is unrecoverably broken and will be disposed!

ddunsmuir commented 5 years ago

Following the instructions for AndroidStudio that you left, I was able to generate a jar file the exact same number of bytes as the one on this repository. Modifying the code to set back some of the changes in 500c2a5cff, namely setting back getStringExtra -> getExtras().getString getIntExtra -> getExtras().getInt the Exceptions no longer occur, yet the black screen issue remains.

ddunsmuir commented 5 years ago

Upon further investigation it seems like this is due to some commit in lambdanative between 525e863 and the current ec4fb33. I built with an old LNhealth and the problem persisted. When I built also with the old Lambdanative commit it disappeared. I'll need to look into it further tomorrow.

ddunsmuir commented 5 years ago

@ionathanch the culprit is bd06a846ce in lambdanative, specifically the change to loaders/android/bootstrap.java.in. Reverting this one file fixes the black screen issue. Unfortunately if I revert that change it does break the media scanner fix. That is, the media scanner does not run without it. I'm not sure of the best solution for this.

ionathanch commented 5 years ago

Perhaps the media scanner should be called on a per-app basis, since the majority of the apps (IIRC) don't write files to the filesystem, so if an app makes a file change and is run on Android it will call the scanner, and not the event loop?

ddunsmuir commented 5 years ago

That's not ideal, but I agree that may be the best thing to do at this point. We'll just have to document that it's necessary to call an extra thing if you want your file system updated when your app quits. So would we make this happen optionally? You would still to not do the pause when finishing for those apps you wish to run it, right? Or are you moving all the code to the app side? What would this look like within the app? In our scenario of RRate and the DemoRRateRequestor, the media scanner could be run when the requestor is being terminated.