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

Compare commits

...

115 Commits

Author SHA1 Message Date
Adam Howard
c4ea73ca7a Merge pull request #93 from chschtsch/patch-6
remove quotation marks added by weblate
2015-11-13 12:19:21 +00:00
Adam Howard
2aa28d6453 Merge pull request #92 from chschtsch/patch-5
remove quotation marks added by weblate
2015-11-13 12:19:11 +00:00
Adam Howard
2d51085ccf Merge pull request #91 from chschtsch/patch-4
remove quotation marks added by weblate
2015-11-13 12:19:03 +00:00
Adam Howard
4eae02e47e Merge pull request #90 from chschtsch/patch-2
remove quotation marks added by weblate
2015-11-13 12:18:48 +00:00
Adam Howard
f3bf9f9e5d Merge pull request #89 from chschtsch/patch-3
remove quotation marks added by weblate
2015-11-13 12:18:38 +00:00
Greg
75d0b84bdb remove quotation marks added by weblate 2015-11-13 15:00:24 +03:00
Greg
3643ddcf5c remove quotation marks added by weblate 2015-11-13 14:58:16 +03:00
Greg
35500e8ef7 remove quotation marks added by weblate 2015-11-13 14:57:52 +03:00
Greg
6badcf5391 remove quotation marks added by weblate 2015-11-13 14:57:09 +03:00
Greg
d4898043f6 remove quotation marks added by weblate 2015-11-13 14:56:38 +03:00
Weblate
2322ba833a Merge remote-tracking branch 'origin/master' 2015-11-13 12:27:21 +01:00
Greg
5aabb2917f Translated using Weblate (Spanish)
Currently translated at 95.6% (44 of 46 strings)
2015-11-13 12:27:21 +01:00
Greg
eacbf6ce50 Translated using Weblate (German)
Currently translated at 97.8% (45 of 46 strings)
2015-11-13 12:27:20 +01:00
Greg
031300a132 Translated using Weblate (French)
Currently translated at 76.0% (35 of 46 strings)
2015-11-13 12:27:20 +01:00
Greg
f905611e69 Translated using Weblate (English)
Currently translated at 100.0% (46 of 46 strings)

changing 'published' to 'updloaded'
2015-11-13 12:27:20 +01:00
Greg
e475f9f876 Translated using Weblate (Dutch)
Currently translated at 97.8% (45 of 46 strings)
2015-11-13 12:27:20 +01:00
Adam Howard
b65263349e Merged upstream translation commits 2015-11-13 11:07:22 +00:00
Adam Howard
5cb8026f6d Merge pull request #87 from chschtsch/patch-1
remove quotation marks added by weblate
2015-11-13 11:05:48 +00:00
Adam Howard
cc7ce5cf93 fixed inefficient double-conversion of parceled VideoInfoItems, from being cast from VideoInfoItem[] to Vector<>, to using ArrayList as an implementation of List 2015-11-13 10:47:05 +00:00
Greg
af506639a9 remove quotation marks added by weblate 2015-11-13 12:46:55 +03:00
Greg
d377d67174 Translated using Weblate (Russian)
Currently translated at 100.0% (46 of 46 strings)
2015-11-13 10:06:06 +01:00
Greg
cf926353d1 Translated using Weblate (Russian)
Currently translated at 100.0% (46 of 46 strings)
2015-11-13 09:54:54 +01:00
Weblate
d686c744d0 Merge remote-tracking branch 'origin/master' 2015-11-13 03:22:52 +01:00
Greg
501c60b180 Translated using Weblate (Russian)
Currently translated at 97.8% (45 of 46 strings)
2015-11-13 03:22:52 +01:00
jasperweiss
da36687e25 Translated using Weblate (Dutch)
Currently translated at 100.0% (46 of 46 strings)
2015-11-13 03:22:52 +01:00
Adam Howard
f13f9a066a updated README to include language-specific search feature 2015-11-12 15:51:22 +00:00
Christian Schabesberger
8eaa4f7654 Merge pull request #82 from chschtsch/master
fix bug with parsing like/dislike count
2015-11-12 10:26:50 +01:00
Greg
145a7f8e0d fix bug with parsing like/dislike count 2015-11-12 12:18:41 +03:00
Adam Howard
67ba126602 implemented locale-specific formatting of view, like and dislike counts, and video published date 2015-11-11 16:23:22 +00:00
Adam Howard
c5084901b5 removed commented-out code, added another TODO note 2015-11-11 13:08:53 +00:00
Adam Howard
3bfc82f7c0 Refactoring YoutubeExtractor:
-replaced single use of terrible_unescape_workaround_fuck(String) with call to URLDecoder.decode(String, String)
* tested new regex implementation of YoutubeExtractor.getVideoId(String)
- deleted old HashMap-based implementation of YoutubeExtractor.getVideoId(String)
* Miscellaneous typo corrections
* replaced direct page-scraping extraction of video publication date in YoutubeExtractor.getVideoInfo(String) with jsoup-based scrape of <meta> tag field in YYYY-MM-DD format
*similarly,  replaced direct page-scraping extraction of view count with <meta> tag field.

Both <meta> tag fields still need to be formatted locale-specifically
2015-11-11 13:07:09 +00:00
Adam Howard
3411b53450 implemented optimised version of YoutubeExtractor.getVideoId().
new version uses a regular expression instead of creating a HashMap and looping over them.
Needs testing before pushing to origin
2015-11-11 01:48:44 +00:00
Christian Schabesberger
873564f2aa removed .idea folder 2015-11-10 21:17:07 +01:00
Christian Schabesberger
353ed90d12 New version number 0.6.0 and some fixes:
* moved on to version 0.6.0
* fixed youtube url sicnature encryption (vevo videos can be watched again)
* removed play action from the ActionBar
* rolled back changes for hiding the InfoBar inside PlayVideoActivity
* some small layout changes
* removed some files to be ignored (mostly inside .idea directory)
* etc
2015-11-10 20:51:39 +01:00
Christian Schabesberger
799faecc5b Merge pull request #80 from chschtsch/master
Update layout (initially suggested by @darkon5) + miscellaneous fixes
2015-11-10 19:28:53 +01:00
chschtsch
731321b1f9 tryna merge dem files 2015-11-10 20:50:15 +03:00
chschtsch
7ff43caf96 tryna merge dem files 2015-11-10 20:36:35 +03:00
chschtsch
d0877c3132 tryna merge dem files 2015-11-10 20:34:08 +03:00
chschtsch
c589b03dcb rollback setting English as a default language for content 2015-11-10 20:28:05 +03:00
chschtsch
862b5aaef6 update layout (implementing redesign suggested by @darkon5) & set english as a default language for content 2015-11-10 20:26:20 +03:00
Adam Howard
596443bf5e added licensing notice to MediaFormat 2015-11-10 17:23:07 +00:00
Adam Howard
27b450f1e3 minor commit:
-removed now-redundant language code check
2015-11-10 17:09:26 +00:00
chschtsch
61a09e97ca update colors (implementing redesign suggested by @darkon5) 2015-11-10 19:55:58 +03:00
chschtsch
224e7a8969 update date extracting regex pattern + fix some strings in English 2015-11-10 19:50:04 +03:00
Adam Howard
9e7d9ee973 merged commits from origin 2015-11-10 12:43:40 +00:00
Weblate
586bad345c Merge remote-tracking branch 'origin/master' 2015-11-09 08:16:47 +01:00
Szöllősi Attila
abdd7dc7d3 Translated using Weblate (Hungarian)
Currently translated at 97.8% (45 of 46 strings)
2015-11-09 08:16:47 +01:00
jasperweiss
aee32f7a3e Translated using Weblate (Dutch)
Currently translated at 100.0% (46 of 46 strings)
2015-11-09 08:16:45 +01:00
Christian Schabesberger
696760e65a removed printing the player url 2015-11-08 21:22:24 +01:00
Christian Schabesberger
200db15d4b Merge branch 'master' of github.com:theScrabi/NewPipe 2015-11-08 21:19:09 +01:00
Christian Schabesberger
33e332f105 impofed performance and made similar video button hidable 2015-11-08 21:17:51 +01:00
Timofonic
bb2955e442 Translated using Weblate (Spanish)
Currently translated at 100.0% (46 of 46 strings)
2015-11-08 19:54:28 +01:00
Adam Howard
2fc2fa56c3 refactoring VideoInfo & MediaFormat, part 2:
* fixed errors caused by moving media format code to MediaFormat enum
2015-11-08 02:22:40 +00:00
Adam Howard
c87458590c refactoring VideoInfo & VideoInfoItem, part 1:
+ created enum VideoFormat
2015-11-08 02:04:03 +00:00
Adam Howard
8aff134c56 replaced content tountry selection with search language selection.Should now allows users to search for videos in their preferred language. Needs testing before pushing to origin. 2015-11-08 01:09:03 +00:00
Christian Schabesberger
4a938b81df Merge pull request #73 from joshsoftware/feature_search_suggestion
Feature search suggestion (enhancement)
2015-11-05 12:36:43 +01:00
chandrashekhar
4def715b25 + Added TODO & remove unused lines. 2015-11-05 13:19:28 +05:30
chandrashekhar
821acf12d8 +Merge Adam Howard's (medavox) commit with my changes & remove conflict.
+update searchEngine.java & YoutubeSearchEngine.java file.

