热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

LaucherActivity的源码分析和应用(非launcher桌面应用)

一、启动初探【要看Launcher如何启动桌面上的app的同学,请绕行,非本篇内容】”在android手机上,当我们点击桌面上的按钮启动

一、启动初探

【要看Launcher如何启动桌面上的app的同学,请绕行,非本篇内容】
”在android手机上,当我们点击桌面上的按钮启动一个应用,就能打开应用的界面。这里我们所说的桌面其实就是android系统启动后的就已经帮我们运行的第一个程序,launcher程序。

launcher程序可以理解为作为其它应用app入口管理的一个系统自带的app,正常情况下,安装一个新的应用,就会在桌面(laucher)程序中显示一个相应的图标。

上述点击桌面上的图标打开应用的过程,本质上是通过lancher应用的提供的桌面图标启动另一个app的过程,并打开了新应用的首个Activity。

我们自己是否能开发这样的一个自定义桌面程序呢,其实是可以的。

二、Android提供的launcherActivity源码分析(基于Android10.0源码)

桌面程序就是我们平常所说的launcher程序,我们在手机桌面上看到的应用的icon,实际上是在LauncherActivity上实现的。接下来我们看launcherActivity的源代码:

/*** Displays a list of all activities which can be performed* for a given intent. Launches when clicked.* 翻译:显示所有通过给定的intent能被执行的Activity列表。点击的时候启动*/
public abstract class LauncherActivity extends ListActivity {Intent mIntent;PackageManager mPackageManager;//包管理器IconResizer mIconResizer;.....@Overrideprotected void onListItemClick(ListView l, View v, int position, long id) {//此处就是桌面图标被点击后,执行的核心代码Intent intent = intentForPosition(position);//调用了是Activity的startActivity方法startActivity(intent);}...}

《基于android10.0源码分析Activity的启动流程》在之前写过这篇文章中,我们就是从StartActivity入手,分析了启动Activity的源码实现流程。

对于从桌面启动一个Activity本质上也是构建了一个intent去调用startActivity(intent)。这里面我们再看一下intentForPosition(position)的源码,来确定我们的intent构建是大概是如何关联到我们的我们平常在开发自己的应用的时候设置的launcher activity。

/*** 返回指定位置所对应的app的真实intent*/
protected Intent intentForPosition(int position) {ActivityAdapter adapter = (ActivityAdapter) mAdapter;return adapter.intentForPosition(position);
}

实际上继续调用了LaucherActivity的内容类ActivityAdapter的intentForPosition()

private class ActivityAdapter extends BaseAdapter implements Filterable {public Intent intentForPosition(int position) {if (mActivitiesList == null) {return null;}// 通过mIntent构建了intentIntent intent = new Intent(mIntent);// 获取确定位置的activity是谁ListItem item = mActivitiesList.get(position);intent.setClassName(item.packageName, item.className);if (item.extras != null) {intent.putExtras(item.extras);}return intent;}
}

当前要执行的Activity的确定是在mActivitiesList获取的。看一下mActivitiesList的存储的内容:

private class ActivityAdapter extends BaseAdapter implements Filterable {...... public ActivityAdapter(IconResizer resizer) {mIconResizer = resizer;mInflater = (LayoutInflater) LauncherActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);mShowIcons = onEvaluateShowIcons();//在构造方法中,我们找到此方法mActivitiesList = makeListItems();}
}

接着看makeListItems()

public List<ListItem> makeListItems() {// Load all matching activities and sort correctlyList<ResolveInfo> list &#61; onQueryPackageManager(mIntent);onSortResultList(list);ArrayList<ListItem> result &#61; new ArrayList<ListItem>(list.size());int listSize &#61; list.size();for (int i &#61; 0; i < listSize; i&#43;&#43;) {ResolveInfo resolveInfo &#61; list.get(i);result.add(new ListItem(mPackageManager, resolveInfo, null));}return result;
}

这里面&#xff0c;我们看到实际的ActivitiesList是通过PackageManager加载得到&#xff0c;getPackageManager实现是在contextImpl.java中实现&#xff0c;通过下载android的framework层的源码关联找到&#xff0c;刚开始在android studio中直接关联是找不到具体的方法实现。

&#64;Override
public PackageManager getPackageManager() {if (mPackageManager !&#61; null) {return mPackageManager;}//非常熟悉的ActivityThread&#xff0c;后续的源码实现&#xff0c;我们能看到类似Ams的binder的接口//这里也是跨进程的通信IPackageManager pm &#61; ActivityThread.getPackageManager();if (pm !&#61; null) {// Doesn&#39;t matter if we make more than one instance.return (mPackageManager &#61; new ApplicationPackageManager(this, pm));}return null;
}

上面的有些跑偏了&#xff0c;回到桌面上点击一个应用icon启动应用的流程上来&#xff0c;其实源码流程还是非常简单的&#xff1a;

1.通过PackageManager检索以mIntent为筛选条件的ResolveInfo集合

List<ResolveInfo> list &#61; onQueryPackageManager(mIntent);

2.对ResolveInfo集合二次封装成ListItem集合&#xff0c;成为列表Adapter的数据

3.当点击条目时&#xff0c;通过ListItem创建出跳转Intent&#xff0c;调用startActivity跳转

Intent intent &#61; intentForPosition(position);
startActivity(intent);

看完了这laucherActivity的源码&#xff0c;我们只要实现一个类继承此类&#xff0c;并改变getTargetIntent的实现。


推荐阅读
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • (三)多表代码生成的实现方法
    本文介绍了一种实现多表代码生成的方法,使用了java代码和org.jeecg框架中的相关类和接口。通过设置主表配置,可以生成父子表的数据模型。 ... [详细]
author-avatar
区小靜
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有