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_SWAPif (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 changingif (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(){@Overridepublic 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
中添加数组主要修改values
下arrays.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>