我正在尝试在Android中打开Overview/Recents屏幕.从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);
}
Run Code Online (Sandbox Code Playgroud)
然而,toggleRecentApps()就是在IStatusBarService不再因为牛轧糖,并且它会导致NoSuchMethodException.
是否有其他方法(不包括AccessibilityService)可用于打开Overview/Obnts屏幕?
编辑:实现IStatusBarService的类似乎是StatusBarManagerService.但是,调用statusBarObject.getClass().getCanonicalName()返回com.android.internal.statusbar.IStatusBarService.Stub.Proxy,因此通过私有字段获取IStatusBar(确实实现toggleRecentApps())mBar似乎不是一种工作方式来获取它.
编辑2:看到StatusBarManagerInternal.java是一个包含的接口void toggleRecentApps(),我试图找到它的实现,我发现StatusBarManagerService:
private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() { ... }
Run Code Online (Sandbox Code Playgroud)
所以它是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);
}
Run Code Online (Sandbox Code Playgroud)
因此它显然将其注册,然后在以下LocalServices内容中管理它ArrayMap:
private static final ArrayMap<Class<?>, Object> sLocalServiceObjects =
new ArrayMap<Class<?>, Object>();
Run Code Online (Sandbox Code Playgroud)
因此,我试图访问它:
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);
}
Run Code Online (Sandbox Code Playgroud)
然而:
/**
* 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}
*/
Run Code Online (Sandbox Code Playgroud)
唉,我必须在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)
}
}
Run Code Online (Sandbox Code Playgroud)
致电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>
Run Code Online (Sandbox Code Playgroud)
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" />
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅https://developer.android.com/guide/topics/ui/accessibility/services.html
| 归档时间: |
|
| 查看次数: |
773 次 |
| 最近记录: |