1
mirror of https://github.com/TeamNewPipe/NewPipe synced 2025-09-20 23:00:50 +02:00

Compare commits

...

154 Commits

Author SHA1 Message Date
Weblate
794ae4c5da Merge remote-tracking branch 'origin/master' 2016-03-13 22:38:50 +01:00
Mladen Pejaković
060e744924 Translated using Weblate (Serbian)
Currently translated at 98.1% (105 of 107 strings)
2016-03-13 22:38:50 +01:00
Christian Schabesberger
de62ed772f Merge branch 'master' of https://github.com/kamadi/NewPipe into kamadi-master 2016-03-13 22:36:33 +01:00
Christian Schabesberger
6a8c4a65c5 Merge pull request #237 from DevFactory/release/general-code-quality-fix-2
General code quality fix-2
2016-03-13 22:30:24 +01:00
Christian Schabesberger
03738aeb27 merged my changes with them of rrooij 2016-03-13 22:22:18 +01:00
Weblate
243cb8569e Merge remote-tracking branch 'origin/master' 2016-03-13 02:59:46 +01:00
Mladen Pejaković
1bd660fbbe Translated using Weblate (Serbian)
Currently translated at 98.1% (104 of 106 strings)
2016-03-13 02:59:46 +01:00
Christian Schabesberger
fec80b39f0 Merge pull request #238 from rrooij/yt_streampreviewextractor
Move YoutubeStreamPreviewInfoExtractor to separate class
2016-03-13 02:59:43 +01:00
rrooij
21768432c8 Move YoutubeStreamPreviewInfoExtractor to separate class
The class should be separate because channel support in the future would require video preview extraction too, which doesn't differ much from the extraction done from the search results.
2016-03-12 18:15:20 +01:00
Benedikt Freisen
e9b900ff28 Translated using Weblate (German)
Currently translated at 100.0% (106 of 106 strings)
2016-03-12 11:59:04 +01:00
naofum
c57cb8fec1 Translated using Weblate (Japanese)
Currently translated at 100.0% (106 of 106 strings)
2016-03-12 06:28:19 +01:00
Matej U
247681e3ef Translated using Weblate (Slovenian)
Currently translated at 100.0% (106 of 106 strings)
2016-03-11 23:46:28 +01:00
Faisal Hameed
2f9142419a Fixing squid:S1155, squid:S2293, squid:S1488 2016-03-12 02:01:47 +05:00
Christian Schabesberger
b84eb3df7f made stream type part of abstractVideoinfo 2016-03-11 16:20:02 +01:00
Christian Schabesberger
4058ec2ee9 fixed another livestream related issue 2016-03-11 15:43:50 +01:00
Christian Schabesberger
23a9061871 changed autoplay text 2016-03-11 15:10:13 +01:00
Weblate
9e95ca10b2 Merge remote-tracking branch 'origin/master' 2016-03-11 15:07:20 +01:00
Christian Schabesberger
4c0809d3d3 Translated using Weblate (German)
Currently translated at 100.0% (104 of 104 strings)
2016-03-11 15:07:20 +01:00
Christian Schabesberger
d43365f6e6 add custom error report function 2016-03-11 14:56:41 +01:00
Christian Schabesberger
c6ccc2b20d Merge pull request #232 from DevFactory/release/null-pointer-should-not-be-dereferenced-fix-1
Code quality fix - Null pointers should not be dereferenced.
2016-03-11 14:15:41 +01:00
Christian Schabesberger
31dd68be1d Merge pull request #233 from DevFactory/release/useless-parentheses-should-be-removed-fix-1
Code quality fix - Useless parentheses around expressions should be removed to prevent any misunderstanding.
2016-03-11 14:14:29 +01:00
Christian Schabesberger
1c94620c06 Merge pull request #234 from DevFactory/release/variable-should-comply-with-naming-conventions-fix-1
Code quality fix - Local variable and method parameter names should comply with a naming convention.
2016-03-11 14:13:51 +01:00
Weblate
82d214faa6 Merge remote-tracking branch 'origin/master' 2016-03-11 14:12:50 +01:00
Sérgio Marques
04b2e3689c Translated using Weblate (Portuguese)
Currently translated at 100.0% (104 of 104 strings)
2016-03-11 14:12:50 +01:00
Benedikt Volkmer
f00b8a3941 Translated using Weblate (German)
Currently translated at 100.0% (104 of 104 strings)
2016-03-11 14:12:49 +01:00
Henk de Vries
390cc9cfc9 Translated using Weblate (Dutch)
Currently translated at 95.1% (99 of 104 strings)
2016-03-11 14:12:49 +01:00
Christian Schabesberger
8259872e2d Merge pull request #235 from DevFactory/release/utility-classes-should-not-have-public-constructors-fix-1
Code quality fix - Utility classes should not have public constructors.
2016-03-11 14:12:45 +01:00
Faisal Hameed
1a3aaf86ee Fixing squid:S2259- Null pointers should not be dereferenced. 2016-03-10 15:07:23 +05:00
Faisal Hameed
cade4f932d Fixing squid:S00117- Local variable and method parameter names should comply with a naming convention. 2016-03-10 15:01:38 +05:00
Faisal Hameed
eb060602cd Fixing squid:S1118 - Utility classes should not have public constructors. 2016-03-10 14:50:42 +05:00
Faisal Hameed
805f046696 Fixing squid:UselessParenthesesCheck - Useless parentheses around expressions should be removed to prevent any misunderstanding. 2016-03-10 14:41:12 +05:00
Matej U
35e11e43de Translated using Weblate (Slovenian)
Currently translated at 100.0% (104 of 104 strings)
2016-03-08 21:22:44 +01:00
Mohamad Hasan Al Banna
ba15c6dc60 Translated using Weblate (Indonesian)
Currently translated at 100% (0 of 0 strings)

