这一章是来学习intent还有任务,在这章中我们可以了解intent和intent过滤器,Android应用之间是如何交互的

可启动的应用都有着MAIN和LAUNCHER的类别的过滤器,所以我们可以添加下面的方法来创建一个intent从PackageManager那里来获得比配它的activity

private void setupAdapter(){
Intent intent = new Intent(Intent.ACTION_MAIN);
startupIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PackageManager pm = getActivity().getPackageManager();
List<ResolveInfo> activitiis = pm.queryIntentActivities(startupIntent,0);
}
startActivity()方法是启动比配隐式intent的的默认activity,而不是启动比配隐式intent的activity,调用这个方法发送隐式intent后,操作系统会悄悄地给目标intent加上Intent.CATEGORY_DEFAULT类别
所以如果希望在intent过滤器中比配到这个方法发送的intent,那么就必须在这个的里面加上上面所说的类别
而MAIN/LAUNCHERintent过滤器并不一定有包含上面的类别,所以我们就使用intent直接来向PackageManager查询带有MAIN/LAUNCHER过滤器的activity
(1)接下来就是在界面中去展示这些activity了,从PackageManager返回的ResolveInfor对象里面,就可以获取到activity和标签和其他一些元数据
 
private void setupAdapter(){
Intent intent = new Intent(Intent.ACTION_MAIN);
startupIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PackageManager pm = getActivity().getPackageManager();
List<ResolveInfo> activiyie = pm.queryIntentActivities(startupIntent,0);
//下面是对搜索到的activity进行排序
Collections.sort(activtities,new Comparator<ReslveInfo>(){
PackageManager pm = getActivity().getPackageManager();
return String.CASE_INSESITIVE_ORDER.compare(
a.loadLabel(pm).toString(),
b.loadLabel(pm).toString()'
);
}
};
(2)下面实现ViewHolder来展示名字
public class ActivityHolder extends RecyclerView.ViewHolder{
private ResolveInfo mResolveInfo;
private TextView mTextView;
public ActivityHolder(View itenView) {
super(itenView);
mTextView = (TextView)ItenView;
}
public void bindActivity(ResolveInfo resolveInfo) {
mResolveInfo = reslveInfo;
PackageManager pm = getActivity().getPackageManager();
String appName = mResolveInfo.loadLable(pm).toString();
mTextView.setText(appName);
}
}
(3)然后实现Adapter
private class ActivityAdapter extends RecyclerView.Adapter<ActivityHolder> {
private final Llist<ResolveInfo> mActivities;
public ActivityAdapter(List<ResolveInfo> activities) {
mActivities = activities;
}
public ActivityHolder onCreateViewHolder(ViewGroup parent,int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View view = layoutInflater.inflate(android.R.layout.simple_list_item_1,parent,false);
return new ActivitiesHolder(view);
}
public void onBindViewHolder (ActivityHolder holder,int position) {
ResolverInfo resolveInfo = mActivities.get(position);
holder.bindActivity(resolveInfo);
}
public int getItemCount(){
return mActivities.size();
}
}
(5)下面我们利用包名和类名来创建显式的intent,上面我们利用隐式intent来获取目标activity以列表的形式来展示,接下来我们需要实现点击任何一个列表项然后进行他们对应的activity,这边我们就需要来创建相应的显方式intent来进入
要创建启动activity的显方式intent,我们需要在ResolveInfo对象来去得到它的包名和类名,该信息可以在ReslveInfo对象中的ActivityInfo来获取,这样我们需要在ActivityHolder类中实现一个点击监听器,然后使用ActivityInfo对象中的数据信息来创建一个显方式intent
 
public class ActivityHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private ResolveInfo mResolveInfo;
private TextView mTextView;
public ActivityHolder(View itenView) {
super(itenView);
mTextView = (TextView)ItenView;
mTextView.setOnClickListener(this);
}
public void bindActivity(ResolveInfo resolveInfo) {
mResolveInfo = reslveInfo;
PackageManager pm = getActivity().getPackageManager();
String appName = mResolveInfo.loadLable(pm).toString();
mTextView.setText(appName);
}
public void onClick(View v) {
ActivityInfo activitiyInfo = mResolveInfo.activityInfo();
Intent i = new Intent(Intent.ACTION_MAIN).setClassName(activityInfo.application.packageName,activityInfo.name);
//这样构造方法会确定Activity类自行确定全路径的包名,它也可以自动创建组件名
startActivity(i);
}
}

(6)任务和回退栈

应用运行时,Android使用任务来跟踪用户状态,通过Android默认启动器应用打开的应用都有自己的任务,任务是一个activity栈,栈顶的activity用户可以看到,如果按后退键,栈顶的activity就会退出栈外,如果用户看到的界面是基activity,那么此时按后退键就会退回到主屏幕

如果我们想要在新的activity中去启动新任务,那么要为intent添加一个flag

addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

在Android中,每一个进程都有着一个虚拟机

任务只包含在activity中,这些activity通常不同的应用的进程,进程包含了应用的全部运行代码和对象

在设备上,如果需要应用启动多个任务,那么可以采用下面两种方式:

1.给intent加上Inten.FLAG_ACTIVITY_NEW_DOCUMENT标签,再调用startActivity()方法,或是再manifest文件里面为该activity设置如下面的代码

android:documentLaunchMode = "intoExising"/>这样后,一份文档就对应着一个任务,上面实现的原因来自于并发文档的新概念,这样就可以为运行的应用创建任意数目的任务了

 

2.如果在任何时候都想创建新任务,那么就给intent同时加上Inten.FLAG_ACTIVITY_NEW_DOCUMENT和Intent.FLAG_ACTIVITY_MULIPIE_TASK标签,或是把manifest文件里面的documentLaunchMode属性改为alaway