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

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.mfbz.cn/a/129621.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《持续交付:发布可靠软件的系统方法》- 读书笔记(十二)

持续交付&#xff1a;发布可靠软件的系统方法&#xff08;十二&#xff09; 第 12 章 数据管理12.1 引言12.2 数据库脚本化12.3 增量式修改12.3.1 对数据库进行版本控制12.3.2 联合环境中的变更管理 12.4 数据库回滚和无停机发布12.4.1 保留数据的回滚12.4.2 将应用程序部署与数…

Vue集成海康websdk实现摄像头预览

选择以及下载相应的websdk&#xff1a; 从海康开放平台下载相应的sdk&#xff0c;web3.0不支持高版本浏览器&#xff0c;web3.2需要摄像头支持摄像头取流&#xff0c;web3.3支持高版本浏览器 我这选择的是3.3的。可以先测试下开发包是否可以成功访问&#xff0c;修改用ip、户名…

visual studio 启用DPI识别功能

在开发widow程序时&#xff0c;有时必须将电脑 设置-->显示-->缩放与布局-->更改文本、应用项目的大小-->100%后&#xff0c;程序的画面才能正确运行&#xff0c;居说这是锁定了dpi的原因&#xff0c;需要启dpi识别功能。设置方法如下&#xff1a; 或者

ubuntu 16.04.5 安装 vivado 2019.1 完整编译AD9361的环境

一、前期安装 1、安装ncurses库&#xff08;已经包含了&#xff0c;其他的os需要安装&#xff09; sudo apt install libncurses5二、安装 sudo ./xsetup使用lic进行激活。 三、安装后 输入指令 sudo gedit ~/.bashrc 末尾添加 source /opt/Xilinx/Vivado/2019.1/setti…

防火防盗防小人 使用 Jasypt 库来加密配置文件

⚔️ 项目配置信息存放在哪&#xff1f; 在日常开发工作中&#xff0c;我们经常需要使用到各种敏感配置&#xff0c;如数据库密码、各厂商的 SecretId、SecretKey 等敏感信息。 通常情况下&#xff0c;我们会将这些敏感信息明文放到配置文件中&#xff0c;或者放到配置中心中。…

论文速览 | arxiv 2023, 马氏距离感知训练在分布外检测中的应用

注1:本文系“最新论文速览”系列之一,致力于简洁清晰地介绍、解读最新的顶会/顶刊论文。 OOD论文速览 | arxiv 2023, Mahalanobis-Aware Training for Out-of-Distribution Detection 该论文旨在提出一种改进的深度学习模型训练方法,以提高对分布外(OOD)样本的检测能力。…

小米智能电视投屏方法

小米智能电视也提供了投屏功能。 使用遥控器&#xff0c;在应用中找到它&#xff0c;点击进入。 小米电视支持windows笔记本&#xff0c;macbook笔记本&#xff0c;iphone手机&#xff0c;安卓手机投屏。 windows笔记本投屏 在投屏应用中找到windows投屏&#xff0c;选中开…

【经验模态分解】4.信号由时域向频域的转换

