首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Android背景下发生的本机视频崩溃

在Android背景下发生的本机视频崩溃
EN

Stack Overflow用户
提问于 2018-09-19 07:26:23
回答 1查看 1.8K关注 0票数 2

我正在实现用于音频播放的视频组件:

代码语言:javascript
运行
复制
import React, {Component} from 'react';
import {StyleSheet, View,} from 'react-native';
import Video from 'react-native-video';

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
          <Video source={require('./cats.mp3')}
             ref={(ref) => {
                 this.player = ref
         }}
             playInBackground={true}
             playWhenInactive={true}
             onBuffer={this.onBuffer}               
             onEnd={this.onEnd}                      
             onError={this.videoError}               

          />
      </View>
    );
  }
}

当在物理设备(Pixel 2 8.1.0)上运行并将应用程序留在后台时,音频播放在3-10分钟后停止,应用程序崩溃。回放只能通过重新启动应用程序来重新启动。只有当设备上没有电力电缆时,才会出现此问题。当有外部电源的时候,应用程序就会按原计划运行。

我从日志里拿出这个:

代码语言:javascript
运行
复制
ActivityManager: Killing 20894:com.videotest/u0a419 (adj 700): excessive cpu 53130 during 300068 dur=1762444 limit=2

看起来Android因为滥用cpu而拒绝了这个应用程序?什么样的解决方案可以迫使操作系统允许这个应用程序在没有中断的情况下运行,就像我们拥有外部电源时一样?

本机版本: 0.57版本-本机视频版本: 3.2.1

EN

回答 1

Stack Overflow用户

发布于 2019-02-15 09:12:30

我刚刚回答了这个问题的反应-本机-视频问题这里,并将复制在这里。

=========================================================

我已经设法解决了这个问题,至少在我的用例中,我遵循了ExoPlayer FAQ的背景音频指南:https://google.github.io/ExoPlayer/faqs.html#how-do-i-keep-audio-playing-when-my-app-is-backgrounded

当我的应用程序处于后台时,我如何保持音频播放? 当您的应用程序处于后台时,您需要采取以下几个步骤来确保音频的持续播放:

  1. 您需要运行前台服务。这将防止系统关闭进程以释放资源。
  2. 您需要持有一个WifiLock和一个WakeLock。这确保了系统保持WiFi收音机和CPU的清醒。

重要的是,您停止服务,并释放锁,一旦音频不再被播放。

为了在RN中实现wakelock和wifilock,我添加了这个包:“react-原生-wakeful”:"^0.1.0“

为了在RN中实现前台服务,我添加了这个包:"@voximplant/react-native-foreground-service":"^1.1.0“

确保按照这两个包的自述更新AndroidManifest.xml。

这个演示回购的App.js有一个关于如何使用前台服务的明确示例:https://github.com/voximplant/react-native-foreground-service-demo/blob/master/App.js

代码语言:javascript
运行
复制
/**
 * Copyright (c) 2011-2019, Zingaya, Inc. All rights reserved.
 *
 * @format
 * @flow
 * @lint-ignore-every XPLATJSCOPYRIGHT1
 */

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, Button} from 'react-native';
import VIForegroundService from "@voximplant/react-native-foreground-service";

type Props = {};
export default class App extends Component<Props> {

    async startService() {
        if (Platform.OS !== 'android') {
            console.log('Only Android platform is supported');
            return;
        }
        if (Platform.Version >= 26) {
            const channelConfig = {
                id: 'ForegroundServiceChannel',
                name: 'Notification Channel',
                description: 'Notification Channel for Foreground Service',
                enableVibration: false,
                importance: 2
            };
            await VIForegroundService.createNotificationChannel(channelConfig);
        }
        const notificationConfig = {
            id: 3456,
            title: 'Foreground Service',
            text: 'Foreground service is running',
            icon: 'ic_notification',
            priority: 0
        };
        if (Platform.Version >= 26) {
            notificationConfig.channelId = 'ForegroundServiceChannel';
        }
        await VIForegroundService.startService(notificationConfig);
    }

    async stopService() {
        await VIForegroundService.stopService();
    }


    render() {
        return (
            <View style={styles.container}>
                <Button title="Start foreground service" onPress={() => this.startService()}/>
                <View style={styles.space}/>
                <Button title="Stop foreground service" onPress={() => this.stopService()}/>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    space: {
        flex: 0.1
    }
});

这个例子所缺少的一点是,stopService()一开始就需要一个守卫:

代码语言:javascript
运行
复制
  async stopService() {
    // Only Android platform is supported
    if (Platform.OS !== 'android') {
      return;
    }

    await VIForegroundService.stopService();
  }

在我的应用程序中,当用户单击“播放/暂停”按钮时,我会这样做:

代码语言:javascript
运行
复制
    // play or pause the player, then.....

    if (this.isPaused) {
      // release wakelock, wifilock and stop foreground service
      wakeful.release();
      this.stopService();
    } else {
      // acquire wakelock, wifilock and start foreground service
      wakeful.acquire();
      this.startService();
    }

wakeful.release() / wakeful.acquire()可以保留为iOS,因为在这种情况下,它们只是没有操作。

如果有人需要帮助,请告诉我:)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52400385

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档