如何从后台开启android蓝牙的可见性以及始终保持可见性

本文揭示了如何通过反射技术绕过系统提示,实现Android蓝牙自动开启可见性,并介绍了超时后自动关闭可见性的方法及注意事项。适用于Android 4.2及以上版本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近工作中遇到一个特殊的需求,要求代码能够从后台开机android手机蓝牙的可见性。而framework提供了一种打开可见性的操作,就是通过向用户弹出一个提示框,来询问是否允许开启可见性。而且限制了最长时间为300秒,代码如下:

?
1
2
3
4
5
//启动修改蓝牙可见性的Intent
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
//设置蓝牙可见性的时间,方法本身规定最多可见300秒
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300 );
startActivity(intent);

但通过android的自带的settings程序,我们可以直接开机蓝牙可见性。所以下载settings的源码,进行分析。找到了开启蓝牙可见性的代码,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void setEnabled( boolean enable) {
         if (enable) {
             int timeout = getDiscoverableTimeout();
             mLocalAdapter.setDiscoverableTimeout(timeout);
 
             long endTimestamp = System.currentTimeMillis() + timeout * 1000L;
             LocalBluetoothPreferences.persistDiscoverableEndTimestamp(mContext, endTimestamp);
 
             mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, timeout);
             updateCountdownSummary();
         } else {
             mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
         }
     }

这下就清楚了,是BluetoothAdapter 里面的setDiscoverableTimeout和setScanMode起到了关键性左右,再看BluetoothAdapter源码,发现这2个方法都被隐藏(hide)了。如何能访问到被隐藏的方法呢?自然是用强大的反射:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void setDiscoverableTimeout( int timeout) {
         BluetoothAdapter adapter=BluetoothAdapter.getDefaultAdapter();
         try {
             Method setDiscoverableTimeout = BluetoothAdapter. class .getMethod( "setDiscoverableTimeout" , int . class );
             setDiscoverableTimeout.setAccessible( true );
             Method setScanMode =BluetoothAdapter. class .getMethod( "setScanMode" , int . class , int . class );
             setScanMode.setAccessible( true );
             
             setDiscoverableTimeout.invoke(adapter, timeout);
             setScanMode.invoke(adapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE,timeout);
         } catch (Exception e) {
             e.printStackTrace();
         }
     }

用这种方法开启的可见性,还有个附件的属性,timeout值并没有起到作用,可见性是一直保持的。可以通行下面类似的代码进行关闭:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void closeDiscoverableTimeout() {
         BluetoothAdapter adapter=BluetoothAdapter.getDefaultAdapter();
         try {
             Method setDiscoverableTimeout = BluetoothAdapter. class .getMethod( "setDiscoverableTimeout" , int . class );
             setDiscoverableTimeout.setAccessible( true );
             Method setScanMode =BluetoothAdapter. class .getMethod( "setScanMode" , int . class , int . class );
             setScanMode.setAccessible( true );
             
             setDiscoverableTimeout.invoke(adapter, 1 );
             setScanMode.invoke(adapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE, 1 );
         } catch (Exception e) {
             e.printStackTrace();
         }
     }

改变BluetoothAdapter.SCAN_MODE_CONNECTABLE是关键。

如果想实现超时后自动关闭可见性的效果,使用Handler

postDelayed(Runnable r, long delayMillis)
就可以轻松实现这个功能。


以上代码在android4.2以上可以允许,4.2以下会因为缺少系统权限而运行失败。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值