/* IRKitDeviceService.java Copyright (c) 2014 NTT DOCOMO,INC. Released under the MIT license http://opensource.org/licenses/mit-license.php */ package org.deviceconnect.android.deviceplugin.irkit; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.wifi.WifiManager; import android.support.v4.content.LocalBroadcastManager; import org.deviceconnect.android.deviceplugin.irkit.IRKitManager.DetectionListener; import org.deviceconnect.android.deviceplugin.irkit.data.IRKitDBHelper; import org.deviceconnect.android.deviceplugin.irkit.data.VirtualDeviceData; import org.deviceconnect.android.deviceplugin.irkit.network.WiFiUtil; import org.deviceconnect.android.deviceplugin.irkit.profile.IRKitSystemProfile; import org.deviceconnect.android.deviceplugin.irkit.service.IRKitService; import org.deviceconnect.android.deviceplugin.irkit.service.VirtualService; import org.deviceconnect.android.event.EventManager; import org.deviceconnect.android.event.cache.MemoryCacheController; import org.deviceconnect.android.localoauth.LocalOAuth2Main; import org.deviceconnect.android.message.DConnectMessageService; import org.deviceconnect.android.profile.SystemProfile; import org.deviceconnect.android.service.DConnectService; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; /** * IRKitデバイスプラグインサービス. * @author NTT DOCOMO, INC. */ public class IRKitDeviceService extends DConnectMessageService implements DetectionListener { /** * IRKitの検知を再スタートさせるためのアクションを定義. */ public static final String ACTION_RESTART_DETECTION_IRKIT = "action.ACTION_RESTART_DETECTION_IRKIT"; /** * 仮想デバイスの追加を通知するアクションを定義. */ public static final String ACTION_VIRTUAL_DEVICE_ADDED = "action.ACTION_VIRTUAL_DEVICE_ADDED"; /** * 仮想デバイスの削除を通知するアクションを定義. */ public static final String ACTION_VIRTUAL_DEVICE_REMOVED = "action.ACTION_VIRTUAL_DEVICE_REMOVED"; /** * 仮想デバイスのステータス更新を通知するアクションを定義. */ public static final String ACTION_VIRTUAL_DEVICE_UPDATED = "action.ACTION_VIRTUAL_DEVICE_UPDATED"; /** * 仮想デバイスのIDを取得するためのキー. */ public static final String EXTRA_VIRTUAL_DEVICE_ID = "extra.EXTRA_VIRTUAL_DEVICE_ID"; /** * 検知したデバイス群. */ private final ConcurrentHashMap<String, IRKitDevice> mDevices = new ConcurrentHashMap<String, IRKitDevice>(); /** * 現在のSSID. */ private String mCurrentSSID; /** DB Helper. */ private IRKitDBHelper mDBHelper; /** ロガー. */ private final Logger mLogger = Logger.getLogger("irkit.dplugin"); /** 内部的なブロードキャストレシーバー. */ private final BroadcastReceiver mLocalBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(final Context context, final Intent intent) { if (intent == null || intent.getAction() == null) { return; } String action = intent.getAction(); if (ACTION_RESTART_DETECTION_IRKIT.equals(action)) { if (WiFiUtil.isOnWiFi(IRKitDeviceService.this)) { restartDetection(); } else { stopDetection(); } } else if (ACTION_VIRTUAL_DEVICE_ADDED.equals(action)) { String id = intent.getStringExtra(EXTRA_VIRTUAL_DEVICE_ID); if (id != null) { DConnectService service = getServiceProvider().getService(id); if (service == null) { List<VirtualDeviceData> devices = mDBHelper.getVirtualDevices(id); if (devices.size() > 0) { VirtualDeviceData device = devices.get(0); service = new VirtualService(device, mDBHelper, getServiceProvider()); getServiceProvider().addService(service); } } } } else if (ACTION_VIRTUAL_DEVICE_UPDATED.equals(action)) { String id = intent.getStringExtra(EXTRA_VIRTUAL_DEVICE_ID); if (id != null) { DConnectService service = getServiceProvider().getService(id); if (service != null) { VirtualService virtualService = (VirtualService) service; service.setOnline(virtualService.isOnline()); } } } else if (ACTION_VIRTUAL_DEVICE_REMOVED.equals(action)) { String id = intent.getStringExtra(EXTRA_VIRTUAL_DEVICE_ID); if (id != null) { DConnectService service = getServiceProvider().getService(id); if (service != null) { getServiceProvider().removeService(service); } } } } }; @Override public void onCreate() { super.onCreate(); EventManager.INSTANCE.setController(new MemoryCacheController()); mDBHelper = new IRKitDBHelper(getContext()); for (VirtualDeviceData device : mDBHelper.getVirtualDevices(null)) { VirtualService vDevice = new VirtualService(device, mDBHelper, getServiceProvider()); vDevice.setOnline(vDevice.isOnline()); getServiceProvider().addService(vDevice); } IRKitApplication app = (IRKitApplication) getApplication(); app.setIRKitDevices(mDevices); IRKitManager.INSTANCE.init(this); IRKitManager.INSTANCE.setDetectionListener(this); if (WiFiUtil.isOnWiFi(this)) { startDetection(); } mCurrentSSID = WiFiUtil.getCurrentSSID(this); IntentFilter localFilter = new IntentFilter(); localFilter.addAction(ACTION_RESTART_DETECTION_IRKIT); localFilter.addAction(ACTION_VIRTUAL_DEVICE_ADDED); localFilter.addAction(ACTION_VIRTUAL_DEVICE_REMOVED); localFilter.addAction(ACTION_VIRTUAL_DEVICE_UPDATED); LocalBroadcastManager.getInstance(this).registerReceiver(mLocalBroadcastReceiver, localFilter); } @Override public int onStartCommand(final Intent intent, final int flags, final int startId) { if (intent != null) { String action = intent.getAction(); if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) { if (!WiFiUtil.isOnWiFi(this) && IRKitManager.INSTANCE.isDetecting()) { stopDetection(); } else if (WiFiUtil.isOnWiFi(this) && WiFiUtil.isChangedSSID(this, mCurrentSSID)) { restartDetection(); } return START_STICKY; } } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); stopDetection(); // 参照をきっておく IRKitManager.INSTANCE.setDetectionListener(null); LocalOAuth2Main.destroy(); } @Override protected void onManagerUninstalled() { // Managerアンインストール検知時の処理。 if (BuildConfig.DEBUG) { mLogger.info("Plug-in : onManagerUninstalled"); } } @Override protected void onManagerTerminated() { // Manager正常終了通知受信時の処理。 if (BuildConfig.DEBUG) { mLogger.info("Plug-in : onManagerTerminated"); } } @Override protected void onDevicePluginReset() { // Device Plug-inへのReset要求受信時の処理。 if (BuildConfig.DEBUG) { mLogger.info("Plug-in : onDevicePluginReset"); } } /** * サービスIDからIRKitのデバイスを取得する. * * @param serviceId サービスID * @return デバイス */ public IRKitDevice getDevice(final String serviceId) { return mDevices.get(serviceId); } @Override protected SystemProfile getSystemProfile() { return new IRKitSystemProfile(); } @Override public void onFoundDevice(final IRKitDevice device) { updateDeviceList(device, true); DConnectService service = getServiceProvider().getService(device.getName()); if (service == null) { service = new IRKitService(device); getServiceProvider().addService(service); } service.setOnline(true); } @Override public void onLostDevice(final IRKitDevice device) { updateDeviceList(device, false); DConnectService service = getServiceProvider().getService(device.getName()); if (service != null) { service.setOnline(false); } } /** * デバイスリストを更新する. * * @param device デバイス * @param isOnline trueなら発見、falseなら消失を意味する */ private void updateDeviceList(final IRKitDevice device, final boolean isOnline) { synchronized (mDevices) { IRKitDevice d = mDevices.get(device.getName()); if (d != null) { if (!isOnline) { mDevices.remove(device.getName()); } } else if (isOnline) { mDevices.put(device.getName(), device); } } IRKitApplication app = (IRKitApplication) getApplication(); app.setIRKitDevices(mDevices); } /** * 検知を開始する. */ private void startDetection() { mCurrentSSID = WiFiUtil.getCurrentSSID(this); IRKitManager.INSTANCE.startDetection(this); } /** * 検知を終了する. */ private void stopDetection() { mCurrentSSID = null; mDevices.clear(); IRKitManager.INSTANCE.stopDetection(); } private void restartDetection() { new Thread(new Runnable() { @Override public void run() { stopDetection(); startDetection(); } }).start(); } }