diff --git a/app/src/main/java/net/schueller/peertube/activity/VideoPlayActivity.java b/app/src/main/java/net/schueller/peertube/activity/VideoPlayActivity.java index 3f658da..aa33eb1 100644 --- a/app/src/main/java/net/schueller/peertube/activity/VideoPlayActivity.java +++ b/app/src/main/java/net/schueller/peertube/activity/VideoPlayActivity.java @@ -21,11 +21,16 @@ package net.schueller.peertube.activity; import android.annotation.SuppressLint; import android.app.AppOpsManager; +import android.app.PendingIntent; import android.app.PictureInPictureParams; +import android.app.RemoteAction; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Configuration; +import android.graphics.drawable.Icon; import android.os.Build; import android.os.Bundle; @@ -49,12 +54,18 @@ import net.schueller.peertube.fragment.VideoMetaDataFragment; import net.schueller.peertube.fragment.VideoPlayerFragment; import net.schueller.peertube.service.VideoPlayerService; + +import java.util.ArrayList; import java.util.Objects; import androidx.fragment.app.FragmentManager; //import static net.schueller.peertube.helper.Constants.BACKGROUND_PLAY_PREF_KEY; +import static com.google.android.exoplayer2.ui.PlayerNotificationManager.ACTION_PAUSE; +import static com.google.android.exoplayer2.ui.PlayerNotificationManager.ACTION_PLAY; +import static com.google.android.exoplayer2.ui.PlayerNotificationManager.ACTION_STOP; +import static net.schueller.peertube.helper.Constants.BACKGROUND_AUDIO; import static net.schueller.peertube.helper.Constants.DEFAULT_THEME; import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY; @@ -62,7 +73,108 @@ public class VideoPlayActivity extends AppCompatActivity { private static final String TAG = "VideoPlayActivity"; + private static boolean floatMode = false; + private static final int REQUEST_CODE = 101; + private BroadcastReceiver receiver; + //This can only be called when in entering pip mode which can't happen if the device doesn't support pip mode. + @SuppressLint("NewApi") + public void makePipControls() { + FragmentManager fragmentManager = getSupportFragmentManager(); + VideoPlayerFragment videoPlayerFragment = (VideoPlayerFragment) fragmentManager.findFragmentById(R.id.video_player_fragment); + ArrayList actions = new ArrayList<>(); + + Intent actionIntent = new Intent(BACKGROUND_AUDIO); + PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), REQUEST_CODE, actionIntent, 0); + @SuppressLint({"NewApi", "LocalSuppress"}) Icon icon = Icon.createWithResource(getApplicationContext(), android.R.drawable.stat_sys_speakerphone); + @SuppressLint({"NewApi", "LocalSuppress"}) RemoteAction remoteAction = new RemoteAction(icon, "close pip", "from pip window custom command", pendingIntent); + actions.add(remoteAction); + + actionIntent = new Intent(ACTION_STOP); + pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), REQUEST_CODE, actionIntent, 0); + icon = Icon.createWithResource(getApplicationContext(), com.google.android.exoplayer2.ui.R.drawable.exo_notification_stop); + remoteAction = new RemoteAction(icon, "play", "stop the media", pendingIntent); + actions.add(remoteAction); + + if (videoPlayerFragment.isPaused()){ + Log.e(TAG,"setting actions with play button"); + actionIntent = new Intent(ACTION_PLAY); + pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), REQUEST_CODE, actionIntent, 0); + icon = Icon.createWithResource(getApplicationContext(), com.google.android.exoplayer2.ui.R.drawable.exo_notification_play); + remoteAction = new RemoteAction(icon, "play", "play the media", pendingIntent); + actions.add(remoteAction); + } else { + Log.e(TAG,"setting actions with pause button"); + actionIntent = new Intent(ACTION_PAUSE); + pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), REQUEST_CODE, actionIntent, 0); + icon = Icon.createWithResource(getApplicationContext(), com.google.android.exoplayer2.ui.R.drawable.exo_notification_pause); + remoteAction = new RemoteAction(icon, "pause", "pause the media", pendingIntent); + actions.add(remoteAction); + } + + + //add custom actions to pip window + PictureInPictureParams params = + new PictureInPictureParams.Builder() + .setActions(actions) + .build(); + setPictureInPictureParams(params); + + } + public void changedToPipMode() { + FragmentManager fragmentManager = getSupportFragmentManager(); + VideoPlayerFragment videoPlayerFragment = (VideoPlayerFragment) fragmentManager.findFragmentById(R.id.video_player_fragment); + + videoPlayerFragment.showControls(false); + //create custom actions + makePipControls(); + + //setup receiver to handle customer actions + IntentFilter filter = new IntentFilter(); + filter.addAction(ACTION_STOP); + filter.addAction(ACTION_PAUSE); + filter.addAction(ACTION_PLAY); + filter.addAction((BACKGROUND_AUDIO)); + receiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(ACTION_PAUSE)) { + videoPlayerFragment.pauseVideo(); + makePipControls(); + } + if (action.equals(ACTION_PLAY)) { + videoPlayerFragment.unPauseVideo(); + makePipControls(); + } + + if (action.equals(BACKGROUND_AUDIO)) { + unregisterReceiver(receiver); + finish(); + } + if (action.equals(ACTION_STOP)) { + unregisterReceiver(receiver); + finishAndRemoveTask(); + } + } + }; + registerReceiver(receiver, filter); + + Log.v(TAG, "switched to pip "); + floatMode=true; + videoPlayerFragment.showControls(false); + } + public void changedToNormalMode(){ + FragmentManager fragmentManager = getSupportFragmentManager(); + VideoPlayerFragment videoPlayerFragment = (VideoPlayerFragment) fragmentManager.findFragmentById(R.id.video_player_fragment); + + videoPlayerFragment.showControls(true); + if (receiver != null) { + unregisterReceiver(receiver); + } + Log.v(TAG,"switched to normal"); + floatMode=false; + } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -357,9 +469,11 @@ public class VideoPlayActivity extends AppCompatActivity { VideoPlayerFragment videoPlayerFragment = (VideoPlayerFragment) fragmentManager.findFragmentById(R.id.video_player_fragment); if (isInPictureInPictureMode) { + changedToPipMode(); Log.v(TAG,"switched to pip "); videoPlayerFragment.useController(false); } else { + changedToNormalMode(); Log.v(TAG,"switched to normal"); videoPlayerFragment.useController(true); } diff --git a/app/src/main/java/net/schueller/peertube/fragment/VideoPlayerFragment.java b/app/src/main/java/net/schueller/peertube/fragment/VideoPlayerFragment.java index f7cac8a..9fad3b3 100644 --- a/app/src/main/java/net/schueller/peertube/fragment/VideoPlayerFragment.java +++ b/app/src/main/java/net/schueller/peertube/fragment/VideoPlayerFragment.java @@ -268,6 +268,17 @@ public class VideoPlayerFragment extends Fragment implements VideoRendererEventL mService.player.setPlayWhenReady(!mService.player.getPlayWhenReady()); } } + public void unPauseVideo() { + if (mBound) { + mService.player.setPlayWhenReady(true); + } + } + public boolean isPaused(){ + return !mService.player.getPlayWhenReady(); + } + public void showControls(boolean value){ + simpleExoPlayerView.setUseController(value); + } public void stopVideo() { if (mBound) { diff --git a/app/src/main/java/net/schueller/peertube/helper/Constants.java b/app/src/main/java/net/schueller/peertube/helper/Constants.java index 729377f..0e87a3f 100644 --- a/app/src/main/java/net/schueller/peertube/helper/Constants.java +++ b/app/src/main/java/net/schueller/peertube/helper/Constants.java @@ -21,4 +21,5 @@ public class Constants { public static final String THEME_PREF_KEY = "pref_theme"; public static final String DEFAULT_THEME = "AppTheme.BLUE"; public static final String BACKGROUND_PLAY_PREF_KEY = "pref_background_play"; + public static final String BACKGROUND_AUDIO = "BACKGROUND_AUDIO"; } diff --git a/app/src/main/java/net/schueller/peertube/helper/MetaDataHelper.java b/app/src/main/java/net/schueller/peertube/helper/MetaDataHelper.java index 6c4b98e..84e9de9 100644 --- a/app/src/main/java/net/schueller/peertube/helper/MetaDataHelper.java +++ b/app/src/main/java/net/schueller/peertube/helper/MetaDataHelper.java @@ -28,10 +28,9 @@ import java.util.Date; public class MetaDataHelper { public static String getMetaString(Date getCreatedAt, Integer viewCount, Context context) { - return DateUtils. - getRelativeTimeSpanString(getCreatedAt.getTime()).toString() + + return (DateUtils.getRelativeTimeSpanString(context,getCreatedAt.getTime(),false).toString() + context.getResources().getString(R.string.meta_data_seperator) + - viewCount + context.getResources().getString(R.string.meta_data_views); + viewCount + context.getResources().getString(R.string.meta_data_views)); } public static String getOwnerString(String accountName, String serverHost, Context context) { diff --git a/app/src/main/java/net/schueller/peertube/service/VideoPlayerService.java b/app/src/main/java/net/schueller/peertube/service/VideoPlayerService.java index e3fcb71..d3aa9a8 100644 --- a/app/src/main/java/net/schueller/peertube/service/VideoPlayerService.java +++ b/app/src/main/java/net/schueller/peertube/service/VideoPlayerService.java @@ -64,6 +64,7 @@ import net.schueller.peertube.model.Video; import static android.media.session.PlaybackState.ACTION_PAUSE; import static android.media.session.PlaybackState.ACTION_PLAY; +import static com.google.android.exoplayer2.ui.PlayerNotificationManager.ACTION_STOP; import static net.schueller.peertube.activity.VideoListActivity.EXTRA_VIDEOID; public class VideoPlayerService extends Service { @@ -107,6 +108,7 @@ public class VideoPlayerService extends Service { if (playbackState == ACTION_PLAY) { // this means that play is available, hence the audio is paused or stopped Log.v(TAG, "ACTION_PAUSE: " + playbackState); unregisterReceiver(myNoisyAudioStreamReceiver); + myNoisyAudioStreamReceiver=null; } } } ); @@ -243,6 +245,7 @@ public class VideoPlayerService extends Service { // don't show skip buttons in notification playerNotificationManager.setUseNavigationActions(false); + playerNotificationManager.setUseStopAction(true); playerNotificationManager.setNotificationListener( new PlayerNotificationManager.NotificationListener() { @@ -254,9 +257,18 @@ public class VideoPlayerService extends Service { @Override public void onNotificationCancelled(int notificationId) { Log.v(TAG, "onNotificationCancelled..."); + stopForeground(true); + Intent killFloat = new Intent(ACTION_STOP); + sendBroadcast(killFloat); + /* + Intent killFloat = new Intent(BROADCAST_ACTION); + Intent killFloatingWindow = new Intent(getApplicationContext(),VideoPlayActivity.class); + killFloatingWindow.putExtra("killFloat",true); + startActivity(killFloatingWindow); // TODO: only kill the notification if we no longer have a bound activity stopForeground(true); + */ } } ); diff --git a/app/src/main/res/layout/row_video.xml b/app/src/main/res/layout/row_video.xml index afc2c1e..170c104 100644 --- a/app/src/main/res/layout/row_video.xml +++ b/app/src/main/res/layout/row_video.xml @@ -3,6 +3,7 @@ xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" + android:focusable="true" card_view:cardCornerRadius="0dp" card_view:cardElevation="0dp" card_view:contentPadding="0dp"