Android 通过阿里语音实现打电话功能

一:捋清楚打电话的逻辑

        语音实现打电话功能,说难不难,说简单不简单,从表面现象来看,打电话其实很简单,但是其中还是很多奥秘的,要想把打电话,得先把打电话的逻辑思考好,打电话的逻辑分为三种情况:

       (1) 当通讯录里名字只有一个电话号码的时候

          说:打电话给 XX 时

          回:正在为您拨打 XX 电话

          呼叫:跳转到手机拨打电话的界面

          取消:回答录音界面

        (2) 当通讯录里面有多个名字多个号码的时

          说:打电话给 XX 时

          回:找到多个联系人,请选择第几个

          说:第一个

          回:正在为你拨打 XX 的电话

          取消:回答录音界面

           (3) 当通讯录没有名字的时候

             说:打电话给 XX 

             回: 找不到联系人,请再说一遍

注意: 在语音识别到打电话的时候,必须先动态申请打电话的权限,如果没有申请权限,就要用一个友好的提示框提示用户先申请权限。

附加上以上三种情况的原型图,便于理解

第一种情况

 Android 通过阿里语音实现打电话功能_第1张图片 

 

第二种情况

Android 通过阿里语音实现打电话功能_第2张图片

二:实现功能

 话不多说,先贴一个查找通讯录的工具类

****打电话使用的类**********/

public class PhoneUtils {
    public static boolean matchPhone(String value) {
        Pattern p = Pattern.compile("[幺零一二三四五六七八九万亿壹贰叁肆伍陆柒捌玖萬]{3,}");
        Matcher m = p.matcher(value);
        if (m.matches()) {
            return true;
        } else {
            return false;
        }
    }

    //电话为数字
    public static void CallPhoneByNumber(Context context, String phone) {
        //String phoneNumber = getPhoneNumber(phone);
        Intent intent = new Intent(Intent.ACTION_CALL);
        Uri data = Uri.parse("tel:" + phone);
        intent.setData(data);
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }

    public static String getPhoneNumber(String phone) {
        StringBuffer buffer = new StringBuffer();
        char[] chars = phone.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            buffer.append(getNumber(chars[i] + ""));
        }
        return buffer.toString();
    }

    public static String getNumber(String value) {
        String phone = "";
        switch (value) {
            case "幺":
            case "一":
            case "壹":
                phone = "1";
                break;
            case "贰":
            case "二":
                phone = "2";
                break;
            case "三":
            case "叁":
                phone = "3";
                break;
            case "肆":
            case "四":
                phone = "4";
                break;
            case "伍":
            case "五":
                phone = "5";
                break;
            case "陆":
            case "六":
                phone = "6";
                break;
            case "柒":
            case "七":
                phone = "7";
                break;
            case "捌":
            case "八":
                phone = "8";
                break;
            case "玖":
            case "九":
                phone = "9";
                break;
            case "萬":
            case "万":
                phone = "0000";
                break;
            case "零":
                phone = "0";
                break;
            default:
                phone = "";
                break;
        }
        return phone;
    }

    //电话为名称
    public static void CallPhoneByName(Context context, String name) {
        Intent intent = new Intent(Intent.ACTION_CALL);
        Uri data = Uri.parse("tel:" + name);
        intent.setData(data);
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);

    }

    /**
     * 通过名字来查找通讯录
     *
     * @param value
     * @return
     */
    public static ArrayList doNameFindContacts(Context context, String value) {
        ArrayList phoneInfos = new ArrayList<>();
        Cursor cursor = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
        if (cursor != null) {
            int count = 0;
            while (cursor.moveToNext()) {
                String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
                String contactsName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                if (Pattern.compile(PinYin.getReplaceString(value)).matcher(PinYin.getPinYin(contactsName)).find()) {
                    Cursor phone = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                            ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null);
                    if (phone != null) {
                        while (phone.moveToNext()) {
                            String contactsNumber = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                            PhoneInfo info = new PhoneInfo();
                            info = new PhoneInfo();
                            info.setName(contactsName);
                            info.setNumber(contactsNumber);
                            info.setIndex(count);
                            phoneInfos.add(info);
                            count++;
                        }
                    }
                }
            }
            cursor.close();
        }
        return phoneInfos;
    }


    //判断手机是否安装某应用
    public static boolean isAppInstall(Context context, String packageName) {
        PackageInfo packageInfo;
        try {
            packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
        } catch (PackageManager.NameNotFoundException e) {
            packageInfo = null;
            e.printStackTrace();
        }
        if (packageInfo == null) {
            return false;
        } else {
            return true;
        }
    }

}

 

/******************************   模糊查询  ************************/
public class HanziToPinyin3 {
    private static final String TAG = "HanziToPinyin";

    // Turn on this flag when we want to check internal data structure.
    private static final boolean DEBUG = false;

