Android音频录制方案,Android录音,录制其他App播放的声音
Android录音,录制其他App播放的声音
从Android10(SDK 29)版本开始,可以设置录音App的源为其他App,这样就可以录制其他App播放的声音
此方案有以下注意几点
设置了源为其他App后,就不能设置默认源为麦克风了
录音的线程只能在Service里,这个Service只能是前台Service
具体实现步骤
首先需要在被录音的App的AndroidManifest里面的application元素里设置属性 android:allowAudioPlaybackCapture="true",这样才可以让其他App来录音此App
通过 MediaProjectionManager 获取Intent
// 下面两行代码在onCreate里面,用于在启动时请求MediaProjectionManager
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), 2000);
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK && requestCode == 2000) {
if (data != null) {
code = resultCode;
dataIt = data;
}
}
}
// MediaProjectionPermissionActivity.java
private Intent getMediaProjectionIntent(int uid, String packageName)
throws RemoteException {
IMediaProjection projection = mService.createProjection(uid, packageName,
MediaProjectionManager.TYPE_SCREEN_CAPTURE, false /* permanentGrant */);
Intent intent = new Intent();
intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION, projection.asBinder());
return intent;
}
// MediaProjectionManagerService.java
public IMediaProjection createProjection(int uid, String packageName, int type,
boolean isPermanentGrant) {
if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to grant "
+ "projection permission");
}
if (packageName == null || packageName.isEmpty()) {
throw new IllegalArgumentException("package name must not be empty");
}
final UserHandle callingUser = Binder.getCallingUserHandle();
long callingToken = Binder.clearCallingIdentity();
MediaProjection projection;
try {
ApplicationInfo ai;
try {
ai = mPackageManager.getApplicationInfoAsUser(packageName, 0, callingUser);
} catch (NameNotFoundException e) {
throw new IllegalArgumentException("No package matching :" + packageName);
}
projection = new MediaProjection(type, uid, packageName, ai.targetSdkVersion,
ai.isPrivilegedApp());
if (isPermanentGrant) {
mAppOps.setMode(AppOpsManager.OP_PROJECT_MEDIA,
projection.uid, projection.packageName, AppOpsManager.MODE_ALLOWED);
}
} finally {
Binder.restoreCallingIdentity(callingToken);
}
return projection;
}
// MediaProjectionManagerService.java
MediaProjection(int type, int uid, String packageName, int targetSdkVersion,
boolean isPrivileged) {
mType = type;
this.uid = uid;
this.packageName = packageName;
userHandle = new UserHandle(UserHandle.getUserId(uid));
mTargetSdkVersion = targetSdkVersion;
// mIsPrivileged = isPrivileged;
mIsPrivileged = true;
}
开启录音Service
Intent intent = new Intent(this, AudioRecordService.class);
// 传入的code和dataIt是用来从MediaProjectionManager来获取MediaProjection的
intent.putExtra("code", code);
intent.putExtra("data", dataIt);
startService(intent);
在Service里接收传过来的code和DataIt,并且将此Service设置为前台Service
public int onStartCommand(Intent intent, int flags, int startId) {
data = intent.getParcelableExtra("data");
code = intent.getIntExtra("code", 114);
final Notification notification = createNotification();
startForeground(1000, notification);
startRecording();
return START_STICKY;
}
获取MediaProjectionManager,并且从MediaProjectionManager里获取MediaProjection
projectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
if (projectionManager == null)
return;
projection = projectionManager.getMediaProjection(code, data);
配置需要录音的类型以及包名
AudioPlaybackCaptureConfiguration config = new AudioPlaybackCaptureConfiguration.Builder(projection)
.addMatchingUsage(AudioAttributes.USAGE_MEDIA)
.addMatchingUid(Utils.getPkgInfo(getApplicationContext(), "com.xxx").applicationInfo.uid)
.build();
构建AudioRecord,设置上一步生成的config为录音源
audioRecord = new AudioRecord.Builder().setAudioFormat(
new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setSampleRate(44100)
.setChannelMask(AudioFormat.CHANNEL_IN_MONO)
.build())
.setAudioPlaybackCaptureConfig(config)
.build();
最后就是录音了
audioRecord.startRecording();
int minByteBufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
new Thread(new Runnable() {
@Override
public void run() {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("/sdcard/record.pcm");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
byte[] bArr = new byte[minByteBufferSize];
int readSize = 0;
while (audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {
readSize = audioRecord.read(bArr, 0, minByteBufferSize, AudioRecord.READ_BLOCKING);
Log.i(utils.LOG_TAG, "读取到音频数量: " + readSize);
try {
fos.write(bArr, 0, readSize);
fos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
Log.i(utils.LOG_TAG, "录音线程退出");
}
}).start();
以上是录音其他App播放的音频的简单用法,具体细节可留言讨论,或者添加本人QQ一起交流: 1320024819
Android音频录制方案,Android录音,录制其他App播放的声音相关推荐
- Android音频录制方案,Android录屏的三种方案
本文总结三种用于安卓录屏的解决方案: adb shell命令screenrecord MediaRecorder, MediaProjection MediaProjection , MediaCod ...
- android 屏幕录制方案,Android录制屏幕的实现方法
原文:Paul Kinlan 翻译:Agora.io 长久以来,我一直希望能够直接从Android屏幕上进行录制并将其编码为多种格式,以便将录制内容嵌入在任意位置,而不需要安装任何软件. 如今,我们已 ...
- android 屏幕录制方案,Android录屏的三种解决方案
本文总结三种用于安卓录屏的解决方案: adb shell命令screenrecord MediaRecorder, MediaProjection MediaProjection , MediaCod ...
- android 屏幕录制方案,Android录屏的三种方案
本文总结三种用于安卓录屏的解决方案: adb shell命令screenrecord MediaRecorder, MediaProjection MediaProjection , MediaCod ...
- android tts实现方案,Android自动朗读(TTS)的实现
前言: Android提供了自动朗读支持.可以对指定文本内容进行朗读,从而发生声音:还允许把文本对应的音频录制成音频文件,方便以后播放.Android的自动朗读主要通过TextToSpeech来完成, ...
- android+反调试+方案,Android反调试笔记
1)代码执行时间检测 通过取系统时间,检测关键代码执行耗时,检测单步调试,类似函数有:time,gettimeofday,clock_gettime. 也可以直接使用汇编指令RDTSC读取,但测试AR ...
- Android音频格式转换,Android音视频系列(八):了解音频格式WAV以及与PCM的转换...
前言 之前我们已经了解了PCM音频数据,我们理解为最原始的数据,虽然他的音质是最棒的,但是同时也暴露出两个很重要的问题: 普通播放器无法播放,数据里不包含任何跟音频格式有关的信息(声道,采样率等等): ...
- 在“提示”框中:管理Android音频配置文件,Android上的Google书签和电缆固定
It's a Thursday afternoon and that tip-time-of-week again. This week we're looking at managing audio ...
- android 插件化 方案,Android应用开发之Android 插件化,qihoo360插件方案配置教程
本文将带你了解Android应用开发Android 插件化,qihoo360插件方案配置教程,希望本文对大家学Android有所帮助. Android 插件化,qihoo360插件方案 目录 Andr ...
最新文章
- im即时通讯源码_IM消息ID技术专题(六):深度解密滴滴的高性能ID生成器(Tinyid)
- win7下不能使用dnw烧写的解决办法——韦东山嵌入式Linux学习笔记05
- crontab wget命令定时执行thinkphp的控制器实现定时任务
- 全球首款光线追踪GPU
- linux中流设备_[快速上手Linux设备驱动]之块设备驱动流程详解一
- [CodeForces332E]Binary Key
- Android中ContentProvider组件详解
- 366 斐波那契数列
- 价值1680元的python实战全套教学视频
- kronecker引理证明_连续型Kronecker引理
- 基于VEH调试寄存器实现无痕HOOK(5)
- Java设计模式:单例模式的7种实现
- android自定义锁屏界面设置,android 锁屏壁纸和桌面壁纸的设置实现
- 【IOI 2018】Combo 组合动作(模拟,小技巧)
- 国基北盛-openstack-容器云-环境搭建
- Android 音视频开发之基础篇 使用 SurfaceView绘制一张图片
- 简单实现账号密码登录(写死了)
- 计算机木马犯罪类型,计算机木马病毒犯罪研究..doc
- 《域名投资,从入门到建站》老顾域名投资和网站运营十年经验实战宝典 !
- ANSYS apdl命令流瞬态动力学分析案例5--------凸轮从动件运动分析
热门文章
- 虎符遥控器(PPT遥控翻页)
- 房地产新项目经济测算解决方案
- Java毕设项目重庆旅游景点计算机(附源码+系统+数据库+LW)
- [词根词缀]lum/词源知识L/magn/manmari/mark词根由来
- Dropbox怎么安全地存储用户密码?
- Android UVCCamera问题——Cause: null pointer dereference
- Moons: 大力矩2相步进电机.MS17HD系列
- HTML5——HTML5新标签与特性
- 2018年2月1日的工作总结
- RSS2.0的文档资料