/*** poject 经验模态分解及其衍生算法的研究及其在语音信号处理中的应用* file 傅里叶变换与小波变换* author jUicE_g2R(qq:3406291309)* * language MATLAB* EDA Base on matlabR2022b* editor Obsidian&#xff08;黑曜石笔记软件&#…

亚马逊云科技实时 AI 编程助手 Amazon CodeWhisperer,开发快人一步!

近年来&#xff0c;随着 AI 技术的进步、基础设施建设的不断完善&#xff0c;AI 应用场景不断丰富&#xff0c;各类 AI 产品和工具层出不穷。其中&#xff0c;面向开发者的 AI 编程工具也在不断迭代&#xff0c;并因宣称能“帮开发者写代码”而引发关注。目前&#xff0c;可以为…

喜报!华为云金融PaaS3.0荣获“2023年应用现代化典型案例”称号

中国软件行业协会近期启动了2023“应用现代化产业实践”优秀案例征集活动&#xff0c;旨在加快推动应用现代化发展与推广应用&#xff0c;形成行业应用带动和示范作用&#xff0c;打造应用现代化软件名企、名品&#xff0c;凝聚行业资源&#xff0c;助力我国行业应用现代化高质…

使用jdk21预览版 --enable-preview

异常 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.10.1:compile (default-compile) on project sb3: Compilation failure [ERROR] --enable-preview 一起使用时无效 [ERROR] &#xff08;仅发行版 21 支持预览语言功能&#xff09; 解决…

MIPI配置的OV5640的使用

MIPI摄像头的数据输入FPGA的数据流&#xff1a; N Lane 差分串行输入 ————串转并模块 ————字节对齐处理 ————Lane同步处理处理 ————逆转LLP:Unpacked 处理 ————Byte转Pixel处理 此后写入Wfifo并且存入DDR3。

thinkphp6 起步

1、安装 composer create-project topthink/think6.0 tp62、使用多应用模式&#xff0c;你需要安装多应用模式扩展think-multi-app composer require topthink/think-multi-app3、config/app.php中&#xff0c;将 ‘auto_multi_app’ > flase, 改为true&#xff1b; 需要自…

MySQL-基础篇

文章目录 第一章 MYSQL 概述数据库相关概念MySQL 数据库下载安装启动和停止 MySQL客户端连接解决&#xff1a;mysql 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。配置 Path 环境变量解决&#xff1a;net start mysql80 发生系统错误 5。 拒绝访问。MYSQL 的…

Java自学第8课:电商项目(3) - 重新搭建环境

由于之前用的jdk和eclipse&#xff0c;以及mysql并不是视频教程所采用的&#xff0c;在后面运行源码和使用作者提供源码时&#xff0c;总是报错&#xff0c;怀疑&#xff1a; 1 数据库有问题 2 jdk和引入的jar包不匹配 3 其他什么未知的错误&#xff1f; 所以决定卸载jdk e…

STM32C8T6实现微秒延时函数delay_us

/* USER CODE BEGIN 0 */ void delay_us(uint32_t ii) {uint32_t temp;SysTick->LOADii*8;SysTick->VAL0x00;SysTick->CTRL0x01;//2号位1使用内核时钟do{tempSysTick->CTRL;}while(temp&0x01&&!(temp&(1<<16)));SysTick->CTRL0X00;SysTic…

【学术综述】-如何写出一篇好综述-写好综述要注意的问题

文章目录 1.前置1.1 SSD 的结构1.2 FTL的架构和作用 2 动机-why&#xff1f;3 做了什么【做了哪些方面的survey】&#xff1f;4 背景知识【上下文】5 研究的问题6 每个问题对应的解决方案 从昨天晚上【2023.11.09 22:00】到今天22:29的&#xff0c;花了一天的时间在读这篇surve…

串口通信(11)-CRC校验介绍算法

本文为博主 日月同辉&#xff0c;与我共生&#xff0c;csdn原创首发。希望看完后能对你有所帮助&#xff0c;不足之处请指正&#xff01;一起交流学习&#xff0c;共同进步&#xff01; > 发布人&#xff1a;日月同辉,与我共生_单片机-CSDN博客 > 欢迎你为独创博主日月同…

【全网首发】【Python】Python控制parrot ARDrone 2.0无人机

&#x1f389;欢迎来到Python专栏~Python控制parrot ARDrone 2.0无人机 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Python学习专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误…

公众号标签

公众号标签 本章节&#xff0c;讲解公众号标签的相关内容&#xff0c;支持对标签进行创建、查询、修改、删除等操作&#xff0c;也可以对用户进行打标签、取消标签等操作&#xff0c;对应 《微信公众号官方文档 —— 用户标签管理》 (opens new window)文档。 #1. 表结构 公众…