mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-09-29 05:20:51 +02:00
Compare commits
54 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
37d1f59132 | ||
![]() |
ab0ce55411 | ||
![]() |
c1d66596d1 | ||
![]() |
cbfccdf0d3 | ||
![]() |
9362037177 | ||
![]() |
e25c93bae2 | ||
![]() |
367c434010 | ||
![]() |
02d8463e15 | ||
![]() |
9d5a1d5c43 | ||
![]() |
c8d94f541f | ||
![]() |
27d06eaa6b | ||
![]() |
7f32857e00 | ||
![]() |
2f060f0f52 | ||
![]() |
f89d405226 | ||
![]() |
fd4459e570 | ||
![]() |
eb0df2b101 | ||
![]() |
6c178cfb7e | ||
![]() |
8ced68430d | ||
![]() |
0aade598ff | ||
![]() |
95949fd1ab | ||
![]() |
1a56382112 | ||
![]() |
d610e4b19b | ||
![]() |
fc44d9e36e | ||
![]() |
c07686576a | ||
![]() |
c2400aea4d | ||
![]() |
fb4bf0dde4 | ||
![]() |
e4f638d1ce | ||
![]() |
5c492c01a1 | ||
![]() |
f451e11f82 | ||
![]() |
95b73f35f7 | ||
![]() |
58147e9e12 | ||
![]() |
a8830e2ede | ||
![]() |
9804bb95cc | ||
![]() |
0da1aef763 | ||
![]() |
0a334804a3 | ||
![]() |
94d2f03e9b | ||
![]() |
9127f7f0c2 | ||
![]() |
0bb0226bc2 | ||
![]() |
b3a1a5dcc2 | ||
![]() |
984dd1cc25 | ||
![]() |
5663e543a4 | ||
![]() |
d3879a0398 | ||
![]() |
6bd2468d44 | ||
![]() |
e63d43151b | ||
![]() |
0265da4ae6 | ||
![]() |
ef255d12ae | ||
![]() |
eeb612f9a2 | ||
![]() |
dfcb4edb81 | ||
![]() |
d90162d06f | ||
![]() |
97c924341c | ||
![]() |
cd3f405bff | ||
![]() |
7cfdca7a81 | ||
![]() |
216063dba8 | ||
![]() |
b647bacd72 |
@@ -1,11 +1,11 @@
|
|||||||
#Contributing
|
#Contribution
|
||||||
|
|
||||||
This document contains guidelines on making contributions to NewPipe.
|
This document contains guidelines on making contributions to NewPipe.
|
||||||
|
|
||||||
## Programming
|
## Programming
|
||||||
|
|
||||||
* Follow the [Google Style Guidelines](https://google.github.io/styleguide/javaguide.html)
|
* Follow the [Google Style Guidelines](https://google.github.io/styleguide/javaguide.html)
|
||||||
* Make a new feature on a seperate branch, not on the master branch
|
* Make a new feature on a separate branch, not on the master branch
|
||||||
* Make a [pull request](https://github.com/theScrabi/NewPipe/pulls) if you're done with your changes
|
* Make a [pull request](https://github.com/theScrabi/NewPipe/pulls) if you're done with your changes
|
||||||
* When submitting changes, you agree that your code will be GPLv3 licensed
|
* When submitting changes, you agree that your code will be GPLv3 licensed
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ This document contains guidelines on making contributions to NewPipe.
|
|||||||
compatibility with all git tools
|
compatibility with all git tools
|
||||||
* [This guide](http://chris.beams.io/posts/git-commit/) goes more in depth on what makes a good commit message
|
* [This guide](http://chris.beams.io/posts/git-commit/) goes more in depth on what makes a good commit message
|
||||||
|
|
||||||
## Translating
|
## Translation
|
||||||
|
|
||||||
* NewPipe can be translated on [weblate](https://hosted.weblate.org/projects/newpipe/strings/)
|
* NewPipe can be translated on [weblate](https://hosted.weblate.org/projects/newpipe/strings/)
|
||||||
|
|
||||||
@@ -30,4 +30,4 @@ This document contains guidelines on making contributions to NewPipe.
|
|||||||
## Communication
|
## Communication
|
||||||
|
|
||||||
* For the time being, [Slack](http://invite.chschtsch.ml/) is being used for project communication
|
* For the time being, [Slack](http://invite.chschtsch.ml/) is being used for project communication
|
||||||
* Feel free to post suggestions, changes ideas etc!
|
* Feel free to post suggestions, changes, ideas etc!
|
||||||
|
@@ -36,6 +36,7 @@ NewPipe does not use any Google framework libraries, or the YouTube API. It only
|
|||||||
* Open a video in Kodi
|
* Open a video in Kodi
|
||||||
* Show Next/Related videos
|
* Show Next/Related videos
|
||||||
* Search YouTube in a specific language
|
* Search YouTube in a specific language
|
||||||
|
* Orbot/Tor support (no streaming yet)
|
||||||
|
|
||||||
### Coming Features
|
### Coming Features
|
||||||
|
|
||||||
|
@@ -8,8 +8,8 @@ android {
|
|||||||
applicationId "org.schabi.newpipe"
|
applicationId "org.schabi.newpipe"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 10
|
versionCode 11
|
||||||
versionName "0.7.1"
|
versionName "0.7.2"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
@@ -35,4 +35,5 @@ dependencies {
|
|||||||
compile 'com.android.support:recyclerview-v7:23.1.1'
|
compile 'com.android.support:recyclerview-v7:23.1.1'
|
||||||
compile 'org.jsoup:jsoup:1.8.3'
|
compile 'org.jsoup:jsoup:1.8.3'
|
||||||
compile 'org.mozilla:rhino:1.7.7'
|
compile 'org.mozilla:rhino:1.7.7'
|
||||||
|
compile 'info.guardianproject.netcipher:netcipher:1.2'
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,89 @@
|
|||||||
|
package org.schabi.newpipe.services.youtube;
|
||||||
|
|
||||||
|
import android.test.AndroidTestCase;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.VideoPreviewInfo;
|
||||||
|
import org.schabi.newpipe.services.SearchEngine;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by the-scrabi on 29.12.15.
|
||||||
|
*
|
||||||
|
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||||
|
* YoutubeSearchEngineTest.java is part of NewPipe.
|
||||||
|
*
|
||||||
|
* NewPipe is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NewPipe is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class YoutubeSearchEngineTest extends AndroidTestCase {
|
||||||
|
private SearchEngine.Result result;
|
||||||
|
private ArrayList<String> suggestionReply;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() throws Exception{
|
||||||
|
super.setUp();
|
||||||
|
SearchEngine engine = new YoutubeSearchEngine();
|
||||||
|
result = engine.search("https://www.youtube.com/results?search_query=bla", 0, "de");
|
||||||
|
suggestionReply = engine.suggestionList("hello");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIfNoErrorOccur() {
|
||||||
|
assertEquals(result.errorMessage, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIfListIsNotEmpty() {
|
||||||
|
assertEquals(result.resultList.size() > 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testItemsHaveTitle() {
|
||||||
|
for(VideoPreviewInfo i : result.resultList) {
|
||||||
|
assertEquals(i.title.isEmpty(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testItemsHaveUploader() {
|
||||||
|
for(VideoPreviewInfo i : result.resultList) {
|
||||||
|
assertEquals(i.uploader.isEmpty(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testItemsHaveRightDuration() {
|
||||||
|
for(VideoPreviewInfo i : result.resultList) {
|
||||||
|
assertTrue(i.duration, i.duration.contains(":"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testItemsHaveRightThumbnail() {
|
||||||
|
for (VideoPreviewInfo i : result.resultList) {
|
||||||
|
assertTrue(i.thumbnail_url, i.thumbnail_url.contains("https://"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testItemsHaveRightVideoUrl() {
|
||||||
|
for (VideoPreviewInfo i : result.resultList) {
|
||||||
|
assertTrue(i.webpage_url, i.webpage_url.contains("https://"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIfSuggestionsAreReplied() {
|
||||||
|
assertEquals(suggestionReply.size() > 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIfSuggestionsAreValid() {
|
||||||
|
for(String s : suggestionReply) {
|
||||||
|
assertTrue(s, !s.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,100 @@
|
|||||||
|
package org.schabi.newpipe.services.youtube;
|
||||||
|
|
||||||
|
import android.test.AndroidTestCase;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.services.VideoInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by the-scrabi on 30.12.15.
|
||||||
|
*
|
||||||
|
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||||
|
* YoutubeVideoExtractorDefault.java is part of NewPipe.
|
||||||
|
*
|
||||||
|
* NewPipe is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NewPipe is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class YoutubeVideoExtractorDefaultTest extends AndroidTestCase {
|
||||||
|
private YoutubeVideoExtractor extractor;
|
||||||
|
|
||||||
|
public void setUp() {
|
||||||
|
extractor = new YoutubeVideoExtractor("https://www.youtube.com/watch?v=FmG385_uUys");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetErrorCode() {
|
||||||
|
assertEquals(extractor.getErrorCode(), VideoInfo.NO_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetErrorMessage() {
|
||||||
|
assertEquals(extractor.getErrorMessage(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetTimeStamp() {
|
||||||
|
assertTrue(Integer.toString(extractor.getTimeStamp()),
|
||||||
|
extractor.getTimeStamp() >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetTitle() {
|
||||||
|
assertTrue(!extractor.getTitle().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetDescription() {
|
||||||
|
assertTrue(extractor.getDescription() != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetUploader() {
|
||||||
|
assertTrue(!extractor.getUploader().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetLength() {
|
||||||
|
assertTrue(extractor.getLength() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetViews() {
|
||||||
|
assertTrue(extractor.getLength() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetUploadDate() {
|
||||||
|
assertTrue(extractor.getUploadDate().length() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetThumbnailUrl() {
|
||||||
|
assertTrue(extractor.getThumbnailUrl(),
|
||||||
|
extractor.getThumbnailUrl().contains("https://"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetUploaderThumbnailUrl() {
|
||||||
|
assertTrue(extractor.getUploaderThumbnailUrl(),
|
||||||
|
extractor.getUploaderThumbnailUrl().contains("https://"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetAudioStreams() {
|
||||||
|
for(VideoInfo.AudioStream s : extractor.getAudioStreams()) {
|
||||||
|
assertTrue(s.url,
|
||||||
|
s.url.contains("https://"));
|
||||||
|
assertTrue(s.bandwidth > 0);
|
||||||
|
assertTrue(s.samplingRate > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetVideoStreams() {
|
||||||
|
for(VideoInfo.VideoStream s : extractor.getVideoStreams()) {
|
||||||
|
assertTrue(s.url,
|
||||||
|
s.url.contains("https://"));
|
||||||
|
assertTrue(s.resolution.length() > 0);
|
||||||
|
assertTrue(Integer.toString(s.format),
|
||||||
|
0 <= s.format && s.format <= 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,59 @@
|
|||||||
|
package org.schabi.newpipe.services.youtube;
|
||||||
|
|
||||||
|
import android.test.AndroidTestCase;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.services.VideoInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by the-scrabi on 30.12.15.
|
||||||
|
*
|
||||||
|
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||||
|
* YoutubeVideoExtractorGema.java is part of NewPipe.
|
||||||
|
*
|
||||||
|
* NewPipe is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NewPipe is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// This class only works in Germany.
|
||||||
|
public class YoutubeVideoExtractorGemaTest extends AndroidTestCase {
|
||||||
|
|
||||||
|
// Deaktivate this Test Case bevore uploading it githup, otherwise CI will fail.
|
||||||
|
private static final boolean testActive = false;
|
||||||
|
|
||||||
|
|
||||||
|
private YoutubeVideoExtractor extractor;
|
||||||
|
|
||||||
|
public void setUp() {
|
||||||
|
if(testActive) {
|
||||||
|
extractor = new YoutubeVideoExtractor("https://www.youtube.com/watch?v=3O1_3zBUKM8");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetErrorCode() {
|
||||||
|
if(testActive) {
|
||||||
|
assertEquals(extractor.getErrorCode(), VideoInfo.ERROR_BLOCKED_BY_GEMA);
|
||||||
|
} else {
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetErrorMessage() {
|
||||||
|
if(testActive) {
|
||||||
|
assertTrue(extractor.getErrorMessage(),
|
||||||
|
extractor.getErrorMessage().contains("GEMA"));
|
||||||
|
} else {
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -7,6 +7,7 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
<application
|
<application
|
||||||
|
android:name=".App"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:logo="@mipmap/ic_launcher"
|
android:logo="@mipmap/ic_launcher"
|
||||||
@@ -83,7 +84,7 @@
|
|||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".SettingsActivity"
|
android:name=".SettingsActivity"
|
||||||
android:label="@string/title_activity_settings" >
|
android:label="@string/settings_activity_title" >
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".PanicResponderActivity"
|
android:name=".PanicResponderActivity"
|
||||||
|
@@ -16,6 +16,7 @@ import android.view.MenuInflater;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.services.MediaFormat;
|
||||||
import org.schabi.newpipe.services.VideoInfo;
|
import org.schabi.newpipe.services.VideoInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,8 +99,8 @@ class ActionBarHandler {
|
|||||||
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||||
String[] itemArray = new String[videoStreams.length];
|
String[] itemArray = new String[videoStreams.length];
|
||||||
String defaultResolution = defaultPreferences
|
String defaultResolution = defaultPreferences
|
||||||
.getString(activity.getString(R.string.defaultResolutionPreference),
|
.getString(activity.getString(R.string.default_resolution_key),
|
||||||
activity.getString(R.string.defaultResolutionListItem));
|
activity.getString(R.string.default_resolution_value));
|
||||||
int defaultResolutionPos = 0;
|
int defaultResolutionPos = 0;
|
||||||
|
|
||||||
for(int i = 0; i < videoStreams.length; i++) {
|
for(int i = 0; i < videoStreams.length; i++) {
|
||||||
@@ -123,7 +124,7 @@ class ActionBarHandler {
|
|||||||
// set audioStream
|
// set audioStream
|
||||||
audioStream = null;
|
audioStream = null;
|
||||||
String preferedFormat = defaultPreferences
|
String preferedFormat = defaultPreferences
|
||||||
.getString(activity.getString(R.string.defaultAudioFormatPreference), "webm");
|
.getString(activity.getString(R.string.default_audio_format_key), "webm");
|
||||||
if(preferedFormat.equals("webm")) {
|
if(preferedFormat.equals("webm")) {
|
||||||
for(VideoInfo.AudioStream s : audioStreams) {
|
for(VideoInfo.AudioStream s : audioStreams) {
|
||||||
if(s.format == MediaFormat.WEBMA.id) {
|
if(s.format == MediaFormat.WEBMA.id) {
|
||||||
@@ -157,7 +158,7 @@ class ActionBarHandler {
|
|||||||
MenuItem castItem = menu.findItem(R.id.action_play_with_kodi);
|
MenuItem castItem = menu.findItem(R.id.action_play_with_kodi);
|
||||||
|
|
||||||
castItem.setVisible(defaultPreferences
|
castItem.setVisible(defaultPreferences
|
||||||
.getBoolean(activity.getString(R.string.showPlayWithKodiPreference), false));
|
.getBoolean(activity.getString(R.string.show_play_with_kodi_key), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onItemSelected(MenuItem item) {
|
public boolean onItemSelected(MenuItem item) {
|
||||||
@@ -169,7 +170,7 @@ class ActionBarHandler {
|
|||||||
intent.setAction(Intent.ACTION_SEND);
|
intent.setAction(Intent.ACTION_SEND);
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, websiteUrl);
|
intent.putExtra(Intent.EXTRA_TEXT, websiteUrl);
|
||||||
intent.setType("text/plain");
|
intent.setType("text/plain");
|
||||||
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.shareDialogTitle)));
|
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.share_dialog_title)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case R.id.menu_item_openInBrowser: {
|
case R.id.menu_item_openInBrowser: {
|
||||||
@@ -209,7 +210,7 @@ class ActionBarHandler {
|
|||||||
// ----------- THE MAGIC MOMENT ---------------
|
// ----------- THE MAGIC MOMENT ---------------
|
||||||
if(!videoTitle.isEmpty()) {
|
if(!videoTitle.isEmpty()) {
|
||||||
if (PreferenceManager.getDefaultSharedPreferences(activity)
|
if (PreferenceManager.getDefaultSharedPreferences(activity)
|
||||||
.getBoolean(activity.getString(R.string.useExternalVideoPlayer), false)) {
|
.getBoolean(activity.getString(R.string.use_external_video_player_key), false)) {
|
||||||
|
|
||||||
// External Player
|
// External Player
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
@@ -225,13 +226,13 @@ class ActionBarHandler {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
builder.setMessage(R.string.noPlayerFound)
|
builder.setMessage(R.string.no_player_found)
|
||||||
.setPositiveButton(R.string.installStreamPlayer, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setAction(Intent.ACTION_VIEW);
|
intent.setAction(Intent.ACTION_VIEW);
|
||||||
intent.setData(Uri.parse(activity.getString(R.string.fdroidVLCurl)));
|
intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url)));
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -283,7 +284,7 @@ class ActionBarHandler {
|
|||||||
intent.setAction(Intent.ACTION_VIEW);
|
intent.setAction(Intent.ACTION_VIEW);
|
||||||
intent.setData(Uri.parse(websiteUrl));
|
intent.setData(Uri.parse(websiteUrl));
|
||||||
|
|
||||||
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.chooseBrowser)));
|
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.choose_browser)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,13 +298,13 @@ class ActionBarHandler {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
builder.setMessage(R.string.koreNotFound)
|
builder.setMessage(R.string.kore_not_found)
|
||||||
.setPositiveButton(R.string.installeKore, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setAction(Intent.ACTION_VIEW);
|
intent.setAction(Intent.ACTION_VIEW);
|
||||||
intent.setData(Uri.parse(activity.getString(R.string.fdroidKoreUrl)));
|
intent.setData(Uri.parse(activity.getString(R.string.fdroid_kore_url)));
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -321,7 +322,7 @@ class ActionBarHandler {
|
|||||||
public void playAudio() {
|
public void playAudio() {
|
||||||
|
|
||||||
boolean externalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity)
|
boolean externalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||||
.getBoolean(activity.getString(R.string.useExternalAudioPlayer), false);
|
.getBoolean(activity.getString(R.string.use_external_audio_player_key), false);
|
||||||
Intent intent;
|
Intent intent;
|
||||||
|
|
||||||
if (!externalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 18) {
|
if (!externalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 18) {
|
||||||
@@ -355,13 +356,13 @@ class ActionBarHandler {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
builder.setMessage(R.string.noPlayerFound)
|
builder.setMessage(R.string.no_player_found)
|
||||||
.setPositiveButton(R.string.installStreamPlayer, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setAction(Intent.ACTION_VIEW);
|
intent.setAction(Intent.ACTION_VIEW);
|
||||||
intent.setData(Uri.parse(activity.getString(R.string.fdroidVLCurl)));
|
intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url)));
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
71
app/src/main/java/org/schabi/newpipe/App.java
Normal file
71
app/src/main/java/org/schabi/newpipe/App.java
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import info.guardianproject.netcipher.NetCipher;
|
||||||
|
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
|
||||||
|
* App.java is part of NewPipe.
|
||||||
|
*
|
||||||
|
* NewPipe is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NewPipe is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class App extends Application {
|
||||||
|
|
||||||
|
private static boolean useTor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
if(prefs.getBoolean(getString(R.string.use_tor_key), false)) {
|
||||||
|
OrbotHelper.requestStartTor(this);
|
||||||
|
configureTor(true);
|
||||||
|
} else {
|
||||||
|
configureTor(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT REMOVE THIS FUNCTION!!!
|
||||||
|
// Otherwise downloadPathPreference has invalid value.
|
||||||
|
SettingsActivity.initSettings(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the proxy settings based on whether Tor should be enabled or not.
|
||||||
|
*/
|
||||||
|
static void configureTor(boolean enabled) {
|
||||||
|
useTor = enabled;
|
||||||
|
if (useTor) {
|
||||||
|
NetCipher.useTor();
|
||||||
|
} else {
|
||||||
|
NetCipher.setProxy(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void checkStartTor(Context context) {
|
||||||
|
if (useTor) {
|
||||||
|
OrbotHelper.requestStartTor(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isUsingTor() {
|
||||||
|
return useTor;
|
||||||
|
}
|
||||||
|
}
|
@@ -75,7 +75,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
Toast.makeText(this, R.string.backgroundPlayerStartPlayingToast,
|
Toast.makeText(this, R.string.background_player_playing_toast,
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
String source = intent.getDataString();
|
String source = intent.getDataString();
|
||||||
@@ -135,9 +135,6 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||||||
//so calling the blocking prepare() method should be ok
|
//so calling the blocking prepare() method should be ok
|
||||||
mediaPlayer.prepare();
|
mediaPlayer.prepare();
|
||||||
|
|
||||||
//alternatively:
|
|
||||||
//mediaPlayer.setOnPreparedListener(this);
|
|
||||||
//mediaPlayer.prepareAsync(); //prepare async to not block main thread
|
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
Log.e(TAG, "video source:" + source);
|
Log.e(TAG, "video source:" + source);
|
||||||
@@ -179,15 +176,6 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||||||
|
|
||||||
Notification note = buildNotification();
|
Notification note = buildNotification();
|
||||||
|
|
||||||
Intent openDetailView = new Intent(getApplicationContext(),
|
|
||||||
VideoItemDetailActivity.class);
|
|
||||||
openDetailView.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, serviceId);
|
|
||||||
openDetailView.putExtra(VideoItemDetailFragment.VIDEO_URL, webUrl);
|
|
||||||
openDetailView.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
note.contentIntent = PendingIntent.getActivity(getApplicationContext(),
|
|
||||||
noteID, openDetailView,
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
|
|
||||||
startForeground(noteID, note);
|
startForeground(noteID, note);
|
||||||
|
|
||||||
//currently decommissioned progressbar looping update code - works, but doesn't fit inside
|
//currently decommissioned progressbar looping update code - works, but doesn't fit inside
|
||||||
@@ -207,6 +195,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Handles button presses from the notification. */
|
||||||
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
@@ -217,7 +206,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||||||
mediaPlayer.pause();
|
mediaPlayer.pause();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//reacquire CPU lock after releasing it on pause
|
//reacquire CPU lock after auto-releasing it on pause
|
||||||
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
|
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
|
||||||
mediaPlayer.start();
|
mediaPlayer.start();
|
||||||
}
|
}
|
||||||
@@ -231,8 +220,9 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||||||
};
|
};
|
||||||
|
|
||||||
private void afterPlayCleanup() {
|
private void afterPlayCleanup() {
|
||||||
//noteBuilder.setProgress(0, 0, false);
|
|
||||||
//remove progress bar
|
//remove progress bar
|
||||||
|
//noteBuilder.setProgress(0, 0, false);
|
||||||
|
|
||||||
//remove notification
|
//remove notification
|
||||||
noteMgr.cancel(noteID);
|
noteMgr.cancel(noteID);
|
||||||
unregisterReceiver(broadcastReceiver);
|
unregisterReceiver(broadcastReceiver);
|
||||||
@@ -241,7 +231,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||||||
|
|
||||||
//release wifilock
|
//release wifilock
|
||||||
wifiLock.release();
|
wifiLock.release();
|
||||||
//remove foreground status of service; make us killable
|
//remove foreground status of service; make BackgroundPlayer killable
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
|
|
||||||
stopSelf();
|
stopSelf();
|
||||||
@@ -273,6 +263,13 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||||||
(R.drawable.ic_pause_white_24dp, "Pause", playPI).build();
|
(R.drawable.ic_pause_white_24dp, "Pause", playPI).build();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//build intent to return to video, on tapping notification
|
||||||
|
Intent openDetailView = new Intent(getApplicationContext(),
|
||||||
|
VideoItemDetailActivity.class);
|
||||||
|
openDetailView.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, serviceId);
|
||||||
|
openDetailView.putExtra(VideoItemDetailFragment.VIDEO_URL, webUrl);
|
||||||
|
openDetailView.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
|
||||||
noteBuilder
|
noteBuilder
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.setDeleteIntent(stopPI)
|
.setDeleteIntent(stopPI)
|
||||||
@@ -281,17 +278,22 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||||||
.setSmallIcon(R.drawable.ic_play_circle_filled_white_24dp)
|
.setSmallIcon(R.drawable.ic_play_circle_filled_white_24dp)
|
||||||
.setTicker(
|
.setTicker(
|
||||||
String.format(res.getString(
|
String.format(res.getString(
|
||||||
R.string.backgroundPlayerTickerText), title));
|
R.string.background_player_time_text), title))
|
||||||
|
.setContentIntent(PendingIntent.getActivity(getApplicationContext(),
|
||||||
|
noteID, openDetailView,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT));
|
||||||
|
|
||||||
|
|
||||||
if (android.os.Build.VERSION.SDK_INT < 21) {
|
if (android.os.Build.VERSION.SDK_INT < 21) {
|
||||||
|
|
||||||
NotificationCompat.Action playButton = new NotificationCompat.Action.Builder
|
NotificationCompat.Action playButton = new NotificationCompat.Action.Builder
|
||||||
(R.drawable.ic_play_arrow_white_48dp,
|
(R.drawable.ic_play_arrow_white_48dp,
|
||||||
res.getString(R.string.play), playPI).build();
|
res.getString(R.string.play_btn_text), playPI).build();
|
||||||
|
|
||||||
noteBuilder
|
noteBuilder
|
||||||
.setContentTitle(title)
|
.setContentTitle(title)
|
||||||
//really? Id like to put something more helpful here.
|
//really? Id like to put something more helpful here.
|
||||||
|
//was more of a placeholder than anything else. -medavox
|
||||||
//.setContentText("NewPipe is playing in the background")
|
//.setContentText("NewPipe is playing in the background")
|
||||||
.setContentText(channelName)
|
.setContentText(channelName)
|
||||||
//.setAutoCancel(!mediaPlayer.isPlaying())
|
//.setAutoCancel(!mediaPlayer.isPlaying())
|
||||||
@@ -303,6 +305,9 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||||||
//.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
//.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
//.setLargeIcon(cover)
|
//.setLargeIcon(cover)
|
||||||
|
|
||||||
|
//is wrapping this in an SDK version check really necessary,
|
||||||
|
// if we're using NotificationCompat?
|
||||||
|
// the compat libraries should handle this, right? -medavox
|
||||||
if (android.os.Build.VERSION.SDK_INT >= 16)
|
if (android.os.Build.VERSION.SDK_INT >= 16)
|
||||||
noteBuilder.setPriority(Notification.PRIORITY_LOW);
|
noteBuilder.setPriority(Notification.PRIORITY_LOW);
|
||||||
|
|
||||||
@@ -324,8 +329,10 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
|||||||
view.setOnClickPendingIntent(R.id.backgroundStop, stopPI);
|
view.setOnClickPendingIntent(R.id.backgroundStop, stopPI);
|
||||||
view.setOnClickPendingIntent(R.id.backgroundPlayPause, playPI);
|
view.setOnClickPendingIntent(R.id.backgroundPlayPause, playPI);
|
||||||
|
|
||||||
|
//possibly found the expandedView problem,
|
||||||
|
//but can't test it as I don't have a 5.0 device. -medavox
|
||||||
RemoteViews expandedView =
|
RemoteViews expandedView =
|
||||||
new RemoteViews(BuildConfig.APPLICATION_ID, R.layout.player_notification);
|
new RemoteViews(BuildConfig.APPLICATION_ID, R.layout.player_notification_expanded);
|
||||||
expandedView.setImageViewBitmap(R.id.backgroundCover, videoThumbnail);
|
expandedView.setImageViewBitmap(R.id.backgroundCover, videoThumbnail);
|
||||||
expandedView.setTextViewText(R.id.backgroundSongName, title);
|
expandedView.setTextViewText(R.id.backgroundSongName, title);
|
||||||
expandedView.setTextViewText(R.id.backgroundArtist, channelName);
|
expandedView.setTextViewText(R.id.backgroundArtist, channelName);
|
||||||
|
@@ -52,8 +52,8 @@ public class DownloadDialog extends DialogFragment {
|
|||||||
arguments = getArguments();
|
arguments = getArguments();
|
||||||
super.onCreateDialog(savedInstanceState);
|
super.onCreateDialog(savedInstanceState);
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
builder.setTitle(R.string.downloadDialogTitle)
|
builder.setTitle(R.string.download_dialog_title)
|
||||||
.setItems(R.array.downloadOptions, new DialogInterface.OnClickListener() {
|
.setItems(R.array.download_options, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
Context context = getActivity();
|
Context context = getActivity();
|
||||||
@@ -61,36 +61,43 @@ public class DownloadDialog extends DialogFragment {
|
|||||||
String suffix = "";
|
String suffix = "";
|
||||||
String title = arguments.getString(TITLE);
|
String title = arguments.getString(TITLE);
|
||||||
String url = "";
|
String url = "";
|
||||||
String downloadFolder = "Download";
|
String downloadFolder = Environment.DIRECTORY_DOWNLOADS;
|
||||||
switch(which) {
|
switch(which) {
|
||||||
case 0: // Video
|
case 0: // Video
|
||||||
suffix = arguments.getString(FILE_SUFFIX_VIDEO);
|
suffix = arguments.getString(FILE_SUFFIX_VIDEO);
|
||||||
url = arguments.getString(VIDEO_URL);
|
url = arguments.getString(VIDEO_URL);
|
||||||
downloadFolder = "Movies";
|
downloadFolder = Environment.DIRECTORY_MOVIES;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
suffix = arguments.getString(FILE_SUFFIX_AUDIO);
|
suffix = arguments.getString(FILE_SUFFIX_AUDIO);
|
||||||
url = arguments.getString(AUDIO_URL);
|
url = arguments.getString(AUDIO_URL);
|
||||||
downloadFolder = "Music";
|
downloadFolder = Environment.DIRECTORY_MUSIC;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.d(TAG, "lolz");
|
Log.d(TAG, "lolz");
|
||||||
}
|
}
|
||||||
//to avoid hard-coded string like "/storage/emulated/0/Movies"
|
//to avoid hard-coded string like "/storage/emulated/0/Movies"
|
||||||
String downloadPath = prefs.getString(getString(R.string.downloadPathPreference),
|
String downloadPath = prefs.getString(getString(R.string.download_path_key),
|
||||||
Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + downloadFolder);
|
Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + downloadFolder);
|
||||||
final File dir = new File(downloadPath);
|
final File dir = new File(downloadPath);
|
||||||
if(!dir.exists()) {
|
if(!dir.exists()) {
|
||||||
boolean mkdir = dir.mkdir(); //attempt to create directory
|
//attempt to create directory
|
||||||
|
boolean mkdir = dir.mkdir();
|
||||||
if(!mkdir && !dir.isDirectory()) {
|
if(!mkdir && !dir.isDirectory()) {
|
||||||
Log.e(TAG, "Cant' create directory named " + dir.toString());
|
Log.e(TAG, "Cant' create directory named " + dir.toString());
|
||||||
//TODO notify user "download directory should be changed" ?
|
//TODO notify user "download directory should be changed" ?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String saveFilePath = dir + "/" + title + suffix;
|
||||||
|
if (App.isUsingTor()) {
|
||||||
|
// if using Tor, do not use DownloadManager because the proxy cannot be set
|
||||||
|
Downloader.downloadFile(getContext(), url, saveFilePath);
|
||||||
|
} else {
|
||||||
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||||
DownloadManager.Request request = new DownloadManager.Request(
|
DownloadManager.Request request = new DownloadManager.Request(
|
||||||
Uri.parse(url));
|
Uri.parse(url));
|
||||||
request.setDestinationUri(Uri.fromFile(new File(dir + "/" + title + suffix)));
|
request.setDestinationUri(Uri.fromFile(new File(saveFilePath)));
|
||||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||||
try {
|
try {
|
||||||
dm.enqueue(request);
|
dm.enqueue(request);
|
||||||
@@ -98,6 +105,7 @@ public class DownloadDialog extends DialogFragment {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return builder.create();
|
return builder.create();
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,30 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.support.v4.app.NotificationCompat;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
|
||||||
|
import info.guardianproject.netcipher.NetCipher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Christian Schabesberger on 14.08.15.
|
* Created by Christian Schabesberger on 14.08.15.
|
||||||
*
|
*
|
||||||
@@ -28,7 +46,7 @@ import java.net.UnknownHostException;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class Downloader {
|
public class Downloader {
|
||||||
|
public static final String TAG = "Downloader";
|
||||||
private static final String USER_AGENT = "Mozilla/5.0";
|
private static final String USER_AGENT = "Mozilla/5.0";
|
||||||
|
|
||||||
/**Download the text file at the supplied URL as in download(String),
|
/**Download the text file at the supplied URL as in download(String),
|
||||||
@@ -40,7 +58,7 @@ public class Downloader {
|
|||||||
String ret = "";
|
String ret = "";
|
||||||
try {
|
try {
|
||||||
URL url = new URL(siteUrl);
|
URL url = new URL(siteUrl);
|
||||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
|
||||||
con.setRequestProperty("Accept-Language", language);
|
con.setRequestProperty("Accept-Language", language);
|
||||||
ret = dl(con);
|
ret = dl(con);
|
||||||
}
|
}
|
||||||
@@ -49,8 +67,9 @@ public class Downloader {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Common functionality between download(String url) and download(String url, String language)*/
|
/**Common functionality between download(String url) and download(String url, String language)*/
|
||||||
private static String dl(HttpURLConnection con) throws IOException {
|
private static String dl(HttpsURLConnection con) throws IOException {
|
||||||
StringBuilder response = new StringBuilder();
|
StringBuilder response = new StringBuilder();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -84,7 +103,7 @@ public class Downloader {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
URL url = new URL(siteUrl);
|
URL url = new URL(siteUrl);
|
||||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
HttpsURLConnection con = NetCipher.getHttpsURLConnection(url);
|
||||||
ret = dl(con);
|
ret = dl(con);
|
||||||
}
|
}
|
||||||
catch(Exception e) {
|
catch(Exception e) {
|
||||||
@@ -93,4 +112,92 @@ public class Downloader {
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads a file from a URL in the background using an {@link AsyncTask}.
|
||||||
|
*
|
||||||
|
* @param fileURL HTTP URL of the file to be downloaded
|
||||||
|
* @param saveFilePath path of the directory to save the file
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static void downloadFile(final Context context, final String fileURL, final String saveFilePath) {
|
||||||
|
new AsyncTask<Void, Integer, Void>() {
|
||||||
|
|
||||||
|
private NotificationManager nm;
|
||||||
|
private NotificationCompat.Builder builder;
|
||||||
|
private int notifyId = 0x1234;
|
||||||
|
private int fileSize = 0xffffffff;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
super.onPreExecute();
|
||||||
|
nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
Drawable icon = context.getResources().getDrawable(R.mipmap.ic_launcher);
|
||||||
|
builder = new NotificationCompat.Builder(context)
|
||||||
|
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||||
|
.setLargeIcon(((BitmapDrawable) icon).getBitmap())
|
||||||
|
.setContentTitle(saveFilePath.substring(saveFilePath.lastIndexOf('/') + 1))
|
||||||
|
.setContentText(saveFilePath)
|
||||||
|
.setProgress(fileSize, 0, false);
|
||||||
|
nm.notify(notifyId, builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... voids) {
|
||||||
|
HttpsURLConnection con = null;
|
||||||
|
try {
|
||||||
|
con = NetCipher.getHttpsURLConnection(fileURL);
|
||||||
|
int responseCode = con.getResponseCode();
|
||||||
|
|
||||||
|
// always check HTTP response code first
|
||||||
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||||
|
fileSize = con.getContentLength();
|
||||||
|
InputStream inputStream = new BufferedInputStream(con.getInputStream());
|
||||||
|
FileOutputStream outputStream = new FileOutputStream(saveFilePath);
|
||||||
|
|
||||||
|
int bufferSize = 8192;
|
||||||
|
int downloaded = 0;
|
||||||
|
|
||||||
|
int bytesRead = -1;
|
||||||
|
byte[] buffer = new byte[bufferSize];
|
||||||
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
|
outputStream.write(buffer, 0, bytesRead);
|
||||||
|
downloaded += bytesRead;
|
||||||
|
if (downloaded % 50000 < bufferSize) {
|
||||||
|
publishProgress(downloaded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outputStream.close();
|
||||||
|
inputStream.close();
|
||||||
|
publishProgress(bufferSize);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "No file to download. Server replied HTTP code: " + responseCode);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (con != null) {
|
||||||
|
con.disconnect();
|
||||||
|
con = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onProgressUpdate(Integer... progress) {
|
||||||
|
builder.setProgress(fileSize, progress[0], false);
|
||||||
|
nm.notify(notifyId, builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void aVoid) {
|
||||||
|
super.onPostExecute(aVoid);
|
||||||
|
nm.cancel(notifyId);
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,24 @@ import android.content.Intent;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
|
||||||
|
* ExitActivity.java is part of NewPipe.
|
||||||
|
*
|
||||||
|
* NewPipe is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NewPipe is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
public class ExitActivity extends Activity {
|
public class ExitActivity extends Activity {
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
@@ -15,6 +14,22 @@ import java.util.Locale;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by chschtsch on 12/29/15.
|
* Created by chschtsch on 12/29/15.
|
||||||
|
*
|
||||||
|
* Copyright (C) Gregory Arkhipov 2015
|
||||||
|
* Localization.java is part of NewPipe.
|
||||||
|
*
|
||||||
|
* NewPipe is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NewPipe is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Localization {
|
public class Localization {
|
||||||
@@ -22,7 +37,8 @@ public class Localization {
|
|||||||
public static Locale getPreferredLocale(Context context) {
|
public static Locale getPreferredLocale(Context context) {
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
|
||||||
String languageCode = sp.getString(String.valueOf(R.string.searchLanguage), "en");
|
String languageCode = sp.getString(String.valueOf(R.string.search_language_key),
|
||||||
|
context.getString(R.string.default_language_value));
|
||||||
|
|
||||||
if(languageCode.length() == 2) {
|
if(languageCode.length() == 2) {
|
||||||
return new Locale(languageCode);
|
return new Locale(languageCode);
|
||||||
@@ -39,7 +55,7 @@ public class Localization {
|
|||||||
Locale locale = getPreferredLocale(context);
|
Locale locale = getPreferredLocale(context);
|
||||||
|
|
||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
String viewsString = res.getString(R.string.viewCountText);
|
String viewsString = res.getString(R.string.view_count_text);
|
||||||
|
|
||||||
NumberFormat nf = NumberFormat.getInstance(locale);
|
NumberFormat nf = NumberFormat.getInstance(locale);
|
||||||
String formattedViewCount = nf.format(viewCount);
|
String formattedViewCount = nf.format(viewCount);
|
||||||
@@ -69,7 +85,7 @@ public class Localization {
|
|||||||
|
|
||||||
public static String localizeDate(String date, Context context) {
|
public static String localizeDate(String date, Context context) {
|
||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
String dateString = res.getString(R.string.uploadDateText);
|
String dateString = res.getString(R.string.upload_date_text);
|
||||||
|
|
||||||
String formattedDate = formatDate(date, context);
|
String formattedDate = formatDate(date, context);
|
||||||
return String.format(dateString, formattedDate);
|
return String.format(dateString, formattedDate);
|
||||||
|
@@ -7,6 +7,24 @@ import android.content.Intent;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
|
||||||
|
* PanicResponderActivity.java is part of NewPipe.
|
||||||
|
*
|
||||||
|
* NewPipe is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NewPipe is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
public class PanicResponderActivity extends Activity {
|
public class PanicResponderActivity extends Activity {
|
||||||
|
|
||||||
public static final String PANIC_TRIGGER_ACTION = "info.guardianproject.panic.action.TRIGGER";
|
public static final String PANIC_TRIGGER_ACTION = "info.guardianproject.panic.action.TRIGGER";
|
||||||
|
@@ -187,6 +187,18 @@ public class PlayVideoActivity extends AppCompatActivity {
|
|||||||
videoView.pause();
|
videoView.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
App.checkStartTor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
prefs = getPreferences(Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
int id = item.getItemId();
|
int id = item.getItemId();
|
||||||
@@ -199,7 +211,7 @@ public class PlayVideoActivity extends AppCompatActivity {
|
|||||||
intent.setAction(Intent.ACTION_SEND);
|
intent.setAction(Intent.ACTION_SEND);
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, videoUrl);
|
intent.putExtra(Intent.EXTRA_TEXT, videoUrl);
|
||||||
intent.setType("text/plain");
|
intent.setType("text/plain");
|
||||||
startActivity(Intent.createChooser(intent, getString(R.string.shareDialogTitle)));
|
startActivity(Intent.createChooser(intent, getString(R.string.share_dialog_title)));
|
||||||
break;
|
break;
|
||||||
case R.id.menu_item_screen_rotation:
|
case R.id.menu_item_screen_rotation:
|
||||||
toggleOrientation();
|
toggleOrientation();
|
||||||
|
@@ -1,9 +1,18 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.preference.CheckBoxPreference;
|
||||||
|
import android.preference.EditTextPreference;
|
||||||
|
import android.preference.ListPreference;
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
import android.preference.PreferenceFragment;
|
import android.preference.PreferenceFragment;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.LayoutRes;
|
import android.support.annotation.LayoutRes;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
@@ -13,6 +22,8 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Christian Schabesberger on 31.08.15.
|
* Created by Christian Schabesberger on 31.08.15.
|
||||||
*
|
*
|
||||||
@@ -35,6 +46,7 @@ import android.view.ViewGroup;
|
|||||||
|
|
||||||
public class SettingsActivity extends PreferenceActivity {
|
public class SettingsActivity extends PreferenceActivity {
|
||||||
|
|
||||||
|
private static final int REQUEST_INSTALL_ORBOT = 0x1234;
|
||||||
private AppCompatDelegate mDelegate = null;
|
private AppCompatDelegate mDelegate = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -52,11 +64,99 @@ public class SettingsActivity extends PreferenceActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class SettingsFragment extends PreferenceFragment{
|
public static class SettingsFragment extends PreferenceFragment{
|
||||||
|
SharedPreferences.OnSharedPreferenceChangeListener prefListener;
|
||||||
|
|
||||||
|
// get keys
|
||||||
|
String DEFAULT_RESOLUTION_PREFERENCE;
|
||||||
|
String DEFAULT_AUDIO_FORMAT_PREFERENCE;
|
||||||
|
String SEARCH_LANGUAGE_PREFERENCE;
|
||||||
|
String DOWNLOAD_PATH_PREFERENCE;
|
||||||
|
String USE_TOR_KEY;
|
||||||
|
|
||||||
|
private ListPreference defaultResolutionPreference;
|
||||||
|
private ListPreference defaultAudioFormatPreference;
|
||||||
|
private ListPreference searchLanguagePreference;
|
||||||
|
private EditTextPreference downloadPathPreference;
|
||||||
|
private CheckBoxPreference useTorCheckBox;
|
||||||
|
private SharedPreferences defaultPreferences;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
addPreferencesFromResource(R.xml.settings_screen);
|
addPreferencesFromResource(R.xml.settings);
|
||||||
|
|
||||||
|
final Activity activity = getActivity();
|
||||||
|
|
||||||
|
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||||
|
|
||||||
|
// get keys
|
||||||
|
DEFAULT_RESOLUTION_PREFERENCE =getString(R.string.default_resolution_key);
|
||||||
|
DEFAULT_AUDIO_FORMAT_PREFERENCE =getString(R.string.default_audio_format_key);
|
||||||
|
SEARCH_LANGUAGE_PREFERENCE =getString(R.string.search_language_key);
|
||||||
|
DOWNLOAD_PATH_PREFERENCE = getString(R.string.download_path_key);
|
||||||
|
USE_TOR_KEY = getString(R.string.use_tor_key);
|
||||||
|
|
||||||
|
// get pref objects
|
||||||
|
defaultResolutionPreference =
|
||||||
|
(ListPreference) findPreference(DEFAULT_RESOLUTION_PREFERENCE);
|
||||||
|
defaultAudioFormatPreference =
|
||||||
|
(ListPreference) findPreference(DEFAULT_AUDIO_FORMAT_PREFERENCE);
|
||||||
|
searchLanguagePreference =
|
||||||
|
(ListPreference) findPreference(SEARCH_LANGUAGE_PREFERENCE);
|
||||||
|
downloadPathPreference =
|
||||||
|
(EditTextPreference) findPreference(DOWNLOAD_PATH_PREFERENCE);
|
||||||
|
useTorCheckBox = (CheckBoxPreference) findPreference(USE_TOR_KEY);
|
||||||
|
|
||||||
|
prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
||||||
|
String key) {
|
||||||
|
Activity a = getActivity();
|
||||||
|
updateSummary();
|
||||||
|
|
||||||
|
if (defaultPreferences.getBoolean(USE_TOR_KEY, false)) {
|
||||||
|
if (OrbotHelper.isOrbotInstalled(a)) {
|
||||||
|
App.configureTor(true);
|
||||||
|
OrbotHelper.requestStartTor(a);
|
||||||
|
} else {
|
||||||
|
Intent intent = OrbotHelper.getOrbotInstallIntent(a);
|
||||||
|
a.startActivityForResult(intent, REQUEST_INSTALL_ORBOT);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
App.configureTor(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
defaultPreferences.registerOnSharedPreferenceChangeListener(prefListener);
|
||||||
|
|
||||||
|
updateSummary();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is used to show the status of some preference in the description
|
||||||
|
private void updateSummary() {
|
||||||
|
defaultResolutionPreference.setSummary(
|
||||||
|
defaultPreferences.getString(DEFAULT_RESOLUTION_PREFERENCE,
|
||||||
|
getString(R.string.default_resolution_value)));
|
||||||
|
defaultAudioFormatPreference.setSummary(
|
||||||
|
defaultPreferences.getString(DEFAULT_AUDIO_FORMAT_PREFERENCE,
|
||||||
|
getString(R.string.default_audio_format_value)));
|
||||||
|
searchLanguagePreference.setSummary(
|
||||||
|
defaultPreferences.getString(SEARCH_LANGUAGE_PREFERENCE,
|
||||||
|
getString(R.string.default_language_value)));
|
||||||
|
downloadPathPreference.setSummary(
|
||||||
|
defaultPreferences.getString(DOWNLOAD_PATH_PREFERENCE,
|
||||||
|
getString(R.string.download_path_summary)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
// try to start tor regardless of resultCode since clicking back after
|
||||||
|
// installing the app does not necessarily return RESULT_OK
|
||||||
|
App.configureTor(requestCode == REQUEST_INSTALL_ORBOT
|
||||||
|
&& OrbotHelper.requestStartTor(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -144,4 +244,17 @@ public class SettingsActivity extends PreferenceActivity {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void initSettings(Context context) {
|
||||||
|
PreferenceManager.setDefaultValues(context, R.xml.settings, false);
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
if(sp.getString(context.getString(R.string.download_path_key), "").isEmpty()){
|
||||||
|
SharedPreferences.Editor spEditor = sp.edit();
|
||||||
|
String newPipeDownloadStorage =
|
||||||
|
Environment.getExternalStorageDirectory().getAbsolutePath() + "/NewPipe";
|
||||||
|
spEditor.putString(context.getString(R.string.download_path_key)
|
||||||
|
, newPipeDownloadStorage);
|
||||||
|
spEditor.apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -80,7 +80,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(currentStreamingService == -1) {
|
if(currentStreamingService == -1) {
|
||||||
Toast.makeText(this, R.string.urlNotSupportedText, Toast.LENGTH_LONG)
|
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
//arguments.putString(VideoItemDetailFragment.VIDEO_URL,
|
//arguments.putString(VideoItemDetailFragment.VIDEO_URL,
|
||||||
@@ -89,7 +89,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY,
|
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY,
|
||||||
PreferenceManager.getDefaultSharedPreferences(this)
|
PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
.getBoolean(getString(R.string.autoPlayThroughIntent), false));
|
.getBoolean(getString(R.string.autoplay_through_intent_key), false));
|
||||||
} else {
|
} else {
|
||||||
videoUrl = getIntent().getStringExtra(VideoItemDetailFragment.VIDEO_URL);
|
videoUrl = getIntent().getStringExtra(VideoItemDetailFragment.VIDEO_URL);
|
||||||
currentStreamingService = getIntent().getIntExtra(VideoItemDetailFragment.STREAMING_SERVICE, -1);
|
currentStreamingService = getIntent().getIntExtra(VideoItemDetailFragment.STREAMING_SERVICE, -1);
|
||||||
@@ -113,6 +113,12 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
|||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
App.checkStartTor(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl);
|
outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl);
|
||||||
|
@@ -302,7 +302,7 @@ public class VideoItemDetailFragment extends Fragment {
|
|||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setAction(Intent.ACTION_VIEW);
|
intent.setAction(Intent.ACTION_VIEW);
|
||||||
intent.setData(Uri.parse(activity.getString(R.string.c3sUrl)));
|
intent.setData(Uri.parse(activity.getString(R.string.c3s_url)));
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -345,7 +345,7 @@ public class VideoItemDetailFragment extends Fragment {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
activity = (AppCompatActivity) getActivity();
|
activity = (AppCompatActivity) getActivity();
|
||||||
showNextVideoItem = PreferenceManager.getDefaultSharedPreferences(getActivity())
|
showNextVideoItem = PreferenceManager.getDefaultSharedPreferences(getActivity())
|
||||||
.getBoolean(activity.getString(R.string.showNextVideo), true);
|
.getBoolean(activity.getString(R.string.show_next_video_key), true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -172,7 +172,13 @@ public class VideoItemListActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PreferenceManager.setDefaultValues(this, R.xml.settings_screen, false);
|
PreferenceManager.setDefaultValues(this, R.xml.settings, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
App.checkStartTor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -66,6 +66,9 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
|
|
||||||
private View footer;
|
private View footer;
|
||||||
|
|
||||||
|
// used to suppress request for loading a new page while another page is already loading.
|
||||||
|
private boolean loadingNextPage = true;
|
||||||
|
|
||||||
private class ResultRunnable implements Runnable {
|
private class ResultRunnable implements Runnable {
|
||||||
private final SearchEngine.Result result;
|
private final SearchEngine.Result result;
|
||||||
private final int requestId;
|
private final int requestId;
|
||||||
@@ -76,6 +79,9 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
updateListOnResult(result, requestId);
|
updateListOnResult(result, requestId);
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= 19) {
|
||||||
|
getListView().removeFooterView(footer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +90,7 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
private final String query;
|
private final String query;
|
||||||
private final int page;
|
private final int page;
|
||||||
final Handler h = new Handler();
|
final Handler h = new Handler();
|
||||||
private volatile boolean run = true;
|
private volatile boolean runs = true;
|
||||||
private final int requestId;
|
private final int requestId;
|
||||||
public SearchRunnable(SearchEngine engine, String query, int page, int requestId) {
|
public SearchRunnable(SearchEngine engine, String query, int page, int requestId) {
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
@@ -93,17 +99,18 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
this.requestId = requestId;
|
this.requestId = requestId;
|
||||||
}
|
}
|
||||||
void terminate() {
|
void terminate() {
|
||||||
run = false;
|
runs = false;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
String searchLanguageKey = getContext().getString(R.string.searchLanguage);
|
String searchLanguageKey = getContext().getString(R.string.search_language_key);
|
||||||
String searchLanguage = sp.getString(searchLanguageKey, "en");
|
String searchLanguage = sp.getString(searchLanguageKey,
|
||||||
|
getString(R.string.default_language_value));
|
||||||
SearchEngine.Result result = engine.search(query, page, searchLanguage);
|
SearchEngine.Result result = engine.search(query, page, searchLanguage);
|
||||||
Log.i(TAG, "language code passed:\""+searchLanguage+"\"");
|
Log.i(TAG, "language code passed:\""+searchLanguage+"\"");
|
||||||
if(run) {
|
if(runs) {
|
||||||
h.post(new ResultRunnable(result, requestId));
|
h.post(new ResultRunnable(result, requestId));
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
@@ -111,19 +118,11 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
h.post(new Runnable() {
|
h.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Toast.makeText(getActivity(), "Network Error", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.network_error),
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
getActivity().runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= 19) {
|
|
||||||
getListView().removeFooterView(footer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,8 +202,9 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void nextPage() {
|
private void nextPage() {
|
||||||
|
loadingNextPage = true;
|
||||||
lastPage++;
|
lastPage++;
|
||||||
Log.d(TAG, getString(R.string.searchPage) + Integer.toString(lastPage));
|
Log.d(TAG, getString(R.string.search_page) + Integer.toString(lastPage));
|
||||||
startSearch(query, lastPage);
|
startSearch(query, lastPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
Toast.makeText(getActivity(), result.errorMessage, Toast.LENGTH_LONG).show();
|
Toast.makeText(getActivity(), result.errorMessage, Toast.LENGTH_LONG).show();
|
||||||
} else {
|
} else {
|
||||||
if (!result.suggestion.isEmpty()) {
|
if (!result.suggestion.isEmpty()) {
|
||||||
Toast.makeText(getActivity(), getString(R.string.didYouMean) + result.suggestion + " ?",
|
Toast.makeText(getActivity(), getString(R.string.did_you_mean) + result.suggestion + " ?",
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
updateList(result.resultList);
|
updateList(result.resultList);
|
||||||
@@ -248,6 +248,8 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
Log.w(TAG, "Trying to set value while activity doesn't exist anymore.");
|
Log.w(TAG, "Trying to set value while activity doesn't exist anymore.");
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
loadingNextPage = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +299,8 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
list = getListView();
|
list = getListView();
|
||||||
videoListAdapter = new VideoListAdapter(getActivity(), this);
|
videoListAdapter = new VideoListAdapter(getActivity(), this);
|
||||||
footer = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.paginate_footer, null, false);
|
footer = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE))
|
||||||
|
.inflate(R.layout.paginate_footer, null, false);
|
||||||
|
|
||||||
|
|
||||||
setListAdapter(videoListAdapter);
|
setListAdapter(videoListAdapter);
|
||||||
@@ -318,13 +321,15 @@ public class VideoItemListFragment extends ListFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
public void onScroll(AbsListView view, int firstVisibleItem,
|
||||||
|
int visibleItemCount, int totalItemCount) {
|
||||||
if (mode != PRESENT_VIDEOS_MODE
|
if (mode != PRESENT_VIDEOS_MODE
|
||||||
&& list.getChildAt(0) != null
|
&& list.getChildAt(0) != null
|
||||||
&& list.getLastVisiblePosition() == list.getAdapter().getCount() - 1
|
&& list.getLastVisiblePosition() == list.getAdapter().getCount() - 1
|
||||||
&& list.getChildAt(list.getChildCount() - 1).getBottom() <= list.getHeight()) {
|
&& list.getChildAt(list.getChildCount() - 1).getBottom() <= list.getHeight()) {
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
if ((time - lastScrollDate) > 200) {
|
if ((time - lastScrollDate) > 200
|
||||||
|
&& !loadingNextPage) {
|
||||||
lastScrollDate = time;
|
lastScrollDate = time;
|
||||||
getListView().addFooterView(footer);
|
getListView().addFooterView(footer);
|
||||||
nextPage();
|
nextPage();
|
||||||
|
@@ -99,7 +99,7 @@ class VideoListAdapter extends BaseAdapter {
|
|||||||
convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position), context);
|
convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position), context);
|
||||||
|
|
||||||
if(listView.isItemChecked(position)) {
|
if(listView.isItemChecked(position)) {
|
||||||
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.primaryColorYoutube));
|
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.light_youtube_primary_color));
|
||||||
} else {
|
} else {
|
||||||
convertView.setBackgroundColor(0);
|
convertView.setBackgroundColor(0);
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe.services;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Adam Howard on 08/11/15.
|
* Created by Adam Howard on 08/11/15.
|
@@ -106,20 +106,23 @@ public abstract class VideoExtractor {
|
|||||||
return videoInfo;
|
return videoInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//todo: add licence field
|
||||||
|
public abstract int getErrorCode();
|
||||||
|
public abstract String getErrorMessage();
|
||||||
|
|
||||||
protected abstract int getErrorCode();
|
//todo: remove these functions, or make them static, otherwise its useles, to have them here
|
||||||
protected abstract String getErrorMessage();
|
public abstract String getVideoUrl(String videoId);
|
||||||
protected abstract String getVideoUrl(String videoId);
|
public abstract String getVideoId(String siteUrl);
|
||||||
protected abstract String getVideoId(String siteUrl);
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
protected abstract int getTimeStamp();
|
public abstract int getTimeStamp();
|
||||||
protected abstract String getTitle();
|
public abstract String getTitle();
|
||||||
protected abstract String getDescription();
|
public abstract String getDescription();
|
||||||
protected abstract String getUploader();
|
public abstract String getUploader();
|
||||||
protected abstract int getLength();
|
public abstract int getLength();
|
||||||
protected abstract long getViews();
|
public abstract long getViews();
|
||||||
protected abstract String getUploadDate();
|
public abstract String getUploadDate();
|
||||||
protected abstract String getThumbnailUrl();
|
public abstract String getThumbnailUrl();
|
||||||
protected abstract String getUploaderThumbnailUrl();
|
public abstract String getUploaderThumbnailUrl();
|
||||||
protected abstract VideoInfo.AudioStream[] getAudioStreams();
|
public abstract VideoInfo.AudioStream[] getAudioStreams();
|
||||||
protected abstract VideoInfo.VideoStream[] getVideoStreams();
|
public abstract VideoInfo.VideoStream[] getVideoStreams();
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,7 @@ import org.mozilla.javascript.Function;
|
|||||||
import org.mozilla.javascript.ScriptableObject;
|
import org.mozilla.javascript.ScriptableObject;
|
||||||
import org.schabi.newpipe.Downloader;
|
import org.schabi.newpipe.Downloader;
|
||||||
import org.schabi.newpipe.services.VideoExtractor;
|
import org.schabi.newpipe.services.VideoExtractor;
|
||||||
import org.schabi.newpipe.MediaFormat;
|
import org.schabi.newpipe.services.MediaFormat;
|
||||||
import org.schabi.newpipe.services.VideoInfo;
|
import org.schabi.newpipe.services.VideoInfo;
|
||||||
import org.schabi.newpipe.VideoPreviewInfo;
|
import org.schabi.newpipe.VideoPreviewInfo;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
android:id="@+id/videoitem_detail">
|
android:id="@+id/videoitem_detail">
|
||||||
|
|
||||||
<ImageView android:id="@+id/detailThumbnailView"
|
<ImageView android:id="@+id/detailThumbnailView"
|
||||||
android:contentDescription="@string/detailThumbnailViewDescription"
|
android:contentDescription="@string/detail_thumbnail_view_description"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
app:backgroundTint="@color/primaryColorYoutube"
|
app:backgroundTint="@color/light_youtube_primary_color"
|
||||||
android:src="@drawable/ic_play_arrow_black"
|
android:src="@drawable/ic_play_arrow_black"
|
||||||
android:layout_margin="@dimen/video_item_detail_play_fab_margin"/>
|
android:layout_margin="@dimen/video_item_detail_play_fab_margin"/>
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="@dimen/video_item_detail_info_text_padding"
|
android:padding="@dimen/video_item_detail_info_text_padding"
|
||||||
android:layout_below="@id/detailVideoThumbnailWindowLayout"
|
android:layout_below="@id/detailVideoThumbnailWindowLayout"
|
||||||
android:background="@color/background_gray">
|
android:background="@color/light_background_color">
|
||||||
|
|
||||||
<TextView android:id="@+id/detailVideoTitleView"
|
<TextView android:id="@+id/detailVideoTitleView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
tools:ignore="RtlHardcoded" />
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
<ImageView android:id="@+id/detailUploaderThumbnailView"
|
<ImageView android:id="@+id/detailUploaderThumbnailView"
|
||||||
android:contentDescription="@string/detailUploaderThumbnailViewDescription"
|
android:contentDescription="@string/detail_uploader_thumbnail_view_description"
|
||||||
android:layout_width="@dimen/video_item_detail_uploader_image_size"
|
android:layout_width="@dimen/video_item_detail_uploader_image_size"
|
||||||
android:layout_height="@dimen/video_item_detail_uploader_image_size"
|
android:layout_height="@dimen/video_item_detail_uploader_image_size"
|
||||||
android:layout_below="@id/detailVideoTitleView"
|
android:layout_below="@id/detailVideoTitleView"
|
||||||
@@ -123,7 +123,7 @@
|
|||||||
tools:ignore="RtlHardcoded" />
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
<ImageView android:id="@+id/detailThumbsDownImgView"
|
<ImageView android:id="@+id/detailThumbsDownImgView"
|
||||||
android:contentDescription="@string/detailThumbsDownImgViewDescription"
|
android:contentDescription="@string/detail_dislikes_img_view_description"
|
||||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||||
android:layout_below="@id/detailViewCountView"
|
android:layout_below="@id/detailViewCountView"
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
tools:ignore="RtlHardcoded" />
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
<ImageView android:id="@+id/detailThumbsUpImgView"
|
<ImageView android:id="@+id/detailThumbsUpImgView"
|
||||||
android:contentDescription="@string/detailThumbsUpImgViewDescription"
|
android:contentDescription="@string/detail_likes_img_view_description"
|
||||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||||
android:layout_below="@id/detailViewCountView"
|
android:layout_below="@id/detailViewCountView"
|
||||||
@@ -186,7 +186,7 @@
|
|||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:textSize="@dimen/video_item_detail_next_text_size"
|
android:textSize="@dimen/video_item_detail_next_text_size"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:text="@string/nextVideoTitle"
|
android:text="@string/next_video_title"
|
||||||
android:textAllCaps="true" />
|
android:textAllCaps="true" />
|
||||||
|
|
||||||
<RelativeLayout android:id="@+id/detailNextVidButtonAndContentLayout"
|
<RelativeLayout android:id="@+id/detailNextVidButtonAndContentLayout"
|
||||||
@@ -210,7 +210,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/detailNextVidButtonAndContentLayout"
|
android:layout_below="@id/detailNextVidButtonAndContentLayout"
|
||||||
android:textSize="@dimen/video_item_detail_similar_text_size"
|
android:textSize="@dimen/video_item_detail_similar_text_size"
|
||||||
android:text="@string/showSimilarVideosButtonText"/>
|
android:text="@string/similar_videos_btn_text"/>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
android:id="@+id/videoitem_detail">
|
android:id="@+id/videoitem_detail">
|
||||||
|
|
||||||
<ImageView android:id="@+id/detailThumbnailView"
|
<ImageView android:id="@+id/detailThumbnailView"
|
||||||
android:contentDescription="@string/detailThumbnailViewDescription"
|
android:contentDescription="@string/detail_thumbnail_view_description"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:indeterminate="true"
|
android:indeterminate="true"
|
||||||
android:indeterminateTint="@color/primaryColorYoutube"
|
android:indeterminateTint="@color/light_youtube_primary_color"
|
||||||
android:indeterminateTintMode="src_in"/>
|
android:indeterminateTintMode="src_in"/>
|
||||||
|
|
||||||
<android.support.design.widget.FloatingActionButton
|
<android.support.design.widget.FloatingActionButton
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
app:backgroundTint="@color/primaryColorYoutube"
|
app:backgroundTint="@color/light_youtube_primary_color"
|
||||||
android:src="@drawable/ic_play_arrow_black"
|
android:src="@drawable/ic_play_arrow_black"
|
||||||
android:layout_margin="@dimen/video_item_detail_play_fab_margin"/>
|
android:layout_margin="@dimen/video_item_detail_play_fab_margin"/>
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="@dimen/video_item_detail_info_text_padding"
|
android:padding="@dimen/video_item_detail_info_text_padding"
|
||||||
android:layout_below="@id/detailVideoThumbnailWindowLayout"
|
android:layout_below="@id/detailVideoThumbnailWindowLayout"
|
||||||
android:background="@color/background_gray">
|
android:background="@color/light_background_color">
|
||||||
|
|
||||||
<TextView android:id="@+id/detailVideoTitleView"
|
<TextView android:id="@+id/detailVideoTitleView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
tools:ignore="RtlHardcoded" />
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
<ImageView android:id="@+id/detailUploaderThumbnailView"
|
<ImageView android:id="@+id/detailUploaderThumbnailView"
|
||||||
android:contentDescription="@string/detailUploaderThumbnailViewDescription"
|
android:contentDescription="@string/detail_uploader_thumbnail_view_description"
|
||||||
android:layout_width="@dimen/video_item_detail_uploader_image_size"
|
android:layout_width="@dimen/video_item_detail_uploader_image_size"
|
||||||
android:layout_height="@dimen/video_item_detail_uploader_image_size"
|
android:layout_height="@dimen/video_item_detail_uploader_image_size"
|
||||||
android:layout_below="@id/detailVideoTitleView"
|
android:layout_below="@id/detailVideoTitleView"
|
||||||
@@ -125,7 +125,7 @@
|
|||||||
tools:ignore="RtlHardcoded" />
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
<ImageView android:id="@+id/detailThumbsDownImgView"
|
<ImageView android:id="@+id/detailThumbsDownImgView"
|
||||||
android:contentDescription="@string/detailThumbsDownImgViewDescription"
|
android:contentDescription="@string/detail_dislikes_img_view_description"
|
||||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||||
android:layout_below="@id/detailViewCountView"
|
android:layout_below="@id/detailViewCountView"
|
||||||
@@ -146,7 +146,7 @@
|
|||||||
tools:ignore="RtlHardcoded" />
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
<ImageView android:id="@+id/detailThumbsUpImgView"
|
<ImageView android:id="@+id/detailThumbsUpImgView"
|
||||||
android:contentDescription="@string/detailThumbsUpImgViewDescription"
|
android:contentDescription="@string/detail_likes_img_view_description"
|
||||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||||
android:layout_below="@id/detailViewCountView"
|
android:layout_below="@id/detailViewCountView"
|
||||||
@@ -188,7 +188,7 @@
|
|||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:textSize="@dimen/video_item_detail_next_text_size"
|
android:textSize="@dimen/video_item_detail_next_text_size"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:text="@string/nextVideoTitle"
|
android:text="@string/next_video_title"
|
||||||
android:textAllCaps="true" />
|
android:textAllCaps="true" />
|
||||||
|
|
||||||
<RelativeLayout android:id="@+id/detailNextVidButtonAndContentLayout"
|
<RelativeLayout android:id="@+id/detailNextVidButtonAndContentLayout"
|
||||||
@@ -212,7 +212,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/detailNextVidButtonAndContentLayout"
|
android:layout_below="@id/detailNextVidButtonAndContentLayout"
|
||||||
android:textSize="@dimen/video_item_detail_similar_text_size"
|
android:textSize="@dimen/video_item_detail_similar_text_size"
|
||||||
android:text="@string/showSimilarVideosButtonText"/>
|
android:text="@string/similar_videos_btn_text"/>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
android:background="?attr/selectableItemBackground">
|
android:background="?attr/selectableItemBackground">
|
||||||
|
|
||||||
<ImageView android:id="@+id/detailThumbnailView"
|
<ImageView android:id="@+id/detailThumbnailView"
|
||||||
android:contentDescription="@string/detailThumbnailViewDescription"
|
android:contentDescription="@string/detail_thumbnail_view_description"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
app:backgroundTint="@color/primaryColorYoutube"
|
app:backgroundTint="@color/light_youtube_primary_color"
|
||||||
android:src="@drawable/ic_play_arrow_black"
|
android:src="@drawable/ic_play_arrow_black"
|
||||||
android:layout_margin="@dimen/video_item_detail_play_fab_margin"/>
|
android:layout_margin="@dimen/video_item_detail_play_fab_margin"/>
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="@dimen/video_item_detail_info_text_padding"
|
android:padding="@dimen/video_item_detail_info_text_padding"
|
||||||
android:layout_below="@id/detailVideoThumbnailWindowLayout"
|
android:layout_below="@id/detailVideoThumbnailWindowLayout"
|
||||||
android:background="@color/background_gray">
|
android:background="@color/light_background_color">
|
||||||
|
|
||||||
<TextView android:id="@+id/detailVideoTitleView"
|
<TextView android:id="@+id/detailVideoTitleView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||||
|
|
||||||
<ImageView android:id="@+id/detailUploaderThumbnailView"
|
<ImageView android:id="@+id/detailUploaderThumbnailView"
|
||||||
android:contentDescription="@string/detailUploaderThumbnailViewDescription"
|
android:contentDescription="@string/detail_uploader_thumbnail_view_description"
|
||||||
android:layout_width="@dimen/video_item_detail_uploader_image_size"
|
android:layout_width="@dimen/video_item_detail_uploader_image_size"
|
||||||
android:layout_height="@dimen/video_item_detail_uploader_image_size"
|
android:layout_height="@dimen/video_item_detail_uploader_image_size"
|
||||||
android:layout_below="@id/detailVideoTitleView"
|
android:layout_below="@id/detailVideoTitleView"
|
||||||
@@ -118,12 +118,13 @@
|
|||||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
<ImageView android:id="@+id/detailThumbsDownImgView"
|
<ImageView android:id="@+id/detailThumbsDownImgView"
|
||||||
android:contentDescription="@string/detailThumbsDownImgViewDescription"
|
android:contentDescription="@string/detail_dislikes_img_view_description"
|
||||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||||
android:layout_below="@id/detailViewCountView"
|
android:layout_below="@id/detailViewCountView"
|
||||||
android:layout_toLeftOf="@id/detailThumbsDownCountView"
|
android:layout_toLeftOf="@id/detailThumbsDownCountView"
|
||||||
android:layout_toStartOf="@id/detailThumbsDownCountView"
|
android:layout_toStartOf="@id/detailThumbsDownCountView"
|
||||||
|
android:layout_marginLeft="@dimen/video_item_detail_like_margin"
|
||||||
android:src="@drawable/thumbs_down" />
|
android:src="@drawable/thumbs_down" />
|
||||||
|
|
||||||
<TextView android:id="@+id/detailThumbsUpCountView"
|
<TextView android:id="@+id/detailThumbsUpCountView"
|
||||||
@@ -136,7 +137,7 @@
|
|||||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||||
|
|
||||||
<ImageView android:id="@+id/detailThumbsUpImgView"
|
<ImageView android:id="@+id/detailThumbsUpImgView"
|
||||||
android:contentDescription="@string/detailThumbsUpImgViewDescription"
|
android:contentDescription="@string/detail_likes_img_view_description"
|
||||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||||
android:layout_below="@id/detailViewCountView"
|
android:layout_below="@id/detailViewCountView"
|
||||||
@@ -175,7 +176,7 @@
|
|||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:textSize="@dimen/video_item_detail_next_text_size"
|
android:textSize="@dimen/video_item_detail_next_text_size"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:text="@string/nextVideoTitle"
|
android:text="@string/next_video_title"
|
||||||
android:textAllCaps="true" />
|
android:textAllCaps="true" />
|
||||||
|
|
||||||
<RelativeLayout android:id="@+id/detailNextVidButtonAndContentLayout"
|
<RelativeLayout android:id="@+id/detailNextVidButtonAndContentLayout"
|
||||||
@@ -199,7 +200,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/detailNextVidButtonAndContentLayout"
|
android:layout_below="@id/detailNextVidButtonAndContentLayout"
|
||||||
android:textSize="@dimen/video_item_detail_similar_text_size"
|
android:textSize="@dimen/video_item_detail_similar_text_size"
|
||||||
android:text="@string/showSimilarVideosButtonText"/>
|
android:text="@string/similar_videos_btn_text"/>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@@ -32,7 +32,7 @@
|
|||||||
tools:ignore="RtlHardcoded">
|
tools:ignore="RtlHardcoded">
|
||||||
|
|
||||||
<ImageView android:id="@+id/itemThumbnailView"
|
<ImageView android:id="@+id/itemThumbnailView"
|
||||||
android:contentDescription="@string/itemThumbnailViewDescription"
|
android:contentDescription="@string/list_thumbnail_view_description"
|
||||||
android:layout_width="@dimen/video_item_search_thumbnail_image_width"
|
android:layout_width="@dimen/video_item_search_thumbnail_image_width"
|
||||||
android:layout_height="@dimen/video_item_search_thumbnail_image_height"
|
android:layout_height="@dimen/video_item_search_thumbnail_image_height"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
@@ -56,8 +56,8 @@
|
|||||||
android:paddingLeft="@dimen/video_item_search_duration_horizontal_padding"
|
android:paddingLeft="@dimen/video_item_search_duration_horizontal_padding"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
android:textSize="@dimen/video_item_search_duration_text_size"
|
android:textSize="@dimen/video_item_search_duration_text_size"
|
||||||
android:background="@color/durationBackground"
|
android:background="@color/duration_dackground_color"
|
||||||
android:textColor="@color/durationText"/>
|
android:textColor="@color/duration_text_color"/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<item android:id="@+id/menu_item_screen_rotation"
|
<item android:id="@+id/menu_item_screen_rotation"
|
||||||
android:title="@string/screenRotation"
|
android:title="@string/screen_rotation"
|
||||||
app:showAsAction="always"
|
app:showAsAction="always"
|
||||||
android:icon="@drawable/ic_screen_rotation_white"/>
|
android:icon="@drawable/ic_screen_rotation_white"/>
|
||||||
</menu>
|
</menu>
|
@@ -3,7 +3,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<item android:id="@+id/menu_item_play_audio"
|
<item android:id="@+id/menu_item_play_audio"
|
||||||
android:title="@string/playAudio"
|
android:title="@string/play_audio"
|
||||||
app:showAsAction="ifRoom"
|
app:showAsAction="ifRoom"
|
||||||
android:icon="@drawable/ic_headset_black" />
|
android:icon="@drawable/ic_headset_black" />
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
android:icon="@drawable/ic_share_black"/>
|
android:icon="@drawable/ic_share_black"/>
|
||||||
|
|
||||||
<item android:id="@+id/action_play_with_kodi"
|
<item android:id="@+id/action_play_with_kodi"
|
||||||
android:title="@string/playWithKodiTitle"
|
android:title="@string/play_with_kodi_title"
|
||||||
app:showAsAction="ifRoom"
|
app:showAsAction="ifRoom"
|
||||||
android:icon="@drawable/ic_cast_black"/>
|
android:icon="@drawable/ic_cast_black"/>
|
||||||
|
|
||||||
|
@@ -1,53 +1,59 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="viewCountText">%1$s Aufrufe</string>
|
<string name="view_count_text">%1$s Aufrufe</string>
|
||||||
<string name="uploadDateText">Hochgeladen am %1$s</string>
|
<string name="upload_date_text">Hochgeladen am %1$s</string>
|
||||||
<string name="noPlayerFound">Keinen Streamplayer gefunden. Vielleicht möchtest du einen installieren.</string>
|
<string name="no_player_found">Keinen Streamplayer gefunden. Vielleicht möchtest du einen installieren.</string>
|
||||||
<string name="installStreamPlayer">Jetzt installieren</string>
|
<string name="install">Jetzt installieren</string>
|
||||||
<string name="cancel">Abbrechen</string>
|
<string name="cancel">Abbrechen</string>
|
||||||
<string name="open_in_browser">In Browser öffnen</string>
|
<string name="open_in_browser">In Browser öffnen</string>
|
||||||
<string name="share">Teilen</string>
|
<string name="share">Teilen</string>
|
||||||
<string name="download">Download</string>
|
<string name="download">Download</string>
|
||||||
<string name="search">Suchen</string>
|
<string name="search">Suchen</string>
|
||||||
<string name="settings">Einstellungen</string>
|
<string name="settings">Einstellungen</string>
|
||||||
<string name="didYouMean">Meintest du: </string>
|
<string name="did_you_mean">Meintest du: </string>
|
||||||
<string name="searchPage">Suchseite: </string>
|
<string name="search_page">Suchseite: </string>
|
||||||
<string name="shareDialogTitle">Teilen mit:</string>
|
<string name="share_dialog_title">Teilen mit:</string>
|
||||||
<string name="chooseBrowser">Browser:</string>
|
<string name="choose_browser">Browser:</string>
|
||||||
<string name="screenRotation">Rotation</string>
|
<string name="screen_rotation">Rotation</string>
|
||||||
<string name="title_activity_settings">Einstellungen</string>
|
<string name="settings_activity_title">Einstellungen</string>
|
||||||
<string name="useExternalPlayerTitle">Externen Player benutzen</string>
|
<string name="useExternalPlayerTitle">Externen Player benutzen</string>
|
||||||
<string name="downloadLocation">Downloadverzeichnis</string>
|
<string name="download_path_title">Downloadverzeichnis</string>
|
||||||
<string name="downloadLocationSummary">Verzeichnis in dem heruntergeladene Videos gespeichert werden.</string>
|
<string name="download_path_summary">Verzeichnis in dem heruntergeladene Videos gespeichert werden.</string>
|
||||||
<string name="downloadLocationDialogTitle">Download Verzeichnis eingeben</string>
|
<string name="download_path_dialog_title">Download Verzeichnis eingeben</string>
|
||||||
<string name="autoPlayThroughIntentTitle">Automatisches Abspielen durch Intent</string>
|
<string name="autoplay_through_intent_title">Automatisches Abspielen durch Intent</string>
|
||||||
<string name="autoPlayThroughIntentSummary">Startet ein Video automatisch wenn es von einer anderen App aufgerufen wurde.</string>
|
<string name="autoplay_through_intent_summary">Startet ein Video automatisch wenn es von einer anderen App aufgerufen wurde.</string>
|
||||||
<string name="defaultResolutionPreferenceTitle">Standard Auflösung</string>
|
<string name="default_resolution_title">Standard Auflösung</string>
|
||||||
<string name="playWithKodiTitle">Mit Kodi abspielen</string>
|
<string name="play_with_kodi_title">Mit Kodi abspielen</string>
|
||||||
<string name="koreNotFound">Kore app wurde nicht gefunden. Kore wird benötigt, um Videos mit Kodi wieder zu geben.</string>
|
<string name="kore_not_found">Kore app wurde nicht gefunden. Kore wird benötigt, um Videos mit Kodi wieder zu geben.</string>
|
||||||
<string name="installeKore">Kore installieren</string>
|
<string name="installeKore">Kore installieren</string>
|
||||||
<string name="showPlayWithKodiTitle">Zeige \"Mit Kodi abspielen\" Option</string>
|
<string name="show_play_with_kodi_title">Zeige \"Mit Kodi abspielen\" Option</string>
|
||||||
<string name="showPlayWithKodiSummary">Zeigt eine Option an, über die man Videos mit dem Kodi Mediacenter abspielen kann.</string>
|
<string name="show_play_with_kodi_summary">Zeigt eine Option an, über die man Videos mit dem Kodi Mediacenter abspielen kann.</string>
|
||||||
<string name="playAudio">Audio</string>
|
<string name="play_audio">Audio</string>
|
||||||
<string name="defaultAudioFormatTitle">Bevorzugtes Audio Format</string>
|
<string name="default_audio_format_title">Bevorzugtes Audio Format</string>
|
||||||
<string name="webMAudioDescription">WebM - freies Format</string>
|
<string name="webm_description">WebM — freies Format</string>
|
||||||
<string name="m4aAudioDescription">m4a - bessere Qualität</string>
|
<string name="m4a_description">m4a — bessere Qualität</string>
|
||||||
<string name="downloadDialogTitle">Herunterladen</string>
|
<string name="download_dialog_title">Herunterladen</string>
|
||||||
<string-array name="downloadOptions">
|
<string-array name="downloadOptions">
|
||||||
<item>Video</item>
|
<item>Video</item>
|
||||||
<item>Audio</item>
|
<item>Audio</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string name="nextVideoTitle">Nächstes Video</string>
|
<string name="next_video_title">Nächstes Video</string>
|
||||||
<string name="showNextAndSimilarTitle">Zeige nächstes und ähnliche Videos</string>
|
<string name="show_next_and_similar_title">Zeige nächstes und ähnliche Videos</string>
|
||||||
<string name="urlNotSupportedText">URL wird nicht unterstützt.</string>
|
<string name="url_not_supported_toast">URL wird nicht unterstützt.</string>
|
||||||
<string name="showSimilarVideosButtonText">Ähnliche Videos</string>
|
<string name="similar_videos_btn_text">Ähnliche Videos</string>
|
||||||
<string name="settingsCategoryVideoAudioTitle">VIDEO & AUDIO</string>
|
<string name="settings_category_video_audio_title">Video & Audio</string>
|
||||||
<string name="settingsCategoryVideoInfoTittle">INFO</string>
|
<string name="search_language_title">Bevorzugte Sprache des Inhalts</string>
|
||||||
<string name="settingsCategoryEtcTitle">ETC</string>
|
<string name="list_thumbnail_view_description">Video-Vorschau-Bild</string>
|
||||||
<string name="searchLanguageTitle">Bevorzugte Sprache</string>
|
<string name="detail_thumbnail_view_description">Video-Vorschau-Bild</string>
|
||||||
<string name="itemThumbnailViewDescription">Video-Vorschau-Bild</string>
|
<string name="detail_uploader_thumbnail_view_description">Nutzerbild</string>
|
||||||
<string name="detailThumbnailViewDescription">Video-Vorschau-Bild</string>
|
<string name="detail_dislikes_img_view_description">Gefällt nicht</string>
|
||||||
<string name="detailUploaderThumbnailViewDescription">Nutzerbild</string>
|
<string name="detail_likes_img_view_description">Gefällt</string>
|
||||||
<string name="detailThumbsDownImgViewDescription">gefällt nicht</string>
|
<string name="loading">Lade</string>
|
||||||
<string name="detailThumbsUpImgViewDescription">gefällt</string>
|
<string name="use_external_video_player_title">Benutze externen Videoabspieler</string>
|
||||||
|
<string name="use_external_audio_player_title">Benutze externen Audioabspieler</string>
|
||||||
|
<string name="background_player_playing_toast">Spiele im Hintergrund ab</string>
|
||||||
|
<string name="play_btn_text">Abspielen</string>
|
||||||
|
|
||||||
|
<string name="use_tor_title">Benutze TOR</string>
|
||||||
|
<string name="use_tor_summary">Erzwinge das Herunterladen durch TOR für verbesserte Privatsphäre (Videostream noch nicht unterstützt)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user