adding bluetooth
This commit is contained in:
		@@ -1,6 +1,8 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    package="com.rookiedev.hexapod">
 | 
			
		||||
 | 
			
		||||
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
 | 
			
		||||
    <uses-permission android:name="android.permission.INTERNET" />
 | 
			
		||||
 | 
			
		||||
    <application
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,540 @@
 | 
			
		||||
package com.rookiedev.hexapod.network
 | 
			
		||||
 | 
			
		||||
import android.Manifest
 | 
			
		||||
import android.annotation.SuppressLint
 | 
			
		||||
import android.bluetooth.BluetoothAdapter
 | 
			
		||||
import android.bluetooth.BluetoothDevice
 | 
			
		||||
import android.bluetooth.BluetoothServerSocket
 | 
			
		||||
import android.bluetooth.BluetoothSocket
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.pm.PackageManager
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.os.Handler
 | 
			
		||||
import androidx.core.app.ActivityCompat
 | 
			
		||||
import java.io.IOException
 | 
			
		||||
import java.io.InputStream
 | 
			
		||||
import java.io.OutputStream
 | 
			
		||||
import java.util.*
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This class does all the work for setting up and managing Bluetooth
 | 
			
		||||
 * connections with other devices. It has a thread that listens for
 | 
			
		||||
 * incoming connections, a thread for connecting with a device, and a
 | 
			
		||||
 * thread for performing data transmissions when connected.
 | 
			
		||||
 */
 | 
			
		||||
class BluetoothChatService(context: Context?, handler: Handler) {
 | 
			
		||||
    // Member fields
 | 
			
		||||
    private val mAdapter: BluetoothAdapter
 | 
			
		||||
    private val mHandler: Handler
 | 
			
		||||
    private var mSecureAcceptThread: AcceptThread? = null
 | 
			
		||||
    private var mInsecureAcceptThread: AcceptThread? = null
 | 
			
		||||
    private var mConnectThread: ConnectThread? = null
 | 
			
		||||
    private var mConnectedThread: ConnectedThread? = null
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return the current connection state.
 | 
			
		||||
     */
 | 
			
		||||
    @get:Synchronized
 | 
			
		||||
    var mState: Int
 | 
			
		||||
        private set
 | 
			
		||||
    private var mNewState: Int
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Update UI title according to the current state of the chat connection
 | 
			
		||||
     */
 | 
			
		||||
    @Synchronized
 | 
			
		||||
    private fun updateUserInterfaceTitle() {
 | 
			
		||||
        mState = mState
 | 
			
		||||
//        Log.d(TAG, "updateUserInterfaceTitle() " + mNewState + " -> " + state)
 | 
			
		||||
        mNewState = mState
 | 
			
		||||
 | 
			
		||||
        // Give the new state to the Handler so the UI Activity can update
 | 
			
		||||
        mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, mNewState, -1).sendToTarget()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Start the chat service. Specifically start AcceptThread to begin a
 | 
			
		||||
     * session in listening (server) mode. Called by the Activity onResume()
 | 
			
		||||
     */
 | 
			
		||||
    @Synchronized
 | 
			
