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

Compare commits

...

308 Commits

Author SHA1 Message Date
Christian Schabesberger
aa06e3490d Merge branch 'master' of github.com:theScrabi/NewPipe 2016-01-08 22:22:55 +01:00
Christian Schabesberger
ece889b36b moved on to 0.7.3 2016-01-08 22:22:39 +01:00
Christian Schabesberger
9848f19ce6 Merge github.com:k3b/NewPipe into k3bMaster 2016-01-08 22:04:42 +01:00
Weblate
e59b087057 Merge remote-tracking branch 'origin/master' 2016-01-08 22:00:27 +01:00
Greg
5b451d1ac7 Translated using Weblate (Spanish)
Currently translated at 64.2% (36 of 56 strings)
2016-01-08 22:00:27 +01:00
Greg
f050c05b3c Translated using Weblate (Russian)
Currently translated at 98.2% (55 of 56 strings)
2016-01-08 22:00:27 +01:00
Sérgio Marques
06b8edefbf Translated using Weblate (Portuguese)
Currently translated at 100.0% (56 of 56 strings)
2016-01-08 22:00:26 +01:00
Greg
f3a2a28398 Translated using Weblate (German)
Currently translated at 91.0% (51 of 56 strings)
2016-01-08 22:00:26 +01:00
Greg
9b0a1fc2ec Translated using Weblate (English)
Currently translated at 100.0% (56 of 56 strings)
2016-01-08 22:00:26 +01:00
riotism
c87ab234eb Translated using Weblate (Chinese (Taiwan))
Currently translated at 100.0% (56 of 56 strings)
2016-01-08 22:00:25 +01:00
riotism
68468756a8 Translated using Weblate (Chinese (Hong Kong))
Currently translated at 100.0% (56 of 56 strings)
2016-01-08 22:00:24 +01:00
riotism
9016df0195 Translated using Weblate (Chinese (China))
Currently translated at 100.0% (56 of 56 strings)
2016-01-08 22:00:24 +01:00
Christian Schabesberger
7acece9705 Merge pull request #145 from 42SK/master
Fixed #143
2016-01-08 22:00:21 +01:00
red
d1896c23c0 Translated using Weblate (French)
Currently translated at 100.0% (56 of 56 strings)
2016-01-08 14:04:29 +01:00
riotism
dae19f03e0 Translated using Weblate (Chinese (China))
Currently translated at 100.0% (56 of 56 strings)
2016-01-07 23:07:42 +01:00
riotism
9dafccf0f7 Translated using Weblate (Chinese (China))
Currently translated at 100% (0 of 0 strings)

Created new translation.
2016-01-07 22:46:44 +01:00
riotism
5f270c41ae Translated using Weblate (Chinese (Taiwan))
Currently translated at 100.0% (56 of 56 strings)
2016-01-07 22:46:12 +01:00
riotism
f9f80e9003 Translated using Weblate (Chinese (Taiwan))
Currently translated at 100% (0 of 0 strings)

Created new translation.
2016-01-07 22:08:02 +01:00
riotism
c5063d4269 Translated using Weblate (Chinese (Hong Kong))
Currently translated at 100.0% (56 of 56 strings)
2016-01-07 22:06:57 +01:00
riotism
ccbe18ec1c Translated using Weblate (Chinese (Hong Kong))
Currently translated at 100% (0 of 0 strings)

Created new translation.
2016-01-07 21:21:58 +01:00
k3b
321a8a8b25 Translated using Weblate (German)
Currently translated at 91.0% (51 of 56 strings)
2016-01-07 20:20:57 +01:00
k3b
77a9560376 #143 #44 #42 #22: Fixed some download problems with invalid directories or filenames. Added user Feedback. Different settings for audio and video download dir. 2016-01-07 14:32:16 +01:00
k3b
058a039a82 #143 #44 #42 #22: Fixed some download problems with invalid directories or filenames. Added user Feedback. Different settings for audio and video download dir. 2016-01-07 14:22:55 +01:00
naofum
7c744703e4 Translated using Weblate (Japanese)
Currently translated at 100.0% (56 of 56 strings)
2016-01-07 14:15:56 +01:00
42SK
a934cbb085 Fixed #143 2016-01-07 13:28:17 +01:00
Sérgio Marques
cf4158c0d0 Translated using Weblate (Portuguese)
Currently translated at 100.0% (56 of 56 strings)
2016-01-07 00:48:13 +01:00
M2ck
dc56eab9b6 Translated using Weblate (French)
Currently translated at 100.0% (56 of 56 strings)
2016-01-06 16:47:54 +01:00
Weblate
37d1f59132 Merge remote-tracking branch 'origin/master' 2016-01-06 15:13:03 +01:00
Christian Schabesberger
ab0ce55411 merge unitTesting 2016-01-06 15:13:55 +01:00
Matej U
c1d66596d1 Translated using Weblate (Slovenian)
Currently translated at 100.0% (56 of 56 strings)
2016-01-06 15:13:03 +01:00
Mladen Pejaković
cbfccdf0d3 Translated using Weblate (Serbian)
Currently translated at 100.0% (56 of 56 strings)
2016-01-06 15:13:02 +01:00
Christian Schabesberger
9362037177 remove theme option since it's not yet working 2016-01-06 15:00:33 +01:00
Matej U
e25c93bae2 Translated using Weblate (Slovenian)
Currently translated at 100.0% (56 of 56 strings)
2016-01-06 09:28:10 +01:00
Mladen Pejaković
367c434010 Translated using Weblate (Serbian)
Currently translated at 100.0% (56 of 56 strings)
2016-01-05 23:54:30 +01:00
chschtsch
02d8463e15 rename resource 2016-01-06 00:02:10 +03:00
Christian Schabesberger
9d5a1d5c43 removed unnececeary comment 2016-01-05 21:54:40 +01:00
Christian Schabesberger
c8d94f541f resolved merge conflict 2016-01-05 21:50:25 +01:00
Christian Schabesberger
27d06eaa6b removed hardcoded string, and add licece to some files. 2016-01-05 21:41:55 +01:00
Christian Schabesberger
7f32857e00 buxfix 2016-01-05 21:23:16 +01:00
chschtsch
2f060f0f52 merging with eb0df2b 2016-01-05 23:16:50 +03:00
chschtsch
f89d405226 merging with eb0df2b 2016-01-05 23:13:52 +03:00
chschtsch
fd4459e570 Merge branch 'master' of github.com:theScrabi/NewPipe 2016-01-05 23:12:22 +03:00
Christian Schabesberger
eb0df2b101 set download path on startup 2016-01-05 21:11:15 +01:00
chschtsch
6c178cfb7e add back missing like button margin 2016-01-05 23:09:15 +03:00
chschtsch
8ced68430d update resources names to match naming convention & cleanup & start working on themes 2016-01-05 22:56:40 +03:00
Aitor Beriain
0aade598ff Translated using Weblate (Basque)
Currently translated at 100.0% (53 of 53 strings)
2016-01-04 20:02:01 +01:00
Aitor Beriain
95949fd1ab Translated using Weblate (Basque)
Currently translated at 100% (0 of 0 strings)

Created new translation.
2016-01-04 19:35:11 +01:00
naofum
1a56382112 Translated using Weblate (Japanese)
Currently translated at 100.0% (53 of 53 strings)
2016-01-04 11:51:32 +01:00
Adam Howard
d610e4b19b minor code tweaks to BackgroundPlayer 2016-01-04 01:51:24 +00:00
Adam Howard
fc44d9e36e Merge branch 'master' of github.com:theScrabi/NewPipe 2016-01-04 01:15:33 +00:00
Adam Howard
c07686576a possible fix for expandedView bug in BackgroundPlayer 2016-01-04 01:15:13 +00:00
Weblate
c2400aea4d Merge remote-tracking branch 'origin/master' 2016-01-04 00:11:51 +01:00
Benedikt Geißler
fb4bf0dde4 Translated using Weblate (German)
Currently translated at 98.1% (52 of 53 strings)
2016-01-04 00:11:51 +01:00
Christian Schabesberger
e4f638d1ce Merge branch 'master' of github.com:theScrabi/NewPipe 2016-01-04 00:11:00 +01:00
Christian Schabesberger
5c492c01a1 adjusted orbot support and moved on to 0.7.2 2016-01-04 00:10:51 +01:00
M2ck
f451e11f82 Translated using Weblate (French)
Currently translated at 100.0% (53 of 53 strings)
2016-01-03 20:55:44 +01:00
Adam Howard
95b73f35f7 Merge branch 'master' of github.com:theScrabi/NewPipe 2016-01-03 19:44:13 +00:00
Adam Howard
58147e9e12 removed commented code in BackgroundPlayer 2016-01-03 19:44:04 +00:00
Christian Schabesberger
a8830e2ede preference screen previews set values 2016-01-03 19:55:04 +01:00
Mladen Pejaković
9804bb95cc Translated using Weblate (Serbian)
Currently translated at 100.0% (53 of 53 strings)
2016-01-03 19:12:16 +01:00
Christian Schabesberger
0da1aef763 Merge pull request #136 from eighthave/tor-support-for-all-except-streaming
Tor support for all except streaming
2016-01-03 17:40:02 +01:00
M2ck
0a334804a3 Translated using Weblate (French)
Currently translated at 100.0% (51 of 51 strings)
2016-01-03 16:56:51 +01:00
naofum
94d2f03e9b Translated using Weblate (Japanese)
Currently translated at 100.0% (51 of 51 strings)
2016-01-03 10:31:40 +01:00
Hans-Christoph Steiner
9127f7f0c2 make progress notification for Tor downloader (closes #39) 2016-01-03 00:04:55 +01:00
Hans-Christoph Steiner
0bb0226bc2 download files via Tor when Tor is enabled
DownloadManager does not let you set its proxy or change how it connects to
the internet.  So we have to make a custom one, unfortunately.  This is a
very basic downloader with none of the special sauce that makes the
built-in DownloadManager handy.
2016-01-02 22:47:21 +01:00
Hans-Christoph Steiner
b3a1a5dcc2 Android provides global vars for the actual download directories 2016-01-02 21:53:48 +01:00
Hans-Christoph Steiner
984dd1cc25 checking on "Use Tor" when Orbot is not installed starts install
If the user turns on "Use Tor" and they are missing Orbot, bring them to
the screen to install Tor.
2016-01-02 21:21:34 +01:00
Hans-Christoph Steiner
5663e543a4 whenever an Activity resumes and tor is enabled, request it start
This makes sure that Orbot is running when the user expects it to be. If
NewPipe is configured to use Tor, then going to a NewPipe screen should
ensure Tor is running.
2016-01-02 21:21:34 +01:00
Hans-Christoph Steiner
d3879a0398 setup Tor at app start, and config immediately when pref is changed
This adds an Application subclass to get the onCreate() method, which is
called once at the first start up of the app, before any Activity starts.
Tor is configured there to ensure it is setup before anything happens.

This also moves the "Use Tor" pref listener to a more appropriate place.
2016-01-02 21:21:34 +01:00
Hans-Christoph Steiner
6bd2468d44 if Orbot is installed, then default to using Tor
If the user has not changed the "Use Tor" preference, then the default
should be to use Tor if Orbot is installed. The user can still override it
by going an unchecking "Use Tor".
2016-01-02 21:21:34 +01:00
Hans-Christoph Steiner
e63d43151b add a title plus summary to "Use Tor" preference 2016-01-02 21:21:33 +01:00
Hans-Christoph Steiner
0265da4ae6 use HttpsURLConnections since youtube.com always uses HTTPS
This helps enforce that the connection is encrypted. If for whatever reason
an unencrypted connection is created, an Exception will be thrown.
2016-01-02 21:21:28 +01:00
GDR!
ef255d12ae Test tor code 2016-01-02 20:22:05 +01:00
Matej U
eeb612f9a2 Translated using Weblate (Slovenian)
Currently translated at 100.0% (51 of 51 strings)
2016-01-02 19:48:51 +01:00
Mladen Pejaković
dfcb4edb81 Translated using Weblate (Serbian)
Currently translated at 100.0% (51 of 51 strings)
2016-01-02 18:04:01 +01:00
Christian Schabesberger
d3500e9036 removed onion routing from readme 2016-01-02 17:41:33 +01:00
Christian Schabesberger
adcb8c6469 add c3s thumbnail and moved on to 0.7.1 2016-01-02 17:40:58 +01:00
Christian Schabesberger
592eee7d3d Merge pull request #134 from eighthave/intent-filters-and-other-fixes
Intent filters and other fixes
2016-01-02 16:18:56 +01:00
Christian Schabesberger
7dadb2b26c fixed close notification problem 2016-01-02 16:08:18 +01:00
Hans-Christoph Steiner
7cbb135f28 include Tibetan as a language option
The Tibetan alphabet was only recently included on Android, so the language
name needs to also have the English there.  Otherwise it'll appear blank
on devices without Tibetan.
2016-01-02 12:15:56 +01:00
Hans-Christoph Steiner
966ac0673c gradle.properties is only commented out defaults, so remove from git
For anyone who tweaks this file for local settings, it becomes painful
to have it committed in git because those changes which are only
relevant to the local setup will show up in git as changed.
2016-01-02 01:35:29 +01:00
Hans-Christoph Steiner
d715eae0d1 route video downloads to "Movies" and audio to "Music"
use the standard Android folders when downloading files.
2016-01-02 01:34:18 +01:00
Hans-Christoph Steiner
ccdd13d136 youtube URLs can also come from media searches and NFC sends 2016-01-02 00:15:27 +01:00
Hans-Christoph Steiner
efe5de4c75 support youtube's custom URL schemes (vnd.youtube: and vnd.youtube.launch:) 2016-01-02 00:15:27 +01:00
Hans-Christoph Steiner
2a93e9bd2e precisely target these URLs https://www.youtube.com/watch?v=mS1gstS6YS8
These URLs have a Path that always starts with "/watch" so no need for a
pattern.  Also, everything after the "?" is considered the "Query String",
not the Path.  Anything after a "#" is the "Feature String".  The path
matching in IntentFilters only see the Path, and nothing from the "Query
String" or "Feature String".

these are the available kinds of URLs:
https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/YouTubeLinks/YouTubeLinks.html
2016-01-02 00:15:27 +01:00
Hans-Christoph Steiner
28dd53ae50 support another youtube URL format: https://www.youtube.com/v/mS1gstS6YS8
https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/YouTubeLinks/YouTubeLinks.html
2016-01-02 00:15:27 +01:00
Hans-Christoph Steiner
3c1e64d8dc simplify youtube URL IntentFilters
Each <data> elements applies to the whole IntentFilter, so there is no need
to declare the host, scheme, etc. multiple times within a single
IntentFilter.

Also, pathPrefix="/" will match all paths, so it is unnecessary.
2016-01-02 00:15:27 +01:00
Hans-Christoph Steiner
4fe3cb2bca use symlinks to provide alternate folders for Hebrew and Indonesian
These two languages must be included twice (iw/he and id/in)

For a full discussion of why, see:
https://gitlab.com/fdroid/fdroidclient/issues/139
https://stackoverflow.com/questions/5074769/cyanogenmod-translate-a-project/8470980#8470980
https://stackoverflow.com/questions/8393771/android-not-using-finding-my-hebrew-localization

I included a blank placeholder file for Indonesian, it can be simply
replaced by the real one, whenever that comes along.
2016-01-02 00:15:27 +01:00
Hans-Christoph Steiner
b31490c4e3 make all strings translatable 2016-01-02 00:14:35 +01:00
Hans-Christoph Steiner
5533f6ba86 use the standard "Movies" folder for downloads
On all of the devices that I've checked, there is a folder called "Movies"
on the SD Card by default.  NewPipe should use that standard location
since it is always downloading movies :).  People can always change that
via the preferences.

