如何在屏幕锁定时在后台定期 运行 a service/thread?
How can I periodically run a service/thread in background even when the screen is locked?
我正在开发一个可以每半小时检查一次网络数据的应用程序,我需要确保只要电源打开它就会保持 运行。
现在,我的应用程序的结构是这样的:
- main_activity:
onCreate()
中的 AlarmManager
- alarm_receiver:
start_service
为服务获取 partial_wl
- 服务:
使用 StrictMode 获取网络数据
pop activity_2 如果数据是预期的
- activity_2:
振动
退出按钮(activity_2.this.finish())
但在测试中我发现服务会在前 30 分钟后停止(被终止)。另外,如果我在服务中开启一个线程进行联网,而不是使用StrictMode,它会在锁屏后5分钟被杀死。
希望有人能对此提出建议。这真是令人不安。
非常感谢。
无论 activity 发生什么,公共服务都会存在。如果你想让它定期启动检查我的服务:
https://bitbucket.org/kvrus/ocs-android/raw/036de7f0d3579b2a193bcb82309f7f82819508e6/app/src/main/java/koss/ru/oneclickrate/network/EcbEuropeService.java
/**
* 定期从网络加载汇率
* Returns 导致广播消息。
* 由 koss 于 2016 年 2 月 19 日创建。
* */
public class EcbEuropeService 扩展服务 {
public static final String ECB_URL = "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";
public static final int UPDATE_PERIOD = 30000;
public static final int UPDATE_TICK = 1000;
public static final String NOTIFICATION = "koss.ru.oneclickrate.receiver";
public static final String EXTRA_CURRENCIES_MAP = "extra_currencies_map";
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
getUrlData();
return Service.START_NOT_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
public Cubes getUrlData() {
(new AsyncTask<Object, Object, Cubes>() {
Map<CurrencyType, BigDecimal> result = new EnumMap<CurrencyType, BigDecimal>(CurrencyType.class);
@Override
protected Cubes doInBackground(Object... params) {
Cubes cubes = new Cubes();
InputStream is = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(ECB_URL);
urlConnection = (HttpURLConnection) url.openConnection();
is = urlConnection.getInputStream();
cubes = EcbEuropeResponseParser.parse(is);
} catch (Exception e) {
e.printStackTrace();
} finally {
if(urlConnection!=null) IOUtils.close(urlConnection);
if(is!=null) IOUtils.closeQuietly(is);
return cubes;
}
}
@Override
protected void onPostExecute(Cubes map) {
super.onPostExecute(map);
sendBroadcastMessage(map);
startTimer();
}
}).execute();
return null;
}
/**
* Restarts timer
* */
public void startTimer() {
cdt.cancel();
cdt.start();
}
CountDownTimer cdt = new CountDownTimer(UPDATE_PERIOD, UPDATE_TICK) {
@Override
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
getUrlData();
}
};
private void sendBroadcastMessage(Cubes currenciesMap) {
Intent intent = new Intent(NOTIFICATION);
intent.putExtra(EXTRA_CURRENCIES_MAP, currenciesMap);
sendBroadcast(intent);
}
我改变了一些东西,现在效果很好。
1.As 我的 phone 是 4.4.2(api=19),alarmmanager.setrepeating 不准确。所以我转而使用.setExact(.set()的新方法)并在Service中的AsyncTask(网络)结束时重新安排警报。
2.Make全局wakelock实例,在AlarmReceiver中获取,AsyncTask结束时释放。我曾经将 .release() 放在 onDestroy() 中,它会在任务完成之前释放锁。
3.There 是我的 phone 中有关受保护后台应用程序的设置,我没有打开它。这可以让系统杀死应用程序并禁用警报管理器。
我正在开发一个可以每半小时检查一次网络数据的应用程序,我需要确保只要电源打开它就会保持 运行。 现在,我的应用程序的结构是这样的:
- main_activity:
onCreate()
中的 AlarmManager
- alarm_receiver:
start_service 为服务获取 partial_wl - 服务:
使用 StrictMode 获取网络数据 pop activity_2 如果数据是预期的 - activity_2:
振动 退出按钮(activity_2.this.finish())
但在测试中我发现服务会在前 30 分钟后停止(被终止)。另外,如果我在服务中开启一个线程进行联网,而不是使用StrictMode,它会在锁屏后5分钟被杀死。
希望有人能对此提出建议。这真是令人不安。 非常感谢。
无论 activity 发生什么,公共服务都会存在。如果你想让它定期启动检查我的服务: https://bitbucket.org/kvrus/ocs-android/raw/036de7f0d3579b2a193bcb82309f7f82819508e6/app/src/main/java/koss/ru/oneclickrate/network/EcbEuropeService.java
/** * 定期从网络加载汇率 * Returns 导致广播消息。 * 由 koss 于 2016 年 2 月 19 日创建。 * */ public class EcbEuropeService 扩展服务 {
public static final String ECB_URL = "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";
public static final int UPDATE_PERIOD = 30000;
public static final int UPDATE_TICK = 1000;
public static final String NOTIFICATION = "koss.ru.oneclickrate.receiver";
public static final String EXTRA_CURRENCIES_MAP = "extra_currencies_map";
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
getUrlData();
return Service.START_NOT_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
public Cubes getUrlData() {
(new AsyncTask<Object, Object, Cubes>() {
Map<CurrencyType, BigDecimal> result = new EnumMap<CurrencyType, BigDecimal>(CurrencyType.class);
@Override
protected Cubes doInBackground(Object... params) {
Cubes cubes = new Cubes();
InputStream is = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(ECB_URL);
urlConnection = (HttpURLConnection) url.openConnection();
is = urlConnection.getInputStream();
cubes = EcbEuropeResponseParser.parse(is);
} catch (Exception e) {
e.printStackTrace();
} finally {
if(urlConnection!=null) IOUtils.close(urlConnection);
if(is!=null) IOUtils.closeQuietly(is);
return cubes;
}
}
@Override
protected void onPostExecute(Cubes map) {
super.onPostExecute(map);
sendBroadcastMessage(map);
startTimer();
}
}).execute();
return null;
}
/**
* Restarts timer
* */
public void startTimer() {
cdt.cancel();
cdt.start();
}
CountDownTimer cdt = new CountDownTimer(UPDATE_PERIOD, UPDATE_TICK) {
@Override
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
getUrlData();
}
};
private void sendBroadcastMessage(Cubes currenciesMap) {
Intent intent = new Intent(NOTIFICATION);
intent.putExtra(EXTRA_CURRENCIES_MAP, currenciesMap);
sendBroadcast(intent);
}
我改变了一些东西,现在效果很好。
1.As 我的 phone 是 4.4.2(api=19),alarmmanager.setrepeating 不准确。所以我转而使用.setExact(.set()的新方法)并在Service中的AsyncTask(网络)结束时重新安排警报。
2.Make全局wakelock实例,在AlarmReceiver中获取,AsyncTask结束时释放。我曾经将 .release() 放在 onDestroy() 中,它会在任务完成之前释放锁。
3.There 是我的 phone 中有关受保护后台应用程序的设置,我没有打开它。这可以让系统杀死应用程序并禁用警报管理器。