Networking with Jobscheduler - android

Is networking using HttpUrlConnection etc (for uploading data to server) possible with JobScheduler? Or I've to go with GCMNetworkManager? How can I perform network operation scheduling?
MainActivity.class
jobScheduler = (JobScheduler)getSystemService(JOB_SCHEDULER_SERVICE);
btnStartJob.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
ComponentName jobService =
new ComponentName(getPackageName(), MyJobService.class.getName());
JobInfo jobInfo =
new JobInfo.Builder(MYJOBID, jobService).setPeriodic(10000).build();
int jobId = jobScheduler.schedule(jobInfo);
if(jobScheduler.schedule(jobInfo)>0){
Toast.makeText(MainActivity.this,
"Successfully scheduled job: " + jobId,
Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this,
"RESULT_FAILURE: " + jobId,
Toast.LENGTH_SHORT).show();
}
}});
MyJobService.class
public class MyJobService extends JobService {
public MyJobService() {
}
#Override
public boolean onStartJob(JobParameters jobParameters) {
Toast.makeText(this,"MyJobService.onStartJob()",Toast.LENGTH_SHORT).show();
//networking is not working here
return false;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
Toast.makeText(this,
"MyJobService.onStopJob()",
Toast.LENGTH_SHORT).show();
return false;
}
}

Is networking using HttpUrlConnection etc (for uploading data to server) possible with JobScheduler?
Of course. You should use the .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) on the JobInfo builder though, to ensure your job does not run if there is no network available.
You have to do your network operation in JobService on a separate thread though, because the onStartJob is executed on the main thread.

Related

Job scheduler not working in background when app is killed in android version 7,8,9,10?

I have used a timer to call a method at 15 minutes interval inside a job scheduler. But the job scheduler only running on the app running stage, if I kill the app the job scheduler was not worked. How to run the job scheduler to work after I killing my app?
here my code snippet
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startJob();
}
private void startJob(){
JobScheduler jobScheduler = (JobScheduler)getApplicationContext()
.getSystemService(JOB_SCHEDULER_SERVICE);
ComponentName componentName = new ComponentName(this,
RecallMyServicesis.class);
JobInfo jobInfo = new JobInfo.Builder(1, componentName)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setRequiresCharging(true)
.setOverrideDeadline(15*60*1000)
.setPersisted(true)
.build();
int result = jobScheduler.schedule(jobInfo);
if(result == JobScheduler.RESULT_SUCCESS)
{
Log.d("MainActivity","Success");
}else
{
Log.d("MainActivity","Failed");
}
}
}
RecallMyServicesis.java
public class RecallMyServicesis extends JobService {
private static final String TAG = "RecallMyServicesis";
#Override
public boolean onStartJob(JobParameters jobParameters) {
System.out.println("Job Fired");
for(int i = 0; i < 10; i++){
System.out.println("Job Fired i : "+i);
Toast.makeText(this, "Job Fired i : "+i, Toast.LENGTH_SHORT).show();
SystemClock.sleep(1000);
}
jobFinished(jobParameters, false );
return true;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
return false;
}
}
AndroidManifest.xml
​<service android:name=".RecallMyServicesis"
android:permission="android.permission.BIND_JOB_SERVICE" />
I am trying to work on JobScheduler and eventually, It is not working on Android 7.0. I have Samsung s7 device. But when I am deploying apk in Moto e4 which have android 7.1 version, the jobscheduler is working fine on background and app as well, even I kill the app, it is running.

Jobscheduler using JobService stops working after a couple of hours

I am trying to test the reliability of using JobScheduler to schedule background tasks on Android API 23, because I noticed that sometimes it misbehaves and stops working.
This is how I schedule a job in SystemManager.java class:
public static void scheduleUploadJob(Context context) {
ComponentName componentName = new ComponentName(context, BackgroundUploadJobScheduler.class);
JobInfo info = new JobInfo.Builder(123, componentName)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.setPeriodic(120*60*1000)
.build();
JobScheduler scheduler = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE);
int resultCode = scheduler.schedule(info);
if (resultCode == JobScheduler.RESULT_SUCCESS) {
Log.d("ScheduleJob()", "Job scheduled successfully!");
} else {
Log.d("ScheduleJob()", "Job scheduled Failed!");
}
}
public class BackgroundUploadJobScheduler extends JobService {
private static final String TAG = "JobSevice";
public static boolean jobCancelled = false;
#Override
public boolean onStartJob(JobParameters params) {
Log.d(TAG, "Events upload Job started");
doBackgroundUploading(params, this);
return true;
}
#Override
public boolean onStopJob(JobParameters params) {
Log.d(TAG, "upload Job cancelled before completion");
jobCancelled = true;
return true;
}
public synchronized void doBackgroundUploading(final JobParameters params, final Context context) {
new Thread(new Runnable() {
#Override
public void run() {
if (jobCancelled) {
return;
}
UploadObject uploadObject= //get it from RoomDB
NetworkManager.upload(context,uploadObject);
}
jobFinished(params, false);
}
}).start();
}
I do the network call in the NetworkManager.java class using Retrofit:
call.enqueue(new Callback() {
#Override
public void onResponse(Call call, Response response) {
if (response.isSuccessful()) {
SystemManager.scheduleEventRecordUploadJob(context);
}else{
SystemManager.scheduleEventRecordUploadJob(context);
}
}
#Override
public void onFailure(Call call, Throwable t) {
SystemManager.scheduleEventRecordUploadJob(context);
}
});
The problem
After I initialized the app and made the first Network call, I exited the app, disconnected the USB connection and turned off the screen. I left it overnight and came to check the records on my server DB for results.
The device kept sending the server network data with almost the same rate at least twice per minute for a continuous 10 hours! (This wasn't expected, cus the device should enter doze right?)
After that there was no more requests sent! From 3 AM till 9:30 AM I got nothing sent to the server. I turned on my device screen, connected it to power, opened the app... waited for an hour, still nothing more is being sent. Why? Did the service just get killed? How can I solve such an issue?
N.B
Of course, I do not intend to do such heavy repeating work like this on a real application. But, I am just doing a test app to understand the behavior of JobScheduler and JobService. And why does it just die out of nothing all of a sudden and doesn't start again?!

Handle consecutive events with job scheduler

My App must be aware of taking picture by any camera apps on user device and do some progress on that picture.
On API < 24 i used a broadcast receiver which catches com.android.camera.NEW_PICTURE events and it works fine.
But according to this document to achieve that goal in API >= 24 we must use Job-Scheduler instead.
I used this code and it works fine for one picture in one job execution time. but when i take consecutive pictures job scheduler only handles first one.
#TargetApi(Build.VERSION_CODES.N)
public class CameraJobService extends JobService
{
private static final String TAG = "CameraJobService";
#Override
public boolean onStartJob(final JobParameters params)
{
Log.i(TAG, "onStartJob: " + this);
// do in background thread
new Thread(() -> {
doJob(params);
// mark the job as 'finished'
jobFinished(params, false);
// create a new job
prepareJob(getApplicationContext());
}).start();
// mark the job as 'on processing'
return true;
}
#Override
public boolean onStopJob(JobParameters params)
{
Log.i(TAG, "onStopJob: " + this);
// reschedule job if it was terminated by os
return true;
}
private void doJob(JobParameters params)
{
if (params.getTriggeredContentAuthorities() != null && params.getTriggeredContentUris() != null)
{
//some job here
Log.d(TAG, "doJob: ");
}
}
#TargetApi(Build.VERSION_CODES.N)
public static void prepareJob(Context context)
{
Log.i(TAG, "prepareJob");
JobScheduler scheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = new JobInfo.Builder(1001,
new ComponentName(context, CameraJobService.class));
builder.addTriggerContentUri(
new JobInfo.TriggerContentUri(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
if (scheduler != null)
{
scheduler.schedule(builder.build());
}
}
}
I initialized my JobService and BroadcastReceiver Here in MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// use job scheduler
CameraJobService.prepareJob(this);
} else {
// use broadcast receiver
CameraBroadcastReceiver.register(this);
}
}
I think this problem happens because one job is in progress now and we can't start new one before current job be complete. but is there any way to handle this problem?

How Call the getDataFromApi() function using Thread

I'm taking the google calendar API data for my mobile application. i want to check the time to time the changes of the calendar. For that i know, i have to used a thread.
if (isChecked) {
Runnable runnable = new Runnable() {
public void run() {
long endTime = System.currentTimeMillis() + 1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
getResultsFromApi();
} catch (Exception e) {}
}
}
}
};
Thread mythread = new Thread(runnable);
mythread.start();
Toast.makeText(AlertActivity.this, "Calendar Settings Enabled",
Toast.LENGTH_SHORT).show();
} else {
// The toggle is disabled
for(int i=0;i<=broadcastCodeCal;i++)
cancel_Alarm(i);
Toast.makeText(AlertActivity.this, "Calendar Settings Disabled",
Toast.LENGTH_SHORT).show();
}
I want to know how to check the calendar details changes time time to through the mobile application... please guide me...
Create a JobScheduler as below
public static void scheduleJob(Context context) {
ComponentName serviceComponent = new ComponentName(context, TestJobService.class);
JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent);
builder.setMinimumLatency(1 * 1000); // wait at least
builder.setOverrideDeadline(3 * 1000); // maximum delay
JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
jobScheduler.schedule(builder.build());
}
Create the following receiver
public class MyStartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Util.scheduleJob(context);
}
}
Register the receiver in the Android manifest for the BOOT_COMPLETED event.
<receiver android:name="MyStartServiceReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Create a JobService and add your existing code in to onStartJob
public class TestJobService extends JobService {
private static final String TAG = "SyncService";
#Override
public boolean onStartJob(JobParameters params) {
Intent service = new Intent(getApplicationContext(), LocalWordService.class);
getApplicationContext().startService(service);
Util.scheduleJob(getApplicationContext()); // reschedule the job
return true;
}
#Override
public boolean onStopJob(JobParameters params) {
return true;
}
}
For more details refer : linkhere

