问题
I've wrote an app for creating and reminding task which uses local SqliteDatabase. I wrote a jobScheduler service to check the device time and date with tasks on the database and if matches shows a push notification. What I want also is service to run in background and check the data every 5 seconds . but when I write
builder.setPeriodic(5000); builder.setPersisted(true);
the service stops checking data.
Here's my code
MainActivity
public class MainActivity extends AppCompatActivity {
ImageButton plusImageBtn;
DatabaseHelper databaseHelper;
BottomNavigationView navigation;
Toolbar toolbar;
private ComponentName mServiceComponent;
private int jobId=0;
private static final String TAG = MainActivity.class.getSimpleName();
public static final String WORK_DURATION_KEY =
BuildConfig.APPLICATION_ID + ".WORK_DURATION_KEY";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
navigation = (BottomNavigationView) findViewById(R.id.navigation);
plusImageBtn = (ImageButton) findViewById(R.id.plusImagBtn);
toolbar= (Toolbar) findViewById(R.id.toolbar_main);
setSupportActionBar(toolbar);
mServiceComponent = new ComponentName(this, JobSchedulerService.class);
databaseHelper= new DatabaseHelper(this);
navigation.setOnNavigationItemSelectedListener
(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.navigation_calendar:
selectedFragment = new CalendarFragment();
break;
case R.id.navigation_home:
selectedFragment = new ViewListContents();
break;
}
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, selectedFragment);
transaction.commit();
return true;
}
});
FragmentTransaction transaction =
getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout,new ViewListContents());
transaction.commit();
scheduleJob();
}
@Override
protected void onStart() {
super.onStart();
// Start service and provide it a way to communicate with this class.
Intent startServiceIntent = new Intent(this, JobSchedulerService.class);
startService(startServiceIntent);
}
@Override
protected void onStop() {
stopService(new Intent(this,JobSchedulerService.class));
super.onStop();
}
public void scheduleJob() {
JobInfo.Builder builder = new JobInfo.Builder(jobId++, mServiceComponent);
// builder.setPeriodic(5000);
// builder.setPersisted(true);
builder.setMinimumLatency(1000);
builder.setOverrideDeadline(1000);
// Extras, work duration.
PersistableBundle extras = new PersistableBundle();
extras.putLong("",5000);
builder.setExtras(extras);
// Schedule job
Log.d(TAG, "Scheduling job");
JobScheduler tm = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
tm.schedule(builder.build());
Toast.makeText(this, "Scheduling job ", Toast.LENGTH_SHORT).show();
}}
JobSchedulerService
public class JobSchedulerService extends JobService {
int id;
String stringId;
String date;
String taskDate,taskTitle,taskTime,sepYear,sepMonth,
sepDay,convert,DeviceDate;
Cursor taskDateCursor;
DatabaseHelper databaseHelper;
Roozh roozh;
String[] seperatedString;
int iYear,iMonth, iDay;
SimpleDateFormat dateFormat, timeFormat;
private static final String TAG = JobSchedulerService.class.getSimpleName();
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Service created");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "Service destroyed"); }
@Override
public boolean onStartJob(final JobParameters params) {
stringId = String.valueOf(params.getJobId());
id = params.getJobId();
final long duration = params.getExtras().getLong(WORK_DURATION_KEY);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
databaseHelper= new DatabaseHelper(getApplicationContext());
taskDateCursor=databaseHelper.getDateForNotification();
if (taskDateCursor.moveToFirst()){
do {
taskTitle=taskDateCursor.getString(taskDateCursor.getColumnIndex(DatabaseHelper.COL2));
taskDate=taskDateCursor.getString(taskDateCursor.getColumnIndex(DatabaseHelper.COL3));
taskTime=taskDateCursor.getString(taskDateCursor.getColumnIndex(DatabaseHelper.COL4));
roozh= new Roozh();
seperatedString=taskDate.split("/");
sepYear= seperatedString[0];
sepMonth= seperatedString[1];
sepDay= seperatedString[2].trim();
iYear= Integer.parseInt(sepYear);
iMonth= Integer.parseInt(sepMonth);
iDay= Integer.parseInt(sepDay);
roozh.PersianToGregorian(iYear,iMonth,iDay);
convert= roozh.toString();
dateFormat= new SimpleDateFormat(
"yyyy-MM-dd", Locale.getDefault());
DeviceDate= dateFormat.format(new Date());
timeFormat=new SimpleDateFormat("HH:m",Locale.getDefault());
String deviceTime=timeFormat.format(new Date());
RemoteViews remoteViews= new RemoteViews(getPackageName(),R.layout.notification);
remoteViews.setImageViewResource(R.id.notif_image, R.mipmap.ic_launcher);
remoteViews.setTextViewText(R.id.title,taskTitle);
remoteViews.setTextViewText(R.id.text,taskTime);
if (DeviceDate.equals(convert) && deviceTime.equals(taskTime) ){
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext())
.setSmallIcon(R.drawable.drawable_circle)
.setContent(remoteViews)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setColor(ContextCompat.getColor(getApplication(), R.color.primaryDarkColor))
.setShowWhen(true)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getApplicationContext());
notificationManager.notify(0, mBuilder.build());
}
Log.i(TAG, "data " + DeviceDate+ "task" + convert+ " " + "dd" + " "+ taskTime + "dt" + "" + deviceTime);
}while (taskDateCursor.moveToNext());
} }
}, duration);
Log.i(TAG, "on start job: " + params.getJobId());
return true; }
@Override
public boolean onStopJob(JobParameters params) {
Log.i(TAG, "on stop job: " + params.getJobId());
return true; }
回答1:
I think your problem is the frequency you would like to execute your job. The minimum period for a job is 15 minutes in the standard AOSP. So it probably isn't the right API for you. Alarm Manager would probably be what you want, but setting an alarm for every 5 seconds is expensive. Google has also been restricting background services more and more with each release. Just something to keep in mind.
See: JobScheduler not repeating job
回答2:
setPeriodic(long intervalMillis) only works on devices lower than Nougat change it with this setPeriodic (long intervalMillis, long flexMillis) for devices having android version Nougat and above.
回答3:
ScheduledThreadPoolExecutor is a better option. Tasks can be scheduled by scheduleAtFixedRate or scheduleWithFixedDelay.
Reference: https://developer.android.com/reference/kotlin/java/util/concurrent/ScheduledThreadPoolExecutor#schedule
来源:https://stackoverflow.com/questions/49832467/android-setperiodic-for-jobscheduler-wont-work