版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/qq_30552095/article/details/87932081

最近有一个需求,

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

预期:音乐停止。

于是去看看这个按钮的点击事件,本来以为这就是一个简单的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) {

ArrayList eventHandlers = 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

ArrayList tasks = 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);

}

————————————————

版权声明:本文为CSDN博主「Shawn」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_30552095/article/details/87932081

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