教你撸一个属于你独一无二的 Android Launcher

本贴最后更新于 2031 天前,其中的信息可能已经水流花落

序言

之前买了台 Android 测试机,发现原生的 Launcher 不太对我胃口,毕竟 Android 的精髓在于折腾。打算学习一下 Launcher 开发,顺便有了这篇文章。实际上我们的 Android 桌面 Launcher 其实也只是一个稍微特殊一点的 App。并没有什么太高深的内容,我们都可以通过简单的代码实现你心中最完美的 Android Launcher。

惯例先上效果图

画质较差,将就看下

1 准备工作

实际上判断一个 App 是否是 Launcher 很简单,我们只需要在 manifest 里面增加两句 category

 <activity android:name=".MainActivity"
            android:screenOrientation="portrait"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

只需要配置"android.intent.category.HOME" 每次按 Home 键时都会调用该 App
尝试按一下 Home 键看看效果

Screenshot20190521102432.png

可以看到该 App 已经出现在主屏幕应用列表里了。

2.编写界面

这里应该是最有趣的步骤了,你可以按照自己的喜好编写想要的界面。

作为一个 Launcher 应该设置背景为系统壁纸,增加一个 style 并且 parent="android:Theme.Wallpaper"。

<style name="AppTheme" parent="android:Theme.Wallpaper">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowTranslucentNavigation">false</item>
</style>

在 Application 中应用

   <application
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

如果想实现沉浸式状态栏还可以在 Activity 里设置去掉状态栏

   Window window = getWindow();
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

3.展示已安装 App

获取已安装的 App 信息

        private List<ResolveInfo> mApps;
        Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        mApps = getPackageManager().queryIntentActivities(mainIntent, 0);

通过 ResolveInfo 获取具体信息方法:

    包名获取方法:resolve.activityInfo.packageName
    icon获取获取方法:resolve.loadIcon(packageManager)
    应用名称获取方法:resolve.loadLabel(packageManager).toString()

再通过 GridView 展示 App 表格。

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical" >

    <ImageView
        android:layout_centerHorizontal="true"
        android:id="@+id/img"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginTop="10dp"
        />
    <TextView
        android:layout_below="@id/img"
        android:layout_centerHorizontal="true"
        android:id="@+id/text"
        android:lines="1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="2dp"
        android:layout_gravity="center"
        android:textColor="#000"
        android:text="App名称"
        />

</RelativeLayout>

编写一个非常简单的 Gridview item layout 一个 Imageview 一个 TextView 分别显示 App 图标和名字。

 public class AppsAdapter extends BaseAdapter {

        private LayoutInflater mInflater;

        public AppsAdapter() {
            mInflater = LayoutInflater.from(Main3Activity.this);
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if (convertView == null) {
                viewHolder = new ViewHolder();
                convertView = mInflater.inflate(R.layout.gridview_item, null);
                viewHolder.img = (ImageView) convertView.findViewById(R.id.img);
                viewHolder.text = (TextView) convertView.findViewById(R.id.text);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
            ResolveInfo info = mApps.get(position);
            viewHolder.img.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));
            viewHolder.text.setText(info.activityInfo.loadLabel(getPackageManager()));
            return convertView;
        }

        public final int getCount() {
            return mApps.size();
        }

        public final Object getItem(int position) {
            return mApps.get(position);
        }

        public final long getItemId(int position) {
            return position;
        }
    }

    class ViewHolder {
        public ImageView img;
        public TextView text;
    }

至此,已经可以显示所有已安装的 App 了,初步有了 Launcher 的模样。

4.跳转已安装的 App

光有界面是不够的,Launcher 必须要有打开别的 App 的能力。给我们的 mGrid 增加一个点击事件

private AdapterView.OnItemClickListener listener = new AdapterView.OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            ResolveInfo info = mApps.get(position);
            //该应用的包名
            String pkg = info.activityInfo.packageName;
            //应用的主activity类
            String cls = info.activityInfo.name;
            ComponentName componet = new ComponentName(pkg, cls);
            Intent i = new Intent();
            i.setComponent(componet);
            startActivity(i);
        }

    };

只要能获得到 packageName 和 App name 就能通过 i.setComponent(componet); 跳转到相应的 App。

还可以指定跳转到电话,图片,信息,设置界面。

    private class Click implements View.OnClickListener {
        @Override
        public void onClick(View view) {
            String pkg = null;
            String cls = null;
            switch (view.getId()) {
                case R.id.tel:
                    pkg = "com.google.android.dialer";
                    cls = "com.google.android.dialer.extensions.GoogleDialtactsActivity";
                    break;
                case R.id.pic:
                    pkg = "com.google.android.GoogleCamera";
                    cls = "com.android.camera.CameraLauncher";
                    break;
                case R.id.msg:
                    pkg = "com.google.android.apps.messaging";
                    cls = "com.google.android.apps.messaging.ui.ConversationListActivity";
                    break;
                case R.id.set:
                    pkg = "com.android.settings";
                    cls = "com.android.settings.Settings";
                    break;
            }
            if (pkg != null && cls != null) {
                intentApp(pkg, cls);
            }
        }
    }

End

Android 的乐趣在于折腾,实现自己想要的东西还是很有成就感的。另外 Launcher 应该还要有展示小部件的功能,这部分未提到,感兴趣的可以查阅相关资料自行了解。

  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    334 引用 • 323 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...