Feroz Siddiqui
Feroz Siddiqui

Reputation: 4106

Android Oreo - Job Intent Service is running on main Thread causing app to freeze for couple of seconds

I am trying to download some file in background. Earlier i was doing with intent service, and my app wont get freezed in using intent service. But as with oreo and above versions onward Intent service is getting destroyed as soon as app get closed from background. Same processing i did it in a Job service but it seem its running on main thread. What should i do for background processing that shouldn't be running on main thread ?

Below is code for JOB scheduling i did:

public class Util {

    // schedule the start of the service every 10 - 30 seconds
    @TargetApi(Build.VERSION_CODES.M)
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public static void scheduleJob(Context context) {
        ComponentName serviceComponent = new ComponentName(context, MyService.class);
        JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent);
        builder.setMinimumLatency(1 * 1000); // wait at least
        builder.setOverrideDeadline(3 * 1000); // maximum delay
        //builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); // require unmetered network
        //builder.setRequiresDeviceIdle(true); // device should be idle
        //builder.setRequiresCharging(false); // we don't care if the device is charging or not
        JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
        jobScheduler.schedule(builder.build());
    }

}



@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class MyService extends JobService {
    private static final String TAG = "SyncService";
    public Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
    public SharedPreferences sharedPreferences;
    public ComplexObject complexObject;
    private Context context;
    public static final String NOTIFICATION_CHANNEL_ID = "10001";
    @Override
    public boolean onStartJob(JobParameters params) {
        System.out.println("RUnning this Job.......");
        context = this;
        this.sharedPreferences = context.getSharedPreferences(context.getResources().getString(R.string.shared_preference_key), Context.MODE_PRIVATE);

        //30-40 HTTP call to process the data
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return true;
    }

Upvotes: 3

Views: 3367

Answers (3)

M Shafaei N
M Shafaei N

Reputation: 449

You can use JobIntentService as a solution to download/upload some file or even communicate with server. One another good even better approach is WorkManager. Note that IntentService runs on UI thread that is the onHandleIntent(Intent intent) runs on UI thread. So we should use a separate Thread or use of for example AsyncTask. But JobIntentService has the function onHandleWork(@NonNull Intent intent) which is run on a background thread and so we just do the work on it. In WorkManager approach, the work is done in doWork() method of Worker and this function also runs on a background thread and so we should write the main code inside it. I think JobIntentService and WorkerManager are both good for such purpose. JobIntentService just runs the work once, but by WorkManager we can do a work once or repeat it periodically (the interval time between periods has a minimum of 15 minutes).

Upvotes: -1

MikeL
MikeL

Reputation: 2894

Not sure if this will help you since it's kinda old but:
Your title reads JobIntentService and you use JobService, the answer by TheWanderer refers to your used class (JobService), but if you will use JobIntentService, its method onHandleWork runs on a background thread:

This method is called on a background thread, so you can do long blocking operations here.

Upvotes: 3

TheWanderer
TheWanderer

Reputation: 17854

According to the docs:

This service executes each incoming job on a Handler running on your application's main thread. This means that you must offload your execution logic to another thread/handler/AsyncTask of your choosing. Not doing so will result in blocking any future callbacks from the JobManager - specifically onStopJob(android.app.job.JobParameters), which is meant to inform you that the scheduling requirements are no longer being met.

So, you'll need to use an AsyncTask or some other form of asynchronous method to execute your logic. You should use something cancellable, though, since, when onStopJob() is called, you're supposed to stop whatever you're doing.

Also remember to call jobFinished() when your logic has been completed.

Upvotes: 1

Related Questions