Conflicts:
	app/src/main/java/org/schabi/newpipe/SearchEngine.java
	app/src/main/java/org/schabi/newpipe/youtube/YoutubeSearchEngine.java
2015-11-05 13:03:47 +05:30
Adam Howard
fc707b6c7e Added Content Country selection setting. This changes the SearchEngine interface slightly. Still need a reliable test to prove whether YouTube is serving different search results based on the country code passed in the search query. 2015-11-04 12:42:17 +00:00
chandrashekhar
85ac000479 + Change return type of interface method suggestionList, So that it will return arraylist of string type data(suggestion). 2015-11-04 11:44:34 +05:30
chandrashekhar
68a0eefa20 + Added interface method in SearchEngine class for fetch search suggestion list.
+ Implemented SearchEngine Interface method in YoutubeSearchEngine class.
2015-11-04 09:06:21 +05:30
Adam Howard
fc32377ce7 added check and exception reporting to YoutubeExtractor:matchGroup1, so that a failed match doesn't go unnoticed 2015-11-04 00:29:30 +00:00
Christian Schabesberger
59e512a64d fixed notification hiding issue 2015-11-03 22:19:28 +01:00
Christian Schabesberger
c51a5a51f1 Merge pull request #72 from medavox/master
Code cleanup & minor additions
2015-11-03 17:54:09 +01:00
Adam Howard
9546a276dc modified gitignore so jdk versions changes are hopefully not propagated to remote 2015-11-03 13:20:15 +00:00
Adam Howard
a18353df5f still fighting with jdk version strings in app/app.iml, .idea/gradle.xml, .idea/misc.xml 2015-11-03 13:19:23 +00:00
Adam Howard
3c72113f4c replaced 4-line regex blocks with call to equivalent method; removed unecessary try-catch blocks surrounding them: regex methods don't throw runtime exceptions 2015-11-03 12:56:11 +00:00
Adam Howard
7e193751c4 fixed app/app.iml, .idea/grade.xml and .idea/misc.xml siwtching jdk versions between 1.7 and 1.8. Added them to my local .gitignore 2015-11-03 12:08:30 +00:00
Adam Howard
56c96eb712 Merge remote-tracking branch 'upstream/master':
Synced new russian translation from theScrabi/NewPipe
2015-11-03 11:51:40 +00:00
Adam Howard
4106a984ca minor corrections pre-sync 2015-11-03 11:51:18 +00:00
Christian Schabesberger
10f1ab0598 Merge pull request #71 from chschtsch/patch-1
Add russian translation of strings.xml
2015-11-03 11:28:27 +01:00
chschtsch
bca9603440 Add russian translation of strings.xml 2015-11-03 12:34:51 +03:00
Adam Howard
c32c267889 Merge remote-tracking branch 'upstream/master'
Conflicts:
	app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java -- still used class-based passing
	app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java -- just some whitespace
2015-11-02 21:29:43 +00:00
Adam Howard
627e987bda made the PlayVideoActivity return to its VideoItemDetailActivity when the back button is pressed, by setting its parent activity in the manifest. Also grammar fixes for existing comments 2015-11-02 21:19:18 +00:00
Christian Schabesberger
7c18e147f3 added "show next/related videos" to features 2015-11-02 20:32:13 +01:00
Christian Schabesberger
6a8fb5910d changed icon in the README file 2015-11-02 20:18:23 +01:00
Christian Schabesberger
b865326d51 added ability to show similar videos 2015-11-02 19:57:47 +01:00
Adam Howard
a2d5b0893d Merge remote-tracking branch 'upstream/master' 2015-11-02 15:12:34 +00:00
Adam Howard
db0508b9ab refactored StreamingService interface so it acts as a Factory (returning new instances of called classes, eg Extractor), rather than passing Class objects (which loses type safety) which are then instantiated. Also noticed there is a conflict between existing gradle setup and mine: misc.xml and app.iml have had their jvm version values switched from 1.8 to 1.7 2015-11-02 15:03:11 +00:00
Christian Schabesberger
1850dee93a Merge pull request #67 from joshsoftware/remove_deprecation
Remove Deprecated methods
2015-11-02 15:37:17 +01:00
Weblate
7b1eb8a6dc Merge remote-tracking branch 'origin/master' 2015-11-02 14:26:43 +01:00
chandrashekhar
95a9f2f5e3 + Remove deprecated method from app/src/main/java/org/schabi/newpipe/VideoItemListFragment.java
onAttach(Activity activity) is replaced by onAttach(Context context)

