title: Realtime data exchange between Android Wearable and Handheld
body: <p>I am working on a simple app which will run on both wearable(Samsung Gear Live) and handheld(Moto G). I want to display the data from the wearable's heart rate sensor, accelerometer and gyroscope on the handheld. Which is the best way to achieve this.
  Now I am using <code>DataApi</code>, but since I am updating data each second, it is allocating too much memory, and then killed by OS.
  Here is my service which runs on the wearable</p>
  
  <pre><code>public class SensorDataListener extends Service implements SensorEventListener,
          ConnectionCallbacks, OnConnectionFailedListener {
      private static final String TAG = SensorDataListener.class.getSimpleName();
  
      private static final int TIMEOUT_HEART_RATE    = 1000000;
      private static final int TIMEOUT_ACCELEROMETER = 1000000;
      private static final int TIMEOUT_GYROSCOPE     = 1000000;
  
      private static final String PATH_SENSOR_DATA = "/sensor_data";
      private static final String KEY_HEART_RATE = "heart_rate";
  
      private static final String KEY_ACC_X = "acc_x";
      private static final String KEY_ACC_Y = "acc_y";
      private static final String KEY_ACC_Z = "acc_z";
  
      private static final String KEY_GYRO_X = "gyro_x";
      private static final String KEY_GYRO_Y = "gyro_y";
      private static final String KEY_GYRO_Z = "gyro_z";
  
      private SensorManager mSensorManager;
      private Sensor mAccelerometer;
      private Sensor mGyroscope;
      private Sensor mHeartRate;
  
      private int mCurHeartRateVal;
      private float[] mCurAccelerometerVal = new float[3];
      private float[] mCurGyroscopeVal = new float[3];
  
      private GoogleApiClient mGoogleApiClient;
      ScheduledExecutorService mUpdateScheduler;
  
      ScheduledExecutorService scheduler;
  
  
      @Override
      public void onCreate() {
          super.onCreate();
  
          mGoogleApiClient = new GoogleApiClient.Builder(this)
                  .addApi(com.google.android.gms.wearable.Wearable.API)
                  .build();
          mGoogleApiClient.connect();
  
          mSensorManager = ((SensorManager)getSystemService(SENSOR_SERVICE));
  
          mHeartRate     = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
          mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
          mGyroscope     = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
  
          startDataUpdated();
      }
  
  
      private void startDataUpdated() {
          scheduler = Executors.newSingleThreadScheduledExecutor();
  
          scheduler.scheduleAtFixedRate
                  (new Runnable() {
                      public void run() {
                          updateData();
                      }
                  }, 5, 3, TimeUnit.SECONDS);
      }
  
  
      private void updateData() {
          PutDataMapRequest dataMap = PutDataMapRequest.create(PATH_SENSOR_DATA);
          dataMap.getDataMap().putInt(KEY_HEART_RATE, mCurHeartRateVal);
  
          dataMap.getDataMap().putFloat(KEY_ACC_X, mCurAccelerometerVal[0]);
          dataMap.getDataMap().putFloat(KEY_ACC_Y, mCurAccelerometerVal[1]);
          dataMap.getDataMap().putFloat(KEY_ACC_Z, mCurAccelerometerVal[2]);
  
          dataMap.getDataMap().putFloat(KEY_GYRO_X, mCurGyroscopeVal[0]);
          dataMap.getDataMap().putFloat(KEY_GYRO_Y, mCurGyroscopeVal[1]);
          dataMap.getDataMap().putFloat(KEY_GYRO_Z, mCurGyroscopeVal[2]);
  
          PutDataRequest request = dataMap.asPutDataRequest();
          Wearable.DataApi.putDataItem(mGoogleApiClient, request);
      }
  
      @Override
      public int onStartCommand(Intent intent, int flags, int startId) {
          mSensorManager.registerListener(this, mHeartRate, TIMEOUT_HEART_RATE);
          mSensorManager.registerListener(this, mAccelerometer, TIMEOUT_ACCELEROMETER);
          mSensorManager.registerListener(this, mGyroscope, TIMEOUT_GYROSCOPE);
  
          return START_NOT_STICKY;
      }
  
      @Override
      public void onDestroy() {
          Log.d(TAG, "onDestroy");
          mGoogleApiClient.disconnect();
  
          scheduler.shutdown();
          mSensorManager.unregisterListener(this);
  
          //mUpdateScheduler.shutdownNow();
          super.onDestroy();
      }    
  
      @Override
      public void onSensorChanged(SensorEvent event) {
  
          switch(event.sensor.getType()) {
              case Sensor.TYPE_HEART_RATE:
                  if(event.values[0] &lt;= 0) // HR sensor is being initialized
                      return;
                  mCurHeartRateVal = Float.valueOf(event.values[0]).intValue();
                  break;
  
              case Sensor.TYPE_ACCELEROMETER:
                  mCurAccelerometerVal[0] = event.values[0];
                  mCurAccelerometerVal[1] = event.values[1];
                  mCurAccelerometerVal[2] = event.values[2];
                  break;
  
              case Sensor.TYPE_GYROSCOPE: {
                  mCurGyroscopeVal[0] = event.values[0];
                  mCurGyroscopeVal[1] = event.values[1];
                  mCurGyroscopeVal[2] = event.values[2];
                  break;
              }
          }
      }
  
      @Override
      public void onAccuracyChanged(Sensor sensor, int accuracy) {}
  
      @Override
      public void onConnected(Bundle bundle) { Log.d(TAG, "onConnected"); }
  
      @Override
      public void onConnectionSuspended(int i) { Log.d(TAG, "onConnectionSuspended"); }
  
  
      @Override
      public void onConnectionFailed(ConnectionResult connectionResult) { Log.d(TAG, "onConnectionFailed"); }
  
      @Override
      public IBinder onBind(Intent intent) {
          return null;
      }
  }
  </code></pre>