Android重启后AccessibilityService网络请求异常问题排查
问题描述
本人英语水平有限,若表述有语法问题请见谅。在开发AccessibilityService项目时,需求为在onAccessibilityEvent()方法中请求自有服务器接口。项目初次运行时,onAccessibilityEvent中可正常发起网络请求,但Android设备重启后会出现网络请求错误,无法理解报错原因。
相关代码如下:
public class HongBaoService extends AccessibilityService { private static final String ACTION_HIDE="com.example.accessibilityt.ACTION_HIDE"; private SideBarHideReceiver mReceiver; private SideBarArrow mLeftArrowBar; public static HongBaoService mService; @Override protected void onServiceConnected() { super.onServiceConnected(); Log.d("InitApp","AccessibilityService_connected"); Log.d(MainActivity.TAG,"onServiceConnected"); mService=this; IntentFilter intentFilter=new IntentFilter("com.example.accessibilityt.XposedReceiver.ACTION_AGAIN"); registerReceiver(responseXposed,intentFilter); } @Override public void onCreate() { super.onCreate(); createToucher(); } @SuppressLint({"RtlHardcoded", "InflateParams"}) private void createToucher() { Log.d(MainActivity.TAG,"AccessibilityService onCreate"); Log.d("InitApp","AccessibilityService_create"); // get window manager WindowManager windowManager = (WindowManager) getApplication().getSystemService(Context.WINDOW_SERVICE); // left arrow mLeftArrowBar = new SideBarArrow(); LinearLayout mArrowLeft = mLeftArrowBar.getView(this, windowManager, this); } @Override public void onAccessibilityEvent(AccessibilityEvent event) { Log.d("InitApp","AccessibilityService_event"); //核心代码 new Thread(){ @Override public void run() { super.run(); OkHttpClient client=new OkHttpClient(); Request request=new Request.Builder() .url("http://192.168.169.1:8088/dex2java/test") .build(); try { Response response=client.newCall(request).execute(); Log.d("InitAppA",response.body().string()); } catch (IOException e) { throw new RuntimeException(e); } } }.start(); if (sendRequestThead==null) sendRequest(); } @Override public void onInterrupt() { Log.d("InitApp","onInterrupt"); mService=null; } @Override public void onDestroy() { super.onDestroy(); mLeftArrowBar.clearAll(); unregisterReceiver(responseXposed); mService=null; } public static boolean isStart(){ return mService!=null; } public Queue<XposedRequestData> queue=new LinkedList<>(); private BroadcastReceiver responseXposed=new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String urlPath=intent.getStringExtra("urlPath"); String fileName=intent.getStringExtra("fileName"); String packageName=intent.getStringExtra("packageName"); String apkPath=intent.getStringExtra("apkPath"); Log.i("InitApp",urlPath+" "+fileName+" "+packageName+" "+apkPath); queue.add(new XposedRequestData(urlPath,fileName,packageName,apkPath)); loopSetViewProvider(urlPath,fileName,packageName); } }; private static volatile boolean isInterrupt=false; private static volatile boolean isOnDestroy=false; private void loopSetViewProvider(String urlPath,String fileName,String packageName){ Thread thread=new Thread(new Runnable() { @Override public void run() { while (true){ if (isInterrupt) break; } if (queue==null||queue.size()<=0) return; InputStream inputStream; XposedRequestData data; ByteArrayOutputStream buffer; try { data=queue.poll(); buffer=new ByteArrayOutputStream(); inputStream=getApkFile(data.apkPath,data.fileName); int bytesRead; byte[] arrayByte=new byte[4096]; while ((bytesRead=inputStream.read(arrayByte,0,arrayByte.length))!=-1){ buffer.write(arrayByte,0,bytesRead); } buffer.flush(); } catch (IOException e) { throw new RuntimeException(e); } if (inputStream==null){ Log.d("InitAppA","inputstream is null"); return; } Log.i("InitAppA",urlPath+" "+fileName+" "+packageName+" "+buffer.toByteArray()); // 实际需求:在此线程中发起网络请求,该线程有两个触发条件:onAccessibilityEvent调用和responseXposed接收请求 } }); thread.start(); } private ZipFile zipFile; private InputStream getApkFile(String apkPath, String fileName) throws IOException { File file=new File(apkPath); if (file==null||apkPath==null) return null; zipFile=new ZipFile(file); Enumeration<? extends ZipEntry> entries = zipFile.entries(); while (entries.hasMoreElements()){ ZipEntry entry=entries.nextElement(); String entryName=entry.getName(); if (entryName.equals(fileName)){ Log.d("InitAppA",entryName+" "+fileName); return zipFile.getInputStream(entry); } } zipFile.close(); return null; } private Thread sendRequestThead; private void sendRequest(){ sendRequestThead=new Thread(new Runnable() { @Override public void run() { while (!isOnDestroy){ try { if (isInterrupt) Thread.sleep(5000); isInterrupt=!isInterrupt; } catch (InterruptedException e) { throw new RuntimeException(e); } } } }); sendRequestThead.start(); } private class XposedRequestData{ public String urlPath; public String fileName; public String packageName; public String apkPath; public XposedRequestData(String urlPath,String fileName,String packageName,String apkPath){ this.urlPath=urlPath; this.fileName=fileName; this.packageName=packageName; this.apkPath=apkPath; } } }
问题分析与解决方法
可能的原因
- 后台网络访问限制:Android 8.0(API 26)及以上版本,应用在后台运行时默认被限制网络访问,重启后AccessibilityService可能处于后台状态,导致网络请求失败。
- 权限问题:初次运行时权限正常,但重启后系统可能未正确授予
INTERNET或ACCESS_NETWORK_STATE权限,或权限被系统回收。 - OkHttpClient初始化不合理:每次请求新建实例,未配置超时、重试策略,重启后网络环境变化时无法自动恢复。
- 线程逻辑混乱:
loopSetViewProvider中的无限循环会导致线程阻塞、资源耗尽,影响后续网络请求执行。
解决步骤
配置网络相关权限
在AndroidManifest.xml中补充必要权限:<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- Android 10+ 允许后台网络访问 --> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <application ... android:usesCleartextTraffic="true"> <!-- 若使用HTTP明文请求需添加,HTTPS可省略 --> </application>全局复用OkHttpClient实例
避免每次请求新建实例,配置超时与重试策略:private OkHttpClient mOkHttpClient; @Override public void onCreate() { super.onCreate(); createToucher(); // 初始化全局OkHttpClient mOkHttpClient = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .retryOnConnectionFailure(true) .build(); } @Override public void onAccessibilityEvent(AccessibilityEvent event) { Log.d("InitApp","AccessibilityService_event"); new Thread(){ @Override public void run() { super.run(); Request request=new Request.Builder() .url("http://192.168.169.1:8088/dex2java/test") .build(); try { Response response=mOkHttpClient.newCall(request).execute(); Log.d("InitAppA",response.body().string()); } catch (IOException e) { Log.e("InitAppA", "网络请求失败: " + e.getMessage()); } } }.start(); if (sendRequestThead==null) sendRequest(); }修复线程循环逻辑
替换无限循环为合理的队列轮询,避免资源浪费:private void loopSetViewProvider(String urlPath,String fileName,String packageName){ Thread thread=new Thread(new Runnable() { @Override public void run() { while (!isOnDestroy && !Thread.currentThread().isInterrupted()){ if (queue!=null && queue.size()>0){ processQueueItem(); } else { try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } } } private void processQueueItem() { InputStream inputStream = null; XposedRequestData data; ByteArrayOutputStream buffer; try { data=queue.poll(); if (data == null) return; buffer=new ByteArrayOutputStream(); inputStream=getApkFile(data.apkPath,data.fileName); if (inputStream == null){ Log.d("InitAppA","inputstream is null"); return; } int bytesRead; byte[] arrayByte=new byte[4096]; while ((bytesRead=inputStream.read(arrayByte,0,arrayByte.length))!=-1){ buffer.write(arrayByte,0,bytesRead); } buffer.flush(); // 发起网络请求 Request request = new Request.Builder() .url(data.urlPath) .post(RequestBody.create(buffer.toByteArray(), MediaType.parse("application/octet-stream"))) .build(); Response response = mOkHttpClient.newCall(request).execute(); Log.d("InitAppA", "请求结果: " + response.body().string()); } catch (IOException e) { Log.e("InitAppA", "处理队列失败: " + e.getMessage()); } finally { if (inputStream != null){ try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (zipFile != null){ try { zipFile.close(); } catch (IOException e) { e.printStackTrace(); } } } } }); thread.start(); }重启后检查权限
在onServiceConnected中校验权限,缺失则引导用户开启:@Override protected void onServiceConnected() { super.onServiceConnected(); Log.d("InitApp","AccessibilityService_connected"); Log.d(MainActivity.TAG,"onServiceConnected"); mService=this; // 检查网络权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } IntentFilter intentFilter=new IntentFilter("com.example.accessibilityt.XposedReceiver.ACTION_AGAIN"); registerReceiver(responseXposed,intentFilter); }
内容的提问来源于stack exchange,提问作者liang shang
相关产品推荐
相关产品推荐

