Android Oreo - 工作意向服务在主线程上 运行 导致应用冻结几秒钟
Android Oreo - Job Intent Service is running on main Thread causing app to freeze for couple of seconds
我正在尝试在后台下载一些文件。早些时候我在做意图服务,我的应用程序不会在使用意图服务时被冻结。但与 oreo 及以上版本一样,一旦应用程序从后台关闭,Intent 服务就会被破坏。我在作业服务中进行了相同的处理,但它似乎在主线程上 运行 。对于不应该在主线程上 运行 的后台处理,我应该怎么做?
下面是我做的 JOB 调度代码:
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;
}
根据文档:
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.
因此,您需要使用 AsyncTask 或某种其他形式的异步方法来执行您的逻辑。但是,您应该使用可取消的东西,因为当 onStopJob()
被调用时,您应该停止正在做的任何事情。
还记得在您的逻辑完成后调用 jobFinished()
。
不确定这是否对您有帮助,因为它有点旧但是:
你的标题是 JobIntentService
and you use JobService
,答案是
TheWanderer refers to your used class (JobService
), but if you will use JobIntentService
, its method onHandleWork
在后台线程上运行:
This method is called on a background thread, so you can do long blocking operations here.
您可以使用 JobIntentService 作为 download/upload 某些文件甚至与服务器通信的解决方案。另一种更好的方法是 WorkManager。请注意 UI 线程上的 IntentService 运行s 即 UI 线程上的 onHandleIntent(Intent intent)
运行s。所以我们应该使用单独的线程或使用例如 AsyncTask。但是 JobIntentService 有函数 onHandleWork(@NonNull Intent intent)
,它在后台线程上是 运行,所以我们只是在它上面做工作。在 WorkManager 方法中,工作是在 Worker 的 doWork()
方法中完成的,这个函数也在后台线程上 运行s ,所以我们应该把主要代码写在里面。我认为 JobIntentService 和 WorkerManager 都适合这个目的。 JobIntentService 只是 运行 工作一次,但是通过 WorkManager 我们可以做一次工作或定期重复(周期之间的间隔时间至少为 15 分钟)。
我正在尝试在后台下载一些文件。早些时候我在做意图服务,我的应用程序不会在使用意图服务时被冻结。但与 oreo 及以上版本一样,一旦应用程序从后台关闭,Intent 服务就会被破坏。我在作业服务中进行了相同的处理,但它似乎在主线程上 运行 。对于不应该在主线程上 运行 的后台处理,我应该怎么做?
下面是我做的 JOB 调度代码:
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;
}
根据文档:
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.
因此,您需要使用 AsyncTask 或某种其他形式的异步方法来执行您的逻辑。但是,您应该使用可取消的东西,因为当 onStopJob()
被调用时,您应该停止正在做的任何事情。
还记得在您的逻辑完成后调用 jobFinished()
。
不确定这是否对您有帮助,因为它有点旧但是:
你的标题是 JobIntentService
and you use JobService
,答案是
TheWanderer refers to your used class (JobService
), but if you will use JobIntentService
, its method onHandleWork
在后台线程上运行:
This method is called on a background thread, so you can do long blocking operations here.
您可以使用 JobIntentService 作为 download/upload 某些文件甚至与服务器通信的解决方案。另一种更好的方法是 WorkManager。请注意 UI 线程上的 IntentService 运行s 即 UI 线程上的 onHandleIntent(Intent intent)
运行s。所以我们应该使用单独的线程或使用例如 AsyncTask。但是 JobIntentService 有函数 onHandleWork(@NonNull Intent intent)
,它在后台线程上是 运行,所以我们只是在它上面做工作。在 WorkManager 方法中,工作是在 Worker 的 doWork()
方法中完成的,这个函数也在后台线程上 运行s ,所以我们应该把主要代码写在里面。我认为 JobIntentService 和 WorkerManager 都适合这个目的。 JobIntentService 只是 运行 工作一次,但是通过 WorkManager 我们可以做一次工作或定期重复(周期之间的间隔时间至少为 15 分钟)。