蓝牙服务可在多种活动中运行

时间:2019-03-19 16:22:51

标签: android service bluetooth

在两个设备之间交换数据时,在多个活动上实现蓝牙服务时,需要哪种服务?当我在活动之间切换时,连接丢失了。研究使我在本地服务和远程Messenger服务之间进行选择。

我的项目需要通过蓝牙在两个android设备之间交换传感器数据。我一直找不到能够实现此目的的项目,只能找到一个Messenger类型的功能。

如果有人完成了类似的项目,则将非常感谢您提出实施建议。

非常感谢。

到目前为止,这是我的主要活动和聊天服务代码:

public class MainActivity extends AppCompatActivity {

public MainActivity() {
}

private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
public static final int REQUEST_ENABLE_BT = 3;

Button chatBtn, accelerometerBtn, proximityBtn;
CheckBox pairedCheckbox;

public BluetoothAdapter bluetoothAdapter;

public ChatService chatService;

public String connectedDeviceName = null;

// Constants that indicate the current connection state
private static final int STATE_NONE = 0;       // we're doing nothing
private static final int STATE_LISTEN = 1;     // now listening for incoming connections
private static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
private static final int STATE_CONNECTED = 3;  // now connected to a remote device

public StringBuffer messageOutBuffer;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    chatBtn = (Button)findViewById(R.id.chat_btn);
    accelerometerBtn = (Button)findViewById(R.id.accelerometer_btn);
    accelerometerBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            /*if (pairedCheckbox.isChecked()==true){
                openActivityAudio();
            } else {
                Activity activity = MainActivity.this;
                Toast toast = Toast.makeText(activity,"Need to pair device", Toast.LENGTH_SHORT);
                toast.show();
            }*/
            openActivityAccelerometer();
        }
    });
    proximityBtn = (Button)findViewById(R.id.proximity_btn);
    proximityBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            /*if (pairedCheckbox.isChecked()==true){
                openActivityProximity();
            } else {
                Activity activity = MainActivity.this;
                Toast toast = Toast.makeText(activity,"Need to pair device", Toast.LENGTH_SHORT);
                toast.show();
            }*/
            openActivityProximity();
        }
    });

    pairedCheckbox = (CheckBox)findViewById(R.id.paired_checkbox);

    // Get local Bluetooth adapter
    bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    // If the adapter is null, then Bluetooth is not supported
    if (bluetoothAdapter == null){
        Activity activity = MainActivity.this;
        Toast.makeText(activity, "Bluetooth is not available", Toast.LENGTH_LONG).show();
        activity.finish();
    }

    // enable bt adapter here
    if (!bluetoothAdapter.isEnabled()){
        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.options_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Intent serverIntent = null;
    switch (item.getItemId()) {
        case R.id.secure_connect_scan:
            serverIntent = new Intent(MainActivity.this, ConnectionActivity.class);
            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
            return true;
        case R.id.insecure_connect_scan:
            serverIntent = new Intent(MainActivity.this, ConnectionActivity.class);
            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
            return true;
        case R.id.discoverable:
            ensureDiscoverable();
            return true;
    }
    return false;
}

@Override
public void onStart() {
    super.onStart();
    if (chatService == null){
        //Toast.makeText(this, "setting up chat", Toast.LENGTH_SHORT).show();
        setupChat();
    }
}

@Override
public void onStop() {
    super.onStop();
    if (chatService != null) {
        chatService.stop();
    }

}

@Override
public void onResume() {
    super.onResume();

    // Performing this check in onResume() covers the case in which BT was
    // not enabled during onStart(), so we were paused to enable it...
    // onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
    if (chatService != null) {
        // Only if the state is STATE_NONE, do we know that we haven't started already
        if (chatService.getState() == ChatService.STATE_NONE) {
            // Start the Bluetooth chat services
            chatService.start();
        }
    }
}

private void setupChat() {
    // Initialize the ChatService to perform bluetooth connections
    chatService = new ChatService(this, chatHandler);

    // Initialize the buffer for outgoing messages
    messageOutBuffer = new StringBuffer("");
}

protected final Handler chatHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        MainActivity activity = MainActivity.this;
        switch (msg.what) {
            case Constants.MESSAGE_STATE_CHANGE:
                switch (msg.arg1) {
                    case STATE_CONNECTED:
                        setStatus(getString(R.string.title_connected_to, connectedDeviceName));
                        pairedCheckbox.setChecked(true);
                        break;
                    case STATE_CONNECTING:
                        setStatus(R.string.title_connecting);
                        pairedCheckbox.setChecked(false);
                        break;
                    case STATE_LISTEN:
                    case STATE_NONE:
                        setStatus(R.string.title_not_connected);
                        pairedCheckbox.setChecked(false);
                        break;
                }
                break;
            case Constants.MESSAGE_DEVICE_NAME:
                // save the connected device's name
                connectedDeviceName = msg.getData().getString(Constants.DEVICE_NAME);
                if (null != activity) {
                    Toast.makeText(activity, "Connected to " + connectedDeviceName, Toast.LENGTH_SHORT).show();
                }
                break;
            case Constants.MESSAGE_READ:
                byte[] readBuf = (byte[]) msg.obj;
                // construct a string from the valid bytes in the buffer
                String readMessage = new String(readBuf, 0, msg.arg1);
                Toast.makeText(MainActivity.this, readMessage, Toast.LENGTH_SHORT).show();
                break;
            case Constants.MESSAGE_TOAST:
                if (null != activity) {
                    Toast.makeText(activity, msg.getData().getString(Constants.TOAST), Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }
};

private void setStatus(int resId) {
    MainActivity activity = MainActivity.this;
    if (null == activity) {
        return;
    }
    final ActionBar actionBar = this.getActionBar();
    if (null == actionBar) {
        return;
    }
    actionBar.setSubtitle(resId);
}

private void setStatus(CharSequence subTitle) {
    MainActivity activity = MainActivity.this;
    if (null == activity) {
        return;
    }
    final ActionBar actionBar = activity.getActionBar();
    if (null == actionBar) {
        return;
    }
    actionBar.setSubtitle(subTitle);
}


private void ensureDiscoverable() {
    if (bluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){
        Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
        discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
        startActivity(discoverableIntent);
    }
}


public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case REQUEST_CONNECT_DEVICE_SECURE:
            // When DeviceListActivity returns with a device to connect
            if (resultCode == Activity.RESULT_OK) {
                connectDevice(data, true);
            }
            break;
        case REQUEST_CONNECT_DEVICE_INSECURE:
            // When DeviceListActivity returns with a device to connect
            if (resultCode == Activity.RESULT_OK) {
                connectDevice(data, false);
            }
            break;
        case REQUEST_ENABLE_BT:
            // When the request to enable Bluetooth returns
            if (resultCode == Activity.RESULT_CANCELED) {
                // User did not enable Bluetooth or an error occurred
                Toast.makeText(MainActivity.this, R.string.bt_not_enabled_leaving,
                        Toast.LENGTH_SHORT).show();
                MainActivity.this.finish();
            }
    }
}

private void connectDevice(Intent data, boolean secure) {
    // Get the device MAC address
    String address = data.getExtras().getString(ConnectionActivity.EXTRA_DEVICE_ADDRESS);
    // Get the BluetoothDevice object
    BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
    // Connect device
    chatService.connect(device, secure);
}


public void openActivityProximity(){
    Intent intent = new Intent(this, ProximityActivity.class);
    startActivity(intent);

}

public void openActivityAccelerometer(){
    Intent intent = new Intent(this, AccelerometerActivity.class);
    startActivity(intent);
}

}

聊天服务:

public class ChatService {

// Name for the SDP record when creating server socket
private static final String NAME_SECURE = "BluetoothChatSecure";
private static final String NAME_INSECURE = "BluetoothChatInsecure";

// Unique UUID for this application
private static final UUID MY_UUID_SECURE   = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
private static final UUID MY_UUID_INSECURE = UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");

// Member fields
private final BluetoothAdapter adapter;
private final Handler chatHandler;
private AcceptThread secureAcceptThread;
private AcceptThread insecureAcceptThread;
private ConnectThread connectThread;
private ConnectedThread connectedThread;
private int state;
private int newState;

// Constants that indicate the current connection state
public static final int STATE_NONE = 0;       // we're doing nothing
public static final int STATE_LISTEN = 1;     // now listening for incoming connections
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3;  // now connected to a remote device

public ChatService(Context context, Handler handler){
    adapter = BluetoothAdapter.getDefaultAdapter();
    state = STATE_NONE;
    newState = state;
    chatHandler = handler;
}

private synchronized void updateUserInterfaceTitle() {
    state = getState();
    newState = state;

    // Give the new state to the Handler so the UI Activity can update
    chatHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, newState, -1).sendToTarget();
}

