• 仿华为 USB mode 实现方法


    极力推荐文章:欢迎收藏
    Android 干货分享

    阅读5分钟,每日十点、和您一起终身学习,这里是程序员Android

    本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:

    一、实现效果
    二、主要实现思路
    三、主要实现代码
    四、在Framework 层添加资源的方法

    一、实现效果

    仿华为USB Mode弹窗实现效果如下:
    底部USB mode 弹窗实现

    二、主要实现思路

    主要实现思路如下:
    在手机连接USB发送/取消通知的同时,控制弹窗Dialog 的显示/消失。

    三、主要实现代码

    连接USB发送/取消通知主要实现是在UsbDeviceManager.java类中,类路径如下:
    frameworksaseservicesusbjavacomandroidserverusbUsbDeviceManager.java,通过查看此类代码,实现想要的功能。
    修改实现代码如下:

    // add start by wj for usb mode
    import android.app.AlertDialog;
    import android.app.AlertDialog.Builder;
    import android.content.DialogInterface;
    import android.view.WindowManager;
    import android.view.Gravity;
    // add end by wj for usb mode
    
    /**
     * UsbDeviceManager manages USB state in device mode.
     */
    public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver {
    
        private static final String TAG = UsbDeviceManager.class.getSimpleName();
        ... ...
    	// add start by wj for usb mode
        private static UsbHandler mHandler;
    	private static AlertDialog mServiceDialog = null;
    	// add end by wj for usb mode
        ... ...
          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 (mConnected) {
                    if (mCurrentFunctions == UsbManager.FUNCTION_MTP) {
                        titleRes = com.android.internal.R.string.usb_mtp_notification_title;
                        id = SystemMessage.NOTE_USB_MTP;
                    } else if (mCurrentFunctions == UsbManager.FUNCTION_PTP) {
                        titleRes = com.android.internal.R.string.usb_ptp_notification_title;
                        id = SystemMessage.NOTE_USB_PTP;
                    } else if (mCurrentFunctions == UsbManager.FUNCTION_MIDI) {
                        titleRes = com.android.internal.R.string.usb_midi_notification_title;
                        id = SystemMessage.NOTE_USB_MIDI;
                    } else if (mCurrentFunctions == UsbManager.FUNCTION_RNDIS) {
                        titleRes = com.android.internal.R.string.usb_tether_notification_title;
                        id = SystemMessage.NOTE_USB_TETHER;
                    } else if (mCurrentFunctions == UsbManager.FUNCTION_ACCESSORY) {
                        titleRes = com.android.internal.R.string.usb_accessory_notification_title;
                        id = SystemMessage.NOTE_USB_ACCESSORY;
                    }
                    if (mSourcePower) {
                        if (titleRes != 0) {
                            message = r.getText(
                                    com.android.internal.R.string.usb_power_notification_message);
                        } else {
                            titleRes = com.android.internal.R.string.usb_supplying_notification_title;
                            id = SystemMessage.NOTE_USB_SUPPLYING;
                        }
                    } else if (titleRes == 0) {
                        titleRes = com.android.internal.R.string.usb_charging_notification_title;
                        id = SystemMessage.NOTE_USB_CHARGING;
                    }
                } else if (mSourcePower) {
                    titleRes = com.android.internal.R.string.usb_supplying_notification_title;
                    id = SystemMessage.NOTE_USB_SUPPLYING;
                } else if (mHostConnected && mSinkPower && mUsbCharging) {
                    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 start by wj for usb mode
                        if (mServiceDialog != null) {
                            mServiceDialog.dismiss();
                            mServiceDialog=null;
                        }
                        // add start by wj for usb mode
                   .... ... 
                    }
    }
    
    
            protected void updateAdbNotification(boolean force) {
                if (mNotificationManager == null) return;
                final int id = SystemMessage.NOTE_ADB_ACTIVE;
                final int titleRes = com.android.internal.R.string.adb_active_notification_title;
    
                if (mAdbEnabled && mConnected) {
                    if ("0".equals(getSystemProperty("persist.adb.notify", ""))) return;
    
                    if (force && mAdbNotificationShown) {
                        mAdbNotificationShown = false;
                        mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
                    }
    
                    if (!mAdbNotificationShown) {
                        Resources r = mContext.getResources();
                        CharSequence title = r.getText(titleRes);
                        CharSequence message = r.getText(
                                com.android.internal.R.string.adb_active_notification_message);
    
                        Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                                | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                        PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
                                intent, 0, null, UserHandle.CURRENT);
                        Notification notification =
                                new Notification.Builder(mContext, SystemNotificationChannels.DEVELOPER)
                                        .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                                        .setWhen(0)
                                        .setOngoing(true)
                                        .setTicker(title)
                                        .setDefaults(0)  // please be quiet
                                        .setColor(mContext.getColor(
                                                com.android.internal.R.color
                                                        .system_notification_accent_color))
                                        .setContentTitle(title)
                                        .setContentText(message)
                                        .setContentIntent(pi)
                                        .setVisibility(Notification.VISIBILITY_PUBLIC)
                                        .extend(new Notification.TvExtender()
                                                .setChannelId(ADB_NOTIFICATION_CHANNEL_ID_TV))
                                        .build();
                        mAdbNotificationShown = true;
                        mNotificationManager.notifyAsUser(null, id, notification,
                                UserHandle.ALL);
    					// add start by wj for usb mode
    					final String USBModeStr[] = mContext.getResources().getStringArray(com.android.internal.R.array.spro_usb_mode);
    					AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
    					builder.setTitle(mContext.getResources().getString(com.android.internal.R.string.usb_mode_tittle));
    					builder.setSingleChoiceItems(USBModeStr, 0,
    						new DialogInterface.OnClickListener() {
    							@Override
    							public void onClick(DialogInterface dialog,
    									int which) {
    								Slog.e(TAG, "------USBModeStr[which]--------"+USBModeStr[which]);
    								dialog.dismiss();
    						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;
    						}
    							}
    						});
    						builder.setPositiveButton(mContext.getResources().getString(com.android.internal.R.string.usb_mode_cancel),
    												   new DialogInterface.OnClickListener() {
    														public void onClick(DialogInterface dialog, int id) {
    															dialog.cancel();
    
    														}
    														});
    						mServiceDialog = builder.create();
    						mServiceDialog.getWindow().setType(
    								WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
    						mServiceDialog.getWindow().setGravity(Gravity.BOTTOM);
    						if (mServiceDialog != null && !mServiceDialog.isShowing()) {
    							mServiceDialog.show();
    						}
    						// add start by wj for usb mode
                    }
                } else if (mAdbNotificationShown) {
                    mAdbNotificationShown = false;
                    mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
                }
            }
    
    
    }
    

    四、在Framework 层添加资源的方法

    三种USB Mode 的资源需要在Framework资源文件中添加。

    Framework中添加资源的方案如下:

    1. 添加strings 资源

    字符串需要多语言支持,一般建议至少支持英文 、中文。

    添加英文资源

    英文主要修改values文件下的strings.xml
    路径如下:frameworksasecore es esvaluesstrings.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>
    

    添加中文资源

    中文主要修改values-zh-rCN文件下的strings.xml
    修改路径如下:
    frameworksasecore es esvalues-zh-rCNstrings.xml

    添加内容如下:

    <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
         ... ... 
    	<!--start usb mode by wj-->
    	<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 wj-->
         ... ... 
    </resources>
    

    2.添加引用的数组资源

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

    Framework中添加数组主要修改valuesarrays.xml文件frameworksasecore es esvaluesarrays.xml
    添加内容如下:

    <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
         ... ... 
    	<!--start usb mode by wj-->
        <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>
        <!--end usb mode by wj-->
         ... ... 
    </resources>
    

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

    Framework中添加资源后,由于无法像Eclipse或者Androd Studio那样自动生成R.java文件,需要在symbols.xml文件中手动添加自己的资源文件名,否则会导致无法根据com.android.internal.R.**引用所需的字符串资源。
    symbols.xml主要在valuse文件夹下,详细路径为frameworksasecore es esvaluessymbols.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>
    

    至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

    微信关注公众号:  程序员Android,领福利

  • 相关阅读:
    thinkphp tp5 常用 functions
    nginx配置虚拟机 vhost 端口号 域名 区分虚拟机
    thinkphp tp5 模板 引擎 字符串 截取 函数 省略 显示
    C++运算符重载
    c++纯虚函数
    c++面向对象模型---c++如何管理类,对象以及它们之间的联系
    c++多态
    c++友元函数
    c语言的函数指针
    c++两种字符串赋值方式 并介绍 C语言下遍历目录文件的方式
  • 原文地址:https://www.cnblogs.com/wangjie1990/p/11327299.html
Copyright © 2020-2023  润新知