zoukankan      html  css  js  c++  java
  • Android为拨号盘dialer定制声音DTMF Tones

    DTMF :双音多频,电话系统中电话机与交换机之间的一种用户信令,通常用于发送被叫号码。

    双音多频的拨号键盘是4*4的矩阵,每一行代表一个低频,每一列代表一个高频,每按一个键就发送一个高频和低频的正弦信号组合。比如'1'相当于697和1209赫兹(Hz)。交换机可以解码这些频率组合并确定所对应的按键。

    现在我就想给自己的拨号键盘加上双音多频的声音,类似于固定电话拨号的声音。

    页面就不贴出来了,类似于系统的拨号盘。

    public class DialActivity extends Activity implements OnClickListener{
     
        private static String TAG = "【DialApp】";
        private static final int PLAY_TONE = 0x01;
        private static final int DTMF_DURATION_MS = 120; // 声音的播放时间
        private Object mToneGeneratorLock = new Object(); // 监视器对象锁
        private ToneGenerator mToneGenerator;             // 声音产生器
        private static boolean mDTMFToneEnabled;         // 系统参数“按键操作音”标志位
        // 存储DTMF Tones
        private static final HashMap mToneMap = new HashMap();
     
        static {
            mToneMap.put('1', ToneGenerator.TONE_DTMF_1);
            mToneMap.put('2', ToneGenerator.TONE_DTMF_2);
            mToneMap.put('3', ToneGenerator.TONE_DTMF_3);
            mToneMap.put('4', ToneGenerator.TONE_DTMF_4);
            mToneMap.put('5', ToneGenerator.TONE_DTMF_5);
            mToneMap.put('6', ToneGenerator.TONE_DTMF_6);
            mToneMap.put('7', ToneGenerator.TONE_DTMF_7);
            mToneMap.put('8', ToneGenerator.TONE_DTMF_8);
            mToneMap.put('9', ToneGenerator.TONE_DTMF_9);
            mToneMap.put('0', ToneGenerator.TONE_DTMF_0);
            mToneMap.put('#', ToneGenerator.TONE_DTMF_P);
            mToneMap.put('*', ToneGenerator.TONE_DTMF_S);
        }
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //按键声音播放设置及初始化
            try {
                // 获取系统参数“按键操作音”是否开启
                mDTMFToneEnabled = Settings.System.getInt(getContentResolver(),
                        Settings.System.DTMF_TONE_WHEN_DIALING, 1) == 1;
                synchronized (mToneGeneratorLock) {
                    if (mDTMFToneEnabled && mToneGenerator == null) {
                        mToneGenerator = new ToneGenerator(
                                AudioManager.STREAM_DTMF, 80); // 设置声音的大小
                        setVolumeControlStream(AudioManager.STREAM_DTMF);
                    }
                }
            } catch (Exception e) {
                Log.d(TAG, e.getMessage());
                mDTMFToneEnabled = false;
                mToneGenerator = null;
            }
            /*
             * 拨号按钮注册监听事件
             * 
             */
        }
        @Override
        public void onClick(View view) {
            int id = view.getId();   //点击按钮的id
            Integer currentTone;     //获得当前的Tone
            switch(id){
            case R.id.digit1:
                mToneMap.get("1");
                break;
            case R.id.digit2:
                mToneMap.get("2");
                break;
                .
                .
                .        
            }
            if (null != currentTone) {
                //第一种方式,采用Handler消息机制进行发声
                Message msg = mHandler.obtainMessage(PLAY_TONE, currentTone);
                mHandler.sendMessage(msg);
                //第二种方式,直接调用playTone(int tone)方法,不知道二者有何区别?希望大家给点意见。
    //            playTone(currentTone);
            }
        }
        /**
         * 处理按键响应事件的消息
         */
        private Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                try {
                    switch (msg.what) {
                    case PLAY_TONE:
                        Integer tone_id = (Integer) msg.obj;
                        if (tone_id != null) {
                            playTone(tone_id.intValue());
                        }
                        break;
                    }
                } catch (Exception ex) {
                    Log.d(TAG, ex.getMessage());
                }
            }
        };
     
        /**
         * 播放按键声音
         */
        private void playTone(int tone) {
            if (!mDTMFToneEnabled) {
                return;
            }
            AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
            int ringerMode = audioManager.getRingerMode();
            if (ringerMode == AudioManager.RINGER_MODE_SILENT
                    || ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
                // 静音或者震动时不发出声音
                return;
            }
            synchronized (mToneGeneratorLock) {
                if (mToneGenerator == null) {
                    Log.w(TAG, "playTone: mToneGenerator == null, tone: " + tone);
                    return;
                }
                mToneGenerator.startTone(tone, DTMF_DURATION_MS);   //发出声音
            }
        }
    }
    /**
    * @author 张兴业
    * 邮箱:xy-zhang#163.com
    * android开发进阶群:278401545
    *
    */
    
  • 相关阅读:
    获取指定日期相关DATENAME和DATEPART数据
    MySQL 5.7 新备份工具mysqlpump 使用说明
    Kubernetes之Pod控制器
    Python3出现"No module named 'MySQLdb'"问题-以及使用PyMySQL连接数据库
    分布式监控系统Zabbix3.4-针对MongoDB性能监控操作笔记
    基于MongodbDB的用户认证-运维笔记
    基于Nginx+Keepalived的LB服务监控(邮件报警)
    Linux系统用户密码规则
    通过容器提交镜像(docker commit)以及推送镜像(docker push)笔记
    Centos6.9下RocketMQ3.4.6高可用集群部署记录(双主双从+Nameserver+Console)
  • 原文地址:https://www.cnblogs.com/xyzlmn/p/3168109.html
Copyright © 2011-2022 走看看