Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Live stream in background service #14

Open
adelhammoda opened this issue Nov 22, 2023 · 0 comments
Open

Live stream in background service #14

adelhammoda opened this issue Nov 22, 2023 · 0 comments
Assignees

Comments

@adelhammoda
Copy link

adelhammoda commented Nov 22, 2023

I am using live stream in background service to start live stream even when app is closed so i added some lines in background service to start live stream when volume button pressed 5 times in row (Don't make anttention about the way i catch the volume button it's just for test ) . And in log the live stream start successfully but when i am trying to join the live stream from web the video disply as a dark screen.

Note : all the function is work fine when the app is in foreground this issue display in background only.

This my code that i use in background service

import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_volume_controller/flutter_volume_controller.dart';
import 'package:logger/logger.dart';
import 'package:myth/app.dart';
import 'package:myth/config/stream_config.dart';
import 'package:myth/features/emergency/data/data_source/emergency_data_remote_source.dart';
import 'package:myth/features/emergency/params/start_stream_parameters.dart';
import 'package:myth/features/home/data/api_call.dart';
import 'package:videosdk/videosdk.dart';

class BackgroundLiveStreamService {
  void handleVolumeButtonPress() async {
    await FlutterVolumeController.setVolume(1);
    double counter = 1;
    Timer? timer;
    FlutterVolumeController.addListener(
      (volume) async {
        counter++;
        timer?.cancel();
        print(counter);
        if (counter >= 5) {
          counter = 1.0;
          await FlutterVolumeController.setVolume(1);
          await startLiveStream();
          runApp(App.instance);
        }
        timer = Timer(const Duration(seconds: 1), () {
          counter = 1.0;
        });
      },
    );
  }

  Future<void> startLiveStream() async {
    final user = FirebaseAuth.instance.currentUser;
    if (user == null) {
      print('user is null');
      return;
    }
    //init meeting
    await createMeeting().then((meetingId) async {
      Logger().v(meetingId);

      final dataSource = EmergencyDataRemoteSource();
      final room = VideoSDK.createRoom(
        roomId: meetingId,
        token: LiveStreamConfig.token,
        displayName: 'User',
        defaultCameraIndex: 1,
      );
      dataSource.startLiveLocation(user.uid);
      Future<void> createLiveStream() async {
        Logger().i('createLiveStream');
        await dataSource.createLiveStream(
          StartSteamParameters(
            roomId: meetingId,
            dateTime: DateTime.now(),
            userId: user.uid,
            streamId: meetingId,
            userEmail: user.email ?? '',
            userName: user.displayName ?? '',
            deactivateCode: '5555',
          ),
        );
        Logger().i('live stream created');
      }

      await Future.wait(
        <Future<void>>[
          createLiveStream(),
          joinAndStartRecording(room),
        ].map<Future<void>>((e) => e),
      ).catchError((e) => Logger().e(e));
    });
  }

  Future<void> joinAndStartRecording(Room room) async {
    await room.join();
    Timer(const Duration(seconds: 5), () async {
      await room.startHls(
        config: {
          "layout": {
            "type": "SPOTLIGHT",
            "priority": "PIN",
            "GRID": 20,
          },
          "mode": "video-and-audio",
          "theme": "DARK",
          "quality": "high",
          "orientation": "portrait",
        },
      );
      Logger().i('start recording');
      await room.startRecording(
        config: {
          "autoStartConfig": {
            "recording": {
              "config": {
                "layout": {
                  "type": "SPOTLIGHT",
                  "priority": "SPEAKER",
                  "gridSize": 1,
                },
                "mode": "video-and-audio",
                "quality": "med",
                "orientation": "portrait",
              },
            },
          },
        },
      ).onError((error, stackTrace) => Logger().e(error, stackTrace));
      Logger().i('recording started');
    });
  }
}

And this is the AndroidManifest.xml :
`

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<uses-feature android:name="android.hardware.camera" />

<application
    android:name="${applicationName}"
    android:icon="@mipmap/ic_launcher"
    android:label="myth">
    <uses-library
        android:name="org.apache.http.legacy"
        android:required="false" />
    <service
        android:name="MyNavigationService"
        android:foregroundServiceType="location">
    </service>
    <receiver
        android:name=".SosWidget"
        android:exported="true">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>

        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/sos_widget_info" />
    </receiver>

    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="AIzaSyDObDhEPX50nDJ4NuApPrJ0pMg41igS5Ao" />

    <activity
        android:name=".MainActivity"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:exported="true"
        android:hardwareAccelerated="true"
        android:launchMode="standard"
        android:theme="@style/LaunchTheme"
        android:windowSoftInputMode="adjustResize">

        <!--
             Specifies an Android theme to apply to this Activity as soon as
             the Android process has started. This theme is visible to the user
             while the Flutter UI initializes. After that, this theme continues
             to determine the Window background behind the Flutter UI.
        -->
        <meta-data
            android:name="io.flutter.embedding.android.NormalTheme"
            android:resource="@style/NormalTheme" />

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <meta-data
            android:name="flutter_deeplinking_enabled"
            android:value="true" />
        <intent-filter android:autoVerify="true">
            <action android:name="android.intent.action.VIEW" />

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <!-- Accepts URIs that begin with "https://mythsostrigger.page.link/sos” -->
            <data
                android:host="mythsostrigger.page.link"
                android:pathPrefix="/sos"
                android:scheme="https" />
            <data android:scheme="https" />
        </intent-filter>

    </activity>

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="high_importance_channel" />
    <!--

Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java
-->

`

And this is my background service code :

import 'dart:async';
import 'dart:ui';

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_background_service/flutter_background_service.dart';
import 'package:flutter_volume_controller/flutter_volume_controller.dart';
import 'package:geolocator/geolocator.dart';
import 'package:get_it/get_it.dart';
import 'package:logger/logger.dart';
import 'package:myth/core/app_manager/user/user_location.dart';
import 'package:myth/core/service_locator/service_locator.dart';
import 'package:myth/firebase_options.dart';

import 'background_service_functions.dart';

@pragma('vm:entry-point')
Future<void> onStart(ServiceInstance service) async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  setup();
  DartPluginRegistrant.ensureInitialized();
  Logger().i('AppBackgroundService', 'onStart');
  UserLocation().startUpdatingLocation();
  BackgroundLiveStreamService().handleVolumeButtonPress();
}

@pragma('vm:entry-point')
FutureOr<bool> onIosBackground(ServiceInstance service) async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  GetIt.instance.registerSingleton<FirebaseAuth>(FirebaseAuth.instance);
  DartPluginRegistrant.ensureInitialized();
  Logger().i('AppBackgroundService', 'onStart');
  UserLocation().startUpdatingLocation();
  // await handleVolumeButtonPress();
  return true;
}

class AppBackgroundService {
  factory AppBackgroundService() => _instance;

  AppBackgroundService._internal();

  static final AppBackgroundService _instance =
      AppBackgroundService._internal();

  @pragma('vm:entry-point')
  Future<void> init() async {
    DartPluginRegistrant.ensureInitialized();
    final service = FlutterBackgroundService();
    await service.configure(
      androidConfiguration: AndroidConfiguration(
        onStart: onStart,
        autoStart: true,
        isForegroundMode: true,
      ),
      iosConfiguration: IosConfiguration(
        autoStart: true,
        onForeground: onStart,
        onBackground: onIosBackground,
      ),
    );
    await service.startService();
  }
}

For now i need it to work only on android.

@adelhammoda adelhammoda changed the title Recording in background service Live stream in background service Nov 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants