Hi did a sample of JobScheduler in my app.
This is how I initiate it
jobScheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
ComponentName jobService = new ComponentName(getPackageName(),
MyJobService.class.getName());
JobInfo jobInfo = new JobInfo.Builder(MYJOBID, jobService)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setExtras(bundle).build();
jobScheduler.schedule(jobInfo);
And I showed a toast in the JobService:
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class MyJobService extends JobService {
public MyJobService() {
}
#Override
public boolean onStartJob(JobParameters params) {
// UtilityMethods.showToast(this,params.getExtras().getString("json"));
Toast.makeText(this,"test",Toast.LENGTH_SHORT).show();
return false;
}
#Override
public boolean onStopJob(JobParameters params) {
UtilityMethods.showToast(this,"onStop()");
return false;
}
}
And this was working perfectly fine even I tried turning off the internet and killing app from background.
I then tried building a similar thing in one of my libraries. I wrote the same code in the library and I am calling it from my app's MainActivity. But this time, When I kill app from background, it stops working. Can anyone tell me why?
My MainActivity where I initialize it
JobScheduler jobScheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
ComponentName jobService = new ComponentName(getPackageName(),
MyJobService.class.getName());
JobInfo jobInfo = new JobInfo.Builder(MYJOBID, jobService)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY).build();
jobScheduler.schedule(jobInfo);
It is working when I start it from onCreate and not working if I start it from a callback funtion().
Any help is really appreciated.
Android> 7 automatically saves battery power. You must enable the app's battery saver stop
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent intent = new Intent();
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
}
}
add this to AndroidManifest.xml
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
Make this return true
#Override
public boolean onStartJob(JobParameters params) {
// UtilityMethods.showToast(this,params.getExtras().getString("json"));
Toast.makeText(this,"test",Toast.LENGTH_SHORT).show();
return true;
}
and start a new thread from here(as this is executed on mainthread only).
onStartJob
added in API level 21
boolean onStartJob (JobParameters params)
Override this method with the callback logic for your job. Any such logic needs to be performed on a separate thread, as this function is executed on your application's main thread.
Parameters
params JobParameters: Parameters specifying info about this job, including the extras bundle you optionally provided at job-creation time.
Returns
boolean True if your service needs to process the work (on a separate thread). False if there's no more work to be done for this job.
Related
I'm having a problem to create a Background Service to loop a http request, and push notification if data is changed.
In android:
First time, i try to use Service, it's run very nice but it don't run when i close the app.
Second time, i try to use JobService, but it's do nothing. When debug, i see i maybe i can't reach to the JobService.
Code of Job Service:
public override bool OnStartJob(JobParameters #params)
{
Task.Run(() =>
{
CheckData();// my code here
}
);
return true;
}
public override bool OnStopJob(JobParameters #params)
{
return false;
}
In Main Activity:
Java.Lang.Class javaClass = Java.Lang.Class.FromType(typeof(NotificationJobService));
ComponentName component = new ComponentName(ApplicationContext, javaClass);
JobInfo.Builder builder = new JobInfo.Builder(1, component)
.SetRequiresCharging(true)
.SetRequiredNetworkType(NetworkType.Unmetered)
.SetPersisted(true)
.SetPeriodic(3000);
JobInfo jobInfo = builder.Build();
JobScheduler jobScheduler = (JobScheduler)GetSystemService(JobSchedulerService);
int res = jobScheduler.Schedule(jobInfo);
I'm working on an android app which requires a background task to be performed every hour(Job Scheduler or Service). Task gets executed when the app is running but as soon as I kill the app from foreground, service not work. Is there another way to achieve this?
1. Service
public class NotificationService extends JobService {
private void PrintLog()
{
Log.d("DGVCL", "PrintLog()");
}
#Override
public boolean onStartJob(JobParameters jobParameters) {
Log.d("DGVCL", "onStartJob()");
PrintLog();
jobFinished(jobParameters, false);
return true;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
Log.d("DGVCL", "onStopJob()");
return true;
}
}
2. Main Activity
JobScheduler jobScheduler = (JobScheduler)getApplicationContext().getSystemService(JOB_SCHEDULER_SERVICE);
ComponentName componentName = new ComponentName(this, NotificationService.class);
JobInfo jobInfo = new JobInfo.Builder(1, componentName)
.setPeriodic(Global.NOTIFICATION_TIME_PERIOD)
.setBackoffCriteria(Global.NOTIFICATION_TIME_PERIOD, JobInfo.BACKOFF_POLICY_LINEAR)
.setPersisted(true).build();
jobScheduler.schedule(jobInfo);
3. manifest
<service android:name="com.hopesndreams.hiren.hd.service.NotificationService" android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
Use WorkManager it is build on top of JobScheduler and it is specifically build to take on all background services both foreground and background functionalities. https://developer.android.com/topic/libraries/architecture/workmanager
* Using AlarmManager*
Step 1:Create a Service
Do your Logic here in the service
public class AService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//do something
}
#Override
public void onCreate() {
//do somrthing
}
}
Step 2: Create a BroadCast receiver
Start your service with this.
public class AReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
Intent intent = new Intent(context, AService.class);
context.startService(intent);
} catch (Exception e) {
}
}
}
in MainActivity
Intent liveIntent = new Intent(getApplicationContext(), AReceiver.class);
PendingIntent recurring = PendingIntent.getBroadcast(getApplicationContext(), 0, liveIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), 16 * 60 * 1000, recurring);
//wakeup and starts service in every 16 minutes.
This is the method working for me. Works fine even if you close the app. Works in Xiaomi devices.
Don't forget to add the service inside the manifest
Indeed, WorkManager is the way to go.
You can read up more on other work primitives to suit your task here, but the below implementation uses Worker for threading in WorkManager, which performs work synchronously on a background thread.
public class BackgroundWorker extends Worker {
public BackgroundWorker
(#NonNull Context context,
#NonNull WorkerParameters params) {
super(context, params);
}
#NonNull
#Override
public Worker.Result doWork() {
yourBackgroundTask(); // yourBackgroundTask() implementation
return Result.success();
}
public static void schedulePeriodicWork(Data data) {
// When multiple constraints are specified like below,
// your task will run only when all the constraints are met.
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(true)
.build();
PeriodicWorkRequest taskWork = new PeriodicWorkRequest.Builder(BackgroundWorker.class, 60,
TimeUnit.MINUTES)
.setConstraints(constraints)
.setInputData(data)
.build();
WorkManager.getInstance().enqueue(taskWork);
}
}
Later in your MainActivity file, inside onCreate():
Data data = workData();
BackgroundWorker.schedulePeriodicWork(data);
Then outside the onCreate() method,
private Data workData() {
return new Data.Builder() // to build Data objects
.build();
}
One small thing to note, is that though we set the above task to execute every 60 minutes, each iteration may not be executed at the same time interval.
According to Android documentation, WorkManager is meant for deferrable work, and some drift must be tolerated. However, you can check your log console for the update, "WM-WorkerWrapper: Worker result SUCCESS for Work".
Hope this is helpful.
i came to know that background services are not a way around in order to perform background task instead Job Scheduler was focused more as an alternative
i was applying the job scheduler functionality in my app and i was so confused that why my job is not running as expected whereas in android emulator it is running smoothly
below is my code which i have applied so far
Java.Lang.Class javaClass = Java.Lang.Class.FromType(typeof(jobsched));
ComponentName component = new ComponentName(this, javaClass)
JobInfo.Builder builder = new JobInfo.Builder(999, component)
.SetMinimumLatency(1000) // Wait at least 1 second
.SetOverrideDeadline(5000) // But no longer than 5 seconds
.SetPersisted(true)
.SetRequiredNetworkType(NetworkType.Any);
JobInfo jobInfo = builder.Build();
JobScheduler jobScheduler = (JobScheduler)GetSystemService(JobSchedulerService);
int result = jobScheduler.Schedule(jobInfo);
if (result == JobScheduler.ResultSuccess)
{
// The job was scheduled.
}
else
{
// Couldn't schedule the job.
}
And Scheduler service
public override bool OnStartJob(JobParameters #params)
{
Task.Run(() =>
{ });
JobFinished(#params, true);
return true;
}
public override bool OnStopJob(JobParameters #params) {
return true;
}
above scheduler seems to work fine when the app is open but when the app is closed by swiping away from recent task it doesn't notify me any more
i am missing something, please help me with this
I want to call a method once every day to spawn the zombies in my app.
The following method should create a JobScheduler that does this.
My question is: Do I call this method once or can I call it everytime at the startup of the app?
public static void startZombieSpawnService(Context context) {
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(context.JOB_SCHEDULER_SERVICE);
long intervaloDeRepeticao = TimeUnit.DAYS.toMillis(1);
jobScheduler.schedule(new JobInfo.Builder(1, new ComponentName(context, ZombieSpawnService.class)).setPeriodic(intervaloDeRepeticao).setp.build());
}
If you hold the RECEIVE_BOOT_COMPLETED permission, then you can also use setPersisted(true) from JobInfo.Builder(). Then you only need to call it once and it will persist across reboots too.
Otherwise, when your app starts, you can check if your job is scheduled using this function:
public static boolean isJobScheduled(Context mContext, int jobID) {
JobScheduler mScheduler = (JobScheduler)
mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE);
for (JobInfo jobInfo : mScheduler.getAllPendingJobs()) {
if (jobID == jobInfo.getId()) {
return true;
}
}
return false;
}
If it is not scheduled, then schedule it.
I have looked at many other threads on this. However, none of this seems to help.
I need to set up job scheduler that runs everyday at 3PM.
Here is my service class:
public class AttendanceCheckScheduler extends JobService {
private AttendanceCheckTask mAttendanceCheckTask;
private static final String TAG = "AttendanceCheckScheduler";
#Override
public boolean onStartJob(JobParameters params) {
mAttendanceCheckTask = new AttendanceCheckTask();
mAttendanceCheckTask.execute();
jobFinished(params, false);
return true;
}
#Override
public boolean onStopJob(JobParameters params) {
mAttendanceCheckTask.cancel(true);
return false;
}
private class AttendanceCheckTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
// some long running task...
Toast.makeText(getApplicationContext(), "Task run", Toast.LENGTH_SHORT).show();
return null;
}
#Override
protected void onPostExecute(Void s) {
super.onPostExecute(s);
}
}
}
And this is how I am scheduling the job in ActivityHome.
public class ActivityHome extends AppCompatActivity {
private static final int JOB_ID = 100;
private JobScheduler jobScheduler;
protected JobInfo jobInfo;
private static final String TAG = "ActivityHome";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// other irrelevant codes here...
ComponentName componentName = new ComponentName(this, AttendanceCheckScheduler.class);
JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, componentName);
builder.setPeriodic(5000); // every 5 seconds for testing purpose...
builder.setPersisted(true);
jobInfo = builder.build();
jobScheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(jobInfo);
Toast.makeText(this, "job scheduled", Toast.LENGTH_LONG).show();
}
}
Everythings seems to work fine and I am receiving the toast message Task run every 5 seconds as set above.
But when the app is killed (by clearing all task in multitask window), I stop receiving the toast messages.
How do I keep it running even if the app is killed ?
P.S: I want some task to perform once everyday at 3PM.
For background task for long time when your app is killed, you need to implement AlarmManager or WorkManager. WorkManager was in beta but now its ready only for Android X, just implement the dependency and copy paste WorkManager class code from google and put your task.
WorkManager latest dependency:
implementation "androidx.work:work-runtime:2.2.0"
I found this article. Here it says you have to call jobFinished() in your onPostExecute method of the asyncTask to let the system know the job is done.
jobFinished() requires two parameters: the current job, so that it
knows which wakelock can be released, and a boolean indicating whether
you’d like to reschedule the job. If you pass in true, this will kick
off the JobScheduler’s exponential backoff logic for you
I hope it helps.
Scheduling jobs like a pro with JobScheduler
There is an option not to kill the application, but it is very rude and it's the hack:
In your Manifest -> inside activity tag -> Add following line
android:excludeFromRecents="true"
Your app not show in recent apps history. So user can't kill the app.
Information is obtained by reference: https://code-examples.net/en/q/26c6cf8