对于安装卸载更新的广播注册,是在代码里动态进行的。
LauncherAppState的构造方法中:
// Register intent receivers
IntentFilter filter = new IntentFilter( Intent.ACTION_PACKAGE_ADDED );//安装应用
filter.addAction( Intent.ACTION_PACKAGE_REMOVED );//卸载应用
filter.addAction( Intent.ACTION_PACKAGE_CHANGED );//更新应用
filter.addDataScheme( "package" );
sContext.registerReceiver( mModel , filter );
注册广播后,LauncherModel就可以接受应用的安装卸载更新广播,进行相应的处理:
final String action = intent.getAction();
if( Intent.ACTION_PACKAGE_CHANGED.equals( action ) || Intent.ACTION_PACKAGE_REMOVED.equals( action ) || Intent.ACTION_PACKAGE_ADDED.equals( action ) )
{
final String packageName = intent.getData().getSchemeSpecificPart();
final boolean replacing = intent.getBooleanExtra( Intent.EXTRA_REPLACING , false );
int op = PackageUpdatedTask.OP_NONE;
if( packageName == null || packageName.length() == 0 )
{
// they sent us a bad intent
return;
}
if( Intent.ACTION_PACKAGE_CHANGED.equals( action ) )
{
op = PackageUpdatedTask.OP_UPDATE;
}
else if( Intent.ACTION_PACKAGE_REMOVED.equals( action ) )
{
if( !replacing )
{
op = PackageUpdatedTask.OP_REMOVE;
}
// else, we are replacing the package, so a PACKAGE_ADDED will be sent
// later, we will update the package at this time
}
else if( Intent.ACTION_PACKAGE_ADDED.equals( action ) )
{
if( !replacing )
{
op = PackageUpdatedTask.OP_ADD;
}
else
{
op = PackageUpdatedTask.OP_UPDATE;
}
}
enqueuePackageUpdatedApp( op , new String[]{ packageName } );
}
接到广播后,通过action值设置不同的op,对应不同的操作。
/**
* 通过对应的op值和packageName去添加,卸载,更新应用
* @param op
* @param packageName
*/
public void enqueuePackageUpdatedApp(
int op ,
String[] packages )
{
if( op != PackageUpdatedTask.OP_NONE )
{
enqueuePackageUpdated( new PackageUpdatedTask( op , packages ) );
}
}
public static final int OP_ADD = 1;
public static final int OP_UPDATE = 2;
public static final int OP_REMOVE = 3; // uninstlled
通过switch case 判断当前操作(安装、更新、卸载),一下以安装为例:
1、case OP_ADD:循环安装应用的包名数组,并进行mBgAllAppsList.addPackage( context , packages[i] );操作。进入AllAppsList类中
public void addPackage(
Context context ,
String packageName )
{
final List matches = findActivitiesForPackage( context , packageName );
if( matches.size() > 0 )
{
for( ResolveInfo info : matches )
{
add( new AppInfo( context.getPackageManager() , info , mIconCache , null ) );
}
}
}
首先通过包名获得应用的ResolveInfo,然后把应用add进去。add方法中对info进行去重添加,代码就不贴出来了。
AllAppsList类的主要几个成员变量:
public static final int DEFAULT_APPLICATIONS_NUMBER = 42;
/** The list off all apps. */
public ArrayList data = new ArrayList( DEFAULT_APPLICATIONS_NUMBER );//所有应用的info列表
/** The list of apps that have been added since the last notify() call. */
public ArrayList added = new ArrayList( DEFAULT_APPLICATIONS_NUMBER );//安装应用info列表
/** The list of apps that have been removed since the last notify() call. */
public ArrayList removed = new ArrayList();//卸载应用的info列表
/** The list of apps that have been modified since the last notify() call. */
public ArrayList modified = new ArrayList();//更新应用的info列表
至此,安装的应用就被添加到了ArrayList2、把安装应用信息保存在临时列表,清空AllAppsList类中的added列表数据
if( mBgAllAppsList.added.size() > 0 )
{
added = new ArrayList( mBgAllAppsList.added );
mBgAllAppsList.added.clear();
}
3、添加图标
final ArrayList addedInfos = new ArrayList( added );
addAndBindAddedItems( context , addedInfos , null , cb , added , true , !mIsLoaderTaskRunning );
addAndBindAddedItems中的操作在http://blog.csdn.net/a396604593/article/details/52794920中有所介绍。
这篇流程和逻辑比较简单,安装、更新、卸载应用。从几个点出发:
1、怎么获得应用安装、更新、卸载的消息。(注册对应广播,通过不同的action区分不同操作)
2、知道对应的操作和,如何处理数据(launcherModel中的内部类PackageUpdatedTask里面负责数据处理和调用,应用信息数据保存在AllAppsList类中)
3、界面上如何对应数据变化(添加图标、更新图标、删除图标回调launcher中对应的方法)
具体的逻辑还需要对照代码来看一下细节问题,比如应用是否安装、计算安装应用的位置、更新或者卸载桌面图标、等等。