/* SystemProfile.java Copyright (c) 2015 NTT DOCOMO,INC. Released under the MIT license http://opensource.org/licenses/mit-license.php */ package org.deviceconnect.android.profile; import java.util.ArrayList; import java.util.List; import org.deviceconnect.android.profile.api.DConnectApi; import org.deviceconnect.android.profile.api.GetApi; import org.deviceconnect.android.profile.spec.DConnectProfileSpec; import org.deviceconnect.android.profile.spec.DConnectSpecConstants; import org.deviceconnect.message.DConnectMessage; import org.deviceconnect.profile.ServiceDiscoveryProfileConstants; import org.deviceconnect.profile.ServiceInformationProfileConstants; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; /** * Service Information プロファイル. * * <p> * サービス情報を提供するAPI. * </p> * * @author NTT DOCOMO, INC. */ public class ServiceInformationProfile extends DConnectProfile implements ServiceInformationProfileConstants { /** * 設定画面起動用IntentのパラメータオブジェクトのExtraキー. */ public static final String SETTING_PAGE_PARAMS = "org.deviceconnect.profile.system.setting_params"; private static final String KEY_PATHS = "paths"; private static final String KEY_INFO = "info"; private static final String KEY_DEFINITIONS = "definitions"; private static final String KEY_RESPONSES = "responses"; private static final String KEY_PARAMETERS = "parameters"; private static final String KEY_X_EVENT = "x-event"; private static final String KEY_SUMMARY = "summary"; private static final String KEY_DESCRIPTION = "description"; /** * Service Information API. */ private final DConnectApi mServiceInformationApi = new GetApi() { @Override public boolean onRequest(final Intent request, final Intent response) { appendServiceInformation(response); return true; } }; /** * ServiceInformationプロファイルを生成する. */ public ServiceInformationProfile() { addApi(mServiceInformationApi); } @Override public final String getProfileName() { return PROFILE_NAME; } protected void appendServiceInformation(final Intent response) { // connect Bundle connect = new Bundle(); String networkType = getService().getNetworkType(); boolean isOnline = getService().isOnline(); switch (ServiceDiscoveryProfileConstants.NetworkType.getInstance(networkType)) { case WIFI: setWifiState(connect, isOnline); break; case BLUETOOTH: setBluetoothState(connect, isOnline); break; case BLE: setBLEState(connect, isOnline); break; case NFC: setNFCState(connect, isOnline); break; default: break; } setConnect(response, connect); // TODO: getXXXStateメソッドを削除する。 // version setVersion(response, getCurrentVersionName()); // supports, supportApis List<DConnectProfile> profileList = getService().getProfileList(); String[] profileNames = new String[profileList.size()]; int i = 0; for (DConnectProfile profile : profileList) { profileNames[i++] = profile.getProfileName(); } setSupports(response, profileNames); setSupportApis(response, profileList); setResult(response, DConnectMessage.RESULT_OK); } /** * AndroidManifest.xmlのversionNameを取得する. * * @return バージョン名 */ private String getCurrentVersionName() { PackageManager packageManager = getContext().getPackageManager(); try { PackageInfo packageInfo = packageManager.getPackageInfo(getContext().getPackageName(), PackageManager.GET_ACTIVITIES); return packageInfo.versionName; } catch (NameNotFoundException e) { return "Unknown"; } } /** * WiFiの接続状態を取得する. * * @param serviceId サービスID * @return WiFiの接続状態 * @see ConnectState */ protected ConnectState getWifiState(final String serviceId) { return ConnectState.NONE; } /** * Bluetoothの接続状態を取得する. * * @param serviceId サービスID * @return Bluetoothの接続状態 * @see ConnectState */ protected ConnectState getBluetoothState(final String serviceId) { return ConnectState.NONE; } /** * NFCの接続状態を取得する. * * @param serviceId サービスID * @return NFCの接続状態 * @see ConnectState */ protected ConnectState getNFCState(final String serviceId) { return ConnectState.NONE; } /** * BLEの接続状態を取得する. * * @param serviceId サービスID * @return BLEの接続状態 * @see ConnectState */ protected ConnectState getBLEState(final String serviceId) { return ConnectState.NONE; } // ------------------------------------ // レスポンスセッターメソッド群 // ------------------------------------ /** * レスポンスにバージョンを格納する. * * @param response レスポンスパラメータ * @param version バージョン */ public static void setVersion(final Intent response, final String version) { response.putExtra(PARAM_VERSION, version); } /** * レスポンスにサポートしているI/Fの一覧を格納する. * * @param response レスポンスパラメータ * @param supports サポートしているI/F一覧 * @see #setSupportApis(Intent, List) */ public static void setSupports(final Intent response, final String[] supports) { response.putExtra(PARAM_SUPPORTS, supports); } /** * レスポンスにサポートしているI/Fの一覧を格納する. * * @param response レスポンスパラメータ * @param supports サポートしているI/F一覧 */ public static void setSupports(final Intent response, final List<String> supports) { setSupports(response, supports.toArray(new String[supports.size()])); } public static void setSupportApis(final Intent response, final List<DConnectProfile> profileList) { Bundle supportApisBundle = new Bundle(); for (final DConnectProfile profile : profileList) { DConnectProfileSpec profileSpec = profile.getProfileSpec(); if (profileSpec != null) { Bundle bundle = createSupportApisBundle(profileSpec, profile); // 送信しない情報はここで削除. reduceInformation(bundle); supportApisBundle.putBundle(profile.getProfileName(), bundle); } } response.putExtra(PARAM_SUPPORT_APIS, supportApisBundle); } private static Bundle createSupportApisBundle(final DConnectProfileSpec profileSpec, final DConnectProfile profile) { Bundle tmpBundle = new Bundle(profileSpec.toBundle()); Bundle pathsObj = tmpBundle.getBundle(KEY_PATHS); if (pathsObj == null) { return tmpBundle; } List<String> pathNames = new ArrayList<String>(pathsObj.keySet()); for (String pathName : pathNames) { Bundle pathObj = pathsObj.getBundle(pathName); if (pathObj == null) { continue; } for (DConnectSpecConstants.Method method : DConnectSpecConstants.Method.values()) { String methodName = method.getName().toLowerCase(); Bundle methodObj = pathObj.getBundle(methodName); if (methodObj == null) { continue; } if (!profile.hasApi(pathName, method)) { pathObj.remove(methodName); } } if (pathObj.size() == 0) { pathsObj.remove(pathName); } } return tmpBundle; } private static void reduceInformation(final Bundle supportApi) { Bundle infoObj = supportApi.getBundle(KEY_INFO); if (infoObj != null) { infoObj.remove(KEY_DESCRIPTION); } Bundle pathsObj = supportApi.getBundle(KEY_PATHS); if (pathsObj != null) { List<String> pathNames = new ArrayList<String>(pathsObj.keySet()); for (String pathName : pathNames) { Bundle pathObj = pathsObj.getBundle(pathName); if (pathObj == null) { continue; } for (DConnectSpecConstants.Method method : DConnectSpecConstants.Method.values()) { String methodName = method.getName().toLowerCase(); Bundle methodObj = pathObj.getBundle(methodName); if (methodObj == null) { continue; } methodObj.remove(KEY_RESPONSES); methodObj.remove(KEY_X_EVENT); methodObj.remove(KEY_SUMMARY); methodObj.remove(KEY_DESCRIPTION); Bundle[] parameters = (Bundle[]) methodObj.getParcelableArray(KEY_PARAMETERS); if (parameters != null) { for (Bundle parameter : parameters) { parameter.remove(KEY_DESCRIPTION); } } } } } supportApi.remove(KEY_DEFINITIONS); } /** * レスポンスにデバイスの接続状態を設定する. * * @param response レスポンスパラメータ * @param connect デバイスの接続状態 */ public static void setConnect(final Intent response, final Bundle connect) { response.putExtra(PARAM_CONNECT, connect); } /** * 指定されたパラメータに接続状態を設定する. * * @param b バンドルオブジェクト * @param key パラメータキー * @param state 状態 */ private static void setConnectionState(final Bundle b, final String key, final ConnectState state) { // 非対応のものは省略 switch (state) { case ON: b.putBoolean(key, true); break; case OFF: b.putBoolean(key, false); break; default: break; } } /** * デバイスプラグインの接続状態にWiFiの接続状態を設定する. * * @param connect デバイスプラグインの接続状態パラメータ * @param connecting true:ON、false:OFF */ public static void setWifiState(final Bundle connect, final boolean connecting) { connect.putBoolean(PARAM_WIFI, connecting); } /** * デバイスプラグインの接続状態にWiFiの接続状態を設定する. * * @param connect デバイスプラグインの接続状態パラメータ * @param state 接続状態 */ public static void setWifiState(final Bundle connect, final ConnectState state) { setConnectionState(connect, PARAM_WIFI, state); } /** * デバイスプラグインの接続状態にBluetoothの接続状態を設定する. * * @param connect デバイスプラグインの接続状態パラメータ * @param connecting true:ON、false:OFF */ public static void setBluetoothState(final Bundle connect, final boolean connecting) { connect.putBoolean(PARAM_BLUETOOTH, connecting); } /** * デバイスプラグインの接続状態にBluetoothの接続状態を設定する. * * @param connect デバイスプラグインの接続状態パラメータ * @param state 接続状態 */ public static void setBluetoothState(final Bundle connect, final ConnectState state) { setConnectionState(connect, PARAM_BLUETOOTH, state); } /** * デバイスプラグインの接続状態にNFCの接続状態を設定する. * * @param connect デバイスプラグインの接続状態パラメータ * @param connecting true:ON、false:OFF */ public static void setNFCState(final Bundle connect, final boolean connecting) { connect.putBoolean(PARAM_NFC, connecting); } /** * デバイスプラグインの接続状態にNFCの接続状態を設定する. * * @param connect デバイスプラグインの接続状態パラメータ * @param state 接続状態 */ public static void setNFCState(final Bundle connect, final ConnectState state) { setConnectionState(connect, PARAM_NFC, state); } /** * デバイスプラグインの接続状態にBLEの接続状態を設定する. * * @param connect デバイスプラグインの接続状態パラメータ * @param connecting true:ON、false:OFF */ public static void setBLEState(final Bundle connect, final boolean connecting) { connect.putBoolean(PARAM_BLE, connecting); } /** * デバイスプラグインの接続状態にBLEの接続状態を設定する. * * @param connect デバイスプラグインの接続状態パラメータ * @param state 接続状態 */ public static void setBLEState(final Bundle connect, final ConnectState state) { setConnectionState(connect, PARAM_BLE, state); } }