`

在任务栏中清除掉播放器的进程,状态栏仍有音乐播放器状态,且音乐仍在后台播放

阅读更多
在任务栏中清除掉播放器的进程,状态栏仍有音乐播放器状态,且音乐仍在后台播放

1.先从UI切入问题分析,使用Monitor—Hierarchy View找到清除任务X按钮对应的id为r.id.dismiss_task,并且属于SystemUI

2.到SystemUI定位到包含dismiss_task的是TaskViewHeader.java,该按钮对应的onClick事件为:
TaskView tv = Utilities.findParent(this, TaskView.class);
            tv.dismissTask();

            // Keep track of deletions by the dismiss button
            MetricsLogger.histogram(getContext(), "overview_task_dismissed_source",
                    Constants.Metrics.DismissSourceHeaderButton);


3.查看TaskView.java中的dismissTask
void dismissTask() {
        // Animate out the view and call the callback
        final TaskView tv = this;
        DismissTaskViewEvent dismissEvent = new DismissTaskViewEvent(tv);
        dismissEvent.addPostAnimationCallback(new Runnable() {
            @Override
            public void run() {
                EventBus.getDefault().send(new TaskViewDismissedEvent(mTask, tv,
                        new AnimationProps(TaskStackView.DEFAULT_SYNC_STACK_DURATION,
                                Interpolators.FAST_OUT_SLOW_IN)));
            }
        });
        EventBus.getDefault().send(dismissEvent);
    }

这里EventBus send一个DismissTaskViewEvent,处理完成会回调再发生一个TaskViewDismissedEvent

5.定位到处理DismissTaskViewEvent是在TaskStackView.java
    public final void onBusEvent(DismissTaskViewEvent event) {
        // For visible children, defer removing the task until after the animation
        mAnimationHelper.startDeleteTaskAnimation(
                event.taskView, useGridLayout(), event.getAnimationTrigger());
    }


处理TaskViewDismissedEvent
public final void onBusEvent(TaskViewDismissedEvent event) {
        // Announce for accessibility
        announceForAccessibility(getContext().getString(
                R.string.accessibility_recents_item_dismissed, event.task.title));

        if (useGridLayout() && event.animation != null) {
            event.animation.setListener(new AnimatorListenerAdapter() {
                public void onAnimationEnd(Animator animator) {
                    if (mTaskViewFocusFrame != null) {
                        // Resize the grid layout task view focus frame
                        mTaskViewFocusFrame.resize();
                    }
                }
            });
        }

        // Remove the task from the stack
        mStack.removeTask(event.task, event.animation, false /* fromDockGesture */);
        EventBus.getDefault().send(new DeleteTaskDataEvent(event.task));
        if (mStack.getTaskCount() > 0 && Recents.getConfiguration().isLowRamDevice) {
            EventBus.getDefault().send(new ShowStackActionButtonEvent(false /* translate */));
        }

        MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_DISMISS,
                event.task.key.getComponent().toString());
    }


6.接着DeleteTaskDataEvent在RecentsActivity.java处理

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);
    }


7.SystemServicesProxy.java中removeTask
 /** Removes the task */
    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来删除任务

8.通过ActivityManager.java其对应的是ActivityManagerService.java
    @Override
    public boolean removeTask(int taskId) {
        enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS, "removeTask()");
        synchronized (this) {
            final long ident = Binder.clearCallingIdentity();
            try {
                return mStackSupervisor.removeTaskByIdLocked(taskId, true, REMOVE_FROM_RECENTS);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }


9.ActivityStackSupervisor.java
    boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents,
            boolean pauseImmediately) {
        final TaskRecord tr = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
                INVALID_STACK_ID);
        if (tr != null) {
            tr.removeTaskActivitiesLocked(pauseImmediately);
            cleanUpRemovedTaskLocked(tr, killProcess, removeFromRecents);
            if (tr.isPersistable) {
                mService.notifyTaskPersisterLocked(null, true);
            }
            return true;
        }
        Slog.w(TAG, "Request to remove task ignored for non-existent task " + taskId);
        return false;
    }


 void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess, boolean removeFromRecents) {
        if (removeFromRecents) {
            mRecentTasks.remove(tr);
            tr.removedFromRecents();
        }
        ComponentName component = tr.getBaseIntent().getComponent();
        if (component == null) {
            Slog.w(TAG, "No component for base intent of task: " + tr);
            return;
        }

        // Find any running services associated with this app and stop if needed.
        mService.mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent()));

        if (!killProcess) {
            return;
        }

        // Determine if the process(es) for this task should be killed.
        final String pkg = component.getPackageName();
        ArrayList<ProcessRecord> procsToKill = new ArrayList<>();
        ArrayMap<String, SparseArray<ProcessRecord>> pmap = mService.mProcessNames.getMap();
        for (int i = 0; i < pmap.size(); i++) {

            SparseArray<ProcessRecord> uids = pmap.valueAt(i);
            for (int j = 0; j < uids.size(); j++) {
                ProcessRecord proc = uids.valueAt(j);
                if (proc.userId != tr.userId) {
                    // Don't kill process for a different user.
                    continue;
                }
                if (proc == mService.mHomeProcess) {
                    // Don't kill the home process along with tasks from the same package.
                    continue;
                }
                if (!proc.pkgList.containsKey(pkg)) {
                    // Don't kill process that is not associated with this task.
                    continue;
                }

                for (int k = 0; k < proc.activities.size(); k++) {
                    TaskRecord otherTask = proc.activities.get(k).getTask();
                    if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
                        // Don't kill process(es) that has an activity in a different task that is
                        // also in recents.
                        return;
                    }
                }

                if (proc.foregroundServices) {
                    // Don't kill process(es) with foreground service.
                    return;
                }

                // Add process to kill list.
                procsToKill.add(proc);
            }
        }

        // Kill the running processes.
        for (int i = 0; i < procsToKill.size(); i++) {
            ProcessRecord pr = procsToKill.get(i);
            if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                    && pr.curReceivers.isEmpty()) {
                pr.kill("remove task", true);
            } else {
                // We delay killing processes that are not in the background or running a receiver.
                pr.waitingToKill = "remove task";
            }
        }
    }

通过上述定位会发现music app包含了前台的服务foregroundServices,所以其process不会被kill掉。这个是google原生设计的。
那解决该问题,我们可以增加判断如果是removeFromRecents 为true时将其包含foregroundServices也kill掉
分享到:
评论

相关推荐

    Android 11 修改最近任务栏无法kill正在播放的音乐.patch

    Android 11 修改最近任务栏无法kill正在播放的音乐

    结束一个托盘程序进程后,但是windows任务栏托盘区的图标还在,鼠标移上去后图标就消失了 这是为什么 怎么解决.zip

    在Windows操作系统中,托盘区域(也称为系统托盘或通知区域)位于任务栏的右侧,通常用于显示各种应用程序的图标,例如网络连接、音量控制等。这些图标代表正在运行的后台进程,用户可以通过它们快速访问或管理相关...

    不出现在任务栏上的程序.rar

    标题 "不出现在任务栏上的程序.rar" 暗示了我们关注的是计算机操作系统中的一个特定现象,即某些程序在运行时不会在任务栏上显示图标或任务条目。这种情况可能是由于程序的设置、系统配置或者操作系统的问题导致的。...

    带有声音播放的任务栏图标闪烁

    在Windows操作系统中,任务栏图标闪烁通常是一种通知机制,用于提醒用户有未读的消息或正在进行的后台活动。这种现象在“带有声音播放的任务栏图标闪烁”问题中,可能与多种因素有关,包括软件冲突、系统设置、驱动...

    任务栏修复各种BUG

    在Windows操作系统中,任务栏是用户界面的重要组成部分,它提供了启动和切换应用程序、查看系统状态以及访问关键功能的快捷方式。然而,有时任务栏可能会遇到各种问题,如无响应、消失或者频繁崩溃,这给用户的日常...

    xp任务栏 错误彻底修复工具

    在Windows XP操作系统中,任务栏是用户日常操作中不可或缺的一部分,它承载了启动应用程序、切换窗口、查看系统状态等功能。然而,由于系统更新、软件冲突或病毒感染,任务栏可能会出现各种问题,如任务栏消失、无法...

    任务栏不显示已打开窗口的修复脚本

    4. **重置设置**:脚本还可能尝试重置与任务栏相关的用户配置,比如恢复默认的任务栏位置、大小和状态,或者清除可能导致问题的自定义设置。 5. **更新驱动和补丁**:虽然Windows XP已经停止了官方支持,但可能仍有...

    任务栏修复

    在Windows操作系统中,任务栏是用户界面的重要组成部分,它提供了快速访问常用应用程序、切换活动窗口、查看系统状态以及执行各种操作的功能。然而,有时任务栏可能会出现故障,比如不显示Internet Explorer图标,...

    修复任务栏

    4. **自定义设置丢失**:如果你发现任务栏的布局、隐藏状态或功能异常,可以尝试在“任务栏设置”中恢复默认设置。如果脚本能够修复,那么它可能涉及重置这些设置。 5. **系统服务问题**:某些关键服务如“Shell ...

    Windows xp系统任务管理器所有进程介绍及病毒查杀

    在Windows XP系统中,任务管理器是一个至关重要的工具,它提供了对系统运行状态的全面洞察,包括当前运行的进程、CPU使用率、内存占用、网络活动等信息。本篇文章将深入探讨任务管理器中的所有进程,并讲解如何利用...

    在Linux系统中查看进程及杀死僵尸进程的方法.docx

    在Linux操作系统中,进程管理是一项重要的任务,它涉及到系统性能优化、故障排查等多个方面。本文将详细介绍如何使用`ps`命令来查看系统中的进程以及如何处理僵尸进程。 #### 二、ps命令详解 `ps`命令是最基本也是...

    win10系统右击任务栏时一直转圈、卡死的修复工具

    标题中的“win10系统右击任务栏时一直转圈、卡死的修复工具”指出的问题,是Windows 10用户在操作系统中遇到的一个常见故障。通常,当用户尝试右键点击任务栏时,系统应该弹出一个菜单,但在这个情况下,任务栏可能...

    资源管理器中的各进程解析

    在Windows系统中,资源管理器通常指的是Explorer.exe,它负责桌面、任务栏和文件系统的管理。然而,我们今天讨论的重点是"资源管理器中的各进程",这涉及到计算机运行时后台的各个程序和服务。 进程是操作系统中...

    清除系统托盘无效的图标源码(delphi) 非鼠标移动模拟方法

    在Windows操作系统中,系统托盘区域(也称为通知区域)是位于任务栏右侧的一个区域,通常包含各种程序的图标。这些图标可能是后台运行的应用程序、服务或系统工具的代表。然而,随着时间的推移,由于程序异常退出或...

    TaskbarManager.zip

    在Windows 7及更高版本中,任务栏引入了一项创新特性——任务栏进度条,这个功能为用户提供了一个直观的方式,来了解后台进程的执行进度,特别是对于那些没有独立进度窗口的应用程序来说更为实用。"TaskbarManager....

    windows任务管理器无闪屏刷新

    在Windows操作系统中,任务管理器是一项至关重要的工具,它允许用户监控系统性能、查看正在运行的应用程序、进程和服务,以及管理启动项。标题"windows任务管理器无闪屏刷新"指出,我们将探讨如何实现类似任务管理器...

    清除XP系统托盘图标

    在Windows XP操作系统中,系统托盘(又称为通知区域)位于任务栏的右侧,通常显示各种应用程序的小图标,包括运行中的程序、服务以及系统状态指示器。这些图标为用户提供了一个快速访问和管理程序的方式,但有时可能...

    [原创]自动清理托盘图标

    3. 图标:在本场景中,图标是指那些驻留在托盘区的应用程序小图标,它们代表了正在运行的后台进程或服务。 【详细知识点】: 1. **托盘区的作用**:托盘区是操作系统提供的一种界面元素,允许程序在后台运行的同时...

    Win2000进程

    在Windows 2000操作系统中,任务管理器是一个至关重要的工具,它允许用户查看当前系统中运行的程序和进程,以及系统资源的使用情况。然而,对于许多用户来说,理解这些进程的具体功能可能并不直观,尤其是那些由系统...

    vc++ 应用源码包_5

    内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...

Global site tag (gtag.js) - Google Analytics