    /**
     * Unihans array.
     * 

* Each unihans is the first one within same pinyin when collator is zh_CN. */ public static final char[] UNIHANS = { '\u963f', '\u54ce', '\u5b89', '\u80ae', '\u51f9', '\u516b', '\u6300', '\u6273', '\u90a6', '\u52f9', '\u9642', '\u5954', '\u4f3b', '\u5c44', '\u8fb9', '\u706c', '\u618b', '\u6c43', '\u51ab', '\u7676', '\u5cec', '\u5693', '\u5072', '\u53c2', '\u4ed3', '\u64a1', '\u518a', '\u5d7e', '\u66fd', '\u66fe', '\u5c64', '\u53c9', '\u8286', '\u8fbf', '\u4f25', '\u6284', '\u8f66', '\u62bb', '\u6c88', '\u6c89', '\u9637', '\u5403', '\u5145', '\u62bd', '\u51fa', '\u6b3b', '\u63e3', '\u5ddb', '\u5205', '\u5439', '\u65fe', '\u9034', '\u5472', '\u5306', '\u51d1', '\u7c97', '\u6c46', '\u5d14', '\u90a8', '\u6413', '\u5491', '\u5446', '\u4e39', '\u5f53', '\u5200', '\u561a', '\u6265', '\u706f', '\u6c10', '\u55f2', '\u7538', '\u5201', '\u7239', '\u4e01', '\u4e1f', '\u4e1c', '\u543a', '\u53be', '\u8011', '\u8968', '\u5428', '\u591a', '\u59b8', '\u8bf6', '\u5940', '\u97a5', '\u513f', '\u53d1', '\u5e06', '\u531a', '\u98de', '\u5206', '\u4e30', '\u8985', '\u4ecf', '\u7d11', '\u4f15', '\u65ee', '\u4f85', '\u7518', '\u5188', '\u768b', '\u6208', '\u7ed9', '\u6839', '\u522f', '\u5de5', '\u52fe', '\u4f30', '\u74dc', '\u4e56', '\u5173', '\u5149', '\u5f52', '\u4e28', '\u5459', '\u54c8', '\u548d', '\u4f44', '\u592f', '\u8320', '\u8bc3', '\u9ed2', '\u62eb', '\u4ea8', '\u5677', '\u53ff', '\u9f41', '\u4e6f', '\u82b1', '\u6000', '\u72bf', '\u5ddf', '\u7070', '\u660f', '\u5419', '\u4e0c', '\u52a0', '\u620b', '\u6c5f', '\u827d', '\u9636', '\u5dfe', '\u5755', '\u5182', '\u4e29', '\u51e5', '\u59e2', '\u5658', '\u519b', '\u5494', '\u5f00', '\u520a', '\u5ffc', '\u5c3b', '\u533c', '\u808e', '\u52a5', '\u7a7a', '\u62a0', '\u625d', '\u5938', '\u84af', '\u5bbd', '\u5321', '\u4e8f', '\u5764', '\u6269', '\u5783', '\u6765', '\u5170', '\u5577', '\u635e', '\u808b', '\u52d2', '\u5d1a', '\u5215', '\u4fe9', '\u5941', '\u826f', '\u64a9', '\u5217', '\u62ce', '\u5222', '\u6e9c', '\u56d6', '\u9f99', '\u779c', '\u565c', '\u5a08', '\u7567', '\u62a1', '\u7f57', '\u5463', '\u5988', '\u57cb', '\u5ada', '\u7264', '\u732b', '\u4e48', '\u5445', '\u95e8', '\u753f', '\u54aa', '\u5b80', '\u55b5', '\u4e5c', '\u6c11', '\u540d', '\u8c2c', '\u6478', '\u54de', '\u6bea', '\u55ef', '\u62cf', '\u8149', '\u56e1', '\u56d4', '\u5b6c', '\u7592', '\u5a1e', '\u6041', '\u80fd', '\u59ae', '\u62c8', '\u5b22', '\u9e1f', '\u634f', '\u56dc', '\u5b81', '\u599e', '\u519c', '\u7fba', '\u5974', '\u597b', '\u759f', '\u9ec1', '\u90cd', '\u5594', '\u8bb4', '\u5991', '\u62cd', '\u7705', '\u4e53', '\u629b', '\u5478', '\u55b7', '\u5309', '\u4e15', '\u56e8', '\u527d', '\u6c15', '\u59d8', '\u4e52', '\u948b', '\u5256', '\u4ec6', '\u4e03', '\u6390', '\u5343', '\u545b', '\u6084', '\u767f', '\u4eb2', '\u72c5', '\u828e', '\u4e18', '\u533a', '\u5cd1', '\u7f3a', '\u590b', '\u5465', '\u7a63', '\u5a06', '\u60f9', '\u4eba', '\u6254', '\u65e5', '\u8338', '\u53b9', '\u909a', '\u633c', '\u5827', '\u5a51', '\u77a4', '\u637c', '\u4ee8', '\u6be2', '\u4e09', '\u6852', '\u63bb', '\u95aa', '\u68ee', '\u50e7', '\u6740', '\u7b5b', '\u5c71', '\u4f24', '\u5f30', '\u5962', '\u7533', '\u8398', '\u6552', '\u5347', '\u5c38', '\u53ce', '\u4e66', '\u5237', '\u8870', '\u95e9', '\u53cc', '\u8c01', '\u542e', '\u8bf4', '\u53b6', '\u5fea', '\u635c', '\u82cf', '\u72fb', '\u590a', '\u5b59', '\u5506', '\u4ed6', '\u56fc', '\u574d', '\u6c64', '\u5932', '\u5fd1', '\u71a5', '\u5254', '\u5929', '\u65eb', '\u5e16', '\u5385', '\u56f2', '\u5077', '\u51f8', '\u6e4d', '\u63a8', '\u541e', '\u4e47', '\u7a75', '\u6b6a', '\u5f2f', '\u5c23', '\u5371', '\u6637', '\u7fc1', '\u631d', '\u4e4c', '\u5915', '\u8672', '\u4eda', '\u4e61', '\u7071', '\u4e9b', '\u5fc3', '\u661f', '\u51f6', '\u4f11', '\u5401', '\u5405', '\u524a', '\u5743', '\u4e2b', '\u6079', '\u592e', '\u5e7a', '\u503b', '\u4e00', '\u56d9', '\u5e94', '\u54df', '\u4f63', '\u4f18', '\u625c', '\u56e6', '\u66f0', '\u6655', '\u7b60', '\u7b7c', '\u5e00', '\u707d', '\u5142', '\u5328', '\u50ae', '\u5219', '\u8d3c', '\u600e', '\u5897', '\u624e', '\u635a', '\u6cbe', '\u5f20', '\u957f', '\u9577', '\u4f4b', '\u8707', '\u8d1e', '\u4e89', '\u4e4b', '\u5cd9', '\u5ea2', '\u4e2d', '\u5dde', '\u6731', '\u6293', '\u62fd', '\u4e13', '\u5986', '\u96b9', '\u5b92', '\u5353', '\u4e72', '\u5b97', '\u90b9', '\u79df', '\u94bb', '\u539c', '\u5c0a', '\u6628', '\u5159', '\u9fc3', '\u9fc4',}; /** * Pinyin array. *

* Each pinyin is corresponding to unihans of same * offset in the unihans array. */ public static final byte[][] PINYINS = { {65, 0, 0, 0, 0, 0}, {65, 73, 0, 0, 0, 0}, {65, 78, 0, 0, 0, 0}, {65, 78, 71, 0, 0, 0}, {65, 79, 0, 0, 0, 0}, {66, 65, 0, 0, 0, 0}, {66, 65, 73, 0, 0, 0}, {66, 65, 78, 0, 0, 0}, {66, 65, 78, 71, 0, 0}, {66, 65, 79, 0, 0, 0}, {66, 69, 73, 0, 0, 0}, {66, 69, 78, 0, 0, 0}, {66, 69, 78, 71, 0, 0}, {66, 73, 0, 0, 0, 0}, {66, 73, 65, 78, 0, 0}, {66, 73, 65, 79, 0, 0}, {66, 73, 69, 0, 0, 0}, {66, 73, 78, 0, 0, 0}, {66, 73, 78, 71, 0, 0}, {66, 79, 0, 0, 0, 0}, {66, 85, 0, 0, 0, 0}, {67, 65, 0, 0, 0, 0}, {67, 65, 73, 0, 0, 0}, {67, 65, 78, 0, 0, 0}, {67, 65, 78, 71, 0, 0}, {67, 65, 79, 0, 0, 0}, {67, 69, 0, 0, 0, 0}, {67, 69, 78, 0, 0, 0}, {67, 69, 78, 71, 0, 0}, {90, 69, 78, 71, 0, 0}, {67, 69, 78, 71, 0, 0}, {67, 72, 65, 0, 0, 0}, {67, 72, 65, 73, 0, 0}, {67, 72, 65, 78, 0, 0}, {67, 72, 65, 78, 71, 0}, {67, 72, 65, 79, 0, 0}, {67, 72, 69, 0, 0, 0}, {67, 72, 69, 78, 0, 0}, {83, 72, 69, 78, 0, 0}, {67, 72, 69, 78, 0, 0}, {67, 72, 69, 78, 71, 0}, {67, 72, 73, 0, 0, 0}, {67, 72, 79, 78, 71, 0}, {67, 72, 79, 85, 0, 0}, {67, 72, 85, 0, 0, 0}, {67, 72, 85, 65, 0, 0}, {67, 72, 85, 65, 73, 0}, {67, 72, 85, 65, 78, 0}, {67, 72, 85, 65, 78, 71}, {67, 72, 85, 73, 0, 0}, {67, 72, 85, 78, 0, 0}, {67, 72, 85, 79, 0, 0}, {67, 73, 0, 0, 0, 0}, {67, 79, 78, 71, 0, 0}, {67, 79, 85, 0, 0, 0}, {67, 85, 0, 0, 0, 0}, {67, 85, 65, 78, 0, 0}, {67, 85, 73, 0, 0, 0}, {67, 85, 78, 0, 0, 0}, {67, 85, 79, 0, 0, 0}, {68, 65, 0, 0, 0, 0}, {68, 65, 73, 0, 0, 0}, {68, 65, 78, 0, 0, 0}, {68, 65, 78, 71, 0, 0}, {68, 65, 79, 0, 0, 0}, {68, 69, 0, 0, 0, 0}, {68, 69, 78, 0, 0, 0}, {68, 69, 78, 71, 0, 0}, {68, 73, 0, 0, 0, 0}, {68, 73, 65, 0, 0, 0}, {68, 73, 65, 78, 0, 0}, {68, 73, 65, 79, 0, 0}, {68, 73, 69, 0, 0, 0}, {68, 73, 78, 71, 0, 0}, {68, 73, 85, 0, 0, 0}, {68, 79, 78, 71, 0, 0}, {68, 79, 85, 0, 0, 0}, {68, 85, 0, 0, 0, 0}, {68, 85, 65, 78, 0, 0}, {68, 85, 73, 0, 0, 0}, {68, 85, 78, 0, 0, 0}, {68, 85, 79, 0, 0, 0}, {69, 0, 0, 0, 0, 0}, {69, 73, 0, 0, 0, 0}, {69, 78, 0, 0, 0, 0}, {69, 78, 71, 0, 0, 0}, {69, 82, 0, 0, 0, 0}, {70, 65, 0, 0, 0, 0}, {70, 65, 78, 0, 0, 0}, {70, 65, 78, 71, 0, 0}, {70, 69, 73, 0, 0, 0}, {70, 69, 78, 0, 0, 0}, {70, 69, 78, 71, 0, 0}, {70, 73, 65, 79, 0, 0}, {70, 79, 0, 0, 0, 0}, {70, 79, 85, 0, 0, 0}, {70, 85, 0, 0, 0, 0}, {71, 65, 0, 0, 0, 0}, {71, 65, 73, 0, 0, 0}, {71, 65, 78, 0, 0, 0}, {71, 65, 78, 71, 0, 0}, {71, 65, 79, 0, 0, 0}, {71, 69, 0, 0, 0, 0}, {71, 69, 73, 0, 0, 0}, {71, 69, 78, 0, 0, 0}, {71, 69, 78, 71, 0, 0}, {71, 79, 78, 71, 0, 0}, {71, 79, 85, 0, 0, 0}, {71, 85, 0, 0, 0, 0}, {71, 85, 65, 0, 0, 0}, {71, 85, 65, 73, 0, 0}, {71, 85, 65, 78, 0, 0}, {71, 85, 65, 78, 71, 0}, {71, 85, 73, 0, 0, 0}, {71, 85, 78, 0, 0, 0}, {71, 85, 79, 0, 0, 0}, {72, 65, 0, 0, 0, 0}, {72, 65, 73, 0, 0, 0}, {72, 65, 78, 0, 0, 0}, {72, 65, 78, 71, 0, 0}, {72, 65, 79, 0, 0, 0}, {72, 69, 0, 0, 0, 0}, {72, 69, 73, 0, 0, 0}, {72, 69, 78, 0, 0, 0}, {72, 69, 78, 71, 0, 0}, {72, 77, 0, 0, 0, 0}, {72, 79, 78, 71, 0, 0}, {72, 79, 85, 0, 0, 0}, {72, 85, 0, 0, 0, 0}, {72, 85, 65, 0, 0, 0}, {72, 85, 65, 73, 0, 0}, {72, 85, 65, 78, 0, 0}, {72, 85, 65, 78, 71, 0}, {72, 85, 73, 0, 0, 0}, {72, 85, 78, 0, 0, 0}, {72, 85, 79, 0, 0, 0}, {74, 73, 0, 0, 0, 0}, {74, 73, 65, 0, 0, 0}, {74, 73, 65, 78, 0, 0}, {74, 73, 65, 78, 71, 0}, {74, 73, 65, 79, 0, 0}, {74, 73, 69, 0, 0, 0}, {74, 73, 78, 0, 0, 0}, {74, 73, 78, 71, 0, 0}, {74, 73, 79, 78, 71, 0}, {74, 73, 85, 0, 0, 0}, {74, 85, 0, 0, 0, 0}, {74, 85, 65, 78, 0, 0}, {74, 85, 69, 0, 0, 0}, {74, 85, 78, 0, 0, 0}, {75, 65, 0, 0, 0, 0}, {75, 65, 73, 0, 0, 0}, {75, 65, 78, 0, 0, 0}, {75, 65, 78, 71, 0, 0}, {75, 65, 79, 0, 0, 0}, {75, 69, 0, 0, 0, 0}, {75, 69, 78, 0, 0, 0}, {75, 69, 78, 71, 0, 0}, {75, 79, 78, 71, 0, 0}, {75, 79, 85, 0, 0, 0}, {75, 85, 0, 0, 0, 0}, {75, 85, 65, 0, 0, 0}, {75, 85, 65, 73, 0, 0}, {75, 85, 65, 78, 0, 0}, {75, 85, 65, 78, 71, 0}, {75, 85, 73, 0, 0, 0}, {75, 85, 78, 0, 0, 0}, {75, 85, 79, 0, 0, 0}, {76, 65, 0, 0, 0, 0}, {76, 65, 73, 0, 0, 0}, {76, 65, 78, 0, 0, 0}, {76, 65, 78, 71, 0, 0}, {76, 65, 79, 0, 0, 0}, {76, 69, 0, 0, 0, 0}, {76, 69, 73, 0, 0, 0}, {76, 69, 78, 71, 0, 0}, {76, 73, 0, 0, 0, 0}, {76, 73, 65, 0, 0, 0}, {76, 73, 65, 78, 0, 0}, {76, 73, 65, 78, 71, 0}, {76, 73, 65, 79, 0, 0}, {76, 73, 69, 0, 0, 0}, {76, 73, 78, 0, 0, 0}, {76, 73, 78, 71, 0, 0}, {76, 73, 85, 0, 0, 0}, {76, 79, 0, 0, 0, 0}, {76, 79, 78, 71, 0, 0}, {76, 79, 85, 0, 0, 0}, {76, 85, 0, 0, 0, 0}, {76, 85, 65, 78, 0, 0}, {76, 85, 69, 0, 0, 0}, {76, 85, 78, 0, 0, 0}, {76, 85, 79, 0, 0, 0}, {77, 0, 0, 0, 0, 0}, {77, 65, 0, 0, 0, 0}, {77, 65, 73, 0, 0, 0}, {77, 65, 78, 0, 0, 0}, {77, 65, 78, 71, 0, 0}, {77, 65, 79, 0, 0, 0}, {77, 69, 0, 0, 0, 0}, {77, 69, 73, 0, 0, 0}, {77, 69, 78, 0, 0, 0}, {77, 69, 78, 71, 0, 0}, {77, 73, 0, 0, 0, 0}, {77, 73, 65, 78, 0, 0}, {77, 73, 65, 79, 0, 0}, {77, 73, 69, 0, 0, 0}, {77, 73, 78, 0, 0, 0}, {77, 73, 78, 71, 0, 0}, {77, 73, 85, 0, 0, 0}, {77, 79, 0, 0, 0, 0}, {77, 79, 85, 0, 0, 0}, {77, 85, 0, 0, 0, 0}, {78, 0, 0, 0, 0, 0}, {78, 65, 0, 0, 0, 0}, {78, 65, 73, 0, 0, 0}, {78, 65, 78, 0, 0, 0}, {78, 65, 78, 71, 0, 0}, {78, 65, 79, 0, 0, 0}, {78, 69, 0, 0, 0, 0}, {78, 69, 73, 0, 0, 0}, {78, 69, 78, 0, 0, 0}, {78, 69, 78, 71, 0, 0}, {78, 73, 0, 0, 0, 0}, {78, 73, 65, 78, 0, 0}, {78, 73, 65, 78, 71, 0}, {78, 73, 65, 79, 0, 0}, {78, 73, 69, 0, 0, 0}, {78, 73, 78, 0, 0, 0}, {78, 73, 78, 71, 0, 0}, {78, 73, 85, 0, 0, 0}, {78, 79, 78, 71, 0, 0}, {78, 79, 85, 0, 0, 0}, {78, 85, 0, 0, 0, 0}, {78, 85, 65, 78, 0, 0}, {78, 85, 69, 0, 0, 0}, {78, 85, 78, 0, 0, 0}, {78, 85, 79, 0, 0, 0}, {79, 0, 0, 0, 0, 0}, {79, 85, 0, 0, 0, 0}, {80, 65, 0, 0, 0, 0}, {80, 65, 73, 0, 0, 0}, {80, 65, 78, 0, 0, 0}, {80, 65, 78, 71, 0, 0}, {80, 65, 79, 0, 0, 0}, {80, 69, 73, 0, 0, 0}, {80, 69, 78, 0, 0, 0}, {80, 69, 78, 71, 0, 0}, {80, 73, 0, 0, 0, 0}, {80, 73, 65, 78, 0, 0}, {80, 73, 65, 79, 0, 0}, {80, 73, 69, 0, 0, 0}, {80, 73, 78, 0, 0, 0}, {80, 73, 78, 71, 0, 0}, {80, 79, 0, 0, 0, 0}, {80, 79, 85, 0, 0, 0}, {80, 85, 0, 0, 0, 0}, {81, 73, 0, 0, 0, 0}, {81, 73, 65, 0, 0, 0}, {81, 73, 65, 78, 0, 0}, {81, 73, 65, 78, 71, 0}, {81, 73, 65, 79, 0, 0}, {81, 73, 69, 0, 0, 0}, {81, 73, 78, 0, 0, 0}, {81, 73, 78, 71, 0, 0}, {81, 73, 79, 78, 71, 0}, {81, 73, 85, 0, 0, 0}, {81, 85, 0, 0, 0, 0}, {81, 85, 65, 78, 0, 0}, {81, 85, 69, 0, 0, 0}, {81, 85, 78, 0, 0, 0}, {82, 65, 78, 0, 0, 0}, {82, 65, 78, 71, 0, 0}, {82, 65, 79, 0, 0, 0}, {82, 69, 0, 0, 0, 0}, {82, 69, 78, 0, 0, 0}, {82, 69, 78, 71, 0, 0}, {82, 73, 0, 0, 0, 0}, {82, 79, 78, 71, 0, 0}, {82, 79, 85, 0, 0, 0}, {82, 85, 0, 0, 0, 0}, {82, 85, 65, 0, 0, 0}, {82, 85, 65, 78, 0, 0}, {82, 85, 73, 0, 0, 0}, {82, 85, 78, 0, 0, 0}, {82, 85, 79, 0, 0, 0}, {83, 65, 0, 0, 0, 0}, {83, 65, 73, 0, 0, 0}, {83, 65, 78, 0, 0, 0}, {83, 65, 78, 71, 0, 0}, {83, 65, 79, 0, 0, 0}, {83, 69, 0, 0, 0, 0}, {83, 69, 78, 0, 0, 0}, {83, 69, 78, 71, 0, 0}, {83, 72, 65, 0, 0, 0}, {83, 72, 65, 73, 0, 0}, {83, 72, 65, 78, 0, 0}, {83, 72, 65, 78, 71, 0}, {83, 72, 65, 79, 0, 0}, {83, 72, 69, 0, 0, 0}, {83, 72, 69, 78, 0, 0}, {88, 73, 78, 0, 0, 0}, {83, 72, 69, 78, 0, 0}, {83, 72, 69, 78, 71, 0}, {83, 72, 73, 0, 0, 0}, {83, 72, 79, 85, 0, 0}, {83, 72, 85, 0, 0, 0}, {83, 72, 85, 65, 0, 0}, {83, 72, 85, 65, 73, 0}, {83, 72, 85, 65, 78, 0}, {83, 72, 85, 65, 78, 71}, {83, 72, 85, 73, 0, 0}, {83, 72, 85, 78, 0, 0}, {83, 72, 85, 79, 0, 0}, {83, 73, 0, 0, 0, 0}, {83, 79, 78, 71, 0, 0}, {83, 79, 85, 0, 0, 0}, {83, 85, 0, 0, 0, 0}, {83, 85, 65, 78, 0, 0}, {83, 85, 73, 0, 0, 0}, {83, 85, 78, 0, 0, 0}, {83, 85, 79, 0, 0, 0}, {84, 65, 0, 0, 0, 0}, {84, 65, 73, 0, 0, 0}, {84, 65, 78, 0, 0, 0}, {84, 65, 78, 71, 0, 0}, {84, 65, 79, 0, 0, 0}, {84, 69, 0, 0, 0, 0}, {84, 69, 78, 71, 0, 0}, {84, 73, 0, 0, 0, 0}, {84, 73, 65, 78, 0, 0}, {84, 73, 65, 79, 0, 0}, {84, 73, 69, 0, 0, 0}, {84, 73, 78, 71, 0, 0}, {84, 79, 78, 71, 0, 0}, {84, 79, 85, 0, 0, 0}, {84, 85, 0, 0, 0, 0}, {84, 85, 65, 78, 0, 0}, {84, 85, 73, 0, 0, 0}, {84, 85, 78, 0, 0, 0}, {84, 85, 79, 0, 0, 0}, {87, 65, 0, 0, 0, 0}, {87, 65, 73, 0, 0, 0}, {87, 65, 78, 0, 0, 0}, {87, 65, 78, 71, 0, 0}, {87, 69, 73, 0, 0, 0}, {87, 69, 78, 0, 0, 0}, {87, 69, 78, 71, 0, 0}, {87, 79, 0, 0, 0, 0}, {87, 85, 0, 0, 0, 0}, {88, 73, 0, 0, 0, 0}, {88, 73, 65, 0, 0, 0}, {88, 73, 65, 78, 0, 0}, {88, 73, 65, 78, 71, 0}, {88, 73, 65, 79, 0, 0}, {88, 73, 69, 0, 0, 0}, {88, 73, 78, 0, 0, 0}, {88, 73, 78, 71, 0, 0}, {88, 73, 79, 78, 71, 0}, {88, 73, 85, 0, 0, 0}, {88, 85, 0, 0, 0, 0}, {88, 85, 65, 78, 0, 0}, {88, 85, 69, 0, 0, 0}, {88, 85, 78, 0, 0, 0}, {89, 65, 0, 0, 0, 0}, {89, 65, 78, 0, 0, 0}, {89, 65, 78, 71, 0, 0}, {89, 65, 79, 0, 0, 0}, {89, 69, 0, 0, 0, 0}, {89, 73, 0, 0, 0, 0}, {89, 73, 78, 0, 0, 0}, {89, 73, 78, 71, 0, 0}, {89, 79, 0, 0, 0, 0}, {89, 79, 78, 71, 0, 0}, {89, 79, 85, 0, 0, 0}, {89, 85, 0, 0, 0, 0}, {89, 85, 65, 78, 0, 0}, {89, 85, 69, 0, 0, 0}, {89, 85, 78, 0, 0, 0}, {74, 85, 78, 0, 0, 0}, {89, 85, 78, 0, 0, 0}, {90, 65, 0, 0, 0, 0}, {90, 65, 73, 0, 0, 0}, {90, 65, 78, 0, 0, 0}, {90, 65, 78, 71, 0, 0}, {90, 65, 79, 0, 0, 0}, {90, 69, 0, 0, 0, 0}, {90, 69, 73, 0, 0, 0}, {90, 69, 78, 0, 0, 0}, {90, 69, 78, 71, 0, 0}, {90, 72, 65, 0, 0, 0}, {90, 72, 65, 73, 0, 0}, {90, 72, 65, 78, 0, 0}, {90, 72, 65, 78, 71, 0}, {67, 72, 65, 78, 71, 0}, {90, 72, 65, 78, 71, 0}, {90, 72, 65, 79, 0, 0}, {90, 72, 69, 0, 0, 0}, {90, 72, 69, 78, 0, 0}, {90, 72, 69, 78, 71, 0}, {90, 72, 73, 0, 0, 0}, {83, 72, 73, 0, 0, 0}, {90, 72, 73, 0, 0, 0}, {90, 72, 79, 78, 71, 0}, {90, 72, 79, 85, 0, 0}, {90, 72, 85, 0, 0, 0}, {90, 72, 85, 65, 0, 0}, {90, 72, 85, 65, 73, 0}, {90, 72, 85, 65, 78, 0}, {90, 72, 85, 65, 78, 71}, {90, 72, 85, 73, 0, 0}, {90, 72, 85, 78, 0, 0}, {90, 72, 85, 79, 0, 0}, {90, 73, 0, 0, 0, 0}, {90, 79, 78, 71, 0, 0}, {90, 79, 85, 0, 0, 0}, {90, 85, 0, 0, 0, 0}, {90, 85, 65, 78, 0, 0}, {90, 85, 73, 0, 0, 0}, {90, 85, 78, 0, 0, 0}, {90, 85, 79, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {83, 72, 65, 78, 0, 0}, {0, 0, 0, 0, 0, 0},}; /** * First and last Chinese character with known Pinyin according to zh collation */ private static final String FIRST_PINYIN_UNIHAN = "\u963F"; private static final String LAST_PINYIN_UNIHAN = "\u9FFF"; private static final Collator COLLATOR = Collator.getInstance(Locale.CHINA); private static HanziToPinyin3 sInstance; private final boolean mHasChinaCollator; public static class Token { /** * Separator between target string for each source char */ public static final String SEPARATOR = " "; public static final int LATIN = 1; public static final int PINYIN = 2; public static final int UNKNOWN = 3; public Token() { } public Token(int type, String source, String target) { this.type = type; this.source = source; this.target = target; } /** * Type of this token, ASCII, PINYIN or UNKNOWN. */ public int type; /** * Original string before translation. */ public String source; /** * Translated string of source. For Han, target is corresponding Pinyin. Otherwise target is * original string in source. */ public String target; } protected HanziToPinyin3(boolean hasChinaCollator) { mHasChinaCollator = hasChinaCollator; } public static HanziToPinyin3 getInstance() { synchronized (HanziToPinyin3.class) { if (sInstance != null) { return sInstance; } // Check if zh_CN collation data is available final Locale locale[] = Collator.getAvailableLocales(); for (int i = 0; i < locale.length; i++) { if (locale[i].equals(Locale.CHINESE) || locale[i].equals(Locale.CHINA)) { // Do self validation just once. if (DEBUG) { } sInstance = new HanziToPinyin3(true); return sInstance; } } sInstance = new HanziToPinyin3(false); return sInstance; } } /** * Validate if our internal table has some wrong value. * * @return true when the table looks correct. */ private static boolean doSelfValidation() { char lastChar = UNIHANS[0]; String lastString = Character.toString(lastChar); for (char c : UNIHANS) { if (lastChar == c) { continue; } final String curString = Character.toString(c); int cmp = COLLATOR.compare(lastString, curString); if (cmp >= 0) { // Log.e(TAG, "Internal error in Unihan table. " + "The last string \"" + lastString // + "\" is greater than current string \"" + curString + "\"."); return false; } lastString = curString; } return true; } private Token getToken(char character) { Token token = new Token(); final String letter = Character.toString(character); token.source = letter; int offset = -1; int cmp; if (character < 256) { token.type = Token.LATIN; token.target = letter; return token; } else { cmp = COLLATOR.compare(letter, FIRST_PINYIN_UNIHAN); if (cmp < 0) { token.type = Token.UNKNOWN; token.target = letter; return token; } else if (cmp == 0) { token.type = Token.PINYIN; offset = 0; } else { cmp = COLLATOR.compare(letter, LAST_PINYIN_UNIHAN); if (cmp > 0) { token.type = Token.UNKNOWN; token.target = letter; return token; } else if (cmp == 0) { token.type = Token.PINYIN; offset = UNIHANS.length - 1; } } } token.type = Token.PINYIN; if (offset < 0) { int begin = 0; int end = UNIHANS.length - 1; while (begin <= end) { offset = (begin + end) / 2; final String unihan = Character.toString(UNIHANS[offset]); cmp = COLLATOR.compare(letter, unihan); if (cmp == 0) { break; } else if (cmp > 0) { begin = offset + 1; } else { end = offset - 1; } } } if (cmp < 0) { offset--; } StringBuilder pinyin = new StringBuilder(); for (int j = 0; j < PINYINS[offset].length && PINYINS[offset][j] != 0; j++) { pinyin.append((char) PINYINS[offset][j]); } token.target = pinyin.toString(); if (TextUtils.isEmpty(token.target)) { token.type = Token.UNKNOWN; token.target = token.source; } return token; } /** * Convert the input to a array of tokens. The sequence of ASCII or Unknown characters without * space will be put into a Token, One Hanzi character which has pinyin will be treated as a * Token. If these is no China collator, the empty token array is returned. */ public ArrayList get(final String input) { ArrayList tokens = new ArrayList(); if (!mHasChinaCollator || TextUtils.isEmpty(input)) { // return empty tokens. return tokens; } final int inputLength = input.length(); final StringBuilder sb = new StringBuilder(); int tokenType = Token.LATIN; // Go through the input, create a new token when // a. Token type changed // b. Get the Pinyin of current charater. // c. current character is space. for (int i = 0; i < inputLength; i++) { final char character = input.charAt(i); if (character == ' ') { if (sb.length() > 0) { addToken(sb, tokens, tokenType); } } else if (character < 256) { if (tokenType != Token.LATIN && sb.length() > 0) { addToken(sb, tokens, tokenType); } tokenType = Token.LATIN; sb.append(character); } else { Token t = getToken(character); if (t.type == Token.PINYIN) { if (sb.length() > 0) { addToken(sb, tokens, tokenType); } tokens.add(t); tokenType = Token.PINYIN; } else { if (tokenType != t.type && sb.length() > 0) { addToken(sb, tokens, tokenType); } tokenType = t.type; sb.append(character); } } } if (sb.length() > 0) { addToken(sb, tokens, tokenType); } return tokens; } private void addToken( final StringBuilder sb, final ArrayList tokens, final int tokenType) { String str = sb.toString(); tokens.add(new Token(tokenType, str, str)); sb.setLength(0); } }

/************** 模糊查询辅助类 ******************************/
public class PinYin {

    /**
     * 汉字返回拼音,字母原样返回,都转换为小写
     * @param input
     * @return
     */
    public static String getPinYin(String input) {
        ArrayList tokens = HanziToPinyin3.getInstance().get(input);
        StringBuilder sb = new StringBuilder();
        if (tokens != null && tokens.size() > 0) {
            for (HanziToPinyin3.Token token : tokens) {
                if (HanziToPinyin3.Token.PINYIN == token.type) {
                    sb.append(token.target);
                }else {
                    sb.append(token.source);
                }
            }
        }
        return sb.toString().toLowerCase();
    }

    /**
     * 利用正则表达式来通过混淆拼音模糊查询通讯录
     * @param value
     * @return
     */
    public static String getReplaceString(String value){
        String pinyinStr = null;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < value.length(); i++){
            String replace = value.substring(i, i + 1);
            pinyinStr = getPinYin(replace);
            if (Pattern.compile("^[zcs]").matcher(pinyinStr).lookingAt()){
                Pattern beginRange = Pattern.compile("^[zcs]h?");
                Matcher matcher = beginRange.matcher(pinyinStr);
                while (matcher.find()){ //必须要有这个方法,没有会报异常
                    String groupStr = matcher.group();
                    String replaceStr = String.format("%s%s?", groupStr, groupStr.length() == 1 ? "h" : "");
                    pinyinStr = matcher.replaceAll(replaceStr);
                }
            }else if (Pattern.compile("^[ln]").matcher(pinyinStr).lookingAt()){
                Pattern beginRange = Pattern.compile("^[ln]");
                Matcher matcher = beginRange.matcher(pinyinStr);
                while (matcher.find()){
                    String replaceStr = String.format("%s", "[ln]");
                    pinyinStr = matcher.replaceAll(replaceStr);
                }
            }
            if (Pattern.compile("(ang?$)|(eng?$)|(ing?$)").matcher(pinyinStr).find()){
                Pattern beginRange = Pattern.compile("(ang?$)|(eng?$)|(ing?$)");
                Matcher matcher = beginRange.matcher(pinyinStr);
                while (matcher.find()){
                    String groupStr = matcher.group();
                    String replaceStr = String.format("%s%s?", groupStr, groupStr.length() == 2 ? "g" : "");
                    pinyinStr = matcher.replaceAll(replaceStr);
                }
            }
            sb.append(".*").append(pinyinStr);
            pinyinStr = sb.toString() + ".*";
        }
        return pinyinStr;
    }
}

 

/***********  通讯录实体类 **************/
public class PhoneInfo implements Parcelable {

    private String name;
    private String number;
    private int index;
    private String province;

    public PhoneInfo() {
    }

    public PhoneInfo(Parcel in) {
        name = in.readString();
        number = in.readString();
    }

    public static final Creator CREATOR = new Creator() {
        @Override
        public PhoneInfo createFromParcel(Parcel in) {
            return new PhoneInfo(in);
        }

        @Override
        public PhoneInfo[] newArray(int size) {
            return new PhoneInfo[size];
        }
    };

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeString(number);
    }

    @Override
    public String toString() {
        return "PhoneInfo{" +
                "name='" + name + '\'' +
                ", number='" + number + '\'' +
                ", index=" + index +
                ", province='" + province + '\'' +
                '}';
    }
}

好了,有了这个工具类,就可以通过你语音返回的数据,拿到服务器返回的 Service 类型,简而言之就是拿到 phone 这个service,然后拿到名字,再去和通讯录匹配

fun callPhone() {
    runOnUiThread {
        //自己说的话
        var textPhone = customCallPhone!!.value
        if (textPhone.isNotEmpty()) {
            //电话号码
            if (PhoneUtils.matchPhone(textPhone)) {
                //数字电话号码
                val phoneNumber = PhoneUtils.getPhoneNumber(textPhone)
               // mAliRecorderManager.startSpeaking("正在为您拨打$phoneNumber")
                mConetrollerDataList.add(SpeakBean(SpeakBean.Person, queryText, App.instance.selectRecorderModel))
                mConetrollerDataList.add(SpeakBean(SpeakBean.Robot, phoneNumber, null, serviceType, PhoneStatus(true, Phone())))
            } else {
                //人名
                if (customCallPhone == null) {
                    return@runOnUiThread
                }
                val mPhoneName = customCallPhone!!.value
                val doNameFindContacts = PhoneUtils.doNameFindContacts(this, mPhoneName)
                if (doNameFindContacts.size == 0) {
                    //通信录找不到
                    mConetrollerDataList.add(SpeakBean(SpeakBean.Person, queryText, App.instance.selectRecorderModel))
                    mConetrollerDataList.add(SpeakBean(SpeakBean.Robot, getString(R.string.text_find_contact_please_again), doNameFindContacts, serviceType, PhoneStatus(true, Phone())))
                    mAliRecorderManager.startSpeaking(getString(R.string.text_find_contact_please_again))

                } else {
                    //不为空,有
                    mConetrollerDataList.add(SpeakBean(SpeakBean.Person, queryText, App.instance.selectRecorderModel))
                    mConetrollerDataList.add(SpeakBean(SpeakBean.Robot, "", doNameFindContacts, serviceType, PhoneStatus(true, Phone())))

                    if (doNameFindContacts.size == 1) {
                       // AliRecorderManager.instance.startSpeaking(mContext.getString(R.string.text_call_contact_number, doNameFindContacts[0].name))// TTS 播报
                    } else {
                        AliRecorderManager.instance.startSpeaking(mContext.getString(R.string.text_find_more_contacts))// TTS 播报
                    }
                }
            }
        }
        updateUI(mConetrollerDataList)
    }
}

UI 显示的话,个人建议用嵌套的的 Recycleview,只要对其进行显隐的操作就 ok 了,我给的工具类应该可以满足各种语言查询通讯录的要求,我只贴出了实现查询的代码示例, UI 逻辑交互方面实在太多了,就没有贴出来,望各位仁兄海涵

你可能感兴趣的:(Android 通过阿里语音实现打电话功能)