Android 7 JobScheduler get event when new picture is taken by the camera

有些话、适合烂在心里 提交于 2019-12-04 11:45:18

问题


I have a problem on Android 7 that not support the broadcast event "android.hardware.action.NEW_PICTURE" longer. I write now for Android 7 a JobService but it will not fire when a Picture is shot by the internal camera. I don't know what is the problem, can everybody help me.

If any example source in the www that's for Android 7 and JobService for the replacement the broadcast "android.hardware.action.NEW_PICTURE" .

Thanks for help !

Here is my example Code:

  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class ZNJobService extends JobService {
   private static Zlog log = new Zlog(ZNJobService.class.getName());

    static final Uri MEDIA_URI = Uri.parse("content://" + MediaStore.AUTHORITY + "/");
    static final int ZNJOBSERVICE_JOB_ID = 777;
    static  JobInfo JOB_INFO;


    @RequiresApi(api = Build.VERSION_CODES.N)
    public static boolean isRegistered(Context pContext){

            JobScheduler js = pContext.getSystemService(JobScheduler.class);
            List<JobInfo> jobs = js.getAllPendingJobs();
            if (jobs == null) {
                log.INFO("ZNJobService not registered ");
                return false;
            }
            for (int i = 0; i < jobs.size(); i++) {
                if (jobs.get(i).getId() == ZNJOBSERVICE_JOB_ID) {
                    log.INFO("ZNJobService is registered :-)");
                    return true;
                }
            }
            log.INFO("ZNJobService is not registered");
            return false;

    }


    public static void registerJob(Context pContext){

        Log.i("ZNJobService","ZNJobService init");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ) {

            if (! isRegistered(pContext)) {
                Log.i("ZNJobService", "JobBuilder executes");
                log.INFO("JobBuilder executes");
                JobInfo.Builder builder = new JobInfo.Builder(ZNJOBSERVICE_JOB_ID, new ComponentName(pContext, ZNJobService.class.getName()));
                // Look for specific changes to images in the provider.
                builder.addTriggerContentUri(new JobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                                                                           JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
                // Also look for general reports of changes in the overall provider.
                //builder.addTriggerContentUri(new JobInfo.TriggerContentUri(MEDIA_URI, 0));
                JOB_INFO = builder.build();
                log.INFO("JOB_INFO created");

                JobScheduler scheduler = (JobScheduler) pContext.getSystemService(Context.JOB_SCHEDULER_SERVICE);
                int result = scheduler.schedule(JOB_INFO);
                if (result == JobScheduler.RESULT_SUCCESS) {
                    log.INFO(" JobScheduler OK");
                } else {
                    log.ERROR(" JobScheduler fails");
                }
            }

        } else {
            JOB_INFO = null;
        }
    }


    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    public boolean onStartJob(JobParameters params) {
        log.INFO("onStartJob");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            if (params.getJobId() == ZNJOBSERVICE_JOB_ID) {
                if (params.getTriggeredContentAuthorities() != null) {

                    for (Uri uri : params.getTriggeredContentUris()) {
                        log.INFO("JobService Uri=%s",uri.toString());
                    }

                }
            }
        }
        this.jobFinished(params,false);
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            log.INFO("onStopJob");
        }
        return true;

    }
}

回答1:


In the below code you can pass the flag immediate as false for normal operation (i.e. schedule within system guidelines for an app's good behaviour). When your app's main activity starts you can pass immediate as true to force a quick retrieval of media content changes.

You should run code in the onStartJob() method in a background job. (As shown below.)

If you only want to receive media from the camera and not other sources you should just filter out URI's based on their path. So only include "*/DCIM/*". (I haven't put this in the below code though.)

Also the Android job scheduler has a policy where it denies your service if it detects over abuse. Maybe your tests have caused this in your app, so just uninstall and reinstall to reset it.

public class ZNJobService extends JobService {

    //...

    final Handler workHandler = new Handler();
    Runnable workRunnable;

    //...

    public static void registerJob(Context context, boolean immediate) {
        final JobInfo jobInfo = createJobInfo(context, immediate);
        final JobScheduler js = context.getSystemService(JobScheduler.class);
        final int result = js.schedule(jobInfo);
        if (result == JobScheduler.RESULT_SUCCESS) {
            log.INFO(" JobScheduler OK");
        } else {
            log.ERROR(" JobScheduler fails");
        }
    }

    private static JobInfo createJobInfo(Context context, boolean immediate) {
        final JobInfo.Builder b =
            new JobInfo.Builder(
            ZNJOBSERVICE_JOB_ID, new ComponentName(context, ZNJobService.class));

        // Look for specific changes to images in the provider.
        b.addTriggerContentUri(
            new JobInfo.TriggerContentUri(
                MediaStore.Images.Media.INTERNAL_CONTENT_URI,
                JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
        b.addTriggerContentUri(
            new JobInfo.TriggerContentUri(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));

        if (immediate) {
            // Get all media changes within a tenth of a second.
            b.setTriggerContentUpdateDelay(1);
            b.setTriggerContentMaxDelay(100);
        } else {
            // Wait at least 15 minutes before checking content changes.
            // (Change this as necessary.)
            b.setTriggerContentUpdateDelay(15 * 60 * 1000);

            // No longer than 2 hours for content changes.
            // (Change this as necessary.)
            b.setTriggerContentMaxDelay(2 * 60 * 60 * 1000);
        }

        return b.build();
    }

    @Override
    public boolean onStartJob(final JobParameters params) {
        log.INFO("onStartJob");

        if (params.getTriggeredContentAuthorities() != null && params.getTriggeredContentUris() != null) {
            // Process changes to media content in a background thread.
            workRunnable = new Runnable() {
                @Override
                public void run() {
                    yourMethod(params.getTriggeredContentUris());

                    // Reschedule manually. (The 'immediate' flag might have changed.)
                    jobFinished(params, /*reschedule*/false);
                    scheduleJob(ZNJobService.this, /*immediate*/false);
                }};
            Postal.ensurePost(workHandler, workRunnable);

            return true;
        }

        // Only reschedule the job.
        scheduleJob(this, /*immediate*/false);
        return false;
    }

    @Override
    public boolean onStopJob(final JobParameters params) {
        if (workRunnable != null) {
            workHandler.removeCallbacks(workRunnable);
            workRunnable = null;
        }
        return false;
    }

    private static void yourMethod(Uri[] uris) {
        for (Uri uri : uris) {
            log.INFO("JobService Uri=%s", uri.toString());
        }
    }
}


来源:https://stackoverflow.com/questions/43665390/android-7-jobscheduler-get-event-when-new-picture-is-taken-by-the-camera

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!