Search code examples
androidservicebluetoothalarmmanager

Periodically send data to server


I'm working on an app that receives data from Arduino through Bluetooth and sends that data to server. I've got this part working - once a user presses a button, I initiate BT connection, receive data and send it to server via Async Task:

  1. Thread for receiving data:

    private class ConnectedThread extends Thread {
    private final InputStream mmInStream;
    private final OutputStream mmOutStream;
    
    public ConnectedThread(BluetoothSocket socket) {
    
        InputStream tmpIn = null;
        OutputStream tmpOut = null;
    
        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) { }
    
        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }
    
    public void run() {
        Log.i("test", "Connected thread RUN");
        byte[] buffer = new byte[256];
        int bytes;
    
        // Keep listening to the InputStream until an exception occurs
        while (true) {
            try {
                Log.i("test", "Trying....");
                bytes = mmInStream.read(buffer);
                handler.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget();
            } catch (IOException e) {
                break;
            }
        }
    }
    
    public void write(String message) {
        Log.d(TAG, "...Data to send: " + message + "...");
        byte[] msgBuffer = message.getBytes();
        try {
            mmOutStream.write(msgBuffer);
        } catch (IOException e) {
            Log.d(TAG, "...Error data send: " + e.getMessage() + "...");
        }
    }
    

    }

  2. ConnectedThread handler (receives data, starts AsyncTask):

    private final Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case RECIEVE_MESSAGE:
                    byte[] readBuf = (byte[]) msg.obj;
                    //String readMessage = new String(readBuf, 0, msg.arg1);
                    String strIncom = new String(readBuf, 0, msg.arg1);
                    sb.append(strIncom);
                    int endOfLineIndex = sb.indexOf("\r\n");
                    if (endOfLineIndex > 0) {
                        String sbprint = sb.substring(0, endOfLineIndex);
                        sb.delete(0, sb.length());
                        Log.i("test", "sbprint: " + sbprint);
                        sendDataToServer(sbprint);
                        txtData.setText("Data from Arduino: " + sbprint);
                    }
                    break;
            }
        };
    

    };

  3. sendDataToServer method:

    private void sendDataToServer(String dataToSend){
        if(dataToSend != null && !dataToSend.equals("")) {
            sendDataAsyncTask = new SendDataAsyncTask(MyActivity.this, dataToSend);
            sendDataAsyncTask.setSendDataListener(MyActivity.this);
            sendDataAsyncTask.execute();
        }
    }
    

This, more or less works. However, now I need to repeat the process every two minutes. I've got it working with TimerTask, but of course the task stops running when device goes to sleep.

I'm guessing I need a Service and / or an AlarmManager to wake the device every two minutes and run the above code? Any tips for this?


Solution

  • Yes, that's right. You need to implement a Service to do the background job, that is to execute sending data to server, even when your app is not on foreground or device display turning off.

    You can use one of my example code here: https://xjaphx.wordpress.com/2012/07/07/create-a-service-that-does-a-schedule-task/

    Additionally, if you want to make the Service running in the best condition (that is, make sure it is not killed by system), you need to check it frequently by

    • Implement a BOOT_RECEIVED Intent, a BroadcastReceiver, to launch your app when device is started.

    • Register for an AlarmManager to schedule check whether the Service is running or not; if it dies already, you can re-start (wake) it up.