Also, this makes the defaults the same when creating the dir and when
setting the destination URL.
2016-01-02 00:14:11 +01:00
Weblate
8aa5f87a1c Merge remote-tracking branch 'origin/master' 2016-01-01 15:47:36 +01:00
Greg
6deb674377 Translated using Weblate (Hebrew)
Currently translated at 16.6% (8 of 48 strings)
2016-01-01 15:47:36 +01:00
Christian Schabesberger
12d1d998a3 Merge pull request #133 from eighthave/panic-button-support
allow "panic button" apps to wipe activity
2016-01-01 15:47:32 +01:00
Christian Schabesberger
d90162d06f ugly workaround for GEMA test failing 2016-01-01 15:43:06 +01:00
Christian Schabesberger
97c924341c inital YoutubeExtractor test 2016-01-01 15:26:03 +01:00
Hans-Christoph Steiner
e91fc225e1 after receiving panic trigger, quit remove from history
This makes the app fully exit, and removes it from the Recent Apps listing
with the goal of hiding whatever the user was currently watching, and/or
searching for.

PanicKit provides a common framework for creating "panic button" apps that
can trigger actions in "panic responder" apps.  In this case, the response
is to lock the app, if it has been configured to do so

https://dev.guardianproject.info/projects/panic/wiki
2015-12-31 21:53:14 +01:00
M2ck
43149fd832 Translated using Weblate (French)
Currently translated at 100.0% (48 of 48 strings)
2015-12-31 10:27:52 +01:00
Greg
78df579703 Translated using Weblate (Hebrew)
Currently translated at 100% (0 of 0 strings)

