From 648b9b5d028addce33f81625dbd585afab72c9a1 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Wed, 17 Feb 2016 21:39:41 +0100 Subject: [PATCH] made the ui more accommodating for not available audio streams --- .../org/schabi/newpipe/ActionBarHandler.java | 51 +++-- .../org/schabi/newpipe/DownloadDialog.java | 178 +++++++++++------- .../newpipe/VideoItemDetailFragment.java | 166 +++++++++------- .../org/schabi/newpipe/crawler/VideoInfo.java | 5 +- app/src/main/res/values/strings.xml | 13 ++ 5 files changed, 253 insertions(+), 160 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java b/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java index 3dee3dfe6..4f55f1bf6 100644 --- a/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java +++ b/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java @@ -51,13 +51,16 @@ class ActionBarHandler { private SharedPreferences defaultPreferences = null; + private Menu menu; + // 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; + private OnActionListener onShareListener = null; + private OnActionListener onOpenInBrowserListener = null; + private OnActionListener onDownloadListener = null; + private OnActionListener onPlayWithKodiListener = null; + private OnActionListener onPlayAudioListener = null; + // Triggered when a stream related action is triggered. public interface OnActionListener { @@ -128,15 +131,15 @@ class ActionBarHandler { } public void setupMenu(Menu menu, MenuInflater inflater) { + this.menu = menu; + // CAUTION set item properties programmatically otherwise it would not be accepted by // appcompat itemsinflater.inflate(R.menu.videoitem_detail, menu); defaultPreferences = PreferenceManager.getDefaultSharedPreferences(activity); - inflater.inflate(R.menu.videoitem_detail, menu); - MenuItem castItem = menu.findItem(R.id.action_play_with_kodi); - castItem.setVisible(defaultPreferences + showPlayWithKodiAction(defaultPreferences .getBoolean(activity.getString(R.string.show_play_with_kodi_key), false)); } @@ -151,15 +154,21 @@ class ActionBarHandler { intent.setType("text/plain"); activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.share_dialog_title))); */ - onShareListener.onActionSelected(selectedVideoStream); + if(onShareListener != null) { + onShareListener.onActionSelected(selectedVideoStream); + } return true; } case R.id.menu_item_openInBrowser: { - onOpenInBrowserListener.onActionSelected(selectedVideoStream); + if(onOpenInBrowserListener != null) { + onOpenInBrowserListener.onActionSelected(selectedVideoStream); + } } return true; case R.id.menu_item_download: - onDownloadListener.onActionSelected(selectedVideoStream); + if(onDownloadListener != null) { + onDownloadListener.onActionSelected(selectedVideoStream); + } return true; case R.id.action_settings: { Intent intent = new Intent(activity, SettingsActivity.class); @@ -167,10 +176,14 @@ class ActionBarHandler { return true; } case R.id.action_play_with_kodi: - onPlayWithKodiListener.onActionSelected(selectedVideoStream); + if(onPlayWithKodiListener != null) { + onPlayWithKodiListener.onActionSelected(selectedVideoStream); + } return true; case R.id.menu_item_play_audio: - onPlayAudioListener.onActionSelected(selectedVideoStream); + if(onPlayAudioListener != null) { + onPlayAudioListener.onActionSelected(selectedVideoStream); + } return true; default: Log.e(TAG, "Menu Item not known"); @@ -201,4 +214,16 @@ class ActionBarHandler { public void setOnPlayAudioListener(OnActionListener listener) { onPlayAudioListener = listener; } + + public void showAudioAction(boolean visible) { + menu.findItem(R.id.menu_item_play_audio).setVisible(visible); + } + + public void showDownloadAction(boolean visible) { + menu.findItem(R.id.menu_item_download).setVisible(visible); + } + + public void showPlayWithKodiAction(boolean visible) { + menu.findItem(R.id.action_play_with_kodi).setVisible(visible); + } } diff --git a/app/src/main/java/org/schabi/newpipe/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/DownloadDialog.java index 79d24823c..18d97185d 100644 --- a/app/src/main/java/org/schabi/newpipe/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/DownloadDialog.java @@ -1,18 +1,13 @@ package org.schabi.newpipe; import android.Manifest; -import android.app.Activity; import android.app.Dialog; import android.app.DownloadManager; -import android.app.Notification; import android.content.Context; import android.content.DialogInterface; -import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; -import android.os.Environment; -import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.app.DialogFragment; @@ -63,74 +58,68 @@ public class DownloadDialog extends DialogFragment { if(ContextCompat.checkSelfPermission(this.getContext(),Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) ActivityCompat.requestPermissions(getActivity(),new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},0); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - builder.setTitle(R.string.download_dialog_title) - .setItems(R.array.download_options, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Context context = getActivity(); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - String suffix = ""; - String title = arguments.getString(TITLE); - String url = ""; - File downloadDir = NewPipeSettings.getDownloadFolder(); - switch(which) { - case 0: // Video - suffix = arguments.getString(FILE_SUFFIX_VIDEO); - url = arguments.getString(VIDEO_URL); - downloadDir = NewPipeSettings.getVideoDownloadFolder(context); - break; - case 1: - suffix = arguments.getString(FILE_SUFFIX_AUDIO); - url = arguments.getString(AUDIO_URL); - downloadDir = NewPipeSettings.getAudioDownloadFolder(context); - break; - default: - Log.d(TAG, "lolz"); - } - if(!downloadDir.exists()) { - //attempt to create directory - boolean mkdir = downloadDir.mkdirs(); - if(!mkdir && !downloadDir.isDirectory()) { - String message = context.getString(R.string.err_dir_create,downloadDir.toString()); - Log.e(TAG, message); - Toast.makeText(context,message , Toast.LENGTH_LONG).show(); + builder.setTitle(R.string.download_dialog_title); - return; - } - String message = context.getString(R.string.info_dir_created,downloadDir.toString()); - Log.e(TAG, message); - Toast.makeText(context,message , Toast.LENGTH_LONG).show(); - } - - File saveFilePath = new File(downloadDir,createFileName(title) + suffix); - - long id = 0; - if (App.isUsingTor()) { - // if using Tor, do not use DownloadManager because the proxy cannot be set - FileDownloader.downloadFile(getContext(), url, saveFilePath, title); - } else { - DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - DownloadManager.Request request = new DownloadManager.Request( - Uri.parse(url)); - request.setDestinationUri(Uri.fromFile(saveFilePath)); - request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); - - request.setTitle(title); - request.setDescription("'" + url + - "' => '" + saveFilePath + "'"); - request.allowScanningByMediaScanner(); - - try { - id = dm.enqueue(request); - } catch (Exception e) { - e.printStackTrace(); - } - } - - Log.i(TAG,"Started downloading '" + url + - "' => '" + saveFilePath + "' #" + id); + // If no audio stream available + if(arguments.getString(AUDIO_URL) == null) { + builder.setItems(R.array.download_options_no_audio, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Context context = getActivity(); + String title = arguments.getString(TITLE); + switch (which) { + case 0: // Video + download(arguments.getString(VIDEO_URL), + title, + arguments.getString(FILE_SUFFIX_VIDEO), context); + break; + default: + Log.d(TAG, "lolz"); } - }); + } + }); + // If no video stream available + } else if(arguments.getString(VIDEO_URL) == null) { + builder.setItems(R.array.download_options_no_video, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Context context = getActivity(); + String title = arguments.getString(TITLE); + switch (which) { + case 0: // Audio + download(arguments.getString(AUDIO_URL), + title, + arguments.getString(FILE_SUFFIX_AUDIO), context); + break; + default: + Log.d(TAG, "lolz"); + } + } + }); + //if both streams ar available + } else { + builder.setItems(R.array.download_options, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Context context = getActivity(); + String title = arguments.getString(TITLE); + switch (which) { + case 0: // Video + download(arguments.getString(VIDEO_URL), + title, + arguments.getString(FILE_SUFFIX_VIDEO), context); + break; + case 1: + download(arguments.getString(AUDIO_URL), + title, + arguments.getString(FILE_SUFFIX_AUDIO), context); + break; + default: + Log.d(TAG, "lolz"); + } + } + }); + } return builder.create(); } @@ -151,4 +140,51 @@ public class DownloadDialog extends DialogFragment { } return nameToTest; } + + private void download(String url, String title, String fileSuffix, Context context) { + File downloadDir = NewPipeSettings.getDownloadFolder(); + + if(!downloadDir.exists()) { + //attempt to create directory + boolean mkdir = downloadDir.mkdirs(); + if(!mkdir && !downloadDir.isDirectory()) { + String message = context.getString(R.string.err_dir_create,downloadDir.toString()); + Log.e(TAG, message); + Toast.makeText(context,message , Toast.LENGTH_LONG).show(); + + return; + } + String message = context.getString(R.string.info_dir_created,downloadDir.toString()); + Log.e(TAG, message); + Toast.makeText(context,message , Toast.LENGTH_LONG).show(); + } + + File saveFilePath = new File(downloadDir,createFileName(title) + fileSuffix); + + long id = 0; + if (App.isUsingTor()) { + // if using Tor, do not use DownloadManager because the proxy cannot be set + FileDownloader.downloadFile(getContext(), url, saveFilePath, title); + } else { + DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); + DownloadManager.Request request = new DownloadManager.Request( + Uri.parse(url)); + request.setDestinationUri(Uri.fromFile(saveFilePath)); + request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); + + request.setTitle(title); + request.setDescription("'" + url + + "' => '" + saveFilePath + "'"); + request.allowScanningByMediaScanner(); + + try { + id = dm.enqueue(request); + } catch (Exception e) { + e.printStackTrace(); + } + } + + Log.i(TAG,"Started downloading '" + url + + "' => '" + saveFilePath + "' #" + id); + } } diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java index c1437376b..d9977d5ba 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java @@ -414,86 +414,106 @@ public class VideoItemDetailFragment extends Fragment { 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"); - } - }); + try { + Bundle args = new Bundle(); - 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); + // Sometimes it may be that some information is not available due to changes fo the + // website which was crawled. Then the ui has to understand this and act right. - 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); + if (info.audio_streams != null) { + VideoInfo.AudioStream audioStream = + info.audio_streams.get(getPreferredAudioStreamId(info)); + + String audioSuffix = "." + MediaFormat.getSuffixById(audioStream.format); + args.putString(DownloadDialog.AUDIO_URL, audioStream.url); + args.putString(DownloadDialog.FILE_SUFFIX_AUDIO, audioSuffix); } - } 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(); + + if (info.video_streams != null) { + VideoInfo.VideoStream selectedStreamItem = info.video_streams.get(selectedStreamId); + String videoSuffix = "." + MediaFormat.getSuffixById(selectedStreamItem.format); + args.putString(DownloadDialog.FILE_SUFFIX_VIDEO, videoSuffix); + args.putString(DownloadDialog.VIDEO_URL, selectedStreamItem.url); } + + args.putString(DownloadDialog.TITLE, info.title); + DownloadDialog downloadDialog = new DownloadDialog(); + downloadDialog.setArguments(args); + downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog"); + } catch(Exception e) { + Toast.makeText(VideoItemDetailFragment.this.getActivity(), + R.string.could_not_setup_download_menu, Toast.LENGTH_LONG).show(); + e.printStackTrace(); } } }); + + if(info.audio_streams == null) { + actionBarHandler.showAudioAction(false); + } else { + 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) { 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 a6aa4a43e..12449ccbf 100644 --- a/app/src/main/java/org/schabi/newpipe/crawler/VideoInfo.java +++ b/app/src/main/java/org/schabi/newpipe/crawler/VideoInfo.java @@ -55,8 +55,10 @@ public class VideoInfo extends AbstractVideoInfo { } catch(Exception e) { e.printStackTrace(); } + /** Load and extract audio*/ videoInfo.audio_streams = extractor.getAudioStreams(); + // also try to get streams from the dashMpd if(videoInfo.dashMpdUrl != null && !videoInfo.dashMpdUrl.isEmpty()) { if(videoInfo.audio_streams == null) { videoInfo.audio_streams = new Vector(); @@ -82,9 +84,6 @@ public class VideoInfo extends AbstractVideoInfo { videoInfo.next_video = extractor.getNextVideo(); videoInfo.related_videos = extractor.getRelatedVideos(); - //Bitmap thumbnail = null; - //Bitmap uploader_thumbnail = null; - //int videoAvailableStatus = VIDEO_AVAILABLE; return videoInfo; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0e95a3231..33a59d813 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -53,6 +53,15 @@ Video Audio + + + Video + + + + Audio + + Next video Show next and similar videos URL not supported @@ -65,6 +74,8 @@ Playing in background https://www.c3s.cc/ Play + + Error Network error Could not load all Thumbnails @@ -72,6 +83,8 @@ Could not parse website. Content not available. Blocked by GEMA. + Could not setup download menu. + Video preview thumbnail