python播放提示音_android 录像提示音问题

选中拍摄时关闭声音,摄像时会有声音,设备:小米note,红米note,oppo

据查该问题属于一种防偷拍的潜规则类型设置,与android系统提供商相关,拍照/摄像的提示音所有实现都在底层实现,上层能够控制的有限。

为什么拍照可以实现静默?

静默拍照目前可以通过两种方式设置:

android4.2以上的版本可以通过Camera提供的enableShutterSound(boolean enabled)方法禁止拍照提示音;

通过调整接口使用来规避提示音,设置shutter callback为null来实现,该方法在官方api中有提及;

这两种方法在底层的实现原理如下:

// snapshot taken callback

void CameraClient::handleShutter(void) {

//mPlayShutterSound 该值从上层设置 即第一种方法提供的接口实现,4.2以上版本有效

if (mPlayShutterSound) {

//声音调用

mCameraService- >playSound(CameraService::SOUND_SHUTTER);

}

sp c = mCameraClient;

if (c != 0) {

mLock.unlock();

c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);

if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;

}

disableMsgType(CAMERA_MSG_SHUTTER);

mLock.unlock();

}

留意一下handleShutter的调用情况,可以发现在CameraClient中仅有一处调用了该函数:

void CameraClient::notifyCallback(int32_t msgType, int32_t ext1,

int32_t ext2, void* user) {

LOG2("notifyCallback(%d)", msgType);

Mutex* lock = getClientLockFromCookie(user);

if (lock == NULL) return;

Mutex::Autolock alock(*lock);

CameraClient* client =

static_cast(getClientFromCookie(user));

if (client == NULL) return;

if (!client->lockIfMessageWanted(msgType)) return;

switch (msgType) {

case CAMERA_MSG_SHUTTER:

// 控制发声

// ext1 is the dimension of the yuv picture.

client->handleShutter();

break;

default:

client->handleGenericNotify(msgType, ext1, ext2);

break;

}

}

那么第二种规避发声的方法也有了合理的解释,底层的快门声调用放在了notifyCallback中,那么躲开了该回调的使用也就避开了快门的声音。

那么摄像的提示音呢?

摄像功能在java层是通过 MediaRecorder 类实现的,但是在java层包括它对应的jni层大多也只是包裹一个接口、注册等作用,到底层最后的实现还是在CameraClient类中,与提示音有关的代码如下:

status_t CameraClient::startRecordingMode() {

LOG1("startRecordingMode");

status_t result = NO_ERROR;

// if recording has been enabled, nothing needs to be done

if (mHardware->recordingEnabled()) {

return NO_ERROR;

}

// if preview has not been started, start preview first

if (!mHardware->previewEnabled()) {

result = startPreviewMode();

if (result != NO_ERROR) {

return result;

}

}

// start recording mode

enableMsgType(CAMERA_MSG_VIDEO_FRAME);

//提示音代码

mCameraService->playSound(CameraService::SOUND_RECORDING);

result = mHardware->startRecording();

if (result != NO_ERROR) {

ALOGE("mHardware->startRecording() failed with status %d", result);

}

return result;

}

关联代码上下文可以发现startRecordingMode本函数无法规避,想要通过该类实现录像功能这是必走的流程,所以相对而言正规取巧的方法在上层理论上无法操控。能够看出的是4.2中也没有预留标志位给上层去控制。

一些野路子方法如下:

方案一:拍摄开始时设置系统音频流静默并调整音量为0,结束时恢复;

方案二:找到提示音文件,通过改名/移动等方法让发音失灵,由于音频文件在系统中,所以需要root权限,该方案对用户要求比较高,不考虑;

经过测试,方案一能够搞定一部分机型的情况,但不是所有的,如中兴、小米的机器都是无效的,在一篇博客《Android Camera快门音静音问题》中找到了一种解释:

但是需要注意的是:很多机器是强制快门音的,也就是说你在app里调用上述接口也许根本不起作用,你明明enableShutterSound(false)了,但是拍照的时候快门音照样响起,原因在于烧制的系统版本里面有一个值被写死了:ro.camera.sound.forced = 1

在CameraClient代码中找一下这个系统属性值可以找到:

// enable shutter sound

status_t CameraClient::enableShutterSound(bool enable) {

LOG1("enableShutterSound (pid %d)", getCallingPid());

status_t result = checkPidAndHardware();

if (result != NO_ERROR) return result;

if (enable) {

mPlayShutterSound = true;

return OK;

}

// Disabling shutter sound may not be allowed. In that case only

// allow the mediaserver process to disable the sound.

char value[PROPERTY_VALUE_MAX];

//取到系统值来控制 mPlayShutterSound 设置权限

property_get("ro.camera.sound.forced", value, "0");

if (strcmp(value, "0") != 0) {

// Disabling shutter sound is not allowed. Deny if the current

// process is not mediaserver.

if (getCallingPid() != getpid()) {

ALOGE("Failed to disable shutter sound. Permission denied (pid %d)", getCallingPid());

return PERMISSION_DENIED;

}

}

mPlayShutterSound = false;

return OK;

}

那么很明显,在CameraClient中这个系统值的作用就是限制 mPlayShutterSound 的设置了,也是对引文那一段的解释。我们在源码的全局范围内搜索该值,可以发现除了 mPlayShutterSound 该值相关的几个cpp类中有相关的使用以外,audio_policy_hal.cpp 在该类中也可以找到对forced值的使用,经过查询可以了解到这部分是实现了提示音无视静音的功能,原理大概是在播放提示音的时候会将音量调到最大,详细的过程讲解博客见《Android 4.1 与 4.2 (老JB和小JB) 在"强制拍照摄像音"处理上的区别分析》。也就是说部分设置了ro.camera.sound.forced 的系统,采用强制静音或者调音量的方法行不通,该问题基本无解。

从测试的情况看,ZTE Q801L是可以通过命令获取到ro.camera.sound.forced为1的,实现上确实无法静默拍摄;而小米则比较有意思,首先它无法获取到forced值,但是从表现上看小米原生的相机是静默的、第三方的相机则静默不了,可以推测是MiUI内部有相关的内部接口或者公用属性去设置来控制。

结论

对于无root的应用层而言,使用系统提供的MediaRecorder实现的,针对系统的不同有以下几种情况:

系统强制发音,设置了ro.camera.sound.forced的,无解;-- 如中兴ZTE Q801L

定制化系统提供了内部接口的并且外在表现为强制发音的,暂时无解。或许可以有针对性的的对相关的定制系统查找相关的方法;--如小米note、红米note

系统未强制设定的,一部分无需设置(如htc、三星);一部分可以通过提供静音策略来限制,这部分要保证不引发其他的音频类型问题;(魅族?)

除此之外,自定义编写视频录制实现也是个方案,不过工作量需要评估。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值