简体   繁体   中英

How to create a Bluetooth service that runs in background and save received data in db

This code is a Bluetooth service, but I get NullPointerException when connect thread calls and I don't know how to receive data from Bluetooth service to update UI (handle message).

I want that this service runs in background and save received data in the database. I am a beginner and can not solve it.

BluetoothService.java

public class BluetoothService extends Service{

private Handler myHandler = null;
private int state;

BluetoothDevice myDevice;

ConnectThread connectThread;
ConnectedThread connectedThread;
private final IBinder mIBinder = new LocalBinder();
BluetoothAdapter mBluetoothAdapter;

/*public BluetoothService(Handler handler, BluetoothDevice device) {
    state = Constants.STATE_NONE;
    myHandler = handler;
    myDevice = device;
}*/

@Override
public void onCreate()
{
    super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flag, int startId) {
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (mBluetoothAdapter != null) {
        myDevice = (BluetoothDevice) intent.getExtras().get(Constants.EXTRA_DEVICE);
        String deviceName = myDevice.getName();
        String macAddress = myDevice.getAddress();
        if (macAddress != null && macAddress.length() > 0) {
            connect(myDevice);
        } else {
            stopSelf();

        }

    }
    return START_STICKY;
}

public void onDestroy()
{
    if(myHandler != null)
    {
        myHandler = null;
    }
}

    public IBinder onBind(Intent intent)
{
    return mIBinder;
}

public class LocalBinder extends Binder
{
    public BluetoothService getInstance()
    {
        return BluetoothService.this;
    }
}

public void setHandler(Handler handler)
{
    myHandler = handler;
}



public synchronized void connect(BluetoothDevice myDevice) {
    Log.d(Constants.TAG, "Connecting to: " + myDevice.getName() + " - " + myDevice.getAddress());
    // Start the thread to connect with the given device

    setState(Constants.STATE_CONNECTING);
    connectThread = new ConnectThread(myDevice);
    connectThread.start();
}



public synchronized void stop() {
    cancelConnectThread();
    cancelConnectedThread();
    setState(Constants.STATE_NONE);
}

private synchronized void setState(int state) {
    Log.d(Constants.TAG, "setState() " + this.state + " -> " + state);
    this.state = state;
    // Give the new state to the Handler so the UI Activity can update
    myHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}

public synchronized int getState() {
    return state;
}


public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
    Log.d(Constants.TAG, "connected to: " + device.getName());

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

    setState(Constants.STATE_CONNECTED);
}

/**
 * Indicate that the connection attempt failed and notify the UI Activity.
 */
private void connectionFailed() {
    Log.e(Constants.TAG, "Connection Failed");
    // Send a failure item_message back to the Activity
    Message msg = myHandler.obtainMessage(Constants.MESSAGE_SNACKBAR);
    Bundle bundle = new Bundle();
    bundle.putString(Constants.SNACKBAR, "Unable to connect");
    msg.setData(bundle);
    myHandler.sendMessage(msg);
    setState(Constants.STATE_ERROR);
    cancelConnectThread();
}

/**
 * Indicate that the connection was lost and notify the UI Activity.
 */
private void connectionLost() {
    Log.e(Constants.TAG, "Connection Lost");
    // Send a failure item_message back to the Activity
    Message msg = myHandler.obtainMessage(Constants.MESSAGE_SNACKBAR);
    Bundle bundle = new Bundle();
    bundle.putString(Constants.SNACKBAR, "Cconnection was lost");
    msg.setData(bundle);
    myHandler.sendMessage(msg);
    setState(Constants.STATE_ERROR);
    cancelConnectedThread();
}

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

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

public void write(byte[] out) {
    // Create temporary object
    ConnectedThread r;
    // Synchronize a copy of the ConnectedThread
    synchronized (this) {
        if (state != Constants.STATE_CONNECTED) {
            Log.e(Constants.TAG, "Trying to send but not connected");
            return;
        }
        r = connectedThread;
    }

    // Perform the write unsynchronized
    r.write(out);
}

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

    public ConnectThread(BluetoothDevice device) {
        // Use a temporary object that is later assigned to mmSocket,
        // because mmSocket is final
        BluetoothSocket tmp = null;
        mmDevice = device;

        // Get a BluetoothSocket to connect with the given BluetoothDevice
        try {
            // MY_UUID is the app's UUID string, also used by the server code
            UUID uuid = Constants.myUUID;
            tmp = device.createRfcommSocketToServiceRecord(uuid);
        } catch (IOException e) {
            Log.e(Constants.TAG, "Create RFcomm socket failed", e);
        }
        mmSocket = tmp;
    }

    public void run() {
        try {
            // Connect the device through the socket. This will block
            // until it succeeds or throws an exception
            mmSocket.connect();
        } catch (IOException connectException) {
            // Unable to connect; close the socket and get out
            Log.e(Constants.TAG, "Unable to connect", connectException);
            try {
                mmSocket.close();
            } catch (IOException closeException) {
                Log.e(Constants.TAG, "Unable to close() socket during connection failure", closeException);
            }
            connectionFailed();
            return;
        }

        synchronized (BluetoothService.this) {
            connectThread = null;
        }

        // Do work to manage the connection (in a separate thread)
        connected(mmSocket, mmDevice);
    }

    /** Will cancel an in-progress connection, and close the socket */
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) {
            Log.e(Constants.TAG, "Close() socket failed", e);
        }
    }
}


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

    public ConnectedThread(BluetoothSocket socket) {
        mmSocket = socket;
        InputStream tmpIn = null;
        OutputStream tmpOut = null;

        // Get the input and output streams, using temp objects because
        // member streams are final
        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) {
            Log.e(Constants.TAG, "Temp sockets not created", e);
        }

        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }

    public void run() {
        Log.i(Constants.TAG, "Begin connectedThread");
        byte[] buffer = new byte[1024];  // buffer store for the stream
        int bytes; // bytes returned from read()

        StringBuilder readMessage = new StringBuilder();

        // Keep listening to the InputStream until an exception occurs
        while (true) {
            try {

                bytes = mmInStream.read(buffer);
                String read = new String(buffer, 0, bytes);
               readMessage.append(read);

               if (read.contains("\n")) {

                    myHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, readMessage.toString()).sendToTarget();
                    readMessage.setLength(0);
                }

            } catch (Exception e) {

                Log.e(Constants.TAG, "Connection Lost", e);
                connectionLost();
                break;
            }
        }
    }

    /* Call this from the main activity to send data to the remote device */
    public void write(byte[] bytes) {
        try {
            mmOutStream.write(bytes);
            myHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, bytes).sendToTarget();
        } catch (IOException e) {
            Log.e(Constants.TAG, "Exception during write", e);
        }
    }

    /* Call this from the main activity to shutdown the connection */
    /** Will cancel an in-progress connection, and close the socket */
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) {
            Log.e(Constants.TAG, "close() of connect socket failed", e);}
    }
}


}

