I’m developing a library project that will be integrated into some popular android applications which can be seen in Google Play.
Let assume that user can have two or more applications installed, and each one can integrate my library. The library have some specific code used to detect changes of environment’s state. The state is simply sent to my server. The problem is that environment state processing takes a lot of CPU power, but in a short period of time. Cycles of processing are started by AlarmManager, using “non wake up” broadcasts that launch proper IntentService.
My goal is to implement the library such way, that only one instance integrated into application can do the work. I mean only one library module should act as “active”. If there are more applications installed on user’s device – then they shouldn’t overlap.
How to achieve it? I was thinking about some kind of permission validation, and cross package detection, but couldn’t imagine how to implement it.
I have made some additional researches, and managed to find a satisfying solution.
Here it comes:
A library has to be developed in a way, that each application which integrates it – publishes broadcast receiver with known action, eg. com.mylib.ACTION_DETECT.
The library has to have additional Service, that publishes some AIDL interface, which helps with making decision – if current instance of library can be made active. The AIDL can have some useful methods for example getVersion(), isActive(), getUUID().
The pattern for making decision is: if current instance has higher version number, that other one – it will become active. If current instance has lower version – it will deactivate itself, or stay deactivated if it is already deactivated. If current instance has equal version to other instance, then if other instance is not active, and other library’s uuid is lower (through compareTo method) – it will activate itself. In other condition – it will deactivate itself. This cross checking ensures, that each library will make decision on its own – there will be no ambiguous cases, because each library will fetch required data from published AIDL backed Service of other libary instances in other apps.
Next step is to prepare an IntentService, that is started each time new package is removed or added, or the application with library is started first time. The IntentService queries all packages for broadcast receivers, which implement com.mylib.ACTION_DETECT.
Then it iterates through detected packages (rejecting it’s own package), and binds to AIDL backed service of each other instance (the class name of AIDL service will be always the same, only application package would be different). After completing binding – we have clear situation – if applied pattern results “positive” (our instance has better version or higher uuid, or has been active already) then it implies, that other instances figured out themselves as “negative”, and deactivated themselves. Of course the pattern has to be applied on each bound AIDL service.
I apologize for my bad English.
Code of working ConfictAvoidance solution:
IntentService class, that supports binding, so it is also AIDL backed service mentioned above. There is also BroadcastReceiver, which starts conflict checks.
AIDL file:
Sample manifest:
Action:
It is the common action, which is used to detect other apps with the library.
Log usage may look weird, but I use custom wrapper, which supports formatting, to decrease StringBuffers overhead when debugging.