Android 应用程序关闭/设置为后台时如何执行后台任务?
How to execute background task when Android app is closed / set to background?
我的 Android 4+ 应用程序已连接到用于每隔几分钟同步一次数据的自定义 Web 服务。为了确保在线数据始终是最新的,我想在应用程序关闭/发送到后台时触发同步。
在 iOS 下这很容易:
- 在 AppDelegate
中收听 applicationDidEnterBackground:
- 使用
beginBackgroundTaskWithName:
启动你的长期 运行ning 后台任务,避免在任务仍在 运行ning 时被挂起
如何在 Android 上执行此操作?
第一个问题是,没有什么等同于applicationDidEnterBackground:
。到目前为止我发现的所有解决方案都建议使用主要的 Activities onPause()
方法。但是,只要主 Activity
暂停,就会调用此方法,当另一个 Activity
在应用程序中启动时也是如此。 ActivityLifecycleCallbacks
接口中的 onActivityPaused()
方法也是如此。
那么,如何检测app(不仅仅是Activity
)关闭或发送到后台?
第二个问题是,我没有找到任何关于如何运行后台任务的信息。所有解决方案都指向简单地启动一个 AsyncTask
,但这真的是正确的解决方案吗?
AsyncTask
会启动一个新任务,但是当应用程序 closed/inactive 时,这个任务也会 运行 吗?我该怎么做才能防止应用程序和任务在几秒钟后暂停?我怎样才能确保任务可以在应用程序完全挂起之前完成?
当您的应用关闭或在后台时,以下代码将帮助您post您的内容:
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.widget.Toast;
public class SendDataService extends Service {
private final LocalBinder mBinder = new LocalBinder();
protected Handler handler;
protected Toast mToast;
public class LocalBinder extends Binder {
public SendDataService getService() {
return SendDataService .this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
// write your code to post content on server
}
});
return android.app.Service.START_STICKY;
}
}
我的代码的更多解释是:
即使您的应用程序在后台,服务也会在后台运行,但请记住,它始终在主线程上运行,因此我创建了一个单独的线程来执行您的后台操作。
服务作为粘性服务启动,即使由于任何原因您的服务在后台被破坏,它也会自动重新启动。
可在此处找到更多详细信息:
https://developer.android.com/guide/components/services.html
并检查您的应用是否在 foreground/background 中,以下代码将有所帮助:
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
}
// Use like this:
boolean foregroud = new ForegroundCheckTask().execute(context).get();
快乐编码!!!!
您可以使用服务来实现您想要的目标。如果您没有调用 stopService(..) 或 stopSelf(),即使 activity 组件已被销毁 ,服务也会在后台 保持 运行方法。
在该服务中,您可以进行异步网络调用,最好使用改造,然后您可以使用从 Web 服务获取的最新数据更新本地存储,如 Sqlite DB。
Here是官方的link,你可以使用无界服务来达到你想要的效果。
接受的答案不正确。
不幸的是,作者认为将新的 Runnable
任务发布到 Handler()
会创建一个单独的线程 - "I created a separate thread to perform your background operations" :
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
// write your code to post content on server
}
});
return android.app.Service.START_STICKY;
}
onStartCommand()
回调总是在主线程上调用,新的 Handler()
附加到当前线程(即 "main")。所以 Runnable
任务被发布在主线程队列的末尾。
要解决此问题并在真正独立的线程中执行 Runnable
,您可以使用 AsyncTask
作为最简单的解决方案:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
// ...
}
});
return android.app.Service.START_STICKY;
}
在复制粘贴任何内容之前先想想自己...
对于后台操作,您可以使用WorkManager
。
我的 Android 4+ 应用程序已连接到用于每隔几分钟同步一次数据的自定义 Web 服务。为了确保在线数据始终是最新的,我想在应用程序关闭/发送到后台时触发同步。
在 iOS 下这很容易:
- 在 AppDelegate 中收听
- 使用
beginBackgroundTaskWithName:
启动你的长期 运行ning 后台任务,避免在任务仍在 运行ning 时被挂起
applicationDidEnterBackground:
如何在 Android 上执行此操作?
第一个问题是,没有什么等同于applicationDidEnterBackground:
。到目前为止我发现的所有解决方案都建议使用主要的 Activities onPause()
方法。但是,只要主 Activity
暂停,就会调用此方法,当另一个 Activity
在应用程序中启动时也是如此。 ActivityLifecycleCallbacks
接口中的 onActivityPaused()
方法也是如此。
那么,如何检测app(不仅仅是Activity
)关闭或发送到后台?
第二个问题是,我没有找到任何关于如何运行后台任务的信息。所有解决方案都指向简单地启动一个 AsyncTask
,但这真的是正确的解决方案吗?
AsyncTask
会启动一个新任务,但是当应用程序 closed/inactive 时,这个任务也会 运行 吗?我该怎么做才能防止应用程序和任务在几秒钟后暂停?我怎样才能确保任务可以在应用程序完全挂起之前完成?
当您的应用关闭或在后台时,以下代码将帮助您post您的内容:
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.widget.Toast;
public class SendDataService extends Service {
private final LocalBinder mBinder = new LocalBinder();
protected Handler handler;
protected Toast mToast;
public class LocalBinder extends Binder {
public SendDataService getService() {
return SendDataService .this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
// write your code to post content on server
}
});
return android.app.Service.START_STICKY;
}
}
我的代码的更多解释是:
即使您的应用程序在后台,服务也会在后台运行,但请记住,它始终在主线程上运行,因此我创建了一个单独的线程来执行您的后台操作。
服务作为粘性服务启动,即使由于任何原因您的服务在后台被破坏,它也会自动重新启动。
可在此处找到更多详细信息: https://developer.android.com/guide/components/services.html
并检查您的应用是否在 foreground/background 中,以下代码将有所帮助:
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
}
// Use like this:
boolean foregroud = new ForegroundCheckTask().execute(context).get();
快乐编码!!!!
您可以使用服务来实现您想要的目标。如果您没有调用 stopService(..) 或 stopSelf(),即使 activity 组件已被销毁 ,服务也会在后台 保持 运行方法。
在该服务中,您可以进行异步网络调用,最好使用改造,然后您可以使用从 Web 服务获取的最新数据更新本地存储,如 Sqlite DB。
Here是官方的link,你可以使用无界服务来达到你想要的效果。
接受的答案不正确。
不幸的是,作者认为将新的 Runnable
任务发布到 Handler()
会创建一个单独的线程 - "I created a separate thread to perform your background operations" :
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
// write your code to post content on server
}
});
return android.app.Service.START_STICKY;
}
onStartCommand()
回调总是在主线程上调用,新的 Handler()
附加到当前线程(即 "main")。所以 Runnable
任务被发布在主线程队列的末尾。
要解决此问题并在真正独立的线程中执行 Runnable
,您可以使用 AsyncTask
作为最简单的解决方案:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
// ...
}
});
return android.app.Service.START_STICKY;
}
在复制粘贴任何内容之前先想想自己...
对于后台操作,您可以使用WorkManager
。