Android后台Service冻结问题:Volley循环发送GET请求后停止运行
问题排查:Android后台服务运行一段时间后停止HTTP请求
问题描述
本人非Android开发者,首次使用Android Studio构建安卓包,通过视频学习并借助ChatGPT获取基础代码。该应用使用Volley库向远程端点发送GET请求,获取JSON字符串后解析出文本参数,并将文本发送至指定号码。代码可正常运行,但运行20-40分钟后(时长随机,最长可达1小时),Android会冻结该应用,后台不再发送HTTP请求。已配置INTERNET、SEND_SMS等权限,通过MainActivity调用startService启动SMSService,返回START_STICKY,logcat无有效报错信息。
相关代码
public class SMSService extends Service { private static final String TAG = "SMSServiceBackground"; private static final long INTERVAL_MS = 30000; // Query interval in milliseconds (e.g., 1 minute) private Handler handler = new Handler(Looper.getMainLooper()); @Override public int onStartCommand(Intent intent, int flags, int startId) { handler.postDelayed(runnable, 0); return START_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } private Runnable runnable = new Runnable() { private RequestQueue requestQueue; @Override public void run() { try { Log.e(TAG, "Querying"); JsonObjectRequest jsonObjectRequest = new JsonObjectRequest( Request.Method.GET, "https://mywebsite.com/endpoint", null, response -> { try { JSONArray jsonArray = response.getJSONArray("body"); Log.e(TAG, "Received " + jsonArray.length()); for (int i = 0; i < jsonArray.length(); i++) { JSONObject item = jsonArray.getJSONObject(i); String smsBody = item.getString("text"); sendSMS(smsBody); } } catch (JSONException e) { Log.e(TAG, "JSON exception received " + e.getMessage()); //e.printStackTrace(); } }, error -> { Log.e(TAG, "Error: " + error.getMessage()); } ); jsonObjectRequest.setShouldCache(false);// no caching url... jsonObjectRequest.setRetryPolicy( new DefaultRetryPolicy( 10000,//time to wait for it in this case 20s 20,//tries in case of error DefaultRetryPolicy.DEFAULT_BACKOFF_MULT ) ); if( this.requestQueue == null ){ File cacheDir = new File(getApplicationContext().getCacheDir(), "Volley"); this.requestQueue = new RequestQueue(new DiskBasedCache(cacheDir), new BasicNetwork(new HurlStack()), 4); requestQueue.start(); } requestQueue.add(jsonObjectRequest); } catch (Exception exception) { Log.e(TAG, "Error: " + exception.getMessage()); } // Reschedule the task handler.postDelayed(this, INTERVAL_MS); } }; private void sendSMS(String phoneNumber, String smsBody) { // Send using : smsManager.sendMultipartTextMessage(phoneNumber, null, parts, sentIntents, deliveryIntents); } }
排查方向
- Android后台限制机制:从API 26开始,Android对后台服务有严格管控,普通
Service在应用进入后台后会被系统逐步限制,Doze模式和App Standby会直接抑制后台网络请求与任务执行。START_STICKY仅能在服务被意外杀死后尝试重启,无法绕过系统的后台资源限制。 - 主线程阻塞问题:当前使用
Looper.getMainLooper()的Handler,所有任务均在主线程执行。网络请求回调、短信发送操作如果耗时过长,会持续阻塞主线程,触发ANR(应用无响应),最终被系统强制冻结或终止。 - Volley RequestQueue初始化不合理:在
Runnable内部初始化RequestQueue存在线程安全隐患,且不符合Volley官方推荐的全局单例创建方式,多次初始化可能导致资源占用异常。 - 短信发送的潜在阻塞:
sendSMS方法若为同步执行,会占用主线程时间片,累积卡顿后触发系统的应用冻结机制。 - 任务调度中断风险:若
sendSMS或Volley回调中抛出未被捕获的异常,会导致当前Runnable终止,后续的postDelayed任务无法被正常调度,服务也就停止了工作。 - 内存泄漏问题:
Handler持有Service的引用,若服务未正确销毁,会导致内存泄漏,累积到一定程度后触发系统的进程回收机制。
内容的提问来源于stack exchange,提问作者zeroweb
相关产品推荐
相关产品推荐

