
本文共 5021 字,大约阅读时间需要 16 分钟。
Launcher与AppWidget开发实践指南
Launcher的定义及构成
Launcher是系统启动后第一个启动的程序,是其他应用程序的入口,相当于手机程序的桌面程序。通过查看官方提供的Launcher源码可以发现,Launcher其实也是一个Activity,但它的intent-filter有一些特殊之处。
Launcher的intent-filter配置
在Launcher的intent-filter中,action为intent.action.MAIN,表示该Activity是程序的主入口。但它的category是HOME,和一般的app不同,HOME标识了这个Activity是一个Launcher,也就是对应的按下HOME键所跳转到的Activity,是我们的桌面。
普通App的主入口配置
category.LAUNCHER表示该Activity在Launcher上可见,所以它会被添加到Launcher中。
Launcher的构成
Launcher的构成包括HomeScreen(工作区+热门桌面布局)、Shortcut(快捷方式)、LiveFolder(文件夹)、AppWidget(窗口小部件)和WallPaper(壁纸)等。接下来我们将分别探讨这些元素。
1. 快捷方式(Shortcut)
在Launcher的配置文件中,有一个广播接收者用于监听快捷方式的添加,InstallShortcutReceiver的源码如下:
public class InstallShortcutReceiver extends BroadcastReceiver { private static final String ACTION_INSTALL_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT"; private final int[] mCoordinates = new int[2]; public void onReceive(Context context, Intent data) { if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) { return; } int screen = Launcher.getScreen(); if (!installShortcut(context, data, screen)) { // 目标屏满了,尝试其他屏 for (int i = 0; i < Launcher.SCREEN_COUNT; i++) { if (i != screen && installShortcut(context, data, i)) break; } } }}
从上述核心代码可以看出,在接收到INSTALL_SHORTCUT广播后,会尝试在当前屏添加快捷方式。如果当前屏满了,则会尝试添加到其他屏。因此,当我们想主动添加一个快捷方式到屏幕时,只需发送一个广播,并设置Action为INSTALL_SHORTCUT即可。需要注意的是,如果仅仅设置Action是不够的,可能会导致快捷方式重复添加。要避免重复添加,需要做一些设置,详情请参考相关文档。
2. LiveFolder
在Launcher.java文件中,可以找到添加LiveFolder的入口:
// 添加LiveFolder的入口Bundle bundle = new Bundle();ListshortcutNames = new ArrayList<>();shortcutNames.add(getResources().getString(R.string.group_folder));bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames);List shortcutIcons = new ArrayList<>();shortcutIcons.add(ShortcutIconResource.fromContext(Launcher.this, R.drawable.ic_launcher_folder));bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIcons);Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);pickIntent.putExtra(Intent.EXTRA_INTENT, new Intent(LiveFolders.ACTION_CREATE_LIVE_FOLDER));pickIntent.putExtra(Intent.EXTRA_TITLE, getText(R.string.title_select_live_folder));pickIntent.putExtras(bundle);startActivityForResult(pickIntent, REQUEST_PICK_LIVE_FOLDER);
当我们长按桌面后选择添加文件夹时,会执行上述代码。首先会创建一个空文件夹。
3. AppWidget(窗口小部件)
AppWidgetProvider用于在HOME页面显示插件。实现步骤如下:
具体步骤如下:
- 修改MainActivity继承自AppWidgetProvider并覆盖相关方法:
- 为Widget创建一个显示用的布局文件main.xml:
- 在AndroidManifest.xml中声明AppWidgetProvider的子类,并设置相应的intent-filter和meta-data:
- Launcher启动,开始监听。
- 服务发送广播。
- 我的应用接收到广播,执行onUpdate方法。
- onUpdate方法将RemoteViews返回给服务。
- 服务更新AppWidget。
- Launcher监听到,更新AppWidget。
public class MainActivity extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); Timer timer = new Timer(); timer.scheduleAtFixedRate(new LYTimeTask(context, appWidgetManager), 1, 50000); } private class LYTimeTask extends TimerTask { RemoteViews remoteViews; AppWidgetManager appWidgetManager; ComponentName widget; @Override public void run() { Date date = new Date(); Calendar calendar = new GregorianCalendar(2013, 7, 24); long days = (calendar.getTimeInMillis() - date.getTime()) / 1000 / 86400; remoteViews.setTextViewText(R.id.worldcup, "还剩下" + days + "天"); appWidgetManager.updateAppWidget(widget, remoteViews); } public LYTimeTask(Context context, AppWidgetManager appWidgetManger) { super(); this.appWidgetManager = appWidgetManger; remoteViews = new RemoteViews(context.getPackageName(), R.layout.activity_main); widget = new ComponentName(context, MainActivity.class); } }}
AppWidgetProvider的相关方法
public class WidgetProvider extends AppWidgetProvider { @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); } @Override public void onDeleted(Context context, int[] appWidgetIds) { super.onDeleted(context, appWidgetIds); } @Override public void onEnabled(Context context) { super.onEnabled(context); } @Override public void onDisabled(Context context) { super.onDisabled(context); }}
Launcher和AppWidget的交互流程
通过以上步骤,我们可以成功实现AppWidget在HOME页面的显示。
发表评论
最新留言
关于作者
