Observing changes in Android content observer for Audio.Media.EXTERNAL_CONTENT_URI
Asked Answered
A

2

13

I am developing an Android app in which I have to detect changes in Android SD card for audio files with the file name, file path and operation performed upon it. Example if I am adding a file in my SD card then I want to know

  1. Name of the file which is added
  2. Path of the file
  3. Operation -- Add

Previously I Have tried file observer But for that I have to apply it on each and every directory. So I searched for some other solution and got the info about Audio.Media.EXTERNAL_CONTENT_URI. Then I created a content observer like this

UriObserver.java -- which is a content observer

class UriObserver extends ContentObserver {

    public UriObserver(Handler handler) {
        super(handler);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void onChange(boolean selfChange) {
        // TODO Auto-generated method stub
        super.onChange(selfChange);

        Log.d("INSTANT", "GETTING CHANGES");
    }

}

This is the code for registration for it

UriObserver observer = new UriObserver(new Handler());

Log.d("INSTANT", "registered content observer");

this.getApplicationContext()
    .getContentResolver()
    .registerContentObserver(
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, false,
    observer);

Log.d("INSTANT", "registered content observer");

It let me know that some change has been occur in sdcard related to audio files. But it doesn't gives any sort of info about which file has been added, edited or deleted.

Then I searched for for solution and got this post

Android: How to detect a change in MediaStore when connected over MTP

In this post some code is given by Bhiefer as an answer which I think it could work, so I tried to implement that but I am not able to do so.

What can I do for this?

Update

Can I query Audio.Media.EXTERNAL_CONTENT_URI for its latest changes? This code:

mCursor = context.getContentResolver().query(
                    Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, "_id");

mCursor.moveToLast();

doesn't give the latest changes. Is there any other method to get the latest changes?

Address answered 9/4, 2013 at 10:8 Comment(2)
Hi, i am facing same issue, did you get any solution?Edgar
Hi @Nikhi Agrawal were you able to find a solution in terms of contentent observer. As File Observer even made recursive is not working on latest devices.Part
A
10

Let me try to unwind

ContentObserver

It doesn't give you information on what has changed

It's per design. Nothing in documentation says that it will give you this info.

FileObserver

It isn't recursive

Yes. It's know issue. What is the problem with iterating through all directories and setting observers? Per my understand by default there shouldn't be many (let say a dozen or so).

Android: How to detect a change in MediaStore when connected over MTP

The code which you found is just ContentObserver wrapped in UriObserver.

It does several things

  • He gets a cursor for one of content provides (in his case I believe it's images from MediaStore)

  • He registers an observer for this

  • As soon as some changes happens it forward this changes to external listener

However, this solution has two limitation:

  • It has inherit problem of ContentObserver that it doesn't report what happened to the data.

  • I believe it will report only changes to files which are registered in this MediaStore content provider. I believe system scans only special directories on SD card to check for images and so on. So, if a file will be places in some another directory, this solution won't see it.

So, What was your question about his code?

Summary

In the case, if you want to know exact type of changes for ALL files on scdard, I don't think that you can find anything better than FileObserver

Update 1

Couple more ideas, which may be not suitable for you. If you can root a device then you have the option to write filter driver for a filesystem, so your driver will be called each time when something has changed.

You can take a look at this link: http://www.gossamer-threads.com/lists/linux/kernel/355190

Or you can reuse some existing linux changes notifications systems. As example, look at this: http://stefan.buettcher.org/cs/fschange/. However, it could be that FileObserver is based exactly on it.

Anyway, both these approaches are low level and will require more time to figure out.

Amathist answered 12/4, 2013 at 16:48 Comment(4)
But I have to implement File Observers on all the directories. It will to be to long process.Address
@Nikhil: It depends on number of directories. If there were hundreds of them then it make take long. However, for Android Sd card, usually there are not that many folders. BTW. Did you try to do this? Does it make device slow?Amathist
Ya that is what I have more than 1500 folders in my 16 gb sd card. And it is consuming more resources and making my device slow. That is why I am try this optionAddress
I am awarding you this +50 reputation because after posting at so many developers portal you only have guided me to the next level for my question But it is yet not completed. So If you come across any other info related to this question please update your answer. Others who found this post helpful for them if you people come across any other info related to this question please post your answers in this post. Thank you Victor Ronin be in touch always. Thanks to stackoverflow, Our kind and genius moderators and all the great intelligent and maven members of this community.Address
H
1

You can get the latest additions/modifications by querying on the DATE_ADDED and DATE_MODIFIED columns, but you will NOT get DELETIONS.

Here is how I do it:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
long lastDatabaseUpdateTime = preferences.getLong("lastDatabaseUpdateTime", 0);
long newDatabaseUpdateTime = (new Date()).getTime();

String[] cols = new String[] {MediaStore.Audio.Media._ID /* and other columns */};

String where = "("+MediaStore.MediaColumns.DATE_ADDED + ">" + (lastDatabaseUpdateTime/1000);
where += " or " + MediaStore.MediaColumns.DATE_MODIFIED + ">" + (lastDatabaseUpdateTime/1000);
where += ") and "+MediaStore.Audio.AudioColumns.IS_MUSIC+"==1 ";

Cursor cursor = MusicUtils.query(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, cols, where, null, null);

/* Do my work on the cursor and close the cursor */

//If no exceptions, then save the new timestamp
SharedPreferences.Editor editor = preferences.edit();
editor.putLong("lastDatabaseUpdateTime", newDatabaseUpdateTime);
editor.commit();
Hyades answered 13/10, 2015 at 20:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.