mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	implemented locale-specific formatting of view, like and dislike counts, and video published date
This commit is contained in:
		| @@ -2,6 +2,8 @@ package org.schabi.newpipe; | |||||||
|  |  | ||||||
| import android.graphics.Bitmap; | import android.graphics.Bitmap; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
|  |  | ||||||
|  | import java.util.Date; | ||||||
| import java.util.Vector; | import java.util.Vector; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -33,15 +35,15 @@ public class VideoInfo { | |||||||
|     public Bitmap thumbnail = null; |     public Bitmap thumbnail = null; | ||||||
|     public String webpage_url = ""; |     public String webpage_url = ""; | ||||||
|     public String upload_date = ""; |     public String upload_date = ""; | ||||||
|     public String view_count = ""; |     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 = ""; | ||||||
|     public int duration = -1; |     public int duration = -1; | ||||||
|     public int age_limit = 0; |     public int age_limit = 0; | ||||||
|     public String like_count = ""; |     public int like_count = 0; | ||||||
|     public String dislike_count = ""; |     public int dislike_count = 0; | ||||||
|     public String average_rating = ""; |     public String average_rating = ""; | ||||||
|     public VideoStream[] videoStreams = null; |     public VideoStream[] videoStreams = null; | ||||||
|     public AudioStream[] audioStreams = null; |     public AudioStream[] audioStreams = null; | ||||||
| @@ -64,11 +66,6 @@ public class VideoInfo { | |||||||
|         public String resolution = ""; |         public String resolution = ""; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     protected static void formatNotKnown(int id) { |  | ||||||
|         Log.e(TAG, "format not known: \"" + |  | ||||||
|             Integer.toString(id) + "\". Call the programmers, they messed it up!"); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public static class AudioStream { |     public static class AudioStream { | ||||||
|         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; | ||||||
| @@ -78,7 +75,5 @@ public class VideoInfo { | |||||||
|         public int format = -1; |         public int format = -1; | ||||||
|         public int bandwidth = -1; |         public int bandwidth = -1; | ||||||
|         public int samplingRate = -1; |         public int samplingRate = -1; | ||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -5,6 +5,7 @@ import android.os.Bundle; | |||||||
| import android.preference.PreferenceManager; | import android.preference.PreferenceManager; | ||||||
| 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.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; | ||||||
| @@ -60,6 +61,7 @@ public class VideoItemDetailActivity extends AppCompatActivity { | |||||||
|             // this means the video was called though another app |             // this means the video was called though another app | ||||||
|             if (getIntent().getData() != null) { |             if (getIntent().getData() != null) { | ||||||
|                 videoUrl = getIntent().getData().toString(); |                 videoUrl = getIntent().getData().toString(); | ||||||
|  |                 Log.i(TAG, "video URL passed:\"" + videoUrl + "\""); | ||||||
|                 StreamingService[] serviceList = ServiceList.getServices(); |                 StreamingService[] serviceList = ServiceList.getServices(); | ||||||
|                 Extractor extractor = null; |                 Extractor extractor = null; | ||||||
|                 for (int i = 0; i < serviceList.length; i++) { |                 for (int i = 0; i < serviceList.length; i++) { | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ package org.schabi.newpipe; | |||||||
|  |  | ||||||
| import android.app.Activity; | import android.app.Activity; | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
|  | import android.content.SharedPreferences; | ||||||
| import android.graphics.Bitmap; | import android.graphics.Bitmap; | ||||||
| import android.graphics.BitmapFactory; | import android.graphics.BitmapFactory; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| @@ -29,6 +30,11 @@ import android.widget.TextView; | |||||||
| import android.view.MenuItem; | import android.view.MenuItem; | ||||||
|  |  | ||||||
| import java.net.URL; | import java.net.URL; | ||||||
|  | import java.text.DateFormat; | ||||||
|  | import java.text.NumberFormat; | ||||||
|  | import java.util.Calendar; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.Locale; | ||||||
| import java.util.Vector; | import java.util.Vector; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -216,12 +222,31 @@ public class VideoItemDetailFragment extends Fragment { | |||||||
|                 case VideoInfo.VIDEO_AVAILABLE: { |                 case VideoInfo.VIDEO_AVAILABLE: { | ||||||
|                     videoTitleView.setText(info.title); |                     videoTitleView.setText(info.title); | ||||||
|                     uploaderView.setText(info.uploader); |                     uploaderView.setText(info.uploader); | ||||||
|                     viewCountView.setText(info.view_count |  | ||||||
|  |                     Locale locale = getPreferredLocale(); | ||||||
|  |                     NumberFormat nf = NumberFormat.getInstance(locale); | ||||||
|  |                     String localisedViewCount = nf.format(info.view_count); | ||||||
|  |                     viewCountView.setText(localisedViewCount | ||||||
|                             + " " + activity.getString(R.string.viewSufix)); |                             + " " + activity.getString(R.string.viewSufix)); | ||||||
|                     thumbsUpView.setText(info.like_count); |  | ||||||
|                     thumbsDownView.setText(info.dislike_count); |  | ||||||
|  |                     thumbsUpView.setText(nf.format(info.like_count)); | ||||||
|  |                     thumbsDownView.setText(nf.format(info.dislike_count)); | ||||||
|  |  | ||||||
|  |                     //this is horribly convoluted | ||||||
|  |                     //TODO: find a better way to convert YYYY-MM-DD to a locale-specific date | ||||||
|  |                     //suggestions welcome | ||||||
|  |                     int year  = Integer.parseInt(info.upload_date.substring(0, 4)); | ||||||
|  |                     int month = Integer.parseInt(info.upload_date.substring(5, 7)); | ||||||
|  |                     int date  = Integer.parseInt(info.upload_date.substring(8, 10)); | ||||||
|  |                     Calendar cal = Calendar.getInstance(); | ||||||
|  |                     cal.set(year, month, date); | ||||||
|  |                     Date datum = cal.getTime(); | ||||||
|  |                     DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale); | ||||||
|  |  | ||||||
|  |                     String localisedDate = df.format(datum); | ||||||
|                     uploadDateView.setText( |                     uploadDateView.setText( | ||||||
|                             activity.getString(R.string.uploadDatePrefix) + " " + info.upload_date); |                             activity.getString(R.string.uploadDatePrefix) + " " + localisedDate); | ||||||
|                     descriptionView.setText(Html.fromHtml(info.description)); |                     descriptionView.setText(Html.fromHtml(info.description)); | ||||||
|                     descriptionView.setMovementMethod(LinkMovementMethod.getInstance()); |                     descriptionView.setMovementMethod(LinkMovementMethod.getInstance()); | ||||||
|  |  | ||||||
| @@ -369,6 +394,23 @@ public class VideoItemDetailFragment extends Fragment { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public Locale getPreferredLocale() { | ||||||
|  |         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); | ||||||
|  |         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 | ||||||
|  |         languageCode = sp.getString(languageKey, "en"); | ||||||
|  |  | ||||||
|  |         if(languageCode.length() == 2) { | ||||||
|  |             return new Locale(languageCode); | ||||||
|  |         } | ||||||
|  |         else if(languageCode.contains("_")) { | ||||||
|  |             String country = languageCode | ||||||
|  |                     .substring(languageCode.indexOf("_"), languageCode.length()); | ||||||
|  |             return new Locale(languageCode.substring(0, 2), country); | ||||||
|  |         } | ||||||
|  |         return Locale.getDefault(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     public boolean checkIfLandscape() { |     public boolean checkIfLandscape() { | ||||||
|         DisplayMetrics displayMetrics = new DisplayMetrics(); |         DisplayMetrics displayMetrics = new DisplayMetrics(); | ||||||
|         getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); |         getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); | ||||||
|   | |||||||
| @@ -103,7 +103,7 @@ public class VideoItemListActivity extends AppCompatActivity | |||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
|         setContentView(R.layout.activity_videoitem_list); |         setContentView(R.layout.activity_videoitem_list); | ||||||
|  |  | ||||||
|         //-------- remove this line when multiservice support is implemented ---------- |         //------ todo: remove this line when multiservice support is implemented ------ | ||||||
|         currentStreamingServiceId = ServiceList.getIdOfService("Youtube"); |         currentStreamingServiceId = ServiceList.getIdOfService("Youtube"); | ||||||
|         //----------------------------------------------------------------------------- |         //----------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|   | |||||||
| @@ -133,22 +133,27 @@ public class YoutubeExtractor implements Extractor { | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public String getVideoId(String videoUrl) { |     public String getVideoId(String videoUrl) { | ||||||
|         //https://www.youtube.com/watch?v=laF2D3QyAFQ |         String id = ""; | ||||||
|         String id; |  | ||||||
|         Pattern pat; |         Pattern pat; | ||||||
|  |  | ||||||
|         if(videoUrl.contains("youtube")) { |         if(videoUrl.contains("youtube")) { | ||||||
|             pat = Pattern.compile("youtube\\.com/watch\\?v=([a-zA-Z0-9_]{11})"); |             pat = Pattern.compile("youtube\\.com/watch\\?v=([\\-a-zA-Z0-9_]{11})"); | ||||||
|         } |         } | ||||||
|         else if(videoUrl.contains("youtu.be")) { |         else if(videoUrl.contains("youtu.be")) { | ||||||
|             pat = Pattern.compile("youtu\\.be/([a-zA-Z0-9_]{11})"); |             pat = Pattern.compile("youtu\\.be/([a-zA-Z0-9_-]{11})"); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             Log.e(TAG, "Error could not parse url: " + videoUrl); |             Log.e(TAG, "Error could not parse url: " + videoUrl); | ||||||
|             return ""; |             return ""; | ||||||
|         } |         } | ||||||
|         Matcher mat = pat.matcher(videoUrl); |         Matcher mat = pat.matcher(videoUrl); | ||||||
|  |         boolean foundMatch = mat.find(); | ||||||
|  |         if(foundMatch){ | ||||||
|             id = mat.group(1); |             id = mat.group(1); | ||||||
|         return (id == null ? "" : id); |             Log.i(TAG, "string \""+videoUrl+"\" matches!"); | ||||||
|  |         } | ||||||
|  |         Log.i(TAG, "string \""+videoUrl+"\" does not match."); | ||||||
|  |         return id; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
| @@ -163,7 +168,7 @@ 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]{10,})", siteUrl); |         videoInfo.id = matchGroup1("v=([0-9a-zA-Z_-]{11})", siteUrl); | ||||||
|  |  | ||||||
|         videoInfo.age_limit = 0; |         videoInfo.age_limit = 0; | ||||||
|         videoInfo.webpage_url = siteUrl; |         videoInfo.webpage_url = siteUrl; | ||||||
| @@ -173,7 +178,7 @@ public class YoutubeExtractor implements Extractor { | |||||||
|         //------------------------------------- |         //------------------------------------- | ||||||
|         // extracting form player args |         // extracting form player args | ||||||
|         //------------------------------------- |         //------------------------------------- | ||||||
|         JSONObject playerArgs; |         JSONObject playerArgs = null; | ||||||
|         { |         { | ||||||
|             try { |             try { | ||||||
|                 String jsonString = matchGroup1("ytplayer.config\\s*=\\s*(\\{.*?\\});", site); |                 String jsonString = matchGroup1("ytplayer.config\\s*=\\s*(\\{.*?\\});", site); | ||||||
| @@ -185,8 +190,6 @@ public class YoutubeExtractor implements Extractor { | |||||||
|                 // If we fail in this part the video is most likely not available. |                 // If we fail in this part the video is most likely not available. | ||||||
|                 // Determining why is done later. |                 // Determining why is done later. | ||||||
|                 videoInfo.videoAvailableStatus = VideoInfo.VIDEO_UNAVAILABLE; |                 videoInfo.videoAvailableStatus = VideoInfo.VIDEO_UNAVAILABLE; | ||||||
|                 //exit early, since we can't extract other args |  | ||||||
|                 return videoInfo; |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -277,23 +280,27 @@ public class YoutubeExtractor implements Extractor { | |||||||
|  |  | ||||||
|  |  | ||||||
|         // description |         // description | ||||||
|         videoInfo.description = doc.select("p[id=\"eow-description\"]").first() |         videoInfo.description = doc.select("p[id=\"eow-description\"]").first().html(); | ||||||
|                 .html(); |         String likesString = ""; | ||||||
|  |         String dislikesString = ""; | ||||||
|         try { |         try { | ||||||
|             // likes |             // likes | ||||||
|             videoInfo.like_count = doc.select("span[class=\"like-button-renderer \"]").first() |             likesString = doc.select("button.like-button-renderer-like-button").first() | ||||||
|                     .getAllElements().select("button") |                     .select("span.yt-uix-button-content").first().text(); | ||||||
|                     .select("span").get(0).text(); |             videoInfo.like_count = Integer.parseInt(likesString.replace(",", "")); | ||||||
|  |  | ||||||
|             // dislikes |             // dislikes | ||||||
|             videoInfo.dislike_count = doc.select("span[class=\"like-button-renderer \"]").first() |             dislikesString = doc.select("button.like-button-renderer-dislike-button").first() | ||||||
|                     .getAllElements().select("button") |                             .select("span.yt-uix-button-content").first().text(); | ||||||
|                     .select("span").get(2).text(); |  | ||||||
|  |             videoInfo.dislike_count = Integer.parseInt(dislikesString.replace(",", "")); | ||||||
|  |         } catch(NumberFormatException nfe) { | ||||||
|  |             Log.e(TAG, "failed to parse likesString \""+likesString+"\" and dislikesString \""+ | ||||||
|  |             dislikesString+"\" as integers"); | ||||||
|         } catch(Exception e) { |         } catch(Exception e) { | ||||||
|             // if it fails we know that the video does not offer dislikes. |             // if it fails we know that the video does not offer dislikes. | ||||||
|             videoInfo.like_count = "0"; |             e.printStackTrace(); | ||||||
|             videoInfo.dislike_count = "0"; |             videoInfo.like_count = 0; | ||||||
|  |             videoInfo.dislike_count = 0; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // uploader thumbnail |         // uploader thumbnail | ||||||
| @@ -301,8 +308,9 @@ public class YoutubeExtractor implements Extractor { | |||||||
|                 .select("img").first() |                 .select("img").first() | ||||||
|                 .attr("abs:data-thumb"); |                 .attr("abs:data-thumb"); | ||||||
|  |  | ||||||
|         // view count TODO: format locale-specifically |         // view count TODO:  locale-specific formatting | ||||||
|         videoInfo.view_count = doc.select("meta[itemprop=interactionCount]").attr("content"); |         String viewCountString = doc.select("meta[itemprop=interactionCount]").attr("content"); | ||||||
|  |         videoInfo.view_count = Integer.parseInt(viewCountString); | ||||||
|  |  | ||||||
|         // next video |         // next video | ||||||
|         videoInfo.nextVideo = extractVideoInfoItem(doc.select("div[class=\"watch-sidebar-section\"]").first() |         videoInfo.nextVideo = extractVideoInfoItem(doc.select("div[class=\"watch-sidebar-section\"]").first() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Adam Howard
					Adam Howard