当前位置: 首页 > news >正文

Android 自定义应用选择器对话框

Android 自定义应用选择器对话框

    • 一、获取可处理 `ACTION_VIEW` 的应用列表
    • 二、显示应用列表对话框
    • 三、自定义布局
    • 四、示例代码
    • 五、总结

一、获取可处理 ACTION_VIEW 的应用列表

public List<ResolveInfo> getAppsForActionView(Context context, Uri fileUri) {Intent intent = new Intent(Intent.ACTION_VIEW);intent.setData(fileUri);intent.setType("*/*"); // Adjust the MIME type as neededPackageManager packageManager = context.getPackageManager();return packageManager.queryIntentActivities(intent, 0);
}

二、显示应用列表对话框

创建并显示一个对话框,其中包含应用列表。

public void showAppChooserDialog(Context context, Uri fileUri) {List<ResolveInfo> apps = getAppsForActionView(context, fileUri);PackageManager packageManager = context.getPackageManager();AlertDialog.Builder builder = new AlertDialog.Builder(context);builder.setTitle("Select an application");ListAdapter adapter = new ArrayAdapter<String>(context,android.R.layout.select_dialog_item,apps.stream().map(info -> info.loadLabel(packageManager).toString()).collect(Collectors.toList())) {@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view = super.getView(position, convertView, parent);TextView text = view.findViewById(android.R.id.text1);text.setCompoundDrawablesWithIntrinsicBounds(apps.get(position).loadIcon(packageManager),null, null, null);text.setCompoundDrawablePadding(16);return view;}};builder.setAdapter(adapter, (dialog, which) -> {ResolveInfo selectedApp = apps.get(which);Intent intent = new Intent(Intent.ACTION_VIEW);intent.setData(fileUri);intent.setType("*/*");intent.setPackage(selectedApp.activityInfo.packageName);context.startActivity(intent);});builder.show();
}

使用方法

调用 showAppChooserDialog 方法并传递文件的 Uri:

Uri fileUri = Uri.parse("file://path/to/your/file"); // Adjust the file path
showAppChooserDialog(this, fileUri);

说明

  • 自定义对话框:使用 AlertDialog 来创建一个应用选择对话框。
  • 列表适配器ArrayAdapter 用于显示应用名称和图标。
  • 启动选定应用:用户选择应用后,启动对应的应用来处理文件。
  • fileUri:替换为实际需要打开的文件 URI。

三、自定义布局

创建一个布局文件 app_item.xml,包含 ImageViewTextView

<!-- res/layout/app_item.xml -->
<LinearLayout xmlns:android="<http://schemas.android.com/apk/res/android>"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="8dp"><ImageViewandroid:id="@+id/app_icon"android:layout_width="40dp"android:layout_height="40dp"android:layout_marginEnd="8dp" /><TextViewandroid:id="@+id/app_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center_vertical"android:textSize="16sp" />
</LinearLayout>

自定义适配器

创建自定义适配器 AppListAdapter

public class AppListAdapter extends ArrayAdapter<ResolveInfo> {private final List<ResolveInfo> apps;private final PackageManager packageManager;private final int resource;public AppListAdapter(Context context, int resource, List<ResolveInfo> apps) {super(context, resource, apps);this.apps = apps;this.packageManager = context.getPackageManager();this.resource = resource;}@NonNull@Overridepublic View getView(int position, View convertView, @NonNull ViewGroup parent) {if (convertView == null) {convertView = LayoutInflater.from(getContext()).inflate(resource, parent, false);}ResolveInfo appInfo = apps.get(position);ImageView appIcon = convertView.findViewById(R.id.app_icon);TextView appName = convertView.findViewById(R.id.app_name);appIcon.setImageDrawable(appInfo.loadIcon(packageManager));appName.setText(appInfo.loadLabel(packageManager));return convertView;}
}

显示对话框

在你的活动或片段中使用自定义适配器:

public void showAppChooserDialog(Context context, Uri fileUri) {List<ResolveInfo> apps = getAppsForActionView(context, fileUri);AppListAdapter adapter = new AppListAdapter(context, R.layout.app_item, apps);AlertDialog.Builder builder = new AlertDialog.Builder(context);builder.setTitle("Select an application");builder.setAdapter(adapter, (dialog, which) -> {ResolveInfo selectedApp = apps.get(which);Intent intent = new Intent(Intent.ACTION_VIEW);intent.setData(fileUri);intent.setType("*/*");intent.setPackage(selectedApp.activityInfo.packageName);context.startActivity(intent);});AlertDialog dialog = builder.create();dialog.show();// 设置对话框背景dialog.getWindow().setBackgroundDrawableResource(android.R.color.background_light);
}

