- 浏览: 1055584 次
- 性别:
- 来自: 南昌
文章分类
- 全部博客 (276)
- 生活 (1)
- 代码之美 (22)
- Media (7)
- Android Widget (3)
- Android Intent (1)
- Android Activity (4)
- UI event handle--UI事件处理机制 (2)
- Java基础知识 (12)
- android Databases (5)
- Android 系统知识 (70)
- 平常遇到的问题与解决方法 (38)
- Android TextView/EditView (2)
- Thinking Java (1)
- android webkit (6)
- JSON (1)
- XML (4)
- HTTP (1)
- Google Weather API (1)
- android 2.3 NFC (10)
- android app (20)
- android framework (7)
- C++ (2)
- android System (5)
- Pthread (1)
- Wifi (8)
- Unix/Linux C (8)
- Android 4.0 (1)
- Mail (1)
- Smack 源码学习 (4)
- iOS (4)
- Android (1)
- git (1)
- Gallery3d (2)
- React-Natice (1)
最新评论
-
dd18349182956:
你是用的smack哪个版本?我用的smack4.1.3和sma ...
关于socket长连接的心跳包 -
xukaiyin:
全英文
getApplicationContext()与this,getBaseContext() -
裂风矢:
...
<category android:name="android.intent.category.DEFAULT" /> 惹的祸 -
xanthodont:
mark一下
XMPP——Smack -
Evilover3:
mark一下,学习了
XMPP——Smack
在任务栏中清除掉播放器的进程,状态栏仍有音乐播放器状态,且音乐仍在后台播放
1.先从UI切入问题分析,使用Monitor—Hierarchy View找到清除任务X按钮对应的id为r.id.dismiss_task,并且属于SystemUI
2.到SystemUI定位到包含dismiss_task的是TaskViewHeader.java,该按钮对应的onClick事件为:
3.查看TaskView.java中的dismissTask
这里EventBus send一个DismissTaskViewEvent,处理完成会回调再发生一个TaskViewDismissedEvent
5.定位到处理DismissTaskViewEvent是在TaskStackView.java
处理TaskViewDismissedEvent
6.接着DeleteTaskDataEvent在RecentsActivity.java处理
7.SystemServicesProxy.java中removeTask
这里就是关键代码了,通过调用ActivityManager的removeTask来删除任务
8.通过ActivityManager.java其对应的是ActivityManagerService.java
9.ActivityStackSupervisor.java
通过上述定位会发现music app包含了前台的服务foregroundServices,所以其process不会被kill掉。这个是google原生设计的。
那解决该问题,我们可以增加判断如果是removeFromRecents 为true时将其包含foregroundServices也kill掉
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 Webview加载www.youtube.com的问题
2019-04-25 10:36 955Android Webview加载www.youtube.co ... -
EditText键盘删除字符的原理
2018-10-29 19:21 1197转https://blog.csdn.net/tankai19 ... -
Background execution not allowed
2018-10-22 19:02 326911-05 10:08:18.058 673 736 ... -
failed to set system property
2018-10-17 09:21 4155在App的mk文件设置了LOCAL_CERTIFICATE : ... -
CtsDeqpTestCases fail
2018-07-27 09:44 2908Suite / Plan:VTS / cts-on-gsi ... -
在DocumentUI中的Recent(最近)列表无法显示图片的缩略图
2018-06-12 18:23 905今天客户提了一个bug说在短信添加附件,界面无法显示缩略图。接 ... -
junit.framework.AssertionFailedError: Failed to get achievable frame rates for O
2018-05-25 15:41 2245之前对于CTS测试的失败case接触不多,组长突然转了这样一个 ... -
Android 模拟各种事件的方法
2018-05-17 16:30 1487有时候没有对应的硬件设备,那我们就得通过某种方式来模拟。比如模 ... -
Android Email 新建邮件时一直显示“waiting for sync”
2018-02-28 15:48 960当用户在Setting中清除了Email的data,再返回到E ... -
javax.net.ssl.SSLHandshakeException: Unacceptable certificate: CN=GeoTrust SSL C
2018-01-30 16:48 3633最近从Android N升级到Android O,发现163的 ... -
Email中附件名称中包含中文字符显示乱码
2017-11-28 17:09 1572Email中附件名称中包含中文字符显示乱码是因为附件虽包含了中 ... -
不能再通过createPackageContext来访问另外一个应用的资源(Sharepreference)
2017-11-14 17:22 1432以前我们可以通过createPackageContext来访问 ... -
当Email未设置账户时,通过ACTION_SENDTO启动会报ActivityNotFoundException
2017-09-27 18:15 503当Email未设置账户时,通过ACTION_SENDTO启动会 ... -
java.lang.SecurityException: Permission Denial: reading...requires android.permi
2016-05-12 11:12 2294一直在忙于Gallery,最近遇到了这样的bug,在Setti ... -
android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a read
2015-11-27 14:50 2909android.database.sqlite.SQLiteR ... -
AsyncTask
2015-08-21 17:43 382转自http://blog.csdn.net/hitlion2 ... -
解决IllegalStateException: Can not perform this action after onSaveInstanceState
2015-08-07 18:07 1047转自http://www.cnblogs.com/zgz345 ... -
Android setTag方法的key问题
2015-08-03 19:22 1027转自http://www.cnblogs.com/whitew ... -
ActivityGroup对子Activity的管理
2013-06-27 17:41 2069转自http://eyeandroid.diandian.co ... -
listview在activitygroup切换后无法点击的问题
2013-05-14 10:14 1466转自:http://blog.csdn.net/daguaio ...
相关推荐
Android 11 修改最近任务栏无法kill正在播放的音乐
内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...
内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...
内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...
内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...
内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...
内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...
4.1 实例1:在工具栏中添加静态标识符 64 4.2 实例2:在工具栏中添加动态标识符 71 4.3 实例3:只启动一个实例 75 4.4 实例4:创建对话框/MDI混合式 应用程序 77 4.5 实例5:在系统托盘中添加图标 79 4.6 实例6: ...
4.1 实例1:在工具栏中添加静态标识符 64 4.2 实例2:在工具栏中添加动态标识符 71 4.3 实例3:只启动一个实例 75 4.4 实例4:创建对话框/MDI混合式 应用程序 77 4.5 实例5:在系统托盘中添加图标 79 4.6 实例6: ...
4.1 实例1:在工具栏中添加静态标识符 64 4.2 实例2:在工具栏中添加动态标识符 71 4.3 实例3:只启动一个实例 75 4.4 实例4:创建对话框/MDI混合式 应用程序 77 4.5 实例5:在系统托盘中添加图标 79 4.6 实例6: ...
4.2 实例2:在工具栏中添加动态标识符 71 4.3 实例3:只启动一个实例 75 4.4 实例4:创建对话框/MDI混合式 应用程序 77 4.5 实例5:在系统托盘中添加图标 79 4.6 实例6: 主菜单状态栏中的标记 81 第5章 菜单...
4.1 实例1:在工具栏中添加静态标识符 64 4.2 实例2:在工具栏中添加动态标识符 71 4.3 实例3:只启动一个实例 75 4.4 实例4:创建对话框/MDI混合式 应用程序 77 4.5 实例5:在系统托盘中添加图标 79 4.6 实例6: ...
复件 状态栏控件.ec 复制目录.ec 复制目录模块.ec 复制目录模块 1.ec 复制目录模块copy_dir.ec 外挂作坊1.4.ec 外挂作坊1.40909.ec 外挂作坊1.5-第六 版.ec 外挂作坊1.5版.ec 外挂作坊1.8.ec 外挂作坊1.85.ec 外挂...
� A ndroid 在设计初期就考虑了与现其有业务的融合,改变以往从计算机为主改成从手机使用为导向。新 生应用如:G oogle 地图及其衍生应用、 GMail 、 GTalk 等。 � GPS 卫星导航功能,手机照相, MP3 ,蓝芽等均...
6.屏幕偷拍间谍:能够在后台每隔5分中进行屏幕偷拍,悄悄查看别人怎样使用我的电脑。 (九)系统工具 包括:1)系统维护工具;2)系统进程管理;3)系统垃圾清理:4)系统右键设置:5)系统配置程序等. 王牌超级工具...
三星伯爵W629升级成功: 共要分三步分别写入W629 AK22.bin w629_preload_aj04_0x5400000 Mento_gsm_AK19_R ev04 所有过程...在待机状态下输入147*12690*#进入工程模式,选择‘全部清除’进行主清除. OK!!
GetPrivateProfileSection 获取指定小节(在.ini文件中)所有项名和值的一个列表 GetPrivateProfileString 为初始化文件中指定的条目取得字串 GetProfileInt 取得win.ini初始化文件中指定条目的一个整数值 ...
件夹进行访问的进程、禁止的文件操作以及在某人尝试访问阻挡的项目时应 采取的操作。 这些"访问保护"功能在防范入侵时非常有效。在病毒发作时,管理员可以 阻止对感染病毒区域的访问,直到发布新的 DAT。 ...
你可以在压缩对话框中使用 "RAR 5.0" 选项或命令行中 使用 -ma 开关创建 RAR 5.0 压缩文件。 较老的软件,包括老版本的 WinRAR,不能解压 RAR 5.0 压缩文件,所以如果你计划把 一个压缩文件发送给其他人,则需要...
子程序 窗口禁止, 逻辑型, 公开, 在窗口中允许或禁止所有鼠标及键盘输入(成功返回真,失败返回假) .参数 窗口句柄, 整数型, , 欲禁止鼠标键盘输入的窗口或控件的句柄 .参数 是否禁止, 逻辑型, 可空, 默认为真:禁止 假...