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

Compare commits

...

95 Commits

Author SHA1 Message Date
Christian Schabesberger
e5bf98a741 move on to version 0.9.2 2017-04-11 22:51:04 +02:00
Christian Schabesberger
06fafc247e move to version 0.9.2 of NewPipeExtractor 2017-04-11 22:49:18 +02:00
Christian Schabesberger
e8bb17b631 Merge branch 'fix-next-video' of git://github.com/mauriciocolli/NewPipe into mul 2017-04-11 22:26:41 +02:00
Freddy Morán Jr
363cd07883 Translated using Weblate (Spanish)
Currently translated at 100.0% (160 of 160 strings)
2017-04-11 18:56:03 +02:00
Mladen Pejaković
2b4a9286c4 Translated using Weblate (Serbian)
Currently translated at 99.3% (159 of 160 strings)
2017-04-11 00:46:21 +02:00
Nathan Follens
34c985026f Translated using Weblate (Dutch)
Currently translated at 100.0% (160 of 160 strings)
2017-04-10 17:40:52 +02:00
naofum
4a0aa42914 Translated using Weblate (Japanese)
Currently translated at 100.0% (160 of 160 strings)
2017-04-10 17:21:54 +02:00
Mauricio Colli
746c2a15bf Migrate to fragments and improvements
- Migrate to fragments
- Fix #487
- Don't show "Open in popup mode" to channel links
- New backstack of videos
- Change the subscribers count to format using `NumberFormat`, for example some locales use `.`  others `,`, this handles it automatically (and the old method had a bug for leading zero, e.g. 4.82.125 instead of 4.082.125)
- Add string 'subscribers' for channels with more than 1 subscriber (plural)
- Popup player chooses the default format and resolution based on the new preference (format)
- Fix taskaffinity of the router activities
- Show title before loading, as it is available from the items already loaded
2017-04-09 14:34:00 -03:00
zmni
9318bb5306 Translated using Weblate (Indonesian)
Currently translated at 100.0% (160 of 160 strings)
2017-04-09 07:39:53 +02:00
Matej U
2a10ceb74f Translated using Weblate (Slovenian)
Currently translated at 100.0% (160 of 160 strings)
2017-04-08 22:08:31 +02:00
Weblate
83f4db59e2 Merge remote-tracking branch 'origin/master' 2017-04-08 21:47:50 +02:00
Olexandr Nesterenko
9f66f759ad Translated using Weblate (Ukrainian)
Currently translated at 84.9% (135 of 159 strings)
2017-04-08 21:47:47 +02:00
Christian Schabesberger
6f015349e8 moved on to v0.9.1 2017-04-08 17:17:58 +02:00
Christian Schabesberger
a37802c2b9 add prefered video format 2017-04-08 17:17:11 +02:00
Florian
4fa3baf5e1 Translated using Weblate (French)
Currently translated at 99.3% (158 of 159 strings)
2017-04-07 12:45:03 +02:00
Oscar Hemelaar
ef8c2c81d5 Translated using Weblate (Italian)
Currently translated at 98.7% (157 of 159 strings)
2017-04-07 03:45:31 +02:00
Mladen Pejaković
8c80d8c457 Translated using Weblate (Serbian)
Currently translated at 99.3% (158 of 159 strings)
2017-04-07 00:46:25 +02:00
Matej U
1596872c54 Translated using Weblate (Slovenian)
Currently translated at 100.0% (159 of 159 strings)
2017-04-05 14:47:22 +02:00
Oscar Hemelaar
da8873fa78 Translated using Weblate (French)
Currently translated at 99.3% (158 of 159 strings)
2017-04-05 12:14:32 +02:00
Oscar Hemelaar
ecd8439b3f Translated using Weblate (French)
Currently translated at 98.1% (156 of 159 strings)

if it's for a video restart button, it's "Relancer"
2017-04-05 02:53:08 +02:00
Oscar Hemelaar
5d178532ac Translated using Weblate (French)
Currently translated at 97.4% (155 of 159 strings)
2017-04-05 02:52:24 +02:00
Oscar Hemelaar
08e40a013d Translated using Weblate (French)
Currently translated at 96.8% (154 of 159 strings)

