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播放的声音相关推荐

  1. Android音频录制方案,Android录屏的三种方案

    本文总结三种用于安卓录屏的解决方案: adb shell命令screenrecord MediaRecorder, MediaProjection MediaProjection , MediaCod ...

  2. android 屏幕录制方案,Android录制屏幕的实现方法

    原文:Paul Kinlan 翻译:Agora.io 长久以来,我一直希望能够直接从Android屏幕上进行录制并将其编码为多种格式,以便将录制内容嵌入在任意位置,而不需要安装任何软件. 如今,我们已 ...

  3. android 屏幕录制方案,Android录屏的三种解决方案

    本文总结三种用于安卓录屏的解决方案: adb shell命令screenrecord MediaRecorder, MediaProjection MediaProjection , MediaCod ...

  4. android 屏幕录制方案,Android录屏的三种方案

    本文总结三种用于安卓录屏的解决方案: adb shell命令screenrecord MediaRecorder, MediaProjection MediaProjection , MediaCod ...

  5. android tts实现方案,Android自动朗读(TTS)的实现

    前言: Android提供了自动朗读支持.可以对指定文本内容进行朗读,从而发生声音:还允许把文本对应的音频录制成音频文件,方便以后播放.Android的自动朗读主要通过TextToSpeech来完成, ...

  6. android+反调试+方案,Android反调试笔记

    1)代码执行时间检测 通过取系统时间,检测关键代码执行耗时,检测单步调试,类似函数有:time,gettimeofday,clock_gettime. 也可以直接使用汇编指令RDTSC读取,但测试AR ...

  7. Android音频格式转换,Android音视频系列(八):了解音频格式WAV以及与PCM的转换...

    前言 之前我们已经了解了PCM音频数据,我们理解为最原始的数据,虽然他的音质是最棒的,但是同时也暴露出两个很重要的问题: 普通播放器无法播放,数据里不包含任何跟音频格式有关的信息(声道,采样率等等): ...

  8. 在“提示”框中:管理Android音频配置文件,Android上的Google书签和电缆固定

    It's a Thursday afternoon and that tip-time-of-week again. This week we're looking at managing audio ...

  9. android 插件化 方案,Android应用开发之Android 插件化,qihoo360插件方案配置教程

    本文将带你了解Android应用开发Android 插件化,qihoo360插件方案配置教程,希望本文对大家学Android有所帮助. Android 插件化,qihoo360插件方案 目录 Andr ...

最新文章

  1. im即时通讯源码_IM消息ID技术专题(六):深度解密滴滴的高性能ID生成器(Tinyid)
  2. win7下不能使用dnw烧写的解决办法——韦东山嵌入式Linux学习笔记05
  3. crontab wget命令定时执行thinkphp的控制器实现定时任务
  4. 全球首款光线追踪GPU
  5. linux中流设备_[快速上手Linux设备驱动]之块设备驱动流程详解一
  6. [CodeForces332E]Binary Key
  7. Android中ContentProvider组件详解
  8. 366 斐波那契数列
  9. 价值1680元的python实战全套教学视频
  10. kronecker引理证明_连续型Kronecker引理
  11. 基于VEH调试寄存器实现无痕HOOK(5)
  12. Java设计模式:单例模式的7种实现
  13. android自定义锁屏界面设置,android 锁屏壁纸和桌面壁纸的设置实现
  14. 【IOI 2018】Combo 组合动作(模拟,小技巧)
  15. 国基北盛-openstack-容器云-环境搭建
  16. Android 音视频开发之基础篇 使用 SurfaceView绘制一张图片
  17. 简单实现账号密码登录(写死了)
  18. 计算机木马犯罪类型,计算机木马病毒犯罪研究..doc
  19. 《域名投资,从入门到建站》老顾域名投资和网站运营十年经验实战宝典 !
  20. ANSYS apdl命令流瞬态动力学分析案例5--------凸轮从动件运动分析

热门文章

  1. 虎符遥控器(PPT遥控翻页)
  2. 房地产新项目经济测算解决方案
  3. Java毕设项目重庆旅游景点计算机(附源码+系统+数据库+LW)
  4. [词根词缀]lum/词源知识L/magn/manmari/mark词根由来
  5. Dropbox怎么安全地存储用户密码?
  6. Android UVCCamera问题——Cause: null pointer dereference
  7. Moons: 大力矩2相步进电机.MS17HD系列
  8. HTML5——HTML5新标签与特性
  9. 2018年2月1日的工作总结
  10. RSS2.0的文档资料