mirror of
https://github.com/TeamNewPipe/NewPipe.git
synced 2024-11-25 12:32:31 +01:00
Refactoring:
* renamed VideoInfoItem to VideoPreviewInfo * moved streaming service-related classes into their own, new package services * added javadoc to some classes and methods (where functionality is known well enough to explain) * De-duplicated common fields between VideoInfo and VideoPreviewInfo by moving them into a common superclass: AbstractVideoInfo * Removed 2 methods which only call super(), and therefore are unnecessary: PlayVideoActivity.onResume() and PlayVideoActivity.onPostCreate(Bundle)
This commit is contained in:
parent
975a3e8103
commit
320a4e2351
15
app/src/main/java/org/schabi/newpipe/AbstractVideoInfo.java
Normal file
15
app/src/main/java/org/schabi/newpipe/AbstractVideoInfo.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
|
||||||
|
/**Common properties between VideoInfo and VideoPreviewInfo.*/
|
||||||
|
public abstract class AbstractVideoInfo {
|
||||||
|
public String id = "";
|
||||||
|
public String title = "";
|
||||||
|
public String uploader = "";
|
||||||
|
public String thumbnail_url = "";
|
||||||
|
public Bitmap thumbnail = null;
|
||||||
|
public String webpage_url = "";
|
||||||
|
public String upload_date = "";
|
||||||
|
public long view_count = 0;
|
||||||
|
}
|
@ -31,6 +31,11 @@ public class Downloader {
|
|||||||
|
|
||||||
private static final String USER_AGENT = "Mozilla/5.0";
|
private static final String USER_AGENT = "Mozilla/5.0";
|
||||||
|
|
||||||
|
/**Download the text file at the supplied URL as in download(String),
|
||||||
|
* but set the HTTP header field "Accept-Language" to the supplied string.
|
||||||
|
* @param siteUrl the URL of the text file to return the contents of
|
||||||
|
* @param language the language (usually a 2-character code) to set as the preferred language
|
||||||
|
* @return the contents of the specified text file*/
|
||||||
public static String download(String siteUrl, String language) {
|
public static String download(String siteUrl, String language) {
|
||||||
String ret = "";
|
String ret = "";
|
||||||
try {
|
try {
|
||||||
@ -44,7 +49,7 @@ public class Downloader {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
/**Common functionality between download(String url) and download(String url, String language)*/
|
||||||
private static String dl(HttpURLConnection con) {
|
private static String dl(HttpURLConnection con) {
|
||||||
StringBuffer response = new StringBuffer();
|
StringBuffer response = new StringBuffer();
|
||||||
|
|
||||||
@ -72,7 +77,10 @@ public class Downloader {
|
|||||||
return response.toString();
|
return response.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Download (via HTTP) the text file located at the supplied URL, and return its contents.
|
||||||
|
* Primarily intended for downloading web pages.
|
||||||
|
* @param siteUrl the URL of the text file to download
|
||||||
|
* @return the contents of the specified text file*/
|
||||||
public static String download(String siteUrl) {
|
public static String download(String siteUrl) {
|
||||||
String ret = "";
|
String ret = "";
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ package org.schabi.newpipe;
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**Static data about various media formats support by Newpipe, eg mime type, extension*/
|
||||||
public enum MediaFormat {
|
public enum MediaFormat {
|
||||||
// id name suffix mime type
|
// id name suffix mime type
|
||||||
MPEG_4 (0x0, "MPEG-4", "mp4", "video/mp4"),
|
MPEG_4 (0x0, "MPEG-4", "mp4", "video/mp4"),
|
||||||
@ -41,6 +43,10 @@ public enum MediaFormat {
|
|||||||
this.mimeType = mimeType;
|
this.mimeType = mimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Return the friendly name of the media format with the supplied id
|
||||||
|
* @param ident the id of the media format. Currently an arbitrary, NewPipe-specific number.
|
||||||
|
* @return the friendly name of the MediaFormat associated with this ids,
|
||||||
|
* or an empty String if none match it.*/
|
||||||
public static String getNameById(int ident) {
|
public static String getNameById(int ident) {
|
||||||
for (MediaFormat vf : MediaFormat.values()) {
|
for (MediaFormat vf : MediaFormat.values()) {
|
||||||
if(vf.id == ident) return vf.name;
|
if(vf.id == ident) return vf.name;
|
||||||
@ -48,6 +54,10 @@ public enum MediaFormat {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Return the file extension of the media format with the supplied id
|
||||||
|
* @param ident the id of the media format. Currently an arbitrary, NewPipe-specific number.
|
||||||
|
* @return the file extension of the MediaFormat associated with this ids,
|
||||||
|
* or an empty String if none match it.*/
|
||||||
public static String getSuffixById(int ident) {
|
public static String getSuffixById(int ident) {
|
||||||
for (MediaFormat vf : MediaFormat.values()) {
|
for (MediaFormat vf : MediaFormat.values()) {
|
||||||
if(vf.id == ident) return vf.suffix;
|
if(vf.id == ident) return vf.suffix;
|
||||||
@ -55,6 +65,10 @@ public enum MediaFormat {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Return the MIME type of the media format with the supplied id
|
||||||
|
* @param ident the id of the media format. Currently an arbitrary, NewPipe-specific number.
|
||||||
|
* @return the MIME type of the MediaFormat associated with this ids,
|
||||||
|
* or an empty String if none match it.*/
|
||||||
public static String getMimeById(int ident) {
|
public static String getMimeById(int ident) {
|
||||||
for (MediaFormat vf : MediaFormat.values()) {
|
for (MediaFormat vf : MediaFormat.values()) {
|
||||||
if(vf.id == ident) return vf.mimeType;
|
if(vf.id == ident) return vf.mimeType;
|
||||||
|
@ -89,6 +89,8 @@ public class PlayVideoActivity extends AppCompatActivity {
|
|||||||
mediaController = new MediaController(this);
|
mediaController = new MediaController(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
position = intent.getIntExtra(START_POSITION, 0)*1000;//convert from seconds to milliseconds
|
||||||
|
|
||||||
videoView = (VideoView) findViewById(R.id.video_view);
|
videoView = (VideoView) findViewById(R.id.video_view);
|
||||||
progressBar = (ProgressBar) findViewById(R.id.play_video_progress_bar);
|
progressBar = (ProgressBar) findViewById(R.id.play_video_progress_bar);
|
||||||
try {
|
try {
|
||||||
@ -146,11 +148,6 @@ public class PlayVideoActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostCreate(Bundle savedInstanceState) {
|
|
||||||
super.onPostCreate(savedInstanceState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreatePanelMenu(int featured, Menu menu) {
|
public boolean onCreatePanelMenu(int featured, Menu menu) {
|
||||||
super.onCreatePanelMenu(featured, menu);
|
super.onCreatePanelMenu(featured, menu);
|
||||||
@ -160,11 +157,6 @@ public class PlayVideoActivity extends AppCompatActivity {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Christian Schabesberger on 26.08.15.
|
* Created by Christian Schabesberger on 26.08.15.
|
||||||
@ -27,16 +23,7 @@ import java.util.Vector;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**Info object for opened videos, ie the video ready to play.*/
|
/**Info object for opened videos, ie the video ready to play.*/
|
||||||
public class VideoInfo {
|
public class VideoInfo extends AbstractVideoInfo {
|
||||||
public String id = "";
|
|
||||||
public String title = "";
|
|
||||||
public String uploader = "";
|
|
||||||
public String thumbnail_url = "";
|
|
||||||
public Bitmap thumbnail = null;
|
|
||||||
public String webpage_url = "";
|
|
||||||
public String upload_date = "";
|
|
||||||
public long view_count = 0;
|
|
||||||
|
|
||||||
public String uploader_thumbnail_url = "";
|
public String uploader_thumbnail_url = "";
|
||||||
public Bitmap uploader_thumbnail = null;
|
public Bitmap uploader_thumbnail = null;
|
||||||
public String description = "";
|
public String description = "";
|
||||||
@ -47,10 +34,10 @@ public class VideoInfo {
|
|||||||
public String average_rating = "";
|
public String average_rating = "";
|
||||||
public VideoStream[] videoStreams = null;
|
public VideoStream[] videoStreams = null;
|
||||||
public AudioStream[] audioStreams = null;
|
public AudioStream[] audioStreams = null;
|
||||||
public VideoInfoItem nextVideo = null;
|
public VideoPreviewInfo nextVideo = null;
|
||||||
public VideoInfoItem[] relatedVideos = null;
|
public VideoPreviewInfo[] relatedVideos = null;
|
||||||
public int videoAvailableStatus = VIDEO_AVAILABLE;
|
public int videoAvailableStatus = VIDEO_AVAILABLE;
|
||||||
public int startPosition = 0;//in seconds
|
//public int startPosition = 0;//in seconds. some metadata is not passed using a VideoInfo object!
|
||||||
|
|
||||||
private static final String TAG = VideoInfo.class.toString();
|
private static final String TAG = VideoInfo.class.toString();
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public class VideoInfoItemViewCreator {
|
|||||||
this.inflater = inflater;
|
this.inflater = inflater;
|
||||||
}
|
}
|
||||||
|
|
||||||
public View getViewByVideoInfoItem(View convertView, ViewGroup parent, VideoInfoItem info) {
|
public View getViewByVideoInfoItem(View convertView, ViewGroup parent, VideoPreviewInfo info) {
|
||||||
ViewHolder holder;
|
ViewHolder holder;
|
||||||
if(convertView == null) {
|
if(convertView == null) {
|
||||||
convertView = inflater.inflate(R.layout.video_item, parent, false);
|
convertView = inflater.inflate(R.layout.video_item, parent, false);
|
||||||
@ -62,7 +62,7 @@ public class VideoInfoItemViewCreator {
|
|||||||
holder.itemUploadDateView.setText(info.upload_date);
|
holder.itemUploadDateView.setText(info.upload_date);
|
||||||
} else {
|
} else {
|
||||||
//tweak if necessary: This is a hack to prevent having white space in the layout :P
|
//tweak if necessary: This is a hack to prevent having white space in the layout :P
|
||||||
holder.itemUploadDateView.setText(info.view_count);
|
holder.itemUploadDateView.setText(""+info.view_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
return convertView;
|
return convertView;
|
||||||
|
@ -7,10 +7,13 @@ import android.support.v4.app.NavUtils;
|
|||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.services.Extractor;
|
||||||
|
import org.schabi.newpipe.services.ServiceList;
|
||||||
|
import org.schabi.newpipe.services.StreamingService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||||
@ -81,7 +84,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
|||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
arguments.putString(VideoItemDetailFragment.VIDEO_URL,
|
arguments.putString(VideoItemDetailFragment.VIDEO_URL,
|
||||||
extractor.getVideoUrl(extractor.getVideoId(videoUrl)));
|
extractor.getVideoUrl(extractor.getVideoId(videoUrl)));//cleans URL
|
||||||
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY,
|
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY,
|
||||||
PreferenceManager.getDefaultSharedPreferences(this)
|
PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
.getBoolean(getString(R.string.autoPlayThroughIntent), false));
|
.getBoolean(getString(R.string.autoPlayThroughIntent), false));
|
||||||
|
@ -37,6 +37,10 @@ import java.util.Date;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.services.Extractor;
|
||||||
|
import org.schabi.newpipe.services.ServiceList;
|
||||||
|
import org.schabi.newpipe.services.StreamingService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||||
@ -394,10 +398,12 @@ public class VideoItemDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Returns the java.util.Locale object which corresponds to the locale set in NewPipe's preferences.
|
||||||
|
* Currently not affected by the device's locale.*/
|
||||||
public Locale getPreferredLocale() {
|
public Locale getPreferredLocale() {
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
String languageKey = getContext().getString(R.string.searchLanguage);
|
String languageKey = getContext().getString(R.string.searchLanguage);
|
||||||
String languageCode = "en";//i know the following lines defaults languageCode to "en", but java is picky about uninitialised values
|
String languageCode = "en";//i know the following line defaults languageCode to "en", but java is picky about uninitialised values
|
||||||
languageCode = sp.getString(languageKey, "en");
|
languageCode = sp.getString(languageKey, "en");
|
||||||
|
|
||||||
if(languageCode.length() == 2) {
|
if(languageCode.length() == 2) {
|
||||||
|
@ -3,21 +3,18 @@ package org.schabi.newpipe;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.SearchView;
|
import android.support.v7.widget.SearchView;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
|
import org.schabi.newpipe.services.ServiceList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||||
@ -116,7 +113,7 @@ public class VideoItemListActivity extends AppCompatActivity
|
|||||||
|
|
||||||
if(arguments != null) {
|
if(arguments != null) {
|
||||||
//Parcelable[] p = arguments.getParcelableArray(VIDEO_INFO_ITEMS);
|
//Parcelable[] p = arguments.getParcelableArray(VIDEO_INFO_ITEMS);
|
||||||
ArrayList<VideoInfoItem> p = arguments.getParcelableArrayList(VIDEO_INFO_ITEMS);
|
ArrayList<VideoPreviewInfo> p = arguments.getParcelableArrayList(VIDEO_INFO_ITEMS);
|
||||||
if(p != null) {
|
if(p != null) {
|
||||||
mode = PRESENT_VIDEOS_MODE;
|
mode = PRESENT_VIDEOS_MODE;
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
@ -15,10 +15,12 @@ import android.widget.ListView;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.services.SearchEngine;
|
||||||
|
import org.schabi.newpipe.services.StreamingService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||||
@ -119,9 +121,9 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
Handler h = new Handler();
|
Handler h = new Handler();
|
||||||
private volatile boolean run = true;
|
private volatile boolean run = true;
|
||||||
private int requestId;
|
private int requestId;
|
||||||
public LoadThumbsRunnable(Vector<VideoInfoItem> videoList,
|
public LoadThumbsRunnable(Vector<VideoPreviewInfo> videoList,
|
||||||
Vector<Boolean> downloadedList, int requestId) {
|
Vector<Boolean> downloadedList, int requestId) {
|
||||||
for(VideoInfoItem item : videoList) {
|
for(VideoPreviewInfo item : videoList) {
|
||||||
thumbnailUrlList.add(item.thumbnail_url);
|
thumbnailUrlList.add(item.thumbnail_url);
|
||||||
}
|
}
|
||||||
this.downloadedList = downloadedList;
|
this.downloadedList = downloadedList;
|
||||||
@ -168,7 +170,7 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void present(List<VideoInfoItem> videoList) {
|
public void present(List<VideoPreviewInfo> videoList) {
|
||||||
mode = PRESENT_VIDEOS_MODE;
|
mode = PRESENT_VIDEOS_MODE;
|
||||||
setListShown(true);
|
setListShown(true);
|
||||||
getListView().smoothScrollToPosition(0);
|
getListView().smoothScrollToPosition(0);
|
||||||
@ -220,7 +222,7 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateList(List<VideoInfoItem> list) {
|
private void updateList(List<VideoPreviewInfo> list) {
|
||||||
try {
|
try {
|
||||||
videoListAdapter.addVideoList(list);
|
videoListAdapter.addVideoList(list);
|
||||||
terminateThreads();
|
terminateThreads();
|
||||||
|
@ -37,7 +37,7 @@ public class VideoListAdapter extends BaseAdapter {
|
|||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
private VideoInfoItemViewCreator viewCreator;
|
private VideoInfoItemViewCreator viewCreator;
|
||||||
private Vector<VideoInfoItem> videoList = new Vector<>();
|
private Vector<VideoPreviewInfo> videoList = new Vector<>();
|
||||||
private Vector<Boolean> downloadedThumbnailList = new Vector<>();
|
private Vector<Boolean> downloadedThumbnailList = new Vector<>();
|
||||||
VideoItemListFragment videoListFragment;
|
VideoItemListFragment videoListFragment;
|
||||||
ListView listView;
|
ListView listView;
|
||||||
@ -49,7 +49,7 @@ public class VideoListAdapter extends BaseAdapter {
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addVideoList(List<VideoInfoItem> videos) {
|
public void addVideoList(List<VideoPreviewInfo> videos) {
|
||||||
videoList.addAll(videos);
|
videoList.addAll(videos);
|
||||||
for(int i = 0; i < videos.size(); i++) {
|
for(int i = 0; i < videos.size(); i++) {
|
||||||
downloadedThumbnailList.add(false);
|
downloadedThumbnailList.add(false);
|
||||||
@ -63,7 +63,7 @@ public class VideoListAdapter extends BaseAdapter {
|
|||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector<VideoInfoItem> getVideoList() {
|
public Vector<VideoPreviewInfo> getVideoList() {
|
||||||
return videoList;
|
return videoList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import android.os.Parcelable;
|
|||||||
* Created by Christian Schabesberger on 26.08.15.
|
* Created by Christian Schabesberger on 26.08.15.
|
||||||
*
|
*
|
||||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||||
* VideoInfoItem.java is part of NewPipe.
|
* VideoPreviewInfo.java is part of NewPipe.
|
||||||
*
|
*
|
||||||
* NewPipe is free software: you can redistribute it and/or modify
|
* NewPipe is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -25,19 +25,12 @@ import android.os.Parcelable;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**Info object for previews of unopened videos, eg search results, related videos*/
|
/**Info object for previews of unopened videos, eg search results, related videos*/
|
||||||
public class VideoInfoItem implements Parcelable {
|
public class VideoPreviewInfo extends AbstractVideoInfo implements Parcelable {
|
||||||
public String id = "";
|
|
||||||
public String title = "";
|
|
||||||
public String uploader = "";
|
|
||||||
public String thumbnail_url = "";
|
|
||||||
public Bitmap thumbnail = null;
|
|
||||||
public String webpage_url = "";
|
|
||||||
public String upload_date = "";
|
|
||||||
public String view_count = "";
|
|
||||||
|
|
||||||
public String duration = "";
|
public String duration = "";
|
||||||
|
|
||||||
protected VideoInfoItem(Parcel in) {
|
protected VideoPreviewInfo(Parcel in) {
|
||||||
id = in.readString();
|
id = in.readString();
|
||||||
title = in.readString();
|
title = in.readString();
|
||||||
uploader = in.readString();
|
uploader = in.readString();
|
||||||
@ -46,10 +39,10 @@ public class VideoInfoItem implements Parcelable {
|
|||||||
thumbnail = (Bitmap) in.readValue(Bitmap.class.getClassLoader());
|
thumbnail = (Bitmap) in.readValue(Bitmap.class.getClassLoader());
|
||||||
webpage_url = in.readString();
|
webpage_url = in.readString();
|
||||||
upload_date = in.readString();
|
upload_date = in.readString();
|
||||||
view_count = in.readString();
|
view_count = in.readLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
public VideoInfoItem() {
|
public VideoPreviewInfo() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,19 +61,19 @@ public class VideoInfoItem implements Parcelable {
|
|||||||
dest.writeValue(thumbnail);
|
dest.writeValue(thumbnail);
|
||||||
dest.writeString(webpage_url);
|
dest.writeString(webpage_url);
|
||||||
dest.writeString(upload_date);
|
dest.writeString(upload_date);
|
||||||
dest.writeString(view_count);
|
dest.writeLong(view_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static final Parcelable.Creator<VideoInfoItem> CREATOR = new Parcelable.Creator<VideoInfoItem>() {
|
public static final Parcelable.Creator<VideoPreviewInfo> CREATOR = new Parcelable.Creator<VideoPreviewInfo>() {
|
||||||
@Override
|
@Override
|
||||||
public VideoInfoItem createFromParcel(Parcel in) {
|
public VideoPreviewInfo createFromParcel(Parcel in) {
|
||||||
return new VideoInfoItem(in);
|
return new VideoPreviewInfo(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VideoInfoItem[] newArray(int size) {
|
public VideoPreviewInfo[] newArray(int size) {
|
||||||
return new VideoInfoItem[size];
|
return new VideoPreviewInfo[size];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe.services;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Christian Schabesberger on 10.08.15.
|
* Created by Christian Schabesberger on 10.08.15.
|
||||||
@ -20,7 +20,9 @@ package org.schabi.newpipe;
|
|||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.schabi.newpipe.VideoInfo;
|
||||||
|
|
||||||
|
/**Scrapes information from a video streaming service (eg, YouTube). To implement*/
|
||||||
public interface Extractor {
|
public interface Extractor {
|
||||||
VideoInfo getVideoInfo(String siteUrl);
|
VideoInfo getVideoInfo(String siteUrl);
|
||||||
String getVideoUrl(String videoId);
|
String getVideoUrl(String videoId);
|
@ -1,4 +1,6 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe.services;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.VideoPreviewInfo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
@ -29,7 +31,7 @@ public interface SearchEngine {
|
|||||||
class Result {
|
class Result {
|
||||||
public String errorMessage = "";
|
public String errorMessage = "";
|
||||||
public String suggestion = "";
|
public String suggestion = "";
|
||||||
public Vector<VideoInfoItem> resultList = new Vector<>();
|
public Vector<VideoPreviewInfo> resultList = new Vector<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<String> suggestionList(String query);
|
ArrayList<String> suggestionList(String query);
|
@ -1,8 +1,8 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe.services;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.schabi.newpipe.youtube.YoutubeService;
|
import org.schabi.newpipe.services.youtube.YoutubeService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Christian Schabesberger on 23.08.15.
|
* Created by Christian Schabesberger on 23.08.15.
|
||||||
@ -24,6 +24,8 @@ import org.schabi.newpipe.youtube.YoutubeService;
|
|||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**Provides access to the video streaming services supported by NewPipe.
|
||||||
|
* Currently only Youtube until the API becomes more stable.*/
|
||||||
public class ServiceList {
|
public class ServiceList {
|
||||||
private static final String TAG = ServiceList.class.toString();
|
private static final String TAG = ServiceList.class.toString();
|
||||||
private static final StreamingService[] services = {
|
private static final StreamingService[] services = {
|
@ -1,4 +1,4 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe.services;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Christian Schabesberger on 23.08.15.
|
* Created by Christian Schabesberger on 23.08.15.
|
@ -1,4 +1,4 @@
|
|||||||
package org.schabi.newpipe.youtube;
|
package org.schabi.newpipe.services.youtube;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Xml;
|
import android.util.Xml;
|
||||||
@ -12,14 +12,13 @@ import org.mozilla.javascript.Context;
|
|||||||
import org.mozilla.javascript.Function;
|
import org.mozilla.javascript.Function;
|
||||||
import org.mozilla.javascript.ScriptableObject;
|
import org.mozilla.javascript.ScriptableObject;
|
||||||
import org.schabi.newpipe.Downloader;
|
import org.schabi.newpipe.Downloader;
|
||||||
import org.schabi.newpipe.Extractor;
|
import org.schabi.newpipe.services.Extractor;
|
||||||
import org.schabi.newpipe.MediaFormat;
|
import org.schabi.newpipe.MediaFormat;
|
||||||
import org.schabi.newpipe.VideoInfo;
|
import org.schabi.newpipe.VideoInfo;
|
||||||
import org.schabi.newpipe.VideoInfoItem;
|
import org.schabi.newpipe.VideoPreviewInfo;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -161,6 +160,29 @@ public class YoutubeExtractor implements Extractor {
|
|||||||
return "https://www.youtube.com/watch?v=" + videoId;
|
return "https://www.youtube.com/watch?v=" + videoId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getStartPosition(String siteUrl){
|
||||||
|
String timeStamp = matchGroup1("((#|&)t=\\d{0,3}h?\\d{0,3}m?\\d{1,3}s?)", siteUrl);
|
||||||
|
Log.i(TAG, "time stamp:"+timeStamp);
|
||||||
|
//videoInfo.startPosition
|
||||||
|
|
||||||
|
//TODO: test this!
|
||||||
|
if(timeStamp.length() > 0) {
|
||||||
|
String secondsString = matchGroup1("(\\d{1,3})s", timeStamp);
|
||||||
|
if(secondsString.length() == 0)//try again with unspecified units as seconds
|
||||||
|
secondsString = matchGroup1("t=(\\d{1,3})", timeStamp);
|
||||||
|
String minutesString = matchGroup1("(\\d{1,3})m", timeStamp);
|
||||||
|
String hoursString = matchGroup1("(\\d{1,3})h", timeStamp);
|
||||||
|
|
||||||
|
int seconds = (secondsString.length() > 0 ? Integer.parseInt(secondsString) : 0);
|
||||||
|
int minutes = (minutesString.length() > 0 ? Integer.parseInt(minutesString) : 0);
|
||||||
|
int hours = (hoursString.length() > 0 ? Integer.parseInt(hoursString) : 0);
|
||||||
|
|
||||||
|
return seconds + (60*minutes) + (3600*hours);//don't trust BODMAS!
|
||||||
|
//the ordering varies internationally
|
||||||
|
}//else, return default 0
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VideoInfo getVideoInfo(String siteUrl) {
|
public VideoInfo getVideoInfo(String siteUrl) {
|
||||||
String site = Downloader.download(siteUrl);
|
String site = Downloader.download(siteUrl);
|
||||||
@ -169,23 +191,6 @@ public class YoutubeExtractor implements Extractor {
|
|||||||
Document doc = Jsoup.parse(site, siteUrl);
|
Document doc = Jsoup.parse(site, siteUrl);
|
||||||
|
|
||||||
videoInfo.id = matchGroup1("v=([0-9a-zA-Z_-]{11})", siteUrl);
|
videoInfo.id = matchGroup1("v=([0-9a-zA-Z_-]{11})", siteUrl);
|
||||||
String timeStamp = matchGroup1("((#|&)t=\\d{0,3}h?\\d{0,3}m?\\d{1,3}s)", siteUrl);
|
|
||||||
Log.i(TAG, "time stamp:"+timeStamp);
|
|
||||||
//videoInfo.startPosition
|
|
||||||
|
|
||||||
//TODO: test this!
|
|
||||||
if(timeStamp.length() > 0) {
|
|
||||||
String secondsString = matchGroup1("(\\d{1,3})s", timeStamp);
|
|
||||||
String minutesString = matchGroup1("(\\d{1,3})m", timeStamp);
|
|
||||||
String hoursString = matchGroup1("(\\d{1,3})h", timeStamp);
|
|
||||||
|
|
||||||
int seconds = (secondsString.length() > 0 ? Integer.parseInt(secondsString) : 0);
|
|
||||||
int minutes = (minutesString.length() > 0 ? Integer.parseInt(minutesString) : 0);
|
|
||||||
int hours = (hoursString.length() > 0 ? Integer.parseInt(hoursString) : 0);
|
|
||||||
|
|
||||||
videoInfo.startPosition = seconds + (60*minutes) + (3600*hours);//don't trust BODMAS!
|
|
||||||
//the ordering varies internationally
|
|
||||||
}//else, leave videoInfo.startPosition as default 0
|
|
||||||
|
|
||||||
videoInfo.age_limit = 0;
|
videoInfo.age_limit = 0;
|
||||||
videoInfo.webpage_url = siteUrl;
|
videoInfo.webpage_url = siteUrl;
|
||||||
@ -334,14 +339,14 @@ public class YoutubeExtractor implements Extractor {
|
|||||||
.select("li").first());
|
.select("li").first());
|
||||||
|
|
||||||
// related videos
|
// related videos
|
||||||
Vector<VideoInfoItem> relatedVideos = new Vector<>();
|
Vector<VideoPreviewInfo> relatedVideos = new Vector<>();
|
||||||
for(Element li : doc.select("ul[id=\"watch-related\"]").first().children()) {
|
for(Element li : doc.select("ul[id=\"watch-related\"]").first().children()) {
|
||||||
// first check if we have a playlist. If so leave them out
|
// first check if we have a playlist. If so leave them out
|
||||||
if(li.select("a[class*=\"content-link\"]").first() != null) {
|
if(li.select("a[class*=\"content-link\"]").first() != null) {
|
||||||
relatedVideos.add(extractVideoInfoItem(li));
|
relatedVideos.add(extractVideoInfoItem(li));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
videoInfo.relatedVideos = relatedVideos.toArray(new VideoInfoItem[relatedVideos.size()]);
|
videoInfo.relatedVideos = relatedVideos.toArray(new VideoPreviewInfo[relatedVideos.size()]);
|
||||||
return videoInfo;
|
return videoInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,8 +414,8 @@ public class YoutubeExtractor implements Extractor {
|
|||||||
return audioStreams.toArray(new VideoInfo.AudioStream[audioStreams.size()]);
|
return audioStreams.toArray(new VideoInfo.AudioStream[audioStreams.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private VideoInfoItem extractVideoInfoItem(Element li) {
|
private VideoPreviewInfo extractVideoInfoItem(Element li) {
|
||||||
VideoInfoItem info = new VideoInfoItem();
|
VideoPreviewInfo info = new VideoPreviewInfo();
|
||||||
info.webpage_url = li.select("a[class*=\"content-link\"]").first()
|
info.webpage_url = li.select("a[class*=\"content-link\"]").first()
|
||||||
.attr("abs:href");
|
.attr("abs:href");
|
||||||
try {
|
try {
|
||||||
@ -421,13 +426,13 @@ public class YoutubeExtractor implements Extractor {
|
|||||||
|
|
||||||
//todo: check NullPointerException causing
|
//todo: check NullPointerException causing
|
||||||
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.view_count = Long.parseLong(li.select("span[class*=\"view-count\"]").first().text());
|
||||||
info.uploader = li.select("span[class=\"g-hovercard\"]").first().text();
|
info.uploader = li.select("span[class=\"g-hovercard\"]").first().text();
|
||||||
info.duration = li.select("span[class=\"video-time\"]").first().text();
|
info.duration = li.select("span[class=\"video-time\"]").first().text();
|
||||||
|
|
||||||
Element img = li.select("img").first();
|
Element img = li.select("img").first();
|
||||||
info.thumbnail_url = img.attr("abs:src");
|
info.thumbnail_url = img.attr("abs:src");
|
||||||
// Sometimes youtube sends links to gif files which somehow sesm to not exist
|
// Sometimes youtube sends links to gif files which somehow seem to not exist
|
||||||
// anymore. Items with such gif also offer a secondary image source. So we are going
|
// anymore. Items with such gif also offer a secondary image source. So we are going
|
||||||
// to use that if we caught such an item.
|
// to use that if we caught such an item.
|
||||||
if(info.thumbnail_url.contains(".gif")) {
|
if(info.thumbnail_url.contains(".gif")) {
|
@ -1,4 +1,4 @@
|
|||||||
package org.schabi.newpipe.youtube;
|
package org.schabi.newpipe.services.youtube;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -7,8 +7,8 @@ import org.jsoup.Jsoup;
|
|||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
import org.jsoup.nodes.Element;
|
import org.jsoup.nodes.Element;
|
||||||
import org.schabi.newpipe.Downloader;
|
import org.schabi.newpipe.Downloader;
|
||||||
import org.schabi.newpipe.SearchEngine;
|
import org.schabi.newpipe.services.SearchEngine;
|
||||||
import org.schabi.newpipe.VideoInfoItem;
|
import org.schabi.newpipe.VideoPreviewInfo;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
@ -101,7 +101,7 @@ public class YoutubeSearchEngine implements SearchEngine {
|
|||||||
|
|
||||||
// video item type
|
// video item type
|
||||||
} else if(!((el = item.select("div[class*=\"yt-lockup-video\"").first()) == null)) {
|
} else if(!((el = item.select("div[class*=\"yt-lockup-video\"").first()) == null)) {
|
||||||
VideoInfoItem resultItem = new VideoInfoItem();
|
VideoPreviewInfo resultItem = new VideoPreviewInfo();
|
||||||
Element dl = el.select("h3").first().select("a").first();
|
Element dl = el.select("h3").first().select("a").first();
|
||||||
resultItem.webpage_url = dl.attr("abs:href");
|
resultItem.webpage_url = dl.attr("abs:href");
|
||||||
try {
|
try {
|
@ -1,8 +1,8 @@
|
|||||||
package org.schabi.newpipe.youtube;
|
package org.schabi.newpipe.services.youtube;
|
||||||
|
|
||||||
import org.schabi.newpipe.StreamingService;
|
import org.schabi.newpipe.services.StreamingService;
|
||||||
import org.schabi.newpipe.Extractor;
|
import org.schabi.newpipe.services.Extractor;
|
||||||
import org.schabi.newpipe.SearchEngine;
|
import org.schabi.newpipe.services.SearchEngine;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
Loading…
Reference in New Issue
Block a user