android多任务按键点击事件,Android8.1 SystemUI中Recents(多任务),"全部清除"按钮点击事件简单梳理...

最近有一个需求,

现象:播放音乐时,点击多任务中的“全部清除”按钮,音乐未停止;

预期:音乐停止。

于是去看看这个按钮的点击事件,本来以为这就是一个简单的onclick事件,可是并没有这么简单,首先找到这个按钮:

com.android.systemui.recents.views.RecentsView中的mStackActionButton,这个就是按钮的对象了,可是这个按钮并没有找到onclick事件,所以猜测是不是在onTouchEvent中处理的

com.android.systemui.recents.views.RecentsView -> onTouchEvent()

@Override

public boolean onTouchEvent(MotionEvent ev) {

return mTouchHandler.onTouchEvent(ev);

}

继续跟,RecentsViewTouchHandler这个类很像是专门处理recentsView的touch事件的

com.android.systemui.recents.views.RecentsViewTouchHandler ->onTouchEvent();

public boolean onTouchEvent(MotionEvent ev) {

handleTouchEvent(ev);

if (ev.getAction() == MotionEvent.ACTION_UP && mRv.getStack().getStackTaskCount() == 0) {

EventBus.getDefault().send(new HideRecentsEvent(false, true));

}

return true;

}

在com.android.systemui.recents.views.RecentsViewTouchHandler -> handleTouchEvent(ev)

中的ACTION_UP事件中找到了

case MotionEvent.ACTION_UP:

case MotionEvent.ACTION_CANCEL: {

if (mRv.getStackActionButton().isPressed() && isWithinStackActionButton(evX, evY)) {

EventBus.getDefault().send(new DismissAllTaskViewsEvent());

consumed = true;

}

......

}

这里就是处理点击事件的地方了,继续跟到EventBus中

com.android.systemui.recents.events.EventBus -> send();

public void send(Event event) {

......

queueEvent(event);

}

com.android.systemui.recents.events.EventBus -> queueEvent();

private void queueEvent(final Event event) {

ArrayListeventHandlers = mEventTypeMap.get(event.getClass());

if (eventHandlers == null) {

// This is just an optimization to return early if there are no handlers. However, we

// should still ensure that we call pre/post dispatch callbacks so that AnimatedEvents

// are still cleaned up correctly if a listener has not been registered to handle them

event.onPreDispatch();

event.onPostDispatch();

return;

}

// Prepare this event

boolean hasPostedEvent = false;

event.onPreDispatch();

// We need to clone the list in case a subscriber unregisters itself during traversal

// TODO: Investigate whether we can skip the object creation here

eventHandlers = (ArrayList) eventHandlers.clone();

int eventHandlerCount = eventHandlers.size();

for (int i = 0; i < eventHandlerCount; i++) {

final EventHandler eventHandler = eventHandlers.get(i);

if (eventHandler.subscriber.getReference() != null) {

if (event.requiresPost) {

mHandler.post(new Runnable() {

@Override

public void run() {

processEvent(eventHandler, event);

}

});

hasPostedEvent = true;

} else {

processEvent(eventHandler, event);

}

}

}

// Clean up after this event, deferring until all subscribers have been called

if (hasPostedEvent) {

mHandler.post(new Runnable() {

@Override

public void run() {

event.onPostDispatch();

}

});

} else {

event.onPostDispatch();

}

}

通过打断点发现走的是 processEvent(eventHandler, event);

com.android.systemui.recents.events.EventBus -> processEvent();

private void processEvent(final EventHandler eventHandler, final Event event) {

// Skip if the event was already cancelled

if (event.cancelled) {

if (event.trace || DEBUG_TRACE_ALL) {

logWithPid("Event dispatch cancelled");

}

return;

}

try {

if (event.trace || DEBUG_TRACE_ALL) {

logWithPid(" -> " + eventHandler.toString());

}

Object sub = eventHandler.subscriber.getReference();

if (sub != null) {

long t1 = 0;

if (DEBUG_TRACE_ALL) {

t1 = SystemClock.currentTimeMicro();

}

eventHandler.method.invoke(sub, event);

if (DEBUG_TRACE_ALL) {

long duration = (SystemClock.currentTimeMicro() - t1);

mCallDurationMicros += duration;

mCallCount++;

logWithPid(eventHandler.method.toString() + " duration: " + duration +

" microseconds, avg: " + (mCallDurationMicros / mCallCount));

}

} else {

Log.e(TAG, "Failed to deliver event to null subscriber");

}

} catch (IllegalAccessException e) {

Log.e(TAG, "Failed to invoke method", e.getCause());

} catch (InvocationTargetException e) {

throw new RuntimeException(e.getCause());

}

}

这里调用的反射,仍然是通过断点,发现走的是eventHandler.method.invoke(sub, event);

sub是com.android.systemui.recents.views.TaskStackView

event是com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent

在TaskStackView中找到这个方法

