mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-09-23 09:20:51 +02:00
Compare commits
139 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e5bf98a741 | ||
![]() |
06fafc247e | ||
![]() |
e8bb17b631 | ||
![]() |
363cd07883 | ||
![]() |
2b4a9286c4 | ||
![]() |
34c985026f | ||
![]() |
4a0aa42914 | ||
![]() |
746c2a15bf | ||
![]() |
9318bb5306 | ||
![]() |
2a10ceb74f | ||
![]() |
83f4db59e2 | ||
![]() |
9f66f759ad | ||
![]() |
6f015349e8 | ||
![]() |
a37802c2b9 | ||
![]() |
4fa3baf5e1 | ||
![]() |
ef8c2c81d5 | ||
![]() |
8c80d8c457 | ||
![]() |
1596872c54 | ||
![]() |
da8873fa78 | ||
![]() |
ecd8439b3f | ||
![]() |
5d178532ac | ||
![]() |
08e40a013d | ||
![]() |
c136f7363c | ||
![]() |
a60f10d739 | ||
![]() |
ae46afcb42 | ||
![]() |
bffb9f6800 | ||
![]() |
79aa9ad04b | ||
![]() |
ff5714f04a | ||
![]() |
ce499a9766 | ||
![]() |
d3bb8b7651 | ||
![]() |
6d9c23c4cb | ||
![]() |
b95a9332a9 | ||
![]() |
609715eb5c | ||
![]() |
a1266c919c | ||
![]() |
a1925a0302 | ||
![]() |
a7a4c03372 | ||
![]() |
37201600e0 | ||
![]() |
a94f40ed62 | ||
![]() |
0b08cf8c76 | ||
![]() |
33e29be7db | ||
![]() |
bd1c7851c7 | ||
![]() |
82faea5965 | ||
![]() |
0bbbfd3217 | ||
![]() |
fb578ecda8 | ||
![]() |
e804647a65 | ||
![]() |
c3c3a94593 | ||
![]() |
9d55569f80 | ||
![]() |
5dd8271c15 | ||
![]() |
7a4a54c3ea | ||
![]() |
7c9078a625 | ||
![]() |
71ae342f52 | ||
![]() |
b43c56085d | ||
![]() |
83d2ab95e0 | ||
![]() |
20a8d7372c | ||
![]() |
c36ba88db7 | ||
![]() |
4aa23023ee | ||
![]() |
8735cf931a | ||
![]() |
2473069326 | ||
![]() |
03bab57a97 | ||
![]() |
e3baf69533 | ||
![]() |
461f747af1 | ||
![]() |
028872a7d8 | ||
![]() |
a1483b6c55 | ||
![]() |
e406ba094c | ||
![]() |
c100d15ba8 | ||
![]() |
b4ea592638 | ||
![]() |
16b757d9a3 | ||
![]() |
2aa801a392 | ||
![]() |
b838344526 | ||
![]() |
233a3df222 | ||
![]() |
da6661b1ea | ||
![]() |
c6e120fc51 | ||
![]() |
c416a1254d | ||
![]() |
2aa4f6ddda | ||
![]() |
129597023d | ||
![]() |
02aed86b7e | ||
![]() |
e44f4b5823 | ||
![]() |
2f0c0f0fc2 | ||
![]() |
e5ce3f3007 | ||
![]() |
095a2be748 | ||
![]() |
c75fe88757 | ||
![]() |
a8ff4b0744 | ||
![]() |
c02c511e31 | ||
![]() |
b9550fb528 | ||
![]() |
a37d8f083a | ||
![]() |
abff1f537b | ||
![]() |
483fde5e42 | ||
![]() |
761b7ea57b | ||
![]() |
af92631a0c | ||
![]() |
ffe832d061 | ||
![]() |
a08cbfcef1 | ||
![]() |
d2d6ac1bf8 | ||
![]() |
615ffca64b | ||
![]() |
2fcf6197c5 | ||
![]() |
22d31ae14f | ||
![]() |
8c786e121b | ||
![]() |
99d2a33c8c | ||
![]() |
010a24db3f | ||
![]() |
9408da453b | ||
![]() |
dbda4202fd | ||
![]() |
5776e91459 | ||
![]() |
664d7b69b1 | ||
![]() |
6b9140c60d | ||
![]() |
383857d110 | ||
![]() |
cffd049c8a | ||
![]() |
ecabc65e94 | ||
![]() |
780f1d5da3 | ||
![]() |
e2d0fc34a3 | ||
![]() |
3404231457 | ||
![]() |
b17928570d | ||
![]() |
8ed86261ef | ||
![]() |
a313b91a0a | ||
![]() |
7b6dae20be | ||
![]() |
552c70bb0d | ||
![]() |
8f734737f0 | ||
![]() |
800e7bcb7a | ||
![]() |
2002234d86 | ||
![]() |
5923663e08 | ||
![]() |
4cdf20ab8c | ||
![]() |
af65a1cfef | ||
![]() |
927057ab83 | ||
![]() |
ffbc001ad5 | ||
![]() |
f5625a1151 | ||
![]() |
ce2ceb8a1b | ||
![]() |
c14771534f | ||
![]() |
553cec16d5 | ||
![]() |
d17496f720 | ||
![]() |
89e70626eb | ||
![]() |
2ccae841d6 | ||
![]() |
07f6d0f149 | ||
![]() |
319d769233 | ||
![]() |
6ec393699e | ||
![]() |
f8d9e0fa60 | ||
![]() |
50ed962a82 | ||
![]() |
8654705e9b | ||
![]() |
b79ed8185f | ||
![]() |
0d6c67f64f | ||
![]() |
e97a6569a6 | ||
![]() |
c2fcae7c43 |
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "app/src/main/java/org/schabi/newpipe/extractor"]
|
||||
path = app/src/main/java/org/schabi/newpipe/extractor
|
||||
url = https://github.com/TeamNewPipe/NewPipeExtractor.git
|
24
.travis.yml
24
.travis.yml
@@ -5,35 +5,15 @@ android:
|
||||
components:
|
||||
# The BuildTools version used by NewPipe
|
||||
- tools
|
||||
- build-tools-23.0.3
|
||||
- build-tools-25.0.0
|
||||
|
||||
# The SDK version used to compile NewPipe
|
||||
- android-25
|
||||
|
||||
# Additional components
|
||||
- extra-android-support
|
||||
- extra-android-m2repository
|
||||
- extra-google-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)
|
||||
- GRADLE_OPTS=-Xmx512m # give gradle more memory since it seem to fail otherwise
|
||||
matrix:
|
||||
- ANDROID_TARGET=android-21 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 &
|
||||
|
||||
script: ./gradlew --info build connectedCheck
|
||||
script: ./gradlew -Dorg.gradle.jvmargs=-Xmx1536m assembleDebug lintDebug testDebugUnitTest
|
||||
|
||||
licenses:
|
||||
- '.+'
|
||||
|
BIN
CCC_NewPipe_presentation.pdf
Normal file
BIN
CCC_NewPipe_presentation.pdf
Normal file
Binary file not shown.
10
README.md
10
README.md
@@ -37,23 +37,27 @@ NewPipe does not use any Google framework libraries, or the YouTube API. It only
|
||||
* Listen to YouTube videos (experimental)
|
||||
* Select the streaming player to watch the video with
|
||||
* Download videos
|
||||
* Download audio only * Open a video in Kodi
|
||||
* Download audio only
|
||||
* Open a video in Kodi
|
||||
* Show Next/Related videos
|
||||
* Search YouTube in a specific language
|
||||
* Watch age restricted material
|
||||
* Display general information about channels
|
||||
* Search channels
|
||||
* Watch videos from a channel
|
||||
* Orbot/Tor support (not yet directly)
|
||||
|
||||
### Coming Features
|
||||
|
||||
* Orbot/Tor support
|
||||
* Bookmarks
|
||||
* View history
|
||||
* Search history
|
||||
* Subscribe to channels
|
||||
* Watch videos from a channel
|
||||
* Search/Watch Playlists
|
||||
* Queeing videos
|
||||
* Subtitles support
|
||||
* 1080p support
|
||||
* livestream support
|
||||
* ... and many more
|
||||
|
||||
### Multiservice support
|
||||
|
@@ -2,14 +2,14 @@ apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion '23.0.3'
|
||||
buildToolsVersion '25.0.0'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "org.schabi.newpipe"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 25
|
||||
versionCode 24
|
||||
versionName "0.8.10"
|
||||
versionCode 29
|
||||
versionName "0.9.2"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
@@ -32,21 +32,21 @@ android {
|
||||
|
||||
dependencies {
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile 'com.android.support:appcompat-v7:25.1.1'
|
||||
compile 'com.android.support:support-v4:25.1.1'
|
||||
compile 'com.android.support:design:25.1.1'
|
||||
compile 'com.android.support:recyclerview-v7:25.1.1'
|
||||
testCompile 'org.mockito:mockito-core:1.10.19'
|
||||
testCompile 'org.json:json:20160810'
|
||||
|
||||
compile 'com.android.support:appcompat-v7:25.1.0'
|
||||
compile 'com.android.support:support-v4:25.1.0'
|
||||
compile 'com.android.support:design:25.1.0'
|
||||
compile 'com.android.support:recyclerview-v7:25.1.0'
|
||||
compile 'org.jsoup:jsoup:1.8.3'
|
||||
compile 'org.mozilla:rhino:1.7.7'
|
||||
compile 'info.guardianproject.netcipher:netcipher:1.2'
|
||||
compile 'de.hdodenhof:circleimageview:2.0.0'
|
||||
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
||||
compile 'com.github.nirhart:parallaxscroll:1.0'
|
||||
compile 'com.google.android.exoplayer:exoplayer:r1.5.5'
|
||||
compile 'com.google.code.gson:gson:2.4'
|
||||
compile 'com.nononsenseapps:filepicker:3.0.0'
|
||||
compile 'ch.acra:acra:4.9.0'
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'org.mockito:mockito-core:1.10.19'
|
||||
testCompile 'org.json:json:20160810'
|
||||
compile 'com.google.android.exoplayer:exoplayer:r2.3.1'
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@
|
||||
<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" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
@@ -16,72 +17,17 @@
|
||||
android:logo="@mipmap/ic_launcher"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="AllowBackup">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name">
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".detail.VideoItemDetailActivity"
|
||||
android:label="@string/title_videoitem_detail"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/AppTheme">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".MainActivity" />
|
||||
|
||||
<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="youtube.com" />
|
||||
<data android:host="m.youtube.com" />
|
||||
<data android:host="www.youtube.com" />
|
||||
<data android:pathPrefix="/v/" />
|
||||
<data android:pathPrefix="/watch" />
|
||||
<data android:pathPrefix="/attribution_link" />
|
||||
</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>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".player.PlayVideoActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
@@ -97,25 +43,8 @@
|
||||
android:name=".player.ExoPlayerActivity"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleInstance"
|
||||
android:theme="@style/PlayerTheme">
|
||||
<intent-filter>
|
||||
<action android:name="org.schabi.newpipe.exoplayer.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
<data android:scheme="content" />
|
||||
<data android:scheme="asset" />
|
||||
<data android:scheme="file" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".player.BackgroundPlayer"
|
||||
android:exported="false"
|
||||
android:label="@string/background_player_name" />
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/PlayerTheme"/>
|
||||
|
||||
<activity
|
||||
android:name=".settings.SettingsActivity"
|
||||
@@ -149,16 +78,8 @@
|
||||
<activity
|
||||
android:name="com.nononsenseapps.filepicker.FilePickerActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/FilePickerTheme"
|
||||
android:launchMode="singleTop">
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ChannelActivity"
|
||||
android:label="@string/title_activity_channel"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/FilePickerTheme"/>
|
||||
<activity
|
||||
android:name=".ReCaptchaActivity"
|
||||
android:label="@string/reCaptchaActivity" />
|
||||
@@ -170,8 +91,125 @@
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/provider_paths"/>
|
||||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
|
||||
<activity
|
||||
android:name=".RouterActivity"
|
||||
android:taskAffinity=""
|
||||
android:theme="@android:style/Theme.NoDisplay">
|
||||
<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="youtube.com" />
|
||||
<data android:host="m.youtube.com" />
|
||||
<data android:host="www.youtube.com" />
|
||||
<!-- video prefix -->
|
||||
<data android:pathPrefix="/v/" />
|
||||
<data android:pathPrefix="/embed/" />
|
||||
<data android:pathPrefix="/watch" />
|
||||
<data android:pathPrefix="/attribution_link" />
|
||||
<!-- channel prefix -->
|
||||
<data android:pathPrefix="/channel/"/>
|
||||
<data android:pathPrefix="/user/"/>
|
||||
</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>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".RouterPopupActivity"
|
||||
android:taskAffinity=""
|
||||
android:theme="@android:style/Theme.NoDisplay"
|
||||
android:label="@string/popup_mode_share_menu_title">
|
||||
<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="youtube.com" />
|
||||
<data android:host="m.youtube.com" />
|
||||
<data android:host="www.youtube.com" />
|
||||
<!-- video prefix -->
|
||||
<data android:pathPrefix="/v/" />
|
||||
<data android:pathPrefix="/embed/" />
|
||||
<data android:pathPrefix="/watch" />
|
||||
<data android:pathPrefix="/attribution_link" />
|
||||
</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>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service android:name=".player.PopupVideoPlayer"/>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
</manifest>
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,14 @@
|
||||
package org.schabi.newpipe;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.View;
|
||||
|
||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
||||
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 01.08.16.
|
||||
@@ -33,11 +33,11 @@ import org.schabi.newpipe.extractor.NewPipe;
|
||||
public class ImageErrorLoadingListener implements ImageLoadingListener {
|
||||
|
||||
private int serviceId = -1;
|
||||
private Activity activity = null;
|
||||
private Context context = null;
|
||||
private View rootView = null;
|
||||
|
||||
public ImageErrorLoadingListener(Activity activity, View rootView, int serviceId) {
|
||||
this.activity = activity;
|
||||
public ImageErrorLoadingListener(Context context, View rootView, int serviceId) {
|
||||
this.context = context;
|
||||
this.serviceId= serviceId;
|
||||
this.rootView = rootView;
|
||||
}
|
||||
@@ -47,7 +47,7 @@ public class ImageErrorLoadingListener implements ImageLoadingListener {
|
||||
|
||||
@Override
|
||||
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
||||
ErrorActivity.reportError(activity,
|
||||
ErrorActivity.reportError(context,
|
||||
failReason.getCause(), null, rootView,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.LOAD_IMAGE,
|
||||
NewPipe.getNameOfService(serviceId), imageUri,
|
||||
|
@@ -1,59 +1,99 @@
|
||||
package org.schabi.newpipe;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.media.AudioManager;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
import org.schabi.newpipe.download.DownloadActivity;
|
||||
import org.schabi.newpipe.settings.SettingsActivity;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Created by Christian Schabesberger on 02.08.16.
|
||||
*
|
||||
* <p>
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* DownloadActivity.java is part of NewPipe.
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
*
|
||||
* <p>
|
||||
* 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 MainActivity extends ThemableActivity {
|
||||
private Fragment mainFragment = null;
|
||||
package org.schabi.newpipe;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
|
||||
import org.schabi.newpipe.download.DownloadActivity;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.fragments.OnItemSelectedListener;
|
||||
import org.schabi.newpipe.fragments.channel.ChannelFragment;
|
||||
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
|
||||
import org.schabi.newpipe.fragments.search.SearchFragment;
|
||||
import org.schabi.newpipe.settings.SettingsActivity;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements OnItemSelectedListener {
|
||||
private static final String TAG = MainActivity.class.toString();
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Activity's LifeCycle
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
ThemeHelper.setTheme(this, true);
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
mainFragment = getSupportFragmentManager()
|
||||
.findFragmentById(R.id.search_fragment);
|
||||
if (savedInstanceState == null) initFragments();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
handleIntent(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
|
||||
if (fragment instanceof VideoDetailFragment) if (((VideoDetailFragment) fragment).onActivityBackPressed()) return;
|
||||
|
||||
if (getSupportFragmentManager().getBackStackEntryCount() >= 2) {
|
||||
getSupportFragmentManager().popBackStackImmediate();
|
||||
} else {
|
||||
if (fragment instanceof SearchFragment) {
|
||||
SearchFragment searchFragment = (SearchFragment) fragment;
|
||||
if (!searchFragment.isMainBgVisible()) {
|
||||
getSupportFragmentManager().beginTransaction().remove(fragment).commitNow();
|
||||
NavigationHelper.openMainActivity(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Menu
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
|
||||
inflater.inflate(R.menu.main_menu, menu);
|
||||
return true;
|
||||
}
|
||||
@@ -64,9 +104,10 @@ public class MainActivity extends ThemableActivity {
|
||||
|
||||
switch (id) {
|
||||
case android.R.id.home: {
|
||||
Intent intent = new Intent(this, MainActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
NavUtils.navigateUpTo(this, intent);
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
|
||||
if (fragment instanceof VideoDetailFragment) ((VideoDetailFragment) fragment).clearHistory();
|
||||
|
||||
NavigationHelper.openMainActivity(this);
|
||||
return true;
|
||||
}
|
||||
case R.id.action_settings: {
|
||||
@@ -87,8 +128,111 @@ public class MainActivity extends ThemableActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
//ignore back
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Init
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private void initFragments() {
|
||||
if (getIntent() != null && getIntent().hasExtra(Constants.KEY_URL)) {
|
||||
handleIntent(getIntent());
|
||||
} else openSearchFragment();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// OnItemSelectedListener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onItemSelected(StreamingService.LinkType linkType, int serviceId, String url, String name) {
|
||||
switch (linkType) {
|
||||
case STREAM:
|
||||
openVideoDetailFragment(serviceId, url, name, false);
|
||||
break;
|
||||
case CHANNEL:
|
||||
openChannelFragment(serviceId, url, name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
if (intent.hasExtra(Constants.KEY_LINK_TYPE)) {
|
||||
String url = intent.getStringExtra(Constants.KEY_URL);
|
||||
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
|
||||
try {
|
||||
switch (((StreamingService.LinkType) intent.getSerializableExtra(Constants.KEY_LINK_TYPE))) {
|
||||
case STREAM:
|
||||
handleVideoDetailIntent(serviceId, url, intent);
|
||||
break;
|
||||
case CHANNEL:
|
||||
handleChannelIntent(serviceId, url, intent);
|
||||
break;
|
||||
case NONE:
|
||||
throw new Exception("Url not known to service. service=" + Integer.toString(serviceId) + " url=" + url);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
openSearchFragment();
|
||||
}
|
||||
}
|
||||
|
||||
private void openSearchFragment() {
|
||||
ImageLoader.getInstance().clearMemoryCache();
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
|
||||
.replace(R.id.fragment_holder, new SearchFragment())
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
}
|
||||
|
||||
private void openVideoDetailFragment(int serviceId, String url, String title, boolean autoPlay) {
|
||||
ImageLoader.getInstance().clearMemoryCache();
|
||||
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
|
||||
if (title == null) title = "";
|
||||
|
||||
if (fragment instanceof VideoDetailFragment && fragment.isVisible()) {
|
||||
VideoDetailFragment detailFragment = (VideoDetailFragment) fragment;
|
||||
detailFragment.setAutoplay(autoPlay);
|
||||
detailFragment.selectAndLoadVideo(serviceId, url, title);
|
||||
return;
|
||||
}
|
||||
|
||||
VideoDetailFragment instance = VideoDetailFragment.getInstance(serviceId, url, title);
|
||||
instance.setAutoplay(autoPlay);
|
||||
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
|
||||
.replace(R.id.fragment_holder, instance)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
}
|
||||
|
||||
private void openChannelFragment(int serviceId, String url, String name) {
|
||||
ImageLoader.getInstance().clearMemoryCache();
|
||||
if (name == null) name = "";
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
|
||||
.replace(R.id.fragment_holder, ChannelFragment.newInstance(serviceId, url, name))
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
}
|
||||
|
||||
private void handleVideoDetailIntent(int serviceId, String url, Intent intent) {
|
||||
boolean autoPlay = intent.getBooleanExtra(VideoDetailFragment.AUTO_PLAY, false);
|
||||
String title = intent.getStringExtra(Constants.KEY_TITLE);
|
||||
openVideoDetailFragment(serviceId, url, title, autoPlay);
|
||||
}
|
||||
|
||||
private void handleChannelIntent(int serviceId, String url, Intent intent) {
|
||||
String name = intent.getStringExtra(Constants.KEY_TITLE);
|
||||
openChannelFragment(serviceId, url, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
124
app/src/main/java/org/schabi/newpipe/RouterActivity.java
Normal file
124
app/src/main/java/org/schabi/newpipe/RouterActivity.java
Normal file
@@ -0,0 +1,124 @@
|
||||
package org.schabi.newpipe;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
/*
|
||||
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
|
||||
* RouterActivity .java is part of NewPipe.
|
||||
*
|
||||
* OpenHitboxStreams 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.
|
||||
*
|
||||
* OpenHitboxStreams 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 OpenHitboxStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This Acitivty is designed to route share/open intents to the specified service, and
|
||||
* to the part of the service which can handle the url.
|
||||
*/
|
||||
public class RouterActivity extends Activity {
|
||||
//private static final String TAG = "RouterActivity"
|
||||
|
||||
/**
|
||||
* Removes invisible separators (\p{Z}) and punctuation characters including
|
||||
* brackets (\p{P}). See http://www.regular-expressions.info/unicode.html for
|
||||
* more details.
|
||||
*/
|
||||
private final static String REGEX_REMOVE_FROM_URL = "[\\p{Z}\\p{P}]";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
handleIntent(getIntent());
|
||||
finish();
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
String videoUrl = "";
|
||||
|
||||
// first gather data and find service
|
||||
if (intent.getData() != null) {
|
||||
// this means the video was called though another app
|
||||
videoUrl = intent.getData().toString();
|
||||
} else if (intent.getStringExtra(Intent.EXTRA_TEXT) != null) {
|
||||
//this means that vidoe was called through share menu
|
||||
String extraText = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||
videoUrl = getUris(extraText)[0];
|
||||
}
|
||||
|
||||
try {
|
||||
NavigationHelper.openByLink(this, videoUrl);
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private static String removeHeadingGibberish(final String input) {
|
||||
int start = 0;
|
||||
for (int i = input.indexOf("://") - 1; i >= 0; i--) {
|
||||
if (!input.substring(i, i + 1).matches("\\p{L}")) {
|
||||
start = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return input.substring(start, input.length());
|
||||
}
|
||||
|
||||
private static String trim(final String input) {
|
||||
if (input == null || input.length() < 1) {
|
||||
return input;
|
||||
} else {
|
||||
String output = input;
|
||||
while (output.length() > 0 && output.substring(0, 1).matches(REGEX_REMOVE_FROM_URL)) {
|
||||
output = output.substring(1);
|
||||
}
|
||||
while (output.length() > 0
|
||||
&& output.substring(output.length() - 1, output.length()).matches(REGEX_REMOVE_FROM_URL)) {
|
||||
output = output.substring(0, output.length() - 1);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all Strings which look remotely like URLs from a text.
|
||||
* Used if NewPipe was called through share menu.
|
||||
*
|
||||
* @param sharedText text to scan for URLs.
|
||||
* @return potential URLs
|
||||
*/
|
||||
private String[] getUris(final String sharedText) {
|
||||
final Collection<String> result = new HashSet<>();
|
||||
if (sharedText != null) {
|
||||
final String[] array = sharedText.split("\\p{Space}");
|
||||
for (String s : array) {
|
||||
s = trim(s);
|
||||
if (s.length() != 0) {
|
||||
if (s.matches(".+://.+")) {
|
||||
result.add(removeHeadingGibberish(s));
|
||||
} else if (s.matches(".+\\..+")) {
|
||||
result.add("http://" + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toArray(new String[result.size()]);
|
||||
}
|
||||
|
||||
}
|
130
app/src/main/java/org/schabi/newpipe/RouterPopupActivity.java
Normal file
130
app/src/main/java/org/schabi/newpipe/RouterPopupActivity.java
Normal file
@@ -0,0 +1,130 @@
|
||||
package org.schabi.newpipe;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.player.PopupVideoPlayer;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* This activity is thought to open video streams form an external app using the popup player.
|
||||
*/
|
||||
public class RouterPopupActivity extends Activity {
|
||||
//private static final String TAG = "RouterPopupActivity";
|
||||
|
||||
/**
|
||||
* Removes invisible separators (\p{Z}) and punctuation characters including
|
||||
* brackets (\p{P}). See http://www.regular-expressions.info/unicode.html for
|
||||
* more details.
|
||||
*/
|
||||
private final static String REGEX_REMOVE_FROM_URL = "[\\p{Z}\\p{P}]";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
handleIntent(getIntent());
|
||||
finish();
|
||||
}
|
||||
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||
&& !PermissionHelper.checkSystemAlertWindowPermission(this)) {
|
||||
Toast.makeText(this, R.string.msg_popup_permission, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
String videoUrl = "";
|
||||
StreamingService service;
|
||||
|
||||
// first gather data and find service
|
||||
if (intent.getData() != null) {
|
||||
// this means the video was called though another app
|
||||
videoUrl = intent.getData().toString();
|
||||
} else if (intent.getStringExtra(Intent.EXTRA_TEXT) != null) {
|
||||
//this means that vidoe was called through share menu
|
||||
String extraText = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||
videoUrl = getUris(extraText)[0];
|
||||
}
|
||||
|
||||
service = NewPipe.getServiceByUrl(videoUrl);
|
||||
if (service == null) {
|
||||
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
Intent callIntent = new Intent(this, PopupVideoPlayer.class);
|
||||
switch (service.getLinkTypeByUrl(videoUrl)) {
|
||||
case STREAM:
|
||||
break;
|
||||
default:
|
||||
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
callIntent.putExtra(Constants.KEY_URL, videoUrl);
|
||||
callIntent.putExtra(Constants.KEY_SERVICE_ID, service.getServiceId());
|
||||
startService(callIntent);
|
||||
}
|
||||
|
||||
private static String removeHeadingGibberish(final String input) {
|
||||
int start = 0;
|
||||
for (int i = input.indexOf("://") - 1; i >= 0; i--) {
|
||||
if (!input.substring(i, i + 1).matches("\\p{L}")) {
|
||||
start = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return input.substring(start, input.length());
|
||||
}
|
||||
|
||||
private static String trim(final String input) {
|
||||
if (input == null || input.length() < 1) {
|
||||
return input;
|
||||
} else {
|
||||
String output = input;
|
||||
while (output.length() > 0 && output.substring(0, 1).matches(REGEX_REMOVE_FROM_URL)) {
|
||||
output = output.substring(1);
|
||||
}
|
||||
while (output.length() > 0
|
||||
&& output.substring(output.length() - 1, output.length()).matches(REGEX_REMOVE_FROM_URL)) {
|
||||
output = output.substring(0, output.length() - 1);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all Strings which look remotely like URLs from a text.
|
||||
* Used if NewPipe was called through share menu.
|
||||
*
|
||||
* @param sharedText text to scan for URLs.
|
||||
* @return potential URLs
|
||||
*/
|
||||
private String[] getUris(final String sharedText) {
|
||||
final Collection<String> result = new HashSet<>();
|
||||
if (sharedText != null) {
|
||||
final String[] array = sharedText.split("\\p{Space}");
|
||||
for (String s : array) {
|
||||
s = trim(s);
|
||||
if (s.length() != 0) {
|
||||
if (s.matches(".+://.+")) {
|
||||
result.add(removeHeadingGibberish(s));
|
||||
} else if (s.matches(".+\\..+")) {
|
||||
result.add("http://" + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toArray(new String[result.size()]);
|
||||
}
|
||||
|
||||
}
|
@@ -1,230 +0,0 @@
|
||||
package org.schabi.newpipe.detail;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamExtractor;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 02.08.16.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* StreamInfoWorker.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 StreamInfoWorker {
|
||||
|
||||
private static final String TAG = StreamInfoWorker.class.toString();
|
||||
|
||||
public interface OnStreamInfoReceivedListener {
|
||||
void onReceive(StreamInfo info);
|
||||
void onError(int messageId);
|
||||
void onReCaptchaException();
|
||||
void onBlockedByGemaError();
|
||||
void onContentErrorWithMessage(int messageId);
|
||||
void onContentError();
|
||||
}
|
||||
|
||||
private class StreamExtractorRunnable implements Runnable {
|
||||
private final Handler h = new Handler();
|
||||
private StreamExtractor streamExtractor;
|
||||
private final int serviceId;
|
||||
private final String videoUrl;
|
||||
private Activity a;
|
||||
|
||||
public StreamExtractorRunnable(Activity a, String videoUrl, int serviceId) {
|
||||
this.serviceId = serviceId;
|
||||
this.videoUrl = videoUrl;
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
StreamInfo streamInfo = null;
|
||||
StreamingService service = null;
|
||||
try {
|
||||
service = NewPipe.getService(serviceId);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorActivity.reportError(h, a, e, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
"", videoUrl, R.string.could_not_get_stream));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
streamExtractor = service.getExtractorInstance(videoUrl);
|
||||
streamInfo = StreamInfo.getVideoInfo(streamExtractor);
|
||||
|
||||
final StreamInfo info = streamInfo;
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onStreamInfoReceivedListener.onReceive(info);
|
||||
}
|
||||
});
|
||||
|
||||
// look for errors during extraction
|
||||
// this if statement only covers extra information.
|
||||
// if these are not available or caused an error, they are just not available
|
||||
// but don't render the stream information unusalbe.
|
||||
if(streamInfo != null &&
|
||||
!streamInfo.errors.isEmpty()) {
|
||||
Log.e(TAG, "OCCURRED ERRORS DURING EXTRACTION:");
|
||||
for (Throwable e : streamInfo.errors) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "------");
|
||||
}
|
||||
|
||||
View rootView = a != null ? a.findViewById(R.id.video_item_detail) : null;
|
||||
ErrorActivity.reportError(h, a,
|
||||
streamInfo.errors, null, rootView,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, 0 /* no message for the user */));
|
||||
}
|
||||
|
||||
// These errors render the stream information unusable.
|
||||
} catch (ReCaptchaException e) {
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onStreamInfoReceivedListener.onReCaptchaException();
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onStreamInfoReceivedListener.onError(R.string.network_error);
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
} catch (YoutubeStreamExtractor.DecryptException de) {
|
||||
// custom service related exceptions
|
||||
ErrorActivity.reportError(h, a, de, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.youtube_signature_decryption_error));
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
a.finish();
|
||||
}
|
||||
});
|
||||
de.printStackTrace();
|
||||
} catch (YoutubeStreamExtractor.GemaException ge) {
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onStreamInfoReceivedListener.onBlockedByGemaError();
|
||||
}
|
||||
});
|
||||
} catch(YoutubeStreamExtractor.LiveStreamException e) {
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onStreamInfoReceivedListener
|
||||
.onContentErrorWithMessage(R.string.live_streams_not_supported);
|
||||
}
|
||||
});
|
||||
}
|
||||
// ----------------------------------------
|
||||
catch(StreamExtractor.ContentNotAvailableException e) {
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onStreamInfoReceivedListener
|
||||
.onContentError();
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
} catch(StreamInfo.StreamExctractException e) {
|
||||
if(!streamInfo.errors.isEmpty()) {
|
||||
// !!! if this case ever kicks in someone gets kicked out !!!
|
||||
ErrorActivity.reportError(h, a, e, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.could_not_get_stream));
|
||||
} else {
|
||||
ErrorActivity.reportError(h, a, streamInfo.errors, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.could_not_get_stream));
|
||||
}
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
a.finish();
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
} catch (ParsingException e) {
|
||||
ErrorActivity.reportError(h, a, e, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.parsing_error));
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
a.finish();
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
} catch(Exception e) {
|
||||
ErrorActivity.reportError(h, a, e, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.general_error));
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
a.finish();
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static StreamInfoWorker streamInfoWorker = null;
|
||||
private StreamExtractorRunnable runnable = null;
|
||||
private OnStreamInfoReceivedListener onStreamInfoReceivedListener = null;
|
||||
|
||||
private StreamInfoWorker() {
|
||||
|
||||
}
|
||||
|
||||
public static StreamInfoWorker getInstance() {
|
||||
return streamInfoWorker == null ? (streamInfoWorker = new StreamInfoWorker()) : streamInfoWorker;
|
||||
}
|
||||
|
||||
public void search(int serviceId, String url, Activity a) {
|
||||
runnable = new StreamExtractorRunnable(a, url, serviceId);
|
||||
Thread thread = new Thread(runnable);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void setOnStreamInfoReceivedListener(
|
||||
OnStreamInfoReceivedListener onStreamInfoReceivedListener) {
|
||||
this.onStreamInfoReceivedListener = onStreamInfoReceivedListener;
|
||||
}
|
||||
}
|
@@ -1,253 +0,0 @@
|
||||
package org.schabi.newpipe.detail;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.ThemableActivity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.util.NavStack;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
|
||||
/**
|
||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||
* VideoItemDetailActivity.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 VideoItemDetailActivity extends ThemableActivity {
|
||||
|
||||
/**
|
||||
* Removes invisible separators (\p{Z}) and punctuation characters including
|
||||
* brackets (\p{P}). See http://www.regular-expressions.info/unicode.html for
|
||||
* more details.
|
||||
*/
|
||||
private final static String REGEX_REMOVE_FROM_URL = "[\\p{Z}\\p{P}]";
|
||||
|
||||
private static final String TAG = VideoItemDetailActivity.class.toString();
|
||||
|
||||
private VideoItemDetailFragment fragment;
|
||||
|
||||
private String videoUrl;
|
||||
private int currentStreamingService = -1;
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_videoitem_detail);
|
||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
// Show the Up button in the action bar.
|
||||
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
|
||||
// (e.g. when rotating the screen from portrait to landscape).
|
||||
// In this case, the fragment will automatically be re-added
|
||||
// to its container so we don't need to manually add it.
|
||||
// For more information, see the Fragments API guide at:
|
||||
//
|
||||
// http://developer.android.com/guide/components/fragments.html
|
||||
//
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
handleIntent(getIntent());
|
||||
} else {
|
||||
videoUrl = savedInstanceState.getString(NavStack.URL);
|
||||
currentStreamingService = savedInstanceState.getInt(NavStack.SERVICE_ID);
|
||||
NavStack.getInstance()
|
||||
.restoreSavedInstanceState(savedInstanceState);
|
||||
addFragment(savedInstanceState);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
handleIntent(intent);
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
Bundle arguments = new Bundle();
|
||||
boolean autoplay = false;
|
||||
if (intent.getData() != null) {
|
||||
// this means the video was called though another app
|
||||
videoUrl = intent.getData().toString();
|
||||
currentStreamingService = getServiceIdByUrl(videoUrl);
|
||||
if(currentStreamingService == -1) {
|
||||
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
autoplay = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.getBoolean(getString(R.string.autoplay_through_intent_key), false);
|
||||
} else if(intent.getStringExtra(Intent.EXTRA_TEXT) != null) {
|
||||
//this means that vidoe was called through share menu
|
||||
String extraText = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||
videoUrl = getUris(extraText)[0];
|
||||
currentStreamingService = getServiceIdByUrl(videoUrl);
|
||||
} else {
|
||||
//this is if the video was called through another NewPipe activity
|
||||
videoUrl = intent.getStringExtra(NavStack.URL);
|
||||
currentStreamingService = intent.getIntExtra(NavStack.SERVICE_ID, -1);
|
||||
}
|
||||
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY, autoplay);
|
||||
arguments.putString(NavStack.URL, videoUrl);
|
||||
arguments.putInt(NavStack.SERVICE_ID, currentStreamingService);
|
||||
addFragment(arguments);
|
||||
}
|
||||
|
||||
private void addFragment(final Bundle arguments) {
|
||||
// Create the detail fragment and add it to the activity
|
||||
// using a fragment transaction.
|
||||
fragment = new VideoItemDetailFragment();
|
||||
fragment.setArguments(arguments);
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.videoitem_detail_container, fragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
App.checkStartTor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString(NavStack.URL, videoUrl);
|
||||
outState.putInt(NavStack.SERVICE_ID, currentStreamingService);
|
||||
outState.putBoolean(VideoItemDetailFragment.AUTO_PLAY, false);
|
||||
NavStack.getInstance()
|
||||
.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
super.onOptionsItemSelected(item);
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
// This ID represents the Home or Up button. In the case of this
|
||||
// activity, the Up button is shown. Use NavUtils to allow users
|
||||
// to navigate up one level in the application structure. For
|
||||
// more details, see the Navigation pattern on Android Design:
|
||||
|
||||
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
|
||||
|
||||
NavStack.getInstance()
|
||||
.openMainActivity(this);
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
try {
|
||||
NavStack.getInstance()
|
||||
.navBack(this);
|
||||
} catch (Exception e) {
|
||||
ErrorActivity.reportUiError(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all Strings which look remotely like URLs from a text.
|
||||
* Used if NewPipe was called through share menu.
|
||||
*
|
||||
* @param sharedText text to scan for URLs.
|
||||
* @return potential URLs
|
||||
*/
|
||||
private String[] getUris(final String sharedText) {
|
||||
final Collection<String> result = new HashSet<>();
|
||||
if (sharedText != null) {
|
||||
final String[] array = sharedText.split("\\p{Space}");
|
||||
for (String s : array) {
|
||||
s = trim(s);
|
||||
if (s.length() != 0) {
|
||||
if (s.matches(".+://.+")) {
|
||||
result.add(removeHeadingGibberish(s));
|
||||
} else if (s.matches(".+\\..+")) {
|
||||
result.add("http://" + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toArray(new String[result.size()]);
|
||||
}
|
||||
|
||||
private static String removeHeadingGibberish(final String input) {
|
||||
int start = 0;
|
||||
for (int i = input.indexOf("://") - 1; i >= 0; i--) {
|
||||
if (!input.substring(i, i + 1).matches("\\p{L}")) {
|
||||
start = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return input.substring(start, input.length());
|
||||
}
|
||||
|
||||
private static String trim(final String input) {
|
||||
if (input == null || input.length() < 1) {
|
||||
return input;
|
||||
} else {
|
||||
String output = input;
|
||||
while (output.length() > 0 && output.substring(0, 1).matches(REGEX_REMOVE_FROM_URL)) {
|
||||
output = output.substring(1);
|
||||
}
|
||||
while (output.length() > 0
|
||||
&& output.substring(output.length() - 1, output.length()).matches(REGEX_REMOVE_FROM_URL)) {
|
||||
output = output.substring(0, output.length() - 1);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
private int getServiceIdByUrl(String url) {
|
||||
StreamingService[] serviceList = NewPipe.getServices();
|
||||
int service = -1;
|
||||
for (int i = 0; i < serviceList.length; i++) {
|
||||
if (serviceList[i].getStreamUrlIdHandlerInstance().acceptUrl(videoUrl)) {
|
||||
service = i;
|
||||
//videoExtractor = ServiceList.getService(i).getExtractorInstance();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return service;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -3,18 +3,15 @@ package org.schabi.newpipe.download;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
@@ -28,32 +25,28 @@ import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.schabi.newpipe.ThemableActivity;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.settings.NewPipeSettings;
|
||||
import org.schabi.newpipe.settings.SettingsActivity;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Vector;
|
||||
|
||||
import us.shandian.giga.get.DownloadManager;
|
||||
import us.shandian.giga.service.DownloadManagerService;
|
||||
import us.shandian.giga.ui.fragment.AllMissionsFragment;
|
||||
import us.shandian.giga.ui.fragment.MissionsFragment;
|
||||
import us.shandian.giga.util.CrashHandler;
|
||||
import us.shandian.giga.util.Utility;
|
||||
|
||||
public class DownloadActivity extends ThemableActivity implements AdapterView.OnItemClickListener{
|
||||
public class DownloadActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
|
||||
|
||||
public static final String INTENT_DOWNLOAD = "us.shandian.giga.intent.DOWNLOAD";
|
||||
|
||||
public static final String INTENT_LIST = "us.shandian.giga.intent.LIST";
|
||||
|
||||
private static final String TAG = DownloadActivity.class.toString();
|
||||
public static final String THREADS = "threads";
|
||||
|
||||
|
||||
private static final String TAG = DownloadActivity.class.toString();
|
||||
private MissionsFragment mFragment;
|
||||
|
||||
|
||||
@@ -72,9 +65,9 @@ public class DownloadActivity extends ThemableActivity implements AdapterView.On
|
||||
startService(i);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
ThemeHelper.setTheme(this, true);
|
||||
setContentView(R.layout.activity_downloader);
|
||||
|
||||
|
||||
//noinspection ConstantConditions
|
||||
|
||||
// its ok if this fails, we will catch that error later, and send it as report
|
||||
|
1
app/src/main/java/org/schabi/newpipe/extractor
Submodule
1
app/src/main/java/org/schabi/newpipe/extractor
Submodule
Submodule app/src/main/java/org/schabi/newpipe/extractor added at b587d175bb
@@ -1,41 +0,0 @@
|
||||
package org.schabi.newpipe.extractor;
|
||||
|
||||
/**
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* AbstractStreamInfo.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/>.
|
||||
*/
|
||||
|
||||
/**Common properties between StreamInfo and StreamInfoItem.*/
|
||||
public abstract class AbstractStreamInfo {
|
||||
public enum StreamType {
|
||||
NONE, // placeholder to check if stream type was checked or not
|
||||
VIDEO_STREAM,
|
||||
AUDIO_STREAM,
|
||||
LIVE_STREAM,
|
||||
AUDIO_LIVE_STREAM,
|
||||
FILE
|
||||
}
|
||||
|
||||
public StreamType stream_type;
|
||||
public int service_id = -1;
|
||||
public String id = "";
|
||||
public String title = "";
|
||||
public String uploader = "";
|
||||
public String thumbnail_url = "";
|
||||
public String webpage_url = "";
|
||||
public String upload_date = "";
|
||||
public long view_count = -1;
|
||||
}
|
@@ -1,113 +0,0 @@
|
||||
package org.schabi.newpipe.extractor;
|
||||
|
||||
import android.util.Xml;
|
||||
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||
import org.schabi.newpipe.extractor.stream_info.AudioStream;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 02.02.16.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* DashMpdParser.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 DashMpdParser {
|
||||
|
||||
private DashMpdParser() {
|
||||
}
|
||||
|
||||
static class DashMpdParsingException extends ParsingException {
|
||||
DashMpdParsingException(String message, Exception e) {
|
||||
super(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<AudioStream> getAudioStreams(String dashManifestUrl)
|
||||
throws DashMpdParsingException, ReCaptchaException {
|
||||
String dashDoc;
|
||||
Downloader downloader = NewPipe.getDownloader();
|
||||
try {
|
||||
dashDoc = downloader.download(dashManifestUrl);
|
||||
} catch(IOException ioe) {
|
||||
throw new DashMpdParsingException("Could not get dash mpd: " + dashManifestUrl, ioe);
|
||||
} catch (ReCaptchaException e) {
|
||||
throw new ReCaptchaException("reCaptcha Challenge needed");
|
||||
}
|
||||
Vector<AudioStream> audioStreams = new Vector<>();
|
||||
try {
|
||||
XmlPullParser parser = Xml.newPullParser();
|
||||
parser.setInput(new StringReader(dashDoc));
|
||||
String tagName = "";
|
||||
String currentMimeType = "";
|
||||
int currentBandwidth = -1;
|
||||
int currentSamplingRate = -1;
|
||||
boolean currentTagIsBaseUrl = false;
|
||||
for(int eventType = parser.getEventType();
|
||||
eventType != XmlPullParser.END_DOCUMENT;
|
||||
eventType = parser.next() ) {
|
||||
switch(eventType) {
|
||||
case XmlPullParser.START_TAG:
|
||||
tagName = parser.getName();
|
||||
if(tagName.equals("AdaptationSet")) {
|
||||
currentMimeType = parser.getAttributeValue(XmlPullParser.NO_NAMESPACE, "mimeType");
|
||||
} else if(tagName.equals("Representation") && currentMimeType.contains("audio")) {
|
||||
currentBandwidth = Integer.parseInt(
|
||||
parser.getAttributeValue(XmlPullParser.NO_NAMESPACE, "bandwidth"));
|
||||
currentSamplingRate = Integer.parseInt(
|
||||
parser.getAttributeValue(XmlPullParser.NO_NAMESPACE, "audioSamplingRate"));
|
||||
} else if(tagName.equals("BaseURL")) {
|
||||
currentTagIsBaseUrl = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case XmlPullParser.TEXT:
|
||||
// actual stream tag
|
||||
if(currentTagIsBaseUrl &&
|
||||
(currentMimeType.contains("audio"))) {
|
||||
int format = -1;
|
||||
if(currentMimeType.equals(MediaFormat.WEBMA.mimeType)) {
|
||||
format = MediaFormat.WEBMA.id;
|
||||
} else if(currentMimeType.equals(MediaFormat.M4A.mimeType)) {
|
||||
format = MediaFormat.M4A.id;
|
||||
}
|
||||
audioStreams.add(new AudioStream(parser.getText(),
|
||||
format, currentBandwidth, currentSamplingRate));
|
||||
}
|
||||
break;
|
||||
|
||||
case XmlPullParser.END_TAG:
|
||||
if(tagName.equals("AdaptationSet")) {
|
||||
currentMimeType = "";
|
||||
} else if(tagName.equals("BaseURL")) {
|
||||
currentTagIsBaseUrl = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
throw new DashMpdParsingException("Could not parse Dash mpd", e);
|
||||
}
|
||||
return audioStreams;
|
||||
}
|
||||
}
|
@@ -1,52 +0,0 @@
|
||||
package org.schabi.newpipe.extractor;
|
||||
|
||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 28.01.16.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* Downloader.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 interface Downloader {
|
||||
|
||||
/**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
|
||||
* @throws IOException*/
|
||||
String download(String siteUrl, String language) throws IOException, ReCaptchaException;
|
||||
|
||||
/**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 customProperties set request header properties
|
||||
* @return the contents of the specified text file
|
||||
* @throws IOException*/
|
||||
String download(String siteUrl, Map<String, String> customProperties) throws IOException, ReCaptchaException;
|
||||
|
||||
/**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
|
||||
* @throws IOException*/
|
||||
String download(String siteUrl) throws IOException, ReCaptchaException;
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
package org.schabi.newpipe.extractor;
|
||||
|
||||
/**
|
||||
* Created by the-scrabi on 11.02.17.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
|
||||
* InfoItem.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 interface InfoItem {
|
||||
public enum InfoType {
|
||||
STREAM,
|
||||
PLAYLIST,
|
||||
CHANNEL
|
||||
}
|
||||
|
||||
InfoType infoType();
|
||||
String getTitle();
|
||||
String getLink();
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
package org.schabi.newpipe.extractor;
|
||||
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 12.02.17.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
|
||||
* InfoItemCollector.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 InfoItemCollector {
|
||||
private List<InfoItem> itemList = new Vector<>();
|
||||
private List<Throwable> errors = new Vector<>();
|
||||
private int serviceId = -1;
|
||||
|
||||
public InfoItemCollector(int serviceId) {
|
||||
this.serviceId = serviceId;
|
||||
}
|
||||
|
||||
public List<InfoItem> getItemList() {
|
||||
return itemList;
|
||||
}
|
||||
public List<Throwable> getErrors() {
|
||||
return errors;
|
||||
}
|
||||
protected void addFromCollector(InfoItemCollector otherC) throws ExtractionException {
|
||||
if(serviceId != otherC.serviceId) {
|
||||
throw new ExtractionException("Service Id does not equal: "
|
||||
+ NewPipe.getNameOfService(serviceId)
|
||||
+ " and " + NewPipe.getNameOfService(otherC.serviceId));
|
||||
}
|
||||
errors.addAll(otherC.errors);
|
||||
itemList.addAll(otherC.itemList);
|
||||
}
|
||||
protected void addError(Exception e) {
|
||||
errors.add(e);
|
||||
}
|
||||
protected void addItem(InfoItem item) {
|
||||
itemList.add(item);
|
||||
}
|
||||
protected int getServiceId() {
|
||||
return serviceId;
|
||||
}
|
||||
}
|
@@ -1,83 +0,0 @@
|
||||
package org.schabi.newpipe.extractor;
|
||||
|
||||
/**
|
||||
* Created by Adam Howard on 08/11/15.
|
||||
*
|
||||
* Copyright (c) Christian Schabesberger <chris.schabesberger@mailbox.org>
|
||||
* and Adam Howard <achdisposable1@gmail.com> 2015
|
||||
*
|
||||
* MediaFormat.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/>.
|
||||
*/
|
||||
|
||||
/**Static data about various media formats support by Newpipe, eg mime type, extension*/
|
||||
|
||||
public enum MediaFormat {
|
||||
//video and audio combined formats
|
||||
// id name suffix mime type
|
||||
MPEG_4 (0x0, "MPEG-4", "mp4", "video/mp4"),
|
||||
v3GPP (0x1, "3GPP", "3gp", "video/3gpp"),
|
||||
WEBM (0x2, "WebM", "webm", "video/webm"),
|
||||
// audio formats
|
||||
M4A (0x3, "m4a", "m4a", "audio/mp4"),
|
||||
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;
|
||||
|
||||
MediaFormat(int id, String name, String suffix, String mimeType) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.suffix = suffix;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
@@ -1,88 +0,0 @@
|
||||
package org.schabi.newpipe.extractor;
|
||||
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeService;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 23.08.15.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||
* NewPipe.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/>.
|
||||
*/
|
||||
|
||||
/**Provides access to the video streaming services supported by NewPipe.
|
||||
* Currently only Youtube until the API becomes more stable.*/
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
public class NewPipe {
|
||||
|
||||
private NewPipe() {
|
||||
}
|
||||
|
||||
private static final String TAG = NewPipe.class.toString();
|
||||
|
||||
|
||||
private static Downloader downloader = null;
|
||||
|
||||
public static StreamingService[] getServices() {
|
||||
return ServiceList.serviceList;
|
||||
}
|
||||
public static StreamingService getService(int serviceId)throws ExtractionException {
|
||||
for(StreamingService s : ServiceList.serviceList) {
|
||||
if(s.getServiceId() == serviceId) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static StreamingService getService(String serviceName) throws ExtractionException {
|
||||
return ServiceList.serviceList[getIdOfService(serviceName)];
|
||||
}
|
||||
public static String getNameOfService(int id) {
|
||||
try {
|
||||
return getService(id).getServiceInfo().name;
|
||||
} catch (Exception e) {
|
||||
System.err.println("Service id not known");
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
public static int getIdOfService(String serviceName) {
|
||||
for(int i = 0; i < ServiceList.serviceList.length; i++) {
|
||||
if(ServiceList.serviceList[i].getServiceInfo().name.equals(serviceName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void init(Downloader d) {
|
||||
downloader = d;
|
||||
}
|
||||
|
||||
public static Downloader getDownloader() {
|
||||
return downloader;
|
||||
}
|
||||
|
||||
public static StreamingService getServiceByUrl(String url) {
|
||||
for(StreamingService s : ServiceList.serviceList) {
|
||||
if(s.getLinkTypeByUrl(url) != StreamingService.LinkType.NONE) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -1,77 +0,0 @@
|
||||
package org.schabi.newpipe.extractor;
|
||||
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 02.02.16.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* Parser.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/>.
|
||||
*/
|
||||
|
||||
/** avoid using regex !!! */
|
||||
public class Parser {
|
||||
|
||||
private Parser() {
|
||||
}
|
||||
|
||||
public static class RegexException extends ParsingException {
|
||||
public RegexException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static String matchGroup1(String pattern, String input) throws RegexException {
|
||||
return matchGroup(pattern, input, 1);
|
||||
}
|
||||
|
||||
public static String matchGroup(String pattern, String input, int group) throws RegexException {
|
||||
Pattern pat = Pattern.compile(pattern);
|
||||
Matcher mat = pat.matcher(input);
|
||||
boolean foundMatch = mat.find();
|
||||
if (foundMatch) {
|
||||
return mat.group(group);
|
||||
}
|
||||
else {
|
||||
//Log.e(TAG, "failed to find pattern \""+pattern+"\" inside of \""+input+"\"");
|
||||
if(input.length() > 1024) {
|
||||
throw new RegexException("failed to find pattern \""+pattern);
|
||||
} else {
|
||||
throw new RegexException("failed to find pattern \"" + pattern + " inside of " + input + "\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, String> compatParseMap(final String input) throws UnsupportedEncodingException {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
for(String arg : input.split("&")) {
|
||||
String[] splitArg = arg.split("=");
|
||||
if(splitArg.length > 1) {
|
||||
map.put(splitArg[0], URLDecoder.decode(splitArg[1], "UTF-8"));
|
||||
} else {
|
||||
map.put(splitArg[0], "");
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
package org.schabi.newpipe.extractor;
|
||||
|
||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeService;
|
||||
|
||||
/**
|
||||
* Created by the-scrabi on 18.02.17.
|
||||
*/
|
||||
|
||||
class ServiceList {
|
||||
public static final StreamingService[] serviceList = {
|
||||
new YoutubeService(0)
|
||||
};
|
||||
}
|
@@ -1,78 +0,0 @@
|
||||
package org.schabi.newpipe.extractor;
|
||||
|
||||
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.extractor.search.SearchEngine;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamExtractor;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 23.08.15.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* StreamingService.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 abstract class StreamingService {
|
||||
public class ServiceInfo {
|
||||
public String name = "";
|
||||
}
|
||||
|
||||
public enum LinkType {
|
||||
NONE,
|
||||
STREAM,
|
||||
CHANNEL,
|
||||
PLAYLIST
|
||||
}
|
||||
|
||||
private int serviceId;
|
||||
|
||||
public StreamingService(int id) {
|
||||
serviceId = id;
|
||||
}
|
||||
|
||||
public abstract ServiceInfo getServiceInfo();
|
||||
|
||||
public abstract StreamExtractor getExtractorInstance(String url)
|
||||
throws IOException, ExtractionException;
|
||||
public abstract SearchEngine getSearchEngineInstance();
|
||||
public abstract UrlIdHandler getStreamUrlIdHandlerInstance();
|
||||
public abstract UrlIdHandler getChannelUrlIdHandlerInstance();
|
||||
public abstract ChannelExtractor getChannelExtractorInstance(String url, int page)
|
||||
throws ExtractionException, IOException;
|
||||
public abstract SuggestionExtractor getSuggestionExtractorInstance();
|
||||
|
||||
public final int getServiceId() {
|
||||
return serviceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* figure out where the link is pointing to (a channel, video, playlist, etc.)
|
||||
*/
|
||||
public final LinkType getLinkTypeByUrl(String url) {
|
||||
UrlIdHandler sH = getStreamUrlIdHandlerInstance();
|
||||
UrlIdHandler cH = getChannelUrlIdHandlerInstance();
|
||||
|
||||
if(sH.acceptUrl(url)) {
|
||||
return LinkType.STREAM;
|
||||
} else if(cH.acceptUrl(url)) {
|
||||
return LinkType.CHANNEL;
|
||||
} else {
|
||||
return LinkType.NONE;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,43 +0,0 @@
|
||||
package org.schabi.newpipe.extractor;
|
||||
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 28.09.16.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* SuggestionExtractor.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 abstract class SuggestionExtractor {
|
||||
|
||||
private int serviceId;
|
||||
|
||||
public SuggestionExtractor(int serviceId) {
|
||||
this.serviceId = serviceId;
|
||||
}
|
||||
|
||||
public abstract List<String> suggestionList(
|
||||
String query,String contentCountry)
|
||||
throws ExtractionException, IOException;
|
||||
|
||||
public int getServiceId() {
|
||||
return serviceId;
|
||||
}
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
package org.schabi.newpipe.extractor;
|
||||
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 26.07.16.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* UrlIdHandler.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 interface UrlIdHandler {
|
||||
|
||||
String getUrl(String videoId);
|
||||
String getId(String siteUrl) throws ParsingException;
|
||||
String cleanUrl(String siteUrl) throws ParsingException;
|
||||
|
||||
/**When a VIEW_ACTION is caught this function will test if the url delivered within the calling
|
||||
Intent was meant to be watched with this Service.
|
||||
Return false if this service shall not allow to be called through ACTIONs.*/
|
||||
boolean acceptUrl(String videoUrl);
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
package org.schabi.newpipe.extractor.channel;
|
||||
|
||||
import org.schabi.newpipe.extractor.UrlIdHandler;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfoItemCollector;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 25.07.16.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* ChannelExtractor.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 abstract class ChannelExtractor {
|
||||
private int serviceId;
|
||||
private String url;
|
||||
private UrlIdHandler urlIdHandler;
|
||||
private StreamInfoItemCollector previewInfoCollector;
|
||||
private int page = -1;
|
||||
|
||||
public ChannelExtractor(UrlIdHandler urlIdHandler, String url, int page, int serviceId)
|
||||
throws ExtractionException, IOException {
|
||||
this.url = url;
|
||||
this.page = page;
|
||||
this.serviceId = serviceId;
|
||||
this.urlIdHandler = urlIdHandler;
|
||||
previewInfoCollector = new StreamInfoItemCollector(urlIdHandler, serviceId);
|
||||
}
|
||||
|
||||
public String getUrl() { return url; }
|
||||
public UrlIdHandler getUrlIdHandler() { return urlIdHandler; }
|
||||
public StreamInfoItemCollector getStreamPreviewInfoCollector() {
|
||||
return previewInfoCollector;
|
||||
}
|
||||
|
||||
public abstract String getChannelName() throws ParsingException;
|
||||
public abstract String getAvatarUrl() throws ParsingException;
|
||||
public abstract String getBannerUrl() throws ParsingException;
|
||||
public abstract String getFeedUrl() throws ParsingException;
|
||||
public abstract StreamInfoItemCollector getStreams() throws ParsingException;
|
||||
public abstract boolean hasNextPage() throws ParsingException;
|
||||
public int getServiceId() {
|
||||
return serviceId;
|
||||
}
|
||||
}
|
@@ -1,82 +0,0 @@
|
||||
package org.schabi.newpipe.extractor.channel;
|
||||
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfoItemCollector;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 31.07.16.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* ChannelInfo.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 ChannelInfo {
|
||||
|
||||
|
||||
public void addException(Exception e) {
|
||||
errors.add(e);
|
||||
}
|
||||
|
||||
public static ChannelInfo getInfo(ChannelExtractor extractor)
|
||||
throws ParsingException {
|
||||
ChannelInfo info = new ChannelInfo();
|
||||
|
||||
// importand data
|
||||
info.service_id = extractor.getServiceId();
|
||||
info.channel_name = extractor.getChannelName();
|
||||
info.hasNextPage = extractor.hasNextPage();
|
||||
|
||||
try {
|
||||
info.avatar_url = extractor.getAvatarUrl();
|
||||
} catch (Exception e) {
|
||||
info.errors.add(e);
|
||||
}
|
||||
try {
|
||||
info.banner_url = extractor.getBannerUrl();
|
||||
} catch (Exception e) {
|
||||
info.errors.add(e);
|
||||
}
|
||||
try {
|
||||
info.feed_url = extractor.getFeedUrl();
|
||||
} catch(Exception e) {
|
||||
info.errors.add(e);
|
||||
}
|
||||
try {
|
||||
StreamInfoItemCollector c = extractor.getStreams();
|
||||
info.related_streams = c.getItemList();
|
||||
info.errors.addAll(c.getErrors());
|
||||
} catch(Exception e) {
|
||||
info.errors.add(e);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
public int service_id = -1;
|
||||
public String channel_name = "";
|
||||
public String avatar_url = "";
|
||||
public String banner_url = "";
|
||||
public String feed_url = "";
|
||||
public List<InfoItem> related_streams = null;
|
||||
public boolean hasNextPage = false;
|
||||
|
||||
public List<Throwable> errors = new Vector<>();
|
||||
}
|
@@ -1,44 +0,0 @@
|
||||
package org.schabi.newpipe.extractor.channel;
|
||||
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 11.02.17.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
|
||||
* ChannelInfoItem.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 ChannelInfoItem implements InfoItem {
|
||||
|
||||
public int serviceId = -1;
|
||||
public String channelName = "";
|
||||
public String thumbnailUrl = "";
|
||||
public String webPageUrl = "";
|
||||
public String description = "";
|
||||
public long subscriberCount = -1;
|
||||
public int videoAmount = -1;
|
||||
|
||||
public InfoType infoType() {
|
||||
return InfoType.CHANNEL;
|
||||
}
|
||||
public String getTitle() {
|
||||
return channelName;
|
||||
}
|
||||
public String getLink() {
|
||||
return webPageUrl;
|
||||
}
|
||||
}
|
@@ -1,74 +0,0 @@
|
||||
package org.schabi.newpipe.extractor.channel;
|
||||
|
||||
import org.schabi.newpipe.extractor.InfoItemCollector;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.exceptions.FoundAdException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfoItemExtractor;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 12.02.17.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
|
||||
* ChannelInfoItemCollector.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 ChannelInfoItemCollector extends InfoItemCollector {
|
||||
public ChannelInfoItemCollector(int serviceId) {
|
||||
super(serviceId);
|
||||
}
|
||||
|
||||
public ChannelInfoItem extract(ChannelInfoItemExtractor extractor) throws ParsingException {
|
||||
ChannelInfoItem resultItem = new ChannelInfoItem();
|
||||
// importand information
|
||||
resultItem.channelName = extractor.getChannelName();
|
||||
|
||||
resultItem.serviceId = getServiceId();
|
||||
resultItem.webPageUrl = extractor.getWebPageUrl();
|
||||
|
||||
// optional information
|
||||
try {
|
||||
resultItem.subscriberCount = extractor.getSubscriberCount();
|
||||
} catch (Exception e) {
|
||||
addError(e);
|
||||
}
|
||||
try {
|
||||
resultItem.videoAmount = extractor.getVideoAmount();
|
||||
} catch (Exception e) {
|
||||
addError(e);
|
||||
}
|
||||
try {
|
||||
resultItem.thumbnailUrl = extractor.getThumbnailUrl();
|
||||
} catch (Exception e) {
|
||||
addError(e);
|
||||
}
|
||||
try {
|
||||
resultItem.description = extractor.getDescription();
|
||||
} catch (Exception e) {
|
||||
addError(e);
|
||||
}
|
||||
return resultItem;
|
||||
}
|
||||
|
||||
public void commit(ChannelInfoItemExtractor extractor) throws ParsingException {
|
||||
try {
|
||||
addItem(extract(extractor));
|
||||
} catch (Exception e) {
|
||||
addError(e);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user