package org.deviceconnect.android.deviceplugin.wear; import android.app.Service; import android.content.Intent; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.wearable.MessageApi; import com.google.android.gms.wearable.Wearable; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class WearAppService extends Service implements SensorEventListener { /** radian. */ private static final double RAD2DEG = 180 / Math.PI; /** Device NodeID . */ private final List<String> mIds = Collections.synchronizedList(new ArrayList<String>()); /** SensorManager. */ private SensorManager mSensorManager; /** Gyro x. */ private float mGyroX; /** Gyro y. */ private float mGyroY; /** Gyro z. */ private float mGyroZ; /** The start time for measuring the interval. */ private long mStartTime; /** GyroSensor. */ private Sensor mGyroSensor; /** AcceleratorSensor. */ private Sensor mAccelerometer; /** * スレッド管理用クラス. */ private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor(); @Override public void onCreate() { super.onCreate(); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null) { String action = intent.getAction(); String id = intent.getStringExtra(WearConst.PARAM_SENSOR_ID); if (WearConst.DEVICE_TO_WEAR_DEIVCEORIENTATION_REGISTER.equals(action)) { if (!mIds.contains(id)) { mIds.add(id); } registerSensor(); } else if (WearConst.DEVICE_TO_WEAR_DEIVCEORIENTATION_UNREGISTER.equals(action)) { mIds.remove(id); if (mIds.isEmpty()) { unregisterSensor(); } } } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { mIds.clear(); unregisterSensor(); super.onDestroy(); } @Override public void onSensorChanged(final SensorEvent sensorEvent) { if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { long time = System.currentTimeMillis(); long interval = time - mStartTime; mStartTime = time; float accelX = sensorEvent.values[0]; float accelY = sensorEvent.values[1]; float accelZ = sensorEvent.values[2]; final String data = accelX + "," + accelY + "," + accelZ + "," + mGyroX + "," + mGyroY + "," + mGyroZ + "," + interval; mExecutorService.execute(new Runnable() { @Override public void run() { synchronized (mIds) { for (String id : mIds) { sendSensorEvent(data, id); } } } }); } else if (sensorEvent.sensor.getType() == Sensor.TYPE_GYROSCOPE) { mGyroX = (float) (sensorEvent.values[0] * RAD2DEG); mGyroY = (float) (sensorEvent.values[1] * RAD2DEG); mGyroZ = (float) (sensorEvent.values[2] * RAD2DEG); } } @Override public void onAccuracyChanged(final Sensor sensor, final int accuracy) { } /** * センサーイベントをスマホ側に送信する. * @param data 送信するデータ * @param id 送信先のID */ private void sendSensorEvent(final String data, final String id) { GoogleApiClient client = getClient(); if (!client.isConnected()) { ConnectionResult connectionResult = client.blockingConnect(30, TimeUnit.SECONDS); if (!connectionResult.isSuccess()) { if (BuildConfig.DEBUG) { Log.e("WEAR", "Failed to connect google play service."); } return; } } MessageApi.SendMessageResult result = Wearable.MessageApi.sendMessage(client, id, WearConst.WEAR_TO_DEVICE_DEIVCEORIENTATION_DATA, data.getBytes()).await(); if (!result.getStatus().isSuccess()) { if (BuildConfig.DEBUG) { Log.e("WEAR", "Failed to send a sensor event."); } } } /** * センサーを登録する. */ private synchronized void registerSensor() { if (mSensorManager != null) { return; } GoogleApiClient client = getClient(); if (client == null || !client.isConnected()) { client = new GoogleApiClient.Builder(this).addApi(Wearable.API).build(); client.connect(); ConnectionResult connectionResult = client.blockingConnect(30, TimeUnit.SECONDS); if (!connectionResult.isSuccess()) { if (BuildConfig.DEBUG) { Log.e("WEAR", "Failed to connect google play service."); } return; } } mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); List<Sensor> accelSensors = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER); if (accelSensors.size() > 0) { mAccelerometer = accelSensors.get(0); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); } List<Sensor> gyroSensors = mSensorManager.getSensorList(Sensor.TYPE_GYROSCOPE); if (gyroSensors.size() > 0) { mGyroSensor = gyroSensors.get(0); mSensorManager.registerListener(this, mGyroSensor, SensorManager.SENSOR_DELAY_NORMAL); } mStartTime = System.currentTimeMillis(); } /** * センサーを解除する. */ private synchronized void unregisterSensor() { if (mSensorManager != null) { mSensorManager.unregisterListener(this, mAccelerometer); mSensorManager.unregisterListener(this, mGyroSensor); mSensorManager.unregisterListener(this); mSensorManager = null; } } /** * GoogleApiClientを取得する. * @return GoogleApiClient */ private GoogleApiClient getClient() { return ((WearApplication) getApplication()).getGoogleApiClient(); } }