Android T 实现简易的 USB Mode Select 需求

news2024/11/26 15:29:28

Android T 实现 USB Mode Select 需求

一、实现效果

在这里插入图片描述

二、主要实现思路

在手机连接 USB 发生/取消通知的同时,控制弹窗 Dialog 的显示/消失。

三、主要代码实现

连接 USB 发送/取消的主要实现是在 UsbDeviceManager.java 类中。类路径如下:

system/frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java

具体修改代码如下:

//add for bug start {
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.view.WindowManager;
import android.view.Gravity;
// add for bug end }


/**
 * UsbDeviceManager manages USB state in device mode.
 */
public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObserver {
    
    private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv";

    //add for bug start {
    private static UsbHandler mHandler;

    private static AlertDialog mServiceDialog = null;
    //add for bug end }
    
    private final Object mLock = new Object();

    
        protected void updateUsbNotification(boolean force) {
            if (mNotificationManager == null || !mUseUsbNotification
                    || ("0".equals(getSystemProperty("persist.charging.notify", "")))) {
                return;
            }

            // Dont show the notification when connected to a USB peripheral
            // and the link does not support PR_SWAP and DR_SWAP
            if (mHideUsbNotification && !mSupportsAllCombinations) {
                if (mUsbNotificationId != 0) {
                    mNotificationManager.cancelAsUser(null, mUsbNotificationId,
                            UserHandle.ALL);
                    mUsbNotificationId = 0;
                    Slog.d(TAG, "Clear notification");
                }
                return;
            }

            int id = 0;
            int titleRes = 0;
            Resources r = mContext.getResources();
            CharSequence message = r.getText(
                    com.android.internal.R.string.usb_notification_message);
            if (mAudioAccessoryConnected && !mAudioAccessorySupported) {
                titleRes = com.android.internal.R.string.usb_unsupported_audio_accessory_title;
                id = SystemMessage.NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED;
            } 
            ....
            ....
            } else if (mHostConnected && mSinkPower && (mUsbCharging || mUsbAccessoryConnected)) {
                titleRes = com.android.internal.R.string.usb_charging_notification_title;
                id = SystemMessage.NOTE_USB_CHARGING;
            }
            if (id != mUsbNotificationId || force) {
                // clear notification if title needs changing
                if (mUsbNotificationId != 0) {
                    mNotificationManager.cancelAsUser(null, mUsbNotificationId,
                            UserHandle.ALL);
                    Slog.d(TAG, "Clear notification");
                    mUsbNotificationId = 0;
                    // add for bug start {
                    if (mServiceDialog != null){
                        mServiceDialog.dismiss();
                        mServiceDialog = null;
                    }
                    // add for bug end }
                }
                // Not relevant for automotive and watch.
                if ((mContext.getPackageManager().hasSystemFeature(
                        PackageManager.FEATURE_AUTOMOTIVE)
                        || mContext.getPackageManager().hasSystemFeature(
                        PackageManager.FEATURE_WATCH))
                        && id == SystemMessage.NOTE_USB_CHARGING) {
                    mUsbNotificationId = 0;
                    return;
                }

                if (id != 0) {
                    CharSequence title = r.getText(titleRes);
                    PendingIntent pi;
                    String channel;

                    ....
                    ....    
                    Slog.d(TAG, "push notification:" + title);
                    mUsbNotificationId = id;
                }
            }
        }

        // add for bug start {
        public void showDialog(Context context){
            final String USBModeStr[] = context.getResources().getStringArray(com.android.internal.R.array.spro_usb_mode);
            AlertDialog.Builder dialog = new AlertDialog.Builder(context);
            dialog.setTitle(context.getResources().getString(com.android.internal.R.string.usb_mode_tittle));
            dialog.setSingleChoiceItems(USBModeStr, 0 ,
                    new DialogInterface.OnClickListener(){
                        @Override
                        public void onClick(DialogInterface dialog, int which){
                            Slog.d(TAG, "----------USBModeStr------------" + USBModeStr[which]);
                            switch (which){
                                case 1:
                                    mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, UsbManager.FUNCTION_MTP);
                                    break;
                                case 2:
                                    mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, UsbManager.FUNCTION_PTP);
                                    break;
                                default:
                                    mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, UsbManager.FUNCTION_NONE);
                                    break;
                            }
                            dialog.dismiss();
                        }
                    }
            );
            dialog.setPositiveButton(context.getResources().getString(com.android.internal.R.string.usb_mode_cancel),
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    });
            mServiceDialog = dialog.create();
            mServiceDialog.getWindow().setType(
                    WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
            mServiceDialog.getWindow().setGravity(Gravity.BOTTOM);
            if (mServiceDialog != null && !mServiceDialog.isShowing()) {
                mServiceDialog.show();
            }
        }

        // add for bug end }
    
    	
            protected void updateAdbNotification(boolean force) {
            if (mNotificationManager == null) return;
            final int id = SystemMessage.NOTE_ADB_ACTIVE;

            if (isAdbEnabled() && mConnected) {
                if ("0".equals(getSystemProperty("persist.adb.notify", ""))) return;

                if (force && mAdbNotificationShown) {
                    mAdbNotificationShown = false;
                    mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
                }

                if (!mAdbNotificationShown) {
                    Notification notification = AdbNotifications.createNotification(mContext,
                            AdbTransportType.USB);
                    mAdbNotificationShown = true;
                    mNotificationManager.notifyAsUser(null, id, notification, UserHandle.ALL);

                    // add for bug start {
                    showDialog(mContext);
                    // add for bug end }
                }
            } else if (mAdbNotificationShown) {
                mAdbNotificationShown = false;
                mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
            }
        }
}
3.2、添加 string 资源
添加英文资源