Created new translation.
2016-03-08 16:29:26 +01:00
Christian Schabesberger
569c227a99 try to give gradle more memory for CI build 2016-03-08 02:43:00 +01:00
Christian Schabesberger
8fd7599158 Merge branch 'master' of github.com:theScrabi/NewPipe 2016-03-08 02:22:35 +01:00
Christian Schabesberger
19418e5dfb fixed another parsing but related to livestreams 2016-03-08 02:22:23 +01:00
Christian Schabesberger
f90a163ede add --info to buildscript 2016-03-08 01:25:07 +01:00
Christian Schabesberger
8fb1fd3602 fixed image loading bug 2016-03-08 01:24:45 +01:00
Christian Schabesberger
0dbf2a347f moved on to version 0.7.7 2016-03-08 01:10:33 +01:00
Christian Schabesberger
38742fd5e8 fixed values-iw build failure 2016-03-08 01:09:39 +01:00
Weblate
67ce7e0979 Merge remote-tracking branch 'origin/master' 2016-03-08 01:06:49 +01:00
Benedikt Freisen
21a7e52f9a Translated using Weblate (German)
Currently translated at 99.0% (103 of 104 strings)
2016-03-08 01:06:49 +01:00
Christian Schabesberger
fcb445a381 removed --stacktrace form CI buildscript 2016-03-08 01:02:01 +01:00
Christian Schabesberger
f6450d4b4d removed not or almost not existing translations 2016-03-07 19:15:01 +01:00
Christian Schabesberger
a01d1b89b6 Merge branch 'master' of github.com:theScrabi/NewPipe 2016-03-07 18:51:51 +01:00
Christian Schabesberger
0c9b6582cc made CI script print stack trace 2016-03-07 18:51:43 +01:00
Christian Schabesberger
2d47daabf8 add xxxhdpi app icon 2016-03-07 15:03:26 +01:00
Weblate
ce20cbe435 Merge remote-tracking branch 'origin/master' 2016-03-07 15:00:43 +01:00
Matej U
99e5415bfc Translated using Weblate (Slovenian)
Currently translated at 87.5% (91 of 104 strings)
2016-03-07 15:00:42 +01:00
madiyar
b2d935dd6d Restoring search query after orientation change in two pane mode 2016-03-07 13:05:05 +06:00
madiyar
eb66cc5db8 Restoring search query after orientation change 2016-03-07 12:58:48 +06:00
naofum
6d6b8363a8 Translated using Weblate (Japanese)
Currently translated at 100.0% (104 of 104 strings)
2016-03-06 12:19:11 +01:00
Mladen Pejaković
bf79b02e15 Translated using Weblate (Serbian)
Currently translated at 100.0% (104 of 104 strings)
2016-03-05 18:57:47 +01:00
Christian Schabesberger
3ce7eda3eb made newpipe handle not available like/dislike count 2016-03-05 18:35:28 +01:00
Christian Schabesberger
378e6b6547 fixed fix portrait view 2016-03-05 17:49:11 +01:00
Christian Schabesberger
f63b35e2c0 fixed search error 2016-03-05 17:35:57 +01:00
Christian Schabesberger
9a480cbe3e fixed backarrow on player_activity 2016-03-05 17:16:28 +01:00
Christian Schabesberger
76ca937bb8 set tor into experimental state 2016-03-05 17:04:37 +01:00
Christian Schabesberger
8a29567572 merge addExoplayer 2016-03-05 16:54:24 +01:00
Christian Schabesberger
839cd7d1c7 some small fixes 2016-03-05 16:24:47 +01:00
Christian Schabesberger
0bfc7a9177 Merge branch 'master' of github.com:theScrabi/NewPipe 2016-03-05 16:15:00 +01:00
Christian Schabesberger
26e11f96e0 add streamtype field 2016-03-04 15:18:04 +01:00
Christian Schabesberger
86c36acedc removed android code from extractor side 2016-03-04 14:25:37 +01:00
Christian Schabesberger
2318ad2bde changed viewcount notation 2016-03-04 14:16:02 +01:00
Christian Schabesberger
9548dfabd6 made service list do propper error handling 2016-03-04 14:10:41 +01:00
Christian Schabesberger
0c716c12d7 fixed viewcount test again 2016-03-04 13:51:50 +01:00
Weblate
08dd176753 Merge remote-tracking branch 'origin/master' 2016-03-04 13:49:06 +01:00
Thejesh GN
07086bfb3e Translated using Weblate (Kannada)
Currently translated at 30.5% (26 of 85 strings)
2016-03-04 13:49:06 +01:00
Christian Schabesberger
b1d2e64450 ad service_id field, and pulled video/audio stream out of streaminfo 2016-03-04 13:45:41 +01:00
Christian Schabesberger
d9cd928100 fixed audio settings changed bug 2016-03-02 23:23:52 +01:00
naofum
37ec26c8fd Translated using Weblate (Japanese)
Currently translated at 100.0% (85 of 85 strings)
2016-03-02 13:05:54 +01:00
Christian Schabesberger
68b7d9cdff made duration an integer, and made youtubesearch engine throw more parsingexceptions 2016-03-02 02:36:45 +01:00
Christian Schabesberger
3aecd15916 Merge branch 'advancedErrorHandling' 2016-03-02 00:29:56 +01:00
Christian Schabesberger
97d76aee18 fixed failing unit test 2016-03-01 23:54:26 +01:00
Christian Schabesberger
781bf8e7ec fixed yet another bug 2016-03-01 23:28:22 +01:00
Christian Schabesberger
77b9457707 add error handling to suggestions 2016-03-01 18:43:36 +01:00
Christian Schabesberger
1210ab0de0 changed color of snackbar action text 2016-02-29 21:22:16 +01:00
Christian Schabesberger
3c93c4714e fixed crash during crash report 2016-02-29 21:13:02 +01:00
Christian Schabesberger
f90a1ede70 fixed some more bugs 2016-02-29 21:06:00 +01:00
Christian Schabesberger
028354b283 fixed some bugs 2016-02-29 20:33:28 +01:00
Christian Schabesberger
18493a578d made error message be displayed inside erroractivity 2016-02-29 19:23:01 +01:00
Christian Schabesberger
1829dc79c8 make erroractivity handle search engine exceptions 2016-02-29 19:02:40 +01:00
Weblate
7575e8fbe3 Merge remote-tracking branch 'origin/master' 2016-02-29 16:16:54 +01:00
Christian Schabesberger
eed9915c12 add missing gpl3 header to SuggestionListAdapter 2016-02-29 16:19:34 +01:00
Filip Sebastian
be71e45954 Translated using Weblate (Romanian)
Currently translated at 100.0% (72 of 72 strings)
2016-02-29 16:16:54 +01:00
Kamil Modzelewski
3a7978eca0 Translated using Weblate (Polish)
Currently translated at 54.1% (39 of 72 strings)
2016-02-29 16:16:53 +01:00
naofum
c37d2250d4 Translated using Weblate (Japanese)
Currently translated at 100.0% (72 of 72 strings)
2016-02-29 16:16:53 +01:00
Benedikt Freisen
45819d1cd4 Translated using Weblate (German)
Currently translated at 98.6% (71 of 72 strings)
2016-02-29 16:16:53 +01:00
Christian Schabesberger
4ac36af40c made extractor not throw exception upon missing dash mpd 2016-02-29 16:15:15 +01:00
Christian Schabesberger
1a2840b33f made ui handle missing information on search 2016-02-29 16:10:46 +01:00
Christian Schabesberger
d7e75e6011 restructured search engine 2016-02-29 15:59:06 +01:00
Gian Maria Viglianti
73316b87a3 Translated using Weblate (English)
Currently translated at 100.0% (72 of 72 strings)
2016-02-29 03:44:20 +01:00
Matej U
46402691b0 Translated using Weblate (Slovenian)
Currently translated at 100.0% (72 of 72 strings)
2016-02-27 23:05:13 +01:00
Filip Sebastian
e7cef4549f Translated using Weblate (Romanian)
Currently translated at 100.0% (72 of 72 strings)
2016-02-27 17:51:43 +01:00
Christian Schabesberger
737a41f45b display error message 2016-02-27 17:02:38 +01:00
Christian Schabesberger
045ca40a77 renamed video classes to stream classes 2016-02-27 16:37:15 +01:00
Christian Schabesberger
b1fe197c11 changed crashreport email address 2016-02-27 15:57:37 +01:00
Mladen Pejaković
8888530ae3 Translated using Weblate (Serbian)
Currently translated at 100.0% (72 of 72 strings)
2016-02-27 15:34:44 +01:00
Christian Schabesberger
2d51c7428e add ip and timestamp 2016-02-27 15:02:28 +01:00
Christian Schabesberger
863e2a80a2 set errors mail address 2016-02-27 02:26:06 +01:00
Weblate
41d17d2a47 Merge remote-tracking branch 'origin/master' 2016-02-27 02:12:18 +01:00
Christian Schabesberger
36934468d6 uppdate support framework 2016-02-27 02:14:55 +01:00
Thejesh GN
5029ce8728 Translated using Weblate (Kannada)
Currently translated at 1.3% (1 of 72 strings)
2016-02-27 02:12:17 +01:00
Gian Maria Viglianti
e6ab24bcb4 Translated using Weblate (Italian)
Currently translated at 100.0% (72 of 72 strings)
2016-02-27 02:12:17 +01:00
Christian Schabesberger
f3bd263ada new website for newpipe 2016-02-27 02:11:31 +01:00
Gian Maria Viglianti
db7ab3ffce Translated using Weblate (Italian)
Currently translated at 100.0% (72 of 72 strings)
2016-02-27 01:37:42 +01:00
Thejesh GN
85c3755b96 Translated using Weblate (Kannada)
Currently translated at 100% (0 of 0 strings)

