1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2024-07-02 01:53:19 +00:00

restructured ActionbarHandler

This commit is contained in:
Christian Schabesberger 2016-02-08 18:46:42 +01:00
parent 80ddc76926
commit 1e93d06a25
3 changed files with 369 additions and 337 deletions

View File

@ -45,28 +45,23 @@ import java.util.List;
class ActionBarHandler { class ActionBarHandler {
private static final String TAG = ActionBarHandler.class.toString(); 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 AppCompatActivity activity;
private List<VideoInfo.VideoStream> videoStreams = null; private int selectedVideoStream = -1;
private VideoInfo.AudioStream audioStream = null;
private int selectedStream = -1;
private String videoTitle = "";
private SharedPreferences defaultPreferences = null; private SharedPreferences defaultPreferences = null;
private int startPosition;
@SuppressWarnings("deprecation") // Only callbacks are listed here, there are more actions which don't need a callback.
private class FormatItemSelectListener implements ActionBar.OnNavigationListener { // those are edited directly. Typically VideoItemDetailFragment will implement those callbacks.
@Override private OnActionListener onShareListener;
public boolean onNavigationItemSelected(int itemPosition, long itemId) { private OnActionListener onOpenInBrowserListener;
selectFormatItem((int)itemId); private OnActionListener onDownloadListener;
return true; 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) { public ActionBarHandler(AppCompatActivity activity) {
@ -83,74 +78,53 @@ class ActionBarHandler {
} }
} }
public void setServiceId(int id) { public void setupStreamList(final List<VideoInfo.VideoStream> videoStreams) {
serviceId = id; if (activity != null) {
} selectedVideoStream = 0;
public void setVideoThumbnail(Bitmap bitmap) {
videoThumbnail = bitmap;
}
public void setChannelName(String name) { // this array will be shown in the dropdown menu for selecting the stream/resolution.
channelName = name;
}
@SuppressWarnings("deprecation")
public void setStreams(List<VideoInfo.VideoStream> videoStreams,
List<VideoInfo.AudioStream> audioStreams) {
this.videoStreams = videoStreams;
selectedStream = 0;
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(activity);
String[] itemArray = new String[videoStreams.size()]; String[] itemArray = new String[videoStreams.size()];
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); VideoInfo.VideoStream item = videoStreams.get(i);
itemArray[i] = MediaFormat.getNameById(item.format) + " " + item.resolution; itemArray[i] = MediaFormat.getNameById(item.format) + " " + item.resolution;
if(defaultResolution.equals(item.resolution)) {
defaultResolutionPos = i;
}
} }
int defaultResolution = getDefaultResolution(videoStreams);
ArrayAdapter<String> itemAdapter = new ArrayAdapter<>(activity.getBaseContext(), ArrayAdapter<String> itemAdapter = new ArrayAdapter<>(activity.getBaseContext(),
android.R.layout.simple_spinner_dropdown_item, itemArray); android.R.layout.simple_spinner_dropdown_item, itemArray);
if(activity != null) {
ActionBar ab = activity.getSupportActionBar(); ActionBar ab = activity.getSupportActionBar();
//todo: make this throwsable
assert ab != null : "Could not get actionbar"; assert ab != null : "Could not get actionbar";
ab.setListNavigationCallbacks(itemAdapter ab.setListNavigationCallbacks(itemAdapter
, new FormatItemSelectListener()); , new ActionBar.OnNavigationListener() {
@Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
selectedVideoStream = (int) itemId;
return true;
}
});
ab.setSelectedNavigationItem(defaultResolutionPos); ab.setSelectedNavigationItem(defaultResolution);
}
// 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; private int getDefaultResolution(final List<VideoInfo.VideoStream> videoStreams) {
String defaultResolution = defaultPreferences
.getString(activity.getString(R.string.default_resolution_key),
activity.getString(R.string.default_resolution_value));
for (int i = 0; i < videoStreams.size(); i++) {
VideoInfo.VideoStream item = videoStreams.get(i);
if (defaultResolution.equals(item.resolution)) {
return 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) { public void setupMenu(Menu menu, MenuInflater inflater) {
@ -167,222 +141,64 @@ class ActionBarHandler {
} }
public boolean onItemSelected(MenuItem item) { public boolean onItemSelected(MenuItem item) {
if(!videoTitle.isEmpty()) {
int id = item.getItemId(); int id = item.getItemId();
switch (id) { switch (id) {
case R.id.menu_item_share: { case R.id.menu_item_share: {
/*
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND); intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, websiteUrl); intent.putExtra(Intent.EXTRA_TEXT, websiteUrl);
intent.setType("text/plain"); intent.setType("text/plain");
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.share_dialog_title))); activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.share_dialog_title)));
*/
onShareListener.onActionSelected(selectedVideoStream);
return true; return true;
} }
case R.id.menu_item_openInBrowser: { case R.id.menu_item_openInBrowser: {
openInBrowser(); onOpenInBrowserListener.onActionSelected(selectedVideoStream);
} }
return true; return true;
case R.id.menu_item_download: case R.id.menu_item_download:
downloadVideo(); onDownloadListener.onActionSelected(selectedVideoStream);
return true; return true;
case R.id.action_settings: { case R.id.action_settings: {
Intent intent = new Intent(activity, SettingsActivity.class); Intent intent = new Intent(activity, SettingsActivity.class);
activity.startActivity(intent); activity.startActivity(intent);
return true;
} }
break;
case R.id.action_play_with_kodi: case R.id.action_play_with_kodi:
playWithKodi(); onPlayWithKodiListener.onActionSelected(selectedVideoStream);
return true; return true;
case R.id.menu_item_play_audio: case R.id.menu_item_play_audio:
playAudio(); onPlayAudioListener.onActionSelected(selectedVideoStream);
return true; return true;
default: default:
Log.e(TAG, "Menu Item not known"); Log.e(TAG, "Menu Item not known");
} }
} else {
// That line may not be necessary.
return true;
}
return false; return false;
} }
public void setVideoInfo(String websiteUrl, String videoTitle) { public int getSelectedVideoStream() {
this.websiteUrl = websiteUrl; return selectedVideoStream;
this.videoTitle = videoTitle;
} }
public void playVideo() { public void setOnShareListener(OnActionListener listener) {
// ----------- THE MAGIC MOMENT --------------- onShareListener = listener;
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 setStartPosition(int startPositionSeconds) public void setOnOpenInBrowserListener(OnActionListener listener) {
{ onOpenInBrowserListener = listener;
this.startPosition = startPositionSeconds;
} }
private void downloadVideo() { public void setOnDownloadListener(OnActionListener listener) {
if(!videoTitle.isEmpty()) { onDownloadListener = listener;
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");
}
} }
private void openInBrowser() { public void setOnPlayWithKodiListener(OnActionListener listener) {
if(!videoTitle.isEmpty()) { onPlayWithKodiListener = listener;
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)));
}
} }
private void playWithKodi() { public void setOnPlayAudioListener(OnActionListener listener) {
if(!videoTitle.isEmpty()) { onPlayAudioListener = listener;
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();
}
}
} }
} }

