[英]Android: programmatically open Overview/Recents screen in API 24+
我正在尝试在Android中打开“概述/最新信息”屏幕。 从Android:以编程方式打开“最近使用的应用程序”对话框 ,我可以使用以下代码:
try {
Class serviceManagerClass = Class.forName("android.os.ServiceManager");
Method getService = serviceManagerClass.getMethod("getService", String.class);
IBinder retbinder = (IBinder) getService.invoke(null, "statusbar");
Class statusBarClass = Class.forName(retbinder.getInterfaceDescriptor());
Object statusBarObject = statusBarClass.getClasses()[0]
.getMethod("asInterface", IBinder.class).invoke(null, retbinder);
Method toggleRecentApps = statusBarClass.getMethod("toggleRecentApps");
toggleRecentApps.setAccessible(true);
toggleRecentApps.invoke(statusBarObject);
} catch (InvocationTargetException| NoSuchMethodException | RemoteException | IllegalAccessException | ClassNotFoundException e){
handleError(e);
}
但是,自从牛轧糖以来, toggleRecentApps()
中就不再存在 toggleRecentApps()
,它会导致NoSuchMethodException。
是否可以使用其他任何方式(不包括AccessibilityService)打开“概述/近期”屏幕?
编辑 :实现IStatusBarService的类似乎是StatusBarManagerService 。 但是,调用statusBarObject.getClass().getCanonicalName()
返回com.android.internal.statusbar.IStatusBarService.Stub.Proxy
,因此通过私有字段mBar
获得IStatusBar
(确实实现了toggleRecentApps()
)似乎不是一种获得它的工作方法。
编辑2 :看到StatusBarManagerInternal.java是一个包含void toggleRecentApps()
的接口,我试图找到其实现,该StatusBarManagerService
在StatusBarManagerService
找到:
private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() { ... }
因此,它是StatusManagerService中的一个匿名类。 > :(。
但是,我还发现:
/**
* Construct the service, add the status bar view to the window manager
*/
public StatusBarManagerService(Context context, WindowManagerService windowManager) {
mContext = context;
mWindowManager = windowManager;
LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
}
因此,它显然在LocalServices
注册了它,而LocalServices
又在ArrayMap
对其进行了ArrayMap
:
private static final ArrayMap<Class<?>, Object> sLocalServiceObjects =
new ArrayMap<Class<?>, Object>();
因此,我尝试访问它:
try {
Field services = Class.forName("com.android.server.LocalServices")
.getDeclaredField("sLocalServiceObjects");
services.setAccessible(true);
ArrayMap<Class<?>, Object> serviceMap = (ArrayMap<Class<?>, Object>) services.get(null);
Set<Map.Entry<Class<?>, Object>> serviceSet = serviceMap.entrySet();
for (Map.Entry<Class<?>, Object> serviceEntry : serviceSet) {
if (serviceEntry.getKey().isInterface()) {
if ("com.android.server.statusbar.StatusBarManagerInternal"
.equals(serviceEntry.getKey().getName())) {
Object statusBarInternalObject = serviceEntry.getValue();
Class statusBarInternalClass = serviceEntry.getKey();
Method openRecents = statusBarInternalClass.getMethod("toggleRecentApps");
openRecents.setAccessible(true);
openRecents.invoke(statusBarInternalObject);
return;
}
}
}
} catch (Exception e) {
handleError(e);
}
然而:
/**
* This class is used in a similar way as ServiceManager, except the services registered here
* are not Binder objects and are only available in the same process.
*
* Once all services are converted to the SystemService interface, this class can be absorbed
* into SystemServiceManager.
*
* {@hide}
*/
las,我必须在SystemUI进程中(或看来)才能访问它。 (实际上, ArrayMap
为空,使我的尝试无用。)
任何有关如何从此处进行的指导将不胜感激。
创建从AccessibilityService
扩展的服务:
class ExampleAccessService:AccessibilityService() {
override fun onInterrupt() {
}
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
}
fun doAction(){
performGlobalAction(GLOBAL_ACTION_RECENTS)
// performGlobalAction(GLOBAL_ACTION_BACK)
// performGlobalAction(GLOBAL_ACTION_HOME)
// performGlobalAction(GLOBAL_ACTION_NOTIFICATIONS)
// performGlobalAction(GLOBAL_ACTION_POWER_DIALOG)
// performGlobalAction(GLOBAL_ACTION_QUICK_SETTINGS)
// performGlobalAction(GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN)
}
}
在需要操作的地方调用doAction()
添加到Manifest
:
<application
...
<service
android:name=".ExampleAccessService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:label="Name of servise" // it will be viewed in Settings->Accessibility->Services
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config"/>
</service>
...
</application>
accessibility_service_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="false"
android:description="your description"
android:notificationTimeout="100"
android:packageNames="your app package, ex: ex: com.example.android"
android:settingsActivity="your settings activity ex: com.example.android.MainActivity" />
有关更多信息, 请参见https://developer.android.com/guide/topics/ui/accessibility/services.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.