android launcher3 安装卸载

launcher3安装卸载流程

当手机安装卸载应用时,桌面图标会跟随发生变化(单层)、主菜单图标发生变化(双层)。而,能做到这一点,launcher必须知道什么时候安装卸载,什么时候需要添加或者删除图标。本篇文章的触发点就在于,广播接受者!!!

1、广播注册、接受

对于安装卸载更新的广播注册,是在代码里动态进行的。

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 ) );
	}
}

2、安装、卸载、更新

public static final int OP_ADD = 1;
public static final int OP_UPDATE = 2;
public static final int OP_REMOVE = 3; // uninstlled
PackageUpdatedTask implements Runnable,run方法中具体执行了安装、卸载、更新、等广播的操作。

通过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列表

至此,安装的应用就被添加到了ArrayList added中。其他操作同理,之后就是对列表数据的处理,以及桌面图标的变化和数据库的操作。

2、把安装应用信息保存在临时列表,清空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中有所介绍。

3、后记

这篇流程和逻辑比较简单,安装、更新、卸载应用。从几个点出发:

1、怎么获得应用安装、更新、卸载的消息。(注册对应广播,通过不同的action区分不同操作

2、知道对应的操作和,如何处理数据(launcherModel中的内部类PackageUpdatedTask里面负责数据处理和调用,应用信息数据保存在AllAppsList类中

3、界面上如何对应数据变化(添加图标、更新图标、删除图标回调launcher中对应的方法)

具体的逻辑还需要对照代码来看一下细节问题,比如应用是否安装、计算安装应用的位置、更新或者卸载桌面图标、等等。

你可能感兴趣的:(android,launcher)