or "OK" ?
2017-04-05 02:50:49 +02:00
Oscar Hemelaar
c136f7363c Translated using Weblate (French)
Currently translated at 96.2% (153 of 159 strings)
2017-04-05 02:50:26 +02:00
Florian
a60f10d739 Translated using Weblate (French)
Currently translated at 90.5% (144 of 159 strings)
2017-04-04 21:45:44 +02:00
naofum
ae46afcb42 Translated using Weblate (Japanese)
Currently translated at 100.0% (159 of 159 strings)
2017-04-04 16:15:27 +02:00
mueller-ma
bffb9f6800 Translated using Weblate (German)
Currently translated at 95.5% (152 of 159 strings)
2017-04-03 09:29:35 +02:00
Tobias Groza
79aa9ad04b Translated using Weblate (German)
Currently translated at 94.9% (151 of 159 strings)
2017-04-03 09:26:41 +02:00
anonymous
ff5714f04a Translated using Weblate (French)
Currently translated at 89.9% (143 of 159 strings)
2017-04-02 18:59:25 +02:00
zmni
ce499a9766 Translated using Weblate (Indonesian)
Currently translated at 100.0% (159 of 159 strings)
2017-04-02 16:49:33 +02:00
Weblate
d3bb8b7651 Merge remote-tracking branch 'origin/master' 2017-04-02 16:48:37 +02:00
Freddy Morán Jr
6d9c23c4cb Translated using Weblate (Spanish)
Currently translated at 100.0% (158 of 158 strings)
2017-04-02 16:48:36 +02:00
Nathan Follens
b95a9332a9 Translated using Weblate (Dutch)
Currently translated at 100.0% (158 of 158 strings)
2017-04-02 16:48:35 +02:00
zmni
609715eb5c Translated using Weblate (Indonesian)
Currently translated at 100.0% (158 of 158 strings)
2017-04-02 16:48:33 +02:00
Christian Schabesberger
a1266c919c Merge branch 'fix-next-video' of git://github.com/mauriciocolli/NewPipe into strfx 2017-04-02 15:56:41 +02:00
Christian Schabesberger
a1925a0302 Merge branch 'master' of github.com:theScrabi/NewPipe 2017-04-02 15:48:53 +02:00
Christian Schabesberger
a7a4c03372 update features list, and moved on to v0.9.0 2017-04-02 15:47:21 +02:00
Christian Schabesberger
37201600e0 Merge pull request #494 from mueller-ma/patch-1
Fix list in readme
2017-04-02 15:44:14 +02:00
mueller-ma
a94f40ed62 Fix list in readme 2017-04-02 14:33:52 +02:00
naofum
0b08cf8c76 Translated using Weblate (Japanese)
Currently translated at 100.0% (158 of 158 strings)
2017-04-01 13:36:04 +02:00
Mauricio Colli
33e29be7db Fix next video and refactor
- Refactor VideoItemDetailActivity, StreamExtractorWorker
- Remove redundant styles
- Change dimensions
- Nicer animation/transitions
2017-03-31 20:39:54 -03:00
Freddy Morán Jr
bd1c7851c7 Translated using Weblate (Portuguese)
Currently translated at 100.0% (158 of 158 strings)
2017-04-01 01:02:49 +02:00
Freddy Morán Jr
82faea5965 Translated using Weblate (Spanish)
Currently translated at 100.0% (158 of 158 strings)
2017-04-01 00:51:34 +02:00
Weblate
0bbbfd3217 Merge remote-tracking branch 'origin/master' 2017-04-01 00:44:52 +02:00
Freddy Morán Jr
fb578ecda8 Translated using Weblate (Spanish)
Currently translated at 100.0% (156 of 156 strings)
2017-04-01 00:44:41 +02:00
Christian Schabesberger
e804647a65 make exoplayer default player 2017-03-29 09:17:03 +02:00
Christian Schabesberger
c3c3a94593 Merge branch 'feature-popup-fullscreen' of git://github.com/mauriciocolli/NewPipe into toogle 2017-03-29 08:48:00 +02:00
Mauricio Colli
9d55569f80 Fix keep screen on 2017-03-28 09:12:03 -03:00
Christian Schabesberger
5dd8271c15 Merge pull request #489 from mauriciocolli/master
Fix travis and some clean-up
2017-03-27 23:53:04 +02:00
Mauricio Colli
7a4a54c3ea Fix travis
- Remove duplicate of AndroidManifest
- Remove some non-translatable strings from "ar" translation, and general clean-up of other
2017-03-27 16:34:37 -03:00
Mauricio Colli
7c9078a625 Fix non-commited file 2017-03-27 11:26:36 -03:00
Mauricio Colli
71ae342f52 Implement screen orientation toggle 2017-03-27 10:12:22 -03:00
Mauricio Colli
b43c56085d Implement fullscreen and quality selector
- Implement cache
- Abstract player
- Quality selector
- Fullscreen switcher
- Change some drawables
2017-03-27 01:08:16 -03:00
Christian Schabesberger
83d2ab95e0 Merge branch 'master' of github.com:TeamNewPipe/NewPipe 2017-03-26 17:29:25 +02:00
Christian Schabesberger
20a8d7372c fix broken overlay on .svg icon 2017-03-26 17:29:16 +02:00
Weblate
c36ba88db7 Merge remote-tracking branch 'origin/master' 2017-03-25 14:05:16 +01:00
Nathan Follens
4aa23023ee Translated using Weblate (Dutch)
Currently translated at 100.0% (156 of 156 strings)
2017-03-25 14:05:13 +01:00
Christian Schabesberger
8735cf931a update to new backend with playlist support 2017-03-22 20:14:56 +01:00
Weblate
2473069326 Merge remote-tracking branch 'origin/master' 2017-03-21 09:44:34 +01:00
vesp
03bab57a97 Translated using Weblate (Czech)
Currently translated at 99.3% (155 of 156 strings)
2017-03-21 09:44:32 +01:00
Christian Schabesberger
e3baf69533 fix channel rotation problem 2017-03-17 20:35:22 +01:00
Christian Schabesberger
461f747af1 add IOException 2017-03-17 20:18:44 +01:00
Christian Schabesberger
028872a7d8 Merge pull request #483 from mauriciocolli/patch-2
Fix bug when fetching unavailable content
2017-03-17 17:10:03 +01:00
Christian Schabesberger
a1483b6c55 Merge pull request #481 from mauriciocolli/patch-1
Handle embed links
2017-03-17 17:09:13 +01:00
mauriciocolli
e406ba094c Improve bug detection
- Show a message with the appropriate error (network error)
2017-03-17 12:09:20 -03:00
mauriciocolli
c100d15ba8 Fix bug when fetching unavailable content
- Fix #482
- When opening a invalid/deleted/unavailable video, the popup was just printing the error, now it shows a message to the user and exits
2017-03-17 11:50:27 -03:00
mauriciocolli
b4ea592638 Handle embed links
- Fix #480
- Add /embed/ to intent filter, as the app already handles these type of links internally
2017-03-17 00:27:59 -03:00
Sérgio Marques
16b757d9a3 Translated using Weblate (Portuguese)
Currently translated at 100.0% (156 of 156 strings)
2017-03-17 00:46:17 +01:00
Sérgio Marques
2aa801a392 Translated using Weblate (Portuguese)
Currently translated at 100.0% (156 of 156 strings)
2017-03-14 23:24:24 +01:00
Matej U
b838344526 Translated using Weblate (Slovenian)
Currently translated at 100.0% (156 of 156 strings)
2017-03-13 10:30:41 +01:00
zmni
233a3df222 Translated using Weblate (Indonesian)
Currently translated at 100.0% (156 of 156 strings)
2017-03-11 13:27:00 +01:00
naofum
da6661b1ea Translated using Weblate (Japanese)
Currently translated at 100.0% (156 of 156 strings)
2017-03-11 12:37:49 +01:00
Mladen Pejaković
c6e120fc51 Translated using Weblate (Serbian)
Currently translated at 100.0% (156 of 156 strings)
2017-03-10 23:09:42 +01:00
Marian Hanzel
c416a1254d Translated using Weblate (Slovak)
Currently translated at 100.0% (156 of 156 strings)
2017-03-10 23:07:10 +01:00
Weblate
2aa4f6ddda Merge remote-tracking branch 'origin/master' 2017-03-10 21:45:11 +01:00
Enrico Monese
129597023d Translated using Weblate (Italian)
Currently translated at 100.0% (154 of 154 strings)
2017-03-10 21:45:10 +01:00
vesp
02aed86b7e Translated using Weblate (Czech)
Currently translated at 98.7% (152 of 154 strings)
2017-03-10 21:45:10 +01:00
Tobias Groza
e44f4b5823 Translated using Weblate (German)
Currently translated at 98.7% (152 of 154 strings)
2017-03-10 21:45:08 +01:00
Christian Schabesberger
2f0c0f0fc2 Merge branch 'master' of github.com:TeamNewPipe/NewPipe 2017-03-09 16:21:36 +01:00
Christian Schabesberger
e5ce3f3007 moved on to version 0.8.12 2017-03-09 16:21:20 +01:00
Christian Schabesberger
095a2be748 change popuplayer class description 2017-03-09 16:14:49 +01:00
Christian Schabesberger
c75fe88757 Merge branch 'feature-popup' of git://github.com/mauriciocolli/NewPipe 2017-03-09 16:08:33 +01:00
Christian Schabesberger
a8ff4b0744 Fix backbutton behaviour
- close on MainActivity when back pressed
- clear NavStack on rotation
2017-03-09 16:01:09 +01:00
Christian Schabesberger
c02c511e31 Update .travis.yml
update build-tools version for travis
2017-03-09 15:41:10 +01:00
Mauricio Colli
b9550fb528 Merge remote-tracking branch 'upstream/master' into feature-popup 2017-03-09 04:49:15 -03:00
Mauricio Colli
a37d8f083a Implement popup mode
- Add icons replay, fast_forward
- Add strings
- Add menu entry
- Add as option to open link directly to popup mode
2017-03-09 04:42:40 -03:00
Mauricio Colli
abff1f537b Add ExoMedia and remove ExoPlayer
- Remove ExoPlayer files
- Added ExoMedia library
2017-03-09 01:44:00 -03:00
Enrico Monese
483fde5e42 Translated using Weblate (Italian)
Currently translated at 100.0% (154 of 154 strings)
2017-03-08 23:52:45 +01:00
Weblate
761b7ea57b Merge remote-tracking branch 'origin/master' 2017-03-07 18:45:34 +01:00
zmni
af92631a0c Translated using Weblate (Indonesian)
Currently translated at 100.0% (154 of 154 strings)
2017-03-07 18:45:29 +01:00
Christian Schabesberger
ffe832d061 update gradle verson 2017-03-07 14:14:02 +01:00
Christian Schabesberger
a08cbfcef1 Merge branch 'master' of github.com:TeamNewPipe/NewPipe 2017-03-06 15:36:13 +01:00
Christian Schabesberger
d2d6ac1bf8 add CCC slides 2017-03-06 15:36:04 +01:00
Weblate
615ffca64b Merge remote-tracking branch 'origin/master' 2017-03-05 16:35:55 +01:00
Tobias Groza
2fcf6197c5 Translated using Weblate (German)
Currently translated at 97.4% (150 of 154 strings)
2017-03-05 16:35:54 +01:00
zmni
22d31ae14f Translated using Weblate (Indonesian)
Currently translated at 100.0% (154 of 154 strings)
2017-03-05 16:35:52 +01:00
165 changed files with 6609 additions and 6802 deletions

