gpt4 book ai didi

android - 当相机拍摄新照片时,Oreo JobScheduler 不工作

转载 作者:行者123 更新时间:2023-11-29 01:01:27 24 4
gpt4 key购买 nike

在 android 中,Oreo 广播接收器不适用于“android.hardware.action.NEW_PICTURE”,因此我必须将其替换为 JobScheduler。现在的问题是当我重新启动应用程序时,PhotoContentsJob 被调用并显示拍摄的新图像的 toast 但是一旦拍摄新照片它就不会在后台工作。请帮助我如何实现它。附上代码以供引用。

在MainActivity的onCreate方法中

 if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
scheduleCameraJob();
}

@RequiresApi(api = Build.VERSION_CODES.O)
private void scheduleCameraJob() {
final Uri MEDIA_URI = Uri.parse("content://" + MediaStore.AUTHORITY + "/");

JobInfo.Builder builder = new JobInfo.Builder(11,
new ComponentName(this, PhotosContentJob.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));
builder.setTriggerContentUpdateDelay(1);
builder.setTriggerContentMaxDelay(100);
JobInfo myCameraJob = builder.build();
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(myCameraJob);
}

PhotosContentJob 服务--工作代码

@RequiresApi(api = Build.VERSION_CODES.O)
public class PhotosContentJob extends JobService {

SpreadsheetImage spreadsheetImage;
DatabaseHandler databaseHandler;

// Path segments for image-specific URIs in the provider.
static final List<String> EXTERNAL_PATH_SEGMENTS
= MediaStore.Images.Media.EXTERNAL_CONTENT_URI.getPathSegments();
// The columns we want to retrieve about a particular image.
static final String[] PROJECTION = new String[] {
MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.DATA
};
static final int PROJECTION_ID = 0;
static final int PROJECTION_DATA = 1;
// This is the external storage directory where cameras place pictures.
static final String DCIM_DIR = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM).getPath();


JobParameters mRunningParams;

// Check whether this job is currently scheduled.
public static boolean isScheduled(Context context) {
JobScheduler js = context.getSystemService(JobScheduler.class);
List<JobInfo> jobs = js.getAllPendingJobs();
if (jobs == null) {
return false;
}
for (int i=0; i<jobs.size(); i++) {
if (jobs.get(i).getId() == 11) {
return true;
}
}
return false;
}

// Cancel this job, if currently scheduled.
public static void cancelJob(Context context) {
JobScheduler js = context.getSystemService(JobScheduler.class);
js.cancel(11);
}

@Override
public boolean onStartJob(JobParameters params) {
Log.e("PhotosContentJob", "JOB STARTED!");
mRunningParams = params;
// Instead of real work, we are going to build a string to show to the user.
Date addedDate=new Date();
databaseHandler=new DatabaseHandler(getApplicationContext());
spreadsheetImage=new SpreadsheetImage();

StringBuilder sb = new StringBuilder();
// Did we trigger due to a content change?
if (params.getTriggeredContentAuthorities() != null) {
boolean rescanNeeded = false;
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.
ArrayList<String> ids = new ArrayList<>();
for (Uri uri : params.getTriggeredContentUris()) {
List<String> path = uri.getPathSegments();
if (path != null && path.size() == EXTERNAL_PATH_SEGMENTS.size()+1) {
// This is a specific file.
ids.add(path.get(path.size()-1));
} else {
// Oops, there is some general change!
rescanNeeded = true;
}
}
if (ids.size() > 0) {
// If we found some ids that changed, we want to determine what they are.
// First, we do a query with content provider to ask about all of them.
StringBuilder selection = new StringBuilder();
for (int i=0; i<ids.size(); i++) {
if (selection.length() > 0) {
selection.append(" OR ");
}
selection.append(MediaStore.Images.ImageColumns._ID);
selection.append("='");
selection.append(ids.get(i));
selection.append("'");
}
// Now we iterate through the query, looking at the filenames of
// the items to determine if they are ones we are interested in.
Cursor cursor = null;
boolean haveFiles = false;
try {
cursor = getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
PROJECTION, selection.toString(), null, null);
while (cursor.moveToNext()) {
// We only care about files in the DCIM directory.
String dir = cursor.getString(PROJECTION_DATA);
if (dir.startsWith(DCIM_DIR)) {
if (!haveFiles) {
haveFiles = true;
sb.append("New photos:\n");
}
sb.append(cursor.getInt(PROJECTION_ID));
sb.append(": ");
sb.append(dir);
sb.append("\n");

spreadsheetImage.ImagePath=dir;
spreadsheetImage.AddedOn=addedDate;
databaseHandler.AddSpreadSheetImage(spreadsheetImage);
}
}
} catch (SecurityException e) {
sb.append("Error: no access to media!");
} finally {
if (cursor != null) {
cursor.close();
}
}
}
} else {
// We don't have any details about URIs (because too many changed at once),
// so just note that we need to do a full rescan.
rescanNeeded = true;
}
if (rescanNeeded) {
sb.append("Photos rescan needed!");
}
} else {
sb.append("(No photos content)");
}

Toast.makeText(this, sb.toString(), Toast.LENGTH_LONG).show();
jobFinished(params, /*reschedule*/false);
scheduleCameraJob( /*immediate*/false);
return true;
}
@Override
public boolean onStopJob(JobParameters params) {

return false;
}

@RequiresApi(api = Build.VERSION_CODES.O)
private void scheduleCameraJob(Boolean Immediate) {
final Uri MEDIA_URI = Uri.parse("content://" + MediaStore.AUTHORITY + "/");

JobInfo.Builder builder = new JobInfo.Builder(11,
new ComponentName(this, PhotosContentJob.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));

if (Immediate) {
// Get all media changes within a tenth of a second.
builder.setTriggerContentUpdateDelay(1);
builder.setTriggerContentMaxDelay(100);
} else {
builder.setTriggerContentUpdateDelay(1);
builder.setTriggerContentMaxDelay(100);
}

JobInfo myCameraJob = builder.build();
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
int result =jobScheduler.schedule(myCameraJob);
if (result == JobScheduler.RESULT_SUCCESS) {
Log.e("JobScheduler"," JobScheduler OK");
} else {
Log.e("JobScheduler"," JobScheduler fails");
}
}
}

最佳答案

根据内容观察器 URI 调度一个 JobScheduler 只是一个时间任务。当您收到对 PhotosContentJob 的更改时,您需要在 onStartJob(JobParameters params) 结束时再次重新安排作业以继续接收更新。

基于文档:

Note: TriggerContentUri() cannot be used in combination with setPeriodic() or setPersisted(). To continually monitor for content changes, schedule a new JobInfo before the app’s JobService finishes handling the most recent callback.

注意:

记得在设备重启时重新安排作业。由于计划的作业不会在重启后持续存在。

关于android - 当相机拍摄新照片时,Oreo JobScheduler 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50872557/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com