com.mobileglobe.android.customdialer.common.compat.telecom.TelecomManagerCompat.java Source code

Java tutorial

Introduction

Here is the source code for com.mobileglobe.android.customdialer.common.compat.telecom.TelecomManagerCompat.java

Source

/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mobileglobe.android.customdialer.common.compat.telecom;

import android.Manifest;
import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import com.mobileglobe.android.customdialer.DialerApplication;
import com.mobileglobe.android.customdialer.common.compat.CompatUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * Compatibility class for {@link TelecomManager}.
 */
public class TelecomManagerCompat {
    public static final String TELECOM_MANAGER_CLASS = "android.telecom.TelecomManager";

    /**
     * Places a new outgoing call to the provided address using the system telecom service with
     * the specified intent.
     *
     * @param activity {@link Activity} used to start another activity for the given intent
     * @param telecomManager the {@link TelecomManager} used to place a call, if possible
     * @param intent the intent for the call
     */
    public static void placeCall(@Nullable Activity activity, @Nullable TelecomManager telecomManager,
            @Nullable Intent intent) {
        if (activity == null || telecomManager == null || intent == null) {
            return;
        }
        if (CompatUtils.isMarshmallowCompatible()) {
            if (ActivityCompat.checkSelfPermission(activity,
                    Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            telecomManager.placeCall(intent.getData(), intent.getExtras());
            return;
        }
        activity.startActivityForResult(intent, 0);
    }

    /**
     * Get the URI for running an adn query.
     *
     * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
     * @param accountHandle The handle for the account to derive an adn query URI for or
     * {@code null} to return a URI which will use the default account.
     * @return The URI (with the content:// scheme) specific to the specified {@link PhoneAccount}
     * for the the content retrieve.
     */
    public static Uri getAdnUriForPhoneAccount(@Nullable TelecomManager telecomManager,
            PhoneAccountHandle accountHandle) {
        if (telecomManager != null && (CompatUtils.isMarshmallowCompatible() || CompatUtils
                .isMethodAvailable(TELECOM_MANAGER_CLASS, "getAdnUriForPhoneAccount", PhoneAccountHandle.class))) {
            return telecomManager.getAdnUriForPhoneAccount(accountHandle);
        }
        return Uri.parse("content://icc/adn");
    }

    /**
     * Returns a list of {@link PhoneAccountHandle}s which can be used to make and receive phone
     * calls. The returned list includes only those accounts which have been explicitly enabled
     * by the user.
     *
     * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
     * @return A list of PhoneAccountHandle objects.
     */
    public static List<PhoneAccountHandle> getCallCapablePhoneAccounts(@Nullable TelecomManager telecomManager) {
        if (telecomManager != null && (CompatUtils.isMarshmallowCompatible()
                || CompatUtils.isMethodAvailable(TELECOM_MANAGER_CLASS, "getCallCapablePhoneAccounts"))) {
            if (ActivityCompat.checkSelfPermission(DialerApplication.getContext(),
                    Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return new ArrayList<>();
            }
            return telecomManager.getCallCapablePhoneAccounts();
        }
        return new ArrayList<>();
    }

    /**
     * Used to determine the currently selected default dialer package.
     *
     * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
     * @return package name for the default dialer package or null if no package has been
     *         selected as the default dialer.
     */
    @Nullable
    public static String getDefaultDialerPackage(@Nullable TelecomManager telecomManager) {
        if (telecomManager != null && CompatUtils.isDefaultDialerCompatible()) {
            return telecomManager.getDefaultDialerPackage();
        }
        return null;
    }

    /**
     * Return the {@link PhoneAccount} which will be used to place outgoing calls to addresses with
     * the specified {@code uriScheme}. This PhoneAccount will always be a member of the
     * list which is returned from invoking {@link TelecomManager#getCallCapablePhoneAccounts()}.
     * The specific account returned depends on the following priorities:
     *
     * 1. If the user-selected default PhoneAccount supports the specified scheme, it will
     * be returned.
     * 2. If there exists only one PhoneAccount that supports the specified scheme, it
     * will be returned.
     *
     * If no PhoneAccount fits the criteria above, this method will return {@code null}.
     *
     * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
     * @param uriScheme The URI scheme.
     * @return The {@link PhoneAccountHandle} corresponding to the account to be used.
     */
    @Nullable
    public static PhoneAccountHandle getDefaultOutgoingPhoneAccount(@Nullable TelecomManager telecomManager,
            @Nullable String uriScheme) {
        if (telecomManager != null && (CompatUtils.isMarshmallowCompatible() || CompatUtils
                .isMethodAvailable(TELECOM_MANAGER_CLASS, "getDefaultOutgoingPhoneAccount", String.class))) {
            if (ActivityCompat.checkSelfPermission(DialerApplication.getContext(),
                    Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return null;
            }
            return telecomManager.getDefaultOutgoingPhoneAccount(uriScheme);
        }
        return null;
    }

    /**
     * Return the line 1 phone number for given phone account.
     *
     * @param telecomManager the {@link TelecomManager} to use in the event that
     *    {@link TelecomManager#getLine1Number(PhoneAccountHandle)} is available
     * @param telephonyManager the {@link TelephonyManager} to use if TelecomManager#getLine1Number
     *    is unavailable
     * @param phoneAccountHandle the phoneAccountHandle upon which to check the line one number
     * @return the line one number
     */
    @Nullable
    public static String getLine1Number(@Nullable TelecomManager telecomManager,
            @Nullable TelephonyManager telephonyManager, @Nullable PhoneAccountHandle phoneAccountHandle) {
        if (telecomManager != null && CompatUtils.isMarshmallowCompatible()) {
            if (ActivityCompat.checkSelfPermission(DialerApplication.getContext(),
                    Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return null;
            }
            return telecomManager.getLine1Number(phoneAccountHandle);
        }
        if (telephonyManager != null) {
            return telephonyManager.getLine1Number();
        }
        return null;
    }

    /**
     * Return whether a given phone number is the configured voicemail number for a
     * particular phone account.
     *
     * @param telecomManager the {@link TelecomManager} to use for checking the number.
     * @param accountHandle The handle for the account to check the voicemail number against
     * @param number The number to look up.
     */
    public static boolean isVoiceMailNumber(@Nullable TelecomManager telecomManager,
            @Nullable PhoneAccountHandle accountHandle, @Nullable String number) {
        if (telecomManager != null
                && (CompatUtils.isMarshmallowCompatible() || CompatUtils.isMethodAvailable(TELECOM_MANAGER_CLASS,
                        "isVoiceMailNumber", PhoneAccountHandle.class, String.class))) {
            if (ActivityCompat.checkSelfPermission(DialerApplication.getContext(),
                    Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return false;
            }
            return telecomManager.isVoiceMailNumber(accountHandle, number);
        }

        return PhoneNumberUtils.isVoiceMailNumber(number);
    }

    /**
     * Return the {@link PhoneAccount} for a specified {@link PhoneAccountHandle}. Object includes
     * resources which can be used in a user interface.
     *
     * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
     * @param account The {@link PhoneAccountHandle}.
     * @return The {@link PhoneAccount} object or null if it doesn't exist.
     */
    @Nullable
    public static PhoneAccount getPhoneAccount(@Nullable TelecomManager telecomManager,
            @Nullable PhoneAccountHandle accountHandle) {
        if (telecomManager != null && (CompatUtils.isMethodAvailable(TELECOM_MANAGER_CLASS, "getPhoneAccount",
                PhoneAccountHandle.class))) {
            return telecomManager.getPhoneAccount(accountHandle);
        }
        return null;
    }

    /**
     * Return the voicemail number for a given phone account.
     *
     * @param telecomManager The {@link TelecomManager} object to use for retrieving the voicemail
     * number if accountHandle is specified.
     * @param telephonyManager The {@link TelephonyManager} object to use for retrieving the
     * voicemail number if accountHandle is null.
     * @param accountHandle The handle for the phone account.
     * @return The voicemail number for the phone account, and {@code null} if one has not been
     *         configured.
     */
    @Nullable
    public static String getVoiceMailNumber(@Nullable TelecomManager telecomManager,
            @Nullable TelephonyManager telephonyManager, @Nullable PhoneAccountHandle accountHandle) {
        if (telecomManager != null && (CompatUtils.isMethodAvailable(TELECOM_MANAGER_CLASS, "getVoiceMailNumber",
                PhoneAccountHandle.class))) {
            if (ActivityCompat.checkSelfPermission(DialerApplication.getContext(),
                    Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return null;
            }
            return telecomManager.getVoiceMailNumber(accountHandle);
        } else if (telephonyManager != null) {
            return telephonyManager.getVoiceMailNumber();
        }
        return null;
    }

    /**
     * Processes the specified dial string as an MMI code.
     * MMI codes are any sequence of characters entered into the dialpad that contain a "*" or "#".
     * Some of these sequences launch special behavior through handled by Telephony.
     *
     * @param telecomManager The {@link TelecomManager} object to use for handling MMI.
     * @param dialString The digits to dial.
     * @return {@code true} if the digits were processed as an MMI code, {@code false} otherwise.
     */
    public static boolean handleMmi(@Nullable TelecomManager telecomManager, @Nullable String dialString,
            @Nullable PhoneAccountHandle accountHandle) {
        if (telecomManager == null || TextUtils.isEmpty(dialString)) {
            return false;
        }
        if (CompatUtils.isMarshmallowCompatible()) {
            return telecomManager.handleMmi(dialString, accountHandle);
        }

        Object handleMmiResult = CompatUtils.invokeMethod(telecomManager, "handleMmi",
                new Class<?>[] { PhoneAccountHandle.class, String.class },
                new Object[] { accountHandle, dialString });
        if (handleMmiResult != null) {
            return (boolean) handleMmiResult;
        }

        return telecomManager.handleMmi(dialString);
    }

    /**
     * Silences the ringer if a ringing call exists. Noop if {@link TelecomManager#silenceRinger()}
     * is unavailable.
     *
     * @param telecomManager the TelecomManager to use to silence the ringer.
     */
    public static void silenceRinger(@Nullable TelecomManager telecomManager) {
        if (telecomManager != null && (CompatUtils.isMarshmallowCompatible()
                || CompatUtils.isMethodAvailable(TELECOM_MANAGER_CLASS, "silenceRinger"))) {
            telecomManager.silenceRinger();
        }
    }

    /**
     * Returns the current SIM call manager. Apps must be prepared for this method to return null,
     * indicating that there currently exists no registered SIM call manager.
     *
     * @param telecomManager the {@link TelecomManager} to use to fetch the SIM call manager.
     * @return The phone account handle of the current sim call manager.
     */
    @Nullable
    public static PhoneAccountHandle getSimCallManager(TelecomManager telecomManager) {
        if (telecomManager != null && (CompatUtils.isMarshmallowCompatible()
                || CompatUtils.isMethodAvailable(TELECOM_MANAGER_CLASS, "getSimCallManager"))) {
            return telecomManager.getSimCallManager();
        }
        return null;
    }
}