简体   繁体   中英

Is there a way to get the uri of an image right after it is removed from external storage?

I'm coding a gallery app and for the first time when app is launched it scans the whole external storage to retrieve all image Uris and stores them in a database so for the later launches it can load them from its own db. Now my question is, when an image is removed, how can I get the deleted image Uri to notify the gallery and update the database.

I tried JobSchecular for the case when a new Image is added through the camera and it perfectly worked.

here is the code.

public class MediaJobSchedulerService extends JobService {

    private static final int ASJOBSERVICE_JOB_ID = 999;

    // A pre-built JobInfo we use for scheduling our job.
    private static JobInfo JOB_INFO = null;

    public static int a(Context context) {
        int schedule = (context.getSystemService(JobScheduler.class)).schedule(JOB_INFO);
        Log.i("PhotosContentJob", "JOB SCHEDULED!");
        return schedule;
    }

    // Schedule this job, replace any existing one.
    public static void scheduleJob(Context context) {
        if (JOB_INFO != null) {
            a(context);
        } else {
            JobScheduler js = context.getSystemService(JobScheduler.class);
            JobInfo.Builder builder = new JobInfo.Builder(ASJOBSERVICE_JOB_ID,
                new ComponentName(context, MediaJobSchedulerService.class));
            builder.addTriggerContentUri(new JobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
            builder.addTriggerContentUri(new JobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1));
            builder.setTriggerContentMaxDelay(500);
            JOB_INFO = builder.build();
            js.schedule(JOB_INFO);
        }
    }


    @Override
    public boolean onStartJob(final JobParameters params) {
        // Did we trigger due to a content change?
        final Context context = this;
        if (params.getTriggeredContentAuthorities() != null) {
            if (params.getTriggeredContentUris() != null) {
                // If we have details about which URIs changed, then iterate through them
                // and collect either the ids that were impacted or note that a generic
                // change has happened.
                final Repository repo = Repository.getInstance(this);
                ArrayList<String> ids = new ArrayList<>();
                for (final Uri uri : params.getTriggeredContentUris()) {
                    if (uri != null) {

                        Handler handler = new Handler();
                        handler.post(new Runnable() {
                            @Override
                            public void run() {

                                if (!uri.toString().equals("content://media/external")) {
                                    Log.i("NEW_MEDIA", getRealPathFromUri(context, uri));
                                    repo.addImage(getRealPathFromUri(context, uri));
                                }
                            }
                        });
                    }
                }
                jobFinished(params, true); // see this, we are saying we just finished the job
                // We will emulate taking some time to do this work, so we can see batching happen.
                scheduleJob(this);
            }
        }
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return false;
    }

    public static String getRealPathFromUri(Context context, Uri contentUri) {
        Cursor cursor = null;
        try {
            String[] proj = {MediaStore.Images.Media.DATA};
            cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }

}

but in case when the image is removed the Uri is missing.

My great appreciation towards your help.

Android doesn't have and event for this, but you can use and FileObserver . This will catch the deletion of a file. Example:

import android.os.FileObserver;
public class FileDeletedObserver extends FileObserver {
    public String absolutePath;
    public FileDeletedObserver(String path) {
        super(path, FileObserver.DELETE);
        absolutePath = path;
    }
    @Override
    public void onEvent(int event, String path) {
        if (path == null) {
            return;
        }

        if ((FileObserver.DELETE & event)!=0) {
            //handle deleted file
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM