前言需求开发有时候需要获取蓝牙连接状态以及实时监听蓝牙连接状态的变化,为此在网络搜索了一圈,发现能解决的方法目前看到的只有一种,就是反射。闲下来总结一下,跳转蓝牙、WIFI、移动网络和热点设置页的富文本跳转。
1. 实际效果
![](https://i-blog.csdnimg.cn/blog_migrate/663a84ed80abcb2123cb634343801a48.png)
2. 蓝牙
想要实时监听蓝牙的连接状态你必须需要两样东西:广播监听和API判断。因为并不知道你启动Activity时,蓝牙是处于什么一个状态,而且当Activity不在前台时,你的广播监听是无效的,有效时蓝牙状态也可能不会发送变化,因此并不能实时捕捉到蓝牙的状态。
2.1 蓝牙广播监听和注册
// 1、创建一个广播
private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(p0: Context?, p1: Intent?) {
when (p1?.action) {
BluetoothDevice.ACTION_ACL_CONNECTED -> {
Log.i(TAG, "ACTION_ACL_CONNECTED")
}
BluetoothDevice.ACTION_ACL_DISCONNECTED -> {
Log.i(TAG, "ACTION_ACL_DISCONNECTED")
}
BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED -> {
Log.i(TAG, "isConnected = ${isConnected()}")
updatePage()
}
}
}
}
//2、在onCreate()中注册广播
private fun registerReceiver() {
val intentFilter = IntentFilter()
intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED)
intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED)
intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)
context?.registerReceiver(broadcastReceiver, intentFilter)
}
//3. 在onDestroy()中反注册广播
private fun unregisterReceiver() {
context?.unregisterReceiver(broadcastReceiver)
}
2.2 蓝牙连接状态API判断
/**
* 判断蓝牙是否连接
*/
private fun isConnected(): Boolean {
var res = false
val adapter = BluetoothAdapter.getDefaultAdapter()
val bluetoothAdapterClass = BluetoothAdapter::class.java
try {
val method =
bluetoothAdapterClass.getDeclaredMethod("getConnectionState", *emptyArray())
method.isAccessible = true
val state = method.invoke(adapter, *emptyArray()) as Int
if (state != BluetoothAdapter.STATE_CONNECTED) return false
Log.i(TAG, "BluetoothAdapter.STATE_CONNECTED")
val devices = adapter.bondedDevices
Log.i(TAG, "devices:" + devices.size)
for (device in devices) {
val isConnectedMethod =
BluetoothDevice::class.java.getDeclaredMethod("isConnected", *emptyArray())
method.isAccessible = true
val isConnected =
isConnectedMethod.invoke(device, *emptyArray()) as Boolean
if (isConnected) {
Log.i(TAG, "connected:" + device.name)
bluetoothDevice = device.name
res = isConnected
}
}
} catch (e: Exception) {
e.printStackTrace()
}
return res
}
3 富文本超链接跳转设置
使用 val spannableString = SpannableStringBuilder(content)来创建一个可以点击、可以设置颜色以及可以监听点击事件的字符串,想具体了解的看这篇文章。
这里我将其抽成一个方法使用如下:
/**
* 设置超链接
* @tipsView: 超链接设置的TextView
* @content:文本所有的内容
* @hyperText:超链接文字
* @action:intent跳转的action
* @context:Context
* Tips:超链接文字hyperText要在content中包含
*/
private fun setHyperLinkTips(
tipsView: TextView?,
content: String,
hyperText: String,
action: String,
context: Context
) {
val spannableString = SpannableStringBuilder(content)
val span = object : ClickableSpan() {
override fun onClick(p0: View) {
Log.i(TAG, "Go to $hyperText page.")
try {
// 特殊处理,hotspot热点,因为每个手机厂商跳转的action不一样。
if (p0.id == R.id.hyper_link_tip_hotspot) {
startHotspotActivity()
return
}
context.startActivity(Intent(action))
} catch (e: Exception) {
Log.i(TAG, "Go to $hyperText page fail.")
}
}
}
val startIndex = content.indexOf(hyperText)
if (startIndex == -1) {
return
}
val endIndex = startIndex + hyperText.length
spannableString.setSpan(span, startIndex, endIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
tipsView?.movementMethod = LinkMovementMethod.getInstance()
tipsView?.text = spannableString
tipsView?.highlightColor = Color.parseColor("#36969696");
}
可以看到其中有有一个特殊处理:开启热点,全网搜了一圈只能打开热点设置页面,而且每个手机还不一样。
// 热点设置页面处理
private fun startHotspotActivity() {
val intent = Intent()
intent.addCategory(Intent.CATEGORY_DEFAULT)
intent.action = "android.intent.action.MAIN"
val cn = ComponentName(
"com.android.settings",
// com.android.settings.Settings$TetherSettingsActivity // 来自网上
"com.android.settings.Settings\$WirelessSettingsActivity" // 华为 nova6 热点开关页面(亲测)
)
intent.component = cn
startActivity(intent)
}
这样我们就可以像开头那样,点击页面中高亮的文字就可以实现系统页面的跳转啦。以下是设置每个页面跳转的富文本具体设置:
// 蓝牙设置
setHyperLinkTips(
findViewById<TextView>(R.id.hyper_link_tip_bluetooth),
getString(R.string.hyper_link_tip),
getString(R.string.hyper_link_bluetooth),
Settings.ACTION_BLUETOOTH_SETTINGS,
this
)
// wifi
setHyperLinkTips(
findViewById<TextView>(R.id.hyper_link_tip_wifi),
getString(R.string.hyper_link_tip),
getString(R.string.hyper_link_wifi),
Settings.ACTION_WIFI_SETTINGS,
this
)
// 移动网络
setHyperLinkTips(
findViewById<TextView>(R.id.hyper_link_tip_wireless),
getString(R.string.hyper_link_tip),
getString(R.string.hyper_link_network),
Settings.ACTION_DATA_ROAMING_SETTINGS,
this
)
//个人热点
setHyperLinkTips(
findViewById<TextView>(R.id.hyper_link_tip_hotspot),
getString(R.string.hyper_link_tip),
getString(R.string.hyper_link_hotspot),
"com.android.settings/com.android.settings.SubSettings",
this
)
4 布局举例
5 总结
到这里就结束了,就可实现在你的使用出跳转到系统设置页面,进行设置了。
(如果错误,欢迎批评指正,请大佬轻喷)