AndroidのOverview/Recents画面を開こうとしています。 Android: Programmatically open "Recent Apps" dialogから、私は次のコードを使用することができます:Android:プログラムで開いているAPIの概要/ Recents画面24+
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であり、それはないNoSuchMethodExceptionが発生します。
Overview/Recents画面を開くために使用できる他の方法(AccessibilityServiceを除く)はありますか?
EDIT:IStatusBarServiceはStatusBarManagerServiceであるように思わ実装するクラスです。ただし、statusBarObject.getClass().getCanonicalName()
を呼び出すとcom.android.internal.statusbar.IStatusBarService.Stub.Proxy
が返されるため、IStatusBar
(toggleRecentApps()
が実装されています)をプライベートフィールドmBar
で取得することは効果的ではありません。
EDIT 2:
private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() { ... }
だから、匿名クラスの中にあります:StatusBarManagerInternal.javaはvoid toggleRecentApps()
が含まれているインターフェースであることを見て、私は私がStatusBarManagerService
で見つかったその実装を、見つけることを試みました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);
}
だから、明らかに順番にArrayMap
でそれを管理する、LocalServices
に登録する:
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
は空であり、私の試行は役に立たない。)
ここから進める方法についてのガイダンスはありがたい。
のAPIが変更することができますリフレクション経由で呼び出されるメソッドの問題です。 – rekire
デバイスメーカやカスタムROM開発者は、Androidの内部構造を適切に修正することができますので、その方法は必ずしも任意のデバイスで利用できるわけではありません。 – CommonsWare
@CommonsWareは真だが、少なくとも私は在庫のAndroidで動作する必要があります。 –