Skip to content
This repository was archived by the owner on Aug 28, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
build/
.idea/

# If you're building an application, you may want to check-in your pubspec.lock
pubspec.lock

# Directory created by dartdoc
# If you don't generate documentation locally you can remove this line.
doc/api/
Expand All @@ -28,3 +25,9 @@ example/web

# Env files
*.env

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
8 changes: 8 additions & 0 deletions android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
47 changes: 47 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
group 'com.millicast_flutter_sdk'
version '1.0'

buildscript {
repositories {
google()
mavenCentral()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:4.1.3'
}
}

rootProject.allprojects {
repositories {
google()
mavenCentral()
jcenter()
maven { url 'https://jitpack.io' }
}
}

apply plugin: 'com.android.library'

android {
compileSdkVersion 31

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

defaultConfig {
minSdkVersion 21
multiDexEnabled true
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
consumerProguardFiles 'proguard-rules.pro'
}
}

dependencies {
implementation 'com.github.webrtc-sdk:android:97.4692.01'
implementation 'androidx.annotation:annotation:1.1.0'
implementation 'com.android.support:multidex:2.0.1'
}
16 changes: 16 additions & 0 deletions android/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Mon May 02 10:37:31 UYT 2022
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
3 changes: 3 additions & 0 deletions android/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Flutter WebRTC
-keep class com.cloudwebrtc.webrtc.** { *; }
-keep class org.webrtc.** { *; }
1 change: 1 addition & 0 deletions android/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.name = 'millicast_flutter_sdk'
3 changes: 3 additions & 0 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.millicast_flutter_sdk">
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.millicast_flutter_sdk;

import androidx.annotation.NonNull;

// import com.cloudwebrtc.webrtc.utils.EglUtils;

import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.EglBase;
import org.webrtc.VideoCodecInfo;

import java.util.ArrayList;
import java.util.Map;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

/** MillicastFlutterSdkPlugin */
public class MillicastFlutterSdkPlugin implements FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private MethodChannel channel;

@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "millicast_flutter_sdk");
channel.setMethodCallHandler(this);
}

@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
switch (call.method) {
case "getSupportedCodecs":
EglBase eglBase = EglBase.createEgl10(EglBase.CONFIG_PLAIN);
EglBase.Context eglContext = eglBase == null ? null : eglBase.getEglBaseContext();
DefaultVideoEncoderFactory dummyEncoderFactory = new DefaultVideoEncoderFactory(
eglContext, true, true);
ArrayList<String> codecs = new ArrayList<String>();
for (VideoCodecInfo codec : dummyEncoderFactory.getSupportedCodecs()) {
codecs.add(codec.name);
}
result.success(codecs);
break;
case "getPlatformVersion":
result.success("Android " + android.os.Build.VERSION.RELEASE);
default:
result.notImplemented();
break;
}
}

@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
}
1 change: 1 addition & 0 deletions example/android/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ gradle-wrapper.jar
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
/app/local.properties

# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
Expand Down
4 changes: 2 additions & 2 deletions example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@ android {
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.millicast.flutter.example"
minSdkVersion 21
targetSdkVersion flutter.targetSdkVersion
Expand All @@ -64,5 +63,6 @@ flutter {
}

dependencies {
implementation 'androidx.annotation:annotation:1.1.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.millicast.flutter.example;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;

public class MainActivity extends FlutterActivity {
}

This file was deleted.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class MyApp extends StatelessWidget {
'/subscriber': (context) => const SubscriberWidget(),
'/settings': (context) => const PublisherSettingsWidget(
isConnected: false,
supportedCodecs: [],
)
},
home: HomeScreen(),
Expand Down
9 changes: 7 additions & 2 deletions example/lib/millicast_publisher_user_media.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:io';

import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:millicast_flutter_sdk/millicast_flutter_sdk.dart';
import 'package:flutter/foundation.dart';

var _logger = getLogger('MillicastPublishUserMedia');

Expand All @@ -15,6 +16,7 @@ const String? sourceId = String.fromEnvironment('sourceId');

class MillicastPublishUserMedia extends Publish {
MillicastMedia? mediaManager;
List<String>? supportedCodecs;

MillicastPublishUserMedia(options, tokenGenerator, autoReconnect)
: super(
Expand Down Expand Up @@ -102,8 +104,11 @@ class MillicastMedia {
try {
mediaStream = await navigator.mediaDevices.getUserMedia(constraints);

if (Platform.isIOS) {
mediaStream?.getAudioTracks()[0].enableSpeakerphone(true);
// Adding this check check so we don't lose web support
if (!kIsWeb) {
if (Platform.isIOS) {
mediaStream?.getAudioTracks()[0].enableSpeakerphone(true);
}
}

return mediaStream;
Expand Down
12 changes: 10 additions & 2 deletions example/lib/publisher_settings_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@ class PublisherSettingsWidget extends StatefulWidget {
final MillicastPublishUserMedia? publisherMedia;
final Map? options;
final bool isConnected;
final List<String> supportedCodecs;
const PublisherSettingsWidget(
{this.publisherMedia, this.options, required this.isConnected, Key? key})
{this.publisherMedia,
required this.supportedCodecs,
this.options,
required this.isConnected,
Key? key})
: super(key: key);
@override
_PublisherSettingsWidgetState createState() =>
// ignore: no_logic_in_create_state
_PublisherSettingsWidgetState(
publisherMedia: publisherMedia,
supportedCodecs: supportedCodecs,
options: options,
isConnected: isConnected);
}
Expand All @@ -30,9 +36,11 @@ class _PublisherSettingsWidgetState extends State<PublisherSettingsWidget> {
final _formKey = GlobalKey<FormState>();
MillicastPublishUserMedia? publisherMedia;
bool isSimulcastEnabled = true;
List<String> supportedCodecs = ['h264', 'vp8', 'vp9', 'av1'];

_PublisherSettingsWidgetState(
{required this.publisherMedia,
required this.supportedCodecs,
required this.options,
required this.isConnected});

Expand Down Expand Up @@ -254,7 +262,7 @@ class _PublisherSettingsWidgetState extends State<PublisherSettingsWidget> {
style: TextStyle(color: Colors.white, fontSize: 15)),
dropdownColor: Colors.purple,
value: options?['codec'],
items: ['h264', 'vp8', 'vp9', 'av1'].map((String value) {
items: supportedCodecs.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
Expand Down
22 changes: 15 additions & 7 deletions example/lib/publisher_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ class _PublisherWidgetState extends State<PublisherWidget>
mode: StopWatchMode.countUp,
);
final RTCVideoRenderer _localRenderer = RTCVideoRenderer();
late String _viewers = '0';
String _viewers = '0';
late MillicastPublishUserMedia _publisherMedia;
late List<String> _supportedCodecs;
bool isVideoMuted = false;
bool isConnected = false;
bool isLoading = false;
Expand Down Expand Up @@ -72,6 +73,7 @@ class _PublisherWidgetState extends State<PublisherWidget>
@override
void initState() {
initRenderers();
_setSupportedCodecs();
initPublish();
super.initState();
WidgetsBinding.instance?.addObserver(this);
Expand Down Expand Up @@ -109,12 +111,6 @@ class _PublisherWidgetState extends State<PublisherWidget>
stopWatchTimer.onExecute.add(StopWatchExecute.start);
});

Map<String, dynamic> onUserCountOptions = {
'accountId': Constants.accountId,
'streamName': Constants.streamName,
'callback': (countChange) => {refresh(countChange)},
};

setUserCount();
}

Expand All @@ -123,6 +119,17 @@ class _PublisherWidgetState extends State<PublisherWidget>
setState(() {});
}

_setSupportedCodecs() async {
var codecObjects = (await PeerConnection.getCapabilities('video'))['codec'];
List<String> codecs = [];
for (var codec in codecObjects) {
codecs.add((codec as String).toLowerCase());
}
setState(() {
_supportedCodecs = codecs;
});
}

void setUserCount() {
// Add listener of broacastEvent to get UserCount
_publisherMedia.on('broadcastEvent', this, (event, context) {
Expand Down Expand Up @@ -248,6 +255,7 @@ class _PublisherWidgetState extends State<PublisherWidget>
builder: (BuildContext context) =>
PublisherSettingsWidget(
publisherMedia: _publisherMedia,
supportedCodecs: _supportedCodecs,
options: options,
isConnected: isConnected),
));
Expand Down
Loading