View File

@@ -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:
- '.+'

Binary file not shown.

View File

@@ -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

View File

@@ -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 25
versionName "0.8.11"
versionCode 29
versionName "0.9.2"
}
buildTypes {
release {
@@ -32,6 +32,9 @@ android {
dependencies {
testCompile 'junit:junit:4.12'
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'
@@ -42,11 +45,8 @@ dependencies {
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'
}

View File

@@ -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"
@@ -18,22 +19,15 @@
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" />
</activity>
<activity
android:name=".player.PlayVideoActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
@@ -49,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"
@@ -103,9 +80,6 @@
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/FilePickerTheme"/>
<activity
android:name=".ChannelActivity"
android:launchMode="singleTask" />
<activity
android:name=".ReCaptchaActivity"
android:label="@string/reCaptchaActivity" />
@@ -120,7 +94,9 @@
android:resource="@xml/provider_paths" />
</provider>
<activity android:name=".RouterActivity"
<activity
android:name=".RouterActivity"
android:taskAffinity=""
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -137,6 +113,7 @@
<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 -->
@@ -175,6 +152,64 @@
<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

View File

@@ -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,

View File

@@ -1,54 +1,95 @@
/*
* 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/>.
*/
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.NavUtils;
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;
/**
* Created by Christian Schabesberger on 02.08.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* DownloadActivity.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 MainActivity extends AppCompatActivity {
private Fragment mainFragment = null;
public class MainActivity extends AppCompatActivity implements OnItemSelectedListener {
private static final String TAG = MainActivity.class.toString();
/*//////////////////////////////////////////////////////////////////////////
// Activity's LifeCycle
//////////////////////////////////////////////////////////////////////////*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(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);
@@ -63,9 +104,10 @@ public class MainActivity extends AppCompatActivity {
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: {
@@ -86,8 +128,111 @@ public class MainActivity extends AppCompatActivity {
}
}
@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);
}
}

View File

@@ -2,22 +2,15 @@ package org.schabi.newpipe;
import android.app.Activity;
import android.content.Intent;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import org.schabi.newpipe.detail.VideoItemDetailActivity;
import org.schabi.newpipe.detail.VideoItemDetailFragment;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.util.NavStack;
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.
*
@@ -40,7 +33,7 @@ import java.util.HashSet;
* to the part of the service which can handle the url.
*/
public class RouterActivity extends Activity {
private static final String TAG = RouterActivity.class.toString();
//private static final String TAG = "RouterActivity"
/**
* Removes invisible separators (\p{Z}) and punctuation characters including
@@ -56,6 +49,25 @@ public class RouterActivity extends Activity {
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;
@@ -109,50 +121,4 @@ public class RouterActivity extends Activity {
return result.toArray(new String[result.size()]);
}
private void handleIntent(Intent intent) {
String videoUrl = "";
StreamingService service = null;
// 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;
} else {
Intent callIntent = new Intent();
switch(service.getLinkTypeByUrl(videoUrl)) {
case CHANNEL:
callIntent.setClass(this, ChannelActivity.class);
break;
case STREAM:
callIntent.setClass(this, VideoItemDetailActivity.class);
callIntent.putExtra(VideoItemDetailFragment.AUTO_PLAY,
PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean(
getString(R.string.autoplay_through_intent_key), false));
break;
case PLAYLIST:
Log.e(TAG, "NOT YET DEFINED");
break;
default:
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG)
.show();
return;
}
callIntent.putExtra(NavStack.URL, videoUrl);
callIntent.putExtra(NavStack.SERVICE_ID, service.getServiceId());
startActivity(callIntent);
}
}
}

View 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()]);
}
}

View File

@@ -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;
}
}

View File

@@ -1,155 +0,0 @@
package org.schabi.newpipe.detail;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MenuItem;
import org.schabi.newpipe.App;
import org.schabi.newpipe.R;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.NavStack;
import org.schabi.newpipe.util.ThemeHelper;
/**
* 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 AppCompatActivity {
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);
ThemeHelper.setTheme(this, true);
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;
videoUrl = intent.getStringExtra(NavStack.URL);
currentStreamingService = intent.getIntExtra(NavStack.SERVICE_ID, -1);
if(intent.hasExtra(VideoItemDetailFragment.AUTO_PLAY)) {
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY,
intent.getBooleanExtra(VideoItemDetailFragment.AUTO_PLAY, false));
}
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);
}
}
}

View File

@@ -0,0 +1,10 @@
package org.schabi.newpipe.fragments;
import org.schabi.newpipe.extractor.StreamingService;
/**
* Interface for communication purposes between activity and fragment
*/
public interface OnItemSelectedListener {
void onItemSelected(StreamingService.LinkType linkType, int serviceId, String url, String name);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,5 @@
package org.schabi.newpipe.detail;
package org.schabi.newpipe.fragments.detail;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBar;
@@ -12,9 +11,9 @@ import android.view.MenuItem;
import android.widget.ArrayAdapter;
import org.schabi.newpipe.R;
import org.schabi.newpipe.settings.SettingsActivity;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.stream_info.VideoStream;
import org.schabi.newpipe.util.Utils;
import java.util.List;
@@ -50,9 +49,10 @@ class ActionBarHandler {
private Menu menu;
// Only callbacks are listed here, there are more actions which don't need a callback.
// those are edited directly. Typically VideoItemDetailFragment will implement those callbacks.
// those are edited directly. Typically VideoDetailFragment will implement those callbacks.
private OnActionListener onShareListener;
private OnActionListener onOpenInBrowserListener;
private OnActionListener onOpenInPopupListener;
private OnActionListener onDownloadListener;
private OnActionListener onPlayWithKodiListener;
private OnActionListener onPlayAudioListener;
@@ -88,7 +88,7 @@ class ActionBarHandler {
VideoStream item = videoStreams.get(i);
itemArray[i] = MediaFormat.getNameById(item.format) + " " + item.resolution;
}
int defaultResolution = getDefaultResolution(videoStreams);
int defaultResolution = Utils.getPreferredResolution(activity, videoStreams);
ArrayAdapter<String> itemAdapter = new ArrayAdapter<>(activity.getBaseContext(),
android.R.layout.simple_spinner_dropdown_item, itemArray);
@@ -109,26 +109,6 @@ class ActionBarHandler {
}
}
private int getDefaultResolution(final List<VideoStream> videoStreams) {
if (defaultPreferences == null)
return 0;
String defaultResolution = defaultPreferences
.getString(activity.getString(R.string.default_resolution_key),
activity.getString(R.string.default_resolution_value));
for (int i = 0; i < videoStreams.size(); i++) {
VideoStream item = videoStreams.get(i);
if (defaultResolution.equals(item.resolution)) {
return i;
}
}
// this is actually an error,
// but maybe there is really no stream fitting to the default value.
return 0;
}
public void setupMenu(Menu menu, MenuInflater inflater) {
this.menu = menu;
@@ -169,11 +149,6 @@ class ActionBarHandler {
onDownloadListener.onActionSelected(selectedVideoStream);
}
return true;
case R.id.action_settings: {
Intent intent = new Intent(activity, SettingsActivity.class);
activity.startActivity(intent);
return true;
}
case R.id.action_play_with_kodi:
if(onPlayWithKodiListener != null) {
onPlayWithKodiListener.onActionSelected(selectedVideoStream);
@@ -184,10 +159,10 @@ class ActionBarHandler {
onPlayAudioListener.onActionSelected(selectedVideoStream);
}
return true;
case R.id.menu_item_downloads: {
Intent intent =
new Intent(activity, org.schabi.newpipe.download.DownloadActivity.class);
activity.startActivity(intent);
case R.id.menu_item_popup: {
if(onOpenInPopupListener != null) {
onOpenInPopupListener.onActionSelected(selectedVideoStream);
}
return true;
}
default:
@@ -208,6 +183,10 @@ class ActionBarHandler {
onOpenInBrowserListener = listener;
}
public void setOnOpenInPopupListener(OnActionListener listener) {
onOpenInPopupListener = listener;
}
public void setOnDownloadListener(OnActionListener listener) {
onDownloadListener = listener;
}

View File

@@ -0,0 +1,31 @@
package org.schabi.newpipe.fragments.detail;
import java.io.Serializable;
@SuppressWarnings("WeakerAccess")
public class StackItem implements Serializable {
private String title, url;
public StackItem(String url, String title) {
this.title = title;
this.url = url;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public String getUrl() {
return url;
}
@Override
public String toString() {
return getUrl() + " > " + getTitle();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
package org.schabi.newpipe.search_fragment;
package org.schabi.newpipe.fragments.search;
import android.support.v7.widget.SearchView;

View File

@@ -1,4 +1,4 @@
package org.schabi.newpipe.search_fragment;
package org.schabi.newpipe.fragments.search;
import android.app.Activity;
import android.content.SharedPreferences;
@@ -7,13 +7,13 @@ import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.extractor.search.SearchEngine;
import org.schabi.newpipe.extractor.search.SearchResult;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.NewPipe;
import java.io.IOException;
import java.util.EnumSet;
@@ -209,6 +209,7 @@ public class SearchWorker {
}
public void terminate() {
if (runnable == null) return;
requestId++;
runnable.terminate();
}

View File

@@ -1,4 +1,4 @@
package org.schabi.newpipe.search_fragment;
package org.schabi.newpipe.fragments.search;
import android.content.Context;
import android.database.Cursor;

View File

@@ -1,4 +1,4 @@
package org.schabi.newpipe.search_fragment;
package org.schabi.newpipe.fragments.search;
import android.app.Activity;
import android.content.SharedPreferences;
@@ -6,11 +6,11 @@ import android.os.Handler;
import android.preference.PreferenceManager;
import android.widget.Toast;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.SuggestionExtractor;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.SuggestionExtractor;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.report.ErrorActivity;
import java.io.IOException;
import java.util.List;

View File

@@ -1,11 +1,10 @@
package org.schabi.newpipe.info_list;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
@@ -39,20 +38,21 @@ import org.schabi.newpipe.extractor.stream_info.StreamInfoItem;
public class InfoItemBuilder {
final String viewsS;
final String videosS;
final String subsS;
private final String viewsS;
private final String videosS;
private final String subsS;
private final String subsPluralS;
final String thousand;
final String million;
final String billion;
private final String thousand;
private final String million;
private final String billion;
private static final String TAG = InfoItemBuilder.class.toString();
public interface OnInfoItemSelectedListener {
void selected(String url, int serviceId);
void selected(int serviceId, String url, String title);
}
private Activity activity = null;
private Context mContext = null;
private View rootView = null;
private ImageLoader imageLoader = ImageLoader.getInstance();
private DisplayImageOptions displayImageOptions =
@@ -60,15 +60,16 @@ public class InfoItemBuilder {
private OnInfoItemSelectedListener onStreamInfoItemSelectedListener;
private OnInfoItemSelectedListener onChannelInfoItemSelectedListener;
public InfoItemBuilder(Activity a, View rootView) {
activity = a;
public InfoItemBuilder(Context context, View rootView) {
mContext = context;
this.rootView = rootView;
viewsS = a.getString(R.string.views);
videosS = a.getString(R.string.videos);
subsS = a.getString(R.string.subscriber);
thousand = a.getString(R.string.short_thousand);
million = a.getString(R.string.short_million);
billion = a.getString(R.string.short_billion);
viewsS = context.getString(R.string.views);
videosS = context.getString(R.string.videos);
subsS = context.getString(R.string.subscriber);
subsPluralS = context.getString(R.string.subscriber_plural);
thousand = context.getString(R.string.short_thousand);
million = context.getString(R.string.short_million);
billion = context.getString(R.string.short_billion);
}
public void setOnStreamInfoItemSelectedListener(
@@ -156,13 +157,13 @@ public class InfoItemBuilder {
imageLoader.displayImage(info.thumbnail_url,
holder.itemThumbnailView,
displayImageOptions,
new ImageErrorLoadingListener(activity, rootView, info.service_id));
new ImageErrorLoadingListener(mContext, rootView, info.service_id));
}
holder.itemButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onStreamInfoItemSelectedListener.selected(info.webpage_url, info.service_id);
onStreamInfoItemSelectedListener.selected(info.service_id, info.webpage_url, info.getTitle());
}
});
}
@@ -178,13 +179,13 @@ public class InfoItemBuilder {
imageLoader.displayImage(info.thumbnailUrl,
holder.itemThumbnailView,
displayImageOptions,
new ImageErrorLoadingListener(activity, rootView, info.serviceId));
new ImageErrorLoadingListener(mContext, rootView, info.serviceId));
}
holder.itemButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onChannelInfoItemSelectedListener.selected(info.getLink(), info.serviceId);
onChannelInfoItemSelectedListener.selected(info.serviceId, info.getLink(), info.channelName);
}
});
}
@@ -202,15 +203,17 @@ public class InfoItemBuilder {
}
}
public String shortSubscriber(Long count){
if(count >= 1000000000){
return Long.toString(count/1000000000)+ billion + " " + subsS;
}else if(count>=1000000){
return Long.toString(count/1000000)+ million + " " + subsS;
}else if(count>=1000){
return Long.toString(count/1000)+ thousand + " " + subsS;
}else {
return Long.toString(count)+ " " + subsS;
public String shortSubscriber(Long count) {
String curSubString = count > 1 ? subsPluralS : subsS;
if (count >= 1000000000) {
return Long.toString(count / 1000000000) + billion + " " + curSubString;
} else if (count >= 1000000) {
return Long.toString(count / 1000000) + million + " " + curSubString;
} else if (count >= 1000) {
return Long.toString(count / 1000) + thousand + " " + curSubString;
} else {
return Long.toString(count) + " " + curSubString;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -24,10 +24,10 @@ import android.widget.Toast;
import org.schabi.newpipe.ActivityCommunicator;
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.R;
import org.schabi.newpipe.detail.VideoItemDetailActivity;
import org.schabi.newpipe.detail.VideoItemDetailFragment;
import org.schabi.newpipe.util.NavStack;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.util.Constants;
import java.io.IOException;
import java.util.Arrays;
@@ -343,7 +343,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
/*
NotificationCompat.Action pauseButton = new NotificationCompat.Action.Builder
(R.drawable.ic_pause_white_24dp, "Pause", playPI).build();
(R.drawable.ic_pause_white, "Pause", playPI).build();
*/
PendingIntent playPI = PendingIntent.getBroadcast(owner, noteID,
@@ -354,10 +354,11 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
new Intent(ACTION_REWIND), PendingIntent.FLAG_UPDATE_CURRENT);
//build intent to return to video, on tapping notification
Intent openDetailViewIntent = new Intent(getApplicationContext(),
VideoItemDetailActivity.class);
openDetailViewIntent.putExtra(NavStack.SERVICE_ID, serviceId);
openDetailViewIntent.putExtra(NavStack.URL, webUrl);
Intent openDetailViewIntent = new Intent(getApplicationContext(), MainActivity.class);
openDetailViewIntent.putExtra(Constants.KEY_SERVICE_ID, serviceId);
openDetailViewIntent.putExtra(Constants.KEY_URL, webUrl);
openDetailViewIntent.putExtra(Constants.KEY_TITLE, title);
openDetailViewIntent.putExtra(Constants.KEY_LINK_TYPE, StreamingService.LinkType.STREAM);
openDetailViewIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent openDetailView = PendingIntent.getActivity(owner, noteID,
openDetailViewIntent, PendingIntent.FLAG_UPDATE_CURRENT);
@@ -465,7 +466,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
RemoteViews views = getContentView(), bigViews = getBigContentView();
int imageSrc;
if(isPlaying) {
imageSrc = R.drawable.ic_pause_white_24dp;
imageSrc = R.drawable.ic_pause_white;
} else {
imageSrc = R.drawable.ic_play_circle_filled_white_24dp;
}

View File

@@ -5,9 +5,8 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.media.MediaPlayer;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -28,7 +27,6 @@ import android.widget.MediaController;
import android.widget.ProgressBar;
import android.widget.VideoView;
import org.schabi.newpipe.App;
import org.schabi.newpipe.R;
/**

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
package org.schabi.newpipe.player;
public interface StateInterface {
int STATE_LOADING = 123;
int STATE_PLAYING = 124;
int STATE_BUFFERING = 125;
int STATE_PAUSED = 126;
int STATE_PAUSED_SEEK = 127;
int STATE_COMPLETED = 128;
void changeState(int state);
void onLoading();
void onPlaying();
void onBuffering();
void onPaused();
void onPausedSeek();
void onCompleted();
}

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