From d9e690f62c2d0c28c633a7771f7c1187a3672706 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Sun, 25 Oct 2015 19:13:44 +0100 Subject: [PATCH] added NextVideo support --- .idea/misc.xml | 2 +- .../org/schabi/newpipe/VideoInfoItem.java | 1 + .../newpipe/VideoInfoItemViewCreator.java | 76 ++++++++++++++++++ .../newpipe/VideoItemDetailFragment.java | 64 +++++++++------ .../org/schabi/newpipe/VideoListAdapter.java | 42 ++-------- .../newpipe/youtube/YoutubeExtractor.java | 15 ++-- .../layout-land/fragment_videoitem_detail.xml | 77 ++++++++++++++----- .../fragment_videoitem_detail.xml | 77 ++++++++++++++----- .../res/layout/fragment_videoitem_detail.xml | 73 ++++++++++++++---- app/src/main/res/layout/video_item.xml | 3 +- app/src/main/res/values-de/strings.xml | 3 +- app/src/main/res/values/strings.xml | 1 + 12 files changed, 311 insertions(+), 123 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/VideoInfoItemViewCreator.java diff --git a/.idea/misc.xml b/.idea/misc.xml index fbb68289f..5d1998103 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,7 +37,7 @@ - + diff --git a/app/src/main/java/org/schabi/newpipe/VideoInfoItem.java b/app/src/main/java/org/schabi/newpipe/VideoInfoItem.java index 30d304bd7..ce7ebdd6e 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoInfoItem.java +++ b/app/src/main/java/org/schabi/newpipe/VideoInfoItem.java @@ -31,4 +31,5 @@ public class VideoInfoItem { public Bitmap thumbnail = null; public String webpage_url = ""; public String upload_date = ""; + public String view_count = ""; } \ No newline at end of file diff --git a/app/src/main/java/org/schabi/newpipe/VideoInfoItemViewCreator.java b/app/src/main/java/org/schabi/newpipe/VideoInfoItemViewCreator.java new file mode 100644 index 000000000..64db7d15d --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/VideoInfoItemViewCreator.java @@ -0,0 +1,76 @@ +package org.schabi.newpipe; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +/** + * Created by Christian Schabesberger on 24.10.15. + * + * Copyright (C) Christian Schabesberger 2015 + * VideoInfoItemViewCreator.java is part of NewPipe. + * + * NewPipe is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NewPipe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NewPipe. If not, see . + */ + +public class VideoInfoItemViewCreator { + private static final String TAG = VideoInfoItemViewCreator.class.toString(); + + LayoutInflater inflater; + + public VideoInfoItemViewCreator(LayoutInflater inflater) { + this.inflater = inflater; + } + + public View getViewByVideoInfoItem(View convertView, ViewGroup parent, VideoInfoItem info) { + ViewHolder holder; + if(convertView == null) { + convertView = inflater.inflate(R.layout.video_item, parent, false); + holder = new ViewHolder(); + holder.itemThumbnailView = (ImageView) convertView.findViewById(R.id.itemThumbnailView); + holder.itemVideoTitleView = (TextView) convertView.findViewById(R.id.itemVideoTitleView); + holder.itemUploaderView = (TextView) convertView.findViewById(R.id.itemUploaderView); + holder.itemDurationView = (TextView) convertView.findViewById(R.id.itemDurationView); + holder.itemUploadDateView = (TextView) convertView.findViewById(R.id.itemUploadDateView); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + if(info.thumbnail == null) { + holder.itemThumbnailView.setImageResource(R.drawable.dummi_thumbnail); + } else { + holder.itemThumbnailView.setImageBitmap(info.thumbnail); + } + holder.itemVideoTitleView.setText(info.title); + holder.itemUploaderView.setText(info.uploader); + holder.itemDurationView.setText(info.duration); + if(!info.upload_date.isEmpty()) { + holder.itemUploadDateView.setText(info.upload_date); + } else { + //tewak if nececeary: This is a hack preventing to have a white space in the layout :P + holder.itemUploadDateView.setText(info.view_count); + } + + return convertView; + } + + private class ViewHolder { + public ImageView itemThumbnailView; + public TextView itemVideoTitleView, itemUploaderView, itemDurationView, itemUploadDateView; + } + +} diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java index a578a6f01..542b43a74 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java @@ -1,6 +1,7 @@ package org.schabi.newpipe; import android.app.Activity; +import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; @@ -15,9 +16,12 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; +import android.widget.ScrollView; import android.widget.TextView; import java.net.URL; @@ -57,6 +61,7 @@ public class VideoItemDetailFragment extends Fragment { private boolean autoPlayEnabled = false; private Thread extractorThread = null; + private VideoInfo currentVideoInfo = null; private class ExtractorRunnable implements Runnable { private Handler h = new Handler(); @@ -83,6 +88,11 @@ public class VideoItemDetailFragment extends Fragment { new URL(videoInfo.uploader_thumbnail_url) .openConnection() .getInputStream()), SetThumbnailRunnable.CHANNEL_THUMBNAIL)); + h.post(new SetThumbnailRunnable( + BitmapFactory.decodeStream( + new URL(videoInfo.nextVideo.thumbnail_url) + .openConnection() + .getInputStream()), SetThumbnailRunnable.NEXT_VIDEO_THUMBNAIL)); } } catch (Exception e) { e.printStackTrace(); @@ -103,8 +113,9 @@ public class VideoItemDetailFragment extends Fragment { } private class SetThumbnailRunnable implements Runnable { - public static final int CHANNEL_THUMBNAIL = 2; public static final int VIDEO_THUMBNAIL = 1; + public static final int CHANNEL_THUMBNAIL = 2; + public static final int NEXT_VIDEO_THUMBNAIL = 3; private Bitmap thumbnail; private int thumbnailId; public SetThumbnailRunnable(Bitmap thumbnail, int id) { @@ -123,19 +134,25 @@ public class VideoItemDetailFragment extends Fragment { try { switch (id) { case SetThumbnailRunnable.VIDEO_THUMBNAIL: - thumbnailView = (ImageView) a.findViewById(R.id.detailThumbnailView); break; case SetThumbnailRunnable.CHANNEL_THUMBNAIL: thumbnailView = (ImageView) a.findViewById(R.id.detailUploaderThumbnailView); break; + case SetThumbnailRunnable.NEXT_VIDEO_THUMBNAIL: + FrameLayout nextVideoFrame = (FrameLayout) a.findViewById(R.id.detailNextVideoFrame); + thumbnailView = (ImageView) nextVideoFrame.findViewById(R.id.itemThumbnailView); + currentVideoInfo.nextVideo.thumbnail = thumbnail; + break; default: Log.d(TAG, "Error: Thumbnail id not known"); return; } + if (thumbnailView != null) { thumbnailView.setImageBitmap(thumbnail); } + } catch (java.lang.NullPointerException e) { // No god programm design i know. :/ Log.w(TAG, "updateThumbnail(): Fragment closed before thread ended work"); @@ -144,7 +161,12 @@ public class VideoItemDetailFragment extends Fragment { public void updateInfo(VideoInfo info) { Activity a = getActivity(); + currentVideoInfo = info; try { + VideoInfoItemViewCreator videoItemViewCreator = + new VideoInfoItemViewCreator(LayoutInflater.from(getActivity())); + + ScrollView contentMainView = (ScrollView) a.findViewById(R.id.detailMainContent); ProgressBar progressBar = (ProgressBar) a.findViewById(R.id.detailProgressBar); TextView videoTitleView = (TextView) a.findViewById(R.id.detailVideoTitleView); TextView uploaderView = (TextView) a.findViewById(R.id.detailUploaderView); @@ -154,28 +176,14 @@ public class VideoItemDetailFragment extends Fragment { TextView uploadDateView = (TextView) a.findViewById(R.id.detailUploadDateView); TextView descriptionView = (TextView) a.findViewById(R.id.detailDescriptionView); ImageView thumbnailView = (ImageView) a.findViewById(R.id.detailThumbnailView); - ImageView uploaderThumbnailView = (ImageView) a.findViewById(R.id.detailUploaderThumbnailView); - ImageView thumbsUpPic = (ImageView) a.findViewById(R.id.detailThumbsUpImgView); - ImageView thumbsDownPic = (ImageView) a.findViewById(R.id.detailThumbsDownImgView); - View textSeperationLine = a.findViewById(R.id.textSeperationLine); + FrameLayout nextVideoFrame = (FrameLayout) a.findViewById(R.id.detailNextVideoFrame); + View nextVideoView = videoItemViewCreator + .getViewByVideoInfoItem(null, nextVideoFrame, info.nextVideo); + nextVideoFrame.addView(nextVideoView); + Button nextVideoButton = (Button) a.findViewById(R.id.detailNextVideoButton); - - if(textSeperationLine != null) { - textSeperationLine.setVisibility(View.VISIBLE); - } + contentMainView.setVisibility(View.VISIBLE); progressBar.setVisibility(View.GONE); - videoTitleView.setVisibility(View.VISIBLE); - uploaderView.setVisibility(View.VISIBLE); - uploadDateView.setVisibility(View.VISIBLE); - viewCountView.setVisibility(View.VISIBLE); - thumbsUpView.setVisibility(View.VISIBLE); - thumbsDownView.setVisibility(View.VISIBLE); - uploadDateView.setVisibility(View.VISIBLE); - descriptionView.setVisibility(View.VISIBLE); - thumbnailView.setVisibility(View.VISIBLE); - uploaderThumbnailView.setVisibility(View.VISIBLE); - thumbsUpPic.setVisibility(View.VISIBLE); - thumbsDownPic.setVisibility(View.VISIBLE); switch (info.videoAvailableStatus) { case VideoInfo.VIDEO_AVAILABLE: { @@ -203,6 +211,18 @@ public class VideoItemDetailFragment extends Fragment { } ActionBarHandler.getHandler().setStreams(streamList, info.audioStreams); } + + nextVideoButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent detailIntent = new Intent(getActivity(), VideoItemDetailActivity.class); + detailIntent.putExtra(VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); + detailIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url); + //todo: make id dynamic the following line is crap + detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, 0); + startActivity(detailIntent); + } + }); break; case VideoInfo.VIDEO_UNAVAILABLE_GEMA: thumbnailView.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.gruese_die_gema_unangebracht)); diff --git a/app/src/main/java/org/schabi/newpipe/VideoListAdapter.java b/app/src/main/java/org/schabi/newpipe/VideoListAdapter.java index 6edda8736..ea69be538 100644 --- a/app/src/main/java/org/schabi/newpipe/VideoListAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/VideoListAdapter.java @@ -6,14 +6,12 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; -import android.widget.ImageView; import android.widget.ListView; -import android.widget.TextView; import java.util.Vector; /** - * Created by the-scrabi on 11.08.15. + * Created by Christian Schabesberger on 11.08.15. * * Copyright (C) Christian Schabesberger 2015 * VideoListAdapter.java is part of NewPipe. @@ -33,18 +31,20 @@ import java.util.Vector; */ public class VideoListAdapter extends BaseAdapter { - private static final String TAG = VideoListAdapter.class.toString(); - private LayoutInflater inflater; + + private Context context; + private VideoInfoItemViewCreator viewCreator; private Vector videoList = new Vector<>(); private Vector downloadedThumbnailList = new Vector<>(); VideoItemListFragment videoListFragment; ListView listView; public VideoListAdapter(Context context, VideoItemListFragment videoListFragment) { - inflater = LayoutInflater.from(context); + viewCreator = new VideoInfoItemViewCreator(LayoutInflater.from(context)); this.videoListFragment = videoListFragment; this.listView = videoListFragment.getListView(); + this.context = context; } public void addVideoList(Vector videos) { @@ -96,30 +96,7 @@ public class VideoListAdapter extends BaseAdapter { @Override public View getView(int position, View convertView, ViewGroup parent) { - ViewHolder holder; - if(convertView == null) { - convertView = inflater.inflate(R.layout.video_item, parent, false); - holder = new ViewHolder(); - holder.itemThumbnailView = (ImageView) convertView.findViewById(R.id.itemThumbnailView); - holder.itemVideoTitleView = (TextView) convertView.findViewById(R.id.itemVideoTitleView); - holder.itemUploaderView = (TextView) convertView.findViewById(R.id.itemUploaderView); - holder.itemDurationView = (TextView) convertView.findViewById(R.id.itemDurationView); - holder.itemUploadDateView = (TextView) convertView.findViewById(R.id.itemUploadDateView); - convertView.setTag(holder); - } else { - holder = (ViewHolder) convertView.getTag(); - } - - final Context context = parent.getContext(); - if(videoList.get(position).thumbnail == null) { - holder.itemThumbnailView.setImageResource(R.drawable.dummi_thumbnail); - } else { - holder.itemThumbnailView.setImageBitmap(videoList.get(position).thumbnail); - } - holder.itemVideoTitleView.setText(videoList.get(position).title); - holder.itemUploaderView.setText(videoList.get(position).uploader); - holder.itemDurationView.setText(videoList.get(position).duration); - holder.itemUploadDateView.setText(videoList.get(position).upload_date); + convertView = viewCreator.getViewByVideoInfoItem(convertView, parent, videoList.get(position)); if(listView.isItemChecked(position)) { convertView.setBackgroundColor(context.getResources().getColor(R.color.primaryColorYoutube)); @@ -129,9 +106,4 @@ public class VideoListAdapter extends BaseAdapter { return convertView; } - - private class ViewHolder { - public ImageView itemThumbnailView; - public TextView itemVideoTitleView, itemUploaderView, itemDurationView, itemUploadDateView; - } } \ No newline at end of file diff --git a/app/src/main/java/org/schabi/newpipe/youtube/YoutubeExtractor.java b/app/src/main/java/org/schabi/newpipe/youtube/YoutubeExtractor.java index 39425db27..15a80a950 100644 --- a/app/src/main/java/org/schabi/newpipe/youtube/YoutubeExtractor.java +++ b/app/src/main/java/org/schabi/newpipe/youtube/YoutubeExtractor.java @@ -153,7 +153,7 @@ public class YoutubeExtractor implements Extractor { //------------------------------------- JSONObject playerArgs = null; JSONObject ytAssets = null; - String dashManifest = ""; + String dashManifest; { Pattern p = Pattern.compile("ytplayer.config\\s*=\\s*(\\{.*?\\});"); Matcher m = p.matcher(site); @@ -294,12 +294,10 @@ public class YoutubeExtractor implements Extractor { // view count videoInfo.view_count = doc.select("div[class=\"watch-view-count\"]").first().text(); - /* // next video videoInfo.nextVideo = extractVideoInfoItem(doc.select("div[class=\"watch-sidebar-section\"]").first() .select("li").first()); - int i = 0; // related videos videoInfo.relatedVideos = new Vector<>(); @@ -308,10 +306,8 @@ public class YoutubeExtractor implements Extractor { if(li.select("a[class*=\"content-link\"]").first() != null) { videoInfo.relatedVideos.add(extractVideoInfoItem(li)); i++; - Log.d(TAG, Integer.toString(i)); } } - */ return videoInfo; } @@ -403,11 +399,10 @@ public class YoutubeExtractor implements Extractor { } catch (Exception e) { e.printStackTrace(); } - info.title = li.select("span[class=\"title\"]").first() - .text(); + info.title = li.select("span[class=\"title\"]").first().text(); + info.view_count = li.select("span[class*=\"view-count\"]").first().text(); info.uploader = li.select("span[class=\"g-hovercard\"]").first().text(); - info.duration = li.select("span[class=\"video-time\"]").first().text(); Element img = li.select("img").first(); @@ -418,7 +413,9 @@ public class YoutubeExtractor implements Extractor { if(info.thumbnail_url.contains(".gif")) { info.thumbnail_url = img.attr("data-thumb"); } - + if(info.thumbnail_url.startsWith("//")) { + info.thumbnail_url = "https:" + info.thumbnail_url; + } return info; } diff --git a/app/src/main/res/layout-land/fragment_videoitem_detail.xml b/app/src/main/res/layout-land/fragment_videoitem_detail.xml index 1850c3c48..b547e40e6 100644 --- a/app/src/main/res/layout-land/fragment_videoitem_detail.xml +++ b/app/src/main/res/layout-land/fragment_videoitem_detail.xml @@ -6,7 +6,8 @@ style="?android:attr/textAppearanceLarge" tools:context=".VideoItemDetailFragment" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:id="@+id/videoitem_detail"> + android:textIsSelectable="true" + android:visibility="invisible"> + android:src="@drawable/dummi_thumbnail"/> + android:text="Bla blabla !!!"/> + + + + + + +