+ Remove deprecated method from pp/src/main/java/org/schabi/newpipe/VideoListAdapter.java
context.getResource().getColor(resId) is replaced by ContextCompat.getColor(context,resId)
2015-11-02 18:02:32 +05:30
darkon5
ae7ed2d226 Merge pull request #65 from medavox/master
Minor README edits
2015-11-02 10:18:24 +01:00
Szöllősi Attila
20cf82bab1 Translated using Weblate (Hungarian)
Currently translated at 100.0% (44 of 44 strings)
2015-11-01 21:42:52 +01:00
Mladen Pejaković
5dcb1e26b5 Translated using Weblate (Serbian)
Currently translated at 100.0% (44 of 44 strings)
2015-10-31 19:56:57 +01:00
Christian Schabesberger
8076589180 Translated using Weblate (German)
Currently translated at 100.0% (44 of 44 strings)
2015-10-31 16:11:54 +01:00
Christian Schabesberger
edbd4003be Merge pull request #64 from mamins1376/master
add Persian translation
2015-10-31 13:53:26 +01:00
medavox
122b089bf0 minor grammar 2015-10-31 12:07:07 +00:00
medavox
a28d917990 fixed typo 2015-10-31 12:05:42 +00:00
Mohammad Amin Sameti
5b605a1100 add Persian translation 2015-10-31 02:30:08 +03:30
Christian Schabesberger
f67158a2a7 Fixed:
- made "could not find a streamingplayer" thing inside ActionBarHandler yield stacktraces
- remove watermark
- fixed fab layout
- changed version number to 0.5.0
2015-10-29 18:37:32 +01:00
Christian Schabesberger
c22c2009d4 - changed icon again
- made ActionBarHandler not be a singelton anymore
 - fixed go back bug for the "Next Video" thing
 - fixed opening youtube mobile links
2015-10-29 17:56:35 +01:00
Christian Schabesberger
ab4d626ea9 fixed opening videos via firefox/fenec 2015-10-28 20:48:03 +01:00
Christian Schabesberger
96709d22e9 Merge pull request #61 from Natureshadow/patch-1
Add missing patterns as described in isue #50
2015-10-28 19:39:06 +01:00
Christian Schabesberger
f0bd171eee small layout changed in README.md 2015-10-28 19:08:58 +01:00
Dominik George
c4191077f3 Add missing patterns as described in isue #50 2015-10-28 15:24:46 +01:00
Christian Schabesberger
321d090052 - added dracon5's website to README.md
- added halcyonest icon (with smal modifications)
2015-10-27 21:35:08 +01:00
Christian Schabesberger
32dcb4d281 improved README file 2015-10-27 20:01:56 +01:00
Christian Schabesberger
080159849e - added preference for "next video" item
- display if a url is supported or nod
2015-10-27 18:13:04 +01:00
Christian Schabesberger
d9e690f62c added NextVideo support 2015-10-25 19:14:29 +01:00
Christian Schabesberger
8c0156dea3 fixed broken commit 2015-10-24 16:05:23 +02:00
Christian Schabesberger
038c59ce66 fiexed some smaller displaying errors 2015-10-24 16:04:27 +02:00
Christian Schabesberger
72e08c0447 fixed some layout bugs 2015-10-23 23:08:01 +02:00
Christian Schabesberger
173eaa8cf8 Merge pull request #51 from Soofe/master
Fixed some typos and removed unused imports.
2015-10-17 17:22:21 +02:00
Christian Schabesberger
a04cd24e5e Merge pull request #53 from pejakm/srupd
Update Serbian translation
2015-10-17 17:15:53 +02:00
Mladen Pejaković
0e11404b3b Update Serbian translation 2015-10-17 17:13:21 +02:00
Soofe
342807e26a Update VideoItemListFragment.java 2015-10-15 23:58:14 +02:00
Soofe
c068f08ff8 Fixed some typos and removed unused imports. 2015-10-15 23:25:53 +02:00
Christian Schabesberger
b7c0a77edc Merge pull request #45 from ata2001/master
Update hungarian translation
2015-09-25 23:33:01 +02:00
ata2001
aab0f45890 Update hungarian translation 2015-09-26 00:05:54 +02:00
Christian Schabesberger
c62ad66f11 New:
- Show video title instead of stream url in vlc/MXPlayer
 - remember rotation
Fix:
 - sensore controlled landscape rotation in the player
2015-09-25 14:17:43 +02:00
Christian Schabesberger
d8bdada9db Merge pull request #43 from epitron/master
Set the title for external video players
2015-09-25 07:43:46 +02:00
Christian Schabesberger
1b9f7a7654 Merge pull request #40 from ata2001/master
Update hungarian translation
2015-09-25 07:42:41 +02:00
Chris Gahan
ac710fff08 Set the title for external video players. 2015-09-23 21:58:41 -04:00
ata2001
2e09492eef Update hungarian translation 2015-09-23 19:01:09 +02:00
64 changed files with 2835 additions and 1041 deletions

5
.gitignore vendored
View File

@@ -1,7 +1,8 @@
.gitignore
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
/app/app.iml
/.idea

1
.idea/.name generated
View File

@@ -1 +0,0 @@
NewPipe

22
.idea/compiler.xml generated
View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>

View File

@@ -1,3 +0,0 @@
<component name="CopyrightManager">
<settings default="" />
</component>

View File

@@ -1,3 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="the-scrabi" />
</component>

19
.idea/gradle.xml generated
View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="LOCAL" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.4" />
<option name="gradleJvm" value="1.8" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

46
.idea/misc.xml generated
View File

@@ -1,46 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

9
.idea/modules.xml generated
View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/NewPipe.iml" filepath="$PROJECT_DIR$/NewPipe.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
</modules>
</component>
</project>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