frameworks\base\core\res\res\values\strings.xml

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     ... ... 
    <!--start usb mode by wj-->
    <string name="usb_mode_tittle">Use USB for</string>
    <string name="usb_mode_charging_only">Charging only</string>
    <string name="usb_mode_mtp">File Transfer(MTP)</string>
    <string name="usb_mode_ptp">Transfer Photos(PTP)</string>
    <string name="usb_mode_cancel">Cancel</string>
    <!--end usb mode by wj-->
     ... ... 
</resources>

添加中文资源

frameworks\base\core\res\res\values-zh-rCN\strings.xml

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     ... ... 
    <!--start usb mode by-->
    <string name="usb_mode_tittle">USB 用途</string>
    <string name="usb_mode_charging_only">仅限充电</string>
    <string name="usb_mode_mtp">传输文件(MTP)</string>
    <string name="usb_mode_ptp">传输照片(PTP)</string>
    <string name="usb_mode_cancel">取消</string>
    <!--end usb mode by -->
     ... ... 
</resources>
3.3、添加引用的数组资源

因为3种 USB mode,引用了数组资源,所以需要在Framework层添加数组资源。

Framework中添加数组主要修改valuesarrays.xml文件frameworks\base\core\res\res\values\arrays.xml
添加内容如下:

</resources> 
    ... ...
    <!-- add for bug start -->
    <string-array name="spro_usb_mode">
        <item>@string/usb_mode_charging_only</item>
        <item>@string/usb_mode_mtp</item>
        <item>@string/usb_mode_ptp</item>
    </string-array>
    <!-- add for bug end -->
</resources>

3.4、修改Framwork 资源,需要添加symbol,否则无法引用

Framework中添加资源后,由于无法像Eclipse或者Androd Studio那样自动生成R.java文件,需要在symbols.xml文件中手动添加自己的资源文件名,否则会导致无法根据com.android.internal.R.**引用所需的字符串资源。
symbols.xml主要在valuse文件夹下,详细路径为frameworks\base\core\res\res\values\symbols.xml

添加内容如下:

