I'd like to monitor changes to another applications SQLite database. Since the Android doesn't allow me to access another application's internal data, I need a root application which is exactly what mine is.
Is there a way I could monitor changes to a file on the system and trigger an event in my application?
I've Googled around and seen people recommend using FileObserver
class but this wouldn't work for protected files. Any other suggestions?
--
I've been looking for answer for this but I haven't found any. I've tried these two sei-promising techniques but I couldn't get them to work.
- All the files in an application's data directory are owned by that application's user and group.
FileObserver
respects Linux permissions and therefore I can't seem to use it to monitor a database/file in another application's data directory.
I'm wondering if this was possible if I could somehow elevate my application's Linux process to run as root
. This isn't easy either as it would mean toying with the setuid
, setguid
mechanism which I don't have much idea about.
- I tried creating a symbolic link from the other application's database file into my application's data directory. I added all permissions on the symbolic link and then used
FileObserver
to monitor it but this didn't work either. Maybe I did something wrong but my best guess that in Linux, symbolic-link permissions are useless. The permissions on a symbolic link that are respected are that of the target file/directory.
There might be way using JNI and the inotify.h
files but I'm not sure about how to go about this.
I don't want to poll the database from my application. I'd like to have an event trigger mechanism.
Iff you have root access, why not update file permissions to allow group read access to the file in question? i.e.
App2 user should now have read access to file, FileObserver will work.
FYI symbolic links mirror (i.e. respect) the permissions of the file that is being pointed to.
You can't access it from Java.
One way is poll: to run
ls -l /data/data/com.target.app/databases/data.db
and get time-stamp periodically.Or perhaps use
watch
ortail
commands.May be a background service can run this and issue a local broadcast.
Other way is to ship SQLite3 binary with your app, start process as root, and supply commands to it. I think many apps like titanium etc, do this.
Update: Here's an SQLite3 project: http://code.google.com/p/sqlite3-android/
inotify
is the way to go here but you'll need something like the command-lineinotifywait
utility frominotify-tools
, so that you can elevate it withsu
.You can either write your own (it's super easy) or use an existing port.
Then, you run it elevated, in a separate thread, and either wait for it to tell you there's a change or to close down (depending on whether you run
inotifywatch
orinotifywait
).P.S. This will likely fail miserably on 4.3 onwards with the SELinux contexts and whatnot.
One option would be to encapsulate your database with a content provider, and then the other application can subscribe for changes in the tables/URIs with the ContentObserver class