6
.idea/vcs.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="NewPipe" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@@ -1,7 +1,46 @@
NewPipe
-------
# NewPipe
[![Translation Status](https://hosted.weblate.org/widgets/NewPipe/-/svg-badge.svg)](https://hosted.weblate.org/engage/NewPipe/)
NewPipe is a lightweight youtube frontend for android. It's supposed to be used without the youtube-api and without any google play services. NewPipe only parses the youtube website in order to gain the information it needs.
[![NewPipe](https://f-droid.org/repo/icons/org.schabi.newpipe.5.png)](http://dasochan.nl/newpipe/)
NewPipe: A free lightweight Youtube frontend for Android.
This a very early version of the app, so not all functionality is implemented, and there may still be a lot of bugs. But all in all it's doing what it is supposed to do. It makes it possible to watch youtube videos. So don't be cruel to this app. It will improve...
[![F-Droid](https://f-droid.org/wiki/images/0/06/F-Droid-button_get-it-on.png)](https://f-droid.org/repository/browse/?fdfilter=newpipe&fdid=org.schabi.newpipe)
## Description
NewPipe does not use any Google framework libraries, or the YouTube API. It only parses the website in order to gain the information it needs. Therefore this app can be used on devices without G-services installed. Also NewPipe does not store data on the YouTube website (no login), and it's free software.
## Features
* Search videos
* Display general information about a video
* Watch Youtube videos
* Listen to Youtube videos (audio only streaming)
* Select the streaming player to watch the video with
* Download videos (working, but it could be better)
* Download audio only (working but, but it could be better)
* Open a video in Kodi
* Show Next/Related videos
* Search Youtube in a specific language
## Coming Features
* Improved Downloading
* Bookmarks
* View history
* Search history
* Search channels
* Display general information about channels
* Subscribe to channels
* Watch videos from a channel
* Search/Watch Playlists
* ... and many more
### Multi service support
Generally NewPipe is designed to not only support YouTube, but many more streaming services. However, right now NewPipe is not stable enough to support more than only YouTube. But if all works as planned, NewPipe will get such support by the version 2.0.
# Help is always welcome !!!
Whether it's about ideas, translation, design changes, code cleaning, or real heavy code changes. Help is always welcome.
The more is done the better it gets!

2
app/.gitignore vendored
View File

@@ -1 +1,3 @@
.gitignore
/build
app.iml

View File

@@ -1,101 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="NewPipe" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":app" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
<afterSyncTasks>
<task>generateDebugAndroidTestSources</task>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="jsoup-1.8.3" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
<orderEntry type="library" exported="" name="rhino-1.7.7" level="project" />
<orderEntry type="library" exported="" name="design-23.0.1" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
</component>
</module>

View File

@@ -8,8 +8,8 @@ android {
applicationId "org.schabi.newpipe"
minSdkVersion 15
targetSdkVersion 23
versionCode 4
versionName "0.4.1"
versionCode 6
versionName "0.6.0"
}
buildTypes {
release {
@@ -21,9 +21,9 @@ android {
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:support-v4:23.0.1'
compile 'com.android.support:appcompat-v7:23.1.0'
compile 'com.android.support:support-v4:23.1.0'
compile 'com.android.support:design:23.1.0'
compile 'org.jsoup:jsoup:1.8.3'
compile 'org.mozilla:rhino:1.7.7'
compile 'com.android.support:design:23.0.1'
}

View File

@@ -34,27 +34,27 @@
<data
android:host="youtube.com"
android:scheme="http"
android:pathPrefix="/watch"/>
android:pathPattern="/?*#*/*watch"/>
<data
android:host="youtube.com"
android:scheme="https"
android:pathPrefix="/watch"/>
android:pathPattern="/?*#*/*watch"/>
<data
android:host="www.youtube.com"
android:scheme="http"
android:pathPrefix="/watch"/>
android:pathPattern="/?*#*/*watch"/>
<data
android:host="www.youtube.com"
android:scheme="https"
android:pathPrefix="/watch"/>
android:pathPattern="/?*#*/*watch"/>
<data
android:host="m.youtube.com"
android:scheme="http"
android:pathPrefix="/watch"/>
android:pathPattern="/?*#*/*watch"/>
<data
android:host="m.youtube.com"
android:scheme="https"
android:pathPrefix="/watch"/>
android:pathPattern="/?*#*/*watch"/>
<data
android:host="youtu.be"
android:scheme="https"
@@ -68,6 +68,7 @@
<activity android:name=".PlayVideoActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/FullscreenTheme"
android:parentActivityName=".VideoItemDetailActivity"
>
</activity>
<activity

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,11 @@
package org.schabi.newpipe;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
/**
* Created by Christian Schabesberger on 14.08.15.
@@ -28,12 +30,25 @@ import java.net.URL;
public class Downloader {
private static final String USER_AGENT = "Mozilla/5.0";
public static String download(String siteUrl) {
StringBuffer response = new StringBuffer();
public static String download(String siteUrl, String language) {
String ret = "";
try {
URL url = new URL(siteUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Accept-Language", language);
ret = dl(con);
}
catch(Exception e) {
e.printStackTrace();
}
return ret;
}
private static String dl(HttpURLConnection con) {
StringBuffer response = new StringBuffer();
try {
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", USER_AGENT);
@@ -45,9 +60,31 @@ public class Downloader {
response.append(inputLine);
}
in.close();
} catch (Exception e) {
}
catch(UnknownHostException uhe) {//thrown when there's no internet connection
uhe.printStackTrace();
//Toast.makeText(getActivity(), uhe.getMessage(), Toast.LENGTH_LONG).show();
}
catch (Exception e) {
e.printStackTrace();
}
return response.toString();
}
public static String download(String siteUrl) {
String ret = "";
try {
URL url = new URL(siteUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
ret = dl(con);
}
catch(Exception e) {
e.printStackTrace();
}
return ret;
}
}

View File

@@ -1,7 +1,5 @@
package org.schabi.newpipe;
import android.graphics.Bitmap;
/**
* Created by Christian Schabesberger on 10.08.15.
*

View File

@@ -0,0 +1,64 @@
package org.schabi.newpipe;
/**
* Created by Adam Howard on 08/11/15.
*
* Copyright (c) Christian Schabesberger <chris.schabesberger@mailbox.org>
* and Adam Howard <achdisposable1@gmail.com> 2015
*
* VideoListAdapter.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 enum MediaFormat {
// 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"),
M4A (0x3, "m4a", "m4a", "audio/mp4"),
WEBMA (0x4, "WebM", "webm", "audio/webm");
public final int id;
public final String name;
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;
}
public static String getNameById(int ident) {
for (MediaFormat vf : MediaFormat.values()) {
if(vf.id == ident) return vf.name;
}
return "";
}
public static String getSuffixById(int ident) {
for (MediaFormat vf : MediaFormat.values()) {
if(vf.id == ident) return vf.suffix;
}
return "";
}
public static String getMimeById(int ident) {
for (MediaFormat vf : MediaFormat.values()) {
if(vf.id == ident) return vf.mimeType;
}
return "";
}
}

View File

@@ -1,9 +1,10 @@
package org.schabi.newpipe;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
@@ -17,15 +18,11 @@ import android.view.Display;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.MediaController;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.VideoView;
/**
@@ -72,6 +69,9 @@ public class PlayVideoActivity extends AppCompatActivity {
private boolean isLandscape = true;
private boolean hasSoftKeys = false;
private SharedPreferences prefs;
private static final String PREF_IS_LANDSCAPE = "is_landscape";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -79,7 +79,7 @@ public class PlayVideoActivity extends AppCompatActivity {
setContentView(R.layout.activity_play_video);
isLandscape = checkIfLandscape();
hasSoftKeys = checkIfhasSoftKeys();
hasSoftKeys = checkIfHasSoftKeys();
actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
@@ -133,15 +133,21 @@ public class PlayVideoActivity extends AppCompatActivity {
}
});
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
if (android.os.Build.VERSION.SDK_INT >= 17) {
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
prefs = getPreferences(Context.MODE_PRIVATE);
if(prefs.getBoolean(PREF_IS_LANDSCAPE, false) && !isLandscape) {
toggleOrientation();
}
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
}
@Override
@@ -179,14 +185,7 @@ public class PlayVideoActivity extends AppCompatActivity {
startActivity(Intent.createChooser(intent, getString(R.string.shareDialogTitle)));
break;
case R.id.menu_item_screen_rotation:
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0
|| display.getRotation() == Surface.ROTATION_180) {
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if(display.getRotation() == Surface.ROTATION_90
|| display.getRotation() == Surface.ROTATION_270) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
toggleOrientation();
break;
default:
Log.e(TAG, "Error: MenuItem not known");
@@ -201,10 +200,10 @@ public class PlayVideoActivity extends AppCompatActivity {
if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
isLandscape = true;
adjustMediaControllMetrics();
adjustMediaControlMetrics();
} else if (config.orientation == Configuration.ORIENTATION_PORTRAIT){
isLandscape = false;
adjustMediaControllMetrics();
adjustMediaControlMetrics();
}
}
@@ -227,7 +226,7 @@ public class PlayVideoActivity extends AppCompatActivity {
uiIsHidden = false;
mediaController.show(100000);
actionBar.show();
adjustMediaControllMetrics();
adjustMediaControlMetrics();
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@@ -248,16 +247,18 @@ public class PlayVideoActivity extends AppCompatActivity {
uiIsHidden = true;
actionBar.hide();
mediaController.hide();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
if (android.os.Build.VERSION.SDK_INT >= 17) {
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
private void adjustMediaControllMetrics() {
private void adjustMediaControlMetrics() {
MediaController.LayoutParams mediaControllerLayout
= new MediaController.LayoutParams(MediaController.LayoutParams.MATCH_PARENT,
MediaController.LayoutParams.WRAP_CONTENT);
@@ -272,7 +273,7 @@ public class PlayVideoActivity extends AppCompatActivity {
mediaController.setLayoutParams(mediaControllerLayout);
}
private boolean checkIfhasSoftKeys(){
private boolean checkIfHasSoftKeys(){
if(Build.VERSION.SDK_INT >= 17) {
return getNavigationBarHeight() != 0 || getNavigationBarWidth() != 0;
} else {
@@ -319,4 +320,17 @@ public class PlayVideoActivity extends AppCompatActivity {
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.heightPixels < displayMetrics.widthPixels;
}
private void toggleOrientation() {
if(isLandscape) {
isLandscape = false;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
isLandscape = true;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(PREF_IS_LANDSCAPE, isLandscape);
editor.commit();
}
}

View File

@@ -1,7 +1,6 @@
package org.schabi.newpipe;
import android.graphics.Bitmap;
import java.util.ArrayList;
import java.util.Vector;
/**
@@ -33,5 +32,8 @@ public interface SearchEngine {
public Vector<VideoInfoItem> resultList = new Vector<>();
}
Result search(String query, int page);
ArrayList<String> suggestionList(String query);
//Result search(String query, int page);
Result search(String query, int page, String contentCountry);
}

View File

@@ -25,11 +25,11 @@ public interface StreamingService {
public String name = "";
}
ServiceInfo getServiceInfo();
Class getExtractorClass();
Class getSearchEngineClass();
Extractor getExtractorInstance();
SearchEngine getSearchEngineInstance();
// 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 callean through ACTIONs.
/**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 callean through ACTIONs.*/
boolean acceptUrl(String videoUrl);
}

View File

@@ -1,5 +1,11 @@
package org.schabi.newpipe;
import android.graphics.Bitmap;
import android.util.Log;
import java.util.Date;
import java.util.Vector;
/**
* Created by Christian Schabesberger on 26.08.15.
*
@@ -20,85 +26,36 @@ package org.schabi.newpipe;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
import android.graphics.Bitmap;
import android.util.Log;
import java.util.Vector;
/**Info object for opened videos, ie the video ready to play.*/
public class VideoInfo {
public String id = "";
public String title = "";
public String uploader = "";
public String thumbnail_url = "";
public Bitmap thumbnail = null;
public String webpage_url = "";
public String upload_date = "";
public long view_count = 0;
public String uploader_thumbnail_url = "";
public Bitmap uploader_thumbnail = null;
public String description = "";
public int duration = -1;
public int age_limit = 0;
public int like_count = 0;
public int dislike_count = 0;
public String average_rating = "";
public VideoStream[] videoStreams = null;
public AudioStream[] audioStreams = null;
public VideoInfoItem nextVideo = null;
public VideoInfoItem[] relatedVideos = null;
public int videoAvailableStatus = VIDEO_AVAILABLE;
private static final String TAG = VideoInfo.class.toString();
// format identifier
public static final int I_MPEG_4 = 0x0;
public static final int I_3GPP = 0x1;
public static final int I_WEBM = 0x2;
public static final int I_M4A = 0x3;
public static final int I_WEBMA = 0x4;
// format name
public static final String F_MPEG_4 = "MPEG-4";
public static final String F_3GPP = "3GPP";
public static final String F_WEBM = "WebM";
public static final String F_M4A = "m4a";
public static final String F_WEBMA = "WebM";
// file suffix
public static final String C_MPEG_4 = "mp4";
public static final String C_3GPP = "3gp";
public static final String C_WEBM = "webm";
public static final String C_M4A = "m4a";
public static final String C_WEBMA = "webm";
// mimeType
public static final String M_MPEG_4 = "video/mp4";
public static final String M_3GPP = "video/3gpp";
public static final String M_WEBM = "video/webm";
public static final String M_M4A = "audio/mp4";
public static final String M_WEBMA = "audio/webm";
public static final int VIDEO_AVAILABLE = 0x00;
public static final int VIDEO_UNAVAILABLE = 0x01;
public static final int VIDEO_UNAVAILABLE_GEMA = 0x02;
public static String getNameById(int id) {
switch(id) {
case I_MPEG_4: return F_MPEG_4;
case I_3GPP: return F_3GPP;
case I_WEBM: return F_WEBM;
case I_M4A: return F_M4A;
case I_WEBMA: return F_WEBMA;
default: Log.e(TAG, "format not known: " +
Integer.toString(id) + "call the programmer he messed it up.");
}
return "";
}
public static String getSuffixById(int id) {
switch(id) {
case I_MPEG_4: return C_MPEG_4;
case I_3GPP: return C_3GPP;
case I_WEBM: return C_WEBM;
case I_M4A: return C_M4A;
case I_WEBMA: return C_WEBMA;
default: Log.e(TAG, "format not known: " +
Integer.toString(id) + "call the programmer he messed it up.");
}
return "";
}
public static String getMimeById(int id) {
switch(id) {
case I_MPEG_4: return M_MPEG_4;
case I_3GPP: return M_3GPP;
case I_WEBM: return M_WEBM;
case I_M4A: return M_M4A;
case I_WEBMA: return M_WEBMA;
default: Log.e(TAG, "format not known: " +
Integer.toString(id) + "call the programmer he messed it up.");
}
return "";
}
public static final int VIDEO_UNAVAILABLE_GEMA = 0x02;//German DRM organisation
public static class VideoStream {
public VideoStream(String url, int format, String res) {
@@ -110,36 +67,13 @@ public class VideoInfo {
}
public static class AudioStream {
public AudioStream(String url, int format, int bandWidth, int samplingRate) {
public AudioStream(String url, int format, int bandwidth, int samplingRate) {
this.url = url; this.format = format;
this.bandWidth = bandWidth; this.samplingRate = samplingRate;
this.bandwidth = bandwidth; this.samplingRate = samplingRate;
}
public String url = "";
public int format = -1;
public int bandWidth = -1;
public int bandwidth = -1;
public int samplingRate = -1;
}
public String id = "";
public String uploader = "";
public String upload_date = "";
public String uploader_thumbnail_url = "";
public Bitmap uploader_thumbnail = null;
public String title = "";
public String thumbnail_url = "";
public Bitmap thumbnail = null;
public String description = "";
public int duration = -1;
public int age_limit = 0;
public String webpage_url = "";
public String view_count = "";
public String like_count = "";
public String dislike_count = "";
public String average_rating = "";
public VideoStream[] videoStreams = null;
public AudioStream[] audioStreams = null;
public VideoInfoItem nextVideo = null;
public Vector<VideoInfoItem> relatedVideos = null;
public int videoAvailableStatus = VIDEO_AVAILABLE;
}

View File

@@ -1,6 +1,8 @@
package org.schabi.newpipe;
import android.graphics.Bitmap;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by Christian Schabesberger on 26.08.15.
@@ -22,13 +24,63 @@ import android.graphics.Bitmap;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class VideoInfoItem {
/**Info object for previews of unopened videos, eg search results, related videos*/
public class VideoInfoItem implements Parcelable {
public String id = "";
public String title = "";
public String uploader = "";
public String duration = "";
public String thumbnail_url = "";
public Bitmap thumbnail = null;
public String webpage_url = "";
public String upload_date = "";
public String view_count = "";
public String duration = "";
protected VideoInfoItem(Parcel in) {
id = in.readString();
title = in.readString();
uploader = in.readString();
duration = in.readString();
thumbnail_url = in.readString();
thumbnail = (Bitmap) in.readValue(Bitmap.class.getClassLoader());
webpage_url = in.readString();
upload_date = in.readString();
view_count = in.readString();
}
public VideoInfoItem() {
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(title);
dest.writeString(uploader);
dest.writeString(duration);
dest.writeString(thumbnail_url);
dest.writeValue(thumbnail);
dest.writeString(webpage_url);
dest.writeString(upload_date);
dest.writeString(view_count);
}
@SuppressWarnings("unused")
public static final Parcelable.Creator<VideoInfoItem> CREATOR = new Parcelable.Creator<VideoInfoItem>() {
@Override
public VideoInfoItem createFromParcel(Parcel in) {
return new VideoInfoItem(in);
}
@Override
public VideoInfoItem[] newArray(int size) {
return new VideoInfoItem[size];
}
};
}

View File

@@ -0,0 +1,76 @@
package org.schabi.newpipe;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
/**
* Created by Christian Schabesberger on 24.10.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* VideoInfoItemViewCreator.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 VideoInfoItemViewCreator {
private static final String TAG = VideoInfoItemViewCreator.class.toString();
LayoutInflater inflater;
public VideoInfoItemViewCreator(LayoutInflater inflater) {
this.inflater = inflater;
}
public View getViewByVideoInfoItem(View convertView, ViewGroup parent, VideoInfoItem info) {
ViewHolder holder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.video_item, parent, false);
holder = new ViewHolder();
holder.itemThumbnailView = (ImageView) convertView.findViewById(R.id.itemThumbnailView);
holder.itemVideoTitleView = (TextView) convertView.findViewById(R.id.itemVideoTitleView);
holder.itemUploaderView = (TextView) convertView.findViewById(R.id.itemUploaderView);
holder.itemDurationView = (TextView) convertView.findViewById(R.id.itemDurationView);
holder.itemUploadDateView = (TextView) convertView.findViewById(R.id.itemUploadDateView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if(info.thumbnail == null) {
holder.itemThumbnailView.setImageResource(R.drawable.dummy_thumbnail);
} else {
holder.itemThumbnailView.setImageBitmap(info.thumbnail);
}
holder.itemVideoTitleView.setText(info.title);
holder.itemUploaderView.setText(info.uploader);
holder.itemDurationView.setText(info.duration);
if(!info.upload_date.isEmpty()) {
holder.itemUploadDateView.setText(info.upload_date);
} else {
//tweak if necessary: This is a hack to prevent having white space in the layout :P
holder.itemUploadDateView.setText(info.view_count);
}
return convertView;
}
private class ViewHolder {
public ImageView itemThumbnailView;
public TextView itemVideoTitleView, itemUploaderView, itemDurationView, itemUploadDateView;
}
}

View File

@@ -1,22 +1,15 @@
package org.schabi.newpipe;
import android.content.ContentProviderOperation;
import android.content.res.Configuration;
import android.os.Build;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.NavUtils;
import android.util.DisplayMetrics;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.WindowManager;
import org.schabi.newpipe.youtube.YoutubeExtractor;
import android.widget.Toast;
/**
@@ -41,9 +34,10 @@ public class VideoItemDetailActivity extends AppCompatActivity {
private static final String TAG = VideoItemDetailActivity.class.toString();
VideoItemDetailFragment fragment;
private String videoUrl;
private int currentStreamingService = -1;
private boolean isLandscape;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -51,7 +45,6 @@ public class VideoItemDetailActivity extends AppCompatActivity {
// Show the Up button in the action bar.
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ActionBarHandler.getHandler().setupNavMenu(this);
// savedInstanceState is non-null when there is fragment state
// saved from previous configurations of this activity
@@ -68,6 +61,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
// this means the video was called though another app
if (getIntent().getData() != null) {
videoUrl = getIntent().getData().toString();
Log.i(TAG, "video URL passed:\"" + videoUrl + "\"");
StreamingService[] serviceList = ServiceList.getServices();
Extractor extractor = null;
for (int i = 0; i < serviceList.length; i++) {
@@ -75,14 +69,17 @@ public class VideoItemDetailActivity extends AppCompatActivity {
arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, i);
try {
currentStreamingService = i;
extractor = (Extractor) ServiceList.getService(i)
.getExtractorClass().newInstance();
extractor = ServiceList.getService(i).getExtractorInstance();
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
if(extractor == null) {
Toast.makeText(this, R.string.urlNotSupportedText, Toast.LENGTH_LONG)
.show();
}
arguments.putString(VideoItemDetailFragment.VIDEO_URL,
extractor.getVideoUrl(extractor.getVideoId(videoUrl)));
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY,
@@ -95,14 +92,27 @@ public class VideoItemDetailActivity extends AppCompatActivity {
arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingService);
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY, false);
}
// Create the detail fragment and add it to the activity
// using a fragment transaction.
VideoItemDetailFragment fragment = new VideoItemDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.add(R.id.videoitem_detail_container, fragment)
.commit();
} else {
videoUrl = savedInstanceState.getString(VideoItemDetailFragment.VIDEO_URL);
currentStreamingService = savedInstanceState.getInt(VideoItemDetailFragment.STREAMING_SERVICE);
arguments = savedInstanceState;
}
// Create the detail fragment and add it to the activity
// using a fragment transaction.
fragment = new VideoItemDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.add(R.id.videoitem_detail_container, fragment)
.commit();
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl);
outState.putInt(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingService);
outState.putBoolean(VideoItemDetailFragment.AUTO_PLAY, false);
}
@Override
@@ -113,25 +123,23 @@ public class VideoItemDetailActivity extends AppCompatActivity {
// 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
//
Intent intent = new Intent(this, VideoItemListActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
NavUtils.navigateUpTo(this, intent);
return true;
} else {
ActionBarHandler.getHandler().onItemSelected(item, this);
return fragment.onOptionsItemSelected(item) ||
super.onOptionsItemSelected(item);
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onCreatePanelMenu(int featured, Menu menu) {
super.onCreatePanelMenu(featured, menu);
MenuInflater inflater = getMenuInflater();
ActionBarHandler.getHandler().setupMenu(menu, inflater, this);
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
fragment.onCreateOptionsMenu(menu, getMenuInflater());
return true;
}
}

View File

@@ -2,23 +2,23 @@ package org.schabi.newpipe;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.support.v7.widget.SearchView;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.Arrays;
/**
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* VideoItemListActivity.java is part of NewPipe.
@@ -41,13 +41,25 @@ public class VideoItemListActivity extends AppCompatActivity
implements VideoItemListFragment.Callbacks {
private static final String TAG = VideoItemListFragment.class.toString();
// arguments to give to this activity
public static final String VIDEO_INFO_ITEMS = "video_info_items";
// savedInstanceBundle arguments
private static final String QUERY = "query";
private static final String STREAMING_SERVICE = "streaming_service";
// activity modes
private static final int SEARCH_MODE = 0;
private static final int PRESENT_VIDEOS_MODE = 1;
private int mode = SEARCH_MODE;
private int currentStreamingServiceId = -1;
private String searchQuery = "";
private VideoItemListFragment listFragment;
private VideoItemDetailFragment videoFragment = null;
Menu menu = null;
public class SearchVideoQueryListener implements SearchView.OnQueryTextListener {
@@ -68,7 +80,6 @@ public class VideoItemListActivity extends AppCompatActivity
// onQueryTextSubmit to trigger twice when focus is not cleared.
// See: http://stackoverflow.com/questions/17874951/searchview-onquerytextsubmit-runs-twice-while-i-pressed-once
getCurrentFocus().clearFocus();
hideWatermark();
} catch(Exception e) {
e.printStackTrace();
}
@@ -82,13 +93,6 @@ public class VideoItemListActivity extends AppCompatActivity
}
private void hideWatermark() {
ImageView waterMark = (ImageView) findViewById(R.id.list_view_watermark);
if(waterMark != null) {
waterMark.setVisibility(View.GONE);
}
}
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
@@ -100,21 +104,33 @@ public class VideoItemListActivity extends AppCompatActivity
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_videoitem_list);
listFragment = (VideoItemListFragment)
getSupportFragmentManager().findFragmentById(R.id.videoitem_list);
//-------- remove this line when multiservice support is implemented ----------
//------ todo: remove this line when multiservice support is implemented ------
currentStreamingServiceId = ServiceList.getIdOfService("Youtube");
//-----------------------------------------------------------------------------
VideoItemListFragment listFragment = (VideoItemListFragment) getSupportFragmentManager()
listFragment = (VideoItemListFragment) getSupportFragmentManager()
.findFragmentById(R.id.videoitem_list);
listFragment.setStreamingService(ServiceList.getService(currentStreamingServiceId));
if(savedInstanceState != null) {
Bundle arguments = getIntent().getExtras();
if(arguments != null) {
//Parcelable[] p = arguments.getParcelableArray(VIDEO_INFO_ITEMS);
ArrayList<VideoInfoItem> p = arguments.getParcelableArrayList(VIDEO_INFO_ITEMS);
if(p != null) {
mode = PRESENT_VIDEOS_MODE;
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
listFragment.present(p);
}
}
if(savedInstanceState != null
&& mode != PRESENT_VIDEOS_MODE) {
searchQuery = savedInstanceState.getString(QUERY);
currentStreamingServiceId = savedInstanceState.getInt(STREAMING_SERVICE);
if(!searchQuery.isEmpty()) {
hideWatermark();
listFragment.search(searchQuery);
}
}
@@ -134,19 +150,18 @@ public class VideoItemListActivity extends AppCompatActivity
.setActivateOnItemClick(true);
SearchView searchView = (SearchView)findViewById(R.id.searchViewTablet);
// Somehow the seticonifiedbydefault property set by the layout xml is not working on
// the support version on SearchView, so it needs to be set programmatically.
searchView.setIconifiedByDefault(false);
searchView.setIconified(false);
searchView.setOnQueryTextListener(new SearchVideoQueryListener());
ActionBarHandler.getHandler().setupNavMenu(this);
if(mode != PRESENT_VIDEOS_MODE) {
// Somehow the seticonifiedbydefault property set by the layout xml is not working on
// the support version on SearchView, so it needs to be set programmatically.
searchView.setIconifiedByDefault(false);
searchView.setIconified(false);
searchView.setOnQueryTextListener(new SearchVideoQueryListener());
} else {
searchView.setVisibility(View.GONE);
}
}
SettingsActivity.initSettings(this);
// TODO: If exposing deep links into your app, handle intents here.
}
/**
@@ -168,10 +183,17 @@ public class VideoItemListActivity extends AppCompatActivity
arguments.putString(VideoItemDetailFragment.ARG_ITEM_ID, id);
arguments.putString(VideoItemDetailFragment.VIDEO_URL, webpage_url);
arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingServiceId);
VideoItemDetailFragment fragment = new VideoItemDetailFragment();
fragment.setArguments(arguments);
videoFragment = new VideoItemDetailFragment();
videoFragment.setArguments(arguments);
videoFragment.setOnInvokeCreateOptionsMenuListener(new VideoItemDetailFragment.OnInvokeCreateOptionsMenuListener() {
@Override
public void createOptionsMenu() {
menu.clear();
onCreateOptionsMenu(menu);
}
});
getSupportFragmentManager().beginTransaction()
.replace(R.id.videoitem_detail_container, fragment)
.replace(R.id.videoitem_detail_container, videoFragment)
.commit();
} else {
// In single-pane mode, simply start the detail activity
@@ -185,10 +207,12 @@ public class VideoItemListActivity extends AppCompatActivity
}
public boolean onCreatePanelMenu(int featured, Menu menu) {
super.onCreatePanelMenu(featured, menu);
if(findViewById(R.id.videoitem_detail_container) == null) {
MenuInflater inflater = getMenuInflater();
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
this.menu = menu;
MenuInflater inflater = getMenuInflater();
if(mode != PRESENT_VIDEOS_MODE &&
findViewById(R.id.videoitem_detail_container) == null) {
inflater.inflate(R.menu.videoitem_list, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
@@ -196,9 +220,10 @@ public class VideoItemListActivity extends AppCompatActivity
searchView.setOnQueryTextListener(
new SearchVideoQueryListener());
} else if (videoFragment != null){
videoFragment.onCreateOptionsMenu(menu, inflater);
} else {
MenuInflater inflater = getMenuInflater();
ActionBarHandler.getHandler().setupMenu(menu, inflater, this);
inflater.inflate(R.menu.videoitem_two_pannel, menu);
}
return true;
@@ -207,14 +232,23 @@ public class VideoItemListActivity extends AppCompatActivity
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == R.id.action_settings) {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
} else {
ActionBarHandler.getHandler().onItemSelected(item, this);
return super.onOptionsItemSelected(item);
switch(id) {
case android.R.id.home: {
Intent intent = new Intent(this, VideoItemListActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
NavUtils.navigateUpTo(this, intent);
return true;
}
case R.id.action_settings: {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
}
default:
return videoFragment.onOptionsItemSelected(item) ||
super.onOptionsItemSelected(item);
}
return true;
}
@Override

View File

@@ -1,10 +1,12 @@
package org.schabi.newpipe;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.View;
@@ -13,6 +15,7 @@ import android.widget.ListView;
import android.widget.Toast;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
@@ -42,6 +45,11 @@ public class VideoItemListFragment extends ListFragment {
private StreamingService streamingService = null;
private VideoListAdapter videoListAdapter;
// activity modes
private static final int SEARCH_MODE = 0;
private static final int PRESENT_VIDEOS_MODE = 1;
private int mode = SEARCH_MODE;
private String query = "";
private int lastPage = 0;
@@ -51,29 +59,30 @@ public class VideoItemListFragment extends ListFragment {
private LoadThumbsRunnable loadThumbsRunnable = null;
// used to track down if results posted by threads ar still valid
private int currentRequestId = -1;
private ListView list;
private class ResultRunnable implements Runnable {
private SearchEngine.Result result;
private int reuqestId;
private int requestId;
public ResultRunnable(SearchEngine.Result result, int requestId) {
this.result = result;
this.reuqestId = requestId;
this.requestId = requestId;
}
@Override
public void run() {
updateListOnResult(result, reuqestId);
updateListOnResult(result, requestId);
}
}
private class SearchRunnable implements Runnable {
private Class engineClass = null;
private SearchEngine engine;
private String query;
private int page;
Handler h = new Handler();
private volatile boolean run = true;
private int requestId;
public SearchRunnable(Class engineClass, String query, int page, int requestId) {
this.engineClass = engineClass;
public SearchRunnable(SearchEngine engine, String query, int page, int requestId) {
this.engine = engine;
this.query = query;
this.page = page;
this.requestId = requestId;
@@ -83,15 +92,12 @@ public class VideoItemListFragment extends ListFragment {
}
@Override
public void run() {
SearchEngine engine = null;
try {
engine = (SearchEngine) engineClass.newInstance();
} catch(Exception e) {
e.printStackTrace();
return;
}
try {
SearchEngine.Result result = engine.search(query, page);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
String searchLanguageKey = getContext().getString(R.string.searchLanguage);
String searchLanguage = sp.getString(searchLanguageKey, "en");
SearchEngine.Result result = engine.search(query, page, searchLanguage);
Log.i(TAG, "language code passed:\""+searchLanguage+"\"");
if(run) {
h.post(new ResultRunnable(result, requestId));
}
@@ -162,7 +168,16 @@ public class VideoItemListFragment extends ListFragment {
}
}
public void present(List<VideoInfoItem> videoList) {
mode = PRESENT_VIDEOS_MODE;
setListShown(true);
getListView().smoothScrollToPosition(0);
updateList(videoList);
}
public void search(String query) {
mode = SEARCH_MODE;
this.query = query;
this.lastPage = 1;
videoListAdapter.clearVideoList();
@@ -180,7 +195,8 @@ public class VideoItemListFragment extends ListFragment {
private void startSearch(String query, int page) {
currentRequestId++;
terminateThreads();
searchRunnable = new SearchRunnable(streamingService.getSearchEngineClass(), query, page, currentRequestId);
searchRunnable = new SearchRunnable(streamingService.getSearchEngineInstance(),
query, page, currentRequestId);
searchThread = new Thread(searchRunnable);
searchThread.start();
}
@@ -204,7 +220,7 @@ public class VideoItemListFragment extends ListFragment {
}
}
private void updateList(Vector<VideoInfoItem> list) {
private void updateList(List<VideoInfoItem> list) {
try {
videoListAdapter.addVideoList(list);
terminateThreads();
@@ -213,7 +229,7 @@ public class VideoItemListFragment extends ListFragment {
loadThumbsThread = new Thread(loadThumbsRunnable);
loadThumbsThread.start();
} catch(java.lang.IllegalStateException e) {
Log.w(TAG, "Trying to set value while activity is not existing anymore.");
Log.w(TAG, "Trying to set value while activity doesn't exist anymore.");
} catch(Exception e) {
e.printStackTrace();
}
@@ -230,15 +246,11 @@ public class VideoItemListFragment extends ListFragment {
}
if(searchThread != null) {
searchRunnable.terminate();
// No need to join, since we don't realy terminate the thread. We just demand
// No need to join, since we don't really terminate the thread. We just demand
// it to post its result runnable into the gui main loop.
}
}
void displayList() {
}
/**
* The serialization (saved instance state) Bundle key representing the
* activated item position. Only used on tablets.
@@ -272,6 +284,7 @@ public class VideoItemListFragment extends ListFragment {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
list = getListView();
videoListAdapter = new VideoListAdapter(getActivity(), this);
setListAdapter(videoListAdapter);
@@ -283,8 +296,6 @@ public class VideoItemListFragment extends ListFragment {
}
getListView().setOnScrollListener(new AbsListView.OnScrollListener() {
private static final float OVERSCROLL_THRESHOLD_IN_PIXELS = 100;
private float downY;
long lastScrollDate = 0;
@Override
@@ -293,8 +304,8 @@ public class VideoItemListFragment extends ListFragment {
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
ListView list = getListView();
if (list.getChildAt(0) != null
if (mode != PRESENT_VIDEOS_MODE
&& list.getChildAt(0) != null
&& list.getLastVisiblePosition() == list.getAdapter().getCount() - 1
&& list.getChildAt(list.getChildCount() - 1).getBottom() <= list.getHeight()) {
long time = System.currentTimeMillis();
@@ -309,15 +320,15 @@ public class VideoItemListFragment extends ListFragment {
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
public void onAttach(Context context) {
super.onAttach(context);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
if (!(context instanceof Callbacks)) {
throw new IllegalStateException("Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
mCallbacks = (Callbacks) context;
}
@Override

View File

@@ -2,18 +2,18 @@ package org.schabi.newpipe;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import java.util.List;
import java.util.Vector;
/**
* Created by the-scrabi on 11.08.15.
* Created by Christian Schabesberger on 11.08.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* VideoListAdapter.java is part of NewPipe.
@@ -33,21 +33,23 @@ import java.util.Vector;
*/
public class VideoListAdapter extends BaseAdapter {
private static final String TAG = VideoListAdapter.class.toString();
private LayoutInflater inflater;
private Context context;
private VideoInfoItemViewCreator viewCreator;
private Vector<VideoInfoItem> videoList = new Vector<>();
private Vector<Boolean> downloadedThumbnailList = new Vector<>();
VideoItemListFragment videoListFragment;
ListView listView;
public VideoListAdapter(Context context, VideoItemListFragment videoListFragment) {
inflater = LayoutInflater.from(context);
viewCreator = new VideoInfoItemViewCreator(LayoutInflater.from(context));
this.videoListFragment = videoListFragment;
this.listView = videoListFragment.getListView();
this.context = context;
}
public void addVideoList(Vector<VideoInfoItem> videos) {
public void addVideoList(List<VideoInfoItem> videos) {
videoList.addAll(videos);
for(int i = 0; i < videos.size(); i++) {
downloadedThumbnailList.add(false);
@@ -96,42 +98,14 @@ public class VideoListAdapter extends BaseAdapter {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.video_item, parent, false);
holder = new ViewHolder();
holder.itemThumbnailView = (ImageView) convertView.findViewById(R.id.itemThumbnailView);
holder.itemVideoTitleView = (TextView) convertView.findViewById(R.id.itemVideoTitleView);
holder.itemUploaderView = (TextView) convertView.findViewById(R.id.itemUploaderView);
holder.itemDurationView = (TextView) convertView.findViewById(R.id.itemDurationView);
holder.itemUploadDateView = (TextView) convertView.findViewById(R.id.itemUploadDateView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final Context context = parent.getContext();
if(videoList.get(position).thumbnail == null) {
holder.itemThumbnailView.setImageResource(R.drawable.dummi_thumbnail);
} else {
holder.itemThumbnailView.setImageBitmap(videoList.get(position).thumbnail);
}
holder.itemVideoTitleView.setText(videoList.get(position).title);
holder.itemUploaderView.setText(videoList.get(position).uploader);
holder.itemDurationView.setText(videoList.get(position).duration);
holder.itemUploadDateView.setText(videoList.get(position).upload_date);
convertView = viewCreator.getViewByVideoInfoItem(convertView, parent, videoList.get(position));
if(listView.isItemChecked(position)) {
convertView.setBackgroundColor(context.getResources().getColor(R.color.primaryColorYoutube));
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.primaryColorYoutube));
} else {
convertView.setBackgroundColor(0);
}
return convertView;
}
private class ViewHolder {
public ImageView itemThumbnailView;
public TextView itemVideoTitleView, itemUploaderView, itemDurationView, itemUploadDateView;
}
}

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