gpt4 book ai didi

Android:以编程方式在 API 24+ 中打开概览/最近屏幕

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:22:23 24 4
gpt4 key购买 nike

我正在尝试在 Android 中打开概览/最近屏幕。来自 Android: Programmatically open "Recent Apps" dialog ,我可以使用以下代码:

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()no longer in IStatusBarService自 Nougat 以来,它会导致 NoSuchMethodException。

是否有任何其他方式(不包括 AccessibilityService)可用于打开概览/最近屏幕?


编辑:实现 IStatusBarService 的类似乎是 StatusBarManagerService .然而,调用 statusBarObject.getClass().getCanonicalName() 返回 com.android.internal.statusbar.IStatusBarService.Stub.Proxy,所以得到一个 IStatusBar(确实通过私有(private)字段 mBar 实现了 toggleRecentApps())似乎不是获得它的有效方法。


编辑 2:看到 StatusBarManagerInternal.java 是一个包含 void toggleRecentApps() 的接口(interface),我试图找到它的实现,我在 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 中注册了它,而后者又在 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}
*/

唉,我必须在 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()

添加到 list :

<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

关于Android:以编程方式在 API 24+ 中打开概览/最近屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41492889/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com