nexxPLAY Flutter
Features
Flutter plugin serves as a wrapper for the Android nexxPLAY, and, combined with the custom code that the "example" app provides, enables next features:
- nexxPLAY native view wrapped with a widget available for use
- Dynamic configuration support
- Public API, consisting from methods falling under these categories: 'Preparing and Configuring the Player', 'Playback Control', 'Requesting Player Status and Details'
- Player events observation
- Fullscreen mode
- PiP mode Please note that iOS is not supported by this plugin.
Integration guide
-
First of all, nexxPLAY dependency has to be included into pubspec.yaml.
-
Secondly, there is a set of Gradle preparations that need to be done:
2.1. Exclude META-INF & LICENCE files from the packaging options:
packagingOptions { exclude 'META-INF/ASL2.0' exclude 'META-INF/LICENSE' exclude 'META-INF/LICENSE.txt' exclude 'LICENSE.txt' exclude 'META-INF/license.txt' exclude 'META-INF/NOTICE' exclude 'META-INF/DEPENDENCIES' exclude 'META-INF/NOTICE.txt' exclude 'META-INF/notice.txt' }
Refer to
example/android/app/build.gradle
for more details.2.2. Minification has to be disabled. Either the native nexxPLAY package can be excluded by the minifier tool (
tv.nexx.*
) or the whole process could be disabled completely like this:minifyEnabled false shrinkResources false
Refer to
example/android/app/build.gradle
for more details. -
Thirdly, a set of Android native configurations have to be done:
3.1. In the Android app's main manifest file, add
tools:replace="android:label"
to theapplication
tag. Refer toexample/android/app/src/main/AndroidManifest.xml
for more details.3.2. In the Android app's main manifest file, add
android:resizeableActivity="true"
andandroid:supportsPictureInPicture="true"
to the tag of the Activity you are using. Refer toexample/android/app/src/main/AndroidManifest.xml
for more details.Refer to `example/android/app/src/main/AndroidManifest.xml` for more details. 3.3. In the Activity's code add (or extend) overrides for `onUserLeaveHint` and `onPictureInPictureModeChanged` methods like this: ```java public class MainActivity extends FlutterActivity { // ... @Override public void onUserLeaveHint() { super.onUserLeaveHint(); NexxPlugin.post(OnUserLeaveHintEvent.create()); } @Override public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) { super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig); NexxPlugin.post(OnPIPModeChangedEvent.create(isInPictureInPictureMode, newConfig)); } }
Refer to
example/android/app/src/main/java/tv/nexx/flutter/android_example/MainActivity.java
for more details.Kotlin version:
class MainActivity : FlutterActivity { override fun onUserLeaveHint() { super.onUserLeaveHint() NexxPlugin.post(OnUserLeaveHintEvent.create()) } override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) { super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig) NexxPlugin.post(OnPIPModeChangedEvent.create(isInPictureInPictureMode,newConfig)) } }
-
Next, inherit from the AppCompat theme for the Android native app part (required by ChromeCast, even if you don't use it, unfortunately):
<style name="NormalTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
Ensure that you have the AndroidX AppCompat dependency, a transitive or a direct one ( implementation "androidx.appcompat:appcompat:1.4.0"
). Refer to example/android/app/build.gradle
, example/android/app/src/main/res/values/styles.xml
and example/android/app/src/main/res/values-night/styles.xml
for more details.
-
Kotlin Gradle Plugin (KGP) with the newer Android Gradle Plugin versions are including a set of the androidx.* dependencies necessary for the native library; the
example
project uses1.9.20
for Kotlin and8.5
for AGP, Gradle Wrapper's version being8.7
. One of the exceptions hinting to the Gradle environment update isFatal Exception: java.lang.RuntimeException: Unable to get provider androidx.startup.InitializationProvider: java.lang.ClassNotFoundException: Didn't find class "androidx.startup.InitializationProvider"
. -
Lastly, there is a set of things to be done from the Flutter PoV for proper fullscreen and PiP support. Example app's
main.dart
file contains all the documentation necessary for that.INTEGRATION_GUIDE
markers were placed all over the documentation for navigation to make the integration process easier. -
OPTIONAL
Sharing Android's MediaSessionCompat instance for all the native nexxPLAY instances.7.1. In the
build.gradle
'sdependencies
block, the following line should be present:implementation "androidx.media:media:1.6.0"
. Refer toexample/android/app/build.gradle
for more details.7.2. In the host Activity class code,
protected void onCreate(@Nullable Bundle savedInstanceState)
method should be overriden (or, for Kotlin,protected onCreate(@Nullable savedInstanceState: Bundle)
). Refer toexample/android/app/src/main/java/tv/nexx/flutter/android_example/MainActivity.java
for more details.7.3. Inside the
onCreate(Bundle)
method, the following lines should be present:final MediaSessionCompat mediaSession = new MediaSessionCompat(getApplicationContext(), getPackageName()); NexxPlayPlugin.addEnvironmentConfigurationEntry(NexxPlayPlugin.KEY_MEDIA_SESSION, mediaSession);
Or, for Kotlin:
val mediaSession = MediaSessionCompat(applicationContext, packageName) NexxPlayPlugin.addEnvironmentConfigurationEntry(NexxPlayPlugin.KEY_MEDIA_SESSION, mediaSession)
The following import has to be present:
import android.support.v4.media.session.MediaSessionCompat;
For the Kotlin version, omit the ending semicolon.
-
OPTIONAL
Advertisements support.8.1. In the
build.gradle
'sdependencies
block, the following line should be present:implementation "tv.nexx.android:admanager:1.0.05"
. Refer toexample/android/app/build.gradle
for more details.8.2. In the host Activity class code,
protected void onCreate(@Nullable Bundle savedInstanceState)
method should be overriden (or, for Kotlin,protected onCreate(@Nullable savedInstanceState: Bundle)
). Refer toexample/android/app/src/main/java/tv/nexx/flutter/android_example/MainActivity.java
for more details.8.3. Inside the
onCreate(Bundle)
method, the following lines should be present:NexxPlayPlugin.addEnvironmentConfigurationEntry(NexxPlayPlugin.KEY_AD_MANAGER, NexxPlayAdManager::new);
Or, for Kotlin:
NexxPlayPlugin.addEnvironmentConfigurationEntry(NexxPlayPlugin.KEY_AD_MANAGER, ::NexxPlayAdManager)
The following import has to be present:
import tv.nexx.android.admanager.NexxPlayAdManager;
For the Kotlin version, omit the ending semicolon.
-
OPTIONAL
Chromecast support.9.1. The next native integration guide items have to be ensured to reproduced.
9.2. Application's activity should extend FlutterFragmentActivity or it's inheritor.
9.3. When resolving the CastContext instance as described by the native integration guide, a modification has to be applied so the CastContext instance is be included into the plugin's configuration:
CastContext.getSharedInstance(this, Executors.newSingleThreadExecutor()) .addOnSuccessListener(castContext -> NexxPlayPlugin.addEnvironmentConfigurationEntry(NexxPlayPlugin.KEY_CAST_CONTEXT, castContext)) .addOnFailureListener(exception -> Log.e("nexxPLAY", "Could not resolve CastContext", exception));
Or, for Kotlin:
CastContext.getSharedInstance(this, Executors.newSingleThreadExecutor()) .addOnSuccessListener { NexxPlayPlugin.addEnvironmentConfigurationEntry(NexxPlayPlugin.KEY_CAST_CONTEXT, it) } .addOnFailureListener { Log.e("nexxPLAY", "Could not resolve CastContext", it) }
The following imports have to be present:
import com.google.android.gms.cast.framework.CastContext; import java.util.concurrent.Executors; import android.util.Log;
For the Kotlin version, omit the ending semicolons.
-
OPTIONAL
Custom notification icon.10.1. Custom notification icon can be set to an Android's R.* resource via the native hook. First, the image resource has to be added to the Android's resources bundle. In case of PNGs or JPGs, it's sufficient to just put the file into
**/android/app/src/main/res/drawable
directory. Otherwise, official documentation contains additional information.10.2. Then the image resource reference has to be used in the configuration.
NexxPlayPlugin
class includes theaddNativeConfigurationEntry
and a static "key" valueKEY_NOTIFICATION_ICON
; value to be passed is the image resource reference — Android framework creates those automatically using the file name itself as the corresponding variable name (e.g. if your image is called "my_image.png" and is placed into the**/res/drawable
directory, then Android will generate theR.drawable.my_image
variable). Regular place for it is the native Android application's MainActivity class, specifically theonCreate
method override:@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... other configuration code NexxPlayPlugin.addNativeConfigurationEntry(NexxPlayPlugin.KEY_NOTIFICATION_ICON, R.drawable.widget_icon); }
Or, for Kotlin:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... other configuration code NexxPlayPlugin.addNativeConfigurationEntry(NexxPlayPlugin.KEY_NOTIFICATION_ICON, R.drawable.widget_icon) }
10.3. Refer to the
example
project for complete integration sample.
Libraries
- nexxplay
- nexxPLAY plugin provides a widget that can be used to embed the native Android player view into Flutter widget hierarchy, configuration routines, controller to manage the player, and the event system that can be plugged into with subscribers.