Skip to content

Commit

Permalink
Feature/january changes (#193)
Browse files Browse the repository at this point in the history
* Reusable video list

* Reusable video list

* Fixed Android native build warnings

* Fixed placeholder until play issues

* Added placeholderOnTop in BetterPlayerConfiguration

* Changelog update
  • Loading branch information
jhomlala authored Jan 3, 2021
1 parent 5257f03 commit 902af1c
Show file tree
Hide file tree
Showing 20 changed files with 523 additions and 113 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## 0.0.43
* Added autoDispose flag in BetterPlayerConfiguration
* Added removeEventsListener in BetterPlayerController
* Video list examples update
* Fixed Android native build warnings
* Fixed placeholder until play issues
* Added placeholderOnTop to the BetterPlayerConfiguration
* Lint fixes

## 0.0.42
* Fixed resolution issue
* Fixed type of BetterPlayerDataSource for file type
Expand Down
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ This plugin is based on [Chewie](https://github.com/brianegan/chewie). Chewie is

```yaml
dependencies:
better_player: ^0.0.42
better_player: ^0.0.43
```
2. Install it
Expand Down Expand Up @@ -269,6 +269,11 @@ Possible configuration options:
/// Should the placeholder be shown until play is pressed
final bool showPlaceholderUntilPlay;
/// Placeholder position of player stack. If false, then placeholder will be
/// displayed on the bottom, so user need to hide it manually. Default is
/// true.
final bool placeholderOnTop;
/// A widget which is placed between the video and the controls
final Widget overlay;
Expand Down Expand Up @@ -324,6 +329,14 @@ Possible configuration options:
///[deviceOrientationsOnFullScreen] and [fullScreenAspectRatio] value will be
/// ignored.
final bool autoDetectFullscreenDeviceOrientation;
///Defines flag which enables/disables lifecycle handling (pause on app closed,
///play on app resumed). Default value is true.
final bool handleLifecycle;
///Defines flag which enabled/disabled auto dispose on BetterPlayer dispose.
///Default value is true.
final bool autoDispose;
```

### BetterPlayerSubtitlesConfiguration
Expand Down
78 changes: 30 additions & 48 deletions android/src/main/java/com/jhomlala/better_player/BetterPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;
import android.view.Surface;

import com.google.android.exoplayer2.C;
Expand Down Expand Up @@ -52,7 +51,6 @@
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.view.TextureRegistry;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
Expand All @@ -73,25 +71,15 @@ final class BetterPlayer {
private static final String DEFAULT_NOTIFICATION_CHANNEL = "BETTER_PLAYER_NOTIFICATION";
private static final int NOTIFICATION_ID = 20772077;

private SimpleExoPlayer exoPlayer;

private Surface surface;

private final SimpleExoPlayer exoPlayer;
private final DefaultTrackSelector trackSelector;
private final TextureRegistry.SurfaceTextureEntry textureEntry;

private QueuingEventSink eventSink = new QueuingEventSink();

private final QueuingEventSink eventSink = new QueuingEventSink();
private final EventChannel eventChannel;

private boolean isInitialized = false;

private Surface surface;
private String key;

private DefaultTrackSelector trackSelector;

private long maxCacheSize;
private long maxCacheFileSize;

private PlayerNotificationManager playerNotificationManager;
private Handler refreshHandler;
private Runnable refreshRunnable;
Expand Down Expand Up @@ -175,24 +163,22 @@ public String getCurrentContentText(Player player) {
@Nullable
@Override
public Bitmap getCurrentLargeIcon(Player player, PlayerNotificationManager.BitmapCallback callback) {
if (imageUrl == null){
if (imageUrl == null) {
return null;
}
if (bitmap != null){
if (bitmap != null) {
return bitmap;
}
new Thread(() -> {
bitmap = null;
if (imageUrl.contains("http")){
if (imageUrl.contains("http")) {
bitmap = getBitmapFromExternalURL(imageUrl);
} else {
bitmap = getBitmapFromInternalURL(imageUrl);
}

Bitmap finalBitmap = bitmap;
new Handler(Looper.getMainLooper()).post(() -> {
callback.onBitmap(finalBitmap);
});
new Handler(Looper.getMainLooper()).post(() -> callback.onBitmap(finalBitmap));

}).start();
return null;
Expand Down Expand Up @@ -246,7 +232,7 @@ public void onCommand(String command, Bundle extras, ResultReceiver cb) {
playerNotificationManager.setControlDispatcher(new ControlDispatcher() {
@Override
public boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady) {
String eventType = "";
String eventType;
if (player.getPlayWhenReady()) {
eventType = "pause";
} else {
Expand Down Expand Up @@ -287,25 +273,22 @@ public boolean dispatchStop(Player player, boolean reset) {
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
refreshHandler = new Handler();
refreshRunnable = new Runnable() {
@Override
public void run() {
PlaybackStateCompat playbackState = null;
if (exoPlayer.getPlayWhenReady()) {
playbackState = new PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_SEEK_TO)
.setState(PlaybackStateCompat.STATE_PAUSED, getPosition(), 1.0f)
.build();
} else {
playbackState = new PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_SEEK_TO)
.setState(PlaybackStateCompat.STATE_PLAYING, getPosition(), 1.0f)
.build();
}

mediaSession.setPlaybackState(playbackState);
refreshHandler.postDelayed(refreshRunnable, 1000);
refreshRunnable = () -> {
PlaybackStateCompat playbackState;
if (exoPlayer.getPlayWhenReady()) {
playbackState = new PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_SEEK_TO)
.setState(PlaybackStateCompat.STATE_PAUSED, getPosition(), 1.0f)
.build();
} else {
playbackState = new PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_SEEK_TO)
.setState(PlaybackStateCompat.STATE_PLAYING, getPosition(), 1.0f)
.build();
}

mediaSession.setPlaybackState(playbackState);
refreshHandler.postDelayed(refreshRunnable, 1000);
};
refreshHandler.postDelayed(refreshRunnable, 0);
}
Expand All @@ -323,36 +306,35 @@ public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
exoPlayer.seekTo(0);
}

public void removeNotificationData(){
public void removeNotificationData() {
exoPlayer.removeListener(exoPlayerEventListener);
if (refreshHandler != null) {
refreshHandler.removeCallbacksAndMessages(null);
refreshHandler = null;
refreshRunnable = null;
}
if (playerNotificationManager != null){
if (playerNotificationManager != null) {
playerNotificationManager.setPlayer(null);
}
bitmap = null;
}

private static Bitmap getBitmapFromInternalURL(String src){
private static Bitmap getBitmapFromInternalURL(String src) {
try {
File file = new File(src);
return BitmapFactory.decodeFile(src);
} catch (Exception exception){
} catch (Exception exception) {
return null;
}
}

private static Bitmap getBitmapFromExternalURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
return BitmapFactory.decodeStream(input);
} catch (IOException exception) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import android.util.Log;
import android.util.LongSparseArray;

import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.EventChannel;
Expand Down Expand Up @@ -108,12 +109,12 @@ public void onAttachedToEngine(FlutterPluginBinding binding) {
binding.getBinaryMessenger(),
FlutterMain::getLookupKeyForAsset,
FlutterMain::getLookupKeyForAsset,
binding.getFlutterEngine().getRenderer());
binding.getTextureRegistry());
flutterState.startListening(this);
}

@Override
public void onDetachedFromEngine(FlutterPluginBinding binding) {
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
if (flutterState == null) {
Log.wtf(TAG, "Detached from the engine before registering to it.");
}
Expand All @@ -140,7 +141,7 @@ private void onDestroy() {
}

@Override
public void onMethodCall(MethodCall call, Result result) {
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (flutterState == null || flutterState.textureRegistry == null) {
result.error("no_activity", "better_player plugin requires a foreground activity", null);
return;
Expand Down Expand Up @@ -211,14 +212,14 @@ private void onMethodCall(MethodCall call, Result result, long textureId, Better
player.sendBufferingUpdate();
break;
case SET_SPEED_METHOD:
player.setSpeed((Double) call.argument(SPEED_PARAMETER));
player.setSpeed(call.argument(SPEED_PARAMETER));
result.success(null);
break;
case SET_TRACK_PARAMETERS_METHOD:
player.setTrackParameters(
(Integer) call.argument(WIDTH_PARAMETER),
(Integer) call.argument(HEIGHT_PARAMETER),
(Integer) call.argument(BITRATE_PARAMETER));
call.argument(WIDTH_PARAMETER),
call.argument(HEIGHT_PARAMETER),
call.argument(BITRATE_PARAMETER));
result.success(null);
break;
case DISPOSE_METHOD:
Expand Down Expand Up @@ -321,8 +322,8 @@ private void removeOtherNotificationListeners() {
}
}


private <T> T getParameter(Map<String, Object> parameters, Object key, T defaultValue) {
@SuppressWarnings("unchecked")
private <T> T getParameter(Map<String, Object> parameters, String key, T defaultValue) {
if (parameters.containsKey(key)) {
Object value = parameters.get(key);
if (value != null) {
Expand Down
2 changes: 1 addition & 1 deletion example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion 28
compileSdkVersion 29

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
Expand Down
1 change: 1 addition & 0 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@
<service android:name=".BetterPlayerService" android:stopWithTask="false"/>
</application>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
18 changes: 7 additions & 11 deletions example/android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
include ':app'

def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()

def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }

plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
File renamed without changes.
Loading

0 comments on commit 902af1c

Please sign in to comment.