/* HostProximityProfile.java Copyright (c) 2014 NTT DOCOMO,INC. Released under the MIT license http://opensource.org/licenses/mit-license.php */ package org.deviceconnect.android.deviceplugin.host.profile; import android.content.Context; import android.content.Intent; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import org.deviceconnect.android.deviceplugin.host.HostDeviceService; import org.deviceconnect.android.event.Event; import org.deviceconnect.android.event.EventError; import org.deviceconnect.android.event.EventManager; import org.deviceconnect.android.message.MessageUtils; import org.deviceconnect.android.profile.DConnectProfile; import org.deviceconnect.android.profile.ProximityProfile; import org.deviceconnect.android.profile.api.DConnectApi; import org.deviceconnect.android.profile.api.DeleteApi; import org.deviceconnect.android.profile.api.GetApi; import org.deviceconnect.android.profile.api.PutApi; import org.deviceconnect.message.DConnectMessage; import java.util.ArrayList; import java.util.List; /** * Proximity Profile. * * @author NTT DOCOMO, INC. */ public class HostProximityProfile extends ProximityProfile implements SensorEventListener { /** * サービスID. */ private static String sServiceId = ""; private final DConnectApi mGetOnUserProximityApi = new GetApi() { @Override public String getAttribute() { return ATTRIBUTE_ON_USER_PROXIMITY; } @Override public boolean onRequest(final Intent request, final Intent response) { return getOnUserProximity(response); } }; private final DConnectApi mPutOnUserProximityApi = new PutApi() { @Override public String getAttribute() { return ATTRIBUTE_ON_USER_PROXIMITY; } @Override public boolean onRequest(final Intent request, final Intent response) { String serviceId = getServiceID(request); // イベントの登録 EventError error = EventManager.INSTANCE.addEvent(request); if (error == EventError.NONE) { sServiceId = serviceId; if (registerProximity()) { setResult(response, DConnectMessage.RESULT_OK); } else { MessageUtils.setNotSupportAttributeError(response, "This device is not support proximity."); } } else { MessageUtils.setUnknownError(response, "Failed to register event."); } return true; } }; private final DConnectApi mDeleteOnUserProximityApi = new DeleteApi() { @Override public String getAttribute() { return ATTRIBUTE_ON_USER_PROXIMITY; } @Override public boolean onRequest(final Intent request, final Intent response) { // イベントの解除 EventError error = EventManager.INSTANCE.removeEvent(request); if (error == EventError.NONE) { if (unregisterProximity()) { setResult(response, DConnectMessage.RESULT_OK); } else { MessageUtils.setNotSupportAttributeError(response, "This device is not support proximity."); } } else { MessageUtils.setUnknownError(response, "Failed to unregister event."); } return true; } }; public HostProximityProfile() { addApi(mGetOnUserProximityApi); addApi(mPutOnUserProximityApi); addApi(mDeleteOnUserProximityApi); } @Override public void onSensorChanged(final SensorEvent sensorEvent) { if (sensorEvent.sensor.getType() == Sensor.TYPE_PROXIMITY) { Bundle mProximityBundle = new Bundle(); if (sensorEvent.values[0] == 0.0) { ProximityProfile.setNear(mProximityBundle, true); } else { ProximityProfile.setNear(mProximityBundle, false); } List<Event> events = EventManager.INSTANCE.getEventList(sServiceId, ProximityProfile.PROFILE_NAME, null, ProximityProfile.ATTRIBUTE_ON_USER_PROXIMITY); if (events == null || events.size() == 0) { unregisterProximity(); return; } synchronized (events) { for (Event event : events) { Intent evtIntent = EventManager.createEventMessage(event); ProximityProfile.setProximity(evtIntent, mProximityBundle); sendEvent(evtIntent, event.getAccessToken()); } } } } @Override public void onAccuracyChanged(final Sensor sensor, final int accuracy) { // No operation. } /** * Proximityのセンサーリストを取得する. * <p> * Proximityのセンサーに対応していない場合には、空の配列が返却される。 * @return センサーリスト */ private List<Sensor> getSensorList() { SensorManager mgr = getSensorManager(); if (mgr == null) { return new ArrayList<Sensor>(); } return mgr.getSensorList(Sensor.TYPE_PROXIMITY); } /** * センサー管理クラスを取得する. * @return センサー管理クラス */ private SensorManager getSensorManager() { return (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); } /** * Proximityのセンサーを登録する. * @return trueの場合には登録成功、false場合には失敗 */ private boolean registerProximity() { List<Sensor> sensors = getSensorList(); if (sensors.size() > 0) { Sensor sensor = sensors.get(0); getSensorManager().registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL); return true; } else { return false; } } /** * Proximityのセンサーを解除する. * @return 解除に成功した場合はtrue、それ以外はfalse */ private boolean unregisterProximity() { SensorManager mgr = getSensorManager(); if (mgr == null) { return false; } mgr.unregisterListener(this); return true; } /** * Proximityを一回だけ取得します. * @param response レスポンス * @return 即座に返却する場合はtrue、それ以外はfalse */ private boolean getOnUserProximity(final Intent response) { final SensorEventListener l = new SensorEventListener() { @Override public void onSensorChanged(final SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) { Bundle mProximityBundle = new Bundle(); if (event.values[0] == 0.0) { ProximityProfile.setNear(mProximityBundle, true); } else { ProximityProfile.setNear(mProximityBundle, false); } ProximityProfile.setProximity(response, mProximityBundle); DConnectProfile.setResult(response, DConnectMessage.RESULT_OK); HostDeviceService service = (HostDeviceService) getContext(); service.sendResponse(response); getSensorManager().unregisterListener(this); } } @Override public void onAccuracyChanged(final Sensor sensor, final int accuracy) { } }; List<Sensor> sensors = getSensorList(); if (sensors.size() > 0) { Sensor sensor = sensors.get(0); getSensorManager().registerListener(l, sensor, SensorManager.SENSOR_DELAY_NORMAL); return false; } else { MessageUtils.setNotSupportAttributeError(response, "This device is not support proximity."); return true; } } }