Created new translation.
2016-02-26 10:28:11 +01:00
Christian Schabesberger
5decd55551 fixed another pattern problem 2016-02-26 01:42:38 +01:00
Christian Schabesberger
bc468b6f36 fixed stream exception handling 2016-02-26 01:32:44 +01:00
Christian Schabesberger
369d9204d9 add send via mail/share feature 2016-02-25 23:19:43 +01:00
Christian Schabesberger
7caf7be97e add info box 2016-02-25 22:02:42 +01:00
Christian Schabesberger
64c423902a made error handling work a bit 2016-02-25 03:43:13 +01:00
Christian Schabesberger
27a2dee3bd created error report activity 2016-02-24 23:12:02 +01:00
Christian Schabesberger
11d3aeb0dd fixed faling searchengine unittest 2016-02-24 22:36:16 +01:00
Christian Schabesberger
f54d8d318a remove parcelabel from VideoInfoItem 2016-02-24 22:25:51 +01:00
Christian Schabesberger
210f2ef452 Merge branch 'master' of github.com:theScrabi/NewPipe 2016-02-24 22:12:21 +01:00
Christian Schabesberger
d0bab6183a fixed related view 0 view count error 2016-02-24 22:12:13 +01:00
Christian Schabesberger
3441aceba3 fixed viewcount failure 2016-02-24 16:44:46 +01:00
Weblate
0908b9cd76 Merge remote-tracking branch 'origin/master' 2016-02-24 16:42:14 +01:00
vadin
67494ad4c4 Translated using Weblate (Spanish)
Currently translated at 98.6% (71 of 72 strings)
2016-02-24 16:42:14 +01:00
naofum
5d8f75beb4 Translated using Weblate (Japanese)
Currently translated at 100.0% (72 of 72 strings)
2016-02-24 15:06:59 +01:00
Christian Schabesberger
8e7fde99db fix bitcoin qrcode 2016-02-24 13:34:41 +01:00
Christian Schabesberger
bfdf165584 add bitcoin donations 2016-02-24 13:29:53 +01:00
Weblate
9427ebd489 Merge remote-tracking branch 'origin/master' 2016-02-23 23:33:55 +01:00
Christian Schabesberger
e4f753ae82 fixed emty search query on suggestions error 2016-02-23 23:36:02 +01:00
Benedikt Freisen
f2d9d3c2d7 Translated using Weblate (German)
Currently translated at 98.6% (71 of 72 strings)
2016-02-23 23:33:55 +01:00
Nathan Follens
04c5f31cc1 Translated using Weblate (Dutch)
Currently translated at 100.0% (72 of 72 strings)
2016-02-23 23:33:55 +01:00
Matej U
4ea86b714e Translated using Weblate (Slovenian)
Currently translated at 100.0% (72 of 72 strings)
2016-02-23 18:33:20 +01:00
Nathan Follens
cc0b96cba4 Translated using Weblate (Dutch)
Currently translated at 100.0% (72 of 72 strings)
2016-02-23 18:00:54 +01:00
Christian Schabesberger
9e176f8400 Merge branch 'kamadi-master' 2016-02-23 16:52:52 +01:00
Christian Schabesberger
7195ff349b fixed toast issue of the previous commit 2016-02-23 16:42:04 +01:00
Christian Schabesberger
8048ad343e add toast for suggestion error handling 2016-02-23 16:34:14 +01:00
Christian Schabesberger
799a27ec84 Merge branch 'master' of https://github.com/kamadi/NewPipe into kamadi-master 2016-02-23 16:21:16 +01:00
Christian Schabesberger
c7c77ab20c fixed another pattern problem 2016-02-23 15:25:34 +01:00
madiyar
8fc113cc52 Added country language param to the suggestionList method in search engine 2016-02-23 16:22:49 +06:00
madiyar
c7679bec87 Added suggestion to the searching 2016-02-23 15:01:59 +06:00
madiyar
3301d8b4fb Created suggestion adapter 2016-02-23 14:36:24 +06:00
Christian Schabesberger
f5892093a9 made exoplayer work with youtube again 2016-02-23 01:56:04 +01:00
Christian Schabesberger
b06238ba5d initial changes 2016-02-22 20:28:37 +01:00
Christian Schabesberger
dddcc80f30 merged faridk's code 2016-02-22 19:58:04 +01:00
Christian Schabesberger
8854c8c9d0 Merge branch 'master' of github.com:theScrabi/NewPipe 2016-02-22 19:19:22 +01:00
Christian Schabesberger
d02f441eb0 add age restricted material to description 2016-02-22 19:19:13 +01:00
Christian Schabesberger
ff89dd00b6 Merge branch 'rrooij-age_restriction' 2016-02-22 19:18:22 +01:00
Christian Schabesberger
7041e63268 merged age restricted video request 2016-02-22 19:17:05 +01:00
Weblate
8126fdcd15 Merge remote-tracking branch 'origin/master' 2016-02-22 19:16:57 +01:00
Selim
2d61a2f251 Translated using Weblate (Turkish)
Currently translated at 31.8% (22 of 69 strings)
2016-02-22 19:16:57 +01:00
Matej U
7594ee9dbe Translated using Weblate (Slovenian)
Currently translated at 100.0% (69 of 69 strings)
2016-02-22 19:16:56 +01:00
naofum
0862a38599 Translated using Weblate (Japanese)
Currently translated at 100.0% (69 of 69 strings)
2016-02-22 16:37:05 +01:00
rrooij
d12af16f46 VideoItemDetailFragment: check for next vid
Check if the next video is available before loading the thumbnails.
2016-02-21 19:07:24 +01:00
rrooij
2edfcb78fe YTStreamExtractor: implement getAgeRestriction 2016-02-21 18:45:28 +01:00
rrooij
3f0947fa5b Add unit test for restricted YouTube videos 2016-02-21 18:25:18 +01:00
rrooij
d2b808e540 YTStreamExtractor: fix audio tracks on restricted
Fix audio tracks on restriced videos.
2016-02-21 18:24:53 +01:00
rrooij
4d727245e1 YTStreamExtractor: add support for age restricted
YouTube age restricted videos are now kind of supported. This is not a
final solution to this problem and this commit still crashes because of
some problem with the thumbnail.
2016-02-21 16:39:08 +01:00
Farid
3a8611ebf8 Added ExoPlayer support 2016-02-15 18:49:58 -08:00
98 changed files with 5325 additions and 1072 deletions

View File

@@ -20,6 +20,7 @@ android:
env:
global:
- ADB_INSTALL_TIMEOUT=8 # minutes (2 by default)
- GRADLE_OPTS=-Xmx512m # give gradle more memory since it seem to fail otherwise
matrix:
- ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a
@@ -28,3 +29,5 @@ before_script:
- emulator -avd test -no-skin -no-audio -no-window &
- android-wait-for-emulator
- adb shell input keyevent 82 &
script: ./gradlew --info build connectedCheck

View File

