Android Launcher浅析(三)
发布日期:2021-05-08 00:09:13 浏览次数:27 分类:精选文章

本文共 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();List
shortcutNames = 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页面显示插件。实现步骤如下:

  • 为AppWidget提供一个元布局文件AppWidgetProvider_Provider.xml,用来显示Widget的界面。
  • 创建一个类继承自AppWidgetProvider,并覆盖相关方法,并注册到配置文件中。
  • 为WidgetProvider创建一个引用的布局文件。
  • 具体步骤如下:

  • 在res/xml文件夹下创建AppWidgetProvider_Provider.xml文件:
    1. 修改MainActivity继承自AppWidgetProvider并覆盖相关方法:
    2. 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);        }    }}
      1. 为Widget创建一个显示用的布局文件main.xml:
        1. 在AndroidManifest.xml中声明AppWidgetProvider的子类,并设置相应的intent-filter和meta-data:
        2. 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的交互流程

        3. Launcher启动,开始监听。
        4. 服务发送广播。
        5. 我的应用接收到广播,执行onUpdate方法。
        6. onUpdate方法将RemoteViews返回给服务。
        7. 服务更新AppWidget。
        8. Launcher监听到,更新AppWidget。
        9. 通过以上步骤,我们可以成功实现AppWidget在HOME页面的显示。

    上一篇:Android开发常识
    下一篇:Android中的FlexboxLayout

    发表评论

    最新留言

    第一次来,支持一个
    [***.219.124.196]2025年03月26日 12时37分11秒