Skip to content

Commit d9e690f

Browse files
committed
added NextVideo support
1 parent 8c0156d commit d9e690f

12 files changed

Lines changed: 311 additions & 123 deletions

File tree

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/src/main/java/org/schabi/newpipe/VideoInfoItem.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ public class VideoInfoItem {
3131
public Bitmap thumbnail = null;
3232
public String webpage_url = "";
3333
public String upload_date = "";
34+
public String view_count = "";
3435
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package org.schabi.newpipe;
2+
3+
import android.view.LayoutInflater;
4+
import android.view.View;
5+
import android.view.ViewGroup;
6+
import android.widget.ImageView;
7+
import android.widget.TextView;
8+
9+
/**
10+
* Created by Christian Schabesberger on 24.10.15.
11+
*
12+
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
13+
* VideoInfoItemViewCreator.java is part of NewPipe.
14+
*
15+
* NewPipe is free software: you can redistribute it and/or modify
16+
* it under the terms of the GNU General Public License as published by
17+
* the Free Software Foundation, either version 3 of the License, or
18+
* (at your option) any later version.
19+
*
20+
* NewPipe is distributed in the hope that it will be useful,
21+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
22+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23+
* GNU General Public License for more details.
24+
*
25+
* You should have received a copy of the GNU General Public License
26+
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
27+
*/
28+
29+
public class VideoInfoItemViewCreator {
30+
private static final String TAG = VideoInfoItemViewCreator.class.toString();
31+
32+
LayoutInflater inflater;
33+
34+
public VideoInfoItemViewCreator(LayoutInflater inflater) {
35+
this.inflater = inflater;
36+
}
37+
38+
public View getViewByVideoInfoItem(View convertView, ViewGroup parent, VideoInfoItem info) {
39+
ViewHolder holder;
40+
if(convertView == null) {
41+
convertView = inflater.inflate(R.layout.video_item, parent, false);
42+
holder = new ViewHolder();
43+
holder.itemThumbnailView = (ImageView) convertView.findViewById(R.id.itemThumbnailView);
44+
holder.itemVideoTitleView = (TextView) convertView.findViewById(R.id.itemVideoTitleView);
45+
holder.itemUploaderView = (TextView) convertView.findViewById(R.id.itemUploaderView);
46+
holder.itemDurationView = (TextView) convertView.findViewById(R.id.itemDurationView);
47+
holder.itemUploadDateView = (TextView) convertView.findViewById(R.id.itemUploadDateView);
48+
convertView.setTag(holder);
49+
} else {
50+
holder = (ViewHolder) convertView.getTag();
51+
}
52+
53+
if(info.thumbnail == null) {
54+
holder.itemThumbnailView.setImageResource(R.drawable.dummi_thumbnail);
55+
} else {
56+
holder.itemThumbnailView.setImageBitmap(info.thumbnail);
57+
}
58+
holder.itemVideoTitleView.setText(info.title);
59+
holder.itemUploaderView.setText(info.uploader);
60+
holder.itemDurationView.setText(info.duration);
61+
if(!info.upload_date.isEmpty()) {
62+
holder.itemUploadDateView.setText(info.upload_date);
63+
} else {
64+
//tewak if nececeary: This is a hack preventing to have a white space in the layout :P
65+
holder.itemUploadDateView.setText(info.view_count);
66+
}
67+
68+
return convertView;
69+
}
70+
71+
private class ViewHolder {
72+
public ImageView itemThumbnailView;
73+
public TextView itemVideoTitleView, itemUploaderView, itemDurationView, itemUploadDateView;
74+
}
75+
76+
}

app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.schabi.newpipe;
22

33
import android.app.Activity;
4+
import android.content.Intent;
45
import android.graphics.Bitmap;
56
import android.graphics.BitmapFactory;
67
import android.os.Bundle;
@@ -15,9 +16,12 @@
1516
import android.view.LayoutInflater;
1617
import android.view.View;
1718
import android.view.ViewGroup;
19+
import android.widget.Button;
20+
import android.widget.FrameLayout;
1821
import android.widget.ImageView;
1922
import android.widget.ProgressBar;
2023
import android.widget.RelativeLayout;
24+
import android.widget.ScrollView;
2125
import android.widget.TextView;
2226

2327
import java.net.URL;
@@ -57,6 +61,7 @@ public class VideoItemDetailFragment extends Fragment {
5761

5862
private boolean autoPlayEnabled = false;
5963
private Thread extractorThread = null;
64+
private VideoInfo currentVideoInfo = null;
6065

6166
private class ExtractorRunnable implements Runnable {
6267
private Handler h = new Handler();
@@ -83,6 +88,11 @@ public void run() {
8388
new URL(videoInfo.uploader_thumbnail_url)
8489
.openConnection()
8590
.getInputStream()), SetThumbnailRunnable.CHANNEL_THUMBNAIL));
91+
h.post(new SetThumbnailRunnable(
92+
BitmapFactory.decodeStream(
93+
new URL(videoInfo.nextVideo.thumbnail_url)
94+
.openConnection()
95+
.getInputStream()), SetThumbnailRunnable.NEXT_VIDEO_THUMBNAIL));
8696
}
8797
} catch (Exception e) {
8898
e.printStackTrace();
@@ -103,8 +113,9 @@ public void run() {
103113
}
104114

105115
private class SetThumbnailRunnable implements Runnable {
106-
public static final int CHANNEL_THUMBNAIL = 2;
107116
public static final int VIDEO_THUMBNAIL = 1;
117+
public static final int CHANNEL_THUMBNAIL = 2;
118+
public static final int NEXT_VIDEO_THUMBNAIL = 3;
108119
private Bitmap thumbnail;
109120
private int thumbnailId;
110121
public SetThumbnailRunnable(Bitmap thumbnail, int id) {
@@ -123,19 +134,25 @@ public void updateThumbnail(Bitmap thumbnail, int id) {
123134
try {
124135
switch (id) {
125136
case SetThumbnailRunnable.VIDEO_THUMBNAIL:
126-
127137
thumbnailView = (ImageView) a.findViewById(R.id.detailThumbnailView);
128138
break;
129139
case SetThumbnailRunnable.CHANNEL_THUMBNAIL:
130140
thumbnailView = (ImageView) a.findViewById(R.id.detailUploaderThumbnailView);
131141
break;
142+
case SetThumbnailRunnable.NEXT_VIDEO_THUMBNAIL:
143+
FrameLayout nextVideoFrame = (FrameLayout) a.findViewById(R.id.detailNextVideoFrame);
144+
thumbnailView = (ImageView) nextVideoFrame.findViewById(R.id.itemThumbnailView);
145+
currentVideoInfo.nextVideo.thumbnail = thumbnail;
146+
break;
132147
default:
133148
Log.d(TAG, "Error: Thumbnail id not known");
134149
return;
135150
}
151+
136152
if (thumbnailView != null) {
137153
thumbnailView.setImageBitmap(thumbnail);
138154
}
155+
139156
} catch (java.lang.NullPointerException e) {
140157
// No god programm design i know. :/
141158
Log.w(TAG, "updateThumbnail(): Fragment closed before thread ended work");
@@ -144,7 +161,12 @@ public void updateThumbnail(Bitmap thumbnail, int id) {
144161

145162
public void updateInfo(VideoInfo info) {
146163
Activity a = getActivity();
164+
currentVideoInfo = info;
147165
try {
166+
VideoInfoItemViewCreator videoItemViewCreator =
167+
new VideoInfoItemViewCreator(LayoutInflater.from(getActivity()));
168+
169+
ScrollView contentMainView = (ScrollView) a.findViewById(R.id.detailMainContent);
148170
ProgressBar progressBar = (ProgressBar) a.findViewById(R.id.detailProgressBar);
149171
TextView videoTitleView = (TextView) a.findViewById(R.id.detailVideoTitleView);
150172
TextView uploaderView = (TextView) a.findViewById(R.id.detailUploaderView);
@@ -154,28 +176,14 @@ public void updateInfo(VideoInfo info) {
154176
TextView uploadDateView = (TextView) a.findViewById(R.id.detailUploadDateView);
155177
TextView descriptionView = (TextView) a.findViewById(R.id.detailDescriptionView);
156178
ImageView thumbnailView = (ImageView) a.findViewById(R.id.detailThumbnailView);
157-
ImageView uploaderThumbnailView = (ImageView) a.findViewById(R.id.detailUploaderThumbnailView);
158-
ImageView thumbsUpPic = (ImageView) a.findViewById(R.id.detailThumbsUpImgView);
159-
ImageView thumbsDownPic = (ImageView) a.findViewById(R.id.detailThumbsDownImgView);
160-
View textSeperationLine = a.findViewById(R.id.textSeperationLine);
161-
179+
FrameLayout nextVideoFrame = (FrameLayout) a.findViewById(R.id.detailNextVideoFrame);
180+
View nextVideoView = videoItemViewCreator
181+
.getViewByVideoInfoItem(null, nextVideoFrame, info.nextVideo);
182+
nextVideoFrame.addView(nextVideoView);
183+
Button nextVideoButton = (Button) a.findViewById(R.id.detailNextVideoButton);
162184

163-
if(textSeperationLine != null) {
164-
textSeperationLine.setVisibility(View.VISIBLE);
165-
}
185+
contentMainView.setVisibility(View.VISIBLE);
166186
progressBar.setVisibility(View.GONE);
167-
videoTitleView.setVisibility(View.VISIBLE);
168-
uploaderView.setVisibility(View.VISIBLE);
169-
uploadDateView.setVisibility(View.VISIBLE);
170-
viewCountView.setVisibility(View.VISIBLE);
171-
thumbsUpView.setVisibility(View.VISIBLE);
172-
thumbsDownView.setVisibility(View.VISIBLE);
173-
uploadDateView.setVisibility(View.VISIBLE);
174-
descriptionView.setVisibility(View.VISIBLE);
175-
thumbnailView.setVisibility(View.VISIBLE);
176-
uploaderThumbnailView.setVisibility(View.VISIBLE);
177-
thumbsUpPic.setVisibility(View.VISIBLE);
178-
thumbsDownPic.setVisibility(View.VISIBLE);
179187

180188
switch (info.videoAvailableStatus) {
181189
case VideoInfo.VIDEO_AVAILABLE: {
@@ -203,6 +211,18 @@ public void updateInfo(VideoInfo info) {
203211
}
204212
ActionBarHandler.getHandler().setStreams(streamList, info.audioStreams);
205213
}
214+
215+
nextVideoButton.setOnClickListener(new View.OnClickListener() {
216+
@Override
217+
public void onClick(View v) {
218+
Intent detailIntent = new Intent(getActivity(), VideoItemDetailActivity.class);
219+
detailIntent.putExtra(VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id);
220+
detailIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url);
221+
//todo: make id dynamic the following line is crap
222+
detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, 0);
223+
startActivity(detailIntent);
224+
}
225+
});
206226
break;
207227
case VideoInfo.VIDEO_UNAVAILABLE_GEMA:
208228
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.gruese_die_gema_unangebracht));

app/src/main/java/org/schabi/newpipe/VideoListAdapter.java

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@
66
import android.view.View;
77
import android.view.ViewGroup;
88
import android.widget.BaseAdapter;
9-
import android.widget.ImageView;
109
import android.widget.ListView;
11-
import android.widget.TextView;
1210

1311
import java.util.Vector;
1412

1513
/**
16-
* Created by the-scrabi on 11.08.15.
14+
* Created by Christian Schabesberger on 11.08.15.
1715
*
1816
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
1917
* VideoListAdapter.java is part of NewPipe.
@@ -33,18 +31,20 @@
3331
*/
3432

3533
public class VideoListAdapter extends BaseAdapter {
36-
3734
private static final String TAG = VideoListAdapter.class.toString();
38-
private LayoutInflater inflater;
35+
36+
private Context context;
37+
private VideoInfoItemViewCreator viewCreator;
3938
private Vector<VideoInfoItem> videoList = new Vector<>();
4039
private Vector<Boolean> downloadedThumbnailList = new Vector<>();
4140
VideoItemListFragment videoListFragment;
4241
ListView listView;
4342

4443
public VideoListAdapter(Context context, VideoItemListFragment videoListFragment) {
45-
inflater = LayoutInflater.from(context);
44+
viewCreator = new VideoInfoItemViewCreator(LayoutInflater.from(context));
4645
this.videoListFragment = videoListFragment;
4746
this.listView = videoListFragment.getListView();
47+
this.context = context;
4848
}
4949

5050
public void addVideoList(Vector<VideoInfoItem> videos) {
@@ -96,30 +96,7 @@ public long getItemId(int position) {
9696

9797
@Override
9898
public View getView(int position, View convertView, ViewGroup parent) {
99-
ViewHolder holder;
100-
if(convertView == null) {
101-
convertView = inflater.inflate(R.layout.video_item, parent, false);
102-
holder = new ViewHolder();
103-
holder.itemThumbnailView = (ImageView) convertView.findViewById(R.id.itemThumbnailView);
104-
holder.itemVideoTitleView = (TextView) convertView.findViewById(R.id.itemVideoTitleView);
105-
holder.itemUploaderView = (TextView) convertView.findViewById(R.id.itemUploaderView);
106-
holder.itemDurationView = (TextView) convertView.findViewById(R.id.itemDurationView);
107-
holder.itemUploadDateView = (TextView) convertView.findViewById(R.id.itemUploadDateView);
108-
convertView.setTag(holder);
109-
} else {
110-
holder = (ViewHolder) convertView.getTag();
111-
}
112-
113-
final Context context = parent.getContext();
114-
if(videoList.get(position).thumbnail == null) {
115-
holder.itemThumbnailView.setImageResource(R.drawable.dummi_thumbnail);
116-
} else {
117-
holder.itemThumbnailView.setImageBitmap(videoList.get(position).thumbnail);
118-
}
119-
holder.itemVideoTitleView.setText(videoList.get(position).title);
120-
holder.itemUploaderView.setText(videoList.get(position).uploader);
121-
holder.itemDurationView.setText(videoList.get(position).duration);
122-
holder.itemUploadDateView.setText(videoList.get(position).upload_date);
99+
convertView = viewCreator.getViewByVideoInfoItem(convertView, parent, videoList.get(position));
123100

124101
if(listView.isItemChecked(position)) {
125102
convertView.setBackgroundColor(context.getResources().getColor(R.color.primaryColorYoutube));
@@ -129,9 +106,4 @@ public View getView(int position, View convertView, ViewGroup parent) {
129106

130107
return convertView;
131108
}
132-
133-
private class ViewHolder {
134-
public ImageView itemThumbnailView;
135-
public TextView itemVideoTitleView, itemUploaderView, itemDurationView, itemUploadDateView;
136-
}
137109
}

app/src/main/java/org/schabi/newpipe/youtube/YoutubeExtractor.java

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public VideoInfo getVideoInfo(String siteUrl) {
153153
//-------------------------------------
154154
JSONObject playerArgs = null;
155155
JSONObject ytAssets = null;
156-
String dashManifest = "";
156+
String dashManifest;
157157
{
158158
Pattern p = Pattern.compile("ytplayer.config\\s*=\\s*(\\{.*?\\});");
159159
Matcher m = p.matcher(site);
@@ -294,12 +294,10 @@ public VideoInfo getVideoInfo(String siteUrl) {
294294
// view count
295295
videoInfo.view_count = doc.select("div[class=\"watch-view-count\"]").first().text();
296296

297-
/*
298297
// next video
299298
videoInfo.nextVideo = extractVideoInfoItem(doc.select("div[class=\"watch-sidebar-section\"]").first()
300299
.select("li").first());
301300

302-
303301
int i = 0;
304302
// related videos
305303
videoInfo.relatedVideos = new Vector<>();
@@ -308,10 +306,8 @@ public VideoInfo getVideoInfo(String siteUrl) {
308306
if(li.select("a[class*=\"content-link\"]").first() != null) {
309307
videoInfo.relatedVideos.add(extractVideoInfoItem(li));
310308
i++;
311-
Log.d(TAG, Integer.toString(i));
312309
}
313310
}
314-
*/
315311

316312
return videoInfo;
317313
}
@@ -403,11 +399,10 @@ private VideoInfoItem extractVideoInfoItem(Element li) {
403399
} catch (Exception e) {
404400
e.printStackTrace();
405401
}
406-
info.title = li.select("span[class=\"title\"]").first()
407-
.text();
408402

403+
info.title = li.select("span[class=\"title\"]").first().text();
404+
info.view_count = li.select("span[class*=\"view-count\"]").first().text();
409405
info.uploader = li.select("span[class=\"g-hovercard\"]").first().text();
410-
411406
info.duration = li.select("span[class=\"video-time\"]").first().text();
412407

413408
Element img = li.select("img").first();
@@ -418,7 +413,9 @@ private VideoInfoItem extractVideoInfoItem(Element li) {
418413
if(info.thumbnail_url.contains(".gif")) {
419414
info.thumbnail_url = img.attr("data-thumb");
420415
}
421-
416+
if(info.thumbnail_url.startsWith("//")) {
417+
info.thumbnail_url = "https:" + info.thumbnail_url;
418+
}
422419
return info;
423420
}
424421

0 commit comments

Comments
 (0)