I'm using a messenger to bind to a service in order to get a two-way communication between my activity and my service.
My service is running in background and runs a bluetooth communication. I'm already able to send data to the BluetoothService, which can send it trough Bluetooth. I can receive data Through Bluetooth and print it the terminal. Now I want to send back this data to the UI. I've tried to implement a counter when reaches 10 it sends back the information from my BluetoothService to my TestActivity which is working quite well.
I can't figure out how to do that, if someone can help it would be a great pleasure.
TestActivity :
class TestActivity : AppCompatActivity() {
/** Flag indicating whether we have called bind on the service. */
private var bound: Boolean = false
//////
// Messenger on the server
private var mService: Messenger? = null
// Messenger on the client
lateinit var mMessenger: Messenger
// Signal sent to the server
private val SIG_SEND_PLUS = 0
private val SIG_GET_UPDATE = 1
/**
* Class for interacting with the main interface of the service.
*/
private val mConnection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mService = Messenger(service)
bound = true
}
override fun onServiceDisconnected(className: ComponentName) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null
bound = false
}
}
inner class ClientHandler : Handler() {
override fun handleMessage(msg: Message) {
when (msg.what) {
SIG_GET_UPDATE ->
//changeTextView()
Toast.makeText(applicationContext, "Upgrade", Toast.LENGTH_SHORT).show()
}
}
}
private fun sendMsg(stringToSend: String) {
if (!bound) return
// Create and send a message to the service, using a supported 'what' value
val msg: Message = Message.obtain(null, SEND_MSG, 0, 0, stringToSend)
try {
mService?.send(msg)
} catch (e: RemoteException) {
e.printStackTrace()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
buttonSend.setOnClickListener {
sendMsg(editTextTextPersonName.text.toString())
//sayHello()
}
buttonStart.setOnClickListener {
mMessenger = Messenger(ClientHandler())
// Binding service
bindService(
Intent(this, BluetoothService::class.java),
mConnection,
Context.BIND_AUTO_CREATE
)
}
//+1
button.setOnClickListener {
if (mService != null) {
try {
val message = Message.obtain(null, SIG_SEND_PLUS)
val bundle = Bundle()
bundle.putInt("value", 1)
message.data = bundle
message.replyTo = mMessenger
mService!!.send(message)
} catch (e: RemoteException) {
e.printStackTrace()
}
}
}
}
override fun onStart() {
super.onStart()
}
override fun onStop() {
super.onStop()
// Unbind from the service
if (bound) {
unbindService(mConnection)
bound = false
}
}
}
BluetoothService :
class BluetoothService : Service(){
companion object {
var m_UUID: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
private const val MAC_ADDRESS = "00:0E:EA:CF:53:B5"
var m_bluetoothSocket: BluetoothSocket? = null
const val TAG = "Tag"
// Defines several constants used when transmitting messages between the
// service and the UI.
private const val SIG_GET_PLUS = 0
private const val SIG_SEND_UPDATE = 1
private const val SEND_MSG = 2
lateinit var m_bluetoothAdapter: BluetoothAdapter
var m_isConnected: Boolean = false
}
lateinit var messenger: Messenger
private var sum = 0
lateinit var mClient: Messenger
inner class ServiceHandler : Handler() {
override fun handleMessage(msg: Message) {
// Process the message
when (msg.what) {
SEND_MSG ->
ConnectedThread(m_bluetoothSocket!!).write(msg.obj.toString())
SIG_GET_PLUS -> {
val bundle = msg.data
sum += bundle.getInt("value")
Toast.makeText(applicationContext, sum.toString() + "", Toast.LENGTH_SHORT)
.show()
// =10 Send a message to the client
mClient = msg.replyTo
if (null == mClient) {
return
}
else if (sum == 10) {
val message =
Message.obtain(null, SIG_SEND_UPDATE)
try {
mClient.send(message)
} catch (e: RemoteException) {
e.printStackTrace()
}
}
}
else -> {
}
}
}
}
/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
override fun onBind(intent: Intent): IBinder? {
Toast.makeText(applicationContext, "binding", Toast.LENGTH_SHORT).show()
messenger = Messenger(ServiceHandler())
//Start bluetooth connection
ConnectThread().start()
return messenger.binder
}
private class ConnectThread() : Thread() {
private var connectSuccess: Boolean = true
public override fun run() {
try {
if (m_bluetoothSocket == null || !m_isConnected) {
Companion.m_bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
val device: BluetoothDevice = Companion.m_bluetoothAdapter.getRemoteDevice(MAC_ADDRESS)
m_bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(m_UUID)
BluetoothAdapter.getDefaultAdapter().cancelDiscovery()
m_bluetoothSocket!!.connect()
ConnectedThread(m_bluetoothSocket!!).start()
}
} catch (e: IOException) {
connectSuccess = false
e.printStackTrace()
}
}
// Closes the client socket and causes the thread to finish.
fun cancel() {
if(ControlActivity.m_bluetoothSocket != null){
try {
ControlActivity.m_bluetoothSocket!!.close()
ControlActivity.m_bluetoothSocket = null
ControlActivity.m_isConnected = false
} catch (e : IOException){
e.printStackTrace()
}
}
}
}
private class ConnectedThread(private val mmSocket: BluetoothSocket) : Thread() {
private val mmInStream: InputStream = mmSocket.inputStream
private val mmOutStream: OutputStream = mmSocket.outputStream
private val mmBuffer: ByteArray = ByteArray(1024) // mmBuffer store for the stream
override fun run() {
var numBytes: Int // bytes returned from read()
// Keep listening to the InputStream until an exception occurs.
while (true) {
// Read from the InputStream.
if (mmInStream.available()>0) {
numBytes = try {
mmInStream.read(mmBuffer)
} catch (e: IOException) {
Log.d(TAG, "Input stream was disconnected", e)
break
}
val readMessage = String(mmBuffer, 0, numBytes)
println(readMessage)
}
else {
SystemClock.sleep(100)
}
}
}
// Call this from the main activity to send data to the remote device.
fun write(string : String) {
try {
mmOutStream.write(string.toByteArray())
} catch (e: IOException) {
Log.e(TAG, "Error occurred when sending data", e)
return
}
}
// Call this method from the main activity to shut down the connection.
fun cancel() {
try {
mmSocket.close()
} catch (e: IOException) {
Log.e(TAG, "Could not close the connect socket", e)
}
}
}
}
question from:
https://stackoverflow.com/questions/65647443/accessing-handler-from-thread-in-service 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…