android近期列表RecentsActivity的目录在/frameworks/base/packages/SystemUI/
frameworks的修改需要在fastboot模式下烧system.img文件。
首先,接受开机广播
处理它的Receiver类是BootReceiver。下面是Receiver的内容:
随后,在广播中开启了LoadAveragService服务。
SystemUiServier 服务也开启了
紧接着就是显示界面,主界面是RecentsActivity,首先onCreate(),onStart()。
在onCreate方法中发现布局文件是
接下来看一下布局文件
发现,基本都是自定义控件。
最下面的id = recents_no_apps,是列表中没有条目的时候才会显示。
查找会发现,这个id只有在RcentsPanelView中使用,接下来先看下:
定义一个View
如果有apps的时候,就VISIBLE,否则就是INVISIABLE。
上面noApps的值得来是根据mRecentTaskDescriptions,这是一个List
每一个app都保存成了一个TaskDescription。接下来看一下TaskDescription:
它主要的字段有intent:用于跳转到应用,
taskId,用于标识的id,比如删除,点击,跳转等使用。
以及描述,包名等,icon等。。。
接着来查看一下当有信息的时候显示的布局,RecentsAcitvity的大布局是自定义的,实现类是RecentsPanelView。
整个列表的大布局又放在了一个FrameLayout布局中,然后列表显示在一个自定义的布局中,实现类是RecentsVerticalScrollView。
这个布局之后还有一个LinearLayout
简单解释几个参数
android:fitsSystemWindows="true" 字面意思就是使用系统窗口。总之是对布局的一种处理。
clipToPadding就是说控件的绘制区域是否在padding里面的,true的情况下如果你设置了padding那么绘制的区域就往里 缩,
clipChildren是指子控件是否超过padding区域,这两个属性默认是true的,所以在设置了padding情况下,默认滚动是在 padding内部的,要达到上面的效果主要把这两个属性设置了false那么这样子控件就能画到padding的区域了。
初始化列表,应该是在RecentsPanelView中完成的,
初始化简单到这里,接下来看看操作过程中的的流程。
首先,开机的时候,启动SystemUIServices,然后在onCreate中实例化了Recents类
执行start(),然后执行closeRecents()方法。
开机后点击home键,会执行Recents类的preloadRecentTaskList方法。在里面启动了RecentsPreloadReceiver类。
销毁过程,首先是从内到外,SwipeHelper类中的onTouch方法对
MotionEvent.ACTION_CACEL进行匹配,方法实现如下:
前面绝大部分都是在得到能不能销毁的判断值dismissChild。如果可以销毁,就会执行
dismissChild(方法),如果滑动没有超过一定距离,就执行else中的内容。在上述方法中,基本实现的就是对动画的处理,如果显示动画效果,消除相应的view。
紧接着就是RecentsVerticalScrollView类中的onChildDismissed()方法。
首先先看addToRecycledViews(v);从字面意思就是将需要消除的view添加到recycle的view中。
一个简单的方法实现
然后就是mLinearLayout.removeView(v);在布局上移除相应的视图。
然后就是mCallback.handleSwipe(v);实际的实现在RecentsPanelView中。
首先获得TaskDescription,也就得到了某个条目的包括id,description,等等信息。
然后每一个item是一个RecentTaskDescription对象,然后将这个对象移除了。
紧接着调用RecentTaskLoader的remove方法。
然后就是将存放的list集合的相应index给remove掉。
其实真正滑动销毁应用生效的一句话就是am.removeTask(ad.presistentTaskId,ActivityManager.REMOVE_TASK_KILL_PROCESS);
上面的内容是关键,根据存储的taskid,kill掉相应的process。
当长按home键直到显示RecentsActivity的过程中,流程log如下:
首先走的是Recetns类中的preloadRecentTaskList()方法。
在这个方法中,发送了广播RecentsPreloadReceiver,
而且还调用了preloadFirstTask()方法来加载第一个Task。
下图是RecentsPreloadReceiver的内容
当我们短按home键的时候,会先走if再走,再走else if,当长按home的时候,只走if,只有在home关闭的时候,才会走else if
说明,短按home键,也走了一遍查询的流程,然后瞬间又关闭掉了。
在receiver中获得了RecentTaskLoader的实例后,调用了preloadRecentTaskList()方法,
在其中,用handler操纵了一个线程,线程中调用了loadTaskInBackground()方法,加载背景
下面就是loadTasksInBackground()方法
中间有个AsyncTask,用于加载初始化每个Task。doInbackground中用for循环来遍历Task。
For循环中有如下代码
每次加载一个task,都要调用createTaskDescription()方法
上面就是方法的内容。
接着会在BaseStatus类的toogleRecentActivity中调用Recents类的toogleRecents()方法。
然后就开始绘制界面,执行RecentsActivity类的oncreate方法
然后执行RecentVerticalScrollView类的setadapter,初始化列表。
然后执行onstart(),update(),.
当关闭这个界面的时候,会调用RecentPreloadReceiver中的RecentsActivity.CANCEL_PRELOAD_INTENT,
然后RecentTasksLoader.getInstance(context).cancelPreloadingRecentTasksList();Cancel掉这个tasklist。
然后调用RecentActivity的onDestroy()
在方法体中进行了receiver的解绑
下面是onReceive中的操作,设置其show(false);
大致就是这样
ActivityManager
参考连接:http://androidbin.iteye.com/blog/1594908 http://www.apihome.cn/api/android/android.app
MainActivity
package com.example.activitymanagerdemo;
import java.util.List;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
private Button button1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1 = (Button) findViewById(R.id.btn1);
button1.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn1:
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
// finish();
break;
default:
break;
}
}
}
TestActivity
package com.example.activitymanagerdemo;
import java.util.Arrays;
import java.util.List;
import android.R.integer;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class TestActivity extends Activity {
public ActivityManager am;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
Button button = (Button) findViewById(R.id.btn1);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
getOrigRunningList();
}
});
}
/**
* 需要添加权限android.permission.GET_TASKS
* 界面是从MainActivity跳转到当前的TestAtivity的。
* 如果,没有finish掉MainAcitity,获得的getClassName()和cn.getShortClassName();获得的是关于MainActivity的
* 如果跳转的时候finish()掉,说明TestActtivity底部就没有其他的Activity了,得到的就是关于TestActivity的结果
*/
private void getRunningTaskName() {
// 获取顶部的activity
ComponentName cn = am.getRunningTasks(1).get(0).topActivity;
// 获取底部的activity。
ComponentName cn1 = am.getRunningTasks(1).get(0).baseActivity;
// 将maxTasks设置成2,就是最多获得两个应用的task。
// get(x)中的值x,是获得应用的角标,最上面一层是0,依次往下是1、2、3...
// get(1),就是获得第二层的应用,比如说我现在正在看短信,忽然电话来了,call应用覆盖了短信,call在上面,此时call应用就是get(0),
// 短信mms就是get(1)。然后在决定获得短信的base还是top
ComponentName cn3 = am.getRunningTasks(2).get(1).baseActivity;
ComponentName cn4 = am.getRunningTasks(2).get(1).topActivity;
// 更具ComponentName获得需要的activity的名字
String topAtyName = cn.getClassName();
// 获得应用的包名
String topPkgName = cn.getPackageName();
// 获得“.MainActivity”形式的结果
String topScName = cn.getShortClassName();
System.out.println("topAtyName--->" + topAtyName);
System.out.println("topPkgName--->" + topPkgName);
System.out.println("topScName--->" + topScName);
}
/**
* 获取表示task的id,进行销毁操作
*/
private void getRunningtaskList() {
List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasks(1,
ActivityManager.RECENT_IGNORE_UNAVAILABLE);
ActivityManager.RecentTaskInfo rtInfo = recentTasks.get(0);
int persistentId = rtInfo.persistentId;
int id = rtInfo.id;
System.out.println("persistentId--->" + persistentId);
System.out.println("id--->" + id);
// 可以根据唯一的标识task id进行销毁应用
// am.removeTask(persistentId,
// ActivityManager.REMOVE_TASK_KILL_PROCESS);
}
/**
* 获得系统正在运行的进程
*/
private void getRuningProcessList() {
List<ActivityManager.RunningAppProcessInfo> appList1 = am
.getRunningAppProcesses();
for (RunningAppProcessInfo running : appList1) {
System.out.println("process--->" + running.processName);
System.out.println("pid--->" + running.pid);
// 所有已加载到进程中的包。大部分只有一个包名,和processName一致,个别的有两个包名
System.out
.println("pkgList--->" + Arrays.toString(running.pkgList));
System.out.println("uid--->" + running.uid);
}
}
/**
* 获得系统正在运行的service
*/
private void getRunningServiceList() {
List<ActivityManager.RunningServiceInfo> serviceList = am
.getRunningServices(1000);
for (RunningServiceInfo running : serviceList) {
System.out.println("--->" + running.service.getClassName());
System.out.println("--->" + running.service.getPackageName());
}
}
private void getOrigRunningList() {
List<ActivityManager.RecentTaskInfo> origList = am.getRecentTasks(100,
1);
for (RecentTaskInfo running : origList) {
System.out.println("origActivityName--->>"
+ running.origActivity.getClassName());
System.out.println("origPkgName--->>"
+ running.origActivity.getPackageName());
}
}
}
http://www.apihome.cn/api/android/android.app
ActivityManager--获得正在运行的activitiy与service http://androidbin.iteye.com/blog/1594908
Android中获取正在运行的应用程序--ActivityManager.RunningAppProcessInfo类详解 http://blog.youkuaiyun.com/qinjuning/article/details/7009824
Android中获取系统内存信息以及进程信息--ActivityManager的使用 http://blog.youkuaiyun.com/qinjuning/article/details/6978560