uniapp implements voice playback function

demand point

  1. Voice playback does not follow the system ringtone pattern.
  2. Voice playback supports speaker/earpiece playback.
  3. In the speaker mode, when the playback detects that the distance is close, the screen needs to be turned off (anti-mistouch) and converted to earpiece playback in real time. When the distance is far away, the screen needs to be turned on and switched back to speaker playback.
  4. In the handset mode, the playback detection distance change does not need to switch the playback channel, but the screen needs to be turned off (anti-mistouch) when the distance is close, and the screen needs to be turned on when the distance is far away.

analysis needs

First of all, it is clear that voice playback supports speaker/earpiece playback, so it can only be plus.audio.createPlayerrealized by using it. To switch the playback channel, you can use the setRoute() method plus.audio.createPlayerof the created instance . Based on the requirements in 3.4, it is clear that a distance monitor needs to be added when playing voice. Here you can use plus.proximity.watchProximity to monitor the proximity of the device in real time. The last one is close to the need for an off-screen, far away from the need for a bright screen. Let’s do the previous one first, and then see how to achieve it.

accomplish

this.playMode: Play channel (speaker 0, earpiece 1)
this.playState: Play parameter in play callback

  1. distance listener
this.watchProximity = plus.proximity.watchProximity((distance) => {
    
    
	/**
	 * iOS端接近为0,远离为Infinity
	 * Android端接近为0,远离为5
	 */
	if (this.playMode === 0) {
    
    
		// 扬声器模式下,需要对声道进行实时修改
		this.voicePlayer.pause();
		if (distance !== 0) {
    
    
			// 扬声器
			this.voicePlayer.setRoute(0);
		} else {
    
    
			// 听筒
			this.voicePlayer.setRoute(1);
		}
		this.voicePlayer.resume();
	}
});
  1. Initialize the player
this.voicePlayer = plus.audio.createPlayer({
    
     src: 'xxx' });
this.voicePlayer.setRoute(this.playMode);
// 监听自然播放完成
this.voicePlayer.addEventListener('ended', () => {
    
    
	// 销毁正在监听设备距离的监听器
	if (this.watchProximity) {
    
    
		plus.proximity.clearWatch(this.watchProximity);
		this.watchProximity = null;
	}
	console.log('播放完毕了');
});
// 监听音频可以开始播放事件
this.voicePlayer.addEventListener('play', () => {
    
    
	// 首次播放时会执行两次回调
	if (this.playState !== 2) {
    
    
		// plus.audio.ROUTE_SPEAKER:扬声器 0
		// plus.audio.ROUTE_EARPIECE:听筒 1
		this.voicePlayer.setRoute(this.playMode);
		this.playState++;
	}
});
// 监听音频播放错误事件
this.voicePlayer.addEventListener('error', (err) => {
    
    
	console.log('报错err', err);
	// 销毁正在监听设备距离的监听器
	if (this.watchProximity) {
    
    
		plus.proximity.clearWatch(this.watchProximity);
		this.watchProximity = null;
	}
});
  1. play
// 在正确的地方调用播放
this.voicePlayer.play();

After playing, I found that the voice on the iOS side is close to the off screen by default and away from the bright screen (default behavior); but when the Android side is playing, the screen is always on. It seems that the Android side needs to implement it by itself.
When playing, the initial playback mode is the speaker mode, close to the earpiece, and far away to switch back to the speaker. It can be perfectly performed on the iOS side, and there is no delay in switching; there is a delay in switching on the Android side, but fortunately, the delay does not affect the playback.
When playing, the initial playback mode is the earpiece mode. There will be a few seconds of lag when playing the audio for the first time on the Android side, and the lag takes up the playback time, which means that the first playback is incomplete. Currently There is no better solution (temporarily shelved).

The Android side realizes that when playing, it is close to the off screen and away from the bright screen

How to start? The blogger checked almost all the APIs of plus, but could not find relevant content. It seems that he can only find it on the Android official website.
Go directly to the Android official website to find APIs related to power supply, find PowerManager , and find a level mode PROXIMITY_SCREEN_OFF_WAKE_LOCK in it , as follows: wake lock level
Isn’t this the answer I want? Without further ado, just do it!

Since PowerManagerthe power management class is globally unique, it cannot be used just like playing audio new. It needs to use the main instance object of Android plus.android.runtimeMainActivity()to call and obtain it.
this.platform: Current mobile platform
this.wakeLock: Wake lock

// Android端需要设置唤醒模式才能在接近传感器激活时关闭屏幕,iOS端自带了
if (this.platform === 'android') {
    
    
	let main = plus.android.runtimeMainActivity();
	let Context = plus.android.importClass('android.content.Context');
	let PowerManager = plus.android.importClass('android.os.PowerManager');
	let pm = main.getSystemService(Context.POWER_SERVICE);
	// 32代表PROXIMITY_SCREEN_OFF_WAKE_LOCK,唤醒锁定电平:当接近传感器激活时关闭屏幕
	let status = pm.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
	// 系统支持该唤醒模式
	if (status) {
    
    
		this.wakeLock = pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, 'TAG');
		this.wakeLock.acquire();
	}
}

In the listening event added when the player is just initialized, increase the release of wake-up mode resources

// 监听自然播放完成
this.voicePlayer.addEventListener('ended', () => {
    
    
	// 销毁正在监听设备距离的监听器
	if (this.watchProximity) {
    
    
		plus.proximity.clearWatch(this.watchProximity);
		this.watchProximity = null;
	}
	// 释放唤醒锁
	if (this.wakeLock) {
    
    
		this.wakeLock.release();
		this.wakeLock = null;
	}
	console.log('播放完毕了');
});
// 监听音频播放错误事件
this.voicePlayer.addEventListener('error', (err) => {
    
    
	console.log('报错err', err);
	// 释放唤醒锁
	if (this.wakeLock) {
    
    
		this.wakeLock.release();
		this.wakeLock = null;
	}
	// 销毁正在监听设备距离的监听器
	if (this.watchProximity) {
    
    
		plus.proximity.clearWatch(this.watchProximity);
		this.watchProximity = null;
	}
});

So far, all the requirements have been satisfactorily completed!

Summarize

With the in-depth understanding of uniapp and the realization of more and more functional points, developers not only need to put their perspective on the front end, but also need to go to the official Android and iOS to consult the relevant API documents to realize it.
According to this trend, bloggers believe that all the functions implemented by the bottom layer of the mobile phone system, but not implemented by uniapp, can be implemented by plus.androidor by calling related functional classes. This quagmire is getting deeper and deeper. All in all, Keep learning…plus.ios

Guess you like

Origin blog.csdn.net/weixin_43905402/article/details/120011089