我目前正在使用 Kotlin 编写的移动应用程序,该应用程序使用户能够通过蓝牙远程控制机器人。我有 MainActivity 类,该类托管 3 个片段:定义蓝牙接口的 FragmentMain、FragmentCamera 和 FragmentDisplayText。 这是我的寻呼机适配器类:
class MyPagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) {
override fun getItem(position: Int): Fragment {
return when (position) {
0 -> FragmentMain()
1 -> FragmentCamera()
2 -> FragmentDisplayText()
else -> FragmentMain()
}
}
override fun getCount(): Int {
return 3
}
}
我的问题是,当我在屏幕之间滑动并到达第三个屏幕时,蓝牙连接关闭。我不知道为什么会这样。
这是我的 MainActivity,我在其中为 ViewPager 设置适配器:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val tabLayout = findViewById<TabLayout>(R.id.tabLayout)
val viewPager = findViewById<ViewPager>(R.id.viewPager)
val adapter = MyPagerAdapter(supportFragmentManager)
viewPager.adapter = adapter
tabLayout.setupWithViewPager(viewPager)
}
}
这就是我的蓝牙接口的工作原理:
/* ============================ Thread to Create Bluetooth Connection =================================== */
inner class CreateConnectThread(private val activity: Activity, private val context: Context, private val bluetoothAdapter: BluetoothAdapter, private val address: String) :
Thread() {
init {
val bluetoothDevice = bluetoothAdapter.getRemoteDevice(address)
var tmp: BluetoothSocket? = null
var uuid: UUID? = null
if (ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED) {
uuid = bluetoothDevice.uuids[0].uuid
} else {
ActivityCompat.requestPermissions(
activity,
arrayOf(
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.BLUETOOTH_SCAN
), PERMISSION_REQUEST_CODE
)
}
try {
tmp = bluetoothDevice.createInsecureRfcommSocketToServiceRecord(uuid)
} catch (e: IOException) {
Log.e(TAG, "Socket's create() method failed", e)
}
if (tmp != null) {
mmSocket = tmp
}
}
override fun run() {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED) {
bluetoothAdapter.cancelDiscovery()
try {
mmSocket.connect()
Log.e("Status", "Device connected")
handler.obtainMessage(CONNECTING_STATUS, 1, -1).sendToTarget()
} catch (connectException: IOException) {
try {
mmSocket.close()
Log.e("Status", "Cannot connect to device")
handler.obtainMessage(CONNECTING_STATUS, -1, -1).sendToTarget()
} catch (closeException: IOException) {
Log.e(TAG, "Could not close the client socket", closeException)
}
return
}
} else {
ActivityCompat.requestPermissions(
activity,
arrayOf(
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.BLUETOOTH_SCAN
), PERMISSION_REQUEST_CODE
)
}
bluetoothAdapter.cancelDiscovery()
connectedThread = ConnectedThread(mmSocket)
connectedThread.start()
}
fun cancel() {
try {
mmSocket.close()
} catch (e: IOException) {
Log.e(TAG, "Could not close the client socket", e)
}
}
}
/* =============================== Thread for Data Transfer =========================================== */
inner class ConnectedThread(socket: BluetoothSocket) : Thread() {
private val mmSocket: BluetoothSocket = socket
private val mmInStream: InputStream
private val mmOutStream: OutputStream
init {
var tmpIn: InputStream? = null
var tmpOut: OutputStream? = null
try {
tmpIn = socket.inputStream
tmpOut = socket.outputStream
} catch (_: IOException) {
}
mmInStream = tmpIn!!
mmOutStream = tmpOut!!
}
override fun run() {
val buffer = ByteArray(1024)
var bytes = 0
while (true) {
try {
buffer[bytes] = mmInStream.read().toByte()
var readMessage: String
if (buffer[bytes] == '\n'.toByte()) {
readMessage = String(buffer, 0, bytes)
Log.e("Arduino Message", readMessage)
handler.obtainMessage(MESSAGE_READ, readMessage).sendToTarget()
bytes = 0
} else {
bytes++
}
} catch (e: IOException) {
e.printStackTrace()
break
}
}
}
fun write(input: String) {
val bytes = input.toByteArray()
try {
mmOutStream.write(bytes)
} catch (e: IOException) {
Log.e("Send Error", "Unable to send message", e)
}
}
fun cancel() {
try {
mmSocket.close()
} catch (e: IOException) {
}
}
}
有人知道可能做错了什么吗?预先感谢您的帮助!
我尝试交换 FragmentCamera 和 FragmentDisplayText 但结果是相同的,蓝牙连接已建立,当我滑动到第二个屏幕时它可以工作,当我滑动到最后一个屏幕时它崩溃。
我认为发生这种情况可能是因为您的蓝牙活动连接到屏幕,因此当您从该屏幕导航时,蓝牙功能会终止。解决方案是在服务中管理蓝牙活动。
一些参考:-