1 原理
在Android 系统应用Setting中做相关的修改,主要逻辑为:不弹出对话框,但 会直接执行点击确定后的逻辑,所以具体的方式就是 先找到配对对话框/忘记设备对话框 执行确定的逻辑,将其移植到Setting中探出对话框的位置。
2 修改方案(Android Q)
2.1 关闭蓝牙配对对话框
对话框显示为:
修改文件位置为:AOSP/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothPairingRequest.java文件,修改内容如下:
public final class BluetoothPairingRequest extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (!action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
return;
}
// convert broadcast intent into activity intent (same action string)
/*注释掉部分为之前的逻辑
Intent pairingIntent = BluetoothPairingService.getPairingDialogIntent(context, intent);
PowerManager powerManager =
(PowerManager)context.getSystemService(Context.POWER_SERVICE);
BluetoothDevice device =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceAddress = device != null ? device.getAddress() : null;
String deviceName = device != null ? device.getName() : null;
boolean shouldShowDialog = LocalBluetoothPreferences.shouldShowDialogInForeground(
context, deviceAddress, deviceName);
if (powerManager.isInteractive() && shouldShowDialog) {
// Since the screen is on and the BT-related activity is in the foreground,
// just open the dialog
context.startActivityAsUser(pairingIntent, UserHandle.CURRENT);
} else {
// Put up a notification that leads to the dialog
intent.setClass(context, BluetoothPairingService.class);
context.startServiceAsUser(intent, UserHandle.CURRENT);
}
*/
/*
* 这里为修改后的逻辑,device.setPairingConfirmation(true);为点击配对对话框的确定按键后
* 执行的逻辑。在这里直接执行,即表示跳过对话框 直接点击确定按键的逻辑。但如果只是为了消除对话
* 框,但不需要点击确认,下面逻辑可以不用执行。
*/
BluetoothDevice device =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
device.setPairingConfirmation(true);
}
}
2.2 关闭蓝牙忘记设备对话框
对话框显示为:
修改文件位置为:AOSP/packages/apps/Settings/src/com/android/settings/bluetooth/ForgetDeviceDialogFragment.java文件,目的是添加 忘记对话框弹出后点击确定按键的方法ExecUnPair,修改内容如下:
public class ForgetDeviceDialogFragment extends InstrumentedDialogFragment {
public static final String TAG = "ForgetBluetoothDevice";
private static final String KEY_DEVICE_ADDRESS = "device_address";
private CachedBluetoothDevice mDevice;
public static ForgetDeviceDialogFragment newInstance(String deviceAddress) {
Bundle args = new Bundle(1);
args.putString(KEY_DEVICE_ADDRESS, deviceAddress);
ForgetDeviceDialogFragment dialog = new ForgetDeviceDialogFragment();
dialog.setArguments(args);
return dialog;
}
/*
* 添加的新方法ExecUnPair,内容为点击忘记设备对话框中确定按键后执行的逻辑。
*/
public void ExecUnPair()
{
Context context = getContext();
mDevice = getDevice(context);
mDevice.unpair();
}
@VisibleForTesting
CachedBluetoothDevice getDevice(Context context) {
String deviceAddress = getArguments().getString(KEY_DEVICE_ADDRESS);
LocalBluetoothManager manager = Utils.getLocalBtManager(context);
BluetoothDevice device = manager.getBluetoothAdapter().getRemoteDevice(deviceAddress);
return manager.getCachedDeviceManager().findDevice(device);
}
@Override
public int getMetricsCategory() {
return SettingsEnums.DIALOG_BLUETOOTH_PAIRED_DEVICE_FORGET;
}
@Override
public Dialog onCreateDialog(Bundle inState) {
DialogInterface.OnClickListener onConfirm = (dialog, which) -> {
mDevice.unpair();
Activity activity = getActivity();
if (activity != null) {
activity.finish();
}
};
Context context = getContext();
mDevice = getDevice(context);
final boolean untetheredHeadset = BluetoothUtils.getBooleanMetaData(
mDevice.getDevice(), BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET);
AlertDialog dialog = new AlertDialog.Builder(context)
.setPositiveButton(R.string.bluetooth_unpair_dialog_forget_confirm_button,
onConfirm)
.setNegativeButton(android.R.string.cancel, null)
.create();
dialog.setTitle(R.string.bluetooth_unpair_dialog_title);
dialog.setMessage(context.getString(untetheredHeadset
? R.string.bluetooth_untethered_unpair_dialog_body
: R.string.bluetooth_unpair_dialog_body,
mDevice.getName()));
return dialog;
}
}
接下来修改 AOSP/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java文件,目的不显示对话框,直接执行逻辑ExecUnPair,修改内容如下:
public class BluetoothDetailsButtonsController extends BluetoothDetailsController {
private static final String KEY_ACTION_BUTTONS = "action_buttons";
private boolean mIsConnected;
private boolean mConnectButtonInitialized;
private ActionButtonsPreference mActionButtons;
public BluetoothDetailsButtonsController(Context context, PreferenceFragmentCompat fragment,
CachedBluetoothDevice device, Lifecycle lifecycle) {
super(context, fragment, device, lifecycle);
mIsConnected = device.isConnected();
}
private void onForgetButtonPressed() {
ForgetDeviceDialogFragment fragment =
ForgetDeviceDialogFragment.newInstance(mCachedDevice.getAddress());
//fragment.show(mFragment.getFragmentManager(), ForgetDeviceDialogFragment.TAG);//该句代码的含义是 显示 忘记设备对话框,将其注释掉。
fragment.ExecUnPair();//不显示对话框,直接执行解除配对的逻辑,注意:如果不想解除该逻辑,则不需要添加该逻辑,不添加即可。
}
@Override
protected void init(PreferenceScreen screen) {
mActionButtons = ((ActionButtonsPreference) screen.findPreference(
getPreferenceKey()))
.setButton1Text(R.string.forget)
.setButton1Icon(R.drawable.ic_settings_delete)
.setButton1OnClickListener((view) -> onForgetButtonPressed())
.setButton1Enabled(true);
}
@Override
protected void refresh() {
mActionButtons.setButton2Enabled(!mCachedDevice.isBusy());
boolean previouslyConnected = mIsConnected;
mIsConnected = mCachedDevice.isConnected();
if (mIsConnected) {
if (!mConnectButtonInitialized || !previouslyConnected) {
mActionButtons
.setButton2Text(R.string.bluetooth_device_context_disconnect)
.setButton2Icon(R.drawable.ic_settings_close)
.setButton2OnClickListener(view -> mCachedDevice.disconnect());
mConnectButtonInitialized = true;
}
} else {
if (!mConnectButtonInitialized || previouslyConnected) {
mActionButtons
.setButton2Text(R.string.bluetooth_device_context_connect)
.setButton2Icon(R.drawable.ic_add_24dp)
.setButton2OnClickListener(
view -> mCachedDevice.connect(true /* connectAllProfiles */));
mConnectButtonInitialized = true;
}
}
}
@Override
public String getPreferenceKey() {
return KEY_ACTION_BUTTONS;
}
}
验证测试后 确认该方案有效。改动不大,关键是找准对话框显示的起始逻辑 以及 点击确定后执行的逻辑。