有时候需要开发一个自己的桌面程序,特别是做产品开发的开发人员,android自定义桌面其实就是一个launcher,然后在相应的activity中把系统中的所有APK加载进来,显示相应的icon图标。
开发自定义桌面需要用到以下几个类
1,ComponentName:组件名称,通常用来打开其他应用程序中的Activity或服务。,
2,PackageInfo:包含了一些信息的基类,它的直接子类有:ApplicationInfo、ComponentInfo、InstrumentationInfo、PermissionGroupInfo、PermissionInfo。它的间接子类有:ActivityInfo、ProviderInfo、ServiceInfo。这个类包含的信息对于所有包中项目是平等的。这些Package items是被Package manager所持有的,这个类提供了属性的非常普通的基本设置。通过 PackageInfo 获取具体信息方法:
包名获取方法:packageInfo.packageName
icon获取获取方法:packageManager.getApplicationIcon(applicationInfo)
应用名称获取方法:packageManager.getApplicationLabel(applicationInfo)
使用权限获取方法:packageManager.getPackageInfo(packageName,PackageManager.GET_PERMISSIONS).requestedPermissions
3,ResolveInfo:这个类是通过解析一个与IntentFilter相对应的intent得到的信息。它部分地对应于从AndroidManifest.xml的<intent>标签收集到的信息。通过 ResolveInfo 获取具体信息方法:
包名获取方法:resolve.activityInfo.packageName
icon获取获取方法:resolve.loadIcon(packageManager)
应用名称获取方法:resolve.loadLabel(packageManager).toString()
4,PackageManger : 获得已安装的应用程序信息,常用方法:
public abstract PackageManager getPackageManager() //功能:获得一个PackageManger对象
public abstract Drawable getApplicationIcon(String packageName) //参数: packageName 包名,功能:返回给定包名的图标,否则返回null
public abstract ApplicationInfo getApplicationInfo(String packageName, int flags) //参数:packagename 包名 flags 该ApplicationInfo是此flags标记,通常可以直接赋予常数0即可,功能:返回该ApplicationInfo对象
public abstract List<ApplicationInfo> getInstalledApplications(int flags) //参数:flag为一般为GET_UNINSTALLED_PACKAGES,那么此时会返回所有ApplicationInfo。我们可以对ApplicationInfo的flags过滤,得到我们需要的。功能:返回给定条件的所有PackageInfo
public abstract List<PackageInfo> getInstalledPackages(int flags) //参数如上,功能:返回给定条件的所有PackageInfo
首先,需要在manifest中加入
<category android:name=”android.intent.category.HOME” />
<category android:name=”android.intent.category.DEFAULT” />
系统启动后,ActivityManagerService会寻找系统中的”android.intent.category.HOME”,然后进行加载,如果”android.intent.category.HOME”有多个,则会让其进行选择,完整的如下
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.launcher"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
<activity
android:name="com.test.Launcher"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
/>
</application>
</manifest>
需定义一个xml来定义桌面的布局:
<com.test.launcher.Test
android:id="@+id/apps_customize_pane_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
launcher:cellCountX="4"
launcher:cellCountY="2"
launcher:maxAppCellCountX="@integer/apps_customize_maxCellCountX"
launcher:maxAppCellCountY="@integer/apps_customize_maxCellCountY"
launcher:pageLayoutWidthGap="@dimen/apps_customize_pageLayoutWidthGap"
launcher:pageLayoutHeightGap="@dimen/apps_customize_pageLayoutHeightGap"
launcher:pageLayoutPaddingTop="@dimen/apps_customize_pageLayoutPaddingTop"
launcher:pageLayoutPaddingBottom="@dimen/apps_customize_pageLayoutPaddingBottom"
launcher:pageLayoutPaddingLeft="@dimen/apps_customize_pageLayoutPaddingLeft"
launcher:pageLayoutPaddingRight="@dimen/apps_customize_pageLayoutPaddingRight"
launcher:widgetCellWidthGap="@dimen/apps_customize_widget_cell_width_gap"
launcher:widgetCellHeightGap="@dimen/apps_customize_widget_cell_height_gap"
launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x"
launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y"
launcher:clingFocusedX="@integer/apps_customize_cling_focused_x"
launcher:clingFocusedY="@integer/apps_customize_cling_focused_y"
launcher:maxGap="@dimen/workspace_max_gap"/>
然后,实现功能函数:
private ArrayList<ApplicationInfo> mApps;
private int mNumAppsPages;
private int mMaxAppCellCountX, mMaxAppCellCountY;
public void setApps(ArrayList<ApplicationInfo> list) {
mApps = list;
//Collections.sort(mApps, LauncherModel.APP_NAME_COMPARATOR);
updatePageCounts();
if (testDataReady())requestLayout();
}
public void addApps(ArrayList<ApplicationInfo> list) {
addAppsWithoutInvalidate(list);
updatePageCounts();
invalidatePageData();
}
public void removeApps(ArrayList<ApplicationInfo> list) {
removeAppsWithoutInvalidate(list);
updatePageCounts();
invalidatePageData();
}
public void updateApps(ArrayList<ApplicationInfo> list) {
removeAppsWithoutInvalidate(list);
addAppsWithoutInvalidate(list);
updatePageCounts();
invalidatePageData();
}
private void updatePageCounts() {
mNumAppsPages = (int) Math.ceil((float) mApps.size() / (mCellCountX * mCellCountY));
}
private boolean testDataReady() {
// We only do this test once, and we default to the Applications page, so we only really
// have to wait for there to be apps.
// TODO: What if one of them is validly empty
return !mApps.isEmpty();
}
private void addAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
// We add it in place, in alphabetical order
int count = list.size();
for (int i = 0; i < count; ++i) {
ApplicationInfo info = list.get(i);
int index = Collections.binarySearch(mApps, info, ApplicationInfoComparator());
if (index < 0) {
mApps.add(-(index + 1), info);
}
}
}
static class ApplicationInfoComparator implements Comparator<ApplicationInfo> {
@Override
public int compare(ApplicationInfo a, ApplicationInfo b) {
return a.arrID - b.arrID;
}
}
private void removeAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
// loop through all the apps and remove apps that have the same component
int length = list.size();
for (int i = 0; i < length; ++i) {
ApplicationInfo info = list.get(i);
int removeIndex = findAppByComponent(mApps, info);
if (removeIndex > -1) {
mApps.remove(removeIndex);
}
}
}
private int findAppByComponent(List<ApplicationInfo> list, ApplicationInfo item) {
ComponentName removeComponent = item.intent.getComponent();
int length = list.size();
for (int i = 0; i < length; ++i) {
ApplicationInfo info = list.get(i);
if (info.intent.getComponent().equals(removeComponent)) {
return i;
}
}
return -1;
}
自定义ApplicationInfo类:
public class ApplicationInfo extends ItemInfo{
private static final String TAG = "ApplicationInfo";
/**
* The application name.
*/
CharSequence title;
/**
* The intent used to start the application.
*/
Intent intent;
/**
* A bitmap version of the application icon.
*/
Bitmap iconBitmap;
/**
* The time at which the app was first installed.
*/
long firstInstallTime;
ComponentName componentName;
static final int DOWNLOADED_FLAG = 1;
static final int UPDATED_SYSTEM_APP_FLAG = 2;
int flags = 0;
public int arrID;
ApplicationInfo() {
itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
}
/**
* Must not hold the Context.
*/
public ApplicationInfo(PackageManager pm, ResolveInfo info, IconCache iconCache,
HashMap<Object, CharSequence> labelCache, int arrId) {
final String packageName = info.activityInfo.applicationInfo.packageName;
this.componentName = new ComponentName(packageName, info.activityInfo.name);
this.container = ItemInfo.NO_ID;
this.setActivity(componentName,
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
try {
int appFlags = pm.getApplicationInfo(packageName, 0).flags;
if ((appFlags & android.content.pm.ApplicationInfo.FLAG_SYSTEM) == 0) {
flags |= DOWNLOADED_FLAG;
if ((appFlags & android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
flags |= UPDATED_SYSTEM_APP_FLAG;
}
}
firstInstallTime = pm.getPackageInfo(packageName, 0).firstInstallTime;
arrID = arrId;
} catch (NameNotFoundException e) {
Log.d(TAG, "PackageManager.getApplicationInfo failed for " + packageName);
}
iconCache.getTitleAndIcon(this, info, labelCache);
}
public ApplicationInfo(ApplicationInfo info) {
super(info);
componentName = info.componentName;
title = info.title.toString();
intent = new Intent(info.intent);
flags = info.flags;
firstInstallTime = info.firstInstallTime;
arrID= info.arrID;
}
/**
* Creates the application intent based on a component name and various launch flags.
* Sets {@link #itemType} to {@link LauncherSettings.BaseLauncherColumns#ITEM_TYPE_APPLICATION}.
*
* @param className the class name of the component representing the intent
* @param launchFlags the launch flags
*/
final void setActivity(ComponentName className, int launchFlags) {
intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(className);
intent.setFlags(launchFlags);
itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION;
}
@Override
public String toString() {
return "ApplicationInfo(title=" + title.toString() + ")";
}
public static void dumpApplicationInfoList(String tag, String label,
ArrayList<ApplicationInfo> list) {
Log.d(tag, label + " size=" + list.size());
for (ApplicationInfo info: list) {
Log.d(tag, " title=\"" + info.title + "\" iconBitmap="
+ info.iconBitmap + " firstInstallTime="
+ info.firstInstallTime);
}
}
public ShortcutInfo makeShortcut() {
return new ShortcutInfo(this);
}
}
由于水平较次,高手勿喷,仅供学习