public synchronized int getState() {
    return state;
}

public synchronized void start() {
    // Cancel any thread attempting to make a connection
    if (connectThread != null) {
        connectThread.cancel();
        connectThread = null;
    }

    // Cancel any thread currently running a connection
    if (connectedThread != null) {
        connectedThread.cancel();
        connectedThread = null;
    }

    // Start the thread to listen on a BluetoothServerSocket
    if (secureAcceptThread == null) {
        secureAcceptThread = new AcceptThread(true);
        secureAcceptThread.start();
    }
    if (insecureAcceptThread == null) {
        insecureAcceptThread = new AcceptThread(false);
        insecureAcceptThread.start();
    }
}

public synchronized void connect(BluetoothDevice device, boolean secure) {

    // Cancel any thread attempting to make a connection
    if (state == STATE_CONNECTING) {
        if (connectThread != null) {
            connectThread.cancel();
            connectThread = null;
        }
    }

    // Cancel any thread currently running a connection
    if (connectedThread != null) {
        connectedThread.cancel();
        connectedThread = null;
    }

    // Start the thread to connect with the given device
    connectThread = new ConnectThread(device, secure);
    connectThread.start();
    // Update UI title
    updateUserInterfaceTitle();
}

public synchronized void connected(BluetoothSocket socket, BluetoothDevice
        device, final String socketType) {

    // Cancel the thread that completed the connection
    if (connectThread != null) {
        connectThread.cancel();
        connectThread = null;
    }

    // Cancel any thread currently running a connection
    if (connectedThread != null) {
        connectedThread.cancel();
        connectedThread = null;
    }

    // Cancel the accept thread because we only want to connect to one device
    if (secureAcceptThread != null) {
        secureAcceptThread.cancel();
        secureAcceptThread = null;
    }
    if (insecureAcceptThread != null) {
        insecureAcceptThread.cancel();
        insecureAcceptThread = null;
    }

    // Start the thread to manage the connection and perform transmissions
    connectedThread = new ConnectedThread(socket, socketType);
    connectedThread.start();

    // Send the name of the connected device back to the UI Activity
    Message msg = chatHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
    Bundle bundle = new Bundle();
    bundle.putString(Constants.DEVICE_NAME, device.getName());
    msg.setData(bundle);
    chatHandler.sendMessage(msg);
    // Update UI title
    updateUserInterfaceTitle();
}

public synchronized void stop() {

    if (connectThread != null) {
        connectThread.cancel();
        connectThread = null;
    }

    if (connectedThread != null) {
        connectedThread.cancel();
        connectedThread = null;
    }

    if (secureAcceptThread != null) {
        secureAcceptThread.cancel();
        secureAcceptThread = null;
    }

    if (insecureAcceptThread != null) {
        insecureAcceptThread.cancel();
        insecureAcceptThread = null;
    }
    state = STATE_NONE;
    // Update UI title
    updateUserInterfaceTitle();
}

public void write(byte[] out) {
    // Create temporary object
    ConnectedThread r;
    // Synchronize a copy of the ConnectedThread
    synchronized (this) {
        if (state != STATE_CONNECTED) return;
        r = connectedThread;
    }
    // Perform the write unsynchronized
    r.write(out);
}

/**
 * Indicate that the connection attempt failed and notify the UI Activity.
 */
private void connectionFailed() {
    // Send a failure message back to the Activity
    Message msg = chatHandler.obtainMessage(Constants.MESSAGE_TOAST);
    Bundle bundle = new Bundle();
    bundle.putString(Constants.TOAST, "Unable to connect device");
    msg.setData(bundle);
    chatHandler.sendMessage(msg);

    state = STATE_NONE;
    // Update UI title
    updateUserInterfaceTitle();

    // Start the service over to restart listening mode
    ChatService.this.start();
}

/**
 * Indicate that the connection was lost and notify the UI Activity.
 */
private void connectionLost() {
    // Send a failure message back to the Activity
    Message msg = chatHandler.obtainMessage(Constants.MESSAGE_TOAST);
    Bundle bundle = new Bundle();
    bundle.putString(Constants.TOAST, "Device connection was lost");
    msg.setData(bundle);
    chatHandler.sendMessage(msg);

    state = STATE_NONE;
    // Update UI title
    updateUserInterfaceTitle();

    // Start the service over to restart listening mode
    ChatService.this.start();
}

private class AcceptThread extends Thread {
    // The local server socket
    private final BluetoothServerSocket mmServerSocket;
    private String mSocketType;

    public AcceptThread(boolean secure) {
        BluetoothServerSocket tmp = null;
        mSocketType = secure ? "Secure" : "Insecure";

        // Create a new listening server socket
        try {
            if (secure) {
                tmp = adapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
                        MY_UUID_SECURE);
            } else {
                tmp = adapter.listenUsingInsecureRfcommWithServiceRecord(
                        NAME_INSECURE, MY_UUID_INSECURE);
            }
        } catch (IOException e) {
        }
        mmServerSocket = tmp;
        state = STATE_LISTEN;
    }

    public void run() {
        setName("AcceptThread" + mSocketType);

        BluetoothSocket socket = null;

        // Listen to the server socket if we're not connected
        while (state != STATE_CONNECTED) {
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                socket = mmServerSocket.accept();
            } catch (IOException e) {
                break;
            }

            // If a connection was accepted
            if (socket != null) {
                synchronized (ChatService.this) {
                    switch (state) {
                        case STATE_LISTEN:
                        case STATE_CONNECTING:
                            // Situation normal. Start the connected thread.
                            connected(socket, socket.getRemoteDevice(),
                                    mSocketType);
                            break;
                        case STATE_NONE:
                        case STATE_CONNECTED:
                            // Either not ready or already connected. Terminate new socket.
                            try {
                                socket.close();
                            } catch (IOException e) {
                            }
                            break;
                    }
                }
            }
        }

    }

    public void cancel() {
        try {
            mmServerSocket.close();
        } catch (IOException e) {
        }
    }
}

private class ConnectThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;
    private String mSocketType;

    public ConnectThread(BluetoothDevice device, boolean secure) {
        mmDevice = device;
        BluetoothSocket tmp = null;
        mSocketType = secure ? "Secure" : "Insecure";

        // initialise sockets
        try {
            if (secure) {
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE);
            } else {
                tmp = device.createInsecureRfcommSocketToServiceRecord(MY_UUID_INSECURE);
            }
        } catch (IOException e){
        }
        mmSocket = tmp;
        state = STATE_CONNECTING;

    }

    public void run() {
        setName("ConnectThread" + mSocketType);

        // attempt connection
        adapter.cancelDiscovery();

        try {
            mmSocket.connect();
        } catch (IOException e) {
            try {
                mmSocket.close();
            } catch (IOException e2) {
            }
            connectionFailed();
            return;
        }

        synchronized (ChatService.this) {
            connectThread = null;
        }
        connected(mmSocket, mmDevice, mSocketType);
    }

    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) {
        }
    }
}

private class ConnectedThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final InputStream mmInStream;
    private final OutputStream mmOutStream;

    public ConnectedThread(BluetoothSocket socket, String socketType) {
        mmSocket = socket;

        // initialise input and output streams
        InputStream tmpIn = null;
        OutputStream tmpOut = null;
        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) {
        }
        mmInStream = tmpIn;
        mmOutStream = tmpOut;

        state = STATE_CONNECTED;
    }

    public void run() {
        byte[] buffer = new byte[1024];
        int bytes;

        // Keep listening to the InputStream while connected
        while (state == STATE_CONNECTED) {
            try {
                // Read from the InputStream
                bytes = mmInStream.read(buffer);

                // Send the obtained bytes to the UI Activity
                chatHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
                        .sendToTarget();
            } catch (IOException e) {
                connectionLost();
                break;
            }
        }
    }

    public void write(byte[] buffer) {
        try {
            // write to outstream
            mmOutStream.write(buffer);

            // Share the sent message back to the UI Activity
            chatHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer)
                    .sendToTarget();
        } catch (IOException e) {
        }
    }

    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) {
        }
    }
}
}

0 个答案:

没有答案