android蓝牙耳机录音播放,android蓝牙耳机录音并播放(二)
Github下载
package com.example.superb.yy4;
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
/**
Function:判断录音权限,兼容android6.0以下以及以上系统
@author xuzhuyun
@date 2018/5/10
*/
public class CheckAudioPermission {
/**
* 音频获取源
/
public static int audioSource = MediaRecorder.AudioSource.MIC;
/*
* 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025
*/
public static int sampleRateInHz = 44100;
/**
* 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
*/
public static int channelConfig = AudioFormat.CHANNEL_IN_STEREO;
/**
* 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。
*/
public static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
/**
* 缓冲区字节大小
*/
public static int bufferSizeInBytes = 0;
public static AudioRecord audioRecord;
/**
* 判断是是否有录音权限.
*/
public static boolean isHasPermission(final Context context) {
bufferSizeInBytes = 0;
bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
channelConfig, audioFormat);
if (audioRecord == null) {
audioRecord = new AudioRecord(audioSource, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes);
}
//开始录制音频
try {
// 防止某些手机崩溃,例如联想
audioRecord.startRecording();
} catch (IllegalStateException e) {
e.printStackTrace();
}
/**
* 根据开始录音判断是否有录音权限s
*/
if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
return false;
}
audioRecord.stop();
//释放资源
audioRecord.release();
audioRecord = null;
return true;
}
}
package com.example.superb.yy5;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
/**
desc:测试录音权限.
steps:
检测是否有权限–有--执行相关操作
–无权限–
–判断系统版本
–小于6.0 直接获取
–大于6.0 动态申请权限
–对申请结果的处理回调
–允许
–拒绝
test:
test1 build.gradle minsdk <23 真机android7.1 清单文件中配置了录音权限
test2 build.gradle minsdk >=23 真机android7.1 清单文件中配置了录音权限
@author xuzhuyun
@date 2018/5/10
*/
public class Main2Activity extends AppCompatActivity {
private static final String TAG = “MainActivity”;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
//检测是否有录音权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, “默认无录音权限”);
if (Build.VERSION.SDK_INT >= 23) {
Log.i(TAG, “系统版本不低于android6.0 ,需要动态申请权限”);
requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 1001);
}
} else {
Log.i(TAG, “默认有录音权限”);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1001) {
//方式一校验
boolean isHasAudioPermission = CheckAudioPermission.isHasPermission(this);
Log.i(TAG, “申请权限完毕,当前录音权限:” + isHasAudioPermission);
//方式二校验
int result = 0;
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
result++;
}
}
if (result != permissions.length) {
//没有权限
Log.i(TAG, “onRequestPermissionsResult: 申请权限完毕,当前录音权限:false”);
return;
}
//有权限
Log.i(TAG, “onRequestPermissionsResult: 申请后,是否有权限:true”);
}
}
public void ccc(View view) {
startActivity(new Intent(this,MainActivity.class));
}
}
package com.example.superb.yy5;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class MainActivity extends Activity {
//耳机
//耳机
PipedInputStream in;
boolean isRrcord;
mAudio mm ;
mAudioPlayer m;
TextView T1,T2;
Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=findViewById(R.id.search_close_btn);
T1=findViewById(R.id.dddd);
isRrcord = false;
}
public void btnclick(View v){
if (isRrcord){
isRrcord = false;
mm.stopRecord();m.stopPlay();
btn.setText("开始");
T1.setText("点击开始");
}else{
isRrcord = true;
startRecord();
btn.setText("停止");
T1.setText("点击停止");
}
}
private void startRecord(){
in = new PipedInputStream();
new Thread(new Runnable() {
@Override
public void run() {
try {
mm = new mAudio(MainActivity.this, in);
mm.StartAudioData();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
byte[] buffer = new byte[1024];
PipedOutputStream pout = new PipedOutputStream();
m = new mAudioPlayer(MainActivity.this);
try {
m.setOutputStream(pout);
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
m.startPlayAudio();
}
}).start();
} catch (IOException e1) {
e1.printStackTrace();
}
int size = 0 ;
try {
while (true){
while (in.available()>0){
size = in.read(buffer);
pout.write(buffer, 0, size);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
package com.example.superb.yy5;
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.Log;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
/*
To getaudio or play audio
*/
public class mAudio {
//
private int SAMPLE_RATE_HZ = 16000;
private AudioManager mAudioManager;
//
private AudioRecord audioRecord;
private Context context;
private boolean isRecording = false ;
private PipedOutputStream outstream ;//利用管道传输数据
public mAudio(Context context , PipedInputStream instream) throws IOException {
this.context = context;
//初始化管道流 用于向外传输数据
outstream = new PipedOutputStream();
outstream.connect(instream);
}
public void StartAudioData(){//得到录音数据
int frequency = 11025;
mAudioManager = (AudioManager)context.getSystemService(context.AUDIO_SERVICE);
// mAudioManager.setMode(AudioManager.MODE_NORMAL);
// mAudioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
//MODE_IN_COMMUNICATION
mAudioManager.setBluetoothScoOn(true);
//frequency采样率:音频的采样频率,每秒钟能够采样的次数,采样率越高,音质越高。
// 给出的实例是44100、22050、11025但不限于这几个参数。
// 例如要采集低质量的音频就可以使用4000、8000等低采样率。
@SuppressWarnings("deprecation")
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO;//立体声录制通道
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
//编码制式和采样大小:采集来的数据当然使用PCM编码(脉冲代码调制编码,
// 即PCM编码。PCM通过抽样、量化、编码三个步骤将连续变化的模拟信号转换为数字编码。) android支持的采样大小16bit 或者8bit。
// 当然采样大小越大,那么信息量越多,音质也越高,
// 现在主流的采样大小都是16bit,在低质量的语音传输的时候8bit足够了。
//
int buffersize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
//采集数据需要的缓冲区的大小,如果不知道最小需要的大小可以在getMinBufferSize()查看。
//手机VOICE_RECOGNITION
if(!mAudioManager.isBluetoothScoAvailableOffCall()){
Log.d(“dddddddddd”, “系统不支持蓝牙录音”);
return;
}
// mAudioManager.setBluetoothScoOn(true); //打开SCO}
//蓝牙录音的关键,启动SCO连接,耳机话筒才起作用
//mAudioManager.startBluetoothSco();
//蓝牙SCO连接建立需要时间,连接建立后会发出ACTION_SCO_AUDIO_STATE_CHANGED消息,通过接收该消息而进入后续逻辑。
//也有可能此时SCO已经建立,则不会收到上述消息,可以startBluetoothSco()前先stopBluetoothSco()
// if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) {
// mAudioManager.setBluetoothScoOn(true); //打开SCO}
// }
// mAudioManager.setBluetoothScoOn(true); //打开SCO}
//VOICE_COMMUNICATION
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,frequency, channelConfiguration, audioEncoding, buffersize);
//audioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION,frequency, channelConfiguration, audioEncoding, buffersize);
// 耳机
// buffersize = AudioRecord.getMinBufferSize(SAMPLE_RATE_HZ,
// AudioFormat.CHANNEL_IN_MONO,
// AudioFormat.ENCODING_PCM_16BIT) * 2;
//
// int audiosource = MediaRecorder.AudioSource.VOICE_RECOGNITION;
// audioRecord = new AudioRecord(audiosource,
// SAMPLE_RATE_HZ,
// AudioFormat.CHANNEL_IN_MONO,
// AudioFormat.ENCODING_PCM_16BIT,
// buffersize);
// audioRecord = new AudioRecord(audiosource,
// SAMPLE_RATE_HZ,
// AudioFormat.CHANNEL_IN_MONO,
// AudioFormat.ENCODING_PCM_16BIT,
// buffersize);
//音频源:指的是从哪里采集音频。这里我们当然是从麦克风采集音频,所以此参数的值为MIC
//frequency采样率:音频的采样频率,每秒钟能够采样的次数,采样率越高,音质越高。
// 给出的实例是44100、22050、11025但不限于这几个参数。
// 例如要采集低质量的音频就可以使用4000、8000等低采样率。
byte[]buffer = new byte[buffersize];
audioRecord.startRecording();//开始录音
isRecording = true;
int bufferReadSize = 1024;
mAudioManager.startBluetoothSco();
while (isRecording){
audioRecord.read(buffer, 0, bufferReadSize);
try {
outstream.write(buffer, 0, bufferReadSize);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void stopRecord(){//停止录音
// mAudioManager.setMode(AudioManager.MODE_NORMAL);
isRecording = false;
audioRecord.stop();
mAudioManager.startBluetoothSco();
try {
outstream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.example.superb.yy5;
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class mAudioPlayer {
private Context context;
private PipedInputStream instream;
private boolean isPlaying ;
private AudioTrack audioplayer;
private AudioManager mAudioManager;
private byte[] buffer;
public mAudioPlayer(Context context) {
isPlaying = false;
instream = null;
//初始化播音类
this.context=context;
mAudioManager = (AudioManager)context.getSystemService(context.AUDIO_SERVICE);
mAudioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
mAudioManager.setMode(AudioManager.MODE_RINGTONE);
mAudioManager.setBluetoothA2dpOn(false);
int bufsize = AudioTrack.getMinBufferSize(11025, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
audioplayer = new AudioTrack(AudioManager.STREAM_VOICE_CALL, 11025, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT, bufsize,AudioTrack.MODE_STREAM);
}
//设置管道流,用于接受音频数据
public void setOutputStream(PipedOutputStream out) throws IOException{
instream = new PipedInputStream(out);
}
public void startPlayAudio(){ //调用之前先调用setOutputStream 函数
isPlaying = true;
audioplayer.play();//开始接受数据流播放
buffer = new byte[1024];
// mAudioManager.stopBluetoothSco();
while (instream!=null&&isPlaying){
try {
while (instream.available()>0){
int size = instream.read(buffer);
audioplayer.write(buffer, 0
, size);//不断播放数据
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void stopPlay(){//停止播放
isPlaying = false ;
mAudioManager.setMode(AudioManager.MODE_NORMAL);
mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
try {
instream.close();
} catch (IOException e) {
e.printStackTrace();
}
audioplayer.stop();
}
}
android蓝牙耳机录音播放,android蓝牙耳机录音并播放(二)相关推荐
- Android 实时录音和回放,边录音边播放 (KTV回音效果)
原文地址为: Android 实时录音和回放,边录音边播放 (KTV回音效果) 上一篇介绍了如何使用Mediarecorder来录音,以及播放录音.不过并没有达到我的目的,一边录音一边播放.今天就讲解 ...
- android中录音断点播放,Android实现暂停--继续录音(AudioRecord)
Android提供了两个API用于录音的实现:MediaRecorder 和 AudioRecord,各有优劣. 1.MediaRecorder 已经集成了录音.编码.压缩等,支持少量的录音音频格式, ...
- android 实时录音播放,android 使用 audiorecord 和 audiotrack 实现实时录音播放
基本思路就是用 audiorecord不断得到音频数据,然后使用audiotrack 播放 //得到音频 package com.ysg.audiotest; import java.io.IOExc ...
- Android按下录音录音动画效果 ,自定义录音、播放动画View
Android按下录音录音动画效果 ,自定义录音.播放动画View https://download.csdn.net/download/abc2522/10327428?spm=1001.2101. ...
- android中录音断点播放,Android实现语音播放与录音功能
本文实例为大家分享了Android实现语音播放与录音的具体代码,供大家参考,具体内容如下 项目用到的技术点和亮点 语音录音 (单个和列表) 语音播放(单个和列表) 语音录音封装 语音播放器封装 语音列 ...
- android 调用系统自带录音实现,语音录制与播放
相关权限: <uses-permission android:name="android.permission.RECORD_AUDIO"></uses-perm ...
- android 连接蓝牙耳机 播放音乐,android 手机怎么实现和蓝牙耳机建立连接,连接之后可以听音乐...
如题,手机和蓝牙耳机配对之后,怎么建立连接 解决方案 20 BluetoothA2dpService是底层的Service类,你可以通过BluetoothA2dp类来使用它 android.bluet ...
- Android Audio和耳机,蓝牙耳机等音频外设
文章目录 Android Audio和耳机,蓝牙耳机等音频外设 蓝牙连接处理 广播接收 AudioManager接口 Listener监听 蓝牙耳机和AudioService的交互 蓝牙的状态 A2D ...
- android 断点续录,android 录音的断点续传
系统没有暂停的功能 只能把每次的录音进行拼接... package com.example.zrecord; import java.io.File; import java.io.FileInpu ...
最新文章
- L1-023 输出GPLT (C++解决,含题解)
- 春招来袭!程序员如何拿下硅谷顶级公司200万年薪?
- 三安光电圈钱凶猛 两年三轮再融资逾百亿
- python爬虫beautifulsoup实例-Python爬虫学习(二)使用Beautiful Soup库
- 产品经理日常表情包大全,多说是泪拿走不谢!
- Linux基础学习1--档案的属性和目录
- OSGI嵌入jetty应用服务器
- java mouselistener,Java MouseListener接口
- java 类加载 双亲委派_Java类加载器和双亲委派机制
- 架构组件:基于shard-jdbc中间件,实现数据分库分表
- c++ python混合编程 restful_How to use Python to build a RESTful Web Service
- 数据挖掘的步骤有哪些
- ResponsibleChain(责任链模式)
- PyTorch并行与分布式(二)分布式通信包torch.distributed
- python catia 接口_使用Python在CATIA中创建新产品
- 好多游戏,大部分都有修改器,大家赶紧下!
- matlab光学教程,基于MATLAB的物理光学仿真
- mysql front新建数据库_简述MySQL-Front数据库的具体操作
- python用嵌套if结构开发一个输入(input)快递价格的计算器
- Nature|人类肠道细菌对治疗药物的生物累积
热门文章
- 物联网开发笔记(26)- 使用Micropython开发ESP32开发板之控制LCD1602显示屏(续)
- java asn.1_ASN1编解码实现方法 | 学步园
- Unity云渲染搭建二(Unity2019.4)开发版本的webapp服务
- 基于51单片机的智能光控路灯设计及设计报告
- iOS应用处于前台、后台、应用被杀掉场景-收到远程推送内容进行收款语音播报;
- C++实例:根据给定的日期计算天数
- 关于ng-alain的st、sf一些小功能的总结
- 【期末大作业】基于HTML+CSS+JavaScript网上订餐系统(23个页面)
- ICT技术发展趋势,AI、大数据和云计算的概述及存储应用技术【2】
- Unity安卓如何调用小键盘对配置文件进行修改