/* HostPhoneProfile.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.Manifest; import android.content.Context; import android.content.Intent; import android.media.AudioManager; import android.net.Uri; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.support.annotation.NonNull; import org.deviceconnect.android.activity.PermissionUtility; import org.deviceconnect.android.event.EventError; import org.deviceconnect.android.event.EventManager; import org.deviceconnect.android.message.MessageUtils; import org.deviceconnect.android.profile.PhoneProfile; import org.deviceconnect.android.profile.api.DConnectApi; import org.deviceconnect.android.profile.api.DeleteApi; import org.deviceconnect.android.profile.api.PostApi; import org.deviceconnect.android.profile.api.PutApi; import org.deviceconnect.message.DConnectMessage; /** * Phoneプロファイル. * * @author NTT DOCOMO, INC. */ public class HostPhoneProfile extends PhoneProfile { /** * 電話番号のサイズ. */ private static final int MAX_PHONE_NUMBER_SIZE = 13; private final DConnectApi mPostCallApi = new PostApi() { @Override public String getAttribute() { return ATTRIBUTE_CALL; } @Override public boolean onRequest(final Intent request, final Intent response) { final String phoneNumber = getPhoneNumber(request); if (phoneNumber != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { PermissionUtility.requestPermissions(getContext(), new Handler(Looper.getMainLooper()), new String[] { Manifest.permission.CALL_PHONE }, new PermissionUtility.PermissionRequestCallback() { @Override public void onSuccess() { onPostCallInternal(request, response, phoneNumber); sendResponse(response); } @Override public void onFail(@NonNull String deniedPermission) { MessageUtils.setIllegalServerStateError(response, "CALL_PHONE permission not granted."); sendResponse(response); } }); return false; } onPostCallInternal(request, response, phoneNumber); } else { MessageUtils.setInvalidRequestParameterError(response, "phoneNumber is invalid."); } return true; } }; private final DConnectApi mPutSetApi = new PutApi() { @Override public String getAttribute() { return ATTRIBUTE_SET; } @Override public boolean onRequest(final Intent request, final Intent response) { PhoneMode mode = getMode(request); // AudioManager AudioManager mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); if (mode.equals(PhoneMode.SILENT)) { mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT); setResult(response, DConnectMessage.RESULT_OK); } else if (mode.equals(PhoneMode.SOUND)) { mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); setResult(response, DConnectMessage.RESULT_OK); } else if (mode.equals(PhoneMode.MANNER)) { mAudioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE); setResult(response, DConnectMessage.RESULT_OK); } else if (mode.equals(PhoneMode.UNKNOWN)) { MessageUtils.setInvalidRequestParameterError(response, "mode is invalid."); } return true; } }; private final DConnectApi mPutOnConnectApi = new PutApi() { @Override public String getAttribute() { return ATTRIBUTE_ON_CONNECT; } @Override public boolean onRequest(final Intent request, final Intent response) { EventError error = EventManager.INSTANCE.addEvent(request); if (error == EventError.NONE) { setResult(response, DConnectMessage.RESULT_OK); } else { switch (error) { case FAILED: MessageUtils.setUnknownError(response, "Do not unregister event."); break; case INVALID_PARAMETER: MessageUtils.setInvalidRequestParameterError(response); break; case NOT_FOUND: MessageUtils.setUnknownError(response, "Event not found."); break; default: MessageUtils.setUnknownError(response); break; } } return true; } }; private final DConnectApi mDeleteOnConnectApi = new DeleteApi() { @Override public String getAttribute() { return ATTRIBUTE_ON_CONNECT; } @Override public boolean onRequest(final Intent request, final Intent response) { EventError error = EventManager.INSTANCE.removeEvent(request); if (error == EventError.NONE) { setResult(response, DConnectMessage.RESULT_OK); } else { switch (error) { case FAILED: MessageUtils.setUnknownError(response, "Do not unregister event."); break; case INVALID_PARAMETER: MessageUtils.setInvalidRequestParameterError(response); break; case NOT_FOUND: MessageUtils.setUnknownError(response, "Event not found."); break; default: MessageUtils.setUnknownError(response); break; } } return true; } }; public HostPhoneProfile() { addApi(mPostCallApi); addApi(mPutSetApi); addApi(mPutOnConnectApi); addApi(mDeleteOnConnectApi); } private void onPostCallInternal(final Intent request, final Intent response, final String phoneNumber) { try { if (!checkPhoneNumber(phoneNumber)) { MessageUtils.setInvalidRequestParameterError(response, "phoneNumber is invalid."); return; } Uri uri = Uri.parse("tel:" + phoneNumber); if (uri != null) { call(uri); setResult(response, DConnectMessage.RESULT_OK); } else { MessageUtils.setInvalidRequestParameterError(response, "phoneNumber is invalid."); } } catch (Throwable throwable) { MessageUtils.setUnknownError(response, "Failed to make a phone call."); } } /** * 電話番号のフォーマットチェックを行う. * * @param phoneNumber 電話番号 * @return 電話番号の場合はtrue、それ以外はfalse */ private boolean checkPhoneNumber(final String phoneNumber) { if (phoneNumber == null) { return false; } if (phoneNumber.length() > MAX_PHONE_NUMBER_SIZE) { return false; } String pattern = "[0-9+]+"; return phoneNumber.matches(pattern); } private void call(final Uri uri) { Intent intent = new Intent(Intent.ACTION_CALL, uri); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getContext().startActivity(intent); } }