why does the job run even if the available network condition isn't verified?

I'm using jobscheduler since it's no longer possible to declare a network connectivity intent in manifest. I've tried using .setPeriodic(10 * 1000) to make the job periodic but in doing so, the job runs after 10 seconds even if there is no available network as if it is ignoring this line .setRequiredNetworkType(NETWORK_TYPE_ANY)
And if I remove .setPeriodic(10 * 1000) then the job runs only once. What I want to achieve is the same that was possible before the background optimisation and disabling apps from waking based on a connectivity change: If there is an available network then run the jobservice, if there is none do nothing.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main5);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
JobScheduler mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = null;
builder = new JobInfo.Builder(1, new ComponentName(getPackageName(),
MyJobService.class.getName()))
.setRequiredNetworkType(NETWORK_TYPE_ANY)
.setPeriodic(10 * 1000);
if (mJobScheduler.schedule(builder.build()) <= 0) {
Log.e("gch", "can't Schedule job for MyJobService");
} else {
Log.d("gch", "Schedule job for MyJobService");
}
}
}
and this is the jobService
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class MyJobService extends android.app.job.JobService {
public MyJobService() {
}
#Override
public boolean onStartJob(JobParameters jobParameters) {
Log.e("gch", "onStartJob");
Toast.makeText(this, "onStartJob", Toast.LENGTH_SHORT).show();
Intent inent = new Intent(this, AnotherActivity.class);
inent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(inent);
return false;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
Log.e("gch", "onStartonStopJob");
Toast.makeText(this, "onStartonStopJob", Toast.LENGTH_SHORT).show();
return true;
}
}
I've added this to the manifest
<service
android:name=".MyJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />

Categories

Resources