diff options
author | Martin Fietz <Martin.Fietz@gmail.com> | 2018-04-22 08:07:05 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-22 08:07:05 +0200 |
commit | a9e269b3bf5a1800bc8f6d5e2b62924c09be80a3 (patch) | |
tree | 60540380e717bf3191390b489e4e86ec6a0322ec | |
parent | 1cc72b37288fed7682bf2c55f0baee85dfc5a947 (diff) | |
parent | 0f80fac6805bd7b1476aa04a37d6f12f1ba10d92 (diff) | |
download | AntennaPod-a9e269b3bf5a1800bc8f6d5e2b62924c09be80a3.zip |
Merge pull request #2506 from ByteHamster/picture-in-picture
Added Picure in picture
13 files changed, 222 insertions, 36 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7a17baff6..23dc8b570 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -222,7 +222,8 @@ <activity android:name=".activity.VideoplayerActivity" - android:configChanges="keyboardHidden|orientation" + android:configChanges="keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize" + android:supportsPictureInPicture="true" android:screenOrientation="sensorLandscape"> <meta-data android:name="android.support.PARENT_ACTIVITY" diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java index 232ff4311..21e375435 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java @@ -46,6 +46,7 @@ import de.danoeh.antennapod.core.util.Flavors; import de.danoeh.antennapod.core.util.ShareUtils; import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.core.util.Supplier; +import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; import de.danoeh.antennapod.core.util.playback.MediaPlayerError; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; @@ -225,9 +226,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements @Override protected void onPause() { - if(controller != null) { - controller.reinitServiceIfPaused(); - controller.pause(); + if (!PictureInPictureUtil.isInPictureInPictureMode(this)) { + if (controller != null) { + controller.reinitServiceIfPaused(); + controller.pause(); + } } super.onPause(); } @@ -379,6 +382,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements } else { startActivity(intent); } + finish(); return true; } else { if (media != null) { diff --git a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java index 54758acf4..733f39b63 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java @@ -10,27 +10,31 @@ import android.support.v4.view.WindowCompat; import android.support.v7.app.ActionBar; import android.util.Log; import android.util.Pair; +import android.view.Menu; +import android.view.MenuItem; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.View; import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.SeekBar; - -import java.lang.ref.WeakReference; -import java.util.concurrent.atomic.AtomicBoolean; - import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.MediaType; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.service.playback.PlayerStatus; +import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; import de.danoeh.antennapod.core.util.playback.ExternalMedia; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.view.AspectRatioVideoView; +import java.lang.ref.WeakReference; +import java.util.concurrent.atomic.AtomicBoolean; + /** * Activity for playing video files. */ @@ -52,6 +56,7 @@ public class VideoplayerActivity extends MediaplayerActivity { private LinearLayout videoOverlay; private AspectRatioVideoView videoview; private ProgressBar progressIndicator; + private FrameLayout videoframe; @Override protected void chooseTheme() { @@ -96,10 +101,27 @@ public class VideoplayerActivity extends MediaplayerActivity { } @Override + protected void onStop() { + super.onStop(); + if (!PictureInPictureUtil.isInPictureInPictureMode(this)) { + videoControlsHider.stop(); + } + } + + @Override + public void onUserLeaveHint () { + if (!PictureInPictureUtil.isInPictureInPictureMode(this) && UserPreferences.getVideoBackgroundBehavior() + == UserPreferences.VideoBackgroundBehavior.PICTURE_IN_PICTURE) { + compatEnterPictureInPicture(); + } + } + + @Override protected void onPause() { - videoControlsHider.stop(); - if (controller != null && controller.getStatus() == PlayerStatus.PLAYING) { - controller.pause(); + if (!PictureInPictureUtil.isInPictureInPictureMode(this)) { + if (controller != null && controller.getStatus() == PlayerStatus.PLAYING) { + controller.pause(); + } } super.onPause(); } @@ -127,7 +149,7 @@ public class VideoplayerActivity extends MediaplayerActivity { @Override protected void setupGUI() { - if(isSetup.getAndSet(true)) { + if (isSetup.getAndSet(true)) { return; } super.setupGUI(); @@ -135,20 +157,23 @@ public class VideoplayerActivity extends MediaplayerActivity { controls = (LinearLayout) findViewById(R.id.controls); videoOverlay = (LinearLayout) findViewById(R.id.overlay); videoview = (AspectRatioVideoView) findViewById(R.id.videoview); + videoframe = (FrameLayout) findViewById(R.id.videoframe); progressIndicator = (ProgressBar) findViewById(R.id.progressIndicator); videoview.getHolder().addCallback(surfaceHolderCallback); - videoview.setOnTouchListener(onVideoviewTouched); + videoframe.setOnTouchListener(onVideoviewTouched); + videoOverlay.setOnTouchListener((view, motionEvent) -> true); // To suppress touches directly below the slider if (Build.VERSION.SDK_INT >= 16) { videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); } - if (Build.VERSION.SDK_INT >= 14) { - videoOverlay.setFitsSystemWindows(true); - } + videoOverlay.setFitsSystemWindows(true); setupVideoControlsToggler(); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + + videoframe.getViewTreeObserver().addOnGlobalLayoutListener(() -> + videoview.setAvailableSize(videoframe.getWidth(), videoframe.getHeight())); } @Override @@ -176,6 +201,9 @@ public class VideoplayerActivity extends MediaplayerActivity { private final View.OnTouchListener onVideoviewTouched = (v, event) -> { if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (PictureInPictureUtil.isInPictureInPictureMode(this)) { + return true; + } videoControlsHider.stop(); toggleVideoControlsVisibility(); if (videoControlsShowing) { @@ -260,7 +288,9 @@ public class VideoplayerActivity extends MediaplayerActivity { public void surfaceDestroyed(SurfaceHolder holder) { Log.d(TAG, "Videosurface was destroyed"); videoSurfaceCreated = false; - if (controller != null && !destroyingDueToReload) { + if (controller != null && !destroyingDueToReload + && UserPreferences.getVideoBackgroundBehavior() + != UserPreferences.VideoBackgroundBehavior.CONTINUE_PLAYING) { controller.notifyVideoSurfaceAbandoned(); } } @@ -269,6 +299,13 @@ public class VideoplayerActivity extends MediaplayerActivity { @Override protected void onReloadNotification(int notificationCode) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && PictureInPictureUtil.isInPictureInPictureMode(this)) { + if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO + || notificationCode == PlaybackService.EXTRA_CODE_CAST) { + finish(); + } + return; + } if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO) { Log.d(TAG, "ReloadNotification received, switching to Audioplayer now"); destroyingDueToReload = true; @@ -313,28 +350,31 @@ public class VideoplayerActivity extends MediaplayerActivity { videoOverlay.startAnimation(animation); controls.startAnimation(animation); } - if (Build.VERSION.SDK_INT >= 14) { - videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); - } + videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); } @SuppressLint("NewApi") - private void hideVideoControls() { - final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_out); - if (animation != null) { - videoOverlay.startAnimation(animation); - controls.startAnimation(animation); - } - if (Build.VERSION.SDK_INT >= 14) { - int videoviewFlag = (Build.VERSION.SDK_INT >= 16) ? View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION : 0; - getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | videoviewFlag); - videoOverlay.setFitsSystemWindows(true); + private void hideVideoControls(boolean showAnimation) { + if (showAnimation) { + final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_out); + if (animation != null) { + videoOverlay.startAnimation(animation); + controls.startAnimation(animation); + } } + int videoviewFlag = (Build.VERSION.SDK_INT >= 16) ? View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION : 0; + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | videoviewFlag); + videoOverlay.setFitsSystemWindows(true); + videoOverlay.setVisibility(View.GONE); controls.setVisibility(View.GONE); } + private void hideVideoControls() { + hideVideoControls(true); + } + @Override protected int getContentViewResourceId() { return R.layout.videoplayer_activity; @@ -350,6 +390,32 @@ public class VideoplayerActivity extends MediaplayerActivity { } } + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + if (PictureInPictureUtil.supportsPictureInPicture(this)) { + menu.findItem(R.id.player_go_to_picture_in_picture).setVisible(true); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.player_go_to_picture_in_picture) { + compatEnterPictureInPicture(); + return true; + } + return super.onOptionsItemSelected(item); + } + + private void compatEnterPictureInPicture() { + if (PictureInPictureUtil.supportsPictureInPicture(this) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + getSupportActionBar().hide(); + hideVideoControls(false); + enterPictureInPictureMode(); + } + } + private static class VideoControlsHider extends Handler { private static final int DELAY = 2500; @@ -362,7 +428,7 @@ public class VideoplayerActivity extends MediaplayerActivity { private final Runnable hideVideoControls = () -> { VideoplayerActivity vpa = activity != null ? activity.get() : null; - if(vpa == null) { + if (vpa == null) { return; } if (vpa.videoControlsShowing) { diff --git a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java index 1ab60ef61..83dd3fe9c 100644 --- a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java +++ b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.config; import android.content.Context; import android.content.Intent; +import android.os.Build; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.AudioplayerActivity; import de.danoeh.antennapod.activity.CastplayerActivity; @@ -18,7 +19,11 @@ public class PlaybackServiceCallbacksImpl implements PlaybackServiceCallbacks { return new Intent(context, CastplayerActivity.class); } if (mediaType == MediaType.VIDEO) { - return new Intent(context, VideoplayerActivity.class); + Intent i = new Intent(context, VideoplayerActivity.class); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + i.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + } + return i; } else { return new Intent(context, AudioplayerActivity.class); } diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java index 2c7d738dd..0e9cf73e0 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java @@ -38,8 +38,10 @@ import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; +import com.afollestad.materialdialogs.prefs.MaterialListPreference; import de.danoeh.antennapod.activity.ImportExportActivity; import de.danoeh.antennapod.activity.OpmlImportFromPathActivity; +import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; import org.apache.commons.lang3.ArrayUtils; import java.io.File; @@ -426,6 +428,11 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc return false; } ); + if (!PictureInPictureUtil.supportsPictureInPicture(activity)) { + MaterialListPreference behaviour = (MaterialListPreference) ui.findPreference(UserPreferences.PREF_VIDEO_BEHAVIOR); + behaviour.setEntries(R.array.video_background_behavior_options_without_pip); + behaviour.setEntryValues(R.array.video_background_behavior_values_without_pip); + } ui.findPreference(PREF_PROXY).setOnPreferenceClickListener(preference -> { ProxyDialog dialog = new ProxyDialog(ui.getActivity()); dialog.createDialog().show(); diff --git a/app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java b/app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java index f930c912a..e79389fb3 100644 --- a/app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java +++ b/app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java @@ -25,6 +25,8 @@ public class AspectRatioVideoView extends VideoView { private int mVideoWidth; private int mVideoHeight; + private float mAvailableWidth = -1; + private float mAvailableHeight = -1; public AspectRatioVideoView(Context context) { this(context, null); @@ -48,8 +50,13 @@ public class AspectRatioVideoView extends VideoView { return; } - float heightRatio = (float) mVideoHeight / (float) getHeight(); - float widthRatio = (float) mVideoWidth / (float) getWidth(); + if (mAvailableWidth < 0 || mAvailableHeight < 0) { + mAvailableWidth = getWidth(); + mAvailableHeight = getHeight(); + } + + float heightRatio = (float) mVideoHeight / mAvailableHeight; + float widthRatio = (float) mVideoWidth / mAvailableWidth; int scaledHeight; int scaledWidth; @@ -94,4 +101,15 @@ public class AspectRatioVideoView extends VideoView { invalidate(); } + /** + * Sets the maximum size that the view might expand to + * @param width + * @param height + */ + public void setAvailableSize(float width, float height) { + mAvailableWidth = width; + mAvailableHeight = height; + requestLayout(); + } + } diff --git a/app/src/main/res/layout/videoplayer_activity.xml b/app/src/main/res/layout/videoplayer_activity.xml index 4db663e19..10fbf8f49 100644 --- a/app/src/main/res/layout/videoplayer_activity.xml +++ b/app/src/main/res/layout/videoplayer_activity.xml @@ -3,7 +3,8 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/black" - android:orientation="vertical"> + android:orientation="vertical" + android:id="@+id/videoframe"> <de.danoeh.antennapod.view.AspectRatioVideoView android:id="@+id/videoview" @@ -103,6 +104,7 @@ android:layout_height="wrap_content" android:layout_toLeftOf="@+id/txtvLength" android:layout_toRightOf="@+id/txtvPosition" + android:layout_centerInParent="true" android:max="500" /> </RelativeLayout> diff --git a/app/src/main/res/menu/mediaplayer.xml b/app/src/main/res/menu/mediaplayer.xml index 530eb3400..98c7478a6 100644 --- a/app/src/main/res/menu/mediaplayer.xml +++ b/app/src/main/res/menu/mediaplayer.xml @@ -41,6 +41,14 @@ android:title="@string/visit_website_label" android:visible="false"> </item> + + <item + android:id="@+id/player_go_to_picture_in_picture" + custom:showAsAction="collapseActionView" + android:title="@string/player_go_to_picture_in_picture" + android:visible="false"> + </item> + <item android:id="@+id/share_item" android:icon="?attr/social_share" diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index ba389fc3c..622fef05b 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -171,6 +171,14 @@ android:key="prefResumeAfterCall" android:summary="@string/pref_resumeAfterCall_sum" android:title="@string/pref_resumeAfterCall_title"/> + <com.afollestad.materialdialogs.prefs.MaterialListPreference + android:defaultValue="stop" + android:entries="@array/video_background_behavior_options" + android:entryValues="@array/video_background_behavior_values" + android:key="prefVideoBehavior" + android:summary="@string/pref_videoBehavior_sum" + android:title="@string/pref_videoBehavior_title" + app:useStockLayout="true"/> </PreferenceCategory> <PreferenceCategory android:title="@string/network_pref"> diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 743ee135d..bad48e4cc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -74,6 +74,7 @@ public class UserPreferences { private static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray"; private static final String PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS = "prefPauseForFocusLoss"; private static final String PREF_RESUME_AFTER_CALL = "prefResumeAfterCall"; + public static final String PREF_VIDEO_BEHAVIOR = "prefVideoBehavior"; // Network private static final String PREF_ENQUEUE_DOWNLOADED = "prefEnqueueDownloaded"; @@ -661,6 +662,14 @@ public class UserPreferences { .apply(); } + public static VideoBackgroundBehavior getVideoBackgroundBehavior() { + switch (prefs.getString(PREF_VIDEO_BEHAVIOR, "stop")) { + case "stop": return VideoBackgroundBehavior.STOP; + case "pip": return VideoBackgroundBehavior.PICTURE_IN_PICTURE; + case "continue": return VideoBackgroundBehavior.CONTINUE_PLAYING; + default: return VideoBackgroundBehavior.STOP; + } + } public static EpisodeCleanupAlgorithm getEpisodeCleanupAlgorithm() { int cleanupValue = Integer.parseInt(prefs.getString(PREF_EPISODE_CLEANUP, "-1")); @@ -839,4 +848,8 @@ public class UserPreferences { public static boolean isCastEnabled() { return prefs.getBoolean(PREF_CAST_ENABLED, false); } + + public enum VideoBackgroundBehavior { + STOP, PICTURE_IN_PICTURE, CONTINUE_PLAYING + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/gui/PictureInPictureUtil.java b/core/src/main/java/de/danoeh/antennapod/core/util/gui/PictureInPictureUtil.java new file mode 100644 index 000000000..f763653a1 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/gui/PictureInPictureUtil.java @@ -0,0 +1,27 @@ +package de.danoeh.antennapod.core.util.gui; + +import android.app.Activity; +import android.content.pm.PackageManager; +import android.os.Build; + +public class PictureInPictureUtil { + private PictureInPictureUtil() { + } + + public static boolean supportsPictureInPicture(Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + PackageManager packageManager = activity.getPackageManager(); + return packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE); + } else { + return false; + } + } + + public static boolean isInPictureInPictureMode(Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && supportsPictureInPicture(activity)) { + return activity.isInPictureInPictureMode(); + } else { + return false; + } + } +} diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 45650495c..9d9a2453d 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -224,4 +224,26 @@ <item>@string/fast_forward_label</item> <item>@string/skip_episode_label</item> </string-array> + + <string-array name="video_background_behavior_options"> + <item>@string/stop_playback</item> + <item>@string/player_go_to_picture_in_picture</item> + <item>@string/continue_playback</item> + </string-array> + + <string-array name="video_background_behavior_values"> + <item>stop</item> + <item>pip</item> + <item>continue</item> + </string-array> + + <string-array name="video_background_behavior_options_without_pip"> + <item>@string/stop_playback</item> + <item>@string/continue_playback</item> + </string-array> + + <string-array name="video_background_behavior_values_without_pip"> + <item>stop</item> + <item>continue</item> + </string-array> </resources> diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index ab8a53cde..64568bbac 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -237,6 +237,7 @@ <string name="no_media_playing_label">No media playing</string> <string name="position_default_label" translate="false">00:00:00</string> <string name="player_buffering_msg">Buffering</string> + <string name="player_go_to_picture_in_picture">Picture-in-picture mode</string> <string name="playbackservice_notification_title">Playing podcast</string> <string name="unknown_media_key">AntennaPod - Unknown media key: %1$d</string> @@ -440,6 +441,10 @@ <string name="pref_cast_message_free_flavor">Chromecast requires third party proprietary libraries that are disabled in this version of AntennaPod</string> <string name="pref_enqueue_downloaded_title">Enqueue Downloaded</string> <string name="pref_enqueue_downloaded_summary">Add downloaded episodes to the queue</string> + <string name="pref_videoBehavior_title">Video behavior</string> + <string name="pref_videoBehavior_sum">Behavior when leaving video playback</string> + <string name="stop_playback">Stop playback</string> + <string name="continue_playback">Continue playback</string> <!-- Auto-Flattr dialog --> <string name="auto_flattr_enable">Enable automatic flattring</string> |