@@ -1,7 +1,7 @@
# NewPipe
NewPipe: A free lightweight Youtube frontend for Android.
[![NewPipe](app/src/main/res/mipmap-xhdpi/ic_launcher.png)](http://dasochan.nl/newpipe/)
[![NewPipe](app/src/main/res/mipmap-xhdpi/ic_launcher.png)](https://newpipe.schabi.org)
Project status:
[![Translation Status](https://hosted.weblate.org/widgets/NewPipe/-/svg-badge.svg)](https://hosted.weblate.org/engage/NewPipe/)
@@ -11,6 +11,12 @@ Project status:
[![F-Droid](https://f-droid.org/wiki/images/0/06/F-Droid-button_get-it-on.png)](https://f-droid.org/repository/browse/?fdfilter=newpipe&fdid=org.schabi.newpipe)
## Donate
![Bitcoin](https://bitcoin.org/img/icons/logotop.svg)
`16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh`
![BitcoinQR](assets/16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh.png)
## Screenshots
[<img src="screenshots/screenshot_1.png" width=150>](screenshots/screenshot_1.png)
@@ -36,6 +42,7 @@ NewPipe does not use any Google framework libraries, or the YouTube API. It only
* Show Next/Related videos
* Search YouTube in a specific language
* Orbot/Tor support (no streaming yet, experimental)
* Watch age restricted material
### Coming Features

View File

@@ -8,8 +8,8 @@ android {
applicationId "org.schabi.newpipe"
minSdkVersion 15
targetSdkVersion 23
versionCode 15
versionName "0.7.6"
versionCode 16
versionName "0.7.7"
}
buildTypes {
release {
@@ -32,14 +32,16 @@ android {
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:support-v4:23.1.1'
compile 'com.android.support:design:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'com.android.support:appcompat-v7:23.2.0'
compile 'com.android.support:support-v4:23.2.0'
compile 'com.android.support:design:23.2.0'
compile 'com.android.support:recyclerview-v7:23.2.0'
compile 'org.jsoup:jsoup:1.8.3'
compile 'org.mozilla:rhino:1.7.7'
compile 'info.guardianproject.netcipher:netcipher:1.2'
compile 'de.hdodenhof:circleimageview:2.0.0'
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
compile 'com.github.nirhart:parallaxscroll:1.0'
compile 'org.apache.directory.studio:org.apache.commons.lang:2.6'
compile 'com.google.android.exoplayer:exoplayer:r1.5.5'
}

View File

@@ -1,16 +1,21 @@
package org.schabi.newpipe.services.youtube;
package org.schabi.newpipe.extractor.youtube;
import android.test.AndroidTestCase;
import org.schabi.newpipe.extractor.VideoPreviewInfo;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.schabi.newpipe.extractor.AbstractVideoInfo;
import org.schabi.newpipe.extractor.SearchResult;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamPreviewInfo;
import org.schabi.newpipe.extractor.SearchEngine;
import org.schabi.newpipe.extractor.services.youtube.YoutubeSearchEngine;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.services.youtube.YoutubeService;
import java.util.ArrayList;
/**
* Created by the-scrabi on 29.12.15.
* Created by Christian Schabesberger on 29.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeSearchEngineTest.java is part of NewPipe.
@@ -30,21 +35,23 @@ import java.util.ArrayList;
*/
public class YoutubeSearchEngineTest extends AndroidTestCase {
private SearchEngine.Result result;
private SearchResult result;
private ArrayList<String> suggestionReply;
@Override
public void setUp() throws Exception{
super.setUp();
SearchEngine engine = new YoutubeSearchEngine();
SearchEngine engine = ServiceList.getService("Youtube")
.getSearchEngineInstance(new Downloader());
result = engine.search("https://www.youtube.com/results?search_query=bla",
0, "de", new Downloader());
suggestionReply = engine.suggestionList("hello", new Downloader());
result = engine.search("lefloid",
0, "de", new Downloader()).getSearchResult();
suggestionReply = engine.suggestionList("hello","de",new Downloader());
}
public void testIfNoErrorOccur() {
assertEquals(result.errorMessage, "");
assertTrue(result.errors.isEmpty() ? "" : ExceptionUtils.getStackTrace(result.errors.get(0))
,result.errors.isEmpty());
}
public void testIfListIsNotEmpty() {
@@ -52,43 +59,58 @@ public class YoutubeSearchEngineTest extends AndroidTestCase {
}
public void testItemsHaveTitle() {
for(VideoPreviewInfo i : result.resultList) {
for(StreamPreviewInfo i : result.resultList) {
assertEquals(i.title.isEmpty(), false);
}
}
public void testItemsHaveUploader() {
for(VideoPreviewInfo i : result.resultList) {
for(StreamPreviewInfo i : result.resultList) {
assertEquals(i.uploader.isEmpty(), false);
}
}
public void testItemsHaveRightDuration() {
for(VideoPreviewInfo i : result.resultList) {
assertTrue(i.duration, i.duration.contains(":"));
for(StreamPreviewInfo i : result.resultList) {
assertTrue(i.duration >= 0);
}
}
public void testItemsHaveRightThumbnail() {
for (VideoPreviewInfo i : result.resultList) {
for (StreamPreviewInfo i : result.resultList) {
assertTrue(i.thumbnail_url, i.thumbnail_url.contains("https://"));
}
}
public void testItemsHaveRightVideoUrl() {
for (VideoPreviewInfo i : result.resultList) {
for (StreamPreviewInfo i : result.resultList) {
assertTrue(i.webpage_url, i.webpage_url.contains("https://"));
}
}
public void testViewCount() {
for(VideoPreviewInfo i : result.resultList) {
/*
for(StreamPreviewInfo i : result.resultList) {
assertTrue(Long.toString(i.view_count), i.view_count != -1);
}
*/
// that specific link used for this test, there are no videos with less
// than 10.000 views, so we can test against that.
for(StreamPreviewInfo i : result.resultList) {
assertTrue(i.title + ": " + Long.toString(i.view_count), i.view_count >= 10000);
}
}
public void testStreamType() {
for(StreamPreviewInfo i : result.resultList) {
assertTrue("not a livestream and not a video",
i.stream_type == AbstractVideoInfo.StreamType.VIDEO_STREAM ||
i.stream_type == AbstractVideoInfo.StreamType.LIVE_STREAM);
}
}
public void testIfSuggestionsAreReplied() {
assertEquals(suggestionReply.size() > 0, true);
assertEquals(!suggestionReply.isEmpty(), true);
}
public void testIfSuggestionsAreValid() {

View File

@@ -1,17 +1,19 @@
package org.schabi.newpipe.services.youtube;
package org.schabi.newpipe.extractor.youtube;
import android.test.AndroidTestCase;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.AbstractVideoInfo;
import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.VideoInfo;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamExtractor;
import org.schabi.newpipe.extractor.VideoStream;
import java.io.IOException;
/**
* Created by the-scrabi on 30.12.15.
* Created by Christian Schabesberger on 30.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeVideoExtractorDefault.java is part of NewPipe.
@@ -31,15 +33,11 @@ import java.io.IOException;
*/
public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
private YoutubeStreamExtractor extractor;
private StreamExtractor extractor;
public void setUp() throws IOException, ExtractionException {
/* some anonymus video test
extractor = new YoutubeStreamExtractor("https://www.youtube.com/watch?v=FmG385_uUys",
new Downloader()); */
/* some vevo video (suggested to test against) */
extractor = new YoutubeStreamExtractor("https://www.youtube.com/watch?v=YQHsXMglC9A",
new Downloader());
extractor = ServiceList.getService("Youtube")
.getExtractorInstance("https://www.youtube.com/watch?v=YQHsXMglC9A", new Downloader());
}
public void testGetInvalidTimeStamp() throws ParsingException {
@@ -48,8 +46,9 @@ public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
}
public void testGetValidTimeStamp() throws ExtractionException, IOException {
YoutubeStreamExtractor extractor =
new YoutubeStreamExtractor("https://youtu.be/FmG385_uUys?t=174", new Downloader());
StreamExtractor extractor =
ServiceList.getService("Youtube")
.getExtractorInstance("https://youtu.be/FmG385_uUys?t=174", new Downloader());
assertTrue(Integer.toString(extractor.getTimeStamp()),
extractor.getTimeStamp() == 174);
}
@@ -70,8 +69,9 @@ public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
assertTrue(extractor.getLength() > 0);
}
public void testGetViews() throws ParsingException {
assertTrue(extractor.getLength() > 0);
public void testGetViewCount() throws ParsingException {
assertTrue(Long.toString(extractor.getViewCount()),
extractor.getViewCount() > /* specific to that video */ 1224000074);
}
public void testGetUploadDate() throws ParsingException {
@@ -93,7 +93,7 @@ public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
}
public void testGetVideoStreams() throws ParsingException {
for(VideoInfo.VideoStream s : extractor.getVideoStreams()) {
for(VideoStream s : extractor.getVideoStreams()) {
assertTrue(s.url,
s.url.contains("https://"));
assertTrue(s.resolution.length() > 0);
@@ -102,6 +102,10 @@ public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
}
}
public void testStreamType() throws ParsingException {
assertTrue(extractor.getStreamType() == AbstractVideoInfo.StreamType.VIDEO_STREAM);
}
public void testGetDashMpd() throws ParsingException {
assertTrue(extractor.getDashMpdUrl(),
extractor.getDashMpdUrl() != null || !extractor.getDashMpdUrl().isEmpty());

View File

@@ -1,15 +1,16 @@
package org.schabi.newpipe.services.youtube;
package org.schabi.newpipe.extractor.youtube;
import android.test.AndroidTestCase;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
import java.io.IOException;
/**
* Created by the-scrabi on 30.12.15.
* Created by Christian Schabesberger on 30.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeVideoExtractorGema.java is part of NewPipe.
@@ -38,9 +39,9 @@ public class YoutubeStreamExtractorGemaTest extends AndroidTestCase {
public void testGemaError() throws IOException, ExtractionException {
if(testActive) {
try {
new YoutubeStreamExtractor("https://www.youtube.com/watch?v=3O1_3zBUKM8",
ServiceList.getService("Youtube")
.getExtractorInstance("https://www.youtube.com/watch?v=3O1_3zBUKM8",
new Downloader());
assertTrue("Gema exception not thrown", false);
} catch(YoutubeStreamExtractor.GemaException ge) {
assertTrue(true);
}

View File

@@ -0,0 +1,87 @@
package org.schabi.newpipe.extractor.youtube;
import android.test.AndroidTestCase;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.ParsingException;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamExtractor;
import org.schabi.newpipe.extractor.VideoStream;
import java.io.IOException;
public class YoutubeStreamExtractorRestrictedTest extends AndroidTestCase {
private StreamExtractor extractor;
public void setUp() throws IOException, ExtractionException {
extractor = ServiceList.getService("Youtube")
.getExtractorInstance("https://www.youtube.com/watch?v=i6JTvzrpBy0",
new Downloader());
}
public void testGetInvalidTimeStamp() throws ParsingException {
assertTrue(Integer.toString(extractor.getTimeStamp()),
extractor.getTimeStamp() <= 0);
}
public void testGetValidTimeStamp() throws ExtractionException, IOException {
StreamExtractor extractor=ServiceList.getService("Youtube")
.getExtractorInstance("https://youtu.be/FmG385_uUys?t=174",
new Downloader());
assertTrue(Integer.toString(extractor.getTimeStamp()),
extractor.getTimeStamp() == 174);
}
public void testGetAgeLimit() throws ParsingException {
assertTrue(extractor.getAgeLimit() == 18);
}
public void testGetTitle() throws ParsingException {
assertTrue(!extractor.getTitle().isEmpty());
}
public void testGetDescription() throws ParsingException {
assertTrue(extractor.getDescription() != null);
}
public void testGetUploader() throws ParsingException {
assertTrue(!extractor.getUploader().isEmpty());
}
public void testGetLength() throws ParsingException {
assertTrue(extractor.getLength() > 0);
}
public void testGetViews() throws ParsingException {
assertTrue(extractor.getLength() > 0);
}
public void testGetUploadDate() throws ParsingException {
assertTrue(extractor.getUploadDate().length() > 0);
}
public void testGetThumbnailUrl() throws ParsingException {
assertTrue(extractor.getThumbnailUrl(),
extractor.getThumbnailUrl().contains("https://"));
}
public void testGetUploaderThumbnailUrl() throws ParsingException {
assertTrue(extractor.getUploaderThumbnailUrl(),
extractor.getUploaderThumbnailUrl().contains("https://"));
}
public void testGetAudioStreams() throws ParsingException {
assertTrue(!extractor.getAudioStreams().isEmpty());
}
public void testGetVideoStreams() throws ParsingException {
for(VideoStream s : extractor.getVideoStreams()) {
assertTrue(s.url,
s.url.contains("https://"));
assertTrue(s.resolution.length() > 0);
assertTrue(Integer.toString(s.format),
0 <= s.format && s.format <= 4);
}
}
}

View File

@@ -0,0 +1,52 @@
package org.schabi.newpipe.extractor.youtube;
import android.test.AndroidTestCase;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.AbstractVideoInfo;
import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.ParsingException;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamExtractor;
import java.io.IOException;
/**
* Created by Christian Schabesberger on 11.03.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* YoutubestreamExtractorLiveStreamTest.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 <http://www.gnu.org/licenses/>.
*/
public class YoutubestreamExtractorLiveStreamTest extends AndroidTestCase {
private StreamExtractor extractor;
public void setUp() throws IOException, ExtractionException {
//todo: make the extractor not throw over a livestream
/*
extractor = ServiceList.getService("Youtube")
.getExtractorInstance("https://www.youtube.com/watch?v=J0s6NjqdjLE", new Downloader());
*/
}
public void testStreamType() throws ParsingException {
assertTrue(true);
// assertTrue(extractor.getStreamType() == AbstractVideoInfo.StreamType.LIVE_STREAM);
}
}

View File

@@ -1,23 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.schabi.newpipe" >
<uses-permission android:name= "android.permission.INTERNET" />
<uses-permission android:name= "android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
package="org.schabi.newpipe">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:logo="@mipmap/ic_launcher"
android:label="@string/app_name"
android:logo="@mipmap/ic_launcher"
android:theme="@style/AppTheme"
tools:ignore="AllowBackup">
<activity
android:name=".VideoItemListActivity"
android:label="@string/app_name"
android:configChanges="orientation|screenSize">
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -27,9 +28,7 @@
<activity
android:name=".VideoItemDetailActivity"
android:label="@string/title_videoitem_detail"
android:theme="@style/AppTheme"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait">
android:theme="@style/AppTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".VideoItemListActivity" />
@@ -76,20 +75,40 @@
<data android:scheme="vnd.youtube.launch" />
</intent-filter>
</activity>
<activity android:name=".PlayVideoActivity"
<activity
android:name=".player.PlayVideoActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/VideoPlayerTheme"
android:parentActivityName=".VideoItemDetailActivity"
tools:ignore="UnusedAttribute">
tools:ignore="UnusedAttribute"/>
<service
android:name=".player.BackgroundPlayer"
android:exported="false"
android:label="@string/background_player_name"/>
<activity
android:name=".player.ExoPlayerActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleInstance"
android:theme="@style/PlayerTheme">
<intent-filter>
<action android:name="org.schabi.newpipe.exoplayer.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:scheme="content" />
<data android:scheme="asset" />
<data android:scheme="file" />
</intent-filter>
</activity>
<service
android:name=".BackgroundPlayer"
android:name=".player.BackgroundPlayer"
android:label="@string/background_player_name"
android:exported="false" />
<activity
android:name=".SettingsActivity"
android:label="@string/settings_activity_title" >
</activity>
android:label="@string/settings_activity_title" />
<activity
android:name=".PanicResponderActivity"
android:launchMode="singleInstance"
@@ -97,11 +116,14 @@
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="info.guardianproject.panic.action.TRIGGER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".ExitActivity"
android:label="@string/general_error"
android:theme="@android:style/Theme.NoDisplay" />
<activity android:name=".ErrorActivity"/>
</application>
</manifest>

View File

@@ -12,7 +12,8 @@ import android.view.MenuItem;
import android.widget.ArrayAdapter;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.VideoInfo;
import org.schabi.newpipe.extractor.StreamInfo;
import org.schabi.newpipe.extractor.VideoStream;
import java.util.List;
@@ -75,7 +76,7 @@ class ActionBarHandler {
}
}
public void setupStreamList(final List<VideoInfo.VideoStream> videoStreams) {
public void setupStreamList(final List<VideoStream> videoStreams) {
if (activity != null) {
selectedVideoStream = 0;
@@ -83,7 +84,7 @@ class ActionBarHandler {
// this array will be shown in the dropdown menu for selecting the stream/resolution.
String[] itemArray = new String[videoStreams.size()];
for (int i = 0; i < videoStreams.size(); i++) {
VideoInfo.VideoStream item = videoStreams.get(i);
VideoStream item = videoStreams.get(i);
itemArray[i] = MediaFormat.getNameById(item.format) + " " + item.resolution;
}
int defaultResolution = getDefaultResolution(videoStreams);
@@ -108,13 +109,13 @@ class ActionBarHandler {
}
private int getDefaultResolution(final List<VideoInfo.VideoStream> videoStreams) {
private int getDefaultResolution(final List<VideoStream> videoStreams) {
String defaultResolution = defaultPreferences
.getString(activity.getString(R.string.default_resolution_key),
activity.getString(R.string.default_resolution_value));
for (int i = 0; i < videoStreams.size(); i++) {
VideoInfo.VideoStream item = videoStreams.get(i);
VideoStream item = videoStreams.get(i);
if (defaultResolution.equals(item.resolution)) {
return i;
}

View File

@@ -22,10 +22,12 @@ package org.schabi.newpipe;
import android.graphics.Bitmap;
import java.util.List;
/**
* Singleton:
* Used to send data between certain Activity/Services within the same process.
* This can be considered as hack inside the Android universe. **/
* This can be considered as an ugly hack inside the Android universe. **/
public class ActivityCommunicator {
private static ActivityCommunicator activityCommunicator = null;
@@ -39,4 +41,9 @@ public class ActivityCommunicator {
// Thumbnail send from VideoItemDetailFragment to BackgroundPlayer
public volatile Bitmap backgroundPlayerThumbnail;
// Sent from any activity to ErrorActivity.
public volatile List<Exception> errorList;
public volatile Class returnActivity;
public volatile ErrorActivity.ErrorInfo errorInfo;
}

View File

@@ -130,7 +130,7 @@ public class DownloadDialog extends DialogFragment {
private String createFileName(String fName) {
// from http://eng-przemelek.blogspot.de/2009/07/how-to-create-valid-file-name.html
List<String> forbiddenCharsPatterns = new ArrayList<String> ();
List<String> forbiddenCharsPatterns = new ArrayList<> ();
forbiddenCharsPatterns.add("[:]+"); // Mac OS, but it looks that also Windows XP
forbiddenCharsPatterns.add("[\\*\"/\\\\\\[\\]\\:\\;\\|\\=\\,]+"); // Windows
forbiddenCharsPatterns.add("[^\\w\\d\\.]+"); // last chance... only latin letters and digits

File diff suppressed because it is too large Load Diff

View File

@@ -34,6 +34,9 @@ import java.util.Locale;
public class Localization {
private Localization() {
}
public static Locale getPreferredLocale(Context context) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);

View File

@@ -33,6 +33,10 @@ import java.io.File;
* Helper for global settings
*/
public class NewPipeSettings {
private NewPipeSettings() {
}
public static void initSettings(Context context) {
PreferenceManager.setDefaultValues(context, R.xml.settings, false);
getVideoDownloadFolder(context);

View File

@@ -119,18 +119,20 @@ public class SettingsActivity extends PreferenceActivity {
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
Activity a = getActivity();
updateSummary();
if(a != null) {
updateSummary();
if (defaultPreferences.getBoolean(USE_TOR_KEY, false)) {
if (OrbotHelper.isOrbotInstalled(a)) {
App.configureTor(true);
OrbotHelper.requestStartTor(a);
if (defaultPreferences.getBoolean(USE_TOR_KEY, false)) {
if (OrbotHelper.isOrbotInstalled(a)) {
App.configureTor(true);
OrbotHelper.requestStartTor(a);
} else {
Intent intent = OrbotHelper.getOrbotInstallIntent(a);
a.startActivityForResult(intent, REQUEST_INSTALL_ORBOT);
}
} else {
Intent intent = OrbotHelper.getOrbotInstallIntent(a);
a.startActivityForResult(intent, REQUEST_INSTALL_ORBOT);
App.configureTor(false);
}
} else {
App.configureTor(false);
}
}
};

View File

@@ -0,0 +1,82 @@
package org.schabi.newpipe;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by Madiyar on 23.02.2016.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* SuggestionListAdapter.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 <http://www.gnu.org/licenses/>.
*/
public class SuggestionListAdapter extends CursorAdapter {
private String[] columns = new String[]{"_id", "title"};
public SuggestionListAdapter(Context context) {
super(context, null, false);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
ViewHolder viewHolder;
View view = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false);
viewHolder = new ViewHolder();
viewHolder.suggestionTitle = (TextView) view.findViewById(android.R.id.text1);
view.setTag(viewHolder);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder viewHolder = (ViewHolder) view.getTag();
viewHolder.suggestionTitle.setText(cursor.getString(1));
}
public void updateAdapter(ArrayList<String> suggestions) {
MatrixCursor cursor = new MatrixCursor(columns);
int i = 0;
for (String s : suggestions) {
String[] temp = new String[2];
temp[0] = Integer.toString(i);
temp[1] = s;
i++;
cursor.addRow(temp);
}
changeCursor(cursor);
}
public String getSuggestion(int position) {
return ((Cursor) getItem(position)).getString(1);
}
private class ViewHolder {
public TextView suggestionTitle;
}
}

View File

@@ -1,13 +1,14 @@
package org.schabi.newpipe;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import org.schabi.newpipe.extractor.VideoPreviewInfo;
import org.schabi.newpipe.extractor.AbstractVideoInfo;
import org.schabi.newpipe.extractor.StreamPreviewInfo;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
@@ -31,7 +32,7 @@ import com.nostra13.universalimageloader.core.ImageLoader;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
class VideoInfoItemViewCreator {
public class VideoInfoItemViewCreator {
private final LayoutInflater inflater;
private ImageLoader imageLoader = ImageLoader.getInstance();
private DisplayImageOptions displayImageOptions = new DisplayImageOptions.Builder().cacheInMemory(true).build();
@@ -40,8 +41,10 @@ class VideoInfoItemViewCreator {
this.inflater = inflater;
}
public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, VideoPreviewInfo info, Context context) {
public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, StreamPreviewInfo info) {
ViewHolder holder;
// generate holder
if(convertView == null) {
convertView = inflater.inflate(R.layout.video_item, parent, false);
holder = new ViewHolder();
@@ -56,20 +59,43 @@ class VideoInfoItemViewCreator {
holder = (ViewHolder) convertView.getTag();
}
// fill with information
/*
if(info.thumbnail == null) {
holder.itemThumbnailView.setImageResource(R.drawable.dummy_thumbnail);
} else {
holder.itemThumbnailView.setImageBitmap(info.thumbnail);
}
*/
holder.itemVideoTitleView.setText(info.title);
holder.itemUploaderView.setText(info.uploader);
holder.itemDurationView.setText(info.duration);
holder.itemViewCountView.setText(shortViewCount(info.view_count));
if(info.uploader != null && !info.uploader.isEmpty()) {
holder.itemUploaderView.setText(info.uploader);
} else {
holder.itemDurationView.setVisibility(View.INVISIBLE);
}
if(info.duration > 0) {
holder.itemDurationView.setText(getDurationString(info.duration));
} else {
if(info.stream_type == AbstractVideoInfo.StreamType.LIVE_STREAM) {
holder.itemDurationView.setText(R.string.duration_live);
} else {
holder.itemDurationView.setVisibility(View.GONE);
}
}
if(info.view_count >= 0) {
holder.itemViewCountView.setText(shortViewCount(info.view_count));
} else {
holder.itemViewCountView.setVisibility(View.GONE);
}
if(!info.upload_date.isEmpty()) {
holder.itemUploadDateView.setText(info.upload_date+" • ");
holder.itemUploadDateView.setText(info.upload_date + " • ");
}
imageLoader.displayImage(info.thumbnail_url, holder.itemThumbnailView, displayImageOptions);
holder.itemThumbnailView.setImageResource(R.drawable.dummy_thumbnail);
if(info.thumbnail_url != null && !info.thumbnail_url.isEmpty()) {
imageLoader.displayImage(info.thumbnail_url, holder.itemThumbnailView, displayImageOptions);
}
return convertView;
}
@@ -79,16 +105,69 @@ class VideoInfoItemViewCreator {
public TextView itemVideoTitleView, itemUploaderView, itemDurationView, itemUploadDateView, itemViewCountView;
}
private String shortViewCount(Long view_count){
if(view_count >= 1000000000){
return Long.toString(view_count/1000000000)+"B views";
}else if(view_count>=1000000){
return Long.toString(view_count/1000000)+"M views";
}else if(view_count>=1000){
return Long.toString(view_count/1000)+"K views";
private String shortViewCount(Long viewCount){
if(viewCount >= 1000000000){
return Long.toString(viewCount/1000000000)+"B views";
}else if(viewCount>=1000000){
return Long.toString(viewCount/1000000)+"M views";
}else if(viewCount>=1000){
return Long.toString(viewCount/1000)+"K views";
}else {
return Long.toString(view_count)+" views";
return Long.toString(viewCount)+" views";
}
}
public static String getDurationString(int duration) {
String output = "";
int days = duration / (24 * 60 * 60); /* greater than a day */
duration %= (24 * 60 * 60);
int hours = duration / (60 * 60); /* greater than an hour */
duration %= (60 * 60);
int minutes = duration / 60;
int seconds = duration % 60;
//handle days
if(days > 0) {
output = Integer.toString(days) + ":";
}
// handle hours
if(hours > 0 || !output.isEmpty()) {
if(hours > 0) {
if(hours >= 10 || output.isEmpty()) {
output += Integer.toString(minutes);
} else {
output += "0" + Integer.toString(minutes);
}
} else {
output += "00";
}
output += ":";
}
//handle minutes
if(minutes > 0 || !output.isEmpty()) {
if(minutes > 0) {
if(minutes >= 10 || output.isEmpty()) {
output += Integer.toString(minutes);
} else {
output += "0" + Integer.toString(minutes);
}
} else {
output += "00";
}
output += ":";
}
//handle seconds
if(output.isEmpty()) {
output += "0:";
}
if(seconds >= 10) {
output += Integer.toString(seconds);
} else {
output += "0" + Integer.toString(seconds);
}
return output;
}
}

View File

@@ -73,7 +73,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
StreamingService[] serviceList = ServiceList.getServices();
//StreamExtractor videoExtractor = null;
for (int i = 0; i < serviceList.length; i++) {
if (serviceList[i].getUrlIdHandler().acceptUrl(videoUrl)) {
if (serviceList[i].getUrlIdHandlerInstance().acceptUrl(videoUrl)) {
arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, i);
currentStreamingService = i;
//videoExtractor = ServiceList.getService(i).getExtractorInstance();

View File

@@ -1,5 +1,6 @@
package org.schabi.newpipe;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
@@ -17,8 +18,8 @@ import java.io.IOException;
import java.util.List;
import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.ParsingException;
import org.schabi.newpipe.extractor.VideoPreviewInfo;
import org.schabi.newpipe.extractor.SearchResult;
import org.schabi.newpipe.extractor.StreamPreviewInfo;
import org.schabi.newpipe.extractor.SearchEngine;
import org.schabi.newpipe.extractor.StreamingService;
@@ -68,9 +69,9 @@ public class VideoItemListFragment extends ListFragment {
private boolean loadingNextPage = true;
private class ResultRunnable implements Runnable {
private final SearchEngine.Result result;
private final SearchResult result;
private final int requestId;
public ResultRunnable(SearchEngine.Result result, int requestId) {
public ResultRunnable(SearchResult result, int requestId) {
this.result = result;
this.requestId = requestId;
}
@@ -101,32 +102,60 @@ public class VideoItemListFragment extends ListFragment {
}
@Override
public void run() {
SearchResult result = null;
try {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
String searchLanguageKey = getContext().getString(R.string.search_language_key);
String searchLanguage = sp.getString(searchLanguageKey,
getString(R.string.default_language_value));
SearchEngine.Result result = engine.search(query, page, searchLanguage,
new Downloader());
result = SearchResult
.getSearchResult(engine, query, page, searchLanguage, new Downloader());
//Log.i(TAG, "language code passed:\""+searchLanguage+"\"");
if(runs) {
h.post(new ResultRunnable(result, requestId));
}
// look for errors during extraction
// soft errors:
if(result != null &&
!result.errors.isEmpty()) {
Log.e(TAG, "OCCURRED ERRORS DURING SEARCH EXTRACTION:");
for(Exception e : result.errors) {
e.printStackTrace();
Log.e(TAG, "------");
}
Activity a = getActivity();
View rootView = a.findViewById(R.id.videoitem_list);
ErrorActivity.reportError(h, getActivity(), result.errors, null, rootView,
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
/* todo: this shoudl not be assigned static */ "Youtube", query, R.string.light_parsing_error));
}
// hard errors:
} catch(IOException e) {
postNewErrorToast(h, R.string.network_error);
postNewNothingFoundToast(h, R.string.network_error);
e.printStackTrace();
} catch(ExtractionException ce) {
postNewErrorToast(h, R.string.parsing_error);
ce.printStackTrace();
} catch(SearchEngine.NothingFoundException e) {
postNewErrorToast(h, e.getMessage());
} catch(ExtractionException e) {
ErrorActivity.reportError(h, getActivity(), e, null, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
/* todo: this shoudl not be assigned static */ "Youtube", query, R.string.parsing_error));
//postNewErrorToast(h, R.string.parsing_error);
e.printStackTrace();
} catch(Exception e) {
postNewErrorToast(h, R.string.general_error);
ErrorActivity.reportError(h, getActivity(), e, null, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
/* todo: this shoudl not be assigned static */ "Youtube", query, R.string.general_error));
e.printStackTrace();
}
}
}
public void present(List<VideoPreviewInfo> videoList) {
public void present(List<StreamPreviewInfo> videoList) {
mode = PRESENT_VIDEOS_MODE;
setListShown(true);
getListView().smoothScrollToPosition(0);
@@ -156,7 +185,7 @@ public class VideoItemListFragment extends ListFragment {
private void startSearch(String query, int page) {
currentRequestId++;
terminateThreads();
searchRunnable = new SearchRunnable(streamingService.getSearchEngineInstance(),
searchRunnable = new SearchRunnable(streamingService.getSearchEngineInstance(new Downloader()),
query, page, currentRequestId);
searchThread = new Thread(searchRunnable);
searchThread.start();
@@ -166,28 +195,29 @@ public class VideoItemListFragment extends ListFragment {
this.streamingService = streamingService;
}
private void updateListOnResult(SearchEngine.Result result, int requestId) {
private void updateListOnResult(SearchResult result, int requestId) {
if(requestId == currentRequestId) {
setListShown(true);
if (result.resultList.isEmpty()) {
Toast.makeText(getActivity(), result.errorMessage, Toast.LENGTH_LONG).show();
} else {
if (!result.suggestion.isEmpty()) {
Toast.makeText(getActivity(), getString(R.string.did_you_mean) + result.suggestion + " ?",
Toast.LENGTH_LONG).show();
}
updateList(result.resultList);
updateList(result.resultList);
if(!result.suggestion.isEmpty()) {
Toast.makeText(getActivity(),
String.format(getString(R.string.did_you_mean), result.suggestion),
Toast.LENGTH_LONG).show();
}
}
}
private void updateList(List<VideoPreviewInfo> list) {
private void updateList(List<StreamPreviewInfo> list) {
try {
videoListAdapter.addVideoList(list);
terminateThreads();
} catch(java.lang.IllegalStateException e) {
Toast.makeText(getActivity(), "Trying to set value while activity doesn't exist anymore.",
Toast.LENGTH_SHORT).show();
Log.w(TAG, "Trying to set value while activity doesn't exist anymore.");
} catch(Exception e) {
Toast.makeText(getActivity(), getString(R.string.general_error),
Toast.LENGTH_SHORT).show();
e.printStackTrace();
} finally {
loadingNextPage = false;
@@ -314,13 +344,24 @@ public class VideoItemListFragment extends ListFragment {
mActivatedPosition = position;
}
private void postNewErrorToast(Handler h, final int stringResource) {
private void postNewErrorToast(Handler h, final String message) {
h.post(new Runnable() {
@Override
public void run() {
setListShown(true);
Toast.makeText(getActivity(), message,
Toast.LENGTH_SHORT).show();
}
});
}
private void postNewNothingFoundToast(Handler h, final int stringResource) {
h.post(new Runnable() {
@Override
public void run() {
setListShown(true);
Toast.makeText(getActivity(), getString(stringResource),
Toast.LENGTH_SHORT).show();
Toast.LENGTH_LONG).show();
}
});
}

View File

@@ -8,7 +8,7 @@ import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import org.schabi.newpipe.extractor.VideoPreviewInfo;
import org.schabi.newpipe.extractor.StreamPreviewInfo;
import java.util.List;
import java.util.Vector;
@@ -36,7 +36,7 @@ import java.util.Vector;
class VideoListAdapter extends BaseAdapter {
private final Context context;
private final VideoInfoItemViewCreator viewCreator;
private Vector<VideoPreviewInfo> videoList = new Vector<>();
private Vector<StreamPreviewInfo> videoList = new Vector<>();
private final ListView listView;
public VideoListAdapter(Context context, VideoItemListFragment videoListFragment) {
@@ -47,7 +47,7 @@ class VideoListAdapter extends BaseAdapter {
this.context = context;
}
public void addVideoList(List<VideoPreviewInfo> videos) {
public void addVideoList(List<StreamPreviewInfo> videos) {
videoList.addAll(videos);
notifyDataSetChanged();
}
@@ -57,7 +57,7 @@ class VideoListAdapter extends BaseAdapter {
notifyDataSetChanged();
}
public Vector<VideoPreviewInfo> getVideoList() {
public Vector<StreamPreviewInfo> getVideoList() {
return videoList;
}
@@ -78,7 +78,7 @@ class VideoListAdapter extends BaseAdapter {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position), context);
convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position));
if(listView.isItemChecked(position)) {
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.light_youtube_primary_color));

View File

@@ -20,8 +20,19 @@ import android.graphics.Bitmap;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
/**Common properties between VideoInfo and VideoPreviewInfo.*/
/**Common properties between StreamInfo and StreamPreviewInfo.*/
public abstract class AbstractVideoInfo {
public static enum StreamType {
NONE, // placeholder to check if stream type was checked or not
VIDEO_STREAM,
AUDIO_STREAM,
LIVE_STREAM,
AUDIO_LIVE_STREAM,
FILE
}
public StreamType stream_type;
public int service_id = -1;
public String id = "";
public String title = "";
public String uploader = "";

View File

@@ -0,0 +1,46 @@
package org.schabi.newpipe.extractor;
/**
* Created by Christian Schabesberger on 04.03.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* AudioStream.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 <http://www.gnu.org/licenses/>.
*/
public class AudioStream {
public String url = "";
public int format = -1;
public int bandwidth = -1;
public int sampling_rate = -1;
public AudioStream(String url, int format, int bandwidth, int samplingRate) {
this.url = url; this.format = format;
this.bandwidth = bandwidth; this.sampling_rate = samplingRate;
}
// reveals wether two streams are the same, but have diferent urls
public boolean equalStats(AudioStream cmp) {
return format == cmp.format
&& bandwidth == cmp.bandwidth
&& sampling_rate == cmp.sampling_rate;
}
// revelas wether two streams are equal
public boolean equals(AudioStream cmp) {
return cmp != null && equalStats(cmp)
&& url == cmp.url;
}
}

View File

@@ -31,13 +31,16 @@ import java.util.Vector;
public class DashMpdParser {
private DashMpdParser() {
}
static class DashMpdParsingException extends ParsingException {
DashMpdParsingException(String message, Exception e) {
super(message, e);
}
}
public static List<VideoInfo.AudioStream> getAudioStreams(String dashManifestUrl,
public static List<AudioStream> getAudioStreams(String dashManifestUrl,
Downloader downloader)
throws DashMpdParsingException {
String dashDoc;
@@ -46,7 +49,7 @@ public class DashMpdParser {
} catch(IOException ioe) {
throw new DashMpdParsingException("Could not get dash mpd: " + dashManifestUrl, ioe);
}
Vector<VideoInfo.AudioStream> audioStreams = new Vector<>();
Vector<AudioStream> audioStreams = new Vector<>();
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new StringReader(dashDoc));
@@ -83,7 +86,7 @@ public class DashMpdParser {
} else if(currentMimeType.equals(MediaFormat.M4A.mimeType)) {
format = MediaFormat.M4A.id;
}
audioStreams.add(new VideoInfo.AudioStream(parser.getText(),
audioStreams.add(new AudioStream(parser.getText(),
format, currentBandwidth, currentSamplingRate));
}
break;

View File

@@ -21,8 +21,6 @@ package org.schabi.newpipe.extractor;
*/
public class ExtractionException extends Exception {
public ExtractionException() {}
public ExtractionException(String message) {
super(message);
}

View File

@@ -1,5 +1,7 @@
package org.schabi.newpipe.extractor;
import android.util.Log;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
@@ -30,6 +32,9 @@ import java.util.regex.Pattern;
/** avoid using regex !!! */
public class Parser {
private Parser() {
}
public static class RegexException extends ParsingException {
public RegexException(String message) {
super(message);
@@ -52,8 +57,12 @@ public class Parser {
public static Map<String, String> compatParseMap(final String input) throws UnsupportedEncodingException {
Map<String, String> map = new HashMap<>();
for(String arg : input.split("&")) {
String[] split_arg = arg.split("=");
map.put(split_arg[0], URLDecoder.decode(split_arg[1], "UTF-8"));
String[] splitArg = arg.split("=");
if(splitArg.length > 1) {
map.put(splitArg[0], URLDecoder.decode(splitArg[1], "UTF-8"));
} else {
map.put(splitArg[0], "");
}
}
return map;
}

View File

@@ -22,13 +22,9 @@ package org.schabi.newpipe.extractor;
public class ParsingException extends ExtractionException {
public ParsingException() {}
public ParsingException(String message) {
super(message);
}
public ParsingException(Throwable cause) {
super(cause);
}
public ParsingException(String message, Throwable cause) {
super(message, cause);
}

View File

@@ -26,17 +26,29 @@ import java.util.Vector;
*/
@SuppressWarnings("ALL")
public interface SearchEngine {
class Result {
public String errorMessage = "";
public String suggestion = "";
public final List<VideoPreviewInfo> resultList = new Vector<>();
public abstract class SearchEngine {
public static class NothingFoundException extends ExtractionException {
public NothingFoundException(String message) {
super(message);
}
}
ArrayList<String> suggestionList(String query, Downloader dl)
private StreamPreviewInfoCollector collector;
public SearchEngine(StreamUrlIdHandler urlIdHandler, int serviceId) {
collector = new StreamPreviewInfoCollector(urlIdHandler, serviceId);
}
public StreamPreviewInfoCollector getStreamPreviewInfoCollector() {
return collector;
}
public abstract ArrayList<String> suggestionList(
String query,String contentCountry, Downloader dl)
throws ExtractionException, IOException;
//Result search(String query, int page);
Result search(String query, int page, String contentCountry, Downloader dl)
public abstract StreamPreviewInfoCollector search(
String query, int page, String contentCountry, Downloader dl)
throws ExtractionException, IOException;
}

View File

@@ -0,0 +1,47 @@
package org.schabi.newpipe.extractor;
import java.io.IOException;
import java.util.List;
import java.util.Vector;
/**
* Created by Christian Schabesberger on 29.02.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* SearchResult.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 <http://www.gnu.org/licenses/>.
*/
public class SearchResult {
public static SearchResult getSearchResult(SearchEngine engine, String query,
int page, String languageCode, Downloader dl)
throws ExtractionException, IOException {
SearchResult result = engine.search(query, page, languageCode, dl).getSearchResult();
if(result.resultList.isEmpty()) {
if(result.suggestion.isEmpty()) {
throw new ExtractionException("Empty result despite no error");
} else {
// This is used as a fallback. Do not relay on it !!!
throw new SearchEngine.NothingFoundException(result.suggestion);
}
}
return result;
}
public String suggestion = "";
public final List<StreamPreviewInfo> resultList = new Vector<>();
public List<Exception> errors = new Vector<>();
}

View File

@@ -29,26 +29,43 @@ import org.schabi.newpipe.extractor.services.youtube.YoutubeService;
@SuppressWarnings("ALL")
public class ServiceList {
private ServiceList() {
}
private static final String TAG = ServiceList.class.toString();
private static final StreamingService[] services = {
new YoutubeService()
new YoutubeService(0)
};
public static StreamingService[] getServices() {
return services;
}
public static StreamingService getService(int serviceId) {
return services[serviceId];
public static StreamingService getService(int serviceId) throws ExtractionException {
for(StreamingService s : services) {
if(s.getServiceId() == serviceId) {
return s;
}
}
throw new ExtractionException("Service not known: " + Integer.toString(serviceId));
}
public static StreamingService getService(String serviceName) {
public static StreamingService getService(String serviceName) throws ExtractionException {
return services[getIdOfService(serviceName)];
}
public static int getIdOfService(String serviceName) {
public static String getNameOfService(int id) {
try {
return getService(id).getServiceInfo().name;
} catch (Exception e) {
System.err.println("Service id not known");
e.printStackTrace();
return "";
}
}
public static int getIdOfService(String serviceName) throws ExtractionException {
for(int i = 0; i < services.length; i++) {
if(services[i].getServiceInfo().name.equals(serviceName)) {
return i;
}
}
Log.e(TAG, "Error: Service " + serviceName + " not known.");
return -1;
throw new ExtractionException("Error: Service " + serviceName + " not known.");
}
}

Some files were not shown because too many files have changed in this diff Show More