Skip to content

Commit

Permalink
Picture-In-Picture for Videos (#103)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben-Noah Engelhaupt authored and tobiasrohloff committed Dec 11, 2018
1 parent 368f749 commit 0e9162d
Show file tree
Hide file tree
Showing 15 changed files with 264 additions and 17 deletions.
7 changes: 5 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,11 @@
</activity>
<activity
android:name=".controllers.video.VideoActivity"
android:configChanges="orientation|screenSize"
android:launchMode="singleTop"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:parentActivityName=".controllers.section.CourseItemsActivity"
android:theme="@style/AppThemeDarkStatusBar">
<meta-data
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/de/xikolo/config/FeatureToggle.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package de.xikolo.config;

import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;

import de.xikolo.BuildConfig;

public class FeatureToggle {
Expand Down Expand Up @@ -30,4 +34,7 @@ public static boolean hlsVideo() {
return Config.DEBUG;
}

public static boolean pictureInPicture(Context context) {
return Build.VERSION.SDK_INT >= 26 && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ public boolean onCreateOptionsMenu(Menu menu) {
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);

setIntent(intent);
AutoBundle.bind(this);

handleIntent(intent);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.xikolo.controllers.base;


import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.LoaderManager;
Expand Down Expand Up @@ -35,6 +36,14 @@ protected void onCreate(Bundle savedInstanceState) {
}
}

@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);

getSupportLoaderManager().destroyLoader(loaderId());
initLoader();
}

