赞
踩
相机自动化测试需求,测试apk通过bindService绑定相机apk里面的一个服务,通过AIDL接口的方式向相机apk发送命令,服务接收到命令之后会拉起相机的Activity。原本没有人为干预的情况下是可以拉起这个Activity的,但是拉起Activity之前,我们如果按下Home键,让测试apk退出的话,后台服务就无法拉起Activity了。经过调查发现Android10 之后做了这个限制
https://developer.android.google.cn/guide/components/activities/background-starts
ITestApp通过bindService连接到ITestAppService,是跨进程的。
ITestAppService是我们的相机应用里面的一个服务,主要是响应外部应用的命令;接收到外部应用的命令之后调用相机内部代码。
其中第一条命令一般就是启动 CameraActivity,就是后台服务启动Activity。
当按了Home键之后,后台服务就无法启动相机Activity了,以下是ActivityTaskManager的日志,启动被终止了。
- 11-16 13:54:01.143 1160 8007 W ActivityTaskManager: Background activity start
- [callingPackage: com.android.camera2; callingUid: 10150; appSwitchState: 1;
- isCallingUidForeground: false; callingUidHasAnyVisibleWindow: false;
- callingUidProcState: FOREGROUND_SERVICE; isCallingUidPersistentSystemProcess: false;
- realCallingUid: 10150; isRealCallingUidForeground: false; realCallingUidHasAnyVisibleWindow: false;
- realCallingUidProcState: FOREGROUND_SERVICE; isRealCallingUidPersistentSystemProcess: false;
- originatingPendingIntent: null; allowBackgroundActivityStart: false;
- intent: Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=com.android.camera2/com.android.camera.CameraActivity (has extras) };
- callerApp: ProcessRecord{a469c90 22598:com.android.camera2/u0a150}; inVisibleTask: false]
反正就是一堆启动的条件都没有满足,所以终止了。
拦截的逻辑就在系统ActivityStarter.java的这个方法里面,反正就是一个条件都不满足了。
AMS WMS的相关代码太复杂,没有过多时间仔细研究。简单看了一下shouldAbortBackgroundActivityStart里面返回false的逻辑,有些还是很好理解的。
像这一段表明只要在相机应用的AndroidManifest.xml文件里面加上android:sharedUserId=“android.uid.system“ 这一行就可以了,实际验证之后发现确实可行。
像这一段 说明只要应用有SYSTEM_ALERT_WINDOW 权限就可以了,实测也是可以的
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
如果不想在被测应用加权限/设置android:sharedUserId,也可以在测试端想办法,我们的做法是在测试应用里面加一个浮窗,那么应用退出的时候浮窗还在,还能继续启动被测应用的activity。
浮窗代码也是copy的,就是通过一个服务启动的
- public class FloatingService extends Service {
- private static final String TAG = "CAMTEST_FloatingService";
-
- public FloatingService() {
-
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- Log.d(TAG, "onCreate");
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- Log.d(TAG, "onDestroy");
- }
-
- @Nullable
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- showFloatingWindow();
- return super.onStartCommand(intent, flags, startId);
- }
-
- WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
-
- private void showFloatingWindow() {
- if (Settings.canDrawOverlays(this)) {
- // 获取WindowManager服务
- WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
-
- // 新建悬浮窗控件
- TextView textView = new TextView(getApplicationContext());
- textView.setText("接口测试需要, 勿惊...");
- textView.setTextColor(0xffff0000);
- textView.setGravity(Gravity.CENTER);
- textView.setBackgroundColor(Color.parseColor("#FF6200EE"));
- textView.setOnTouchListener(new FloatingOnTouchListener());
-
- // 设置LayoutParam
- int screenWidth = windowManager.getDefaultDisplay().getWidth();
- int screenHeight = windowManager.getDefaultDisplay().getHeight();
- layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
- layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- layoutParams.format = PixelFormat.RGBA_8888;
- layoutParams.width = 500;
- layoutParams.height = 100;
- layoutParams.x = screenWidth - layoutParams.width;
- layoutParams.y = screenHeight - layoutParams.height;
-
- // 将悬浮窗控件添加到WindowManager
- windowManager.addView(textView, layoutParams);
- }
- }
-
- private class FloatingOnTouchListener implements View.OnTouchListener {
- private int x;
- private int y;
-
- @Override
- public boolean onTouch(View view, MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- x = (int) event.getRawX();
- y = (int) event.getRawY();
- break;
- case MotionEvent.ACTION_MOVE:
- int nowX = (int) event.getRawX();
- int nowY = (int) event.getRawY();
- int movedX = nowX - x;
- int movedY = nowY - y;
- x = nowX;
- y = nowY;
- layoutParams.x = layoutParams.x + movedX;
- layoutParams.y = layoutParams.y + movedY;
-
- // 更新悬浮窗控件布局
- WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
- windowManager.updateViewLayout(view, layoutParams);
- break;
- default:
- break;
- }
- return false;
- }
- }
- }
启动地方代码
- public void startFloatingService(View view) {
- if (!Settings.canDrawOverlays(this)) {
- Toast.makeText(this, "当前无权限,请授权", Toast.LENGTH_SHORT);
- startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 0);
- } else {
- Log.d(TAG, "startFloatingService startService");
- startService(new Intent(MainActivity.this, FloatingService.class));
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。