轮询服务:不定期
Posted
技术标签:
【中文标题】轮询服务:不定期【英文标题】:Polling service: irregular intervals 【发布时间】:2013-12-06 14:20:16 【问题描述】:出于测试目的,我制作了一个由简单活动组成的小型 android 应用程序,您可以在其中插入主机、端口和间隔(以秒为单位)。该应用程序启动一个服务,该服务创建一个线程,该线程的循环从套接字的输入流中读取,直到它被有意停止。 这是服务的代码:
@Override
public int onStartCommand(Intent intent, int flags, int startId)
prepareFileLogging();
FILELOG.info("PollingService: onStartCommand");
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent bIntent = new Intent(this, MainActivity.class);
PendingIntent pbIntent = PendingIntent
.getActivity(this, 0, bIntent, Intent.FLAG_ACTIVITY_CLEAR_TOP);
Notification.Builder bBuilder =
new Notification.Builder(this)
.setSmallIcon(android.R.drawable.stat_notify_sync)
.setContentTitle("PollingTest")
.setContentText("Servizio di polling attivo")
.setAutoCancel(true)
.setOngoing(true)
.setContentIntent(pbIntent);
this.startForeground(1, bBuilder.build());
Log.i("PollingService", "Received start id " + startId + ": " + intent);
FILELOG.info("PollingService: Received start id " + startId + ": " + intent);
hostName = intent.getExtras().getString(PAR_HOST);
portNumber = intent.getExtras().getInt(PAR_PORT);
freqSeconds = intent.getExtras().getInt(PAR_FREQ);
if(pollingThread == null)
FILELOG.info("pollingThread not running: starting...");
pollingThread = new Poll();
pollingThread.start();
Toast.makeText(this, "Servizio in Background: Serviziosincronizzazione.onCreate()",
Toast.LENGTH_LONG).show();
mReceiver = new BroadcastRec();
getApplication().registerReceiver(mReceiver, filter);
return START_REDELIVER_INTENT;
@Override
public void onDestroy()
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification.Builder bBuilder = new Notification.Builder(this)
.setSmallIcon(android.R.drawable.stat_notify_error).setContentTitle(
"PollingTest")
.setContentText("Il Servizio di polling è sinterrotto");
Toast.makeText(this, "Servizio interrotto", Toast.LENGTH_SHORT).show();
getApplication().unregisterReceiver(mReceiver);
stopPollingService();
Log.i("PollingService", "onDestroy");
super.onDestroy();
private class Poll extends Thread
@Override
public void run()
Thread thisThread = Thread.currentThread();
FILELOG.info("pollingThread: started");
try
Socket echoSocket = new Socket(hostName, portNumber);
PrintWriter out =
new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
int nanos = 250000;
while (pollingThread == thisThread)
Log.i("PollThread", "start of a new call");
out.println("prova");
String response = in.readLine();
FILELOG.info("pollingThread: server response: " +response);
System.out.println("server: " + response);
if (response != null && response.equals("null"))
FILELOG.info("pollingThread: server down (reponse 'null'), new socket");
echoSocket = new Socket(hostName, portNumber);
sendBroadcast(new Intent());
try
Log.i("PollThread", "timeout start...");
Thread.sleep(freqSeconds*1000, nanos);
catch (InterruptedException e)
Log.i("PollThread", e.getMessage());
FILELOG.info("pollingThread error: " + e.getMessage());
catch (UnknownHostException e)
FILELOG.info("pollingThread error: Don't know about host " + e.getMessage());
System.err.println("Don't know about host " + hostName);
stopPollingService();
catch (IOException e)
FILELOG.info("pollingThread error: Couldn't get I/O for the connection to " + e.getMessage());
System.err.println("Couldn't get I/O for the connection to " +
hostName);
stopPollingService();
我让应用程序在平板电脑上运行了一天,分析了电池的消耗情况以及两次向服务器发出请求的时间间隔。 我注意到的问题是,大约 10 分钟,5 秒的间隔得到遵守,然后它在 5 到 20 秒之间变化! 平板电脑已被唤醒几次并解锁,服务从未崩溃。 这是服务器观察到的间隔序列:
有人能想到为什么会这样吗?
【问题讨论】:
我认为您的服务正在被系统破坏,然后以不规则的时间间隔重新启动,因为您正在从 onStartCommand 发送重新交付意图常量。你说服务器没有崩溃,但是 onDestroy 曾经被调用过吗? onDestroy 永远不会被调用,而 onStartCommand 只会被调用一次! 【参考方案1】:系统很可能会进入低功耗状态,因为设备空闲了 10 分钟。为了可靠地唤醒您,您需要通过AlarmManager
使用闹钟或保持部分唤醒锁定。
【讨论】:
但是平板被唤醒了两三遍! 可能是您的设备进入睡眠状态并暂停其网络连接,然后唤醒并再次连接(即 wifi)。这可能会使您的套接字通信“涓涓细流”,因此您的in.readLine()
呼叫不会立即发生并导致延迟。在这种情况下,直到你得到一个完整的行,你的 5 秒超时才会发生。
你知道高级设置:“Wifi优化”是什么吗?也许是相关的。
根据我的经验,当进入低功耗状态时,平台对其各种硬件组件(例如 wifi)的处理往往取决于供应商。话虽如此,较新版本的 Android 中提供的“Wifi 优化”功能会在屏幕关闭时通过让硬件长时间休眠来降低 wifi 性能。所以是的,这很可能与您所看到的行为有关。
谢谢!我将在关闭此设置的情况下进行另一次测试以上是关于轮询服务:不定期的主要内容,如果未能解决你的问题,请参考以下文章
如何在 iOS 中使用 AFNetworking 从 REST 接口定期轮询/拉取
使用SqlDependency与表的定期轮询(对性能的影响)