private void initLoader() {
// LoaderCallbacks as an object, so no hint regarding Loader will be leak to the subclasses.
getSupportLoaderManager().initLoader(loaderId(), null, new LoaderManager.LoaderCallbacks<P>() {
Expand Down
20 changes: 18 additions & 2 deletions app/src/main/java/de/xikolo/controllers/helper/VideoHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,13 @@ public int getDuration() {
return (int) videoView.getDuration();
}

public boolean isPlaying() {
if (videoView != null) {
return videoView.isPlaying();
}
return false;
}

public void play() {
buttonPlay.setText(activity.getString(R.string.icon_pause));
videoView.start();
Expand All @@ -368,7 +375,7 @@ public void pause() {
saveCurrentPosition();
}

private void release() {
public void release() {
pause();
videoView.release();
seekBarPreviewThread.quit();
Expand Down Expand Up @@ -452,7 +459,6 @@ public boolean handleBackPress() {
hideSettings();
return false;
}
release();
return true;
}

Expand Down Expand Up @@ -530,6 +536,14 @@ public void onPlaybackSpeedClick() {
public void onQualityClick() {
showSettings(videoSettingsHelper.buildQualityView());
}

@Override
public void onPipClick() {
hideSettings();
if(controllerListener != null) {
controllerListener.onPipClick();
}
}
},
videoMode -> {
if (videoMode == VideoSettingsHelper.VideoMode.HD) {
Expand Down Expand Up @@ -722,6 +736,8 @@ public interface ControllerListener {
void onSettingsOpen();

void onSettingsClosed();

void onPipClick();
}

private static class MessageHandler extends Handler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package de.xikolo.controllers.helper
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Build
import android.provider.Settings
import android.support.annotation.StringRes
import android.support.v4.content.ContextCompat
Expand All @@ -14,6 +13,7 @@ import android.widget.LinearLayout
import android.widget.TextView
import de.xikolo.R
import de.xikolo.config.FeatureToggle
import de.xikolo.managers.PermissionManager
import de.xikolo.models.VideoSubtitles
import de.xikolo.utils.PlaybackSpeedUtil
import java.util.*
Expand Down Expand Up @@ -63,6 +63,16 @@ class VideoSettingsHelper(private val context: Context, private val subtitles: L
)
)
}
if(FeatureToggle.pictureInPicture(context) && PermissionManager.hasPipPermission(context)) {
list.addView(
buildSettingsItem(
R.string.icon_pip,
context.getString(R.string.video_settings_pip),
View.OnClickListener { clickListener.onPipClick() },
false
)
)
}

return list.parent as ViewGroup
}
Expand Down Expand Up @@ -141,12 +151,7 @@ class VideoSettingsHelper(private val context: Context, private val subtitles: L
context.getString(R.string.video_settings_subtitles),
context.getString(R.string.icon_settings),
View.OnClickListener {
val subtitleSettings =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
Settings.ACTION_CAPTIONING_SETTINGS
else
Settings.ACTION_ACCESSIBILITY_SETTINGS
ContextCompat.startActivity(context, Intent(subtitleSettings), null)
ContextCompat.startActivity(context, Intent(Settings.ACTION_CAPTIONING_SETTINGS), null)
}
)

Expand Down Expand Up @@ -239,6 +244,8 @@ class VideoSettingsHelper(private val context: Context, private val subtitles: L
fun onPlaybackSpeedClick()

fun onSubtitleClick()

fun onPipClick()
}

// also invoked when old value equal to new value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ class VideoPreviewFragment : LoadingStatePresenterFragment<VideoPreviewPresenter

override fun startVideo(video: Video) {
activity?.let {
val intent = VideoActivityAutoBundle.builder(courseId, sectionId, itemId, video.id).build(it)
val intent = VideoActivityAutoBundle.builder(courseId, sectionId, itemId, video.id).parentIntent(it.intent).build(it)
startActivity(intent)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ import de.xikolo.App
import de.xikolo.BuildConfig
import de.xikolo.R
import de.xikolo.config.Config
import de.xikolo.config.FeatureToggle
import de.xikolo.controllers.dialogs.ProgressDialogHorizontal
import de.xikolo.controllers.dialogs.ProgressDialogHorizontalAutoBundle
import de.xikolo.controllers.dialogs.StorageMigrationDialog
import de.xikolo.controllers.dialogs.StorageMigrationDialogAutoBundle
import de.xikolo.controllers.login.LoginActivityAutoBundle
import de.xikolo.events.LoginEvent
import de.xikolo.events.LogoutEvent
import de.xikolo.managers.PermissionManager
import de.xikolo.managers.UserManager
import de.xikolo.services.DownloadService
import de.xikolo.utils.DeviceUtil
Expand All @@ -49,6 +51,7 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP

override fun onResume() {
preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
refreshPipStatus()
super.onResume()
}

Expand Down Expand Up @@ -145,6 +148,25 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
general.removePreference(storagePref)
}

val pipSettings = findPreference(getString(R.string.preference_video_pip))
if (!FeatureToggle.pictureInPicture(App.getInstance())) {
val video = findPreference(getString(R.string.preference_category_video_playback_speed)) as PreferenceCategory
video.removePreference(pipSettings)
} else {
pipSettings.setOnPreferenceClickListener {
try {
val intent = Intent("android.settings.PICTURE_IN_PICTURE_SETTINGS")
val uri = Uri.fromParts("package", activity?.packageName, null)
intent.data = uri
activity?.startActivity(intent)
} catch (e: RuntimeException) {
PermissionManager.startAppInfo(activity)
}
true
}
refreshPipStatus()
}

val copyright = findPreference(getString(R.string.preference_copyright))
copyright.title = String.format(copyright.title.toString(), Calendar.getInstance().get(Calendar.YEAR))
copyright.setOnPreferenceClickListener { _ ->
Expand Down Expand Up @@ -214,6 +236,15 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
}
}

private fun refreshPipStatus() {
val pipSettings = findPreference(getString(R.string.preference_video_pip))
if (!PermissionManager.hasPipPermission(context)) {
pipSettings.summary = getString(R.string.settings_summary_video_pip_unavailable)
} else {
pipSettings.summary = ""
}
}

private fun buildLoginView(pref: Preference?) {
if (pref != null) {
pref.title = getString(R.string.login)
Expand Down
Loading

0 comments on commit 0e9162d

Please sign in to comment.