		||||
    fun start() {
 | 
			
		||||
//        Log.d(TAG, "start")
 | 
			
		||||
 | 
			
		||||
        // Cancel any thread attempting to make a connection
 | 
			
		||||
        if (mConnectThread != null) {
 | 
			
		||||
            mConnectThread!!.cancel()
 | 
			
		||||
            mConnectThread = null
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Cancel any thread currently running a connection
 | 
			
		||||
        if (mConnectedThread != null) {
 | 
			
		||||
            mConnectedThread!!.cancel()
 | 
			
		||||
            mConnectedThread = null
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Start the thread to listen on a BluetoothServerSocket
 | 
			
		||||
        if (mSecureAcceptThread == null) {
 | 
			
		||||
            mSecureAcceptThread = AcceptThread(true)
 | 
			
		||||
            mSecureAcceptThread!!.start()
 | 
			
		||||
        }
 | 
			
		||||
        if (mInsecureAcceptThread == null) {
 | 
			
		||||
            mInsecureAcceptThread = AcceptThread(false)
 | 
			
		||||
            mInsecureAcceptThread!!.start()
 | 
			
		||||
        }
 | 
			
		||||
        // Update UI title
 | 
			
		||||
        updateUserInterfaceTitle()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Start the ConnectThread to initiate a connection to a remote device.
 | 
			
		||||
     *
 | 
			
		||||
     * @param device The BluetoothDevice to connect
 | 
			
		||||
     * @param secure Socket Security type - Secure (true) , Insecure (false)
 | 
			
		||||
     */
 | 
			
		||||
    @Synchronized
 | 
			
		||||
    fun connect(device: BluetoothDevice, secure: Boolean) {
 | 
			
		||||
//        Log.d(TAG, "connect to: $device")
 | 
			
		||||
 | 
			
		||||
        // Cancel any thread attempting to make a connection
 | 
			
		||||
        if (mState == STATE_CONNECTING) {
 | 
			
		||||
            if (mConnectThread != null) {
 | 
			
		||||
                mConnectThread!!.cancel()
 | 
			
		||||
                mConnectThread = null
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Cancel any thread currently running a connection
 | 
			
		||||
        if (mConnectedThread != null) {
 | 
			
		||||
            mConnectedThread!!.cancel()
 | 
			
		||||
            mConnectedThread = null
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Start the thread to connect with the given device
 | 
			
		||||
        mConnectThread = ConnectThread(device, secure)
 | 
			
		||||
        mConnectThread!!.start()
 | 
			
		||||
        // Update UI title
 | 
			
		||||
        updateUserInterfaceTitle()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Start the ConnectedThread to begin managing a Bluetooth connection
 | 
			
		||||
     *
 | 
			
		||||
     * @param socket The BluetoothSocket on which the connection was made
 | 
			
		||||
     * @param device The BluetoothDevice that has been connected
 | 
			
		||||
     */
 | 
			
		||||
    @SuppressLint("MissingPermission")
 | 
			
		||||
    @Synchronized
 | 
			
		||||
    fun connected(socket: BluetoothSocket?, device: BluetoothDevice, socketType: String) {
 | 
			
		||||
//        Log.d(TAG, "connected, Socket Type:$socketType")
 | 
			
		||||
 | 
			
		||||
        // Cancel the thread that completed the connection
 | 
			
		||||
        if (mConnectThread != null) {
 | 
			
		||||
            mConnectThread!!.cancel()
 | 
			
		||||
            mConnectThread = null
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Cancel any thread currently running a connection
 | 
			
		||||
        if (mConnectedThread != null) {
 | 
			
		||||
            mConnectedThread!!.cancel()
 | 
			
		||||
            mConnectedThread = null
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Cancel the accept thread because we only want to connect to one device
 | 
			
		||||
        if (mSecureAcceptThread != null) {
 | 
			
		||||
            mSecureAcceptThread!!.cancel()
 | 
			
		||||
            mSecureAcceptThread = null
 | 
			
		||||
        }
 | 
			
		||||
        if (mInsecureAcceptThread != null) {
 | 
			
		||||
            mInsecureAcceptThread!!.cancel()
 | 
			
		||||
            mInsecureAcceptThread = null
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Start the thread to manage the connection and perform transmissions
 | 
			
		||||
        mConnectedThread = ConnectedThread(socket, socketType)
 | 
			
		||||
        mConnectedThread!!.start()
 | 
			
		||||
 | 
			
		||||
        // Send the name of the connected device back to the UI Activity
 | 
			
		||||
        val msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME)
 | 
			
		||||
        val bundle = Bundle()
 | 
			
		||||
        bundle.putString(Constants.DEVICE_NAME, device.name)
 | 
			
		||||
        msg.data = bundle
 | 
			
		||||
        mHandler.sendMessage(msg)
 | 
			
		||||
        // Update UI title
 | 
			
		||||
        updateUserInterfaceTitle()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Stop all threads
 | 
			
		||||
     */
 | 
			
		||||
    @Synchronized
 | 
			
		||||
    fun stop() {
 | 
			
		||||
//        Log.d(TAG, "stop")
 | 
			
		||||
        if (mConnectThread != null) {
 | 
			
		||||
            mConnectThread!!.cancel()
 | 
			
		||||
            mConnectThread = null
 | 
			
		||||
        }
 | 
			
		||||
        if (mConnectedThread != null) {
 | 
			
		||||
            mConnectedThread!!.cancel()
 | 
			
		||||
            mConnectedThread = null
 | 
			
		||||
        }
 | 
			
		||||
        if (mSecureAcceptThread != null) {
 | 
			
		||||
            mSecureAcceptThread!!.cancel()
 | 
			
		||||
            mSecureAcceptThread = null
 | 
			
		||||
        }
 | 
			
		||||
        if (mInsecureAcceptThread != null) {
 | 
			
		||||
            mInsecureAcceptThread!!.cancel()
 | 
			
		||||
            mInsecureAcceptThread = null
 | 
			
		||||
        }
 | 
			
		||||
        mState = STATE_NONE
 | 
			
		||||
        // Update UI title
 | 
			
		||||
        updateUserInterfaceTitle()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Write to the ConnectedThread in an unsynchronized manner
 | 
			
		||||
     *
 | 
			
		||||
     * @param out The bytes to write
 | 
			
		||||
     * @see ConnectedThread.write
 | 
			
		||||
     */
 | 
			
		||||
    fun write(out: ByteArray?) {
 | 
			
		||||
        // Create temporary object
 | 
			
		||||
        var r: ConnectedThread?
 | 
			
		||||
        // Synchronize a copy of the ConnectedThread
 | 
			
		||||
        synchronized(this) {
 | 
			
		||||
            if (mState != STATE_CONNECTED) return
 | 
			
		||||
            r = mConnectedThread
 | 
			
		||||
        }
 | 
			
		||||
        // Perform the write unsynchronized
 | 
			
		||||
        r!!.write(out)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Indicate that the connection attempt failed and notify the UI Activity.
 | 
			
		||||
     */
 | 
			
		||||
    private fun connectionFailed() {
 | 
			
		||||
        // Send a failure message back to the Activity
 | 
			
		||||
        val msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST)
 | 
			
		||||
        val bundle = Bundle()
 | 
			
		||||
        bundle.putString(Constants.TOAST, "Unable to connect device")
 | 
			
		||||
        msg.data = bundle
 | 
			
		||||
        mHandler.sendMessage(msg)
 | 
			
		||||
        mState = STATE_NONE
 | 
			
		||||
        // Update UI title
 | 
			
		||||
        updateUserInterfaceTitle()
 | 
			
		||||
 | 
			
		||||
        // Start the service over to restart listening mode
 | 
			
		||||
        start()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Indicate that the connection was lost and notify the UI Activity.
 | 
			
		||||
     */
 | 
			
		||||
    private fun connectionLost() {
 | 
			
		||||
        // Send a failure message back to the Activity
 | 
			
		||||
        val msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST)
 | 
			
		||||
        val bundle = Bundle()
 | 
			
		||||
        bundle.putString(Constants.TOAST, "Device connection was lost")
 | 
			
		||||
        msg.data = bundle
 | 
			
		||||
        mHandler.sendMessage(msg)
 | 
			
		||||
        mState = STATE_NONE
 | 
			
		||||
        // Update UI title
 | 
			
		||||
        updateUserInterfaceTitle()
 | 
			
		||||
 | 
			
		||||
        // Start the service over to restart listening mode
 | 
			
		||||
        start()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This thread runs while listening for incoming connections. It behaves
 | 
			
		||||
     * like a server-side client. It runs until a connection is accepted
 | 
			
		||||
     * (or until cancelled).
 | 
			
		||||
     */
 | 
			
		||||
    @SuppressLint("MissingPermission")
 | 
			
		||||
    private inner class AcceptThread(secure: Boolean) : Thread() {
 | 
			
		||||
        // The local server socket
 | 
			
		||||
        private val mmServerSocket: BluetoothServerSocket?
 | 
			
		||||
        private val mSocketType: String
 | 
			
		||||
        override fun run() {
 | 
			
		||||
//            Log.d(
 | 
			
		||||
//                TAG, "Socket Type: " + mSocketType +
 | 
			
		||||
//                        "BEGIN mAcceptThread" + this
 | 
			
		||||
//            )
 | 
			
		||||
            name = "AcceptThread$mSocketType"
 | 
			
		||||
            var socket: BluetoothSocket?
 | 
			
		||||
 | 
			
		||||
            // Listen to the server socket if we're not connected
 | 
			
		||||
            while (mState != STATE_CONNECTED) {
 | 
			
		||||
                socket = try {
 | 
			
		||||
                    // This is a blocking call and will only return on a
 | 
			
		||||
                    // successful connection or an exception
 | 
			
		||||
                    mmServerSocket!!.accept()
 | 
			
		||||
                } catch (e: IOException) {
 | 
			
		||||
//                    Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e)
 | 
			
		||||
                    break
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // If a connection was accepted
 | 
			
		||||
                if (socket != null) {
 | 
			
		||||
                    synchronized(this@BluetoothChatService) {
 | 
			
		||||
                        when (mState) {
 | 
			
		||||
                            STATE_LISTEN, STATE_CONNECTING ->                                 // Situation normal. Start the connected thread.
 | 
			
		||||
                                connected(
 | 
			
		||||
                                    socket, socket.remoteDevice,
 | 
			
		||||
                                    mSocketType
 | 
			
		||||
                                )
 | 
			
		||||
                            STATE_NONE, STATE_CONNECTED ->                                 // Either not ready or already connected. Terminate new socket.
 | 
			
		||||
                                try {
 | 
			
		||||
                                    socket.close()
 | 
			
		||||
                                } catch (e: IOException) {
 | 
			
		||||
//                                    Log.e(
 | 
			
		||||
//                                        TAG,
 | 
			
		||||
//                                        "Could not close unwanted socket",
 | 
			
		||||
//                                        e
 | 
			
		||||
//                                    )
 | 
			
		||||
                                }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
//            Log.i(
 | 
			
		||||
//                TAG,
 | 
			
		||||
//                "END mAcceptThread, socket Type: $mSocketType"
 | 
			
		||||
//            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun cancel() {
 | 
			
		||||
//            Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this)
 | 
			
		||||
            try {
 | 
			
		||||
                mmServerSocket!!.close()
 | 
			
		||||
            } catch (e: IOException) {
 | 
			
		||||
//                Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        init {
 | 
			
		||||
            var tmp: BluetoothServerSocket? = null
 | 
			
		||||
            mSocketType = if (secure) "Secure" else "Insecure"
 | 
			
		||||
 | 
			
		||||
            // Create a new listening server socket
 | 
			
		||||
            try {
 | 
			
		||||
                tmp = if (secure) {
 | 
			
		||||
                    mAdapter.listenUsingRfcommWithServiceRecord(
 | 
			
		||||
                        NAME_SECURE,
 | 
			
		||||
                        MY_UUID_SECURE
 | 
			
		||||
                    )
 | 
			
		||||
                } else {
 | 
			
		||||
                    mAdapter.listenUsingInsecureRfcommWithServiceRecord(
 | 
			
		||||
                        NAME_INSECURE, MY_UUID_INSECURE
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            } catch (e: IOException) {
 | 
			
		||||
//                Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e)
 | 
			
		||||
            }
 | 
			
		||||
            mmServerSocket = tmp
 | 
			
		||||
            mState = STATE_LISTEN
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This thread runs while attempting to make an outgoing connection
 | 
			
		||||
     * with a device. It runs straight through; the connection either
 | 
			
		||||
     * succeeds or fails.
 | 
			
		||||
     */
 | 
			
		||||
    @SuppressLint("MissingPermission")
 | 
			
		||||
    private inner class ConnectThread(private val mmDevice: BluetoothDevice, secure: Boolean) :
 | 
			
		||||
        Thread() {
 | 
			
		||||
        private val mmSocket: BluetoothSocket?
 | 
			
		||||
        private val mSocketType: String
 | 
			
		||||
        override fun run() {
 | 
			
		||||
//            Log.i(
 | 
			
		||||
//                TAG,
 | 
			
		||||
//                "BEGIN mConnectThread SocketType:$mSocketType"
 | 
			
		||||
//            )
 | 
			
		||||
            name = "ConnectThread$mSocketType"
 | 
			
		||||
 | 
			
		||||
            // Always cancel discovery because it will slow down a connection
 | 
			
		||||
            mAdapter.cancelDiscovery()
 | 
			
		||||
 | 
			
		||||
            // Make a connection to the BluetoothSocket
 | 
			
		||||
            try {
 | 
			
		||||
                // This is a blocking call and will only return on a
 | 
			
		||||
                // successful connection or an exception
 | 
			
		||||
                mmSocket!!.connect()
 | 
			
		||||
            } catch (e: IOException) {
 | 
			
		||||
                // Close the socket
 | 
			
		||||
                try {
 | 
			
		||||
                    mmSocket!!.close()
 | 
			
		||||
                } catch (e2: IOException) {
 | 
			
		||||
//                    Log.e(
 | 
			
		||||
//                        TAG, "unable to close() " + mSocketType +
 | 
			
		||||
//                                " socket during connection failure", e2
 | 
			
		||||
//                    )
 | 
			
		||||
                }
 | 
			
		||||
                connectionFailed()
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Reset the ConnectThread because we're done
 | 
			
		||||
            synchronized(this@BluetoothChatService) { mConnectThread = null }
 | 
			
		||||
 | 
			
		||||
            // Start the connected thread
 | 
			
		||||
            connected(mmSocket, mmDevice, mSocketType)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun cancel() {
 | 
			
		||||
            try {
 | 
			
		||||
                mmSocket!!.close()
 | 
			
		||||
            } catch (e: IOException) {
 | 
			
		||||
//                Log.e(
 | 
			
		||||
//                    TAG,
 | 
			
		||||
//                    "close() of connect $mSocketType socket failed", e
 | 
			
		||||
//                )
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        init {
 | 
			
		||||
            var tmp: BluetoothSocket? = null
 | 
			
		||||
            mSocketType = if (secure) "Secure" else "Insecure"
 | 
			
		||||
 | 
			
		||||
            // Get a BluetoothSocket for a connection with the
 | 
			
		||||
            // given BluetoothDevice
 | 
			
		||||
            try {
 | 
			
		||||
                tmp = if (secure) {
 | 
			
		||||
//                    if (ActivityCompat.checkSelfPermission(
 | 
			
		||||
//                            this,
 | 
			
		||||
//                            Manifest.permission.BLUETOOTH_CONNECT
 | 
			
		||||
//                        ) != PackageManager.PERMISSION_GRANTED
 | 
			
		||||
//                    ) {
 | 
			
		||||
//                        // TODO: Consider calling
 | 
			
		||||
//                        //    ActivityCompat#requestPermissions
 | 
			
		||||
//                        // here to request the missing permissions, and then overriding
 | 
			
		||||
//                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
 | 
			
		||||
//                        //                                          int[] grantResults)
 | 
			
		||||
//                        // to handle the case where the user grants the permission. See the documentation
 | 
			
		||||
//                        // for ActivityCompat#requestPermissions for more details.
 | 
			
		||||
//                        return
 | 
			
		||||
//                    }
 | 
			
		||||
                    mmDevice.createRfcommSocketToServiceRecord(
 | 
			
		||||
                        MY_UUID_SECURE
 | 
			
		||||
                    )
 | 
			
		||||
                } else {
 | 
			
		||||
                    mmDevice.createInsecureRfcommSocketToServiceRecord(
 | 
			
		||||
                        MY_UUID_INSECURE
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            } catch (e: IOException) {
 | 
			
		||||
//                Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e)
 | 
			
		||||
            }
 | 
			
		||||
            mmSocket = tmp
 | 
			
		||||
            mState = STATE_CONNECTING
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This thread runs during a connection with a remote device.
 | 
			
		||||
     * It handles all incoming and outgoing transmissions.
 | 
			
		||||
     */
 | 
			
		||||
    private inner class ConnectedThread(socket: BluetoothSocket?, socketType: String) :
 | 
			
		||||
        Thread() {
 | 
			
		||||
        private val mmSocket: BluetoothSocket?
 | 
			
		||||
        private val mmInStream: InputStream?
 | 
			
		||||
        private val mmOutStream: OutputStream?
 | 
			
		||||
        override fun run() {
 | 
			
		||||
//            Log.i(TAG, "BEGIN mConnectedThread")
 | 
			
		||||
            val buffer = ByteArray(1024)
 | 
			
		||||
            var bytes: Int
 | 
			
		||||
 | 
			
		||||
            // Keep listening to the InputStream while connected
 | 
			
		||||
            while (mState == STATE_CONNECTED) {
 | 
			
		||||
                try {
 | 
			
		||||
                    // Read from the InputStream
 | 
			
		||||
                    bytes = mmInStream!!.read(buffer)
 | 
			
		||||
 | 
			
		||||
                    // Send the obtained bytes to the UI Activity
 | 
			
		||||
                    mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
 | 
			
		||||
                        .sendToTarget()
 | 
			
		||||
                } catch (e: IOException) {
 | 
			
		||||
//                    Log.e(TAG, "disconnected", e)
 | 
			
		||||
                    connectionLost()
 | 
			
		||||
                    break
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Write to the connected OutStream.
 | 
			
		||||
         *
 | 
			
		||||
         * @param buffer The bytes to write
 | 
			
		||||
         */
 | 
			
		||||
        fun write(buffer: ByteArray?) {
 | 
			
		||||
            try {
 | 
			
		||||
                mmOutStream!!.write(buffer)
 | 
			
		||||
 | 
			
		||||
                // Share the sent message back to the UI Activity
 | 
			
		||||
                mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer)
 | 
			
		||||
                    .sendToTarget()
 | 
			
		||||
            } catch (e: IOException) {
 | 
			
		||||
//                Log.e(TAG, "Exception during write", e)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun cancel() {
 | 
			
		||||
            try {
 | 
			
		||||
                mmSocket!!.close()
 | 
			
		||||
            } catch (e: IOException) {
 | 
			
		||||
//                Log.e(TAG, "close() of connect socket failed", e)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        init {
 | 
			
		||||
//            Log.d(TAG, "create ConnectedThread: $socketType")
 | 
			
		||||
            mmSocket = socket
 | 
			
		||||
            var tmpIn: InputStream? = null
 | 
			
		||||
            var tmpOut: OutputStream? = null
 | 
			
		||||
 | 
			
		||||
            // Get the BluetoothSocket input and output streams
 | 
			
		||||
            try {
 | 
			
		||||
                tmpIn = socket!!.inputStream
 | 
			
		||||
                tmpOut = socket.outputStream
 | 
			
		||||
            } catch (e: IOException) {
 | 
			
		||||
//                Log.e(TAG, "temp sockets not created", e)
 | 
			
		||||
            }
 | 
			
		||||
            mmInStream = tmpIn
 | 
			
		||||
            mmOutStream = tmpOut
 | 
			
		||||
            mState = STATE_CONNECTED
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        // Debugging
 | 
			
		||||
        private const val TAG = "BluetoothChatService"
 | 
			
		||||
 | 
			
		||||
        // Name for the SDP record when creating server socket
 | 
			
		||||
        private const val NAME_SECURE = "BluetoothChatSecure"
 | 
			
		||||
        private const val NAME_INSECURE = "BluetoothChatInsecure"
 | 
			
		||||
 | 
			
		||||
        // Unique UUID for this application
 | 
			
		||||
        private val MY_UUID_SECURE = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66")
 | 
			
		||||
        private val MY_UUID_INSECURE = UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66")
 | 
			
		||||
 | 
			
		||||
        // Constants that indicate the current connection state
 | 
			
		||||
        const val STATE_NONE = 0 // we're doing nothing
 | 
			
		||||
        const val STATE_LISTEN = 1 // now listening for incoming connections
 | 
			
		||||
        const val STATE_CONNECTING = 2 // now initiating an outgoing connection
 | 
			
		||||
        const val STATE_CONNECTED = 3 // now connected to a remote device
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor. Prepares a new BluetoothChat session.
 | 
			
		||||
     *
 | 
			
		||||
     * @param context The UI Activity Context
 | 
			
		||||
     * @param handler A Handler to send messages back to the UI Activity
 | 
			
		||||
     */
 | 
			
		||||
    init {
 | 
			
		||||
        mAdapter = BluetoothAdapter.getDefaultAdapter()
 | 
			
		||||
        mState = STATE_NONE
 | 
			
		||||
        mNewState = mState
 | 
			
		||||
        mHandler = handler
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,19 @@
 | 
			
		||||
package com.rookiedev.hexapod.network
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defines several constants used between [BluetoothChatService] and the UI.
 | 
			
		||||
 */
 | 
			
		||||
interface Constants {
 | 
			
		||||
    companion object {
 | 
			
		||||
        // Message types sent from the BluetoothChatService Handler
 | 
			
		||||
        const val MESSAGE_STATE_CHANGE = 1
 | 
			
		||||
        const val MESSAGE_READ = 2
 | 
			
		||||
        const val MESSAGE_WRITE = 3
 | 
			
		||||
        const val MESSAGE_DEVICE_NAME = 4
 | 
			
		||||
        const val MESSAGE_TOAST = 5
 | 
			
		||||
 | 
			
		||||
        // Key names received from the BluetoothChatService Handler
 | 
			
		||||
        const val DEVICE_NAME = "device_name"
 | 
			
		||||
        const val TOAST = "toast"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user