DTMF原理
处理音频输出的变化
ToneGenerator API
5_1698069103
package com.xg.practise.util
import android.app.Activity
import android.content.Context
import android.media.AudioManager
import android.media.ToneGenerator
import android.provider.Settings
//Tone 相关
const val DTMF_DURATION_MS = 120 // 声音的播放时间,毫秒
class ToneHelper() {
// 监视器对象锁
private val mToneGeneratorLock = Any()
// 声音产生器
private var mToneGenerator
: ToneGenerator? = null
// 系统参数“按键操作音”标志位
private var mDTMFToneEnabled = false
fun initToneGenerator(context: Context) {
runOnBackgroundThread(Runnable {
//按键声音播放设置及初始化
try {
// 获取系统参数“按键操作音”是否开启
mDTMFToneEnabled = Settings.System.getInt(
context.contentResolver,
Settings.System.DTMF_TONE_WHEN_DIALING, 1
) == 1
synchronized(mToneGeneratorLock) {
if (mDTMFToneEnabled && mToneGenerator == null) {
mToneGenerator = ToneGenerator(
AudioManager.STREAM_DTMF, 100
) // 设置声音的大小
if (context is Activity) {
context.volumeControlStream = AudioManager.STREAM_DTMF
}
}
}
} catch (e: Exception) {
e.printStackTrace()
mDTMFToneEnabled = false
mToneGenerator = null
}
})
}
fun playTone(context: Context, dtmf: Int) {
if (dtmf < 0) {
return
}
if (!mDTMFToneEnabled) {
return
}
val audioManager =
context.applicationContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
val ringerMode = audioManager.ringerMode
if ((ringerMode == AudioManager.RINGER_MODE_SILENT
|| ringerMode == AudioManager.RINGER_MODE_VIBRATE)
) {
// 静音或者震动时不发出声音
return
}
synchronized(mToneGeneratorLock) {
mToneGenerator?.startTone(dtmf, DTMF_DURATION_MS) //发出声音
}
}
fun release() {
try {
mDTMFToneEnabled = false
mToneGenerator?.stopTone()
mToneGenerator?.release()
mToneGenerator = null
} catch (e: Exception) {
e.printStackTrace()
}
}
}
package com.xg.practise.util
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit
val executor: ScheduledExecutorService = Executors.newScheduledThreadPool(10)
fun runOnBackgroundThread(runnable: Runnable?) {
executor.execute(runnable)
}
fun runOnBackgroundThread(runnable: Runnable?, delay: Long) {
executor.schedule(runnable, delay, TimeUnit.MILLISECONDS)
}
package com.xg.practise
import android.media.ToneGenerator
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.xg.practise.databinding.ActivityToneBinding
import com.xg.practise.util.ToneHelper
class ToneActivity : AppCompatActivity() {
private var mToneHelper
: ToneHelper? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var dataBinding =
DataBindingUtil.setContentView(this, R.layout.activity_tone);
setContentView(dataBinding.root)
mToneHelper = ToneHelper()
mToneHelper?.initToneGenerator(this@ToneActivity)
var array = arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#")
dataBinding.recycler.layoutManager = GridLayoutManager(this@ToneActivity, 3)
dataBinding.recycler.adapter = object : RecyclerView.Adapter() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(
LayoutInflater.from(parent.context)
.inflate(android.R.layout.simple_list_item_1, parent, false)
)
}
override fun getItemCount(): Int {
return array.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.text.text = array[position]
holder.text.setOnClickListener {
mToneHelper?.playTone(holder.text.context,convertToneDtmf(array[position]))
}
}
}
}
fun convertToneDtmf(key: String?): Int {
return when (key) {
"0" -> ToneGenerator.TONE_DTMF_0
"1" -> ToneGenerator.TONE_DTMF_1
"2" -> ToneGenerator.TONE_DTMF_2
"3" -> ToneGenerator.TONE_DTMF_3
"4" -> ToneGenerator.TONE_DTMF_4
"5" -> ToneGenerator.TONE_DTMF_5
"6" -> ToneGenerator.TONE_DTMF_6
"7" -> ToneGenerator.TONE_DTMF_7
"8" -> ToneGenerator.TONE_DTMF_8
"9" -> ToneGenerator.TONE_DTMF_9
"*" -> ToneGenerator.TONE_DTMF_S
"#" -> ToneGenerator.TONE_DTMF_P
else -> -1
}
}
override fun onDestroy() {
super.onDestroy()
mToneHelper?.release()
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val text: TextView = itemView.findViewById(android.R.id.text1)
}
}