Created new translation.
2015-12-29 21:45:44 +01:00
Greg
f61b915894 Translated using Weblate (Russian)
Currently translated at 100.0% (48 of 48 strings)
2015-12-29 21:45:08 +01:00
Christian Schabesberger
cd3f405bff slightly improved YoutubeSearchEngineTest 2015-12-29 21:41:10 +01:00
Christian Schabesberger
7cfdca7a81 remove failing test again 2015-12-29 21:28:27 +01:00
Christian Schabesberger
216063dba8 test if CI failes on failing test 2015-12-29 21:16:18 +01:00
Christian Schabesberger
b647bacd72 add testcase for YoutubeSearchEngine 2015-12-29 21:05:02 +01:00
Christian Schabesberger
4f77937e3e Merge pull request #131 from chschtsch/refactor
refactor localization
2015-12-29 19:14:55 +01:00
chschtsch
48e299b2ac code cleanup 2015-12-29 17:53:24 +03:00
chschtsch
40f00af196 refactor localization 2015-12-29 17:35:51 +03:00
Christian Schabesberger
bd6cc22e63 small hacky error handling refactoring, and add link to c3s 2015-12-28 00:32:38 +01:00
naofum
8760792426 Translated using Weblate (Japanese)
Currently translated at 100.0% (48 of 48 strings)
2015-12-26 12:33:33 +01:00
Christian Schabesberger
870b0bf7aa Merge pull request #127 from 912d/download-directory
Added visible notification after succesful download
2015-12-25 21:27:45 +01:00
Jacek Musiał
afd0bd4318 Added visible notification after succesful downloads
After succesful download, notification will stay in notification bar. I
used "VISIBILITY_VISIBLE_NOTIFY_COMPLETED"  key.
2015-12-25 19:28:09 +01:00
Jacek Musiał
f829ac1d34 Merge remote-tracking branch 'refs/remotes/theScrabi/master' into download-directory 2015-12-25 19:25:13 +01:00
Christian Schabesberger
86a0177855 Merge pull request #126 from Adam77Root/master
Fix view count parsing for large numbers
2015-12-25 16:02:10 +01:00
Adam77Root
718d4fd0bd Fix view count parsing for large numbers 2015-12-25 15:03:11 +01:00
Mladen Pejaković
365137c32b Translated using Weblate (Serbian)
Currently translated at 100.0% (48 of 48 strings)
2015-12-25 00:22:26 +01:00
Christian Schabesberger
e83ca0dfda some improvements for background player 2015-12-25 00:09:35 +01:00
Christian Schabesberger
6a9f6ef651 Merge pull request #123 from 912d/download-directory
Added check if directory exist and try create it
2015-12-23 23:20:42 +01:00
Jacek Musiał
99122ccc03 added check if directory exist and try create it
Also I added new variable `'final File dir`' with value of key
"download_path_preference" or externalStorageDirectory.
Firstly I check if dir exits, then eventually try to create it and next
- download file.
2015-12-23 17:52:01 +01:00
Christian Schabesberger
97923697e1 fixed small writing erros in the README 2015-12-23 14:31:57 +01:00
Greg
68888b15e0 Merge pull request #121 from chschtsch/master
fix sw600dp-land layout problem (#120)
2015-12-23 13:53:42 +03:00
Greg
f48b26067b Update README.md 2015-12-23 11:31:14 +03:00
Greg
4bf2d5837d Update and rename contributing.md to CONTRIBUTING.md 2015-12-23 11:31:11 +03:00
Weblate
4eb2d09c75 Merge remote-tracking branch 'origin/master' 2015-12-22 19:39:49 +01:00
Jack Musial
a146c1c4b6 Translated using Weblate (Polish)
Currently translated at 100.0% (47 of 47 strings)
2015-12-22 19:39:48 +01:00
Sorry Keep Me Anonymous
2f1ea9aa5d Translated using Weblate (Dutch)
Currently translated at 97.8% (46 of 47 strings)
2015-12-22 19:39:48 +01:00
Greg
a90da62deb Merge pull request #122 from rrooij/contributing_guidelines
Add contribution guidelines
2015-12-22 21:39:45 +03:00
Jack Musial
c1c3fbdf26 Translated using Weblate (Polish)
Currently translated at 100.0% (47 of 47 strings)
2015-12-22 18:50:33 +01:00
rrooij
e07a824d82 Add contribution guidelines
Contribution guidelines are a helpful way to inform new potential
contributors about the way in which they can help with the project.

It's also a helpful way to enforce some consistent coding style and
quality among the contributions.
2015-12-22 16:14:56 +01:00
chschtsch
2aff660a5b fix sw600dp-land layout problem (#120) 2015-12-22 15:11:28 +03:00
Weblate
abfcbe6f0e Merge remote-tracking branch 'origin/master' 2015-12-21 22:04:25 +01:00
Matej U
28bf72ed75 Translated using Weblate (Slovenian)
Currently translated at 100.0% (47 of 47 strings)
2015-12-21 22:04:25 +01:00
naofum
21b054d4ca Translated using Weblate (Japanese)
Currently translated at 100.0% (47 of 47 strings)
2015-12-21 22:04:25 +01:00
Greg
34f115b322 remove broken screenshot links 2015-12-22 00:04:22 +03:00
naofum
8b67354076 Translated using Weblate (Japanese)
Currently translated at 100.0% (47 of 47 strings)
2015-12-21 16:20:39 +01:00
M2ck
b62e0a8b40 Translated using Weblate (French)
Currently translated at 100.0% (47 of 47 strings)
2015-12-21 14:20:07 +01:00
Matej U
f46d5376fe Translated using Weblate (Slovenian)
Currently translated at 100.0% (47 of 47 strings)
2015-12-21 13:39:59 +01:00
Matej U
dc3640578f Translated using Weblate (Slovenian)
Currently translated at 100% (0 of 0 strings)

Created new translation.
2015-12-21 13:07:59 +01:00
Sérgio Marques
0a43494de5 Translated using Weblate (Portuguese)
Currently translated at 100.0% (47 of 47 strings)
2015-12-20 22:46:22 +01:00
Sérgio Marques
2544e45d2d Translated using Weblate (Portuguese)
Currently translated at 100% (0 of 0 strings)

Created new translation.
2015-12-20 22:37:30 +01:00
Mladen Pejaković
4a53e9e018 Translated using Weblate (Serbian)
Currently translated at 100.0% (47 of 47 strings)
2015-12-20 22:21:12 +01:00
Christian Schabesberger
9d7dc99416 Update README.md 2015-12-20 21:32:37 +01:00
Christian Schabesberger
c89dc4ba5b setup for version 0.7.0 2015-12-20 21:28:07 +01:00
Christian Schabesberger
72289ced39 Merge branch 'backgroundPlayback' 2015-12-20 18:16:28 +01:00
Christian Schabesberger
3554ccde05 small adjustment before merg 2015-12-20 18:15:48 +01:00
Christian Schabesberger
73e2c42931 Merge pull request #118 from joshsoftware/master
Adding the loading screen when user scroll through videoList.
2015-12-20 13:35:10 +01:00
Christian Schabesberger
b11778ec55 some post changes on the can't play fix. 2015-12-20 13:33:39 +01:00
Christian Schabesberger
18bc937958 fixed "Can't play this video." bug. 2015-12-20 13:26:12 +01:00
Christian Schabesberger
9f618f6678 fixed loding circle for android5+ 2015-12-20 12:48:06 +01:00
Christian Schabesberger
0c3c7493de second try of fixing the failing build 2015-12-20 02:21:14 +01:00
Christian Schabesberger
8f3f02e9f7 Update .travis.yml 2015-12-20 02:13:42 +01:00
Adam Howard
69903ba889 added preference to switch between external and internal audio players 2015-12-20 00:31:31 +00:00
Adam Howard
25c5f95ad9 added white play button icon for notification controls; pause button soon to follow.
Some checks for audioStreams being null added, along with minor semnatic restructuring of parseDashManifest()
2015-12-20 00:08:12 +00:00
Sanjiv Jha
2546d1107e Merge branch 'master' of github.com:joshsoftware/NewPipe 2015-12-19 20:19:19 +05:30
Sanjiv Jha
fdbeaf8692 Added loading footer on paginate screen 2015-12-19 20:18:28 +05:30
naofum
63c0316af2 Translated using Weblate (Japanese)
Currently translated at 100.0% (46 of 46 strings)
2015-12-18 17:10:36 +01:00
Adam Howard
f2e761c07c added reacquisition of CPU lock after resuming 2015-12-17 18:27:35 +00:00
Adam Howard
6a741de7d1 removed commented-out example code 2015-12-17 18:04:18 +00:00
Adam Howard
3e94d18fe1 removed accidental 'git merge' command from manifest 2015-12-17 18:01:24 +00:00
Adam Howard
95d3651e29 Merge branch 'master' of github.com:theScrabi/NewPipe
Conflicts:
	app/src/main/AndroidManifest.xml
2015-12-17 17:53:54 +00:00
Adam Howard
cd2d88781a implemented play/pause and cancel controls 2015-12-17 17:49:12 +00:00
Shekhar Sahu
2178e86d09 Merge branch 'master' of github.com:theScrabi/NewPipe 2015-12-16 14:58:28 +05:30
Christian Schabesberger
f9ad0f12d0 Fixed serveral things:
* ugly workaround for the details_view_layout problem on older devices
* removed "display button on the left side" option since it's not nececeay anymore.
2015-12-15 22:53:29 +01:00
M2ck
63b16d925d Translated using Weblate (French)
Currently translated at 100.0% (47 of 47 strings)
2015-12-15 14:28:58 +01:00
Greg
53b9ffcbc8 Translated using Weblate (Russian)
Currently translated at 100.0% (47 of 47 strings)
2015-12-15 14:25:10 +01:00
Shekhar Sahu
df01f41980 Merge branch 'master' of github.com:theScrabi/NewPipe 2015-12-15 17:52:33 +05:30
chschtsch
b0c40d3b09 update cards & update dimens structure 2015-12-15 17:13:43 +05:30
Christian Schabesberger
5880dcbcfd update README.md and readded (still) nececeary assets 2015-12-15 16:49:34 +05:30
Greg
489bbc45f5 Update README.md 2015-12-15 16:49:26 +05:30
chschtsch
5e67502729 add screenshots and new icon 2015-12-15 16:49:25 +05:30
Weblate
842079c928 Merge remote-tracking branch 'origin/master' 2015-12-15 11:57:58 +01:00
M2ck
b0bab07a15 Translated using Weblate (French)
Currently translated at 97.8% (46 of 47 strings)
2015-12-15 11:57:58 +01:00
chschtsch
4dbb12c65d update screenshots 2015-12-15 13:55:56 +03:00
chschtsch
db500e9791 fix layout issues & update screenshots 2015-12-15 13:45:59 +03:00
chschtsch
fd8f600fec update .travis.yml & move screenshots to separate folder 2015-12-15 13:04:51 +03:00
Luca Argentieri
2e2d7d02fb Translated using Weblate (Italian)
Currently translated at 100.0% (47 of 47 strings)
2015-12-14 23:03:17 +01:00
Luca Argentieri
d068cd7f75 Translated using Weblate (Italian)
Currently translated at 100% (0 of 0 strings)

Created new translation.
2015-12-14 22:38:11 +01:00
Christian Schabesberger
5a05ffcbdd Merge pull request #114 from chschtsch/cardview
Design update & refactoring
2015-12-14 20:24:22 +01:00
chschtsch
d8c7f50b39 minor layout fixes 2015-12-14 14:52:14 +03:00
chschtsch
988e6e1c82 update like buttons 2015-12-14 14:42:13 +03:00
chschtsch
f6af19444c update like buttons 2015-12-14 14:34:28 +03:00
chschtsch
0581e50e0c update viewlike buttons 2015-12-14 14:33:00 +03:00
chschtsch
a95da9a42d update views & dimens 2015-12-14 14:10:12 +03:00
chschtsch
be10b9750f mering with master 2015-12-14 13:44:15 +03:00
chschtsch
29a3cbc688 mering with master 2015-12-14 13:07:54 +03:00
chschtsch
4f57d3a201 merging with master 2015-12-14 13:01:34 +03:00
Christian Schabesberger
c9be1398b0 fixed green arrow layout error 2015-12-13 21:13:48 +01:00
halcyonest
30eef4db12 Translated using Weblate (Korean)
Currently translated at 100.0% (47 of 47 strings)
2015-12-13 13:51:55 +01:00
halcyonest
b932dbf514 Translated using Weblate (Korean)
Currently translated at 100% (0 of 0 strings)

Created new translation.
2015-12-13 13:40:17 +01:00
chschtsch
320ac82dea merging with master 2015-12-11 14:01:04 +03:00
Christian Schabesberger
af1b21db23 code_lint and moved on to v0.6.1 2015-12-09 23:17:29 +01:00
Christian Schabesberger
0e892ff60e code_lint 2015-12-09 22:31:24 +01:00
Christian Schabesberger
074963aee0 put progressbar on top of thumbnail and made it red 2015-12-09 22:14:22 +01:00
Christian Schabesberger
37d9be9095 put fab button on top of video thumbnail 2015-12-08 21:29:29 +01:00
Adam Howard, from my DSABang
26e36454ef merged changes from master 2015-12-03 14:39:51 +00:00
Christian Schabesberger
78b95f67eb made content scroll over thumbnail 2015-12-02 21:20:52 +01:00
chschtsch
6c63841d0c update video detail layout 2015-12-02 21:55:57 +03:00
chschtsch
6ec2d91d91 fix card margin as well 2015-12-02 17:36:20 +03:00
chschtsch
3299b90c20 better padding for landscape card 2015-12-02 17:33:58 +03:00
chschtsch
7b6d6da9a6 improve card margin & edit its dimensions for landscape 2015-12-02 17:26:20 +03:00
chschtsch
7c7c61fc35 use singleLine instead of manually setting height 2015-12-02 17:18:40 +03:00
chschtsch
c5408fb6b8 finally make card layout look good 2015-12-02 17:13:01 +03:00
chschtsch
1c49102f67 update card layout 2015-12-02 17:00:37 +03:00
chschtsch
f9dd88c1cb remove divider from listview 2015-12-02 16:29:58 +03:00
chschtsch
9ed4a65fd2 move all dimensions do dimens.xml 2015-12-02 16:23:31 +03:00
chschtsch
10bebf8a89 update cards & update dimens structure 2015-12-02 15:27:19 +03:00
chschtsch
36260dac18 tryna add cardview 2015-12-02 13:08:43 +03:00
Christian Schabesberger
2e4e993967 removed unececeary commends 2015-12-02 00:19:47 +01:00
Christian Schabesberger
ef1bfe98f7 try to fix timeout error 2015-12-02 00:11:39 +01:00
Christian Schabesberger
2e123aa617 try to get emulator running part 2 2015-12-01 23:55:07 +01:00
Christian Schabesberger
cf2ef0f2a8 try to get emulator running 2015-12-01 23:48:41 +01:00
Christian Schabesberger
520f40d862 fiexed travis build error 2015-12-01 23:16:58 +01:00
Christian Schabesberger
856bdac84b Merge branch 'master' of github.com:theScrabi/NewPipe 2015-12-01 22:32:55 +01:00
Christian Schabesberger
deb7e38fcf fixed travis.yml error 2015-12-01 22:32:44 +01:00
Weblate
e5f47a4563 Merge remote-tracking branch 'origin/master' 2015-12-01 21:56:17 +01:00
Roland Sawicki
d1b465d8be Translated using Weblate (Polish)
Currently translated at 100.0% (47 of 47 strings)
2015-12-01 21:56:17 +01:00
Christian Schabesberger
5c73b2f324 trigger first CI pull 2015-12-01 21:35:18 +01:00
Christian Schabesberger
7d3e992b3f init CI 2015-12-01 21:31:10 +01:00
Christian Schabesberger
296640930e fixed some spelling errors 2015-12-01 18:50:57 +01:00
Christian Schabesberger
1c42735e3a fixed screenshot error -.- 2015-12-01 18:37:50 +01:00
Christian Schabesberger
0800bc1790 post edit README.md 2015-12-01 18:36:39 +01:00
Christian Schabesberger
bd76a12b90 update README.md and readded (still) nececeary assets 2015-12-01 18:23:06 +01:00
Christian Schabesberger
d3daea6383 Merge pull request #107 from chschtsch/refactor
Slightly update readme file + add screenshots
2015-12-01 17:52:57 +01:00
naofum
df1acd5413 Translated using Weblate (Japanese)
Currently translated at 100.0% (47 of 47 strings)
2015-12-01 14:38:28 +01:00
Greg
0d65cc09f6 Merge pull request #9 from chschtsch/master
.
2015-12-01 12:59:16 +03:00
Greg
892b082b9e Update README.md 2015-12-01 12:58:47 +03:00
Mladen Pejaković
9069ef1325 Translated using Weblate (Serbian)
Currently translated at 100.0% (47 of 47 strings)
2015-11-30 22:24:17 +01:00
Roland Sawicki
47cc493ab5 Translated using Weblate (Polish)
Currently translated at 100.0% (47 of 47 strings)
2015-11-30 22:08:09 +01:00
Greg
f43d7837f8 Merge pull request #8 from chschtsch/refactor
Refactor
2015-11-30 23:56:14 +03:00
Greg
91921ae672 Update README.md 2015-11-30 23:55:24 +03:00
Greg
eba6afc12b Merge pull request #7 from chschtsch/master
.
2015-11-30 23:52:52 +03:00
Greg
ff826a9eeb Update README.md 2015-11-30 23:49:13 +03:00
Greg
6c01a30af5 Merge pull request #5 from chschtsch/refactor
edit screenshots
2015-11-30 23:43:09 +03:00
Greg
53f8d09d31 Merge pull request #6 from chschtsch/master
.
2015-11-30 23:42:54 +03:00
chschtsch
ae191aaafe edit screenshots 2015-11-30 23:40:44 +03:00
Greg
d1694d563b Update README.md 2015-11-30 23:40:29 +03:00
Greg
75fadf79da Delete gruese_die_gema_original.png 2015-11-30 23:38:30 +03:00
Greg
23ce5a6b1e Merge pull request #4 from chschtsch/refactor
add screenshots and new icon
2015-11-30 23:36:29 +03:00
chschtsch
bb65e2b84d add screenshots and new icon 2015-11-30 23:32:10 +03:00
Greg
aa42b1d95a Update README.md 2015-11-30 23:08:28 +03:00
Greg
32d5a18198 Update README.md 2015-11-30 23:07:07 +03:00
Greg
63faefe9c3 Update README.md 2015-11-30 23:01:55 +03:00
syl0s
a90c49d030 Translated using Weblate (German)
Currently translated at 100.0% (47 of 47 strings)
2015-11-30 20:57:19 +01:00
Christian Schabesberger
b1ef3fa4df Translated using Weblate (German)
Currently translated at 100.0% (47 of 47 strings)
2015-11-30 20:55:15 +01:00
Greg
b8cf67cba9 Merge pull request #3 from theScrabi/master
.
2015-11-30 22:53:01 +03:00
Weblate
4780e10ade Merge remote-tracking branch 'origin/master' 2015-11-30 20:51:43 +01:00
Roland Sawicki
401e606fbc Translated using Weblate (Polish)
Currently translated at 95.9% (47 of 49 strings)
2015-11-30 20:51:43 +01:00
syl0s
6b4ef8f397 Translated using Weblate (German)
Currently translated at 100.0% (49 of 49 strings)
2015-11-30 20:51:41 +01:00
Greg
7c66d07779 Merge pull request #2 from theScrabi/master
pull from theScrabi/NewPipe
2015-11-30 22:51:20 +03:00
Christian Schabesberger
92aed0cc3a add link to slack group 2015-11-30 20:48:59 +01:00
Christian Schabesberger
457b08d3cc merge strings.xml collision 2015-11-30 20:00:28 +01:00
Christian Schabesberger
1e5f6fd2b8 merge code_lint 2015-11-30 19:47:21 +01:00
Adam Howard
aebfeb98aa sync so I can clone this branch on another machine 2015-11-29 17:05:44 +00:00
Christian Schabesberger
f6974e8315 code lint 2015-11-29 13:11:56 +01:00
Xenotium
2ce6313ac1 Forgot about quotes... 2015-11-29 11:49:47 +01:00
RACER
e98a113a59 Translated using Weblate (Japanese)
Currently translated at 100.0% (49 of 49 strings)
2015-11-28 15:16:15 +01:00
Mladen Pejaković
ba7bed9c2c Translated using Weblate (Serbian)
Currently translated at 100.0% (49 of 49 strings)
2015-11-27 23:47:01 +01:00
Xenotium
c9ea451c53 Make some strings non-translatable
Apart from app name, which at the moment is the same no matter what language, there are URLs here. They shouldn't reside here but make them (and the app name) at least "translatable=false".
2015-11-27 20:51:56 +01:00
Roland Sawicki
4261ff32c7 Translated using Weblate (Polish)
Currently translated at 100% (0 of 0 strings)

Created new translation.
2015-11-27 20:10:57 +01:00
Christian Schabesberger
cb4b20af45 use format strings now 2015-11-26 20:43:16 +01:00
Christian Schabesberger
b8a27adb93 removed unused resources 2015-11-26 20:22:45 +01:00
Christian Schabesberger
15b58128f4 fiexed lint layout suggestions 2015-11-26 20:16:23 +01:00
Christian Schabesberger
237282db28 refactored VideoPlayer theme 2015-11-26 19:54:13 +01:00
Christian Schabesberger
71bb59dbb8 update gradle/libs and use Perference.Editor.apply() instead of commit() 2015-11-26 19:36:14 +01:00
Christian Schabesberger
e41c46c075 made lint ignore that parentActivityName is not compatible to sdk 15 2015-11-26 19:28:50 +01:00
Christian Schabesberger
6ca9e52f2f made lint ignore some code and layout warnings 2015-11-26 19:11:31 +01:00
Christian Schabesberger
2afee89de3 added contentDescription for better accesebility 2015-11-26 18:47:36 +01:00
Christian Schabesberger
189bee3e44 named drawable folder drawable-nodpi and moved orig. gema image to assets 2015-11-26 18:37:40 +01:00
Christian Schabesberger
6b9a4d5e0a add ellipsis character to spanish translation 2015-11-26 18:32:06 +01:00
Christian Schabesberger
451e2b2182 removed hardcoded strings 2015-11-26 18:29:00 +01:00
Christian Schabesberger
f6ff41cfb4 removed obsolete translations 2015-11-26 18:26:28 +01:00
Christian Schabesberger
d6d144c927 renamed Extractor into VideoExtractor 2015-11-26 17:29:26 +01:00
Christian Schabesberger
7f86872139 Categorized settings & moved AbstractVideoInfo into service folder 2015-11-25 21:08:19 +01:00
Adam Howard
dc0fc05a9e cleaned up BackgroundPlayer code a little 2015-11-25 17:36:01 +00:00
Adam Howard
6b2c3217ab Implemented a playback notification with a progress bar. No playback controls yet. 2015-11-25 17:18:01 +00:00
Adam Howard
0f93a45b9d reimplemented BackgroundPlayer extending Service, not IntentService. See http://stackoverflow.com/questions/17237746 and http://stackoverflow.com/questions/8690198 2015-11-25 15:19:50 +00:00
Adam Howard
943027ffdd implemented stage 1 ultra-basic background play of videos; see https://github.com/theScrabi/NewPipe/wiki/Background-Playback-Mini-Roadmap 2015-11-24 00:40:36 +00:00
Greg
5d28b2400f Merge pull request #1 from theScrabi/master
merge from theScrabi/NewPipe
2015-11-23 23:02:30 +03:00
Weblate
67324bfc80 Merge remote-tracking branch 'origin/master' 2015-11-22 13:24:52 +01:00
syl0s
3c340e7144 Translated using Weblate (German)
Currently translated at 97.8% (45 of 46 strings)
2015-11-22 13:24:51 +01:00
dostoi
c834405a92 Translated using Weblate (French)
Currently translated at 97.8% (45 of 46 strings)
2015-11-22 13:24:51 +01:00
Greg
4ee9e26847 Translated using Weblate (Dutch)
Currently translated at 100.0% (46 of 46 strings)
2015-11-22 13:24:50 +01:00
Adam Howard
94293ca9d9 Merge pull request #100 from theScrabi/refactor
+ Implemented timestamps
* 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 in `PlayVideoActivity` which only call `super()`, and therefore are unnecessary: `onResume()` and `onPostCreate(Bundle)`
+ Added `VideoInfo(AbstractVideoInfo)` constructor
    - to support converting `VideoPreviewInfo`s into `VideoInfo`s, to reuse scraped info (yet to be implemented)
* Made the Extractor class behave as a per-video object;
    - most method return values are video-specific, so it makes sense (to me) to have Extractor be stateful. 
    - The only stateless methods are getVideoUrl(), getVideoId() and loadDecryptionCode(String)
* Implemented a constructor for YoutubeExtractor, which performs all initialisation work, such as fetching `Jsoup.Document`, and `playerArgs:JSONObject`
2015-11-21 11:11:17 +00:00
Mladen Pejaković
b9cd9f8d35 Translated using Weblate (Serbian)
Currently translated at 100.0% (46 of 46 strings)
2015-11-20 18:45:03 +01:00
Adam Howard
812dd9282d Merge pull request #102 from chschtsch/refactor
fix bug with upload date + better way to parse it
2015-11-20 01:44:32 +00:00
chschtsch
fa1d386fcc cleanup 2015-11-20 00:52:43 +03:00
chschtsch
0392bf6a02 fix bug with upload date + better way to parse it 2015-11-20 00:49:52 +03:00
naofum
97f771ff50 Translated using Weblate (Japanese)
Currently translated at 100.0% (46 of 46 strings)
2015-11-19 16:20:26 +01:00
naofum
6adcc72a8a Translated using Weblate (Japanese)
Currently translated at 100% (0 of 0 strings)

Created new translation.
2015-11-19 16:17:28 +01:00
Adam Howard
2c11bd1889 fixed Bundle casting bug incurred during related videosdisplay 2015-11-19 14:40:35 +00:00
Adam Howard
23e0196fcc * fixed counterintuitive back button behaviour in PlayVideoActivity; see https://github.com/theScrabi/NewPipe/issues/99
* fixed a rarely-caused NullPointerException caused by a related video's view-count field being missing
2015-11-19 00:08:51 +00:00
Adam Howard
91f98c125e finished implementing timestamp, along with refactoring services
* added VideoInfo(AbstractVideoInfo) constructor, to support later implementation for reusing info scraped into VideoPreviewInfo, into VideoInfo
* Made the Extractor class behave as a per-video object;
    - most method return values are video-specific, so it makes sense (to me) to have Extractor be stateful.
    - The only stateless methods are getVideoUrl(), getVideoId() and loadDecryptionCode(String)
* Implemented a constructor for YoutubeExtractor, which performs all initialisation work
2015-11-17 22:51:27 +00:00
Adam Howard
7f01e9a4d9 Merge branch 'master' of github.com:theScrabi/NewPipe
translations
2015-11-16 23:45:42 +00:00
Adam Howard
320a4e2351 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)
2015-11-16 23:32:00 +00:00
Weblate
0829ce51fc Merge remote-tracking branch 'origin/master' 2015-11-16 17:36:14 +01:00
Mladen Pejaković
97ec50c202 Translated using Weblate (Serbian)
Currently translated at 100.0% (46 of 46 strings)
2015-11-16 17:36:12 +01:00
Adam Howard
975a3e8103 Merge branch 'master' of github.com:theScrabi/NewPipe 2015-11-16 14:18:12 +00:00
Christian Schabesberger
658ef2ef26 Merge pull request #97 from chschtsch/master
Update design
2015-11-15 11:49:49 +01:00
chschtsch
bd1e531d7b update design 2015-11-14 21:04:14 +03:00
chschtsch
e440d1d1bd update design 2015-11-14 20:55:28 +03:00
chschtsch
2110020165 update design 2015-11-14 20:48:42 +03:00
chschtsch
dac74dc30d Merge github.com:chschtsch/NewPipe 2015-11-14 20:12:11 +03:00
chschtsch
fa4b971254 update .gitignore 2015-11-14 20:11:41 +03:00
Greg
2d31ae0baa Delete NewPipe.iml 2015-11-14 19:20:31 +03:00
chschtsch
5eebfa132f update .gitignore 2015-11-14 19:19:45 +03:00
chschtsch
522febef93 update .gitignore 2015-11-14 19:17:54 +03:00
chschtsch
a421645ea5 update fragment_videoitem_detail layout 2015-11-14 19:14:51 +03:00
chschtsch
0aac4b1347 update fragment_videoitem_detail layout 2015-11-14 19:11:08 +03:00
chschtsch
36697825cf update fragment_videoitem_detail layout 2015-11-14 19:08:13 +03:00
Adam Howard
b0182ed604 halfway through implementing timestamps:
* still need to use the start position value stored in the PlayVideoActivity's Intent bundle, to set the VideoView using seekTo()
* need to test timestamp extraction regex, and possibly move it somewhere else
*need to find a better way to get the startPosition value to ActionBarHandler, which I thought used VideoInfo objects, but apparently doesn't
    * currently there is a small setStartPosition() method
2015-11-14 11:47:21 +00:00
147 changed files with 5290 additions and 3291 deletions

2
.gitignore vendored
View File

@@ -6,3 +6,5 @@
/captures
/app/app.iml
/.idea
/*.iml
gradle.properties

30
.travis.yml Normal file
View File

@@ -0,0 +1,30 @@
language: android
android:
components:
# The BuildTools version used by NewPipe
- tools
- build-tools-23.0.2
# The SDK version used to compile NewPipe
- android-23
# Additional components
- extra-android-support
- extra-android-m2repository
# Emulators
- sys-img-armeabi-v7a-android-21
- sys-img-armeabi-v7a-android-19
- sys-img-armeabi-v7a-android-15
env:
global:
- ADB_INSTALL_TIMEOUT=8 # minutes (2 by default)
matrix:
- ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a
before_script:
- echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI
- emulator -avd test -no-skin -no-audio -no-window &
- android-wait-for-emulator
- adb shell input keyevent 82 &

33
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,33 @@
#Contribution
This document contains guidelines on making contributions to NewPipe.
## Programming
* Follow the [Google Style Guidelines](https://google.github.io/styleguide/javaguide.html)
* Make a new feature on a separate branch, not on the master branch
* Make a [pull request](https://github.com/theScrabi/NewPipe/pulls) if you're done with your changes
* When submitting changes, you agree that your code will be GPLv3 licensed
## Commit messages
* The subject line of your commit message shouldn't be longer than 72 characters
* Try to keep each line of your commit message 72 characters to ensure proper
compatibility with all git tools
* [This guide](http://chris.beams.io/posts/git-commit/) goes more in depth on what makes a good commit message
## Translation
* NewPipe can be translated on [weblate](https://hosted.weblate.org/projects/newpipe/strings/)
## Issue reporting
* Search the [existing issues](https://github.com/theScrabi/NewPipe/issues) first to make sure your issue hasn't been reported before
* Check if this issue is already fixed in the repository
* When making bug reports, be sure to tell which version of NewPipe you are using and the steps to reproduce the problem
* Please include a log if you can
## Communication
* For the time being, [Slack](http://invite.chschtsch.ml/) is being used for project communication
* Feel free to post suggestions, changes, ideas etc!

View File

@@ -1,30 +1,44 @@
# NewPipe
NewPipe: A free lightweight Youtube frontend for Android.
[![NewPipe](app/src/main/res/mipmap-xhdpi/ic_launcher.png)](http://dasochan.nl/newpipe/)
Project status:
[![Translation Status](https://hosted.weblate.org/widgets/NewPipe/-/svg-badge.svg)](https://hosted.weblate.org/engage/NewPipe/)
[![Build Status](https://travis-ci.org/theScrabi/NewPipe.svg)](https://travis-ci.org/theScrabi/NewPipe)
[![NewPipe](https://f-droid.org/repo/icons/org.schabi.newpipe.5.png)](http://dasochan.nl/newpipe/)
NewPipe: A free lightweight Youtube frontend for Android.
## Get NewPipe
[![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)
## Screenshots
[<img src="screenshots/screenshot_1.png" width=150>](screenshots/screenshot_1.png)
[<img src="screenshots/screenshot_2.png" width=150>](screenshots/screenshot_2.png)
[<img src="screenshots/screenshot_3.png" width=150>](screenshots/screenshot_3.png)
[<img src="screenshots/screenshot_4.png" width=150>](screenshots/screenshot_4.png)
[<img src="screenshots/screenshot_5.png" width=150>](screenshots/screenshot_5.png)
[<img src="screenshots/screenshot_6.png" width=250>](screenshots/screenshot_6.png)
## Description
NewPipe does not use any Google framework libraries, or the YouTube API. It only parses the website in order to gain the information it needs. Therefore this app can be used on devices without G-services installed. Also NewPipe does not store data on the YouTube website (no login), and it's free software.
NewPipe does not use any Google framework libraries, or the YouTube API. It only parses the website in order to gain the information it needs. Therefore this app can be used on devices without Google Services installed. Also, you don't need a YouTube account to use NewPipe, and it's FLOSS.
## Features
### Features
* Search videos
* Display general information about a video
* Watch Youtube videos
* Listen to Youtube videos (audio only streaming)
* Watch YouTube videos
* Listen to YouTube videos (experimental)
* Select the streaming player to watch the video with
* Download videos (working, but it could be better)
* Download audio only (working but, but it could be better)
* Download videos (experimental)
* Download audio only (experimental)
* Open a video in Kodi
* Show Next/Related videos
* Search Youtube in a specific language
* Search YouTube in a specific language
* Orbot/Tor support (no streaming yet)
## Coming Features
### Coming Features
* Improved Downloading
* Bookmarks
@@ -37,10 +51,20 @@ NewPipe does not use any Google framework libraries, or the YouTube API. It only
* Search/Watch Playlists
* ... and many more
### Multi service support
Generally NewPipe is designed to not only support YouTube, but many more streaming services. However, right now NewPipe is not stable enough to support more than only YouTube. But if all works as planned, NewPipe will get such support by the version 2.0.
# Help is always welcome !!!
Whether it's about ideas, translation, design changes, code cleaning, or real heavy code changes. Help is always welcome.
### Multiservice support
Although NewPipe only supports YouTube at the moment, it's designed to support many more streaming services. The plan is, that NewPipe will get such support by the version 2.0.
## Contribution
Whether you have ideas, translation, design changes, code cleaning, or real heavy code changes, help is always welcome.
The more is done the better it gets!
If you'd like to get involved, check our [contribution notes](CONTRIBUTING.md).
## License
[![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](http://www.gnu.org/licenses/gpl-3.0.en.html)
NewPipe is Free Software: You can use, study share and improve it at your
will. Specifically you can redistribute and/or modify it under the terms of the
[GNU General Public License](https://www.gnu.org/licenses/gpl.html) as
published by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

View File

@@ -2,14 +2,14 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "org.schabi.newpipe"
minSdkVersion 15
targetSdkVersion 23
versionCode 6
versionName "0.6.0"
versionCode 12
versionName "0.7.3"
}
buildTypes {
release {
@@ -17,13 +17,23 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:23.1.0'
compile 'com.android.support:support-v4:23.1.0'
compile 'com.android.support:design:23.1.0'
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:cardview-v7:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'org.jsoup:jsoup:1.8.3'
compile 'org.mozilla:rhino:1.7.7'
compile 'info.guardianproject.netcipher:netcipher:1.2'
}

View File

@@ -0,0 +1,89 @@
package org.schabi.newpipe.services.youtube;
import android.test.AndroidTestCase;
import org.schabi.newpipe.VideoPreviewInfo;
import org.schabi.newpipe.services.SearchEngine;
import java.util.ArrayList;
/**
* Created by the-scrabi on 29.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeSearchEngineTest.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 YoutubeSearchEngineTest extends AndroidTestCase {
private SearchEngine.Result result;
private ArrayList<String> suggestionReply;
@Override
public void setUp() throws Exception{
super.setUp();
SearchEngine engine = new YoutubeSearchEngine();
result = engine.search("https://www.youtube.com/results?search_query=bla", 0, "de");
suggestionReply = engine.suggestionList("hello");
}
public void testIfNoErrorOccur() {
assertEquals(result.errorMessage, "");
}
public void testIfListIsNotEmpty() {
assertEquals(result.resultList.size() > 0, true);
}
public void testItemsHaveTitle() {
for(VideoPreviewInfo i : result.resultList) {
assertEquals(i.title.isEmpty(), false);
}
}
public void testItemsHaveUploader() {
for(VideoPreviewInfo i : result.resultList) {
assertEquals(i.uploader.isEmpty(), false);
}
}
public void testItemsHaveRightDuration() {
for(VideoPreviewInfo i : result.resultList) {
assertTrue(i.duration, i.duration.contains(":"));
}
}
public void testItemsHaveRightThumbnail() {
for (VideoPreviewInfo i : result.resultList) {
assertTrue(i.thumbnail_url, i.thumbnail_url.contains("https://"));
}
}
public void testItemsHaveRightVideoUrl() {
for (VideoPreviewInfo i : result.resultList) {
assertTrue(i.webpage_url, i.webpage_url.contains("https://"));
}
}
public void testIfSuggestionsAreReplied() {
assertEquals(suggestionReply.size() > 0, true);
}
public void testIfSuggestionsAreValid() {
for(String s : suggestionReply) {
assertTrue(s, !s.isEmpty());
}
}
}

View File

@@ -0,0 +1,100 @@
package org.schabi.newpipe.services.youtube;
import android.test.AndroidTestCase;
import android.util.Log;
import org.schabi.newpipe.services.VideoInfo;
/**
* Created by the-scrabi on 30.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeVideoExtractorDefault.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 YoutubeVideoExtractorDefaultTest extends AndroidTestCase {
private YoutubeVideoExtractor extractor;
public void setUp() {
extractor = new YoutubeVideoExtractor("https://www.youtube.com/watch?v=FmG385_uUys");
}
public void testGetErrorCode() {
assertEquals(extractor.getErrorCode(), VideoInfo.NO_ERROR);
}
public void testGetErrorMessage() {
assertEquals(extractor.getErrorMessage(), "");
}
public void testGetTimeStamp() {
assertTrue(Integer.toString(extractor.getTimeStamp()),
extractor.getTimeStamp() >= 0);
}
public void testGetTitle() {
assertTrue(!extractor.getTitle().isEmpty());
}
public void testGetDescription() {
assertTrue(extractor.getDescription() != null);
}
public void testGetUploader() {
assertTrue(!extractor.getUploader().isEmpty());
}
public void testGetLength() {
assertTrue(extractor.getLength() > 0);
}
public void testGetViews() {
assertTrue(extractor.getLength() > 0);
}
public void testGetUploadDate() {
assertTrue(extractor.getUploadDate().length() > 0);
}
public void testGetThumbnailUrl() {
assertTrue(extractor.getThumbnailUrl(),
extractor.getThumbnailUrl().contains("https://"));
}
public void testGetUploaderThumbnailUrl() {
assertTrue(extractor.getUploaderThumbnailUrl(),
extractor.getUploaderThumbnailUrl().contains("https://"));
}
public void testGetAudioStreams() {
for(VideoInfo.AudioStream s : extractor.getAudioStreams()) {
assertTrue(s.url,
s.url.contains("https://"));
assertTrue(s.bandwidth > 0);
assertTrue(s.samplingRate > 0);
}
}
public void testGetVideoStreams() {
for(VideoInfo.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,59 @@
package org.schabi.newpipe.services.youtube;
import android.test.AndroidTestCase;
import org.schabi.newpipe.services.VideoInfo;
/**
* Created by the-scrabi on 30.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeVideoExtractorGema.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/>.
*/
// This class only works in Germany.
public class YoutubeVideoExtractorGemaTest extends AndroidTestCase {
// Deaktivate this Test Case bevore uploading it githup, otherwise CI will fail.
private static final boolean testActive = false;
private YoutubeVideoExtractor extractor;
public void setUp() {
if(testActive) {
extractor = new YoutubeVideoExtractor("https://www.youtube.com/watch?v=3O1_3zBUKM8");
}
}
public void testGetErrorCode() {
if(testActive) {
assertEquals(extractor.getErrorCode(), VideoInfo.ERROR_BLOCKED_BY_GEMA);
} else {
assertTrue(true);
}
}
public void testGetErrorMessage() {
if(testActive) {
assertTrue(extractor.getErrorMessage(),
extractor.getErrorMessage().contains("GEMA"));
} else {
assertTrue(true);
}
}
}

View File

@@ -1,19 +1,22 @@
<?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"/>
<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:logo="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
android:theme="@style/AppTheme"
tools:ignore="AllowBackup">
<activity
android:name=".VideoItemListActivity"
android:label="@string/app_name" >
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -22,58 +25,79 @@
</activity>
<activity
android:name=".VideoItemDetailActivity"
android:label="@string/title_videoitem_detail" >
android:label="@string/title_videoitem_detail"
android:theme="@style/AppTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".VideoItemListActivity" />
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="youtube.com"
android:scheme="http"
android:pathPattern="/?*#*/*watch"/>
<data
android:host="youtube.com"
android:scheme="https"
android:pathPattern="/?*#*/*watch"/>
<data
android:host="www.youtube.com"
android:scheme="http"
android:pathPattern="/?*#*/*watch"/>
<data
android:host="www.youtube.com"
android:scheme="https"
android:pathPattern="/?*#*/*watch"/>
<data
android:host="m.youtube.com"
android:scheme="http"
android:pathPattern="/?*#*/*watch"/>
<data
android:host="m.youtube.com"
android:scheme="https"
android:pathPattern="/?*#*/*watch"/>
<data
android:host="youtu.be"
android:scheme="https"
android:pathPrefix="/"/>
<data
android:host="youtu.be"
android:scheme="http"
android:pathPrefix="/"/>
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="youtube.com" />
<data android:host="m.youtube.com" />
<data android:host="www.youtube.com" />
<data android:pathPrefix="/v/" />
<data android:pathPrefix="/watch" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="youtu.be" />
<data android:pathPrefix="/" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="vnd.youtube" />
<data android:scheme="vnd.youtube.launch" />
</intent-filter>
</activity>
<activity android:name=".PlayVideoActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/FullscreenTheme"
android:theme="@style/VideoPlayerTheme"
android:parentActivityName=".VideoItemDetailActivity"
>
tools:ignore="UnusedAttribute">
</activity>
<service
android:name=".BackgroundPlayer"
android:label="@string/background_player_name"
android:exported="false" />
<activity
android:name=".SettingsActivity"
android:label="@string/title_activity_settings" >
android:label="@string/settings_activity_title" >
</activity>
<activity
android:name=".PanicResponderActivity"
android:launchMode="singleInstance"
android:noHistory="true"
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:theme="@android:style/Theme.NoDisplay" />
</application>
</manifest>

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
package org.schabi.newpipe;
/**
* Created by Christian Schabesberger on 10.08.15.
* Created by Christian Schabesberger on 24.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* Extractor.java is part of NewPipe.
* ActivityCommunicator.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
@@ -20,9 +20,23 @@ package org.schabi.newpipe;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
import android.graphics.Bitmap;
public interface Extractor {
VideoInfo getVideoInfo(String siteUrl);
String getVideoUrl(String videoId);
String getVideoId(String videoUrl);
/**
* Singleton:
* Used to send data between certain Activity/Services within the same process.
* This can be considered as hack inside the Android universe. **/
public class ActivityCommunicator {
private static ActivityCommunicator activityCommunicator = null;
public static ActivityCommunicator getCommunicator() {
if(activityCommunicator == null) {
activityCommunicator = new ActivityCommunicator();
}
return activityCommunicator;
}
// Thumbnail send from VideoItemDetailFragment to BackgroundPlayer
public volatile Bitmap backgroundPlayerThumbnail;
}

View File

@@ -0,0 +1,71 @@
package org.schabi.newpipe;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import info.guardianproject.netcipher.NetCipher;
import info.guardianproject.netcipher.proxy.OrbotHelper;
/**
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
* App.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 App extends Application {
private static boolean useTor;
@Override
public void onCreate() {
super.onCreate();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if(prefs.getBoolean(getString(R.string.use_tor_key), false)) {
OrbotHelper.requestStartTor(this);
configureTor(true);
} else {
configureTor(false);
}
// DO NOT REMOVE THIS FUNCTION!!!
// Otherwise downloadPathPreference has invalid value.
SettingsActivity.initSettings(this);
}
/**
* Set the proxy settings based on whether Tor should be enabled or not.
*/
static void configureTor(boolean enabled) {
useTor = enabled;
if (useTor) {
NetCipher.useTor();
} else {
NetCipher.setProxy(null);
}
}
static void checkStartTor(Context context) {
if (useTor) {
OrbotHelper.requestStartTor(context);
}
}
static boolean isUsingTor() {
return useTor;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,29 @@
package org.schabi.newpipe;
import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.app.DownloadManager;
import android.app.Notification;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.DialogFragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Christian Schabesberger on 21.09.15.
@@ -42,48 +53,102 @@ public class DownloadDialog extends DialogFragment {
public static final String FILE_SUFFIX_VIDEO = "file_suffix_video";
public static final String AUDIO_URL = "audio_url";
public static final String VIDEO_URL = "video_url";
Bundle arguments;
private Bundle arguments;
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
arguments = getArguments();
super.onCreateDialog(savedInstanceState);
if(ContextCompat.checkSelfPermission(this.getContext(),Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(getActivity(),new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},0);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.downloadDialogTitle)
.setItems(R.array.downloadOptions, new DialogInterface.OnClickListener() {
builder.setTitle(R.string.download_dialog_title)
.setItems(R.array.download_options, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Context context = getActivity();
SharedPreferences defaultPreferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String suffix = "";
String title = arguments.getString(TITLE);
String url = "";
File downloadDir = NewPipeSettings.getDownloadFolder();
switch(which) {
case 0: // Video
suffix = arguments.getString(FILE_SUFFIX_VIDEO);
url = arguments.getString(VIDEO_URL);
downloadDir = NewPipeSettings.getVideoDownloadFolder(context);
break;
case 1:
suffix = arguments.getString(FILE_SUFFIX_AUDIO);
url = arguments.getString(AUDIO_URL);
downloadDir = NewPipeSettings.getAudioDownloadFolder(context);
break;
default:
Log.d(TAG, "lolz");
}
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(
Uri.parse(url));
request.setDestinationUri(Uri.fromFile(new File(
defaultPreferences.getString("download_path_preference", "/storage/emulated/0/NewPipe")
+ "/" + title + suffix)));
try {
dm.enqueue(request);
} catch (Exception e) {
e.printStackTrace();
if(!downloadDir.exists()) {
//attempt to create directory
boolean mkdir = downloadDir.mkdirs();
if(!mkdir && !downloadDir.isDirectory()) {
String message = context.getString(R.string.err_dir_create,downloadDir.toString());
Log.e(TAG, message);
Toast.makeText(context,message , Toast.LENGTH_LONG).show();
return;
}
String message = context.getString(R.string.info_dir_created,downloadDir.toString());
Log.e(TAG, message);
Toast.makeText(context,message , Toast.LENGTH_LONG).show();
}
File saveFilePath = new File(downloadDir,createFileName(title) + suffix);
long id = 0;
if (App.isUsingTor()) {
// if using Tor, do not use DownloadManager because the proxy cannot be set
Downloader.downloadFile(getContext(), url, saveFilePath, title);
} else {
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(
Uri.parse(url));
request.setDestinationUri(Uri.fromFile(saveFilePath));
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setTitle(title);
request.setDescription("'" + url +
"' => '" + saveFilePath + "'");
request.allowScanningByMediaScanner();
try {
id = dm.enqueue(request);
} catch (Exception e) {
e.printStackTrace();
}
}
Log.i(TAG,"Started downloading '" + url +
"' => '" + saveFilePath + "' #" + id);
}
});
return builder.create();
}
/**
* #143 #44 #42 #22: make shure that the filename does not contain illegal chars.
* This should fix some of the "cannot download" problems.
* */
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> ();
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
String nameToTest = fName;
for (String pattern : forbiddenCharsPatterns) {
nameToTest = nameToTest.replaceAll(pattern, "_");
}
return nameToTest;
}
}

View File

@@ -1,12 +1,31 @@
package org.schabi.newpipe;
import android.app.NotificationManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
import javax.net.ssl.HttpsURLConnection;
import info.guardianproject.netcipher.NetCipher;
/**
* Created by Christian Schabesberger on 14.08.15.
*
@@ -27,15 +46,42 @@ import java.net.UnknownHostException;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class Downloader {
public class Downloader extends AsyncTask<Void, Integer, Void> {
public static final String TAG = "Downloader";
private static final String USER_AGENT = "Mozilla/5.0";
private NotificationManager nm;
private NotificationCompat.Builder builder;
private int notifyId = 0x1234;
private int fileSize = 0xffffffff;
private final Context context;
private final String fileURL;
private final File saveFilePath;
private final String title;
private final String debugContext;
public Downloader(Context context, String fileURL, File saveFilePath, String title) {
this.context = context;
this.fileURL = fileURL;
this.saveFilePath = saveFilePath;
this.title = title;
this.debugContext = "'" + fileURL +
"' => '" + saveFilePath + "'";
}
/**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) {
String ret = "";
try {
URL url = new URL(siteUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestProperty("Accept-Language", language);
ret = dl(con);
}
@@ -45,8 +91,9 @@ public class Downloader {
return ret;
}
private static String dl(HttpURLConnection con) {
StringBuffer response = new StringBuffer();
/**Common functionality between download(String url) and download(String url, String language)*/
private static String dl(HttpsURLConnection con) throws IOException {
StringBuilder response = new StringBuilder();
try {
con.setRequestMethod("GET");
@@ -66,19 +113,20 @@ public class Downloader {
uhe.printStackTrace();
//Toast.makeText(getActivity(), uhe.getMessage(), Toast.LENGTH_LONG).show();
}
catch (Exception e) {
e.printStackTrace();
}
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) {
String ret = "";
try {
URL url = new URL(siteUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
HttpsURLConnection con = NetCipher.getHttpsURLConnection(url);
ret = dl(con);
}
catch(Exception e) {
@@ -87,4 +135,102 @@ public class Downloader {
return ret;
}
/**
* Downloads a file from a URL in the background using an {@link AsyncTask}.
*
* @param fileURL HTTP URL of the file to be downloaded
* @param saveFilePath path of the directory to save the file
* @param title
* @throws IOException
*/
public static void downloadFile(final Context context, final String fileURL, final File saveFilePath, String title) {
new Downloader(context, fileURL, saveFilePath, title).execute();
}
/** AsyncTask impl: executed in gui thread */
@Override
protected void onPreExecute() {
super.onPreExecute();
nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Drawable icon = context.getResources().getDrawable(R.mipmap.ic_launcher);
builder = new NotificationCompat.Builder(context)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setLargeIcon(((BitmapDrawable) icon).getBitmap())
.setContentTitle(saveFilePath.getName())
.setContentText(saveFilePath.getAbsolutePath())
.setProgress(fileSize, 0, false);
nm.notify(notifyId, builder.build());
}
/** AsyncTask impl: executed in background thread does the download */
@Override
protected Void doInBackground(Void... voids) {
HttpsURLConnection con = null;
InputStream inputStream = null;
FileOutputStream outputStream = null;
try {
con = NetCipher.getHttpsURLConnection(fileURL);
int responseCode = con.getResponseCode();
// always check HTTP response code first
if (responseCode == HttpURLConnection.HTTP_OK) {
fileSize = con.getContentLength();
inputStream = new BufferedInputStream(con.getInputStream());
outputStream = new FileOutputStream(saveFilePath);
int bufferSize = 8192;
int downloaded = 0;
int bytesRead = -1;
byte[] buffer = new byte[bufferSize];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
downloaded += bytesRead;
if (downloaded % 50000 < bufferSize) {
publishProgress(downloaded);
}
}
publishProgress(bufferSize);
} else {
Log.i(TAG, "No file to download. Server replied HTTP code: " + responseCode);
}
} catch (IOException e) {
Log.e(TAG, "No file to download. Server replied HTTP code: ", e);
e.printStackTrace();
} finally {
try {
if (outputStream != null) {
outputStream.close();
outputStream = null;
}
if (inputStream != null) {
inputStream.close();
inputStream = null;
}
} catch (IOException e) {
e.printStackTrace();
}
if (con != null) {
con.disconnect();
con = null;
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... progress) {
builder.setProgress(fileSize, progress[0], false);
nm.notify(notifyId, builder.build());
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
nm.cancel(notifyId);
}
}

View File

@@ -0,0 +1,54 @@
package org.schabi.newpipe;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
/**
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
* ExitActivity.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 ExitActivity extends Activity {
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= 21) {
finishAndRemoveTask();
} else {
finish();
}
System.exit(0);
}
public static void exitAndRemoveFromRecentApps(Activity activity) {
Intent intent = new Intent(activity, ExitActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_NO_ANIMATION);
activity.startActivity(intent);
}
}

View File

@@ -0,0 +1,93 @@
package org.schabi.newpipe;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.preference.PreferenceManager;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* Created by chschtsch on 12/29/15.
*
* Copyright (C) Gregory Arkhipov 2015
* Localization.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 Localization {
public static Locale getPreferredLocale(Context context) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
String languageCode = sp.getString(String.valueOf(R.string.search_language_key),
context.getString(R.string.default_language_value));
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 static String localizeViewCount(long viewCount, Context context) {
Locale locale = getPreferredLocale(context);
Resources res = context.getResources();
String viewsString = res.getString(R.string.view_count_text);
NumberFormat nf = NumberFormat.getInstance(locale);
String formattedViewCount = nf.format(viewCount);
return String.format(viewsString, formattedViewCount);
}
public static String localizeNumber(long number, Context context) {
Locale locale = getPreferredLocale(context);
NumberFormat nf = NumberFormat.getInstance(locale);
return nf.format(number);
}
private static String formatDate(String date, Context context) {
Locale locale = getPreferredLocale(context);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date datum = null;
try {
datum = formatter.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
return df.format(datum);
}
public static String localizeDate(String date, Context context) {
Resources res = context.getResources();
String dateString = res.getString(R.string.upload_date_text);
String formattedDate = formatDate(date, context);
return String.format(dateString, formattedDate);
}
}

View File

@@ -0,0 +1,72 @@
/**
* Created by k3b on 07.01.2016.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* NewPipeSettings.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/>.
*/
package org.schabi.newpipe;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.util.Log;
import java.io.File;
/**
* Helper for global settings
*/
public class NewPipeSettings {
public static void initSettings(Context context) {
PreferenceManager.setDefaultValues(context, R.xml.settings, false);
getVideoDownloadFolder(context);
getAudioDownloadFolder(context);
}
public static File getDownloadFolder() {
return getFolder(Environment.DIRECTORY_DOWNLOADS);
}
public static File getVideoDownloadFolder(Context context) {
return getFolder(context, R.string.download_path_key, Environment.DIRECTORY_MOVIES);
}
public static File getAudioDownloadFolder(Context context) {
return getFolder(context, R.string.download_path_audio_key, Environment.DIRECTORY_MUSIC);
}
private static File getFolder(Context context, int keyID, String defaultDirectoryName) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
final String key = context.getString(keyID);
String downloadPath = prefs.getString(key, null);
if ((downloadPath != null) && (!downloadPath.isEmpty())) return new File(downloadPath.trim());
final File folder = getFolder(defaultDirectoryName);
SharedPreferences.Editor spEditor = prefs.edit();
spEditor.putString(key
, new File(folder,"NewPipe").getAbsolutePath());
spEditor.apply();
return folder;
}
@NonNull
private static File getFolder(String defaultDirectoryName) {
return new File(Environment.getExternalStorageDirectory(),defaultDirectoryName);
}
}

View File

@@ -0,0 +1,50 @@
package org.schabi.newpipe;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
/**
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
* PanicResponderActivity.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 PanicResponderActivity extends Activity {
public static final String PANIC_TRIGGER_ACTION = "info.guardianproject.panic.action.TRIGGER";
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent != null && PANIC_TRIGGER_ACTION.equals(intent.getAction())) {
// TODO explicitly clear the search results once they are restored when the app restarts
// or if the app reloads the current video after being killed, that should be cleared also
ExitActivity.exitAndRemoveFromRecentApps(this);
}
if (Build.VERSION.SDK_INT >= 21) {
finishAndRemoveTask();
} else {
finish();
}
}
}

View File

@@ -15,6 +15,7 @@ import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -52,9 +53,9 @@ public class PlayVideoActivity extends AppCompatActivity {
public static final String STREAM_URL = "stream_url";
public static final String VIDEO_TITLE = "video_title";
private static final String POSITION = "position";
public static final String START_POSITION = "start_position";
private static final long HIDING_DELAY = 3000;
private static final long TAB_HIDING_DELAY = 100;
private String videoUrl = "";
@@ -82,12 +83,38 @@ public class PlayVideoActivity extends AppCompatActivity {
hasSoftKeys = checkIfHasSoftKeys();
actionBar = getSupportActionBar();
assert actionBar != null;
actionBar.setDisplayHomeAsUpEnabled(true);
Intent intent = getIntent();
if(mediaController == null) {
mediaController = new MediaController(this);
//prevents back button hiding media controller controls (after showing them)
//instead of exiting video
//see http://stackoverflow.com/questions/6051825
//also solves https://github.com/theScrabi/NewPipe/issues/99
mediaController = new MediaController(this) {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
int keyCode = event.getKeyCode();
final boolean uniqueDown = event.getRepeatCount() == 0
&& event.getAction() == KeyEvent.ACTION_DOWN;
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (uniqueDown)
{
if (isShowing()) {
finish();
} else {
hide();
}
}
return true;
}
return super.dispatchKeyEvent(event);
}
};
}
position = intent.getIntExtra(START_POSITION, 0)*1000;//convert from seconds to milliseconds
videoView = (VideoView) findViewById(R.id.video_view);
progressBar = (ProgressBar) findViewById(R.id.play_video_progress_bar);
try {
@@ -145,11 +172,6 @@ public class PlayVideoActivity extends AppCompatActivity {
}
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
}
@Override
public boolean onCreatePanelMenu(int featured, Menu menu) {
super.onCreatePanelMenu(featured, menu);
@@ -159,17 +181,24 @@ public class PlayVideoActivity extends AppCompatActivity {
return true;
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onPause() {
super.onPause();
videoView.pause();
}
@Override
public void onResume() {
super.onResume();
App.checkStartTor(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
prefs = getPreferences(Context.MODE_PRIVATE);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
@@ -182,7 +211,7 @@ public class PlayVideoActivity extends AppCompatActivity {
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, videoUrl);
intent.setType("text/plain");
startActivity(Intent.createChooser(intent, getString(R.string.shareDialogTitle)));
startActivity(Intent.createChooser(intent, getString(R.string.share_dialog_title)));
break;
case R.id.menu_item_screen_rotation:
toggleOrientation();
@@ -274,11 +303,9 @@ public class PlayVideoActivity extends AppCompatActivity {
}
private boolean checkIfHasSoftKeys(){
if(Build.VERSION.SDK_INT >= 17) {
return getNavigationBarHeight() != 0 || getNavigationBarWidth() != 0;
} else {
return true;
}
return Build.VERSION.SDK_INT >= 17 ||
getNavigationBarHeight() != 0 ||
getNavigationBarWidth() != 0;
}
private int getNavigationBarHeight() {
@@ -315,7 +342,7 @@ public class PlayVideoActivity extends AppCompatActivity {
}
}
public boolean checkIfLandscape() {
private boolean checkIfLandscape() {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.heightPixels < displayMetrics.widthPixels;
@@ -331,6 +358,6 @@ public class PlayVideoActivity extends AppCompatActivity {
}
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(PREF_IS_LANDSCAPE, isLandscape);
editor.commit();
editor.apply();
}
}

View File

@@ -1,23 +1,29 @@
package org.schabi.newpipe;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Environment;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import info.guardianproject.netcipher.proxy.OrbotHelper;
/**
* Created by Christian Schabesberger on 31.08.15.
*
@@ -38,8 +44,9 @@ import android.view.ViewGroup;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class SettingsActivity extends PreferenceActivity {
public class SettingsActivity extends PreferenceActivity {
private static final int REQUEST_INSTALL_ORBOT = 0x1234;
private AppCompatDelegate mDelegate = null;
@Override
@@ -56,12 +63,108 @@ public class SettingsActivity extends PreferenceActivity {
}
public static class SettingsFragment extends PreferenceFragment {
public static class SettingsFragment extends PreferenceFragment{
SharedPreferences.OnSharedPreferenceChangeListener prefListener;
// get keys
String DEFAULT_RESOLUTION_PREFERENCE;
String DEFAULT_AUDIO_FORMAT_PREFERENCE;
String SEARCH_LANGUAGE_PREFERENCE;
String DOWNLOAD_PATH_PREFERENCE;
String DOWNLOAD_PATH_AUDIO_PREFERENCE;
String USE_TOR_KEY;
private ListPreference defaultResolutionPreference;
private ListPreference defaultAudioFormatPreference;
private ListPreference searchLanguagePreference;
private EditTextPreference downloadPathPreference;
private EditTextPreference downloadPathAudioPreference;
private CheckBoxPreference useTorCheckBox;
private SharedPreferences defaultPreferences;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings_screen);
addPreferencesFromResource(R.xml.settings);
final Activity activity = getActivity();
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(activity);
// get keys
DEFAULT_RESOLUTION_PREFERENCE =getString(R.string.default_resolution_key);
DEFAULT_AUDIO_FORMAT_PREFERENCE =getString(R.string.default_audio_format_key);
SEARCH_LANGUAGE_PREFERENCE =getString(R.string.search_language_key);
DOWNLOAD_PATH_PREFERENCE = getString(R.string.download_path_key);
DOWNLOAD_PATH_AUDIO_PREFERENCE = getString(R.string.download_path_audio_key);
USE_TOR_KEY = getString(R.string.use_tor_key);
// get pref objects
defaultResolutionPreference =
(ListPreference) findPreference(DEFAULT_RESOLUTION_PREFERENCE);
defaultAudioFormatPreference =
(ListPreference) findPreference(DEFAULT_AUDIO_FORMAT_PREFERENCE);
searchLanguagePreference =
(ListPreference) findPreference(SEARCH_LANGUAGE_PREFERENCE);
downloadPathPreference =
(EditTextPreference) findPreference(DOWNLOAD_PATH_PREFERENCE);
downloadPathAudioPreference =
(EditTextPreference) findPreference(DOWNLOAD_PATH_AUDIO_PREFERENCE);
useTorCheckBox = (CheckBoxPreference) findPreference(USE_TOR_KEY);
prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
Activity a = getActivity();
updateSummary();
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 {
App.configureTor(false);
}
}
};
defaultPreferences.registerOnSharedPreferenceChangeListener(prefListener);
updateSummary();
}
// This is used to show the status of some preference in the description
private void updateSummary() {
defaultResolutionPreference.setSummary(
defaultPreferences.getString(DEFAULT_RESOLUTION_PREFERENCE,
getString(R.string.default_resolution_value)));
defaultAudioFormatPreference.setSummary(
defaultPreferences.getString(DEFAULT_AUDIO_FORMAT_PREFERENCE,
getString(R.string.default_audio_format_value)));
searchLanguagePreference.setSummary(
defaultPreferences.getString(SEARCH_LANGUAGE_PREFERENCE,
getString(R.string.default_language_value)));
downloadPathPreference.setSummary(
defaultPreferences.getString(DOWNLOAD_PATH_PREFERENCE,
getString(R.string.download_path_summary)));
downloadPathAudioPreference.setSummary(
defaultPreferences.getString(DOWNLOAD_PATH_AUDIO_PREFERENCE,
getString(R.string.download_path_audio_summary)));
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// try to start tor regardless of resultCode since clicking back after
// installing the app does not necessarily return RESULT_OK
App.configureTor(requestCode == REQUEST_INSTALL_ORBOT
&& OrbotHelper.requestStartTor(this));
}
@Override
@@ -70,14 +173,11 @@ public class SettingsActivity extends PreferenceActivity {
getDelegate().onPostCreate(savedInstanceState);
}
public ActionBar getSupportActionBar() {
private ActionBar getSupportActionBar() {
return getDelegate().getSupportActionBar();
}
public void setSupportActionBar(@Nullable Toolbar toolbar) {
getDelegate().setSupportActionBar(toolbar);
}
@NonNull
@Override
public MenuInflater getMenuInflater() {
return getDelegate().getMenuInflater();
@@ -154,15 +254,6 @@ public class SettingsActivity extends PreferenceActivity {
}
public static void initSettings(Context context) {
PreferenceManager.setDefaultValues(context, R.xml.settings_screen, false);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
if(sp.getString(context.getString(R.string.downloadPathPreference), "").isEmpty()){
SharedPreferences.Editor spEditor = sp.edit();
String newPipeDownloadStorage =
Environment.getExternalStorageDirectory().getAbsolutePath() + "/NewPipe";
spEditor.putString(context.getString(R.string.downloadPathPreference)
, newPipeDownloadStorage);
spEditor.commit();
}
NewPipeSettings.initSettings(context);
}
}

View File

@@ -1,79 +0,0 @@
package org.schabi.newpipe;
import android.graphics.Bitmap;
import android.util.Log;
import java.util.Date;
import java.util.Vector;
/**
* Created by Christian Schabesberger on 26.08.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* VideoInfo.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/>.
*/
/**Info object for opened videos, ie the video ready to play.*/
public class VideoInfo {
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 Bitmap uploader_thumbnail = null;
public String description = "";
public int duration = -1;
public int age_limit = 0;
public int like_count = 0;
public int dislike_count = 0;
public String average_rating = "";
public VideoStream[] videoStreams = null;
public AudioStream[] audioStreams = null;
public VideoInfoItem nextVideo = null;
public VideoInfoItem[] relatedVideos = null;
public int videoAvailableStatus = VIDEO_AVAILABLE;
private static final String TAG = VideoInfo.class.toString();
public static final int VIDEO_AVAILABLE = 0x00;
public static final int VIDEO_UNAVAILABLE = 0x01;
public static final int VIDEO_UNAVAILABLE_GEMA = 0x02;//German DRM organisation
public static class VideoStream {
public VideoStream(String url, int format, String res) {
this.url = url; this.format = format; resolution = res;
}
public String url = ""; //url of the stream
public int format = -1;
public String resolution = "";
}
public static class AudioStream {
public AudioStream(String url, int format, int bandwidth, int samplingRate) {
this.url = url; this.format = format;
this.bandwidth = bandwidth; this.samplingRate = samplingRate;
}
public String url = "";
public int format = -1;
public int bandwidth = -1;
public int samplingRate = -1;
}
}

View File

@@ -1,5 +1,6 @@
package org.schabi.newpipe;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -26,16 +27,14 @@ import android.widget.TextView;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class VideoInfoItemViewCreator {
private static final String TAG = VideoInfoItemViewCreator.class.toString();
LayoutInflater inflater;
class VideoInfoItemViewCreator {
private final LayoutInflater inflater;
public VideoInfoItemViewCreator(LayoutInflater inflater) {
this.inflater = inflater;
}
public View getViewByVideoInfoItem(View convertView, ViewGroup parent, VideoInfoItem info) {
public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, VideoPreviewInfo info, Context context) {
ViewHolder holder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.video_item, parent, false);
@@ -61,8 +60,7 @@ public class VideoInfoItemViewCreator {
if(!info.upload_date.isEmpty()) {
holder.itemUploadDateView.setText(info.upload_date);
} else {
//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(Localization.localizeViewCount(info.view_count, context));
}
return convertView;

View File

@@ -7,10 +7,12 @@ import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
import org.schabi.newpipe.services.ServiceList;
import org.schabi.newpipe.services.StreamingService;
/**
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
@@ -34,7 +36,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
private static final String TAG = VideoItemDetailActivity.class.toString();
VideoItemDetailFragment fragment;
private VideoItemDetailFragment fragment;
private String videoUrl;
private int currentStreamingService = -1;
@@ -44,7 +46,13 @@ public class VideoItemDetailActivity extends AppCompatActivity {
setContentView(R.layout.activity_videoitem_detail);
// Show the Up button in the action bar.
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
try {
//noinspection ConstantConditions
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} catch(Exception e) {
Log.d(TAG, "Could not get SupportActionBar");
e.printStackTrace();
}
// savedInstanceState is non-null when there is fragment state
// saved from previous configurations of this activity
@@ -61,30 +69,27 @@ public class VideoItemDetailActivity extends AppCompatActivity {
// this means the video was called though another app
if (getIntent().getData() != null) {
videoUrl = getIntent().getData().toString();
Log.i(TAG, "video URL passed:\"" + videoUrl + "\"");
StreamingService[] serviceList = ServiceList.getServices();
Extractor extractor = null;
//VideoExtractor videoExtractor = null;
for (int i = 0; i < serviceList.length; i++) {
if (serviceList[i].acceptUrl(videoUrl)) {
arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, i);
try {
currentStreamingService = i;
extractor = ServiceList.getService(i).getExtractorInstance();
} catch (Exception e) {
e.printStackTrace();
}
currentStreamingService = i;
//videoExtractor = ServiceList.getService(i).getExtractorInstance();
break;
}
}
if(extractor == null) {
Toast.makeText(this, R.string.urlNotSupportedText, Toast.LENGTH_LONG)
if(currentStreamingService == -1) {
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG)
.show();
}
arguments.putString(VideoItemDetailFragment.VIDEO_URL,
extractor.getVideoUrl(extractor.getVideoId(videoUrl)));
//arguments.putString(VideoItemDetailFragment.VIDEO_URL,
// videoExtractor.getVideoUrl(videoExtractor.getVideoId(videoUrl)));//cleans URL
arguments.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl);
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY,
PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean(getString(R.string.autoPlayThroughIntent), false));
.getBoolean(getString(R.string.autoplay_through_intent_key), false));
} else {
videoUrl = getIntent().getStringExtra(VideoItemDetailFragment.VIDEO_URL);
currentStreamingService = getIntent().getIntExtra(VideoItemDetailFragment.STREAMING_SERVICE, -1);
@@ -108,6 +113,12 @@ public class VideoItemDetailActivity extends AppCompatActivity {
.commit();
}
@Override
public void onResume() {
super.onResume();
App.checkStartTor(this);
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl);

View File

@@ -3,8 +3,7 @@ package org.schabi.newpipe;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.SearchView;
@@ -14,10 +13,10 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.Arrays;
import org.schabi.newpipe.services.ServiceList;
/**
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
@@ -59,9 +58,9 @@ public class VideoItemListActivity extends AppCompatActivity
private VideoItemListFragment listFragment;
private VideoItemDetailFragment videoFragment = null;
Menu menu = null;
private Menu menu = null;
public class SearchVideoQueryListener implements SearchView.OnQueryTextListener {
private class SearchVideoQueryListener implements SearchView.OnQueryTextListener {
@Override
public boolean onQueryTextSubmit(String query) {
@@ -72,8 +71,14 @@ public class VideoItemListActivity extends AppCompatActivity
// hide virtual keyboard
InputMethodManager inputManager =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(
getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
try {
//noinspection ConstantConditions
inputManager.hideSoftInputFromWindow(
getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
} catch(NullPointerException e) {
Log.e(TAG, "Could not get widget with focus");
e.printStackTrace();
}
// clear focus
// 1. to not open up the keyboard after switching back to this
// 2. It's a workaround to a seeming bug by the Android OS it self, causing
@@ -116,10 +121,16 @@ public class VideoItemListActivity extends AppCompatActivity
if(arguments != null) {
//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) {
mode = PRESENT_VIDEOS_MODE;
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
try {
//noinspection ConstantConditions
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} catch (NullPointerException e) {
Log.e(TAG, "Could not get SupportActionBar");
e.printStackTrace();
}
listFragment.present(p);
}
@@ -161,7 +172,13 @@ public class VideoItemListActivity extends AppCompatActivity
}
}
SettingsActivity.initSettings(this);
PreferenceManager.setDefaultValues(this, R.xml.settings, false);
}
@Override
public void onResume() {
super.onResume();
App.checkStartTor(this);
}
/**
@@ -180,7 +197,7 @@ public class VideoItemListActivity extends AppCompatActivity
// adding or replacing the detail fragment using a
// fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(VideoItemDetailFragment.ARG_ITEM_ID, id);
//arguments.putString(VideoItemDetailFragment.ARG_ITEM_ID, id);
arguments.putString(VideoItemDetailFragment.VIDEO_URL, webpage_url);
arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingServiceId);
videoFragment = new VideoItemDetailFragment();
@@ -199,7 +216,7 @@ public class VideoItemListActivity extends AppCompatActivity
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, VideoItemDetailActivity.class);
detailIntent.putExtra(VideoItemDetailFragment.ARG_ITEM_ID, id);
//detailIntent.putExtra(VideoItemDetailFragment.ARG_ITEM_ID, id);
detailIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, webpage_url);
detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingServiceId);
startActivity(detailIntent);

View File

@@ -32,24 +32,22 @@ import java.util.Vector;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class VideoListAdapter extends BaseAdapter {
private static final String TAG = VideoListAdapter.class.toString();
private Context context;
private VideoInfoItemViewCreator viewCreator;
private Vector<VideoInfoItem> videoList = new Vector<>();
class VideoListAdapter extends BaseAdapter {
private final Context context;
private final VideoInfoItemViewCreator viewCreator;
private Vector<VideoPreviewInfo> videoList = new Vector<>();
private Vector<Boolean> downloadedThumbnailList = new Vector<>();
VideoItemListFragment videoListFragment;
ListView listView;
private final ListView listView;
public VideoListAdapter(Context context, VideoItemListFragment videoListFragment) {
viewCreator = new VideoInfoItemViewCreator(LayoutInflater.from(context));
this.videoListFragment = videoListFragment;
this.listView = videoListFragment.getListView();
this.listView.setDivider(null);
this.listView.setDividerHeight(0);
this.context = context;
}
public void addVideoList(List<VideoInfoItem> videos) {
public void addVideoList(List<VideoPreviewInfo> videos) {
videoList.addAll(videos);
for(int i = 0; i < videos.size(); i++) {
downloadedThumbnailList.add(false);
@@ -63,12 +61,12 @@ public class VideoListAdapter extends BaseAdapter {
notifyDataSetChanged();
}
public Vector<VideoInfoItem> getVideoList() {
public Vector<VideoPreviewInfo> getVideoList() {
return videoList;
}
public void updateDownloadedThumbnailList(int index, boolean val) {
downloadedThumbnailList.set(index, val);
public void updateDownloadedThumbnailList(int index) {
downloadedThumbnailList.set(index, true);
}
public Vector<Boolean> getDownloadedThumbnailList() {
@@ -98,10 +96,10 @@ public class VideoListAdapter extends BaseAdapter {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = viewCreator.getViewByVideoInfoItem(convertView, parent, videoList.get(position));
convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position), context);
if(listView.isItemChecked(position)) {
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.primaryColorYoutube));
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.light_youtube_primary_color));
} else {
convertView.setBackgroundColor(0);
}

View File

@@ -4,11 +4,13 @@ import android.graphics.Bitmap;
import android.os.Parcel;
import android.os.Parcelable;
import org.schabi.newpipe.services.AbstractVideoInfo;
/**
* Created by Christian Schabesberger on 26.08.15.
*
* 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
* it under the terms of the GNU General Public License as published by
@@ -25,19 +27,10 @@ import android.os.Parcelable;
*/
/**Info object for previews of unopened videos, eg search results, related videos*/
public class VideoInfoItem 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 class VideoPreviewInfo extends AbstractVideoInfo implements Parcelable {
public String duration = "";
protected VideoInfoItem(Parcel in) {
@SuppressWarnings("WeakerAccess")
protected VideoPreviewInfo(Parcel in) {
id = in.readString();
title = in.readString();
uploader = in.readString();
@@ -46,10 +39,10 @@ public class VideoInfoItem implements Parcelable {
thumbnail = (Bitmap) in.readValue(Bitmap.class.getClassLoader());
webpage_url = 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.writeString(webpage_url);
dest.writeString(upload_date);
dest.writeString(view_count);
dest.writeLong(view_count);
}
@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
public VideoInfoItem createFromParcel(Parcel in) {
return new VideoInfoItem(in);
public VideoPreviewInfo createFromParcel(Parcel in) {
return new VideoPreviewInfo(in);
}
@Override
public VideoInfoItem[] newArray(int size) {
return new VideoInfoItem[size];
public VideoPreviewInfo[] newArray(int size) {
return new VideoPreviewInfo[size];
}
};
}

View File

@@ -0,0 +1,16 @@
package org.schabi.newpipe.services;
import android.graphics.Bitmap;
/**Common properties between VideoInfo and VideoPreviewInfo.*/
public abstract class AbstractVideoInfo {
public String id = "";
public String title = "";
public String uploader = "";
//public int duration = -1;
public String thumbnail_url = "";
public Bitmap thumbnail = null;
public String webpage_url = "";
public String upload_date = "";
public long view_count = -1;
}

View File

@@ -1,4 +1,4 @@
package org.schabi.newpipe;
package org.schabi.newpipe.services;
/**
* Created by Adam Howard on 08/11/15.
@@ -21,6 +21,9 @@ package org.schabi.newpipe;
* You should have received a copy of the GNU General Public License
* 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 {
// id name suffix mime type
MPEG_4 (0x0, "MPEG-4", "mp4", "video/mp4"),
@@ -30,7 +33,9 @@ public enum MediaFormat {
WEBMA (0x4, "WebM", "webm", "audio/webm");
public final int id;
@SuppressWarnings("WeakerAccess")
public final String name;
@SuppressWarnings("WeakerAccess")
public final String suffix;
public final String mimeType;
@@ -41,6 +46,10 @@ public enum MediaFormat {
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) {
for (MediaFormat vf : MediaFormat.values()) {
if(vf.id == ident) return vf.name;
@@ -48,6 +57,10 @@ public enum MediaFormat {
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) {
for (MediaFormat vf : MediaFormat.values()) {
if(vf.id == ident) return vf.suffix;
@@ -55,6 +68,10 @@ public enum MediaFormat {
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) {
for (MediaFormat vf : MediaFormat.values()) {
if(vf.id == ident) return vf.mimeType;

View File

@@ -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.Vector;
@@ -23,13 +25,14 @@ import java.util.Vector;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
@SuppressWarnings("ALL")
public interface SearchEngine {
class Result {
public String errorMessage = "";
public String suggestion = "";
public Vector<VideoInfoItem> resultList = new Vector<>();
public final Vector<VideoPreviewInfo> resultList = new Vector<>();
}
ArrayList<String> suggestionList(String query);

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