<resources>
     ... ... 
  <!--start usb mode by wj-->
  <java-symbol type="string" name="usb_mode_tittle" />
  <java-symbol type="string" name="usb_mode_charging_only" />
  <java-symbol type="string" name="usb_mode_mtp" />
  <java-symbol type="string" name="usb_mode_ptp" />
  <java-symbol type="string" name="usb_mode_cancel" />
  <java-symbol type="array" name="spro_usb_mode" />
  <!--end usb mode by wj-->
     ... ... 
</resources>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1193154.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

公司批量寄件教程

公司批量寄快递如何实现&#xff1f;相信不少企业行政人员、财务人员等都有类似的困扰。 很简单&#xff0c;随着经济和快递行业的发展&#xff0c;因公寄件在企业中已经是件常事了&#xff0c;其中不乏有批量寄件的时候。比如说财务批量寄递发票、行政批量寄递节日慰问品、业…

工作利器!熟悉这几款数据流图工具,事半功倍!

数据流图工具在现代工作中起到了非常重要的作用。无论是在企业内部的流程优化&#xff0c;还是在软件开发、项目管理、系统设计等领域&#xff0c;数据流图工具都扮演着关键的角色。本文将为大家介绍8款高效的数据流图工具&#xff0c;帮助大家选择适合自己工作需求的工具。 1.…

工作四年,关于过滤敏感词,我准备这样干

文章目录 &#x1f4c6; 业务场景&#x1f5a5;️业务梳理&#x1f4cc;小技巧 &#x1f4c7;完整代码&#x1f58a;️最后总结胖奥特曼悠闲躺着 &#x1f4c6; 业务场景 提交订单评价时需要对评价内容进行判断&#xff0c;如果出现敏感词则提示修改 &#x1f50a;这不就是写一…

WorkPlus定制化的沟通协作平台,助您实现企业级完全掌控

在企业沟通协作的领域&#xff0c;一种高度定制化的平台是至关重要的。WorkPlus作为一款领先的沟通协作平台&#xff0c;具备高度定制化的特点&#xff0c;能够满足企业各项需求。通过平台级定制扩展和上下游完全掌控&#xff0c;WorkPlus成为了企业实现定制化和完全掌控的理想…

关于近期360自动屏保导致的问题

本身是一个好产品 但是对于某些应用就有点画蛇添足了 1、导致K3无法使用 K3中间层需要用户持续登入系统 2、导致系统停止工作 3、停止网络 4、占用系统资源 5、占用网络资源 6、占用硬件资源 。。。。。。 对于24小时开机的用户影响巨大 对于局域网信息点多的网络影响巨…

2011年09月01日 Go生态洞察:Go语言词法扫描与App Engine演示

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

全方位解析跨境电商系统源码,开启全球贸易新篇章

随着全球电商市场的快速发展&#xff0c;跨境电商已经成为越来越多企业的必然选择。在这个过程中&#xff0c;跨境电商系统源码的重要性不言而喻。本文将全方位解析跨境电商系统源码&#xff0c;帮助您更好地了解其核心构成、功能特点以及开发流程。 一、跨境电商系统源码的核心…

重温数据结构与算法之前缀和

文章目录 前言一、基础1.1 定义1.2 时间复杂度 二、扩展2.1 二维前缀和2.2 差分数组2.3 前缀积 三、LeetCode 实战3.1 长度最小的子数组3.2 二维区域和检索 - 矩阵不可变 参考 前言 前缀和&#xff08;Prefix Sum&#xff09;&#xff0c;也被称为累计和&#xff0c;是一种在计…

【EI会议征稿】第三届新能源技术创新与低碳发展国际研讨会(NET-LC 2024)

第三届新能源技术创新与低碳发展国际研讨会&#xff08;NET-LC 2024&#xff09; 2024 3rd International Symposium on New Energy Technology Innovation and Low Carbon Development 先进的现代能源技术对世界各地的经济发展至关重要。持续的经济进步取决于安全、可靠和负担…

