mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-09-19 23:40:51 +02:00
Compare commits
281 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
37d1f59132 | ||
![]() |
ab0ce55411 | ||
![]() |
c1d66596d1 | ||
![]() |
cbfccdf0d3 | ||
![]() |
9362037177 | ||
![]() |
e25c93bae2 | ||
![]() |
367c434010 | ||
![]() |
02d8463e15 | ||
![]() |
9d5a1d5c43 | ||
![]() |
c8d94f541f | ||
![]() |
27d06eaa6b | ||
![]() |
7f32857e00 | ||
![]() |
2f060f0f52 | ||
![]() |
f89d405226 | ||
![]() |
fd4459e570 | ||
![]() |
eb0df2b101 | ||
![]() |
6c178cfb7e | ||
![]() |
8ced68430d | ||
![]() |
0aade598ff | ||
![]() |
95949fd1ab | ||
![]() |
1a56382112 | ||
![]() |
d610e4b19b | ||
![]() |
fc44d9e36e | ||
![]() |
c07686576a | ||
![]() |
c2400aea4d | ||
![]() |
fb4bf0dde4 | ||
![]() |
e4f638d1ce | ||
![]() |
5c492c01a1 | ||
![]() |
f451e11f82 | ||
![]() |
95b73f35f7 | ||
![]() |
58147e9e12 | ||
![]() |
a8830e2ede | ||
![]() |
9804bb95cc | ||
![]() |
0da1aef763 | ||
![]() |
0a334804a3 | ||
![]() |
94d2f03e9b | ||
![]() |
9127f7f0c2 | ||
![]() |
0bb0226bc2 | ||
![]() |
b3a1a5dcc2 | ||
![]() |
984dd1cc25 | ||
![]() |
5663e543a4 | ||
![]() |
d3879a0398 | ||
![]() |
6bd2468d44 | ||
![]() |
e63d43151b | ||
![]() |
0265da4ae6 | ||
![]() |
ef255d12ae | ||
![]() |
eeb612f9a2 | ||
![]() |
dfcb4edb81 | ||
![]() |
d3500e9036 | ||
![]() |
adcb8c6469 | ||
![]() |
592eee7d3d | ||
![]() |
7dadb2b26c | ||
![]() |
7cbb135f28 | ||
![]() |
966ac0673c | ||
![]() |
d715eae0d1 | ||
![]() |
ccdd13d136 | ||
![]() |
efe5de4c75 | ||
![]() |
2a93e9bd2e | ||
![]() |
28dd53ae50 | ||
![]() |
3c1e64d8dc | ||
![]() |
4fe3cb2bca | ||
![]() |
b31490c4e3 | ||
![]() |
5533f6ba86 | ||
![]() |
8aa5f87a1c | ||
![]() |
6deb674377 | ||
![]() |
12d1d998a3 | ||
![]() |
d90162d06f | ||
![]() |
97c924341c | ||
![]() |
e91fc225e1 | ||
![]() |
43149fd832 | ||
![]() |
78df579703 | ||
![]() |
f61b915894 | ||
![]() |
cd3f405bff | ||
![]() |
7cfdca7a81 | ||
![]() |
216063dba8 | ||
![]() |
b647bacd72 | ||
![]() |
4f77937e3e | ||
![]() |
48e299b2ac | ||
![]() |
40f00af196 | ||
![]() |
bd6cc22e63 | ||
![]() |
8760792426 | ||
![]() |
870b0bf7aa | ||
![]() |
afd0bd4318 | ||
![]() |
f829ac1d34 | ||
![]() |
86a0177855 | ||
![]() |
718d4fd0bd | ||
![]() |
365137c32b | ||
![]() |
e83ca0dfda | ||
![]() |
6a9f6ef651 | ||
![]() |
99122ccc03 | ||
![]() |
97923697e1 | ||
![]() |
68888b15e0 | ||
![]() |
f48b26067b | ||
![]() |
4bf2d5837d | ||
![]() |
4eb2d09c75 | ||
![]() |
a146c1c4b6 | ||
![]() |
2f1ea9aa5d | ||
![]() |
a90da62deb | ||
![]() |
c1c3fbdf26 | ||
![]() |
e07a824d82 | ||
![]() |
2aff660a5b | ||
![]() |
abfcbe6f0e | ||
![]() |
28bf72ed75 | ||
![]() |
21b054d4ca | ||
![]() |
34f115b322 | ||
![]() |
8b67354076 | ||
![]() |
b62e0a8b40 | ||
![]() |
f46d5376fe | ||
![]() |
dc3640578f | ||
![]() |
0a43494de5 | ||
![]() |
2544e45d2d | ||
![]() |
4a53e9e018 | ||
![]() |
9d7dc99416 | ||
![]() |
c89dc4ba5b | ||
![]() |
72289ced39 | ||
![]() |
3554ccde05 | ||
![]() |
73e2c42931 | ||
![]() |
b11778ec55 | ||
![]() |
18bc937958 | ||
![]() |
9f618f6678 | ||
![]() |
0c3c7493de | ||
![]() |
8f3f02e9f7 | ||
![]() |
69903ba889 | ||
![]() |
25c5f95ad9 | ||
![]() |
2546d1107e | ||
![]() |
fdbeaf8692 | ||
![]() |
63c0316af2 | ||
![]() |
f2e761c07c | ||
![]() |
6a741de7d1 | ||
![]() |
3e94d18fe1 | ||
![]() |
95d3651e29 | ||
![]() |
cd2d88781a | ||
![]() |
2178e86d09 | ||
![]() |
f9ad0f12d0 | ||
![]() |
63b16d925d | ||
![]() |
53b9ffcbc8 | ||
![]() |
df01f41980 | ||
![]() |
b0c40d3b09 | ||
![]() |
5880dcbcfd | ||
![]() |
489bbc45f5 | ||
![]() |
5e67502729 | ||
![]() |
842079c928 | ||
![]() |
b0bab07a15 | ||
![]() |
4dbb12c65d | ||
![]() |
db500e9791 | ||
![]() |
fd8f600fec | ||
![]() |
2e2d7d02fb | ||
![]() |
d068cd7f75 | ||
![]() |
5a05ffcbdd | ||
![]() |
d8c7f50b39 | ||
![]() |
988e6e1c82 | ||
![]() |
f6af19444c | ||
![]() |
0581e50e0c | ||
![]() |
a95da9a42d | ||
![]() |
be10b9750f | ||
![]() |
29a3cbc688 | ||
![]() |
4f57d3a201 | ||
![]() |
c9be1398b0 | ||
![]() |
30eef4db12 | ||
![]() |
b932dbf514 | ||
![]() |
320ac82dea | ||
![]() |
af1b21db23 | ||
![]() |
0e892ff60e | ||
![]() |
074963aee0 | ||
![]() |
37d9be9095 | ||
![]() |
26e36454ef | ||
![]() |
78b95f67eb | ||
![]() |
6c63841d0c | ||
![]() |
6ec2d91d91 | ||
![]() |
3299b90c20 | ||
![]() |
7b6d6da9a6 | ||
![]() |
7c7c61fc35 | ||
![]() |
c5408fb6b8 | ||
![]() |
1c49102f67 | ||
![]() |
f9dd88c1cb | ||
![]() |
9ed4a65fd2 | ||
![]() |
10bebf8a89 | ||
![]() |
36260dac18 | ||
![]() |
2e4e993967 | ||
![]() |
ef1bfe98f7 | ||
![]() |
2e123aa617 | ||
![]() |
cf2ef0f2a8 | ||
![]() |
520f40d862 | ||
![]() |
856bdac84b | ||
![]() |
deb7e38fcf | ||
![]() |
e5f47a4563 | ||
![]() |
d1b465d8be | ||
![]() |
5c73b2f324 | ||
![]() |
7d3e992b3f | ||
![]() |
296640930e | ||
![]() |
1c42735e3a | ||
![]() |
0800bc1790 | ||
![]() |
bd76a12b90 | ||
![]() |
d3daea6383 | ||
![]() |
df1acd5413 | ||
![]() |
0d65cc09f6 | ||
![]() |
892b082b9e | ||
![]() |
9069ef1325 | ||
![]() |
47cc493ab5 | ||
![]() |
f43d7837f8 | ||
![]() |
91921ae672 | ||
![]() |
eba6afc12b | ||
![]() |
ff826a9eeb | ||
![]() |
6c01a30af5 | ||
![]() |
53f8d09d31 | ||
![]() |
ae191aaafe | ||
![]() |
d1694d563b | ||
![]() |
75fadf79da | ||
![]() |
23ce5a6b1e | ||
![]() |
bb65e2b84d | ||
![]() |
aa42b1d95a | ||
![]() |
32d5a18198 | ||
![]() |
63faefe9c3 | ||
![]() |
a90c49d030 | ||
![]() |
b1ef3fa4df | ||
![]() |
b8cf67cba9 | ||
![]() |
4780e10ade | ||
![]() |
401e606fbc | ||
![]() |
6b4ef8f397 | ||
![]() |
7c66d07779 | ||
![]() |
92aed0cc3a | ||
![]() |
457b08d3cc | ||
![]() |
1e5f6fd2b8 | ||
![]() |
aebfeb98aa | ||
![]() |
f6974e8315 | ||
![]() |
2ce6313ac1 | ||
![]() |
e98a113a59 | ||
![]() |
ba7bed9c2c | ||
![]() |
c9ea451c53 | ||
![]() |
4261ff32c7 | ||
![]() |
cb4b20af45 | ||
![]() |
b8a27adb93 | ||
![]() |
15b58128f4 | ||
![]() |
237282db28 | ||
![]() |
71bb59dbb8 | ||
![]() |
e41c46c075 | ||
![]() |
6ca9e52f2f | ||
![]() |
2afee89de3 | ||
![]() |
189bee3e44 | ||
![]() |
6b9a4d5e0a | ||
![]() |
451e2b2182 | ||
![]() |
f6ff41cfb4 | ||
![]() |
d6d144c927 | ||
![]() |
7f86872139 | ||
![]() |
dc0fc05a9e | ||
![]() |
6b2c3217ab | ||
![]() |
0f93a45b9d | ||
![]() |
943027ffdd | ||
![]() |
5d28b2400f | ||
![]() |
67324bfc80 | ||
![]() |
3c340e7144 | ||
![]() |
c834405a92 | ||
![]() |
4ee9e26847 | ||
![]() |
94293ca9d9 | ||
![]() |
b9cd9f8d35 | ||
![]() |
812dd9282d | ||
![]() |
fa1d386fcc | ||
![]() |
0392bf6a02 | ||
![]() |
97f771ff50 | ||
![]() |
6adcc72a8a | ||
![]() |
2c11bd1889 | ||
![]() |
23e0196fcc | ||
![]() |
91f98c125e | ||
![]() |
7f01e9a4d9 | ||
![]() |
320a4e2351 | ||
![]() |
0829ce51fc | ||
![]() |
97ec50c202 | ||
![]() |
975a3e8103 | ||
![]() |
658ef2ef26 | ||
![]() |
bd1e531d7b | ||
![]() |
e440d1d1bd | ||
![]() |
2110020165 | ||
![]() |
dac74dc30d | ||
![]() |
fa4b971254 | ||
![]() |
2d31ae0baa | ||
![]() |
5eebfa132f | ||
![]() |
522febef93 | ||
![]() |
a421645ea5 | ||
![]() |
0aac4b1347 | ||
![]() |
36697825cf | ||
![]() |
b0182ed604 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,3 +6,5 @@
|
||||
/captures
|
||||
/app/app.iml
|
||||
/.idea
|
||||
/*.iml
|
||||
gradle.properties
|
||||
|
30
.travis.yml
Normal file
30
.travis.yml
Normal 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
33
CONTRIBUTING.md
Normal 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!
|
54
README.md
54
README.md
@@ -1,30 +1,44 @@
|
||||
# NewPipe
|
||||
NewPipe: A free lightweight Youtube frontend for Android.
|
||||
|
||||
[](http://dasochan.nl/newpipe/)
|
||||
|
||||
Project status:
|
||||
[](https://hosted.weblate.org/engage/NewPipe/)
|
||||
[](https://travis-ci.org/theScrabi/NewPipe)
|
||||
|
||||
[](http://dasochan.nl/newpipe/)
|
||||
NewPipe: A free lightweight Youtube frontend for Android.
|
||||
## Get NewPipe
|
||||
|
||||
[](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
|
||||
[](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.
|
||||
|
@@ -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 11
|
||||
versionName "0.7.2"
|
||||
}
|
||||
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'
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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
@@ -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;
|
||||
}
|
71
app/src/main/java/org/schabi/newpipe/App.java
Normal file
71
app/src/main/java/org/schabi/newpipe/App.java
Normal 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;
|
||||
}
|
||||
}
|
357
app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java
Normal file
357
app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,9 @@ import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
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.DialogFragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.util.Log;
|
||||
@@ -42,44 +44,66 @@ 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);
|
||||
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 = "";
|
||||
String downloadFolder = Environment.DIRECTORY_DOWNLOADS;
|
||||
switch(which) {
|
||||
case 0: // Video
|
||||
suffix = arguments.getString(FILE_SUFFIX_VIDEO);
|
||||
url = arguments.getString(VIDEO_URL);
|
||||
downloadFolder = Environment.DIRECTORY_MOVIES;
|
||||
break;
|
||||
case 1:
|
||||
suffix = arguments.getString(FILE_SUFFIX_AUDIO);
|
||||
url = arguments.getString(AUDIO_URL);
|
||||
downloadFolder = Environment.DIRECTORY_MUSIC;
|
||||
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();
|
||||
//to avoid hard-coded string like "/storage/emulated/0/Movies"
|
||||
String downloadPath = prefs.getString(getString(R.string.download_path_key),
|
||||
Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + downloadFolder);
|
||||
final File dir = new File(downloadPath);
|
||||
if(!dir.exists()) {
|
||||
//attempt to create directory
|
||||
boolean mkdir = dir.mkdir();
|
||||
if(!mkdir && !dir.isDirectory()) {
|
||||
Log.e(TAG, "Cant' create directory named " + dir.toString());
|
||||
//TODO notify user "download directory should be changed" ?
|
||||
}
|
||||
}
|
||||
|
||||
String saveFilePath = dir + "/" + title + suffix;
|
||||
if (App.isUsingTor()) {
|
||||
// if using Tor, do not use DownloadManager because the proxy cannot be set
|
||||
Downloader.downloadFile(getContext(), url, saveFilePath);
|
||||
} else {
|
||||
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
DownloadManager.Request request = new DownloadManager.Request(
|
||||
Uri.parse(url));
|
||||
request.setDestinationUri(Uri.fromFile(new File(saveFilePath)));
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
try {
|
||||
dm.enqueue(request);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -1,12 +1,30 @@
|
||||
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.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.
|
||||
*
|
||||
@@ -28,14 +46,19 @@ import java.net.UnknownHostException;
|
||||
*/
|
||||
|
||||
public class Downloader {
|
||||
|
||||
public static final String TAG = "Downloader";
|
||||
private static final String USER_AGENT = "Mozilla/5.0";
|
||||
|
||||
/**Download the text file at the supplied URL as in download(String),
|
||||
* but set the HTTP header field "Accept-Language" to the supplied string.
|
||||
* @param siteUrl the URL of the text file to return the contents of
|
||||
* @param language the language (usually a 2-character code) to set as the preferred language
|
||||
* @return the contents of the specified text file*/
|
||||
public static String download(String siteUrl, String language) {
|
||||
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 +68,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 +90,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 +112,92 @@ 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
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void downloadFile(final Context context, final String fileURL, final String saveFilePath) {
|
||||
new AsyncTask<Void, Integer, Void>() {
|
||||
|
||||
private NotificationManager nm;
|
||||
private NotificationCompat.Builder builder;
|
||||
private int notifyId = 0x1234;
|
||||
private int fileSize = 0xffffffff;
|
||||
|
||||
@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.substring(saveFilePath.lastIndexOf('/') + 1))
|
||||
.setContentText(saveFilePath)
|
||||
.setProgress(fileSize, 0, false);
|
||||
nm.notify(notifyId, builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
HttpsURLConnection con = 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 inputStream = new BufferedInputStream(con.getInputStream());
|
||||
FileOutputStream 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);
|
||||
}
|
||||
}
|
||||
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
publishProgress(bufferSize);
|
||||
|
||||
} else {
|
||||
Log.i(TAG, "No file to download. Server replied HTTP code: " + responseCode);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
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);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
54
app/src/main/java/org/schabi/newpipe/ExitActivity.java
Normal file
54
app/src/main/java/org/schabi/newpipe/ExitActivity.java
Normal 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);
|
||||
}
|
||||
}
|
93
app/src/main/java/org/schabi/newpipe/Localization.java
Normal file
93
app/src/main/java/org/schabi/newpipe/Localization.java
Normal 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);
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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,100 @@ 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 USE_TOR_KEY;
|
||||
|
||||
private ListPreference defaultResolutionPreference;
|
||||
private ListPreference defaultAudioFormatPreference;
|
||||
private ListPreference searchLanguagePreference;
|
||||
private EditTextPreference downloadPathPreference;
|
||||
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);
|
||||
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);
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
@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 +165,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 +246,15 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
}
|
||||
|
||||
public static void initSettings(Context context) {
|
||||
PreferenceManager.setDefaultValues(context, R.xml.settings_screen, false);
|
||||
PreferenceManager.setDefaultValues(context, R.xml.settings, false);
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if(sp.getString(context.getString(R.string.downloadPathPreference), "").isEmpty()){
|
||||
if(sp.getString(context.getString(R.string.download_path_key), "").isEmpty()){
|
||||
SharedPreferences.Editor spEditor = sp.edit();
|
||||
String newPipeDownloadStorage =
|
||||
Environment.getExternalStorageDirectory().getAbsolutePath() + "/NewPipe";
|
||||
spEditor.putString(context.getString(R.string.downloadPathPreference)
|
||||
spEditor.putString(context.getString(R.string.download_path_key)
|
||||
, newPipeDownloadStorage);
|
||||
spEditor.commit();
|
||||
spEditor.apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
@@ -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];
|
||||
}
|
||||
};
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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;
|
@@ -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);
|
@@ -1,8 +1,8 @@
|
||||
package org.schabi.newpipe;
|
||||
package org.schabi.newpipe.services;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.schabi.newpipe.youtube.YoutubeService;
|
||||
import org.schabi.newpipe.services.youtube.YoutubeService;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 23.08.15.
|
||||
@@ -24,6 +24,10 @@ import org.schabi.newpipe.youtube.YoutubeService;
|
||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**Provides access to the video streaming services supported by NewPipe.
|
||||
* Currently only Youtube until the API becomes more stable.*/
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
public class ServiceList {
|
||||
private static final String TAG = ServiceList.class.toString();
|
||||
private static final StreamingService[] services = {
|
||||
@@ -40,7 +44,7 @@ public class ServiceList {
|
||||
}
|
||||
public static int getIdOfService(String serviceName) {
|
||||
for(int i = 0; i < services.length; i++) {
|
||||
if(services[i].getServiceInfo().name == serviceName) {
|
||||
if(services[i].getServiceInfo().name.equals(serviceName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user