如何在React Native中实现PIP (Picture in Picture)模式?



我需要使用react native实现PIP模式,但是当用户进入PIP模式时,它应该每秒更新一次日期。

我尝试使用以下软件包,但不工作:react-native-pip-androidreact-native-picture-in-picture

我可能已经找到解决办法了。问题是,当Android应用程序进入PIP时,将调用onPause函数。这是在这里指定https://developer.android.com/develop/ui/views/picture-in-picture#continuing_playback谷歌建议继续视频播放在onPause函数。这对于Android来说是没问题的,因为原生视图不关心当前的Activity状态,即使应用暂停或进入后台状态也可以更新。然而,RN的UI更新,非常重要的是,任何不使用HeadlessJS (https://reactnative.dev/docs/headless-js-android)的东西都会不可靠地运行,如果它们实际上在运行的话。结果是,如果没有headlessJS模式,你的状态都不会更新,你的UI将是一个静态图像,因为它不会更新。所以这个技巧似乎对我有用,2折1。然而,更新你的数据应该通过headlessJs任务完成;和2。通过方法触发RN UI渲染。

对于#1,我就是不能让看似被抛弃的库(react-native-pip-android)工作。这个概念是正确的,您应该像实现那个包一样实现PIP。我首先想要一个事件发射器,通知RN我的应用程序进入PIP模式。这是一个简单的getReactInstanceManager().getCurrentReactContext().getJSModule(RCTDeviceEventEmitter.class).emit("YourEventIDHere", boolean)MainActivityonPictureInPictureModeChange中。然而,组件的useEffect中的常规事件监听器不起作用;我花了一天的时间来推断,事件需要通过AppRegistry.registerHeadlessTask注册,这可能是由于一旦onPictureInPictureModeChange被调用,应用程序在后台,非headless任务将不会执行。然后,我将这个侦听器嵌套到一个普通的store中,然后将该store链接到一个useStore钩子中。

对于#2,没有一个库可以帮助您,因为这是RN的限制。我将把RN的渲染UI函数包装在RN模块方法中,然后从钩子中调用它;然而,我无法理解RN是如何工作的,并找到了一个更直接但粗略的解决方案-我在PIP触发super.onPause后立即调用onResume以将RN恢复到前台。我需要冲洗掉我的其他逻辑首先在发布中测试,但我的UI在调试下完全响应PIP。

public void onPause() {
// If called while in PiP mode, do not pause playback
super.onPause();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (isInPictureInPictureMode()) {
this.onResume(); // <--- this 
// Continue playback
} else {
// Use existing playback logic for paused Activity behavior.
}
} else {
}
}

尝试重新安装react-native-pip-android并删除android/MainActivity之前所做的任何更改。

MainActivity.java中添加以下代码片段,以便能够侦听更改:

import com.reactnativepipandroid.PipAndroidModule;
import android.content.res.Configuration;
@Override
public void onPictureInPictureModeChanged (boolean isInPictureInPictureMode, Configuration newConfig) {
PipAndroidModule.pipModeChanged(isInPictureInPictureMode);
}

在上述更改后构建项目。

注意:build.gradle中,您需要将最小sdk版本设置为24。android中的PIP从API级别24.

buildscript {
ext {
minSdkVersion = 24
}
}

React Native Implementation

import PipHandler, { usePipModeListener } from 'react-native-pip-android';
export default function App() {
// Use this boolean to show / hide ui when pip mode changes
const inPipMode = usePipModeListener();
if (inPipMode) {
return (
<View style={styles.container}>
<Text>PIP Mode</Text>
</View>
);
}
return (
<View style={styles.container}>
<Text style={styles.text}>
These text components will be hidden in pip mode
</Text>
<TouchableOpacity
onPress={() => PipHandler.enterPipMode(300, 214)}
style={styles.box}>
<Text>Click to Enter Pip Mode</Text>
</TouchableOpacity>
</View>
);
}

相关内容

  • 没有找到相关文章

最新更新