View File

@ -1,6 +1,8 @@
package org.schabi.newpipe; package org.schabi.newpipe;
import android.app.Activity; import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -13,6 +15,7 @@ import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.design.widget.FloatingActionButton; import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.text.Html; import android.text.Html;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
@ -43,6 +46,7 @@ import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Vector; import java.util.Vector;
import org.schabi.newpipe.crawler.MediaFormat;
import org.schabi.newpipe.crawler.ParsingException; import org.schabi.newpipe.crawler.ParsingException;
import org.schabi.newpipe.crawler.ServiceList; import org.schabi.newpipe.crawler.ServiceList;
import org.schabi.newpipe.crawler.VideoPreviewInfo; import org.schabi.newpipe.crawler.VideoPreviewInfo;
@ -73,6 +77,7 @@ import org.schabi.newpipe.crawler.services.youtube.YoutubeVideoExtractor;
public class VideoItemDetailFragment extends Fragment { public class VideoItemDetailFragment extends Fragment {
private static final String TAG = VideoItemDetailFragment.class.toString(); 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 * The fragment argument representing the item ID that this fragment
@ -89,8 +94,8 @@ public class VideoItemDetailFragment extends Fragment {
private int streamingServiceId = -1; private int streamingServiceId = -1;
private boolean autoPlayEnabled = false; private boolean autoPlayEnabled = false;
private VideoInfo currentVideoInfo = null;
private boolean showNextVideoItem = false; private boolean showNextVideoItem = false;
private Bitmap videoThumbnail;
private View thumbnailWindowLayout; private View thumbnailWindowLayout;
private FloatingActionButton playVideoButton; private FloatingActionButton playVideoButton;
@ -192,10 +197,9 @@ public class VideoItemDetailFragment extends Fragment {
public void onLoadingCancelled(String imageUri, View view) {} public void onLoadingCancelled(String imageUri, View view) {}
} }
private void updateInfo(VideoInfo info) { private void updateInfo(final VideoInfo info) {
currentVideoInfo = info;
try { try {
Context c = getContext();
VideoInfoItemViewCreator videoItemViewCreator = VideoInfoItemViewCreator videoItemViewCreator =
new VideoInfoItemViewCreator(LayoutInflater.from(getActivity())); new VideoInfoItemViewCreator(LayoutInflater.from(getActivity()));
@ -216,9 +220,11 @@ public class VideoItemDetailFragment extends Fragment {
(RelativeLayout) activity.findViewById(R.id.detailNextVideoRootLayout); (RelativeLayout) activity.findViewById(R.id.detailNextVideoRootLayout);
Button nextVideoButton = (Button) activity.findViewById(R.id.detailNextVideoButton); Button nextVideoButton = (Button) activity.findViewById(R.id.detailNextVideoButton);
TextView similarTitle = (TextView) activity.findViewById(R.id.detailSimilarTitle); TextView similarTitle = (TextView) activity.findViewById(R.id.detailSimilarTitle);
Button backgroundButton = (Button)
activity.findViewById(R.id.detailVideoThumbnailWindowBackgroundButton);
View topView = activity.findViewById(R.id.detailTopView); View topView = activity.findViewById(R.id.detailTopView);
View nextVideoView = videoItemViewCreator View nextVideoView = videoItemViewCreator
.getViewFromVideoInfoItem(null, nextVideoFrame, info.nextVideo, getContext()); .getViewFromVideoInfoItem(null, nextVideoFrame, info.next_video, getContext());
progressBar.setVisibility(View.GONE); progressBar.setVisibility(View.GONE);
nextVideoFrame.addView(nextVideoView); nextVideoFrame.addView(nextVideoView);
@ -253,42 +259,24 @@ public class VideoItemDetailFragment extends Fragment {
}); });
uploaderView.setText(info.uploader); uploaderView.setText(info.uploader);
actionBarHandler.setChannelName(info.uploader);
videoTitleView.setText(info.title); videoTitleView.setText(info.title);
uploaderView.setText(info.uploader); uploaderView.setText(info.uploader);
actionBarHandler.setChannelName(info.uploader); viewCountView.setText(Localization.localizeViewCount(info.view_count, c));
thumbsUpView.setText(Localization.localizeNumber(info.like_count, c));
String localizedViewCount = Localization.localizeViewCount(info.view_count, getContext()); thumbsDownView.setText(Localization.localizeNumber(info.dislike_count, c));
viewCountView.setText(localizedViewCount); uploadDateView.setText(Localization.localizeDate(info.upload_date, c));
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);
descriptionView.setText(Html.fromHtml(info.description)); descriptionView.setText(Html.fromHtml(info.description));
descriptionView.setMovementMethod(LinkMovementMethod.getInstance()); descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
actionBarHandler.setServiceId(streamingServiceId);
actionBarHandler.setVideoInfo(info.webpage_url, info.title);
actionBarHandler.setStartPosition(info.startPosition);
// parse streams // parse streams
Vector<VideoInfo.VideoStream> streamsToUse = new Vector<>(); Vector<VideoInfo.VideoStream> streamsToUse = new Vector<>();
for (VideoInfo.VideoStream i : info.videoStreams) { for (VideoInfo.VideoStream i : info.video_streams) {
if (useStream(i, streamsToUse)) { if (useStream(i, streamsToUse)) {
streamsToUse.add(i); streamsToUse.add(i);
} }
} }
actionBarHandler.setStreams(streamsToUse, info.audioStreams);
nextVideoButton.setOnClickListener(new View.OnClickListener() { nextVideoButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@ -297,18 +285,34 @@ public class VideoItemDetailFragment extends Fragment {
/*detailIntent.putExtra( /*detailIntent.putExtra(
VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); */ VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); */
detailIntent.putExtra( detailIntent.putExtra(
VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url); VideoItemDetailFragment.VIDEO_URL, info.next_video.webpage_url);
detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId); detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId);
startActivity(detailIntent); startActivity(detailIntent);
} }
}); });
textContentLayout.setVisibility(View.VISIBLE); textContentLayout.setVisibility(View.VISIBLE);
initSimilarVideos(videoItemViewCreator); initSimilarVideos(info, videoItemViewCreator);
if(autoPlayEnabled) { 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) { } catch (java.lang.NullPointerException e) {
Log.w(TAG, "updateInfo(): Fragment closed before thread ended work... or else"); Log.w(TAG, "updateInfo(): Fragment closed before thread ended work... or else");
e.printStackTrace(); e.printStackTrace();
@ -325,7 +329,8 @@ public class VideoItemDetailFragment extends Fragment {
imageLoader.displayImage(info.thumbnail_url, videoThumbnailView, imageLoader.displayImage(info.thumbnail_url, videoThumbnailView,
displayImageOptions, new ImageLoadingListener() { displayImageOptions, new ImageLoadingListener() {
@Override @Override
public void onLoadingStarted(String imageUri, View view) {} public void onLoadingStarted(String imageUri, View view) {
}
@Override @Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) { public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
@ -336,21 +341,191 @@ public class VideoItemDetailFragment extends Fragment {
@Override @Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
actionBarHandler.setVideoThumbnail(loadedImage); videoThumbnail = loadedImage;
} }
@Override @Override
public void onLoadingCancelled(String imageUri, View view) {} public void onLoadingCancelled(String imageUri, View view) {
}
}); });
imageLoader.displayImage(info.uploader_thumbnail_url, imageLoader.displayImage(info.uploader_thumbnail_url,
uploaderThumb, displayImageOptions, new ThumbnailLoadingListener()); uploaderThumb, displayImageOptions, new ThumbnailLoadingListener());
imageLoader.displayImage(info.nextVideo.thumbnail_url, imageLoader.displayImage(info.next_video.thumbnail_url,
nextVideoThumb, displayImageOptions, new ThumbnailLoadingListener()); 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); LinearLayout similarLayout = (LinearLayout) activity.findViewById(R.id.similarVideosView);
ArrayList<VideoPreviewInfo> similar = new ArrayList<>(currentVideoInfo.relatedVideos); ArrayList<VideoPreviewInfo> similar = new ArrayList<>(info.related_videos);
for (final VideoPreviewInfo item : similar) { for (final VideoPreviewInfo item : similar) {
View similarView = videoItemViewCreator View similarView = videoItemViewCreator
.getViewFromVideoInfoItem(null, similarLayout, item, getContext()); .getViewFromVideoInfoItem(null, similarLayout, item, getContext());
@ -479,20 +654,6 @@ public class VideoItemDetailFragment extends Fragment {
e.printStackTrace(); 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 // todo: Fix this workaround (probably with a better design), so that older android
// versions don't have problems rendering the thumbnail right. // versions don't have problems rendering the thumbnail right.
if(Build.VERSION.SDK_INT >= 18) { 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 @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
actionBarHandler.setupMenu(menu, inflater); actionBarHandler.setupMenu(menu, inflater);

View File

@ -36,6 +36,7 @@ public class VideoInfo extends AbstractVideoInfo {
VideoUrlIdHandler uiconv = extractor.getUrlIdConverter(); VideoUrlIdHandler uiconv = extractor.getUrlIdConverter();
videoInfo.webpage_url = extractor.getPageUrl(); videoInfo.webpage_url = extractor.getPageUrl();
videoInfo.title = extractor.getTitle(); videoInfo.title = extractor.getTitle();
videoInfo.duration = extractor.getLength(); videoInfo.duration = extractor.getLength();
@ -47,23 +48,23 @@ public class VideoInfo extends AbstractVideoInfo {
videoInfo.id = uiconv.getVideoId(extractor.getPageUrl()); videoInfo.id = uiconv.getVideoId(extractor.getPageUrl());
videoInfo.dashMpdUrl = extractor.getDashMpdUrl(); videoInfo.dashMpdUrl = extractor.getDashMpdUrl();
/** Load and extract audio*/ /** Load and extract audio*/
videoInfo.audioStreams = extractor.getAudioStreams(); videoInfo.audio_streams = extractor.getAudioStreams();
if(videoInfo.dashMpdUrl != null && !videoInfo.dashMpdUrl.isEmpty()) { if(videoInfo.dashMpdUrl != null && !videoInfo.dashMpdUrl.isEmpty()) {
if(videoInfo.audioStreams == null) { if(videoInfo.audio_streams == null) {
videoInfo.audioStreams = new Vector<AudioStream>(); videoInfo.audio_streams = new Vector<AudioStream>();
} }
videoInfo.audioStreams.addAll( videoInfo.audio_streams.addAll(
DashMpdParser.getAudioStreams(videoInfo.dashMpdUrl, downloader)); DashMpdParser.getAudioStreams(videoInfo.dashMpdUrl, downloader));
} }
/** Extract video stream url*/ /** Extract video stream url*/
videoInfo.videoStreams = extractor.getVideoStreams(); videoInfo.video_streams = extractor.getVideoStreams();
videoInfo.uploader_thumbnail_url = extractor.getUploaderThumbnailUrl(); videoInfo.uploader_thumbnail_url = extractor.getUploaderThumbnailUrl();
videoInfo.startPosition = extractor.getTimeStamp(); videoInfo.start_position = extractor.getTimeStamp();
videoInfo.average_rating = extractor.getAverageRating(); videoInfo.average_rating = extractor.getAverageRating();
videoInfo.like_count = extractor.getLikeCount(); videoInfo.like_count = extractor.getLikeCount();
videoInfo.dislike_count = extractor.getDislikeCount(); videoInfo.dislike_count = extractor.getDislikeCount();
videoInfo.nextVideo = extractor.getNextVideo(); videoInfo.next_video = extractor.getNextVideo();
videoInfo.relatedVideos = extractor.getRelatedVideos(); videoInfo.related_videos = extractor.getRelatedVideos();
//Bitmap thumbnail = null; //Bitmap thumbnail = null;
//Bitmap uploader_thumbnail = null; //Bitmap uploader_thumbnail = null;
@ -75,8 +76,8 @@ public class VideoInfo extends AbstractVideoInfo {
public String uploader_thumbnail_url = ""; public String uploader_thumbnail_url = "";
public String description = ""; public String description = "";
/*todo: make this lists over vectors*/ /*todo: make this lists over vectors*/
public List<VideoStream> videoStreams = null; public List<VideoStream> video_streams = null;
public List<AudioStream> audioStreams = null; public List<AudioStream> audio_streams = null;
// video streams provided by the dash mpd do not need to be provided as VideoStream. // 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, // 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 // 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 like_count = -1;
public int dislike_count = -1; public int dislike_count = -1;
public String average_rating = ""; public String average_rating = "";
public VideoPreviewInfo nextVideo = null; public VideoPreviewInfo next_video = null;
public List<VideoPreviewInfo> relatedVideos = null; public List<VideoPreviewInfo> related_videos = null;
//in seconds. some metadata is not passed using a VideoInfo object! //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() {} public VideoInfo() {}
@ -137,11 +139,11 @@ public class VideoInfo extends AbstractVideoInfo {
public String url = ""; public String url = "";
public int format = -1; public int format = -1;
public int bandwidth = -1; public int bandwidth = -1;
public int samplingRate = -1; public int sampling_rate = -1;
public AudioStream(String url, int format, int bandwidth, int samplingRate) { public AudioStream(String url, int format, int bandwidth, int samplingRate) {
this.url = url; this.format = format; this.url = url; this.format = format;
this.bandwidth = bandwidth; this.samplingRate = samplingRate; this.bandwidth = bandwidth; this.sampling_rate = samplingRate;
} }
} }
} }