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
中添加数组主要修改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>