Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
AlessioValentiniAesys committed Aug 7, 2020
1 parent 5656d31 commit cc2e11b
Show file tree
Hide file tree
Showing 98 changed files with 3,334 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: 2ae34518b87dd891355ed6c6ea8cb68c4d52bb9d
channel: stable

project_type: plugin
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 0.0.1

* TODO: Describe initial release.
1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: Add your license here.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# flutter_video_cast

A new flutter plugin project.

## Getting Started

This project is a starting point for a Flutter
[plug-in package](https://flutter.dev/developing-packages/),
a specialized package that includes platform-specific implementation code for
Android and/or iOS.

For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

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 'it.aesys.flutter_video_cast'
version '1.0-SNAPSHOT'

buildscript {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

rootProject.allprojects {
repositories {
google()
jcenter()
}
}

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
compileSdkVersion 28

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
minSdkVersion 16
}
lintOptions {
disable 'InvalidPackage'
}
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

//ChromeCast dependencies
implementation 'com.google.android.gms:play-services-cast-framework:19.0.0'
implementation 'com.google.android.exoplayer:extension-cast:2.11.5'
}
4 changes: 4 additions & 0 deletions android/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
5 changes: 5 additions & 0 deletions android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
1 change: 1 addition & 0 deletions android/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.name = 'flutter_video_cast'
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="it.aesys.flutter_video_cast">
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package it.aesys.flutter_video_cast

import android.content.Context
import android.view.ContextThemeWrapper
import androidx.mediarouter.app.MediaRouteButton
import com.google.android.gms.cast.MediaInfo
import com.google.android.gms.cast.MediaLoadOptions
import com.google.android.gms.cast.MediaSeekOptions
import com.google.android.gms.cast.framework.CastButtonFactory
import com.google.android.gms.cast.framework.CastContext
import com.google.android.gms.cast.framework.Session
import com.google.android.gms.cast.framework.SessionManagerListener
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.platform.PlatformView

class ChromeCastController(
messenger: BinaryMessenger,
viewId: Int,
context: Context?
) : PlatformView, MethodChannel.MethodCallHandler, SessionManagerListener<Session> {
private val channel = MethodChannel(messenger, "plugins.flutter.io/multiPlayer/chromeCast_$viewId")
private val chromeCastButton = MediaRouteButton(ContextThemeWrapper(context, R.style.Theme_AppCompat_NoActionBar))
private val sessionManager = CastContext.getSharedInstance()?.sessionManager

init {
CastButtonFactory.setUpMediaRouteButton(context, chromeCastButton)
channel.setMethodCallHandler(this)
sessionManager?.addSessionManagerListener(this)
}

private fun loadMedia(args: Any?) {
if (args is Map<*, *>) {
val url = args["url"] as? String
val media = MediaInfo.Builder(url).build()
val options = MediaLoadOptions.Builder().build()
val request = sessionManager?.currentCastSession?.remoteMediaClient?.load(media, options)
request?.addStatusListener { status ->
if (status.isSuccess) {
channel.invokeMethod("chromeCast#requestDidComplete", null)
}
}
}
}

private fun play() {
sessionManager?.currentCastSession?.remoteMediaClient?.play()
}

private fun pause() {
sessionManager?.currentCastSession?.remoteMediaClient?.pause()
}

private fun seek(args: Any?) {
if (args is Map<*, *>) {
val relative = (args["relative"] as? Boolean) ?: false
var interval = args["interval"] as? Double
interval = interval?.times(1000)
if (relative) {
interval = interval?.plus(sessionManager?.currentCastSession?.remoteMediaClient?.mediaStatus?.streamPosition ?: 0)
}
val seekOptions = MediaSeekOptions.Builder()
.setPosition(interval?.toLong() ?: 0)
.build()
sessionManager?.currentCastSession?.remoteMediaClient?.seek(seekOptions)
}
}

private fun isPlaying() = sessionManager?.currentCastSession?.remoteMediaClient?.isPlaying ?: false

override fun getView() = chromeCastButton

override fun dispose() {

}

override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when(call.method) {
"chromeCast#wait" -> result.success(null)
"chromeCast#loadMedia" -> {
loadMedia(call.arguments)
result.success(null)
}
"chromeCast#play" -> {
play()
result.success(null)
}
"chromeCast#pause" -> {
pause()
result.success(null)
}
"chromeCast#seek" -> {
seek(call.arguments)
result.success(null)
}
"chromeCast#isPlaying" -> result.success(isPlaying())
}
}

override fun onSessionStarted(p0: Session?, p1: String?) {
channel.invokeMethod("chromeCast#didStartSession", null)
}

override fun onSessionEnded(p0: Session?, p1: Int) {
channel.invokeMethod("chromeCast#didEndSession", null)
}

override fun onSessionResuming(p0: Session?, p1: String?) {

}

override fun onSessionResumed(p0: Session?, p1: Boolean) {

}

override fun onSessionResumeFailed(p0: Session?, p1: Int) {

}

override fun onSessionSuspended(p0: Session?, p1: Int) {

}

override fun onSessionStarting(p0: Session?) {

}

override fun onSessionEnding(p0: Session?) {

}

override fun onSessionStartFailed(p0: Session?, p1: Int) {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package it.aesys.flutter_video_cast

import android.app.Activity
import android.content.Context
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.platform.PlatformViewFactory
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView

class ChromeCastFactory(private val binaryMessenger: BinaryMessenger) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
var activity: Activity? = null

override fun create(
context: Context?,
viewId: Int,
args: Any?
): PlatformView = ChromeCastController(
messenger = binaryMessenger,
viewId = viewId,
context = activity
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package it.aesys.flutter_video_cast

import androidx.annotation.NonNull;

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.PluginRegistry.Registrar

/** FlutterVideoCastPlugin */
public class FlutterVideoCastPlugin: FlutterPlugin, ActivityAware {
private lateinit var chromeCastFactory: ChromeCastFactory

override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
chromeCastFactory = ChromeCastFactory(flutterPluginBinding.binaryMessenger)
flutterPluginBinding
.platformViewRegistry
.registerViewFactory(
"ChromeCastButton",
chromeCastFactory
)
}

// This static function is optional and equivalent to onAttachedToEngine. It supports the old
// pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
// plugin registration via this function while apps migrate to use the new Android APIs
// post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
//
// It is encouraged to share logic between onAttachedToEngine and registerWith to keep
// them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
// depending on the user's project. onAttachedToEngine or registerWith must both be defined
// in the same class.
companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
registrar
.platformViewRegistry()
.registerViewFactory(
"ChromeCastButton",
ChromeCastFactory(registrar.messenger())
)
}
}

override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {

}

override fun onAttachedToActivity(binding: ActivityPluginBinding) {
chromeCastFactory.activity = binding.activity
}

override fun onDetachedFromActivityForConfigChanges() {
TODO("Not yet implemented")
}

override fun onDetachedFromActivity() {
TODO("Not yet implemented")
}

override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
TODO("Not yet implemented")
}
}
44 changes: 44 additions & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/

# Web related
lib/generated_plugin_registrant.dart

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
10 changes: 10 additions & 0 deletions example/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: 2ae34518b87dd891355ed6c6ea8cb68c4d52bb9d
channel: stable

project_type: app
Loading

0 comments on commit cc2e11b

Please sign in to comment.