Main.java

public class Main extends AppCompatActivity {
BluetoothDevice device;
static BluetoothService bluetoothService;
static TextView T2;
Button button;
static ImageView UVBorder;
static ImageView TempBorder;
static ImageView UVStatus;
static ImageView TempStatus;
ImageView UVChart;
ImageView TempChart;
static TextView UVValue;
static TextView TempValue;
TextView UVLable;
TextView TempLable;

static int SAFE_STATUS=R.drawable.ok;
static int NEED_CARE_STATUS=R.drawable.need_care;
static int AT_RISK_STATUS=R.drawable.alert;
//ProgressDialog progressDlg;
//private static ArrayAdapter<String> mConversationArrayAdapter;
//private ListView mConversationView;
private int  time_interval = 2000;
private long oldCurrentTimeMillis;
static String username;
private Toolbar toolbar;
private NavigationView navigationView;
private DrawerLayout drawerLayout;
static  PulsatorLayout mPulsator1;
static  PulsatorLayout mPulsator2;
private BluetoothService mService = null;

private boolean mIsBound;
myHandler handler;

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

    UVStatus=(ImageView) findViewById(R.id.uv_stat);
    TempStatus=(ImageView) findViewById(R.id.temp_stat);



    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);


    User CurrentUser = UserHolder.getInstance().getUser();

    device = getIntent().getExtras().getParcelable(Constants.EXTRA_DEVICE);

    myHandler handler = new myHandler(Main.this);
    ///bluetoothService = new BluetoothService(handler, device);
    Intent intent=new Intent(this.getBaseContext(), BluetoothService.class);
    intent.putExtra(Constants.EXTRA_DEVICE, device);
    startService(intent);
    doBindService();

}

private ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder)
    {
        mService = ((BluetoothService.LocalBinder)iBinder).getInstance();
        mService.setHandler(handler);
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName)
    {
        mService = null;
    }
};

private void doBindService()
{
    // Establish a connection with the service.  We use an explicit
    // class name because we want a specific service implementation that
    // we know will be running in our own process (and thus won't be
    // supporting component replacement by other applications).
    bindService(new Intent(this,
            BluetoothService.class), mConnection, Context.BIND_AUTO_CREATE);
    mIsBound = true;
}

private void doUnbindService()
{
    if (mIsBound)
    {
        // Detach our existing connection.
        unbindService(mConnection);
        mIsBound = false;
    }
}

@Override
protected void onDestroy()
{
    super.onDestroy();
    doUnbindService();
}



@Override protected void onStart() {
    super.onStart();
    IntentFilter filter = new IntentFilter();
    filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
    registerReceiver(mReceiver, filter);

  //  bluetoothService.connect();


}

@Override protected void onStop() {
    super.onStop();

    if (bluetoothService != null) {
        bluetoothService.stop();
        Log.d(Constants.TAG, "Stopping");
    }

    unregisterReceiver(mReceiver);
}


private static class myHandler extends Handler {
    private final WeakReference<Main> mActivity;

    public myHandler(Main activity) {
        mActivity = new WeakReference<Main>(activity);
    }

    // @Override
    public void handleMessage(Message msg) {

       final Main activity = mActivity.get();

        switch (msg.what) {

            case Constants.MESSAGE_READ:
                Packet packet=new Packet();
                User CurrentUser = UserHolder.getInstance().getUser();
                String username=CurrentUser.getUsername();
                packet.setUserName(username);

                int site_id=CurrentUser.getSite().getId();
                packet.setSiteId(site_id);

                String readMessage = (String) msg.obj;
                // mConversationArrayAdapter.add(readMessage);
                Log.e("msg",readMessage);
                //run a asynctask


                break;
        }
    }


}

}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();

    return super.onOptionsItemSelected(item);
}}

I hope you will find answer from below link:

Example link

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM