一个简单的仿 Launcher 应用
本例实现两个功能:
- 系统桌面上的app图标能够排列在我们的页面上。
- 点击自定义桌面上的app图标,能够打开对应的app。
实现思路:
- 我们知道,一个应用的启动页 Activity 的 Intent 的 filter 中 包含
action为Intent.ACTION_MAIN和category为Intent.CATEGORY_LAUNCHER信息,我们构造一个这样的 Intent 来查询所有启动页 Activity 。 - 用一个 RecyclerView 来展示信息。
- 通过 Intent 跳转到对应 app 的主页面。
主要代码如下:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.sharpcj.launchertest.MainActivity">
<android.support.v7.widget.RecyclerView
android:padding="10dp"
android:id="@+id/rv_test"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
recyclerview_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="100dp"
android:layout_height="100dp">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="15dp"
android:layout_marginTop="5dp"
android:textSize="13sp"
android:maxLines="1"
android:ellipsize="end"
android:layout_gravity="center_horizontal"
/>
</LinearLayout>
MainActivity.java
package com.example.sharpcj.launchertest;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerView mRvTest;
private List<ResolveInfo> mlsResolveInfo;
private RvTestAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRvTest = findViewById(R.id.rv_test);
mlsResolveInfo = new ArrayList<>();
mRvTest.setLayoutManager(new GridLayoutManager(this, 4));
mAdapter = new RvTestAdapter(MainActivity.this, mlsResolveInfo, new RvTestAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int position) {
ResolveInfo resolveInfo = mlsResolveInfo.get(position);
startAppByResolveInfo(resolveInfo);
MainActivity.this.finish();
}
});
mRvTest.setAdapter(mAdapter);
List<ResolveInfo> resolveInfos = queryMainActivitiesInfo();
mlsResolveInfo.addAll(resolveInfos);
mAdapter.notifyDataSetChanged();
}
/**
* 查询所有包含启动 intent 的 Activity 信息(去掉本应用)
*
* @return
*/
private List<ResolveInfo> queryMainActivitiesInfo() {
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> resolveInfos = getPackageManager().queryIntentActivities(mainIntent, 0);
// 去掉本应用
Iterator<ResolveInfo> iterator = resolveInfos.iterator();
while (iterator.hasNext()) {
ResolveInfo resolveInfo = iterator.next();
String packageName = resolveInfo.activityInfo.packageName;
if (packageName.equals(getApplication().getPackageName())) {
iterator.remove();
}
}
return resolveInfos;
}
private void startAppByResolveInfo(ResolveInfo resolveInfo) {
String pkg = resolveInfo.activityInfo.packageName;
String cls = resolveInfo.activityInfo.name;
ComponentName componet = new ComponentName(pkg, cls);
//打开该应用的主activity
Intent intent = new Intent();
intent.setComponent(componet);
startActivity(intent);
}
}
RvTestAdapter.java
package com.example.sharpcj.launchertest;
import android.content.Context;
import android.content.pm.ResolveInfo;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
* Created by SharpCJ on 2018/7/26.
*/
public class RvTestAdapter extends RecyclerView.Adapter<RvTestAdapter.ViewHolder> {
public interface OnItemClickListener {
void onClick(View view, int position);
}
private Context mContext;
private List<ResolveInfo> mlsResolveInfo;
private OnItemClickListener mListener;
public RvTestAdapter(Context context, List<ResolveInfo> resolveInfos, OnItemClickListener listener) {
this.mContext = context;
this.mlsResolveInfo = resolveInfos;
this.mListener = listener;
}
public void setmListener(OnItemClickListener listener) {
this.mListener = listener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_item, parent, false);
RvTestAdapter.ViewHolder viewHolder = new RvTestAdapter.ViewHolder(view, mListener);
return viewHolder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
ResolveInfo resolveInfo = mlsResolveInfo.get(position);
holder.imageView.setImageDrawable(resolveInfo.activityInfo.loadIcon(mContext.getPackageManager()));
holder.textView.setText(resolveInfo.activityInfo.applicationInfo.loadLabel(mContext.getPackageManager()));
}
@Override
public int getItemCount() {
return mlsResolveInfo.size();
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
OnItemClickListener onItemClickListener;
ImageView imageView;
TextView textView;
public ViewHolder(View itemView, OnItemClickListener onItemClickListener) {
super(itemView);
this.onItemClickListener = onItemClickListener;
imageView = itemView.findViewById(R.id.iv_icon);
textView = itemView.findViewById(R.id.tv_name);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (onItemClickListener != null) {
onItemClickListener.onClick(v, getAdapterPosition());
}
}
}
}
运行效果如图:

一个简单的仿 Launcher 应用的更多相关文章
- 用Vue编写一个简单的仿Explorer文件管理器
大家一定很熟悉你桌面左上角那个小电脑吧,学名Windows资源管理器,几乎所有的工作都从这里开始,文件云端化是一种趋势.怎样用浏览器实现一个Web版本的Windows资源管理器呢?今天来用Vue好好 ...
- 【Bugly干货分享】一起用 HTML5 Canvas 做一个简单又骚气的粒子引擎
Bugly 技术干货系列内容主要涉及移动开发方向,是由Bugly邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 前言 好吧,说是“粒子引擎”还是大言不 ...
- 一起用HTML5 canvas做一个简单又骚气的粒子引擎
前言 好吧,说是"粒子引擎"还是大言不惭而标题党了,离真正的粒子引擎还有点远.废话少说,先看demo 本文将教会你做一个简单的canvas粒子制造器(下称引擎). 世界观 这个简单 ...
- 自己实现的一个简单的EF框架(反射实现)
我实现了一个简单的EF框架,主要用于操纵数据库.实现了对数据库的基本操纵--CRUD 这是项目结构 这是一个 core 下的 DLL 写了一个数据库工厂,用于执行sql语句.调用sql语句工厂 写了一 ...
- 使用 RxJS 实现一个简易的仿 Elm 架构应用
使用 RxJS 实现一个简易的仿 Elm 架构应用 标签(空格分隔): 前端 什么是 Elm 架构 Elm 架构是一种使用 Elm 语言编写 Web 前端应用的简单架构,在代码模块化.代码重用以及测试 ...
- 5、使用Libgdx设计一个简单的游戏------雨滴
(原文:http://www.libgdx.cn/topic/49/5-%E4%BD%BF%E7%94%A8libgdx%E8%AE%BE%E8%AE%A1%E4%B8%80%E4%B8%AA%E7% ...
- 实现一个简单的shell
使用已学习的各种C函数实现一个简单的交互式Shell,要求:1.给出提示符,让用户输入一行命令,识别程序名和参数并调用适当的exec函数执行程序,待执行完成后再次给出提示符.2.该程序可识别和处理以下 ...
- Core1.1环境下,自己实现的一个简单的CRUD框架(反射实现)
我实现了一个简单的EF框架,主要用于操纵数据库.实现了对数据库的基本操纵--CRUD 这是项目结构 这是一个 core 下的 DLL 写了一个数据库工厂,用于执行sql语句.调用sql语句工厂 写了一 ...
- Prism for WPF 搭建一个简单的模块化开发框架(五)添加聊天、消息模块
原文:Prism for WPF 搭建一个简单的模块化开发框架(五)添加聊天.消息模块 中秋节假期没事继续搞了搞 做了各聊天的模块,需要继续优化 第一步画页面 页面参考https://github.c ...
随机推荐
- 打开.py文件的方法
用IDLE打开这个文件,然后按F5,系统就自动开始运行这个python程序,然后当前运行目录就跳转到这个目录了
- 给jdk配置jvm的参数
(1)window->preference->java->installed JREs ->edit -Xms512m -Xmx512m -XX:MaxNewSize=512 ...
- 用TortoiseSVN忽略文件或文件夹(ignore)(网络摘抄记录)
Android项目需要协同一起开发时,就需要保证项目同步完整性.SVN忽略文件列表:.gradle .idea build local.properties *.iml app/*.iml app/b ...
- 几个比较经典的算法问题的java实现
1.八皇后问题 public class EightQueen { private static final int ROW = 16; private static final int COL = ...
- vue生成图片验证码
最近做项目接触Vue,前端生成验证码.原理其实很简单,首先是生成随机数,然后用canvas绘制. 网上有一些现成的资料,没必要重复造轮子,我是在他们基础上完善了父组件,简化了子组件的调用: ident ...
- Mybatis 二级缓存脏读
脏读的产生 Mybatis的二级缓存是和命名空间绑定的,所以通常情况下每一个Mapper映射文件都有自己的二级缓存,不同的mapper的二级缓存互不影响.这样的设计一不注意就会引起脏读,从而导致数据一 ...
- PostgreSql Partition + Hibernate Insert
与Oracle不同.PostgreSQL须要手动控制分区规则触发器. 步骤一:创建分区 CREATE TABLE table_partition_1( CHECK partition_column c ...
- 深入java虚拟机(一) 虚拟机内存结构
java虚拟机所管理的内存区域(运行时数据区)主要分为如下几个部分:堆(heap).方法区(method area).虚拟机栈(VM stack).本地方法栈(native method stack) ...
- NET Framework 4.5新特性 (三)64位平台支持大于2 GB大小的数组
64位平台.NET Framework数组限制不能超过2GB大小.这种限制对于需要使用到大型矩阵和向量计算的工作人员来说,是一个非常大问题. 无论RAM容量有多大有多少,一旦你使用大型矩阵和向量计算工 ...
- linux ftp 上传与下载命令解析
month=`date -d "last month" +"%Y%m"` year=`date +"%Y"` rm /home/yourDi ...