com.android.systemui.recents.views.TaskStackView -> onBusEvent();

public final void onBusEvent(final DismissAllTaskViewsEvent event) {

// Keep track of the tasks which will have their data removed

ArrayListtasks = new ArrayList<>(mStack.getStackTasks());

mAnimationHelper.startDeleteAllTasksAnimation(

getTaskViews(), useGridLayout(), event.getAnimationTrigger());

event.addPostAnimationCallback(new Runnable() {

@Override

public void run() {

// Announce for accessibility

announceForAccessibility(getContext().getString(

R.string.accessibility_recents_all_items_dismissed));

// Remove all tasks and delete the task data for all tasks

mStack.removeAllTasks(true /* notifyStackChanges */);

for (int i = tasks.size() - 1; i >= 0; i--) {

EventBus.getDefault().send(new DeleteTaskDataEvent(tasks.get(i)));

}

MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_DISMISS_ALL);

}

});

}

找到关键的一句代码EventBus.getDefault().send(new DeleteTaskDataEvent(tasks.get(i)));

这里又走到了EventBus中,同样的在

com.android.systemui.recents.events.EventBus -> processEvent();

这个方法中的eventHandler.method.invoke(sub, event);

sub是com.android.systemui.recents.RecentsActivity

event是com.android.systemui.recents.events.ui.DeleteTaskDataEvent;

找到这个方法

com.android.systemui.recents.RecentsActivity -> onBusEvent();

public final void onBusEvent(DeleteTaskDataEvent event) {

// Remove any stored data from the loader

RecentsTaskLoader loader = Recents.getTaskLoader();

loader.deleteTaskData(event.task, false);

// Remove the task from activity manager

SystemServicesProxy ssp = Recents.getSystemServices();

ssp.removeTask(event.task.key.id);

}

跟到SystemServicesProxy中看看

com.android.systemui.recents.misc.SystemServicesProxy -> removeTask();

public void removeTask(final int taskId) {

if (mAm == null) return;

if (RecentsDebugFlags.Static.EnableMockTasks) return;

// Remove the task.

mUiOffloadThread.submit(() -> {

mAm.removeTask(taskId);

});

}

这个就比较明确了,就是调用了ActivityManager中的removeTask方法。

由此可见,recents中的task都是放在了ActivityManger中的。

--------------------------------------------------------------------分割线-------------------------------------------------------------------

回到我的需求,需要在移除task的时候,将音乐停止,那就在这个地方将这个package停止

增加方法

com.android.systemui.recents.misc.SystemServicesProxy

public void removeTask(final Task.TaskKey key) {

removeTask(key.id);

if (mAm == null || key.getComponent() == null || TextUtils.isEmpty(key.getComponent().getPackageName())) {

return;

}

mAm.forceStopPackage(key.getComponent().getPackageName());

}

在com.android.systemui.recents.RecentsActivity -> onBusEvent();中调用新增的方法

public final void onBusEvent(DeleteTaskDataEvent event) {

// Remove any stored data from the loader

RecentsTaskLoader loader = Recents.getTaskLoader();

loader.deleteTaskData(event.task, false);

// Remove the task from activity manager

SystemServicesProxy ssp = Recents.getSystemServices();

// ssp.removeTask(event.task.key.id);

ssp.removeTask(event.task.key);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android设备,"recents"通常指的是最近活动应用程序的显示列表,可以通过长按"返回"按钮或从屏幕底部向上滑动来访问它。 如果您清除"recents"列表所有的应用程序,即使没有音乐播放器应用程序在列表显示,音乐可能仍然会在背景继续播放。 这种情况可能是由于以下几种原因引起的: 1. 后台播放:某些音乐应用程序具有后台播放功能,这意味着即使您不再使用它们,它们仍然可以在后台播放音乐。您可以通过从通知栏找到相关的音乐播放器通知,然后停止或关闭音乐播放。 2. 音频焦点:Android系统具有管理音频焦点的功能,这意味着即使您关闭或清除了所有的应用程序,其他应用程序也可能继续请求或保持音频焦点,并继续播放音乐。您可以通过在设置查找音频相关的选项来调整或关闭音频焦点。 3. 清除全部应用程序:如果您使用了"任务管理器"或类似的应用程序来清除所有的应用程序,这些应用程序可能会恢复运行并继续播放音乐。您可以尝试检查是否有此类应用程序在运行,并在设置或其它应用程序停止或禁用它们。 总的来说,如果您想完全停止播放音乐,可以尝试以下步骤: - 在"recents"列表找到相关的音乐应用程序,然后从列表向上滑动或左右滑动以关闭它。 - 从通知栏找到音乐播放器通知,并停止或关闭音乐播放。 - 在设置找到音频相关选项,并适当地调整或关闭它们。 - 检查是否有任务管理器类应用程序在后台运行,如果有,停止或禁用它们。 希望以上解答对您有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值