Tuesday, June 14, 2011

Hello, SharedSource!

I've spent the last few days working on methods for registering and unregistering external content providers. Here is the scenario what I came up with:

1. User installs Historify.
2. User installs a 3rd party event provider application (aka Client) that hosts an external source (aka SharedSource).
3. Historify receives the ACTION_PACKAGE_ADDED system broadcast intent, which indicates that a new application has been installed.
4. The application might contain a SharedSource, so Historify addresses the new application to identify itself. This is achieved by broadcasting the BROADCAST_REQUEST_REGISTER_SOURCE Intent. The package name of the newly installed application is added as Intent extra.
5. The newly installed Client declares a Broadcast Intent Receiver called which receives this Intent. The package name Intent extra equals to the Client's package name which indicates that the Intent is sent to this particular application. (Previously installed Clients also receive the Broadcast Intent, but they could filter it out).
6. The newly installed Client registers itself to Historify (by sending the REGISTER_SOURCE Intent) via the BridgeService, which is an IntentService declared in Historify's package.
7. The BridgeService adds the newly registered SharedSource to Historify as a new external source, and posts a Notification to notify the user about the successful registration.

And what if the user installs several Clients BEFORE installing Historify? To detect these applications, Historify also sends the BROADCAST_REQUEST_REGISTER_SOURCE on its first startup, but without adding the package name Intent extra. In this case, all Clients will respond to the Intent, and they all will be calling the BridgeService to register themselves.

The only issue with that is regarding permissions. I got the idea to define my own permission called .permission.USE_BRDIGE that all Clients should hold if they want to use the BridgeService. So every Client that adds the <uses-permission .... /> tag to its manifest, could use the BridgeService, and if an unauthorized application calls the Service, it gets a SecurityException.

The problem is that if the user installs a Client first, way before installing Historify, the <uses-permission> tag will be IGNORED by the system's package manager, since the USE_BRIDGE permission is not registered in the system, and later the permission will not be granted. You could read about this at http://stackoverflow.com/questions/4567812/define-a-permission-for-third-party-apps-to-use-in-android/4569137#4569137

So, to notify the user about this issue, if REGISTER_SOURCE gets a SecurityException, a notification will be displayed which says that the user need to reinstall the Client to get it work with Historify.  When reinstalling the Client, its <uses-permission> will not be ignored this time (since Historify registered it in the system's permission collection), and it will work fine with Historify (You could test this behaviour, see below).

And finally, what if the user uninstalls a Client? In this case, Historify should automatically delete the SharedSource associated with the removed application. Here's the scenario for this:

1. User uninstalls a Client.
2. Historify receives the ACTION_PACKAGE_REMOVED Broadcast Intent.
3. The UID (UNIX user id) of the uninstalled package is provided as Intent extra. Based on that information, Historify could detect that there is an existing registered Source associated with that UID (since UID is stored in the SourcesProvider).
4. The SharedSource will be deleted from the SourcesProvider.

To test the described scenarios, I added a sample project called HelloSharedSource, which is an application that contains a simple event provider.

To try out source registration:
1. Install Historify
2. Install HelloSharedSource --> it will be registered automatically, and a notification will appear.

To try out the issue with permissions:
1. Uninstall everything.
2. Install HelloSharedSource
3. Install Historify --> the notification about the error will appear.
4. Reinstall HelloSharedSource --> it will be registered.

Note that HelloSharedSource also contains the helper classes that future Client applications shall use to interact with Historify. Currently these classes are added to the project as .java files; however, after finalizing the source registration mechanism, they should be placed in a .jar file.

No comments:

Post a Comment