mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-09-20 11:20:52 +02:00
Compare commits
176 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1bef7fbbf3 | ||
![]() |
381f054daf | ||
![]() |
c05d9303a9 | ||
![]() |
cca72a9e4e | ||
![]() |
d4463e5f30 | ||
![]() |
92155e2154 | ||
![]() |
287fd0bf1e | ||
![]() |
9e910d5501 | ||
![]() |
ff54b4d0c9 | ||
![]() |
af0b841bc3 | ||
![]() |
665ea85613 | ||
![]() |
de635392c6 | ||
![]() |
7814cca3d5 | ||
![]() |
6c7204eae0 | ||
![]() |
834d647011 | ||
![]() |
d872263b55 | ||
![]() |
4f8e4ca0ad | ||
![]() |
2abc9d0210 | ||
![]() |
36fb942ce6 | ||
![]() |
56476b35e3 | ||
![]() |
38b3835891 | ||
![]() |
ccf5be116a | ||
![]() |
794ae4c5da | ||
![]() |
060e744924 | ||
![]() |
de62ed772f | ||
![]() |
6a8c4a65c5 | ||
![]() |
03738aeb27 | ||
![]() |
243cb8569e | ||
![]() |
1bd660fbbe | ||
![]() |
fec80b39f0 | ||
![]() |
21768432c8 | ||
![]() |
e9b900ff28 | ||
![]() |
c57cb8fec1 | ||
![]() |
247681e3ef | ||
![]() |
2f9142419a | ||
![]() |
b84eb3df7f | ||
![]() |
4058ec2ee9 | ||
![]() |
23a9061871 | ||
![]() |
9e95ca10b2 | ||
![]() |
4c0809d3d3 | ||
![]() |
d43365f6e6 | ||
![]() |
c6ccc2b20d | ||
![]() |
31dd68be1d | ||
![]() |
1c94620c06 | ||
![]() |
82d214faa6 | ||
![]() |
04b2e3689c | ||
![]() |
f00b8a3941 | ||
![]() |
390cc9cfc9 | ||
![]() |
8259872e2d | ||
![]() |
1a3aaf86ee | ||
![]() |
cade4f932d | ||
![]() |
eb060602cd | ||
![]() |
805f046696 | ||
![]() |
35e11e43de | ||
![]() |
ba15c6dc60 | ||
![]() |
569c227a99 | ||
![]() |
8fd7599158 | ||
![]() |
19418e5dfb | ||
![]() |
f90a163ede | ||
![]() |
8fb1fd3602 | ||
![]() |
0dbf2a347f | ||
![]() |
38742fd5e8 | ||
![]() |
67ce7e0979 | ||
![]() |
21a7e52f9a | ||
![]() |
fcb445a381 | ||
![]() |
f6450d4b4d | ||
![]() |
a01d1b89b6 | ||
![]() |
0c9b6582cc | ||
![]() |
2d47daabf8 | ||
![]() |
ce20cbe435 | ||
![]() |
99e5415bfc | ||
![]() |
b2d935dd6d | ||
![]() |
eb66cc5db8 | ||
![]() |
6d6b8363a8 | ||
![]() |
bf79b02e15 | ||
![]() |
3ce7eda3eb | ||
![]() |
378e6b6547 | ||
![]() |
f63b35e2c0 | ||
![]() |
9a480cbe3e | ||
![]() |
76ca937bb8 | ||
![]() |
8a29567572 | ||
![]() |
839cd7d1c7 | ||
![]() |
0bfc7a9177 | ||
![]() |
26e11f96e0 | ||
![]() |
86c36acedc | ||
![]() |
2318ad2bde | ||
![]() |
9548dfabd6 | ||
![]() |
0c716c12d7 | ||
![]() |
08dd176753 | ||
![]() |
07086bfb3e | ||
![]() |
b1d2e64450 | ||
![]() |
d9cd928100 | ||
![]() |
37ec26c8fd | ||
![]() |
68b7d9cdff | ||
![]() |
3aecd15916 | ||
![]() |
97d76aee18 | ||
![]() |
781bf8e7ec | ||
![]() |
77b9457707 | ||
![]() |
1210ab0de0 | ||
![]() |
3c93c4714e | ||
![]() |
f90a1ede70 | ||
![]() |
028354b283 | ||
![]() |
18493a578d | ||
![]() |
1829dc79c8 | ||
![]() |
7575e8fbe3 | ||
![]() |
eed9915c12 | ||
![]() |
be71e45954 | ||
![]() |
3a7978eca0 | ||
![]() |
c37d2250d4 | ||
![]() |
45819d1cd4 | ||
![]() |
4ac36af40c | ||
![]() |
1a2840b33f | ||
![]() |
d7e75e6011 | ||
![]() |
73316b87a3 | ||
![]() |
46402691b0 | ||
![]() |
e7cef4549f | ||
![]() |
737a41f45b | ||
![]() |
045ca40a77 | ||
![]() |
b1fe197c11 | ||
![]() |
8888530ae3 | ||
![]() |
2d51c7428e | ||
![]() |
863e2a80a2 | ||
![]() |
41d17d2a47 | ||
![]() |
36934468d6 | ||
![]() |
5029ce8728 | ||
![]() |
e6ab24bcb4 | ||
![]() |
f3bd263ada | ||
![]() |
db7ab3ffce | ||
![]() |
85c3755b96 | ||
![]() |
5decd55551 | ||
![]() |
bc468b6f36 | ||
![]() |
369d9204d9 | ||
![]() |
7caf7be97e | ||
![]() |
64c423902a | ||
![]() |
27a2dee3bd | ||
![]() |
11d3aeb0dd | ||
![]() |
f54d8d318a | ||
![]() |
210f2ef452 | ||
![]() |
d0bab6183a | ||
![]() |
3441aceba3 | ||
![]() |
0908b9cd76 | ||
![]() |
67494ad4c4 | ||
![]() |
5d8f75beb4 | ||
![]() |
8e7fde99db | ||
![]() |
bfdf165584 | ||
![]() |
9427ebd489 | ||
![]() |
e4f753ae82 | ||
![]() |
f2d9d3c2d7 | ||
![]() |
04c5f31cc1 | ||
![]() |
4ea86b714e | ||
![]() |
cc0b96cba4 | ||
![]() |
9e176f8400 | ||
![]() |
7195ff349b | ||
![]() |
8048ad343e | ||
![]() |
799a27ec84 | ||
![]() |
c7c77ab20c | ||
![]() |
8fc113cc52 | ||
![]() |
c7679bec87 | ||
![]() |
3301d8b4fb | ||
![]() |
f5892093a9 | ||
![]() |
b06238ba5d | ||
![]() |
dddcc80f30 | ||
![]() |
8854c8c9d0 | ||
![]() |
d02f441eb0 | ||
![]() |
ff89dd00b6 | ||
![]() |
7041e63268 | ||
![]() |
8126fdcd15 | ||
![]() |
2d61a2f251 | ||
![]() |
7594ee9dbe | ||
![]() |
0862a38599 | ||
![]() |
d12af16f46 | ||
![]() |
2edfcb78fe | ||
![]() |
3f0947fa5b | ||
![]() |
d2b808e540 | ||
![]() |
4d727245e1 | ||
![]() |
3a8611ebf8 |
@@ -20,6 +20,7 @@ android:
|
|||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- ADB_INSTALL_TIMEOUT=8 # minutes (2 by default)
|
- ADB_INSTALL_TIMEOUT=8 # minutes (2 by default)
|
||||||
|
- GRADLE_OPTS=-Xmx512m # give gradle more memory since it seem to fail otherwise
|
||||||
matrix:
|
matrix:
|
||||||
- ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a
|
- ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a
|
||||||
|
|
||||||
@@ -28,3 +29,5 @@ before_script:
|
|||||||
- emulator -avd test -no-skin -no-audio -no-window &
|
- emulator -avd test -no-skin -no-audio -no-window &
|
||||||
- android-wait-for-emulator
|
- android-wait-for-emulator
|
||||||
- adb shell input keyevent 82 &
|
- adb shell input keyevent 82 &
|
||||||
|
|
||||||
|
script: ./gradlew --info build connectedCheck
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
# NewPipe
|
# NewPipe
|
||||||
NewPipe: A free lightweight Youtube frontend for Android.
|
NewPipe: A free lightweight Youtube frontend for Android.
|
||||||
|
|
||||||
[](http://dasochan.nl/newpipe/)
|
[](https://newpipe.schabi.org)
|
||||||
|
|
||||||
Project status:
|
Project status:
|
||||||
[](https://hosted.weblate.org/engage/NewPipe/)
|
[](https://hosted.weblate.org/engage/NewPipe/)
|
||||||
@@ -11,6 +11,12 @@ Project status:
|
|||||||
|
|
||||||
[](https://f-droid.org/repository/browse/?fdfilter=newpipe&fdid=org.schabi.newpipe)
|
[](https://f-droid.org/repository/browse/?fdfilter=newpipe&fdid=org.schabi.newpipe)
|
||||||
|
|
||||||
|
## Donate
|
||||||
|

|
||||||
|
`16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
[<img src="screenshots/screenshot_1.png" width=150>](screenshots/screenshot_1.png)
|
[<img src="screenshots/screenshot_1.png" width=150>](screenshots/screenshot_1.png)
|
||||||
@@ -36,6 +42,7 @@ NewPipe does not use any Google framework libraries, or the YouTube API. It only
|
|||||||
* Show Next/Related videos
|
* Show Next/Related videos
|
||||||
* Search YouTube in a specific language
|
* Search YouTube in a specific language
|
||||||
* Orbot/Tor support (no streaming yet, experimental)
|
* Orbot/Tor support (no streaming yet, experimental)
|
||||||
|
* Watch age restricted material
|
||||||
|
|
||||||
### Coming Features
|
### Coming Features
|
||||||
|
|
||||||
|
@@ -8,8 +8,8 @@ android {
|
|||||||
applicationId "org.schabi.newpipe"
|
applicationId "org.schabi.newpipe"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 15
|
versionCode 17
|
||||||
versionName "0.7.6"
|
versionName "0.7.8"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
@@ -32,14 +32,15 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
compile 'com.android.support:appcompat-v7:23.1.1'
|
compile 'com.android.support:appcompat-v7:23.2.0'
|
||||||
compile 'com.android.support:support-v4:23.1.1'
|
compile 'com.android.support:support-v4:23.2.0'
|
||||||
compile 'com.android.support:design:23.1.1'
|
compile 'com.android.support:design:23.2.0'
|
||||||
compile 'com.android.support:recyclerview-v7:23.1.1'
|
compile 'com.android.support:recyclerview-v7:23.2.0'
|
||||||
compile 'org.jsoup:jsoup:1.8.3'
|
compile 'org.jsoup:jsoup:1.8.3'
|
||||||
compile 'org.mozilla:rhino:1.7.7'
|
compile 'org.mozilla:rhino:1.7.7'
|
||||||
compile 'info.guardianproject.netcipher:netcipher:1.2'
|
compile 'info.guardianproject.netcipher:netcipher:1.2'
|
||||||
compile 'de.hdodenhof:circleimageview:2.0.0'
|
compile 'de.hdodenhof:circleimageview:2.0.0'
|
||||||
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
||||||
compile 'com.github.nirhart:parallaxscroll:1.0'
|
compile 'com.github.nirhart:parallaxscroll:1.0'
|
||||||
|
compile 'com.google.android.exoplayer:exoplayer:r1.5.5'
|
||||||
}
|
}
|
||||||
|
@@ -1,16 +1,21 @@
|
|||||||
package org.schabi.newpipe.services.youtube;
|
package org.schabi.newpipe.extractor.youtube;
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
import android.test.AndroidTestCase;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.VideoPreviewInfo;
|
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||||
|
import org.schabi.newpipe.extractor.AbstractVideoInfo;
|
||||||
|
import org.schabi.newpipe.extractor.SearchResult;
|
||||||
|
import org.schabi.newpipe.extractor.ServiceList;
|
||||||
|
import org.schabi.newpipe.extractor.StreamPreviewInfo;
|
||||||
import org.schabi.newpipe.extractor.SearchEngine;
|
import org.schabi.newpipe.extractor.SearchEngine;
|
||||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeSearchEngine;
|
import org.schabi.newpipe.extractor.services.youtube.YoutubeSearchEngine;
|
||||||
import org.schabi.newpipe.Downloader;
|
import org.schabi.newpipe.Downloader;
|
||||||
|
import org.schabi.newpipe.extractor.services.youtube.YoutubeService;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by the-scrabi on 29.12.15.
|
* Created by Christian Schabesberger on 29.12.15.
|
||||||
*
|
*
|
||||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||||
* YoutubeSearchEngineTest.java is part of NewPipe.
|
* YoutubeSearchEngineTest.java is part of NewPipe.
|
||||||
@@ -30,21 +35,23 @@ import java.util.ArrayList;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class YoutubeSearchEngineTest extends AndroidTestCase {
|
public class YoutubeSearchEngineTest extends AndroidTestCase {
|
||||||
private SearchEngine.Result result;
|
private SearchResult result;
|
||||||
private ArrayList<String> suggestionReply;
|
private ArrayList<String> suggestionReply;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUp() throws Exception{
|
public void setUp() throws Exception{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
SearchEngine engine = new YoutubeSearchEngine();
|
SearchEngine engine = ServiceList.getService("Youtube")
|
||||||
|
.getSearchEngineInstance(new Downloader());
|
||||||
|
|
||||||
result = engine.search("https://www.youtube.com/results?search_query=bla",
|
result = engine.search("lefloid",
|
||||||
0, "de", new Downloader());
|
0, "de", new Downloader()).getSearchResult();
|
||||||
suggestionReply = engine.suggestionList("hello", new Downloader());
|
suggestionReply = engine.suggestionList("hello","de",new Downloader());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIfNoErrorOccur() {
|
public void testIfNoErrorOccur() {
|
||||||
assertEquals(result.errorMessage, "");
|
assertTrue(result.errors.isEmpty() ? "" : ExceptionUtils.getStackTrace(result.errors.get(0))
|
||||||
|
,result.errors.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIfListIsNotEmpty() {
|
public void testIfListIsNotEmpty() {
|
||||||
@@ -52,43 +59,58 @@ public class YoutubeSearchEngineTest extends AndroidTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testItemsHaveTitle() {
|
public void testItemsHaveTitle() {
|
||||||
for(VideoPreviewInfo i : result.resultList) {
|
for(StreamPreviewInfo i : result.resultList) {
|
||||||
assertEquals(i.title.isEmpty(), false);
|
assertEquals(i.title.isEmpty(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testItemsHaveUploader() {
|
public void testItemsHaveUploader() {
|
||||||
for(VideoPreviewInfo i : result.resultList) {
|
for(StreamPreviewInfo i : result.resultList) {
|
||||||
assertEquals(i.uploader.isEmpty(), false);
|
assertEquals(i.uploader.isEmpty(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testItemsHaveRightDuration() {
|
public void testItemsHaveRightDuration() {
|
||||||
for(VideoPreviewInfo i : result.resultList) {
|
for(StreamPreviewInfo i : result.resultList) {
|
||||||
assertTrue(i.duration, i.duration.contains(":"));
|
assertTrue(i.duration >= 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testItemsHaveRightThumbnail() {
|
public void testItemsHaveRightThumbnail() {
|
||||||
for (VideoPreviewInfo i : result.resultList) {
|
for (StreamPreviewInfo i : result.resultList) {
|
||||||
assertTrue(i.thumbnail_url, i.thumbnail_url.contains("https://"));
|
assertTrue(i.thumbnail_url, i.thumbnail_url.contains("https://"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testItemsHaveRightVideoUrl() {
|
public void testItemsHaveRightVideoUrl() {
|
||||||
for (VideoPreviewInfo i : result.resultList) {
|
for (StreamPreviewInfo i : result.resultList) {
|
||||||
assertTrue(i.webpage_url, i.webpage_url.contains("https://"));
|
assertTrue(i.webpage_url, i.webpage_url.contains("https://"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testViewCount() {
|
public void testViewCount() {
|
||||||
for(VideoPreviewInfo i : result.resultList) {
|
/*
|
||||||
|
for(StreamPreviewInfo i : result.resultList) {
|
||||||
assertTrue(Long.toString(i.view_count), i.view_count != -1);
|
assertTrue(Long.toString(i.view_count), i.view_count != -1);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
// that specific link used for this test, there are no videos with less
|
||||||
|
// than 10.000 views, so we can test against that.
|
||||||
|
for(StreamPreviewInfo i : result.resultList) {
|
||||||
|
assertTrue(i.title + ": " + Long.toString(i.view_count), i.view_count >= 10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStreamType() {
|
||||||
|
for(StreamPreviewInfo i : result.resultList) {
|
||||||
|
assertTrue("not a livestream and not a video",
|
||||||
|
i.stream_type == AbstractVideoInfo.StreamType.VIDEO_STREAM ||
|
||||||
|
i.stream_type == AbstractVideoInfo.StreamType.LIVE_STREAM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIfSuggestionsAreReplied() {
|
public void testIfSuggestionsAreReplied() {
|
||||||
assertEquals(suggestionReply.size() > 0, true);
|
assertEquals(!suggestionReply.isEmpty(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIfSuggestionsAreValid() {
|
public void testIfSuggestionsAreValid() {
|
||||||
|
@@ -1,17 +1,19 @@
|
|||||||
package org.schabi.newpipe.services.youtube;
|
package org.schabi.newpipe.extractor.youtube;
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
import android.test.AndroidTestCase;
|
||||||
|
|
||||||
import org.schabi.newpipe.Downloader;
|
import org.schabi.newpipe.Downloader;
|
||||||
|
import org.schabi.newpipe.extractor.AbstractVideoInfo;
|
||||||
import org.schabi.newpipe.extractor.ExtractionException;
|
import org.schabi.newpipe.extractor.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.ParsingException;
|
import org.schabi.newpipe.extractor.ParsingException;
|
||||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
|
import org.schabi.newpipe.extractor.ServiceList;
|
||||||
import org.schabi.newpipe.extractor.VideoInfo;
|
import org.schabi.newpipe.extractor.StreamExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.VideoStream;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by the-scrabi on 30.12.15.
|
* Created by Christian Schabesberger on 30.12.15.
|
||||||
*
|
*
|
||||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||||
* YoutubeVideoExtractorDefault.java is part of NewPipe.
|
* YoutubeVideoExtractorDefault.java is part of NewPipe.
|
||||||
@@ -31,15 +33,11 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
|
public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
|
||||||
private YoutubeStreamExtractor extractor;
|
private StreamExtractor extractor;
|
||||||
|
|
||||||
public void setUp() throws IOException, ExtractionException {
|
public void setUp() throws IOException, ExtractionException {
|
||||||
/* some anonymus video test
|
extractor = ServiceList.getService("Youtube")
|
||||||
extractor = new YoutubeStreamExtractor("https://www.youtube.com/watch?v=FmG385_uUys",
|
.getExtractorInstance("https://www.youtube.com/watch?v=YQHsXMglC9A", new Downloader());
|
||||||
new Downloader()); */
|
|
||||||
/* some vevo video (suggested to test against) */
|
|
||||||
extractor = new YoutubeStreamExtractor("https://www.youtube.com/watch?v=YQHsXMglC9A",
|
|
||||||
new Downloader());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetInvalidTimeStamp() throws ParsingException {
|
public void testGetInvalidTimeStamp() throws ParsingException {
|
||||||
@@ -48,8 +46,9 @@ public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testGetValidTimeStamp() throws ExtractionException, IOException {
|
public void testGetValidTimeStamp() throws ExtractionException, IOException {
|
||||||
YoutubeStreamExtractor extractor =
|
StreamExtractor extractor =
|
||||||
new YoutubeStreamExtractor("https://youtu.be/FmG385_uUys?t=174", new Downloader());
|
ServiceList.getService("Youtube")
|
||||||
|
.getExtractorInstance("https://youtu.be/FmG385_uUys?t=174", new Downloader());
|
||||||
assertTrue(Integer.toString(extractor.getTimeStamp()),
|
assertTrue(Integer.toString(extractor.getTimeStamp()),
|
||||||
extractor.getTimeStamp() == 174);
|
extractor.getTimeStamp() == 174);
|
||||||
}
|
}
|
||||||
@@ -70,8 +69,9 @@ public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
|
|||||||
assertTrue(extractor.getLength() > 0);
|
assertTrue(extractor.getLength() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetViews() throws ParsingException {
|
public void testGetViewCount() throws ParsingException {
|
||||||
assertTrue(extractor.getLength() > 0);
|
assertTrue(Long.toString(extractor.getViewCount()),
|
||||||
|
extractor.getViewCount() > /* specific to that video */ 1224000074);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetUploadDate() throws ParsingException {
|
public void testGetUploadDate() throws ParsingException {
|
||||||
@@ -93,7 +93,7 @@ public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testGetVideoStreams() throws ParsingException {
|
public void testGetVideoStreams() throws ParsingException {
|
||||||
for(VideoInfo.VideoStream s : extractor.getVideoStreams()) {
|
for(VideoStream s : extractor.getVideoStreams()) {
|
||||||
assertTrue(s.url,
|
assertTrue(s.url,
|
||||||
s.url.contains("https://"));
|
s.url.contains("https://"));
|
||||||
assertTrue(s.resolution.length() > 0);
|
assertTrue(s.resolution.length() > 0);
|
||||||
@@ -102,6 +102,10 @@ public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testStreamType() throws ParsingException {
|
||||||
|
assertTrue(extractor.getStreamType() == AbstractVideoInfo.StreamType.VIDEO_STREAM);
|
||||||
|
}
|
||||||
|
|
||||||
public void testGetDashMpd() throws ParsingException {
|
public void testGetDashMpd() throws ParsingException {
|
||||||
assertTrue(extractor.getDashMpdUrl(),
|
assertTrue(extractor.getDashMpdUrl(),
|
||||||
extractor.getDashMpdUrl() != null || !extractor.getDashMpdUrl().isEmpty());
|
extractor.getDashMpdUrl() != null || !extractor.getDashMpdUrl().isEmpty());
|
||||||
|
@@ -1,15 +1,16 @@
|
|||||||
package org.schabi.newpipe.services.youtube;
|
package org.schabi.newpipe.extractor.youtube;
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
import android.test.AndroidTestCase;
|
||||||
|
|
||||||
import org.schabi.newpipe.Downloader;
|
import org.schabi.newpipe.Downloader;
|
||||||
import org.schabi.newpipe.extractor.ExtractionException;
|
import org.schabi.newpipe.extractor.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.ServiceList;
|
||||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
|
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by the-scrabi on 30.12.15.
|
* Created by Christian Schabesberger on 30.12.15.
|
||||||
*
|
*
|
||||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||||
* YoutubeVideoExtractorGema.java is part of NewPipe.
|
* YoutubeVideoExtractorGema.java is part of NewPipe.
|
||||||
@@ -38,9 +39,9 @@ public class YoutubeStreamExtractorGemaTest extends AndroidTestCase {
|
|||||||
public void testGemaError() throws IOException, ExtractionException {
|
public void testGemaError() throws IOException, ExtractionException {
|
||||||
if(testActive) {
|
if(testActive) {
|
||||||
try {
|
try {
|
||||||
new YoutubeStreamExtractor("https://www.youtube.com/watch?v=3O1_3zBUKM8",
|
ServiceList.getService("Youtube")
|
||||||
|
.getExtractorInstance("https://www.youtube.com/watch?v=3O1_3zBUKM8",
|
||||||
new Downloader());
|
new Downloader());
|
||||||
assertTrue("Gema exception not thrown", false);
|
|
||||||
} catch(YoutubeStreamExtractor.GemaException ge) {
|
} catch(YoutubeStreamExtractor.GemaException ge) {
|
||||||
assertTrue(true);
|
assertTrue(true);
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,87 @@
|
|||||||
|
package org.schabi.newpipe.extractor.youtube;
|
||||||
|
|
||||||
|
import android.test.AndroidTestCase;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.Downloader;
|
||||||
|
import org.schabi.newpipe.extractor.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.ServiceList;
|
||||||
|
import org.schabi.newpipe.extractor.StreamExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.VideoStream;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class YoutubeStreamExtractorRestrictedTest extends AndroidTestCase {
|
||||||
|
private StreamExtractor extractor;
|
||||||
|
|
||||||
|
public void setUp() throws IOException, ExtractionException {
|
||||||
|
extractor = ServiceList.getService("Youtube")
|
||||||
|
.getExtractorInstance("https://www.youtube.com/watch?v=i6JTvzrpBy0",
|
||||||
|
new Downloader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetInvalidTimeStamp() throws ParsingException {
|
||||||
|
assertTrue(Integer.toString(extractor.getTimeStamp()),
|
||||||
|
extractor.getTimeStamp() <= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetValidTimeStamp() throws ExtractionException, IOException {
|
||||||
|
StreamExtractor extractor=ServiceList.getService("Youtube")
|
||||||
|
.getExtractorInstance("https://youtu.be/FmG385_uUys?t=174",
|
||||||
|
new Downloader());
|
||||||
|
assertTrue(Integer.toString(extractor.getTimeStamp()),
|
||||||
|
extractor.getTimeStamp() == 174);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetAgeLimit() throws ParsingException {
|
||||||
|
assertTrue(extractor.getAgeLimit() == 18);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetTitle() throws ParsingException {
|
||||||
|
assertTrue(!extractor.getTitle().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetDescription() throws ParsingException {
|
||||||
|
assertTrue(extractor.getDescription() != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetUploader() throws ParsingException {
|
||||||
|
assertTrue(!extractor.getUploader().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetLength() throws ParsingException {
|
||||||
|
assertTrue(extractor.getLength() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetViews() throws ParsingException {
|
||||||
|
assertTrue(extractor.getLength() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetUploadDate() throws ParsingException {
|
||||||
|
assertTrue(extractor.getUploadDate().length() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetThumbnailUrl() throws ParsingException {
|
||||||
|
assertTrue(extractor.getThumbnailUrl(),
|
||||||
|
extractor.getThumbnailUrl().contains("https://"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetUploaderThumbnailUrl() throws ParsingException {
|
||||||
|
assertTrue(extractor.getUploaderThumbnailUrl(),
|
||||||
|
extractor.getUploaderThumbnailUrl().contains("https://"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetAudioStreams() throws ParsingException {
|
||||||
|
assertTrue(!extractor.getAudioStreams().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetVideoStreams() throws ParsingException {
|
||||||
|
for(VideoStream s : extractor.getVideoStreams()) {
|
||||||
|
assertTrue(s.url,
|
||||||
|
s.url.contains("https://"));
|
||||||
|
assertTrue(s.resolution.length() > 0);
|
||||||
|
assertTrue(Integer.toString(s.format),
|
||||||
|
0 <= s.format && s.format <= 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
package org.schabi.newpipe.extractor.youtube;
|
||||||
|
|
||||||
|
import android.test.AndroidTestCase;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.Downloader;
|
||||||
|
import org.schabi.newpipe.extractor.AbstractVideoInfo;
|
||||||
|
import org.schabi.newpipe.extractor.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.ServiceList;
|
||||||
|
import org.schabi.newpipe.extractor.StreamExtractor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Christian Schabesberger on 11.03.16.
|
||||||
|
*
|
||||||
|
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||||
|
* YoutubestreamExtractorLiveStreamTest.java is part of NewPipe.
|
||||||
|
*
|
||||||
|
* NewPipe is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NewPipe is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
public class YoutubestreamExtractorLiveStreamTest extends AndroidTestCase {
|
||||||
|
|
||||||
|
private StreamExtractor extractor;
|
||||||
|
|
||||||
|
public void setUp() throws IOException, ExtractionException {
|
||||||
|
//todo: make the extractor not throw over a livestream
|
||||||
|
/*
|
||||||
|
extractor = ServiceList.getService("Youtube")
|
||||||
|
.getExtractorInstance("https://www.youtube.com/watch?v=J0s6NjqdjLE", new Downloader());
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStreamType() throws ParsingException {
|
||||||
|
assertTrue(true);
|
||||||
|
// assertTrue(extractor.getStreamType() == AbstractVideoInfo.StreamType.LIVE_STREAM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -1,23 +1,24 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="org.schabi.newpipe" >
|
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.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:logo="@mipmap/ic_launcher"
|
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
android:logo="@mipmap/ic_launcher"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
tools:ignore="AllowBackup">
|
tools:ignore="AllowBackup">
|
||||||
<activity
|
<activity
|
||||||
android:name=".VideoItemListActivity"
|
android:name=".VideoItemListActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name">
|
||||||
android:configChanges="orientation|screenSize">
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
@@ -27,9 +28,7 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".VideoItemDetailActivity"
|
android:name=".VideoItemDetailActivity"
|
||||||
android:label="@string/title_videoitem_detail"
|
android:label="@string/title_videoitem_detail"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme">
|
||||||
android:configChanges="orientation|screenSize"
|
|
||||||
android:screenOrientation="portrait">
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".VideoItemListActivity" />
|
android:value=".VideoItemListActivity" />
|
||||||
@@ -76,20 +75,40 @@
|
|||||||
<data android:scheme="vnd.youtube.launch" />
|
<data android:scheme="vnd.youtube.launch" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".PlayVideoActivity"
|
<activity
|
||||||
|
android:name=".player.PlayVideoActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||||
android:theme="@style/VideoPlayerTheme"
|
android:theme="@style/VideoPlayerTheme"
|
||||||
android:parentActivityName=".VideoItemDetailActivity"
|
tools:ignore="UnusedAttribute"/>
|
||||||
tools:ignore="UnusedAttribute">
|
<service
|
||||||
|
android:name=".player.BackgroundPlayer"
|
||||||
|
android:exported="false"
|
||||||
|
android:label="@string/background_player_name"/>
|
||||||
|
<activity
|
||||||
|
android:name=".player.ExoPlayerActivity"
|
||||||
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:launchMode="singleInstance"
|
||||||
|
android:theme="@style/PlayerTheme">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="org.schabi.newpipe.exoplayer.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
|
<data android:scheme="http" />
|
||||||
|
<data android:scheme="https" />
|
||||||
|
<data android:scheme="content" />
|
||||||
|
<data android:scheme="asset" />
|
||||||
|
<data android:scheme="file" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<service
|
<service
|
||||||
android:name=".BackgroundPlayer"
|
android:name=".player.BackgroundPlayer"
|
||||||
android:label="@string/background_player_name"
|
android:label="@string/background_player_name"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".SettingsActivity"
|
android:name=".SettingsActivity"
|
||||||
android:label="@string/settings_activity_title" >
|
android:label="@string/settings_activity_title" />
|
||||||
</activity>
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".PanicResponderActivity"
|
android:name=".PanicResponderActivity"
|
||||||
android:launchMode="singleInstance"
|
android:launchMode="singleInstance"
|
||||||
@@ -97,11 +116,14 @@
|
|||||||
android:theme="@android:style/Theme.NoDisplay">
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="info.guardianproject.panic.action.TRIGGER" />
|
<action android:name="info.guardianproject.panic.action.TRIGGER" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ExitActivity"
|
android:name=".ExitActivity"
|
||||||
|
android:label="@string/general_error"
|
||||||
android:theme="@android:style/Theme.NoDisplay" />
|
android:theme="@android:style/Theme.NoDisplay" />
|
||||||
|
<activity android:name=".ErrorActivity"/>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@@ -12,7 +12,8 @@ import android.view.MenuItem;
|
|||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.MediaFormat;
|
import org.schabi.newpipe.extractor.MediaFormat;
|
||||||
import org.schabi.newpipe.extractor.VideoInfo;
|
import org.schabi.newpipe.extractor.StreamInfo;
|
||||||
|
import org.schabi.newpipe.extractor.VideoStream;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ class ActionBarHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setupStreamList(final List<VideoInfo.VideoStream> videoStreams) {
|
public void setupStreamList(final List<VideoStream> videoStreams) {
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
selectedVideoStream = 0;
|
selectedVideoStream = 0;
|
||||||
|
|
||||||
@@ -83,7 +84,7 @@ class ActionBarHandler {
|
|||||||
// this array will be shown in the dropdown menu for selecting the stream/resolution.
|
// this array will be shown in the dropdown menu for selecting the stream/resolution.
|
||||||
String[] itemArray = new String[videoStreams.size()];
|
String[] itemArray = new String[videoStreams.size()];
|
||||||
for (int i = 0; i < videoStreams.size(); i++) {
|
for (int i = 0; i < videoStreams.size(); i++) {
|
||||||
VideoInfo.VideoStream item = videoStreams.get(i);
|
VideoStream item = videoStreams.get(i);
|
||||||
itemArray[i] = MediaFormat.getNameById(item.format) + " " + item.resolution;
|
itemArray[i] = MediaFormat.getNameById(item.format) + " " + item.resolution;
|
||||||
}
|
}
|
||||||
int defaultResolution = getDefaultResolution(videoStreams);
|
int defaultResolution = getDefaultResolution(videoStreams);
|
||||||
@@ -108,13 +109,13 @@ class ActionBarHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private int getDefaultResolution(final List<VideoInfo.VideoStream> videoStreams) {
|
private int getDefaultResolution(final List<VideoStream> videoStreams) {
|
||||||
String defaultResolution = defaultPreferences
|
String defaultResolution = defaultPreferences
|
||||||
.getString(activity.getString(R.string.default_resolution_key),
|
.getString(activity.getString(R.string.default_resolution_key),
|
||||||
activity.getString(R.string.default_resolution_value));
|
activity.getString(R.string.default_resolution_value));
|
||||||
|
|
||||||
for (int i = 0; i < videoStreams.size(); i++) {
|
for (int i = 0; i < videoStreams.size(); i++) {
|
||||||
VideoInfo.VideoStream item = videoStreams.get(i);
|
VideoStream item = videoStreams.get(i);
|
||||||
if (defaultResolution.equals(item.resolution)) {
|
if (defaultResolution.equals(item.resolution)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@@ -22,10 +22,12 @@ package org.schabi.newpipe;
|
|||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton:
|
* Singleton:
|
||||||
* Used to send data between certain Activity/Services within the same process.
|
* Used to send data between certain Activity/Services within the same process.
|
||||||
* This can be considered as hack inside the Android universe. **/
|
* This can be considered as an ugly hack inside the Android universe. **/
|
||||||
public class ActivityCommunicator {
|
public class ActivityCommunicator {
|
||||||
|
|
||||||
private static ActivityCommunicator activityCommunicator = null;
|
private static ActivityCommunicator activityCommunicator = null;
|
||||||
@@ -39,4 +41,9 @@ public class ActivityCommunicator {
|
|||||||
|
|
||||||
// Thumbnail send from VideoItemDetailFragment to BackgroundPlayer
|
// Thumbnail send from VideoItemDetailFragment to BackgroundPlayer
|
||||||
public volatile Bitmap backgroundPlayerThumbnail;
|
public volatile Bitmap backgroundPlayerThumbnail;
|
||||||
|
|
||||||
|
// Sent from any activity to ErrorActivity.
|
||||||
|
public volatile List<Exception> errorList;
|
||||||
|
public volatile Class returnActivity;
|
||||||
|
public volatile ErrorActivity.ErrorInfo errorInfo;
|
||||||
}
|
}
|
||||||
|
@@ -57,7 +57,7 @@ public class App extends Application {
|
|||||||
/**
|
/**
|
||||||
* Set the proxy settings based on whether Tor should be enabled or not.
|
* Set the proxy settings based on whether Tor should be enabled or not.
|
||||||
*/
|
*/
|
||||||
static void configureTor(boolean enabled) {
|
public static void configureTor(boolean enabled) {
|
||||||
useTor = enabled;
|
useTor = enabled;
|
||||||
if (useTor) {
|
if (useTor) {
|
||||||
NetCipher.useTor();
|
NetCipher.useTor();
|
||||||
@@ -66,13 +66,13 @@ public class App extends Application {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkStartTor(Context context) {
|
public static void checkStartTor(Context context) {
|
||||||
if (useTor) {
|
if (useTor) {
|
||||||
OrbotHelper.requestStartTor(context);
|
OrbotHelper.requestStartTor(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isUsingTor() {
|
public static boolean isUsingTor() {
|
||||||
return useTor;
|
return useTor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
410
app/src/main/java/org/schabi/newpipe/ErrorActivity.java
Normal file
410
app/src/main/java/org/schabi/newpipe/ErrorActivity.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,9 @@ import java.util.Locale;
|
|||||||
|
|
||||||
public class Localization {
|
public class Localization {
|
||||||
|
|
||||||
|
private Localization() {
|
||||||
|
}
|
||||||
|
|
||||||
public static Locale getPreferredLocale(Context context) {
|
public static Locale getPreferredLocale(Context context) {
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
|
||||||
|
@@ -25,7 +25,6 @@ import android.content.SharedPreferences;
|
|||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@@ -33,16 +32,16 @@ import java.io.File;
|
|||||||
* Helper for global settings
|
* Helper for global settings
|
||||||
*/
|
*/
|
||||||
public class NewPipeSettings {
|
public class NewPipeSettings {
|
||||||
|
|
||||||
|
private NewPipeSettings() {
|
||||||
|
}
|
||||||
|
|
||||||
public static void initSettings(Context context) {
|
public static void initSettings(Context context) {
|
||||||
PreferenceManager.setDefaultValues(context, R.xml.settings, false);
|
PreferenceManager.setDefaultValues(context, R.xml.settings, false);
|
||||||
getVideoDownloadFolder(context);
|
getVideoDownloadFolder(context);
|
||||||
getAudioDownloadFolder(context);
|
getAudioDownloadFolder(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getDownloadFolder() {
|
|
||||||
return getFolder(Environment.DIRECTORY_DOWNLOADS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File getVideoDownloadFolder(Context context) {
|
public static File getVideoDownloadFolder(Context context) {
|
||||||
return getFolder(context, R.string.download_path_key, Environment.DIRECTORY_MOVIES);
|
return getFolder(context, R.string.download_path_key, Environment.DIRECTORY_MOVIES);
|
||||||
}
|
}
|
||||||
|
@@ -119,18 +119,20 @@ public class SettingsActivity extends PreferenceActivity {
|
|||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
||||||
String key) {
|
String key) {
|
||||||
Activity a = getActivity();
|
Activity a = getActivity();
|
||||||
updateSummary();
|
if(a != null) {
|
||||||
|
updateSummary();
|
||||||
|
|
||||||
if (defaultPreferences.getBoolean(USE_TOR_KEY, false)) {
|
if (defaultPreferences.getBoolean(USE_TOR_KEY, false)) {
|
||||||
if (OrbotHelper.isOrbotInstalled(a)) {
|
if (OrbotHelper.isOrbotInstalled(a)) {
|
||||||
App.configureTor(true);
|
App.configureTor(true);
|
||||||
OrbotHelper.requestStartTor(a);
|
OrbotHelper.requestStartTor(a);
|
||||||
|
} else {
|
||||||
|
Intent intent = OrbotHelper.getOrbotInstallIntent(a);
|
||||||
|
a.startActivityForResult(intent, REQUEST_INSTALL_ORBOT);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Intent intent = OrbotHelper.getOrbotInstallIntent(a);
|
App.configureTor(false);
|
||||||
a.startActivityForResult(intent, REQUEST_INSTALL_ORBOT);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
App.configureTor(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -0,0 +1,82 @@
|
|||||||
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.MatrixCursor;
|
||||||
|
import android.support.v4.widget.CursorAdapter;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Madiyar on 23.02.2016.
|
||||||
|
*
|
||||||
|
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||||
|
* SuggestionListAdapter.java is part of NewPipe.
|
||||||
|
*
|
||||||
|
* NewPipe is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NewPipe is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SuggestionListAdapter extends CursorAdapter {
|
||||||
|
|
||||||
|
private String[] columns = new String[]{"_id", "title"};
|
||||||
|
|
||||||
|
public SuggestionListAdapter(Context context) {
|
||||||
|
super(context, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||||
|
ViewHolder viewHolder;
|
||||||
|
|
||||||
|
View view = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false);
|
||||||
|
viewHolder = new ViewHolder();
|
||||||
|
viewHolder.suggestionTitle = (TextView) view.findViewById(android.R.id.text1);
|
||||||
|
view.setTag(viewHolder);
|
||||||
|
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bindView(View view, Context context, Cursor cursor) {
|
||||||
|
ViewHolder viewHolder = (ViewHolder) view.getTag();
|
||||||
|
viewHolder.suggestionTitle.setText(cursor.getString(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void updateAdapter(ArrayList<String> suggestions) {
|
||||||
|
MatrixCursor cursor = new MatrixCursor(columns);
|
||||||
|
int i = 0;
|
||||||
|
for (String s : suggestions) {
|
||||||
|
String[] temp = new String[2];
|
||||||
|
temp[0] = Integer.toString(i);
|
||||||
|
temp[1] = s;
|
||||||
|
i++;
|
||||||
|
cursor.addRow(temp);
|
||||||
|
}
|
||||||
|
changeCursor(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSuggestion(int position) {
|
||||||
|
return ((Cursor) getItem(position)).getString(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ViewHolder {
|
||||||
|
public TextView suggestionTitle;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,13 +1,14 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.VideoPreviewInfo;
|
import org.schabi.newpipe.extractor.AbstractVideoInfo;
|
||||||
|
import org.schabi.newpipe.extractor.StreamPreviewInfo;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ import com.nostra13.universalimageloader.core.ImageLoader;
|
|||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class VideoInfoItemViewCreator {
|
public class VideoInfoItemViewCreator {
|
||||||
private final LayoutInflater inflater;
|
private final LayoutInflater inflater;
|
||||||
private ImageLoader imageLoader = ImageLoader.getInstance();
|
private ImageLoader imageLoader = ImageLoader.getInstance();
|
||||||
private DisplayImageOptions displayImageOptions = new DisplayImageOptions.Builder().cacheInMemory(true).build();
|
private DisplayImageOptions displayImageOptions = new DisplayImageOptions.Builder().cacheInMemory(true).build();
|
||||||
@@ -40,8 +41,10 @@ class VideoInfoItemViewCreator {
|
|||||||
this.inflater = inflater;
|
this.inflater = inflater;
|
||||||
}
|
}
|
||||||
|
|
||||||
public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, VideoPreviewInfo info, Context context) {
|
public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, StreamPreviewInfo info) {
|
||||||
ViewHolder holder;
|
ViewHolder holder;
|
||||||
|
|
||||||
|
// generate holder
|
||||||
if(convertView == null) {
|
if(convertView == null) {
|
||||||
convertView = inflater.inflate(R.layout.video_item, parent, false);
|
convertView = inflater.inflate(R.layout.video_item, parent, false);
|
||||||
holder = new ViewHolder();
|
holder = new ViewHolder();
|
||||||
@@ -56,20 +59,43 @@ class VideoInfoItemViewCreator {
|
|||||||
holder = (ViewHolder) convertView.getTag();
|
holder = (ViewHolder) convertView.getTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fill with information
|
||||||
|
|
||||||
|
/*
|
||||||
if(info.thumbnail == null) {
|
if(info.thumbnail == null) {
|
||||||
holder.itemThumbnailView.setImageResource(R.drawable.dummy_thumbnail);
|
holder.itemThumbnailView.setImageResource(R.drawable.dummy_thumbnail);
|
||||||
} else {
|
} else {
|
||||||
holder.itemThumbnailView.setImageBitmap(info.thumbnail);
|
holder.itemThumbnailView.setImageBitmap(info.thumbnail);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
holder.itemVideoTitleView.setText(info.title);
|
holder.itemVideoTitleView.setText(info.title);
|
||||||
holder.itemUploaderView.setText(info.uploader);
|
if(info.uploader != null && !info.uploader.isEmpty()) {
|
||||||
holder.itemDurationView.setText(info.duration);
|
holder.itemUploaderView.setText(info.uploader);
|
||||||
holder.itemViewCountView.setText(shortViewCount(info.view_count));
|
} else {
|
||||||
|
holder.itemDurationView.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
if(info.duration > 0) {
|
||||||
|
holder.itemDurationView.setText(getDurationString(info.duration));
|
||||||
|
} else {
|
||||||
|
if(info.stream_type == AbstractVideoInfo.StreamType.LIVE_STREAM) {
|
||||||
|
holder.itemDurationView.setText(R.string.duration_live);
|
||||||
|
} else {
|
||||||
|
holder.itemDurationView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(info.view_count >= 0) {
|
||||||
|
holder.itemViewCountView.setText(shortViewCount(info.view_count));
|
||||||
|
} else {
|
||||||
|
holder.itemViewCountView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
if(!info.upload_date.isEmpty()) {
|
if(!info.upload_date.isEmpty()) {
|
||||||
holder.itemUploadDateView.setText(info.upload_date+" • ");
|
holder.itemUploadDateView.setText(info.upload_date + " • ");
|
||||||
}
|
}
|
||||||
|
|
||||||
imageLoader.displayImage(info.thumbnail_url, holder.itemThumbnailView, displayImageOptions);
|
holder.itemThumbnailView.setImageResource(R.drawable.dummy_thumbnail);
|
||||||
|
if(info.thumbnail_url != null && !info.thumbnail_url.isEmpty()) {
|
||||||
|
imageLoader.displayImage(info.thumbnail_url, holder.itemThumbnailView, displayImageOptions);
|
||||||
|
}
|
||||||
|
|
||||||
return convertView;
|
return convertView;
|
||||||
}
|
}
|
||||||
@@ -79,16 +105,69 @@ class VideoInfoItemViewCreator {
|
|||||||
public TextView itemVideoTitleView, itemUploaderView, itemDurationView, itemUploadDateView, itemViewCountView;
|
public TextView itemVideoTitleView, itemUploaderView, itemDurationView, itemUploadDateView, itemViewCountView;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String shortViewCount(Long view_count){
|
private String shortViewCount(Long viewCount){
|
||||||
if(view_count >= 1000000000){
|
if(viewCount >= 1000000000){
|
||||||
return Long.toString(view_count/1000000000)+"B views";
|
return Long.toString(viewCount/1000000000)+"B views";
|
||||||
}else if(view_count>=1000000){
|
}else if(viewCount>=1000000){
|
||||||
return Long.toString(view_count/1000000)+"M views";
|
return Long.toString(viewCount/1000000)+"M views";
|
||||||
}else if(view_count>=1000){
|
}else if(viewCount>=1000){
|
||||||
return Long.toString(view_count/1000)+"K views";
|
return Long.toString(viewCount/1000)+"K views";
|
||||||
}else {
|
}else {
|
||||||
return Long.toString(view_count)+" views";
|
return Long.toString(viewCount)+" views";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getDurationString(int duration) {
|
||||||
|
String output = "";
|
||||||
|
int days = duration / (24 * 60 * 60); /* greater than a day */
|
||||||
|
duration %= (24 * 60 * 60);
|
||||||
|
int hours = duration / (60 * 60); /* greater than an hour */
|
||||||
|
duration %= (60 * 60);
|
||||||
|
int minutes = duration / 60;
|
||||||
|
int seconds = duration % 60;
|
||||||
|
|
||||||
|
//handle days
|
||||||
|
if(days > 0) {
|
||||||
|
output = Integer.toString(days) + ":";
|
||||||
|
}
|
||||||
|
// handle hours
|
||||||
|
if(hours > 0 || !output.isEmpty()) {
|
||||||
|
if(hours > 0) {
|
||||||
|
if(hours >= 10 || output.isEmpty()) {
|
||||||
|
output += Integer.toString(minutes);
|
||||||
|
} else {
|
||||||
|
output += "0" + Integer.toString(minutes);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output += "00";
|
||||||
|
}
|
||||||
|
output += ":";
|
||||||
|
}
|
||||||
|
//handle minutes
|
||||||
|
if(minutes > 0 || !output.isEmpty()) {
|
||||||
|
if(minutes > 0) {
|
||||||
|
if(minutes >= 10 || output.isEmpty()) {
|
||||||
|
output += Integer.toString(minutes);
|
||||||
|
} else {
|
||||||
|
output += "0" + Integer.toString(minutes);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output += "00";
|
||||||
|
}
|
||||||
|
output += ":";
|
||||||
|
}
|
||||||
|
|
||||||
|
//handle seconds
|
||||||
|
if(output.isEmpty()) {
|
||||||
|
output += "0:";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(seconds >= 10) {
|
||||||
|
output += Integer.toString(seconds);
|
||||||
|
} else {
|
||||||
|
output += "0" + Integer.toString(seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -73,7 +73,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
|||||||
StreamingService[] serviceList = ServiceList.getServices();
|
StreamingService[] serviceList = ServiceList.getServices();
|
||||||
//StreamExtractor videoExtractor = null;
|
//StreamExtractor videoExtractor = null;
|
||||||
for (int i = 0; i < serviceList.length; i++) {
|
for (int i = 0; i < serviceList.length; i++) {
|
||||||
if (serviceList[i].getUrlIdHandler().acceptUrl(videoUrl)) {
|
if (serviceList[i].getUrlIdHandlerInstance().acceptUrl(videoUrl)) {
|
||||||
arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, i);
|
arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, i);
|
||||||
currentStreamingService = i;
|
currentStreamingService = i;
|
||||||
//videoExtractor = ServiceList.getService(i).getExtractorInstance();
|
//videoExtractor = ServiceList.getService(i).getExtractorInstance();
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -17,8 +18,8 @@ import java.io.IOException;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.ExtractionException;
|
import org.schabi.newpipe.extractor.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.ParsingException;
|
import org.schabi.newpipe.extractor.SearchResult;
|
||||||
import org.schabi.newpipe.extractor.VideoPreviewInfo;
|
import org.schabi.newpipe.extractor.StreamPreviewInfo;
|
||||||
import org.schabi.newpipe.extractor.SearchEngine;
|
import org.schabi.newpipe.extractor.SearchEngine;
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
|
|
||||||
@@ -68,9 +69,9 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
private boolean loadingNextPage = true;
|
private boolean loadingNextPage = true;
|
||||||
|
|
||||||
private class ResultRunnable implements Runnable {
|
private class ResultRunnable implements Runnable {
|
||||||
private final SearchEngine.Result result;
|
private final SearchResult result;
|
||||||
private final int requestId;
|
private final int requestId;
|
||||||
public ResultRunnable(SearchEngine.Result result, int requestId) {
|
public ResultRunnable(SearchResult result, int requestId) {
|
||||||
this.result = result;
|
this.result = result;
|
||||||
this.requestId = requestId;
|
this.requestId = requestId;
|
||||||
}
|
}
|
||||||
@@ -101,32 +102,60 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
SearchResult result = null;
|
||||||
try {
|
try {
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
String searchLanguageKey = getContext().getString(R.string.search_language_key);
|
String searchLanguageKey = getContext().getString(R.string.search_language_key);
|
||||||
String searchLanguage = sp.getString(searchLanguageKey,
|
String searchLanguage = sp.getString(searchLanguageKey,
|
||||||
getString(R.string.default_language_value));
|
getString(R.string.default_language_value));
|
||||||
SearchEngine.Result result = engine.search(query, page, searchLanguage,
|
result = SearchResult
|
||||||
new Downloader());
|
.getSearchResult(engine, query, page, searchLanguage, new Downloader());
|
||||||
|
|
||||||
//Log.i(TAG, "language code passed:\""+searchLanguage+"\"");
|
|
||||||
if(runs) {
|
if(runs) {
|
||||||
h.post(new ResultRunnable(result, requestId));
|
h.post(new ResultRunnable(result, requestId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// look for errors during extraction
|
||||||
|
// soft errors:
|
||||||
|
if(result != null &&
|
||||||
|
!result.errors.isEmpty()) {
|
||||||
|
Log.e(TAG, "OCCURRED ERRORS DURING SEARCH EXTRACTION:");
|
||||||
|
for(Exception e : result.errors) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Log.e(TAG, "------");
|
||||||
|
}
|
||||||
|
|
||||||
|
Activity a = getActivity();
|
||||||
|
View rootView = a.findViewById(R.id.videoitem_list);
|
||||||
|
ErrorActivity.reportError(h, getActivity(), result.errors, null, rootView,
|
||||||
|
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
|
||||||
|
/* todo: this shoudl not be assigned static */ "Youtube", query, R.string.light_parsing_error));
|
||||||
|
|
||||||
|
}
|
||||||
|
// hard errors:
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
postNewErrorToast(h, R.string.network_error);
|
postNewNothingFoundToast(h, R.string.network_error);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch(ExtractionException ce) {
|
} catch(SearchEngine.NothingFoundException e) {
|
||||||
postNewErrorToast(h, R.string.parsing_error);
|
postNewErrorToast(h, e.getMessage());
|
||||||
ce.printStackTrace();
|
} catch(ExtractionException e) {
|
||||||
|
ErrorActivity.reportError(h, getActivity(), e, null, null,
|
||||||
|
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
|
||||||
|
/* todo: this shoudl not be assigned static */ "Youtube", query, R.string.parsing_error));
|
||||||
|
//postNewErrorToast(h, R.string.parsing_error);
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
postNewErrorToast(h, R.string.general_error);
|
ErrorActivity.reportError(h, getActivity(), e, null, null,
|
||||||
|
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
|
||||||
|
/* todo: this shoudl not be assigned static */ "Youtube", query, R.string.general_error));
|
||||||
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void present(List<VideoPreviewInfo> videoList) {
|
public void present(List<StreamPreviewInfo> videoList) {
|
||||||
mode = PRESENT_VIDEOS_MODE;
|
mode = PRESENT_VIDEOS_MODE;
|
||||||
setListShown(true);
|
setListShown(true);
|
||||||
getListView().smoothScrollToPosition(0);
|
getListView().smoothScrollToPosition(0);
|
||||||
@@ -156,7 +185,7 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
private void startSearch(String query, int page) {
|
private void startSearch(String query, int page) {
|
||||||
currentRequestId++;
|
currentRequestId++;
|
||||||
terminateThreads();
|
terminateThreads();
|
||||||
searchRunnable = new SearchRunnable(streamingService.getSearchEngineInstance(),
|
searchRunnable = new SearchRunnable(streamingService.getSearchEngineInstance(new Downloader()),
|
||||||
query, page, currentRequestId);
|
query, page, currentRequestId);
|
||||||
searchThread = new Thread(searchRunnable);
|
searchThread = new Thread(searchRunnable);
|
||||||
searchThread.start();
|
searchThread.start();
|
||||||
@@ -166,28 +195,29 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
this.streamingService = streamingService;
|
this.streamingService = streamingService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateListOnResult(SearchEngine.Result result, int requestId) {
|
private void updateListOnResult(SearchResult result, int requestId) {
|
||||||
if(requestId == currentRequestId) {
|
if(requestId == currentRequestId) {
|
||||||
setListShown(true);
|
setListShown(true);
|
||||||
if (result.resultList.isEmpty()) {
|
updateList(result.resultList);
|
||||||
Toast.makeText(getActivity(), result.errorMessage, Toast.LENGTH_LONG).show();
|
if(!result.suggestion.isEmpty()) {
|
||||||
} else {
|
Toast.makeText(getActivity(),
|
||||||
if (!result.suggestion.isEmpty()) {
|
String.format(getString(R.string.did_you_mean), result.suggestion),
|
||||||
Toast.makeText(getActivity(), getString(R.string.did_you_mean) + result.suggestion + " ?",
|
Toast.LENGTH_LONG).show();
|
||||||
Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
updateList(result.resultList);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateList(List<VideoPreviewInfo> list) {
|
private void updateList(List<StreamPreviewInfo> list) {
|
||||||
try {
|
try {
|
||||||
videoListAdapter.addVideoList(list);
|
videoListAdapter.addVideoList(list);
|
||||||
terminateThreads();
|
terminateThreads();
|
||||||
} catch(java.lang.IllegalStateException e) {
|
} catch(java.lang.IllegalStateException e) {
|
||||||
|
Toast.makeText(getActivity(), "Trying to set value while activity doesn't exist anymore.",
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
Log.w(TAG, "Trying to set value while activity doesn't exist anymore.");
|
Log.w(TAG, "Trying to set value while activity doesn't exist anymore.");
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.general_error),
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
loadingNextPage = false;
|
loadingNextPage = false;
|
||||||
@@ -314,13 +344,24 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
mActivatedPosition = position;
|
mActivatedPosition = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postNewErrorToast(Handler h, final int stringResource) {
|
private void postNewErrorToast(Handler h, final String message) {
|
||||||
|
h.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
setListShown(true);
|
||||||
|
Toast.makeText(getActivity(), message,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void postNewNothingFoundToast(Handler h, final int stringResource) {
|
||||||
h.post(new Runnable() {
|
h.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
setListShown(true);
|
setListShown(true);
|
||||||
Toast.makeText(getActivity(), getString(stringResource),
|
Toast.makeText(getActivity(), getString(stringResource),
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,7 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.BaseAdapter;
|
import android.widget.BaseAdapter;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.VideoPreviewInfo;
|
import org.schabi.newpipe.extractor.StreamPreviewInfo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
@@ -36,7 +36,7 @@ import java.util.Vector;
|
|||||||
class VideoListAdapter extends BaseAdapter {
|
class VideoListAdapter extends BaseAdapter {
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final VideoInfoItemViewCreator viewCreator;
|
private final VideoInfoItemViewCreator viewCreator;
|
||||||
private Vector<VideoPreviewInfo> videoList = new Vector<>();
|
private Vector<StreamPreviewInfo> videoList = new Vector<>();
|
||||||
private final ListView listView;
|
private final ListView listView;
|
||||||
|
|
||||||
public VideoListAdapter(Context context, VideoItemListFragment videoListFragment) {
|
public VideoListAdapter(Context context, VideoItemListFragment videoListFragment) {
|
||||||
@@ -47,7 +47,7 @@ class VideoListAdapter extends BaseAdapter {
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addVideoList(List<VideoPreviewInfo> videos) {
|
public void addVideoList(List<StreamPreviewInfo> videos) {
|
||||||
videoList.addAll(videos);
|
videoList.addAll(videos);
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ class VideoListAdapter extends BaseAdapter {
|
|||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector<VideoPreviewInfo> getVideoList() {
|
public Vector<StreamPreviewInfo> getVideoList() {
|
||||||
return videoList;
|
return videoList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ class VideoListAdapter extends BaseAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position), context);
|
convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position));
|
||||||
|
|
||||||
if(listView.isItemChecked(position)) {
|
if(listView.isItemChecked(position)) {
|
||||||
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.light_youtube_primary_color));
|
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.light_youtube_primary_color));
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe.download;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
@@ -16,6 +16,10 @@ import android.support.v7.app.AlertDialog;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.App;
|
||||||
|
import org.schabi.newpipe.NewPipeSettings;
|
||||||
|
import org.schabi.newpipe.R;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -71,7 +75,8 @@ public class DownloadDialog extends DialogFragment {
|
|||||||
case 0: // Video
|
case 0: // Video
|
||||||
download(arguments.getString(VIDEO_URL),
|
download(arguments.getString(VIDEO_URL),
|
||||||
title,
|
title,
|
||||||
arguments.getString(FILE_SUFFIX_VIDEO), context);
|
arguments.getString(FILE_SUFFIX_VIDEO),
|
||||||
|
NewPipeSettings.getVideoDownloadFolder(context),context);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.d(TAG, "lolz");
|
Log.d(TAG, "lolz");
|
||||||
@@ -89,7 +94,8 @@ public class DownloadDialog extends DialogFragment {
|
|||||||
case 0: // Audio
|
case 0: // Audio
|
||||||
download(arguments.getString(AUDIO_URL),
|
download(arguments.getString(AUDIO_URL),
|
||||||
title,
|
title,
|
||||||
arguments.getString(FILE_SUFFIX_AUDIO), context);
|
arguments.getString(FILE_SUFFIX_AUDIO),
|
||||||
|
NewPipeSettings.getAudioDownloadFolder(context),context);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.d(TAG, "lolz");
|
Log.d(TAG, "lolz");
|
||||||
@@ -107,12 +113,14 @@ public class DownloadDialog extends DialogFragment {
|
|||||||
case 0: // Video
|
case 0: // Video
|
||||||
download(arguments.getString(VIDEO_URL),
|
download(arguments.getString(VIDEO_URL),
|
||||||
title,
|
title,
|
||||||
arguments.getString(FILE_SUFFIX_VIDEO), context);
|
arguments.getString(FILE_SUFFIX_VIDEO),
|
||||||
|
NewPipeSettings.getVideoDownloadFolder(context), context);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
download(arguments.getString(AUDIO_URL),
|
download(arguments.getString(AUDIO_URL),
|
||||||
title,
|
title,
|
||||||
arguments.getString(FILE_SUFFIX_AUDIO), context);
|
arguments.getString(FILE_SUFFIX_AUDIO),
|
||||||
|
NewPipeSettings.getAudioDownloadFolder(context), context);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.d(TAG, "lolz");
|
Log.d(TAG, "lolz");
|
||||||
@@ -130,7 +138,7 @@ public class DownloadDialog extends DialogFragment {
|
|||||||
private String createFileName(String fName) {
|
private String createFileName(String fName) {
|
||||||
// from http://eng-przemelek.blogspot.de/2009/07/how-to-create-valid-file-name.html
|
// from http://eng-przemelek.blogspot.de/2009/07/how-to-create-valid-file-name.html
|
||||||
|
|
||||||
List<String> forbiddenCharsPatterns = new ArrayList<String> ();
|
List<String> forbiddenCharsPatterns = new ArrayList<> ();
|
||||||
forbiddenCharsPatterns.add("[:]+"); // Mac OS, but it looks that also Windows XP
|
forbiddenCharsPatterns.add("[:]+"); // Mac OS, but it looks that also Windows XP
|
||||||
forbiddenCharsPatterns.add("[\\*\"/\\\\\\[\\]\\:\\;\\|\\=\\,]+"); // Windows
|
forbiddenCharsPatterns.add("[\\*\"/\\\\\\[\\]\\:\\;\\|\\=\\,]+"); // Windows
|
||||||
forbiddenCharsPatterns.add("[^\\w\\d\\.]+"); // last chance... only latin letters and digits
|
forbiddenCharsPatterns.add("[^\\w\\d\\.]+"); // last chance... only latin letters and digits
|
||||||
@@ -141,8 +149,8 @@ public class DownloadDialog extends DialogFragment {
|
|||||||
return nameToTest;
|
return nameToTest;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void download(String url, String title, String fileSuffix, Context context) {
|
private void download(String url, String title,
|
||||||
File downloadDir = NewPipeSettings.getDownloadFolder();
|
String fileSuffix, File downloadDir, Context context) {
|
||||||
|
|
||||||
if(!downloadDir.exists()) {
|
if(!downloadDir.exists()) {
|
||||||
//attempt to create directory
|
//attempt to create directory
|
||||||
@@ -162,6 +170,8 @@ public class DownloadDialog extends DialogFragment {
|
|||||||
File saveFilePath = new File(downloadDir,createFileName(title) + fileSuffix);
|
File saveFilePath = new File(downloadDir,createFileName(title) + fileSuffix);
|
||||||
|
|
||||||
long id = 0;
|
long id = 0;
|
||||||
|
|
||||||
|
|
||||||
if (App.isUsingTor()) {
|
if (App.isUsingTor()) {
|
||||||
// if using Tor, do not use DownloadManager because the proxy cannot be set
|
// if using Tor, do not use DownloadManager because the proxy cannot be set
|
||||||
FileDownloader.downloadFile(getContext(), url, saveFilePath, title);
|
FileDownloader.downloadFile(getContext(), url, saveFilePath, title);
|
@@ -1,26 +1,21 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe.download;
|
||||||
|
|
||||||
|
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.R;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
|
||||||
@@ -46,6 +41,8 @@ import info.guardianproject.netcipher.NetCipher;
|
|||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: FOR HEVEN SAKE !!! DO NOT SIMPLY USE ASYNCTASK. MAKE THIS A PROPER SERVICE !!!
|
||||||
public class FileDownloader extends AsyncTask<Void, Integer, Void> {
|
public class FileDownloader extends AsyncTask<Void, Integer, Void> {
|
||||||
public static final String TAG = "FileDownloader";
|
public static final String TAG = "FileDownloader";
|
||||||
|
|
||||||
@@ -165,5 +162,4 @@ public class FileDownloader extends AsyncTask<Void, Integer, Void> {
|
|||||||
super.onPostExecute(aVoid);
|
super.onPostExecute(aVoid);
|
||||||
nm.cancel(notifyId);
|
nm.cancel(notifyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -20,8 +20,19 @@ import android.graphics.Bitmap;
|
|||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**Common properties between VideoInfo and VideoPreviewInfo.*/
|
/**Common properties between StreamInfo and StreamPreviewInfo.*/
|
||||||
public abstract class AbstractVideoInfo {
|
public abstract class AbstractVideoInfo {
|
||||||
|
public static enum StreamType {
|
||||||
|
NONE, // placeholder to check if stream type was checked or not
|
||||||
|
VIDEO_STREAM,
|
||||||
|
AUDIO_STREAM,
|
||||||
|
LIVE_STREAM,
|
||||||
|
AUDIO_LIVE_STREAM,
|
||||||
|
FILE
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamType stream_type;
|
||||||
|
public int service_id = -1;
|
||||||
public String id = "";
|
public String id = "";
|
||||||
public String title = "";
|
public String title = "";
|
||||||
public String uploader = "";
|
public String uploader = "";
|
||||||
|
@@ -0,0 +1,46 @@
|
|||||||
|
package org.schabi.newpipe.extractor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Christian Schabesberger on 04.03.16.
|
||||||
|
*
|
||||||
|
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||||
|
* AudioStream.java is part of NewPipe.
|
||||||
|
*
|
||||||
|
* NewPipe is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NewPipe is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class AudioStream {
|
||||||
|
public String url = "";
|
||||||
|
public int format = -1;
|
||||||
|
public int bandwidth = -1;
|
||||||
|
public int sampling_rate = -1;
|
||||||
|
|
||||||
|
public AudioStream(String url, int format, int bandwidth, int samplingRate) {
|
||||||
|
this.url = url; this.format = format;
|
||||||
|
this.bandwidth = bandwidth; this.sampling_rate = samplingRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reveals wether two streams are the same, but have diferent urls
|
||||||
|
public boolean equalStats(AudioStream cmp) {
|
||||||
|
return format == cmp.format
|
||||||
|
&& bandwidth == cmp.bandwidth
|
||||||
|
&& sampling_rate == cmp.sampling_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// revelas wether two streams are equal
|
||||||
|
public boolean equals(AudioStream cmp) {
|
||||||
|
return cmp != null && equalStats(cmp)
|
||||||
|
&& url == cmp.url;
|
||||||
|
}
|
||||||
|
}
|
@@ -31,13 +31,16 @@ import java.util.Vector;
|
|||||||
|
|
||||||
public class DashMpdParser {
|
public class DashMpdParser {
|
||||||
|
|
||||||
|
private DashMpdParser() {
|
||||||
|
}
|
||||||
|
|
||||||
static class DashMpdParsingException extends ParsingException {
|
static class DashMpdParsingException extends ParsingException {
|
||||||
DashMpdParsingException(String message, Exception e) {
|
DashMpdParsingException(String message, Exception e) {
|
||||||
super(message, e);
|
super(message, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<VideoInfo.AudioStream> getAudioStreams(String dashManifestUrl,
|
public static List<AudioStream> getAudioStreams(String dashManifestUrl,
|
||||||
Downloader downloader)
|
Downloader downloader)
|
||||||
throws DashMpdParsingException {
|
throws DashMpdParsingException {
|
||||||
String dashDoc;
|
String dashDoc;
|
||||||
@@ -46,7 +49,7 @@ public class DashMpdParser {
|
|||||||
} catch(IOException ioe) {
|
} catch(IOException ioe) {
|
||||||
throw new DashMpdParsingException("Could not get dash mpd: " + dashManifestUrl, ioe);
|
throw new DashMpdParsingException("Could not get dash mpd: " + dashManifestUrl, ioe);
|
||||||
}
|
}
|
||||||
Vector<VideoInfo.AudioStream> audioStreams = new Vector<>();
|
Vector<AudioStream> audioStreams = new Vector<>();
|
||||||
try {
|
try {
|
||||||
XmlPullParser parser = Xml.newPullParser();
|
XmlPullParser parser = Xml.newPullParser();
|
||||||
parser.setInput(new StringReader(dashDoc));
|
parser.setInput(new StringReader(dashDoc));
|
||||||
@@ -83,7 +86,7 @@ public class DashMpdParser {
|
|||||||
} else if(currentMimeType.equals(MediaFormat.M4A.mimeType)) {
|
} else if(currentMimeType.equals(MediaFormat.M4A.mimeType)) {
|
||||||
format = MediaFormat.M4A.id;
|
format = MediaFormat.M4A.id;
|
||||||
}
|
}
|
||||||
audioStreams.add(new VideoInfo.AudioStream(parser.getText(),
|
audioStreams.add(new AudioStream(parser.getText(),
|
||||||
format, currentBandwidth, currentSamplingRate));
|
format, currentBandwidth, currentSamplingRate));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -21,8 +21,6 @@ package org.schabi.newpipe.extractor;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class ExtractionException extends Exception {
|
public class ExtractionException extends Exception {
|
||||||
public ExtractionException() {}
|
|
||||||
|
|
||||||
public ExtractionException(String message) {
|
public ExtractionException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
package org.schabi.newpipe.extractor;
|
package org.schabi.newpipe.extractor;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -30,6 +32,9 @@ import java.util.regex.Pattern;
|
|||||||
/** avoid using regex !!! */
|
/** avoid using regex !!! */
|
||||||
public class Parser {
|
public class Parser {
|
||||||
|
|
||||||
|
private Parser() {
|
||||||
|
}
|
||||||
|
|
||||||
public static class RegexException extends ParsingException {
|
public static class RegexException extends ParsingException {
|
||||||
public RegexException(String message) {
|
public RegexException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
@@ -52,8 +57,12 @@ public class Parser {
|
|||||||
public static Map<String, String> compatParseMap(final String input) throws UnsupportedEncodingException {
|
public static Map<String, String> compatParseMap(final String input) throws UnsupportedEncodingException {
|
||||||
Map<String, String> map = new HashMap<>();
|
Map<String, String> map = new HashMap<>();
|
||||||
for(String arg : input.split("&")) {
|
for(String arg : input.split("&")) {
|
||||||
String[] split_arg = arg.split("=");
|
String[] splitArg = arg.split("=");
|
||||||
map.put(split_arg[0], URLDecoder.decode(split_arg[1], "UTF-8"));
|
if(splitArg.length > 1) {
|
||||||
|
map.put(splitArg[0], URLDecoder.decode(splitArg[1], "UTF-8"));
|
||||||
|
} else {
|
||||||
|
map.put(splitArg[0], "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
@@ -22,13 +22,9 @@ package org.schabi.newpipe.extractor;
|
|||||||
|
|
||||||
|
|
||||||
public class ParsingException extends ExtractionException {
|
public class ParsingException extends ExtractionException {
|
||||||
public ParsingException() {}
|
|
||||||
public ParsingException(String message) {
|
public ParsingException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
public ParsingException(Throwable cause) {
|
|
||||||
super(cause);
|
|
||||||
}
|
|
||||||
public ParsingException(String message, Throwable cause) {
|
public ParsingException(String message, Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
}
|
}
|
||||||
|
@@ -26,17 +26,29 @@ import java.util.Vector;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@SuppressWarnings("ALL")
|
@SuppressWarnings("ALL")
|
||||||
public interface SearchEngine {
|
public abstract class SearchEngine {
|
||||||
class Result {
|
public static class NothingFoundException extends ExtractionException {
|
||||||
public String errorMessage = "";
|
public NothingFoundException(String message) {
|
||||||
public String suggestion = "";
|
super(message);
|
||||||
public final List<VideoPreviewInfo> resultList = new Vector<>();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<String> suggestionList(String query, Downloader dl)
|
private StreamPreviewInfoCollector collector;
|
||||||
|
|
||||||
|
public SearchEngine(StreamUrlIdHandler urlIdHandler, int serviceId) {
|
||||||
|
collector = new StreamPreviewInfoCollector(urlIdHandler, serviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamPreviewInfoCollector getStreamPreviewInfoCollector() {
|
||||||
|
return collector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract ArrayList<String> suggestionList(
|
||||||
|
String query,String contentCountry, Downloader dl)
|
||||||
throws ExtractionException, IOException;
|
throws ExtractionException, IOException;
|
||||||
|
|
||||||
//Result search(String query, int page);
|
//Result search(String query, int page);
|
||||||
Result search(String query, int page, String contentCountry, Downloader dl)
|
public abstract StreamPreviewInfoCollector search(
|
||||||
|
String query, int page, String contentCountry, Downloader dl)
|
||||||
throws ExtractionException, IOException;
|
throws ExtractionException, IOException;
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user