Android Framework 常见解决方案(10)关闭蓝牙配对对话框 & 关闭蓝牙忘记设备对话框

1 原理

在Android 系统应用Setting中做相关的修改,主要逻辑为:不弹出对话框,但 会直接执行点击确定后的逻辑,所以具体的方式就是 先找到配对对话框/忘记设备对话框 执行确定的逻辑,将其移植到Setting中探出对话框的位置。

2 修改方案(Android Q)

2.1 关闭蓝牙配对对话框

对话框显示为:

Android Framework 常见解决方案(10)关闭蓝牙配对对话框 & 关闭蓝牙忘记设备对话框_第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 关闭蓝牙忘记设备对话框

对话框显示为:

Android Framework 常见解决方案(10)关闭蓝牙配对对话框 & 关闭蓝牙忘记设备对话框_第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;
    }

}

验证测试后 确认该方案有效。改动不大,关键是找准对话框显示的起始逻辑 以及 点击确定后执行的逻辑。

你可能感兴趣的:(常见解决方案,android,framework,android,java,开发语言)