idea2023如何查看被使用上下文关系

1.接口查看实现类&#xff0c;实现类查看接口 查看接口所有实现类 根据类里面的方法查看被覆盖的接口中的方法 2.查看方法、类被调用 3.查看类的继承关系

ChatGPT的图识别来了

前几天ChatGPT推出了Dall-E 3功能&#xff0c;可以根据文字和描述一段话来生成一个或者一组图。 这次又来重磅了&#xff0c;图识别又来了&#xff01;换句话说&#xff0c;也即是文生图&#xff0c;图生文都可以实现了&#xff0c;一起来试试 1、解释图中的意思 &#xff0…

粤嵌实训医疗项目--day06(Vue + SpringBoot)

往期回顾 粤嵌实训医疗项目(小组开发)--day05-CSDN博客粤嵌实训医疗项目--day04&#xff08;Vue SpringBoot&#xff09;-CSDN博客粤嵌实训医疗项目--day03&#xff08;Vue SpringBoot&#xff09;-CSDN博客粤嵌实训医疗项目day02&#xff08;Vue SpringBoot&#xff09;-CS…

Python 测试框架 Pytest 的入门

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;加入1000人软件测试技术学习交流群&#x1f4e2;资源分享&#xff1a;进了字节跳动之后&#xff0c;才…

【算法练习Day44】最长递增子序列最长连续递增序列最长重复子数组

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 最长递增子序列最长连续递增…

线程池创建、执行、销毁的原理解析

目录 线程池的执行原理线程执行参考&#xff1a; 线程池的执行原理 假设最大核心数是2&#xff0c;非核心线程数为1&#xff0c;队列长度是3 来第一个任务的时候&#xff0c;没有工作线程在工作&#xff0c;需要创建一个 来第二个任务的时候&#xff0c;发现当前核心线程数…

C语言 UTF-8与GBK编码互转,一个头文件搞定!不使用第三方库,纯C语言跨平台

背景&#xff1a; 项目需要在mips32架构的freertos系统上将输入的汉字、标点符号、数字、字母等转成机内码输出&#xff0c;第一个想到的办法是移植第三方库进行编码转换&#xff0c;网上搜了一圈libiconv、ICU库都可以实现&#xff0c;但是在我的项目上移植编译各种报错、非常…

【漏洞复现】jumpserver任意密码重置

jumpserver任意密码重置漏洞-CVE-2023-42820 jumpserver jumpserver是FIT2CLOUD飞致云旗下的开源堡垒机。 环境搭建 这里用的是vulhub靶场 进入 jumpserver 的目录 修改配置文件 config.env 里面的 DOMAINS 参数为kali的地址 运行环境&#xff0c;第一次运行的话会拉取文件…

rocksdb 中 db_bench 的使用方法

硬件要求 硬件要求如表1所示。 表1 硬件要求 项目 说明 CPU 12 * AMD Ryzen 5 5500U with Radeon Graphics 内存 DDR4 磁盘 HDD 软件要求 软件要求如表2所示。 表2 软件要求 项目 版本 说明 下载地址 CentOS 7.6 操作系统。 Download kernel 4.14.0 内核。…

射频功率放大器有哪些用途

射频功率放大器是一种专用于放大射频信号的设备&#xff0c;它在现代通信、广播、雷达、无线电频谱监测和科学研究等领域中发挥着重要的作用。射频功率放大器能够将输入的低功率射频信号放大为较高功率的信号&#xff0c;以满足各种应用场景对信号传输距离、质量和稳定性的要求…

基于VPLC711的曲面外观检测XYR运动控制解决方案

市场应用背景 随着消费升级&#xff0c;产品形态正在朝着多样性和精细化方向迅速发展。这导致了对于复杂曲面轨迹加工的需求&#xff0c;包括外观检测、打磨抛光和点胶工艺控制&#xff0c;要求更高的精密度。企业必须主动满足市场需求&#xff0c;不断改进工艺&#xff0c;以…