From 1e93d06a25b8ffbe95e3ffca23fbc55a93448cc3 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Mon, 8 Feb 2016 18:46:42 +0100 Subject: [PATCH] restructured ActionbarHandler --- .../org/schabi/newpipe/ActionBarHandler.java | 358 +++++------------- .../newpipe/VideoItemDetailFragment.java | 316 +++++++++++++--- .../org/schabi/newpipe/crawler/VideoInfo.java | 32 +- 3 files changed, 369 insertions(+), 337 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java b/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java index b3451cbaf..3dee3dfe6 100644 --- a/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java +++ b/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java @@ -45,28 +45,23 @@ import java.util.List; class ActionBarHandler { private static final String TAG = ActionBarHandler.class.toString(); - private static final String KORE_PACKET = "org.xbmc.kore"; - private int serviceId; - private String websiteUrl = ""; - private Bitmap videoThumbnail = null; - private String channelName = ""; private AppCompatActivity activity; - private List videoStreams = null; - private VideoInfo.AudioStream audioStream = null; - private int selectedStream = -1; - private String videoTitle = ""; + private int selectedVideoStream = -1; private SharedPreferences defaultPreferences = null; - private int startPosition; - @SuppressWarnings("deprecation") - private class FormatItemSelectListener implements ActionBar.OnNavigationListener { - @Override - public boolean onNavigationItemSelected(int itemPosition, long itemId) { - selectFormatItem((int)itemId); - return true; - } + // Only callbacks are listed here, there are more actions which don't need a callback. + // those are edited directly. Typically VideoItemDetailFragment will implement those callbacks. + private OnActionListener onShareListener; + private OnActionListener onOpenInBrowserListener; + private OnActionListener onDownloadListener; + private OnActionListener onPlayWithKodiListener; + private OnActionListener onPlayAudioListener; + + // Triggered when a stream related action is triggered. + public interface OnActionListener { + void onActionSelected(int selectedStreamId); } public ActionBarHandler(AppCompatActivity activity) { @@ -78,79 +73,58 @@ class ActionBarHandler { this.activity = activity; try { activity.getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); - } catch(NullPointerException e) { + } catch (NullPointerException e) { e.printStackTrace(); } } - public void setServiceId(int id) { - serviceId = id; + public void setupStreamList(final List videoStreams) { + if (activity != null) { + selectedVideoStream = 0; + + + // this array will be shown in the dropdown menu for selecting the stream/resolution. + String[] itemArray = new String[videoStreams.size()]; + for (int i = 0; i < videoStreams.size(); i++) { + VideoInfo.VideoStream item = videoStreams.get(i); + itemArray[i] = MediaFormat.getNameById(item.format) + " " + item.resolution; + } + int defaultResolution = getDefaultResolution(videoStreams); + + ArrayAdapter itemAdapter = new ArrayAdapter<>(activity.getBaseContext(), + android.R.layout.simple_spinner_dropdown_item, itemArray); + + ActionBar ab = activity.getSupportActionBar(); + //todo: make this throwsable + assert ab != null : "Could not get actionbar"; + ab.setListNavigationCallbacks(itemAdapter + , new ActionBar.OnNavigationListener() { + @Override + public boolean onNavigationItemSelected(int itemPosition, long itemId) { + selectedVideoStream = (int) itemId; + return true; + } + }); + + ab.setSelectedNavigationItem(defaultResolution); + } } - public void setVideoThumbnail(Bitmap bitmap) { - videoThumbnail = bitmap; - } - public void setChannelName(String name) { - channelName = name; - } - - @SuppressWarnings("deprecation") - public void setStreams(List videoStreams, - List audioStreams) { - this.videoStreams = videoStreams; - selectedStream = 0; - defaultPreferences = PreferenceManager.getDefaultSharedPreferences(activity); - String[] itemArray = new String[videoStreams.size()]; + private int getDefaultResolution(final List videoStreams) { String defaultResolution = defaultPreferences .getString(activity.getString(R.string.default_resolution_key), activity.getString(R.string.default_resolution_value)); - int defaultResolutionPos = 0; - for(int i = 0; i < videoStreams.size(); i++) { + for (int i = 0; i < videoStreams.size(); i++) { VideoInfo.VideoStream item = videoStreams.get(i); - itemArray[i] = MediaFormat.getNameById(item.format) + " " + item.resolution; - if(defaultResolution.equals(item.resolution)) { - defaultResolutionPos = i; + if (defaultResolution.equals(item.resolution)) { + return i; } } - - ArrayAdapter itemAdapter = new ArrayAdapter<>(activity.getBaseContext(), - android.R.layout.simple_spinner_dropdown_item, itemArray); - if(activity != null) { - ActionBar ab = activity.getSupportActionBar(); - assert ab != null : "Could not get actionbar"; - ab.setListNavigationCallbacks(itemAdapter - , new FormatItemSelectListener()); - - ab.setSelectedNavigationItem(defaultResolutionPos); - } - - // set audioStream - audioStream = null; - String preferedFormat = defaultPreferences - .getString(activity.getString(R.string.default_audio_format_key), "webm"); - if(preferedFormat.equals("webm")) { - for(VideoInfo.AudioStream s : audioStreams) { - if(s.format == MediaFormat.WEBMA.id) { - audioStream = s; - } - } - } else if(preferedFormat.equals("m4a")){ - for(VideoInfo.AudioStream s : audioStreams) { - if(s.format == MediaFormat.M4A.id && - (audioStream == null || audioStream.bandwidth > s.bandwidth)) { - audioStream = s; - } - } - } - else { - Log.e(TAG, "FAILED to set audioStream value!"); - } - } - - private void selectFormatItem(int i) { - selectedStream = i; + // this is actually an error, + // but maybe there is really no stream fitting to the default value. + return 0; } public void setupMenu(Menu menu, MenuInflater inflater) { @@ -167,222 +141,64 @@ class ActionBarHandler { } public boolean onItemSelected(MenuItem item) { - if(!videoTitle.isEmpty()) { - int id = item.getItemId(); - switch (id) { - case R.id.menu_item_share: { + int id = item.getItemId(); + switch (id) { + case R.id.menu_item_share: { + /* Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_TEXT, websiteUrl); intent.setType("text/plain"); activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.share_dialog_title))); - return true; - } - case R.id.menu_item_openInBrowser: { - openInBrowser(); - } + */ + onShareListener.onActionSelected(selectedVideoStream); return true; - case R.id.menu_item_download: - downloadVideo(); - return true; - case R.id.action_settings: { - Intent intent = new Intent(activity, SettingsActivity.class); - activity.startActivity(intent); - } - break; - case R.id.action_play_with_kodi: - playWithKodi(); - return true; - case R.id.menu_item_play_audio: - playAudio(); - return true; - default: - Log.e(TAG, "Menu Item not known"); } - } else { - // That line may not be necessary. + case R.id.menu_item_openInBrowser: { + onOpenInBrowserListener.onActionSelected(selectedVideoStream); + } return true; + case R.id.menu_item_download: + onDownloadListener.onActionSelected(selectedVideoStream); + return true; + case R.id.action_settings: { + Intent intent = new Intent(activity, SettingsActivity.class); + activity.startActivity(intent); + return true; + } + case R.id.action_play_with_kodi: + onPlayWithKodiListener.onActionSelected(selectedVideoStream); + return true; + case R.id.menu_item_play_audio: + onPlayAudioListener.onActionSelected(selectedVideoStream); + return true; + default: + Log.e(TAG, "Menu Item not known"); } return false; } - public void setVideoInfo(String websiteUrl, String videoTitle) { - this.websiteUrl = websiteUrl; - this.videoTitle = videoTitle; + public int getSelectedVideoStream() { + return selectedVideoStream; } - public void playVideo() { - // ----------- THE MAGIC MOMENT --------------- - if(!videoTitle.isEmpty()) { - VideoInfo.VideoStream selectedStreamItem = videoStreams.get(selectedStream); - - if (PreferenceManager.getDefaultSharedPreferences(activity) - .getBoolean(activity.getString(R.string.use_external_video_player_key), false)) { - - // External Player - Intent intent = new Intent(); - try { - intent.setAction(Intent.ACTION_VIEW); - - intent.setDataAndType(Uri.parse(selectedStreamItem.url), - MediaFormat.getMimeById(selectedStreamItem.format)); - intent.putExtra(Intent.EXTRA_TITLE, videoTitle); - intent.putExtra("title", videoTitle); - - activity.startActivity(intent); // HERE !!! - } catch (Exception e) { - e.printStackTrace(); - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setMessage(R.string.no_player_found) - .setPositiveButton(R.string.install, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Intent intent = new Intent(); - intent.setAction(Intent.ACTION_VIEW); - intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url))); - activity.startActivity(intent); - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }); - builder.create().show(); - } - } else { - // Internal Player - Intent intent = new Intent(activity, PlayVideoActivity.class); - intent.putExtra(PlayVideoActivity.VIDEO_TITLE, videoTitle); - intent.putExtra(PlayVideoActivity.STREAM_URL, selectedStreamItem.url); - intent.putExtra(PlayVideoActivity.VIDEO_URL, websiteUrl); - intent.putExtra(PlayVideoActivity.START_POSITION, startPosition); - activity.startActivity(intent); //also HERE !!! - } - } - // -------------------------------------------- + public void setOnShareListener(OnActionListener listener) { + onShareListener = listener; } - public void setStartPosition(int startPositionSeconds) - { - this.startPosition = startPositionSeconds; + public void setOnOpenInBrowserListener(OnActionListener listener) { + onOpenInBrowserListener = listener; } - private void downloadVideo() { - if(!videoTitle.isEmpty()) { - VideoInfo.VideoStream selectedStreamItem = videoStreams.get(selectedStream); - String videoSuffix = "." + MediaFormat.getSuffixById(selectedStreamItem.format); - String audioSuffix = "." + MediaFormat.getSuffixById(audioStream.format); - Bundle args = new Bundle(); - args.putString(DownloadDialog.FILE_SUFFIX_VIDEO, videoSuffix); - args.putString(DownloadDialog.FILE_SUFFIX_AUDIO, audioSuffix); - args.putString(DownloadDialog.TITLE, videoTitle); - args.putString(DownloadDialog.VIDEO_URL, selectedStreamItem.url); - args.putString(DownloadDialog.AUDIO_URL, audioStream.url); - DownloadDialog downloadDialog = new DownloadDialog(); - downloadDialog.setArguments(args); - downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog"); - } + public void setOnDownloadListener(OnActionListener listener) { + onDownloadListener = listener; } - private void openInBrowser() { - if(!videoTitle.isEmpty()) { - Intent intent = new Intent(); - intent.setAction(Intent.ACTION_VIEW); - intent.setData(Uri.parse(websiteUrl)); - - activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.choose_browser))); - } + public void setOnPlayWithKodiListener(OnActionListener listener) { + onPlayWithKodiListener = listener; } - private void playWithKodi() { - if(!videoTitle.isEmpty()) { - try { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setPackage(KORE_PACKET); - intent.setData(Uri.parse(websiteUrl.replace("https", "http"))); - activity.startActivity(intent); - } catch (Exception e) { - e.printStackTrace(); - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setMessage(R.string.kore_not_found) - .setPositiveButton(R.string.install, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Intent intent = new Intent(); - intent.setAction(Intent.ACTION_VIEW); - intent.setData(Uri.parse(activity.getString(R.string.fdroid_kore_url))); - activity.startActivity(intent); - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }); - builder.create().show(); - } - } - } - - public void playAudio() { - boolean externalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity) - .getBoolean(activity.getString(R.string.use_external_audio_player_key), false); - Intent intent; - - if (!externalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 18) { - //internal music player: explicit intent - if (!BackgroundPlayer.isRunning && videoThumbnail != null) { - ActivityCommunicator.getCommunicator() - .backgroundPlayerThumbnail = videoThumbnail; - intent = new Intent(activity, BackgroundPlayer.class); - - intent.setAction(Intent.ACTION_VIEW); - Log.i(TAG, "audioStream is null:" + (audioStream == null)); - Log.i(TAG, "audioStream.url is null:" + (audioStream.url == null)); - intent.setDataAndType(Uri.parse(audioStream.url), - MediaFormat.getMimeById(audioStream.format)); - intent.putExtra(BackgroundPlayer.TITLE, videoTitle); - intent.putExtra(BackgroundPlayer.WEB_URL, websiteUrl); - intent.putExtra(BackgroundPlayer.SERVICE_ID, serviceId); - intent.putExtra(BackgroundPlayer.CHANNEL_NAME, channelName); - activity.startService(intent); - } - } else { - intent = new Intent(); - try { - intent.setAction(Intent.ACTION_VIEW); - intent.setDataAndType(Uri.parse(audioStream.url), - MediaFormat.getMimeById(audioStream.format)); - intent.putExtra(Intent.EXTRA_TITLE, videoTitle); - intent.putExtra("title", videoTitle); - - activity.startActivity(intent); // HERE !!! - } catch (Exception e) { - e.printStackTrace(); - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setMessage(R.string.no_player_found) - .setPositiveButton(R.string.install, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Intent intent = new Intent(); - intent.setAction(Intent.ACTION_VIEW); - intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url))); - activity.startActivity(intent); - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Log.i(TAG, "You unlocked a secret unicorn."); - } - }); - builder.create().show(); - Log.e(TAG, "Either no Streaming player for audio was installed, or something important crashed:"); - e.printStackTrace(); - } - } + public void setOnPlayAudioListener(OnActionListener listener) { + onPlayAudioListener = listener; } } diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java index ed87235c5..2793e0a98 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java @@ -1,6 +1,8 @@ package org.schabi.newpipe; import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.res.TypedArray; import android.graphics.Bitmap; @@ -13,6 +15,7 @@ import android.os.Handler; import android.preference.PreferenceManager; import android.support.design.widget.FloatingActionButton; import android.support.v4.app.Fragment; +import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.text.Html; import android.text.method.LinkMovementMethod; @@ -43,6 +46,7 @@ import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; import java.util.ArrayList; import java.util.Vector; +import org.schabi.newpipe.crawler.MediaFormat; import org.schabi.newpipe.crawler.ParsingException; import org.schabi.newpipe.crawler.ServiceList; import org.schabi.newpipe.crawler.VideoPreviewInfo; @@ -73,6 +77,7 @@ import org.schabi.newpipe.crawler.services.youtube.YoutubeVideoExtractor; public class VideoItemDetailFragment extends Fragment { private static final String TAG = VideoItemDetailFragment.class.toString(); + private static final String KORE_PACKET = "org.xbmc.kore"; /** * The fragment argument representing the item ID that this fragment @@ -89,8 +94,8 @@ public class VideoItemDetailFragment extends Fragment { private int streamingServiceId = -1; private boolean autoPlayEnabled = false; - private VideoInfo currentVideoInfo = null; private boolean showNextVideoItem = false; + private Bitmap videoThumbnail; private View thumbnailWindowLayout; private FloatingActionButton playVideoButton; @@ -192,10 +197,9 @@ public class VideoItemDetailFragment extends Fragment { public void onLoadingCancelled(String imageUri, View view) {} } - private void updateInfo(VideoInfo info) { - currentVideoInfo = info; - + private void updateInfo(final VideoInfo info) { try { + Context c = getContext(); VideoInfoItemViewCreator videoItemViewCreator = new VideoInfoItemViewCreator(LayoutInflater.from(getActivity())); @@ -216,9 +220,11 @@ public class VideoItemDetailFragment extends Fragment { (RelativeLayout) activity.findViewById(R.id.detailNextVideoRootLayout); Button nextVideoButton = (Button) activity.findViewById(R.id.detailNextVideoButton); TextView similarTitle = (TextView) activity.findViewById(R.id.detailSimilarTitle); + Button backgroundButton = (Button) + activity.findViewById(R.id.detailVideoThumbnailWindowBackgroundButton); View topView = activity.findViewById(R.id.detailTopView); View nextVideoView = videoItemViewCreator - .getViewFromVideoInfoItem(null, nextVideoFrame, info.nextVideo, getContext()); + .getViewFromVideoInfoItem(null, nextVideoFrame, info.next_video, getContext()); progressBar.setVisibility(View.GONE); nextVideoFrame.addView(nextVideoView); @@ -253,42 +259,24 @@ public class VideoItemDetailFragment extends Fragment { }); uploaderView.setText(info.uploader); - actionBarHandler.setChannelName(info.uploader); - videoTitleView.setText(info.title); uploaderView.setText(info.uploader); - actionBarHandler.setChannelName(info.uploader); - - String localizedViewCount = Localization.localizeViewCount(info.view_count, getContext()); - viewCountView.setText(localizedViewCount); - - String localizedLikeCount = Localization.localizeNumber(info.like_count, getContext()); - thumbsUpView.setText(localizedLikeCount); - - String localizedDislikeCount = Localization.localizeNumber(info.dislike_count, getContext()); - thumbsDownView.setText(localizedDislikeCount); - - String localizedDate = Localization.localizeDate(info.upload_date, getContext()); - uploadDateView.setText(localizedDate); - + viewCountView.setText(Localization.localizeViewCount(info.view_count, c)); + thumbsUpView.setText(Localization.localizeNumber(info.like_count, c)); + thumbsDownView.setText(Localization.localizeNumber(info.dislike_count, c)); + uploadDateView.setText(Localization.localizeDate(info.upload_date, c)); descriptionView.setText(Html.fromHtml(info.description)); descriptionView.setMovementMethod(LinkMovementMethod.getInstance()); - actionBarHandler.setServiceId(streamingServiceId); - actionBarHandler.setVideoInfo(info.webpage_url, info.title); - actionBarHandler.setStartPosition(info.startPosition); - // parse streams Vector streamsToUse = new Vector<>(); - for (VideoInfo.VideoStream i : info.videoStreams) { + for (VideoInfo.VideoStream i : info.video_streams) { if (useStream(i, streamsToUse)) { streamsToUse.add(i); } } - actionBarHandler.setStreams(streamsToUse, info.audioStreams); - nextVideoButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -297,18 +285,34 @@ public class VideoItemDetailFragment extends Fragment { /*detailIntent.putExtra( VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); */ detailIntent.putExtra( - VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url); + VideoItemDetailFragment.VIDEO_URL, info.next_video.webpage_url); detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId); startActivity(detailIntent); } }); textContentLayout.setVisibility(View.VISIBLE); - initSimilarVideos(videoItemViewCreator); + initSimilarVideos(info, videoItemViewCreator); if(autoPlayEnabled) { - actionBarHandler.playVideo(); + playVideo(info); } + + playVideoButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + playVideo(info); + } + }); + + backgroundButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + playVideo(info); + } + }); + + setupActionBarHandler(info); } catch (java.lang.NullPointerException e) { Log.w(TAG, "updateInfo(): Fragment closed before thread ended work... or else"); e.printStackTrace(); @@ -325,7 +329,8 @@ public class VideoItemDetailFragment extends Fragment { imageLoader.displayImage(info.thumbnail_url, videoThumbnailView, displayImageOptions, new ImageLoadingListener() { @Override - public void onLoadingStarted(String imageUri, View view) {} + public void onLoadingStarted(String imageUri, View view) { + } @Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) { @@ -336,21 +341,191 @@ public class VideoItemDetailFragment extends Fragment { @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { - actionBarHandler.setVideoThumbnail(loadedImage); + videoThumbnail = loadedImage; } @Override - public void onLoadingCancelled(String imageUri, View view) {} + public void onLoadingCancelled(String imageUri, View view) { + } }); imageLoader.displayImage(info.uploader_thumbnail_url, uploaderThumb, displayImageOptions, new ThumbnailLoadingListener()); - imageLoader.displayImage(info.nextVideo.thumbnail_url, + imageLoader.displayImage(info.next_video.thumbnail_url, nextVideoThumb, displayImageOptions, new ThumbnailLoadingListener()); } - private void initSimilarVideos(VideoInfoItemViewCreator videoItemViewCreator) { + private void setupActionBarHandler(final VideoInfo info) { + actionBarHandler.setupStreamList(info.video_streams); + + actionBarHandler.setOnShareListener(new ActionBarHandler.OnActionListener() { + @Override + public void onActionSelected(int selectedStreamId) { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_SEND); + intent.putExtra(Intent.EXTRA_TEXT, info.webpage_url); + intent.setType("text/plain"); + activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.share_dialog_title))); + } + }); + + actionBarHandler.setOnOpenInBrowserListener(new ActionBarHandler.OnActionListener() { + @Override + public void onActionSelected(int selectedStreamId) { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + intent.setData(Uri.parse(info.webpage_url)); + + activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.choose_browser))); + } + }); + + actionBarHandler.setOnPlayWithKodiListener(new ActionBarHandler.OnActionListener() { + @Override + public void onActionSelected(int selectedStreamId) { + try { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setPackage(KORE_PACKET); + intent.setData(Uri.parse(info.webpage_url.replace("https", "http"))); + activity.startActivity(intent); + } catch (Exception e) { + e.printStackTrace(); + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setMessage(R.string.kore_not_found) + .setPositiveButton(R.string.install, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + intent.setData(Uri.parse(activity.getString(R.string.fdroid_kore_url))); + activity.startActivity(intent); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }); + builder.create().show(); + } + } + }); + + actionBarHandler.setOnDownloadListener(new ActionBarHandler.OnActionListener() { + @Override + public void onActionSelected(int selectedStreamId) { + //VideoInfo.VideoStream selectedStreamItem = videoStreams.get(selectedStream); + VideoInfo.AudioStream audioStream = + info.audio_streams.get(getPreferredAudioStreamId(info)); + VideoInfo.VideoStream selectedStreamItem = info.video_streams.get(selectedStreamId); + String videoSuffix = "." + MediaFormat.getSuffixById(selectedStreamItem.format); + String audioSuffix = "." + MediaFormat.getSuffixById(audioStream.format); + Bundle args = new Bundle(); + args.putString(DownloadDialog.FILE_SUFFIX_VIDEO, videoSuffix); + args.putString(DownloadDialog.FILE_SUFFIX_AUDIO, audioSuffix); + args.putString(DownloadDialog.TITLE, info.title); + args.putString(DownloadDialog.VIDEO_URL, selectedStreamItem.url); + args.putString(DownloadDialog.AUDIO_URL, audioStream.url); + DownloadDialog downloadDialog = new DownloadDialog(); + downloadDialog.setArguments(args); + downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog"); + } + }); + + actionBarHandler.setOnPlayAudioListener(new ActionBarHandler.OnActionListener() { + @Override + public void onActionSelected(int selectedStreamId) { + boolean useExternalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity) + .getBoolean(activity.getString(R.string.use_external_audio_player_key), false); + Intent intent; + VideoInfo.AudioStream audioStream = + info.audio_streams.get(getPreferredAudioStreamId(info)); + if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 18) { + //internal music player: explicit intent + if (!BackgroundPlayer.isRunning && videoThumbnail != null) { + ActivityCommunicator.getCommunicator() + .backgroundPlayerThumbnail = videoThumbnail; + intent = new Intent(activity, BackgroundPlayer.class); + + intent.setAction(Intent.ACTION_VIEW); + Log.i(TAG, "audioStream is null:" + (audioStream == null)); + Log.i(TAG, "audioStream.url is null:" + (audioStream.url == null)); + intent.setDataAndType(Uri.parse(audioStream.url), + MediaFormat.getMimeById(audioStream.format)); + intent.putExtra(BackgroundPlayer.TITLE, info.title); + intent.putExtra(BackgroundPlayer.WEB_URL, info.webpage_url); + intent.putExtra(BackgroundPlayer.SERVICE_ID, streamingServiceId); + intent.putExtra(BackgroundPlayer.CHANNEL_NAME, info.uploader); + activity.startService(intent); + } + } else { + intent = new Intent(); + try { + intent.setAction(Intent.ACTION_VIEW); + intent.setDataAndType(Uri.parse(audioStream.url), + MediaFormat.getMimeById(audioStream.format)); + intent.putExtra(Intent.EXTRA_TITLE, info.title); + intent.putExtra("title", info.title); + // HERE !!! + activity.startActivity(intent); + } catch (Exception e) { + e.printStackTrace(); + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setMessage(R.string.no_player_found) + .setPositiveButton(R.string.install, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url))); + activity.startActivity(intent); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Log.i(TAG, "You unlocked a secret unicorn."); + } + }); + builder.create().show(); + Log.e(TAG, "Either no Streaming player for audio was installed, or something important crashed:"); + e.printStackTrace(); + } + } + } + }); + } + + private int getPreferredAudioStreamId(final VideoInfo info) { + String preferredFormatString = PreferenceManager.getDefaultSharedPreferences(getActivity()) + .getString(activity.getString(R.string.default_audio_format_key), "webm"); + + int preferredFormat = MediaFormat.WEBMA.id; + switch(preferredFormatString) { + case "webm": + preferredFormat = MediaFormat.WEBMA.id; + break; + case "m4a": + preferredFormat = MediaFormat.M4A.id; + break; + default: + break; + } + + for(int i = 0; i < info.audio_streams.size(); i++) { + if(info.audio_streams.get(i).format == preferredFormat) { + return i; + } + } + + //todo: make this a proper error + Log.e(TAG, "FAILED to set audioStream value!"); + return 0; + } + + private void initSimilarVideos(final VideoInfo info, VideoInfoItemViewCreator videoItemViewCreator) { LinearLayout similarLayout = (LinearLayout) activity.findViewById(R.id.similarVideosView); - ArrayList similar = new ArrayList<>(currentVideoInfo.relatedVideos); + ArrayList similar = new ArrayList<>(info.related_videos); for (final VideoPreviewInfo item : similar) { View similarView = videoItemViewCreator .getViewFromVideoInfoItem(null, similarLayout, item, getContext()); @@ -479,20 +654,6 @@ public class VideoItemDetailFragment extends Fragment { e.printStackTrace(); } - playVideoButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - actionBarHandler.playVideo(); - } - }); - - backgroundButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - actionBarHandler.playVideo(); - } - }); - // todo: Fix this workaround (probably with a better design), so that older android // versions don't have problems rendering the thumbnail right. if(Build.VERSION.SDK_INT >= 18) { @@ -517,6 +678,59 @@ public class VideoItemDetailFragment extends Fragment { } } + public void playVideo(final VideoInfo info) { + // ----------- THE MAGIC MOMENT --------------- + VideoInfo.VideoStream selectedVideoStream = + info.video_streams.get(actionBarHandler.getSelectedVideoStream()); + + if (PreferenceManager.getDefaultSharedPreferences(activity) + .getBoolean(activity.getString(R.string.use_external_video_player_key), false)) { + + // External Player + Intent intent = new Intent(); + try { + intent.setAction(Intent.ACTION_VIEW); + + intent.setDataAndType(Uri.parse(selectedVideoStream.url), + MediaFormat.getMimeById(selectedVideoStream.format)); + intent.putExtra(Intent.EXTRA_TITLE, info.title); + intent.putExtra("title", info.title); + + activity.startActivity(intent); // HERE !!! + } catch (Exception e) { + e.printStackTrace(); + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setMessage(R.string.no_player_found) + .setPositiveButton(R.string.install, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url))); + activity.startActivity(intent); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }); + builder.create().show(); + } + } else { + // Internal Player + Intent intent = new Intent(activity, PlayVideoActivity.class); + intent.putExtra(PlayVideoActivity.VIDEO_TITLE, info.title); + intent.putExtra(PlayVideoActivity.STREAM_URL, selectedVideoStream.url); + intent.putExtra(PlayVideoActivity.VIDEO_URL, info.webpage_url); + intent.putExtra(PlayVideoActivity.START_POSITION, info.start_position); + activity.startActivity(intent); //also HERE !!! + } + + // -------------------------------------------- + } + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { actionBarHandler.setupMenu(menu, inflater); diff --git a/app/src/main/java/org/schabi/newpipe/crawler/VideoInfo.java b/app/src/main/java/org/schabi/newpipe/crawler/VideoInfo.java index 2542c501d..ecc691efc 100644 --- a/app/src/main/java/org/schabi/newpipe/crawler/VideoInfo.java +++ b/app/src/main/java/org/schabi/newpipe/crawler/VideoInfo.java @@ -36,6 +36,7 @@ public class VideoInfo extends AbstractVideoInfo { VideoUrlIdHandler uiconv = extractor.getUrlIdConverter(); + videoInfo.webpage_url = extractor.getPageUrl(); videoInfo.title = extractor.getTitle(); videoInfo.duration = extractor.getLength(); @@ -47,23 +48,23 @@ public class VideoInfo extends AbstractVideoInfo { videoInfo.id = uiconv.getVideoId(extractor.getPageUrl()); videoInfo.dashMpdUrl = extractor.getDashMpdUrl(); /** Load and extract audio*/ - videoInfo.audioStreams = extractor.getAudioStreams(); + videoInfo.audio_streams = extractor.getAudioStreams(); if(videoInfo.dashMpdUrl != null && !videoInfo.dashMpdUrl.isEmpty()) { - if(videoInfo.audioStreams == null) { - videoInfo.audioStreams = new Vector(); + if(videoInfo.audio_streams == null) { + videoInfo.audio_streams = new Vector(); } - videoInfo.audioStreams.addAll( + videoInfo.audio_streams.addAll( DashMpdParser.getAudioStreams(videoInfo.dashMpdUrl, downloader)); } /** Extract video stream url*/ - videoInfo.videoStreams = extractor.getVideoStreams(); + videoInfo.video_streams = extractor.getVideoStreams(); videoInfo.uploader_thumbnail_url = extractor.getUploaderThumbnailUrl(); - videoInfo.startPosition = extractor.getTimeStamp(); + videoInfo.start_position = extractor.getTimeStamp(); videoInfo.average_rating = extractor.getAverageRating(); videoInfo.like_count = extractor.getLikeCount(); videoInfo.dislike_count = extractor.getDislikeCount(); - videoInfo.nextVideo = extractor.getNextVideo(); - videoInfo.relatedVideos = extractor.getRelatedVideos(); + videoInfo.next_video = extractor.getNextVideo(); + videoInfo.related_videos = extractor.getRelatedVideos(); //Bitmap thumbnail = null; //Bitmap uploader_thumbnail = null; @@ -75,8 +76,8 @@ public class VideoInfo extends AbstractVideoInfo { public String uploader_thumbnail_url = ""; public String description = ""; /*todo: make this lists over vectors*/ - public List videoStreams = null; - public List audioStreams = null; + public List video_streams = null; + public List audio_streams = null; // video streams provided by the dash mpd do not need to be provided as VideoStream. // Later on this will also aplly to audio streams. Since dash mpd is standarized, // crawling such a file is not service dependent. Therefore getting audio only streams by yust @@ -90,10 +91,11 @@ public class VideoInfo extends AbstractVideoInfo { public int like_count = -1; public int dislike_count = -1; public String average_rating = ""; - public VideoPreviewInfo nextVideo = null; - public List relatedVideos = null; + public VideoPreviewInfo next_video = null; + public List related_videos = null; //in seconds. some metadata is not passed using a VideoInfo object! - public int startPosition = -1; + public int start_position = -1; + //todo: public int service_id = -1; public VideoInfo() {} @@ -137,11 +139,11 @@ public class VideoInfo extends AbstractVideoInfo { public String url = ""; public int format = -1; public int bandwidth = -1; - public int samplingRate = -1; + public int sampling_rate = -1; public AudioStream(String url, int format, int bandwidth, int samplingRate) { this.url = url; this.format = format; - this.bandwidth = bandwidth; this.samplingRate = samplingRate; + this.bandwidth = bandwidth; this.sampling_rate = samplingRate; } } } \ No newline at end of file