Вылетает response-native-video на фоне Android

Я реализую компонент Video для воспроизведения звука:

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 минут и приложение вылетает. Воспроизведение можно возобновить, только перезапустив приложение. Проблема появляется только тогда, когда к устройству не подключен кабель питания. Когда есть внешнее питание, приложение работает как положено.

Я вытащил это из журнала:

ActivityManager: Killing 20894:com.videotest/u0a419 (adj 700): excessive cpu 53130 during 300068 dur=1762444 limit=2

Похоже, Android отклоняет приложение из-за неправильного использования процессора? Что может быть решением, чтобы заставить ОС разрешать этому приложению работать без перебоев, как это происходит при наличии внешнего источника питания?

реагировать на родную версию: 0.57 версия реакции-нативного видео: 3.2.1

2
0
1 304
1

Ответы 1

Я только что ответил на этот вопрос о проблемах с исходным видео здесь и скопирую его сюда.

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

Мне удалось решить эту проблему, по крайней мере, для моего варианта использования, следуя рекомендациям ExoPlayer FAQ для фонового звука: https://google.github.io/ExoPlayer/faqs.html#how-do-i-keep-audio-playing-when-my-app-is-backgounded:

How do I keep audio playing when my app is backgrounded?

There are a few steps that you need to take to ensure continued playback of audio when your app is in the background:

  1. You need to have a running foreground service. This prevents the system from killing your process to free up resources.
  2. You need to hold a WifiLock and a WakeLock. These ensure that the system keeps the WiFi radio and CPU awake.

It’s important that you stop the service and release the locks as soon as audio is no longer being played.

Чтобы реализовать wakelock и wifilock в RN, я добавил этот пакет: "react-native-wakeful": "^ 0.1.0"

Чтобы реализовать службу переднего плана в RN, я добавил этот пакет: "@ voximplant / react-native-foreground-service": "^ 1.1.0"

Обязательно обновите AndroidManifest.xml, как описано в README для этих двух пакетов.

В этом демонстрационном репозитории App.js есть наглядный пример использования службы переднего плана: https://github.com/voximplant/react-native-foreground-service-demo/blob/master/App.js:

/**
 * 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.info('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() нуждается в защите с самого начала:

  async stopService() {
    // Only Android platform is supported
    if (Platform.OS !== 'android') {
      return;
    }

    await VIForegroundService.stopService();
  }

В моем приложении, когда пользователь нажимает кнопку Play / Pause, я делаю следующее:

    // 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, поскольку в этом случае они просто не работают.

Если кому-то понадобится помощь, просто дайте мне знать :)

Другие вопросы по теме

Похожие вопросы

Как написать общий ответ на модернизацию и иметь возможность регистрировать / отлаживать его, когда десериализация не работает?
Вызов метода из моей библиотеки Android с возвращаемым значением в Unity
Как добавить фрагмент и действие в окне просмотра, чтобы фрагмент отображался при смахивании?
Проблема с прослушивателем нажатия кнопки в диалоговом окне
Может ли кто-нибудь порекомендовать веб-видеоплеер, который может автоматически воспроизводить видео на мобильной платформе Android?
Выберите имя / номер отправителя [транзакция / рекламная акция] из почтового ящика на Android
Java.security.cert.CertPathValidatorException: якорь доверия для пути сертификации не найден в React-Native
Как удалить сгенерированнуюJava из Android Studio 3.2
Adform - процесс рендеринга (25539) kill (OOM или update) не был передан всеми связанными веб-просмотрами, убивая приложение
Может ли Android SDK (библиотека) иметь класс приложения?