问题
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