截取android正在播放音乐的audio音频流(后台获取android音频流)

        本文是做项目需求,获取android虚拟机正在播放音频,然后截取,保存成文件,获取的数据是PCM码流,可以通过ffplay播放,播放器播放不了,获取的PCM码流是解码后的原始数据。需要改动的文件是AudioTrack.cpp,路径:存放目录/android/frameworks/av/media/libmedia/

        需要对android源码进行编译,红色为需要添加代码:

 

ssize_t AudioTrack::write(const void* buffer, size_t userSize, bool blocking)
{
    // 该write函数要求mTransfer必须为TRANSFER_SYNC并且不是timetrack
    if (mTransfer != TRANSFER_SYNC || mIsTimed) {
        return INVALID_OPERATION;
    }
// 判断下flag中是否带有direct flag,如果是flag,则去掉CBLK_UNDERRUN、CBLK_LOOP_CYCLE
    // CBLK_LOOP_FINAL、CBLK_BUFFER_END
    if (isDirect()) {
        AutoMutex lock(mLock);
        int32_t flags = android_atomic_and(
                            ~(CBLK_UNDERRUN | CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL | CBLK_BUFFER_END),
                            &mCblk->mFlags);
        // 如果此时flag还含有CBLK_INVALID flag
        if (flags & CBLK_INVALID) {
            return DEAD_OBJECT;
        }
    }

    if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {
        // Sanity-check: user is most-likely passing an error code, and it would
        // make the return value ambiguous (actualSize vs error).
        ALOGE("AudioTrack::write(buffer=%p, size=%zu (%zd)", buffer, userSize, userSize);
        return BAD_VALUE;
    }

    size_t written = 0;
    Buffer audioBuffer;    

    // 进入循环写,直到userSize写完
    while (userSize >= mFrameSize) {
        audioBuffer.frameCount = userSize / mFrameSize;
       // 获取buffer空间,blocking默认为true,所以选择ClientProxy::kForever
        status_t err = obtainBuffer(&audioBuffer,
                blocking ? &ClientProxy::kForever : &ClientProxy::kNonBlocking);
        // 获取失败
        if (err < 0) {
            // 如果之前已经有写入一定的数据,则跳出,否则返回错误的
            if (written > 0) {
                break;
            }
            return ssize_t(err);
        }
        // audioBuffer.size记录的是获取到的空间的大小,然后进行数据拷贝,变量更新
        size_t toWrite = audioBuffer.size;
        memcpy(audioBuffer.i8, buffer, toWrite);//copy PCM data to audioflinger,内存复制,buffer即解码后的PCM码流

        

// --------------------------------------------------------------------------------------------
        //test::write PCM data to file  
        FILE *fp;  
        if((fp=fopen("/data/audioBuffer.txt","a+"))==NULL) {  //a+表示将数据写在之前数据后面,不清除之前数据
            ALOGE("failedopen (buffer=%p, size=%zu (%zd)", buffer, userSize, userSize);   
        }  
        else {
            
            fwrite(buffer,toWrite,1, fp);
            
        } 
        fclose(fp);
// --------------------------------------------------------------------------------------------
        buffer = ((const char *) buffer) + toWrite;//指针跳过已经写入的数据  
        userSize -= toWrite;//剩余数据量 
        written += toWrite;//已经写入的数据量 
        releaseBuffer(&audioBuffer);// 释放audiobuffer 
    } 
    return written;
}

 

 

 

 

编译源码:

 

source build/envsetup.sh

lunch 6

make -j8             注释:-j8是跟电脑配置有关

等待编译完成。然后需要用adb命令来完成文件传递。输入命令:

emulator & 

然后分如下操作:

1.虚拟机一般没有sdcard,需要自己创建一个sdcard

找到自己mksdcard命令所在目录,我的在/usr/share/adt-bundle-linux-x86_64-20140702/sdk/tools

然后通过命令: ./mksdcard -l mycard 100M /home/bruceking90/Documents/workplace/sdcard.img

然后启动带sdcard虚拟机命令:

emulator -sdcard /home/bruceking90/Documents/workplace/sdcard.img &

2.虚拟机自带播放器没有音乐,需要通过多米音乐下载或者你通过其他渠道下载mp3音乐,

通过命令:push /home/bruceking90/Downloads/Prison_break.mp3 /sdcard/Music

3.在ubuntu下新建一个文件,准备写入数据用的文件,与底层写文件同名audioBuffer.txt

然后push到写数据到文件的目录下/data/audioBuffer.txt

push /home/bruceking90/Downloads/audioBuffer.txt /data/

4.打开自带音乐播放器,播放传进去的mp3。数据就写入到audioBuffer.txt,然后通过命令将该文件穿出来,并且将后缀改为mp3:

pull /data/audioBuffer.txt push /home/bruceking90/Downloads/

mv audioBuffer.txt audioBuffer.mp3(可以手动更改)

5.验证获取音频数据对不对:原始数据可以通过一般音频分析软件得到采样率和声道数。该mp3原始采样率44k,双声道。

通过命令 ffplay -f s16le -ar 44k -ac 2 /home/bruceking90/Downloads/audioBuffer.mp3

可以正常播放。

 

小结遇到的问题:

 

1.若不能播放,在ubuntu端启动虚拟机目录下输入adb logcat,查看播放失败日志。android5.0以上,一些avc denied 即权限不够

在android目录下输入命令:adb shell

进入android机制,更改写文件限制,然后输入命令:setenforce 0

一般就可以正常播放,写数据到txt文件里。

2.“&”表示在后台运行,这样方便使用adb命令在当前终端下。当不小心关掉终端,输入emulator没反应需要重新加载环境:

source build/envsetup.sh

 

lunch 6

然后重新启动虚拟机 emulator -sdcard /home/bruceking90/Documents/workplace/sdcard.img &

 

要在Android开机时播放音频,你可以按照以下步骤进行操作: 1. 首先,你需要将音频文件保存到你的Android设备中。你可以将音频文件放在设备的特定目录下,例如"/system/media/audio/boot.mp3"。 2. 然后,你需要修改启动时的脚本文件以在开机时播放音频。这个脚本文件通常位于"/system/etc/init.d"目录下,命名为"bootaudio.sh"。 3. 在脚本文件中,你可以使用命令行工具"am"(Activity Manager)来播放音频。你需要指定音频文件的路径和播放器的包名。下面是一个示例的脚本文件内容: ``` #!/system/bin/sh am start -a android.intent.action.VIEW -d file:///system/media/audio/boot.mp3 -t audio/mp3 -n com.android.music/com.android.music.MediaPlaybackActivity ``` 4. 最后,你需要将脚本文件设置为可执行权限。在终端中,使用以下命令来修改脚本文件的权限: ``` chmod +x /system/etc/init.d/bootaudio.sh ``` 这样,在下次Android设备开机时,音频文件就会被播放出来了。请注意,以上步骤可能需要root权限才能进行操作。同时,根据你的Android设备型号和系统版本,步骤可能会有所不同。在实际操作时,请确保理解每个步骤,并根据你的设备做出相应的修改。由于权限问题导致播放失败,你可以通过在ubuntu端启动虚拟机目录下输入"adb logcat"命令来查看播放失败的日志信息。此外,你还可以通过一般音频分析软件验证获取音频数据的采样率和声道数。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [截取android正在播放音乐audio音频后台获取android音频)](https://blog.csdn.net/Ctrl_qun/article/details/52524993)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孔乙己大叔

你看我有机会吗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值