Android 即使屏幕被锁定,我如何在后台定期运行服务/线程?
我正在开发一款可以每半小时检查一次网络数据的应用程序,我需要确保它在通电的情况下一直运行。 目前,我的应用程序的结构如下:Android 即使屏幕被锁定,我如何在后台定期运行服务/线程?,android,multithreading,service,wakelock,Android,Multithreading,Service,Wakelock,我正在开发一款可以每半小时检查一次网络数据的应用程序,我需要确保它在通电的情况下一直运行。 目前,我的应用程序的结构如下: 主要活动: onCreate()中的AlarmManager 报警接收器: 启动服务 获取服务的部分内容 服务: 使用StrictMode获取网络数据 如果需要数据,则弹出活动2 活动2: 振动 按钮退出(活动2.this.finish()) 但在测试中,我发现服务将在前30分钟后停止(被终止)。此外,如果我在服务中启动一个用于联网的线程而不是使用StrictMode,它将
onCreate()中的AlarmManager
启动服务 获取服务的部分内容
使用StrictMode获取网络数据 如果需要数据,则弹出活动2
振动 按钮退出
(活动2.this.finish())
非常感谢。普通使用寿命不管活动发生了什么。如果您希望定期启动,请查看矿山服务: /** *定期从网络中加载汇率 *返回广播消息中的结果。 *由koss于2016年2月19日创建。 * */ 公共类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);
}
public静态最终字符串ECB\u URL=”http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";
公共静态最终整数更新周期=30000;
公共静态最终整数更新_TICK=1000;
公共静态最终字符串通知=“koss.ru.oneclickrate.receiver”;
公共静态最终字符串EXTRA\u currences\u MAP=“EXTRA\u currences\u MAP”;
@凌驾
公共int onStartCommand(Intent Intent、int标志、int startId){
getUrlData();
退货服务。开始时不粘;
}
@凌驾
公共IBinder onBind(意向){
返回null;
}
公共多维数据集getUrlData(){
(新任务(){
映射结果=新的EnumMap(CurrencyType.class);
@凌驾
受保护的多维数据集doInBackground(对象…参数){
立方体=新立方体();
InputStream=null;
HttpURLConnection-urlConnection=null;
试一试{
URL URL=新URL(ECB_URL);
urlConnection=(HttpURLConnection)url.openConnection();
is=urlConnection.getInputStream();
cubes=ecbeuropresponseparser.parse(is);
}捕获(例外e){
e、 printStackTrace();
}最后{
if(urlConnection!=null)IOUtils.close(urlConnection);
if(is!=null)IOUtils.closes(is);
返回立方体;
}
}
@凌驾
受保护的void onPostExecute(多维数据集映射){
super.onPostExecute(map);
发送广播信息(map);
startTimer();
}
}).execute();
返回null;
}
/**
*重新启动计时器
* */
公共无效startTimer(){
cdt.cancel();
cdt.start();
}
倒计时cdt=新倒计时(更新周期,更新勾号){
@凌驾
公共void onTick(长毫秒未完成){
}
公共无效onFinish(){
getUrlData();
}
};
私有void发送广播消息(多维数据集当前映射){
意向=新意向(通知);
意向。额外支付(额外货币地图、货币地图);
发送广播(意图);
}
我做了一些改动,现在效果很好
1.由于我的手机是4.4.2(api=19),alarmmanager.setrepeating不准确。因此我转而使用.setExact(新方法.set())并在服务中的AsyncTask(网络)结束时重新安排闹钟
2.将wakelock实例设置为全局,在AlarmReceiver中获取它,并在AsyncTask结束时释放。我曾经在onDestroy()中放置.release(),它在任务完成之前释放锁
3.我的手机中有一个关于受保护的后台应用程序的设置,我没有打开它。这会允许系统关闭应用程序并禁用报警管理器。运行后台服务只是为了检查是否有新数据可用不是一个好主意。试着使用GCM实现同样的设置。您不需要创建服务。AlarmManager每半小时重复一次不精确的警报就可以了。事实上,它就是为了这个目的而设计的。我还建议在有数据时发出通知,而不是自己显示活动。这样,用户就可以收到通知,并可以在方便的时候打开已有数据的活动。