定期将数据发送到服务器

时间:2014-07-30 07:54:19

标签: android service bluetooth alarmmanager

我正在开发一款通过蓝牙从Arduino接收数据并将该数据发送到服务器的应用。我已经完成了这部分工作 - 一旦用户按下按钮,我就会启动BT连接,接收数据并通过异步任务将其发送到服务器:

  1. 接收数据的线程:

    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处理程序(接收数据,启动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方法:

    private void sendDataToServer(String dataToSend){
        if(dataToSend != null && !dataToSend.equals("")) {
            sendDataAsyncTask = new SendDataAsyncTask(MyActivity.this, dataToSend);
            sendDataAsyncTask.setSendDataListener(MyActivity.this);
            sendDataAsyncTask.execute();
        }
    }
    
  4. 这或多或少有效。但是,现在我需要每两分钟重复一次这个过程。我已经使用TimerTask,但当设备进入休眠状态时,任务停止运行。

    我猜我需要一个服务和/或一个AlarmManager来每两分钟唤醒一次设备并运行上面的代码?有什么提示吗?

2 个答案:

答案 0 :(得分:3)

是的,没错。您需要实现Service来执行后台作业,即执行向服务器发送数据,即使您的应用不在前台或设备显示器关闭时也是如此。

您可以在此处使用我的示例代码之一:https://xjaphx.wordpress.com/2012/07/07/create-a-service-that-does-a-schedule-task/

此外,如果您想让Service以最佳状态运行(即确保它不被系统杀死),您需要经常检查

  • 实施BOOT_RECEIVED IntentBroadcastReceiver,以便在设备启动时启动您的应用。

  • 注册AlarmManager以安排检查Service是否正在运行;如果它已经死亡,你可以重新启动(唤醒)它。

答案 1 :(得分:0)

对于偶然需要的人:

MainActivity.class:

public class MainActivity extends Activity implements OnClickListener {

private AlarmManager alarmManager;

private static final long INTERVAL = 10*1000;

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

    final Button btn = (Button) findViewById(R.id.btn);
    final Button btn2 = (Button) findViewById(R.id.btn2);
    btn.setOnClickListener(this);
    btn2.setOnClickListener(this);
}

@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.btn:
        setServiceAlarm();
        break;
    case R.id.btn2:
        cancelServiceAlarm();
        break;

    default:
        break;
    }
}

private void setServiceAlarm(){
    if(alarmManager == null){
        Log.i("test", "***STARTING SERVICE***");
        showToast("Starting...");
    Calendar cal = Calendar.getInstance();
    cal.add(Calendar.SECOND, 10);
    Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1, intent, 0);
    alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), INTERVAL, pendingIntent);
    }
}

private void cancelServiceAlarm(){
    if(alarmManager != null){
        Log.i("test", "***STOPPING SERVICE***");
        showToast("Stopping...");
        Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1, intent, 0);
    alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
    alarmManager.cancel(pendingIntent);
    }
}

private void showToast(String message){
    Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
}

AlarmReciever.class:

public class AlarmReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
    Log.i("test", "Alarm received...");
    Intent serviceIntent = new Intent(context, MyIntentService.class);
    serviceIntent.putExtra("date", Utils.getDateTime());
    context.startService(serviceIntent);
    //Log.i("test", "onReceive: " + Utils.getDateTime());
}
}

MyIntentService.class:

public class MyIntentService extends IntentService {

public MyIntentService() {
    super("MyIntentService");
    // TODO Auto-generated constructor stub
}

@Override
protected void onHandleIntent(Intent intent) {
    // TODO Auto-generated method stub
    final String str = intent.getStringExtra("date");
    Log.i("test", "MyIntentService " + str);
}

}

应用程序标记内的清单声明:

<service android:name=".MyIntentService"/>
<receiver android:name=".AlarmReceiver"></receiver>