1

I have looked at several posts in stack overflow related to this topic and the closest I can get is sharing data between APKs using content providers.

What I am looking to do is to first install my application which scans for and connects to Bluetooth Low Energy health devices that follow the BT SIG standards. What I am trying to support is the addition of plugins that will handle third-party proprietary health devices.

I will need to be able to query for such installed plugins or extensions. I will need to obtain some information from the plugin such as the UUID of their proprietary service so I can catch an advertisement from that device.

I will then need to pass the advertisement to that plugin. The plugin will connect and handle the device, and return certain information back to my app, including the measurement data. Note that the plugin will have to engage several Android-specific BTLE APIs; it won't be basic Java code!

These third party plugins are to be developed independently and a user can download them as they become available and therefore add support for the proprietary device.

One can clearly add plugins for a Java app on Windows or Linux. However, is this even possible to do on Android? If someone can point me to the correct documentation, tutorials, etc. I would really appreciate it. I have not been able to put the correct words together in my google searches to find it.

Perhaps the only solution is to create a second APK and communicate through a 'privatized' Broadcast receiver? If there is some type of plugin support I am sure it would make life easier.

====================== FURTHER CONSIDERATIONS =========================== The goal here is to have addable proprietary services that handle proprietary Bluetooth Health Devices my handler does not (it only handles standards). The proprietary service takes advertisement info from my app, connects to the device, gets the data, and sends it back in a callback.

Here is the problem: there can be multiple such services, and I do not know their names and I do not know how many there are. However, all implement the same IPC interface (common AIDL file). How can I find out how many such services there are? Is this a job only a BroadcastReceiver can handle?

Brian Reinhold
  • 2,313
  • 3
  • 27
  • 46
  • 1
    For how you appear to be defining "plugin" (some code that you dynamically load), your primary problem is security. As a result, Google bans dynamic code-loading by apps on the Play Store. However, there are many different IPC patterns to use between apps, not just broadcasts (bound services, started services, `ContentProvider`, etc.). – CommonsWare Feb 05 '20 at 22:51
  • 1
    @CommonsWare I've seen you post a lot of knowledgeable answers and comments as I have looked around this issue. To be honest, I was hoping to avoid doing one of those IPC patterns and have a more tight coupling between the plugin and the app that runs the plugin. The plugin would only be good for the primary application. But I guess that is not an option. – Brian Reinhold Feb 06 '20 at 09:29
  • "But I guess that is not an option" -- if you are distributing via the Play Store, correct. Basically, dynamic code loading from writable locations greatly amplifies the damage that can be caused by other security flaws. For example, the backport of the multidex stuff for Android 4.4 and older uses dynamic code loading from writable locations. Attackers have used bugs (e.g., malformed ZIPs handed to an app that blindly unZIPped them) to replace those extra DEX blobs with malware-laden alternatives. The apps then run that revised code, with bad results. – CommonsWare Feb 06 '20 at 12:01
  • @CommonsWare now that I have looked at this problem further I thought maybe the best approach would be Binders using AIDL or a Message/Handler option. Both look good except for one thing. I have added that in the above question - hope you can look at it! – Brian Reinhold Mar 20 '20 at 19:15

1 Answers1

0

How can I find out how many such services there are?

You can use PackageManager for that sort of introspection. Given some of Android R's changes in this area, you probably want to do this:

  1. Add an <intent-filter> to the <service>, advertising a custom Intent action that you will use for all such services.

  2. Use PackageManager and queryIntentServices() to find all of the services that implement that <intent-filter>.

You can see the basic mechanics for that in this sample app. In my case, I happened to choose the fully-qualified class name of my IDownload interface as my custom action string, but that is certainly not required. And in my case, I am only expecting one such service.

Bonus points for checking to see if the service is signed by the expected signing key, so malware does not try offering up a service and tricking you into using it. This sample app expands on the previous one and handles that. However, these samples are a bit old, so there may be additional work needed for more recent versions of Android.

FWIW, both of those samples are covered in this book.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I take it you wrote that e-book. No wonder you know everything about this stuff. Here is a weird question, if this remote process (which will only ever do anything when accessed by my app) requires permissions like LOCATION is it sufficient that my app had the user grant those permissions? – Brian Reinhold Mar 20 '20 at 20:09
  • That being said, I will try your approach and see if I can get something to work. Thanks. – Brian Reinhold Mar 20 '20 at 20:10
  • @BrianReinhold: "is it sufficient that my app had the user grant those permissions?" -- the app using the permission needs to request it. So, if the service needs that permission, the service needs to request it and have enough of a UI to do that. "I take it you wrote that e-book" -- as a matter of fact, yes. :-) – CommonsWare Mar 20 '20 at 20:12