说明

  • 自定义布局app_item.xml 包含 ImageViewTextView
  • 自定义适配器AppListAdapter 负责为每个应用加载图标和名称。
  • 对话框背景:使用 setBackgroundDrawableResource() 设置对话框背景颜色。你可以根据需要替换为其他颜色资源。

在 Android 中,当使用 Intent.createChooser() 创建一个应用选择器(chooser)时,系统不会自动为传入的 Intent 设置 setPackage()

详细解释:

  1. Intent.createChooser() 的行为
    • 当调用 Intent.createChooser() 时,系统会弹出一个对话框,显示所有能够处理该 Intent 的应用程序列表。
    • 用户选择一个应用后,系统会将该应用的信息(如其包名)与原始 Intent 结合,启动该应用来处理 Intent
  2. 是否自动设置 setPackage()
    • 系统并不会自动为原始的 Intent 添加 setPackage()
    • 系统会临时将用户选择的应用与 Intent 绑定,但不会直接修改或传递 setPackage() 的值到原始 Intent 中。
    • 如果你需要显式指定 setPackage(),需要在代码中自己设置它。
  3. 为什么 setPackage() 很重要
    • 使用 setPackage() 可以强制指定某个应用来处理 Intent,避免系统显示多个应用选择器。
    • 如果使用了 Intent.createChooser()setPackage() 通常不需要,因为用户会手动选择应用。

四、示例代码

以下是一个使用 Intent.createChooser() 的示例:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "Hello, World!");// 创建一个 chooser
Intent chooser = Intent.createChooser(intent, "Choose an app");
startActivity(chooser);
  • 在这里,系统不会为 intent 添加 setPackage(),而是根据用户选择的应用临时处理。

如果需要手动设置 setPackage()

如果你需要显式指定某个应用,可以在 Intent 上调用 setPackage(),如下所示:

intent.setPackage("com.example.specificapp"); // 替换为目标应用的包名
startActivity(intent);

这样会直接跳转到指定应用,而不会弹出应用选择器。


五、总结

  • 默认行为Intent.createChooser() 不会自动为 Intent 添加 setPackage()
  • 临时绑定:系统会根据用户选择的应用临时绑定 Intent 与目标应用。
  • 手动指定:如果需要某个特定应用处理 Intent,需要显式调用 setPackage()

http://www.mrgr.cn/news/78430.html

相关文章:

  • 重构代码之将双向关联改为单向关联
  • SpringBoot+Vue的音乐网站项目
  • vue element-ui的el-image 和 el-table冲突层级冲突问题问题preview-teleported
  • STM32完全学习——使用标准库完成PWM输出
  • 【计算机网络】计算机网络概述
  • SAP学习
  • 浅谈网络 | 应用层之HTTPS协议
  • android 安全sdk相关
  • 韩顺平 一周学会Linux | Linux 实操篇-组管理和权限管理
  • 音视频入门基础:MPEG2-TS专题(8)——TS Header中的适配域
  • 算法设计作业
  • 面试手撕题积累
  • 在 Spring Boot 中构造 API 响应的最佳实践
  • 彻底理解微服务配置中心的作用
  • PyQt学习笔记
  • (长期更新)《零基础入门 ArcGIS(ArcMap) 》实验二----网络分析(超超超详细!!!)
  • android集成FFmpeg步骤以及常用命令,踩坑经历
  • 【Leetcode 每日一题】743. 网络延迟时间
  • 使用ENSP实现NAT
  • PostgreSQL 三种关库模式
  • CTO 实际上是在做什么?
  • LLamafactory API部署与使用异步方式 API 调用优化大模型推理效率
  • 矩阵重新排列——sort函数
  • 使用ENSP实现默认路由
  • 蓝桥杯c++算法秒杀【6】之动态规划【上】(数字三角形、砝码称重(背包问题)、括号序列、组合数问题:::非常典型的必刷例题!!!)
  • 鸿蒙NEXT元服务:利用App Linking实现无缝跳转与二维码拉起