mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-09-30 16:20:54 +02:00
Compare commits
82 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9e76f94cf6 | ||
![]() |
7d6b92e064 | ||
![]() |
849a45a3ca | ||
![]() |
7ddea5a71b | ||
![]() |
5d81358c15 | ||
![]() |
492aad9d70 | ||
![]() |
647cfcd401 | ||
![]() |
c60d98e52d | ||
![]() |
d3cfac6b15 | ||
![]() |
7fb4e5a143 | ||
![]() |
8e451b2a83 | ||
![]() |
8083f06fe7 | ||
![]() |
44521a2e56 | ||
![]() |
dfeed3d0eb | ||
![]() |
081a45b70d | ||
![]() |
616a721bba | ||
![]() |
c9aa553b32 | ||
![]() |
e3d59c3cff | ||
![]() |
df51635674 | ||
![]() |
1e81f61760 | ||
![]() |
a4043eab83 | ||
![]() |
60dc19d2bc | ||
![]() |
a2e4585fe8 | ||
![]() |
b5df281447 | ||
![]() |
650917f9f9 | ||
![]() |
3a9c95a9ae | ||
![]() |
5458acfcad | ||
![]() |
68e80e6054 | ||
![]() |
e4aa69b8d3 | ||
![]() |
dfd40e43da | ||
![]() |
7efd111d9c | ||
![]() |
6809172203 | ||
![]() |
40a4343f06 | ||
![]() |
cd9333b39e | ||
![]() |
82d426c781 | ||
![]() |
c7e773de25 | ||
![]() |
2ded33110f | ||
![]() |
b26c0aa9da | ||
![]() |
2fc8fb6f17 | ||
![]() |
ea76f1d6e2 | ||
![]() |
7cda1d116b | ||
![]() |
8bf7a1a9db | ||
![]() |
0aa0ad65c0 | ||
![]() |
53ff58daa3 | ||
![]() |
b3225bebe6 | ||
![]() |
4beafad71f | ||
![]() |
c96f933626 | ||
![]() |
bea6359d5f | ||
![]() |
92db9cb59b | ||
![]() |
410c4ca736 | ||
![]() |
80c9dbf180 | ||
![]() |
c9edac2820 | ||
![]() |
143df9a529 | ||
![]() |
c87da9903f | ||
![]() |
0f69e6c64d | ||
![]() |
1b9a6e53ce | ||
![]() |
c7abf377eb | ||
![]() |
175d8ce572 | ||
![]() |
1708a401cf | ||
![]() |
141278e668 | ||
![]() |
754bd82699 | ||
![]() |
999efb6660 | ||
![]() |
0b391a9ef3 | ||
![]() |
2a99ac4430 | ||
![]() |
a5589d0865 | ||
![]() |
83541a0d5d | ||
![]() |
ac0dff7aa1 | ||
![]() |
f22b5157f5 | ||
![]() |
659d0d6115 | ||
![]() |
fd8c99fd8d | ||
![]() |
9494f3a299 | ||
![]() |
8021848b03 | ||
![]() |
5a127c26e6 | ||
![]() |
a7d734c20c | ||
![]() |
7c7129f9a1 | ||
![]() |
05cbc7891d | ||
![]() |
14623456ff | ||
![]() |
5064ec3ac4 | ||
![]() |
892888796d | ||
![]() |
4f2826d2c2 | ||
![]() |
7f824d725b | ||
![]() |
da4096c4ef |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,3 +8,4 @@
|
|||||||
/.idea
|
/.idea
|
||||||
/*.iml
|
/*.iml
|
||||||
gradle.properties
|
gradle.properties
|
||||||
|
*~
|
||||||
|
@@ -8,8 +8,8 @@ android {
|
|||||||
applicationId "org.schabi.newpipe"
|
applicationId "org.schabi.newpipe"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 25
|
targetSdkVersion 25
|
||||||
versionCode 20
|
versionCode 22
|
||||||
versionName "0.8.6"
|
versionName "0.8.8"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
@@ -32,10 +32,10 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
compile 'com.android.support:appcompat-v7:25.0.0'
|
compile 'com.android.support:appcompat-v7:25.1.0'
|
||||||
compile 'com.android.support:support-v4:25.0.0'
|
compile 'com.android.support:support-v4:25.1.0'
|
||||||
compile 'com.android.support:design:25.0.0'
|
compile 'com.android.support:design:25.1.0'
|
||||||
compile 'com.android.support:recyclerview-v7:25.0.0'
|
compile 'com.android.support:recyclerview-v7:25.1.0'
|
||||||
compile 'org.jsoup:jsoup:1.8.3'
|
compile 'org.jsoup:jsoup:1.8.3'
|
||||||
compile 'org.mozilla:rhino:1.7.7'
|
compile 'org.mozilla:rhino:1.7.7'
|
||||||
compile 'info.guardianproject.netcipher:netcipher:1.2'
|
compile 'info.guardianproject.netcipher:netcipher:1.2'
|
||||||
@@ -46,5 +46,6 @@ dependencies {
|
|||||||
compile 'com.google.code.gson:gson:2.4'
|
compile 'com.google.code.gson:gson:2.4'
|
||||||
compile 'com.nononsenseapps:filepicker:3.0.0'
|
compile 'com.nononsenseapps:filepicker:3.0.0'
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
|
testCompile 'org.mockito:mockito-core:1.10.19'
|
||||||
compile 'ch.acra:acra:4.9.0'
|
compile 'ch.acra:acra:4.9.0'
|
||||||
}
|
}
|
||||||
|
@@ -161,6 +161,16 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".ReCaptchaActivity"
|
android:name=".ReCaptchaActivity"
|
||||||
android:label="@string/reCaptchaActivity" />
|
android:label="@string/reCaptchaActivity" />
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name="android.support.v4.content.FileProvider"
|
||||||
|
android:authorities="${applicationId}.provider"
|
||||||
|
android:exported="false"
|
||||||
|
android:grantUriPermissions="true">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/provider_paths"/>
|
||||||
|
</provider>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
@@ -48,6 +48,7 @@ public class App extends Application {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
// init crashreport
|
// init crashreport
|
||||||
try {
|
try {
|
||||||
final ACRAConfiguration acraConfig = new ConfigurationBuilder(this)
|
final ACRAConfiguration acraConfig = new ConfigurationBuilder(this)
|
||||||
|
@@ -4,6 +4,7 @@ import android.content.Intent;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.design.widget.CollapsingToolbarLayout;
|
import android.support.design.widget.CollapsingToolbarLayout;
|
||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
@@ -31,6 +32,7 @@ import org.schabi.newpipe.info_list.InfoListAdapter;
|
|||||||
import org.schabi.newpipe.report.ErrorActivity;
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||||
@@ -71,6 +73,10 @@ public class ChannelActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
if (Objects.equals(PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
.getString("theme", getResources().getString(R.string.light_theme_title)), getResources().getString(R.string.dark_theme_title))) {
|
||||||
|
setTheme(R.style.DarkTheme_NoActionBar);
|
||||||
|
}
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_channel);
|
setContentView(R.layout.activity_channel);
|
||||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||||
@@ -128,7 +134,7 @@ public class ChannelActivity extends AppCompatActivity {
|
|||||||
CollapsingToolbarLayout ctl = (CollapsingToolbarLayout) findViewById(R.id.channel_toolbar_layout);
|
CollapsingToolbarLayout ctl = (CollapsingToolbarLayout) findViewById(R.id.channel_toolbar_layout);
|
||||||
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);
|
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);
|
||||||
ImageView channelBanner = (ImageView) findViewById(R.id.channel_banner_image);
|
ImageView channelBanner = (ImageView) findViewById(R.id.channel_banner_image);
|
||||||
FloatingActionButton feedButton = (FloatingActionButton) findViewById(R.id.channel_rss_fab);
|
final FloatingActionButton feedButton = (FloatingActionButton) findViewById(R.id.channel_rss_fab);
|
||||||
ImageView avatarView = (ImageView) findViewById(R.id.channel_avatar_view);
|
ImageView avatarView = (ImageView) findViewById(R.id.channel_avatar_view);
|
||||||
ImageView haloView = (ImageView) findViewById(R.id.channel_avatar_halo);
|
ImageView haloView = (ImageView) findViewById(R.id.channel_avatar_halo);
|
||||||
|
|
||||||
|
@@ -4,13 +4,13 @@ import android.content.Intent;
|
|||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
import org.schabi.newpipe.settings.SettingsActivity;
|
import org.schabi.newpipe.settings.SettingsActivity;
|
||||||
|
import org.schabi.newpipe.util.PermissionHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Christian Schabesberger on 02.08.16.
|
* Created by Christian Schabesberger on 02.08.16.
|
||||||
@@ -32,7 +32,7 @@ import org.schabi.newpipe.settings.SettingsActivity;
|
|||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends ThemableActivity {
|
||||||
|
|
||||||
private Fragment mainFragment = null;
|
private Fragment mainFragment = null;
|
||||||
|
|
||||||
@@ -40,7 +40,6 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||||
mainFragment = getSupportFragmentManager()
|
mainFragment = getSupportFragmentManager()
|
||||||
.findFragmentById(R.id.search_fragment);
|
.findFragmentById(R.id.search_fragment);
|
||||||
@@ -52,8 +51,6 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
MenuInflater inflater = getMenuInflater();
|
MenuInflater inflater = getMenuInflater();
|
||||||
|
|
||||||
inflater.inflate(R.menu.main_menu, menu);
|
inflater.inflate(R.menu.main_menu, menu);
|
||||||
|
|
||||||
mainFragment.onCreateOptionsMenu(menu, inflater);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,13 +71,15 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case R.id.action_show_downloads: {
|
case R.id.action_show_downloads: {
|
||||||
|
if(!PermissionHelper.checkStoragePermissions(this)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
Intent intent = new Intent(this, org.schabi.newpipe.download.DownloadActivity.class);
|
Intent intent = new Intent(this, org.schabi.newpipe.download.DownloadActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return mainFragment.onOptionsItemSelected(item) ||
|
return super.onOptionsItemSelected(item);
|
||||||
super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ package org.schabi.newpipe;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
@@ -34,6 +35,8 @@ import android.webkit.WebViewClient;
|
|||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
public class ReCaptchaActivity extends AppCompatActivity {
|
public class ReCaptchaActivity extends AppCompatActivity {
|
||||||
|
public static final int RECAPTCHA_REQUEST = 10;
|
||||||
|
|
||||||
public static final String TAG = ReCaptchaActivity.class.toString();
|
public static final String TAG = ReCaptchaActivity.class.toString();
|
||||||
public static final String YT_URL = "https://www.youtube.com";
|
public static final String YT_URL = "https://www.youtube.com";
|
||||||
|
|
||||||
@@ -42,6 +45,9 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_recaptcha);
|
setContentView(R.layout.activity_recaptcha);
|
||||||
|
|
||||||
|
// Set return to Cancel by default
|
||||||
|
setResult(RESULT_CANCELED);
|
||||||
|
|
||||||
ActionBar actionBar = getSupportActionBar();
|
ActionBar actionBar = getSupportActionBar();
|
||||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
actionBar.setTitle(R.string.reCaptcha_title);
|
actionBar.setTitle(R.string.reCaptcha_title);
|
||||||
@@ -80,19 +86,26 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
|||||||
context = ctx;
|
context = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
||||||
|
// TODO: Start Loader
|
||||||
|
super.onPageStarted(view, url, favicon);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPageFinished(WebView view, String url) {
|
public void onPageFinished(WebView view, String url) {
|
||||||
String cookies = CookieManager.getInstance().getCookie(url);
|
String cookies = CookieManager.getInstance().getCookie(url);
|
||||||
|
|
||||||
|
// TODO: Stop Loader
|
||||||
|
|
||||||
// find cookies : s_gl & goojf and Add cookies to Downloader
|
// find cookies : s_gl & goojf and Add cookies to Downloader
|
||||||
if (find_access_cookies(cookies)) {
|
if (find_access_cookies(cookies)) {
|
||||||
// Give cookies to Downloader class
|
// Give cookies to Downloader class
|
||||||
Downloader.setCookies(mCookies);
|
Downloader.setCookies(mCookies);
|
||||||
|
|
||||||
// Closing activity and return to parent.
|
// Closing activity and return to parent
|
||||||
Intent intent = new Intent(context, org.schabi.newpipe.MainActivity.class);
|
setResult(RESULT_OK);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
finish();
|
||||||
NavUtils.navigateUpTo(context, intent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
app/src/main/java/org/schabi/newpipe/ThemableActivity.java
Normal file
21
app/src/main/java/org/schabi/newpipe/ThemableActivity.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.R.attr.theme;
|
||||||
|
|
||||||
|
public class ThemableActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (Objects.equals(PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
.getString("theme", getResources().getString(R.string.light_theme_title)), getResources().getString(R.string.dark_theme_title))) {
|
||||||
|
setTheme(R.style.DarkTheme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -5,8 +5,8 @@ import android.os.Handler;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.schabi.newpipe.Downloader;
|
|
||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||||
import org.schabi.newpipe.extractor.stream_info.StreamExtractor;
|
import org.schabi.newpipe.extractor.stream_info.StreamExtractor;
|
||||||
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
@@ -44,6 +44,7 @@ public class StreamInfoWorker {
|
|||||||
public interface OnStreamInfoReceivedListener {
|
public interface OnStreamInfoReceivedListener {
|
||||||
void onReceive(StreamInfo info);
|
void onReceive(StreamInfo info);
|
||||||
void onError(int messageId);
|
void onError(int messageId);
|
||||||
|
void onReCaptchaException();
|
||||||
void onBlockedByGemaError();
|
void onBlockedByGemaError();
|
||||||
void onContentErrorWithMessage(int messageId);
|
void onContentErrorWithMessage(int messageId);
|
||||||
void onContentError();
|
void onContentError();
|
||||||
@@ -107,6 +108,13 @@ public class StreamInfoWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// These errors render the stream information unusable.
|
// These errors render the stream information unusable.
|
||||||
|
} catch (ReCaptchaException e) {
|
||||||
|
h.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
onStreamInfoReceivedListener.onReCaptchaException();
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
h.post(new Runnable() {
|
h.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -115,9 +123,8 @@ public class StreamInfoWorker {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
} catch (YoutubeStreamExtractor.DecryptException de) {
|
||||||
// custom service related exceptions
|
// custom service related exceptions
|
||||||
catch (YoutubeStreamExtractor.DecryptException de) {
|
|
||||||
h.post(new Runnable() {
|
h.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@@ -5,7 +5,6 @@ import android.media.AudioManager;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@@ -14,6 +13,7 @@ import android.widget.Toast;
|
|||||||
import org.schabi.newpipe.App;
|
import org.schabi.newpipe.App;
|
||||||
import org.schabi.newpipe.MainActivity;
|
import org.schabi.newpipe.MainActivity;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
import org.schabi.newpipe.ThemableActivity;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ import java.util.HashSet;
|
|||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class VideoItemDetailActivity extends AppCompatActivity {
|
public class VideoItemDetailActivity extends ThemableActivity {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes invisible separators (\p{Z}) and punctuation characters including
|
* Removes invisible separators (\p{Z}) and punctuation characters including
|
||||||
@@ -141,6 +141,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl);
|
outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl);
|
||||||
outState.putInt(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingService);
|
outState.putInt(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingService);
|
||||||
outState.putBoolean(VideoItemDetailFragment.AUTO_PLAY, false);
|
outState.putBoolean(VideoItemDetailFragment.AUTO_PLAY, false);
|
||||||
@@ -148,6 +149,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
super.onOptionsItemSelected(item);
|
||||||
int id = item.getItemId();
|
int id = item.getItemId();
|
||||||
if (id == android.R.id.home) {
|
if (id == android.R.id.home) {
|
||||||
// This ID represents the Home or Up button. In the case of this
|
// This ID represents the Home or Up button. In the case of this
|
||||||
@@ -162,19 +164,10 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
|||||||
NavUtils.navigateUpTo(this, intent);
|
NavUtils.navigateUpTo(this, intent);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return fragment.onOptionsItemSelected(item) ||
|
return super.onOptionsItemSelected(item);
|
||||||
super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
|
||||||
super.onCreateOptionsMenu(menu);
|
|
||||||
fragment.onCreateOptionsMenu(menu, getMenuInflater());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves all Strings which look remotely like URLs from a text.
|
* Retrieves all Strings which look remotely like URLs from a text.
|
||||||
* Used if NewPipe was called through share menu.
|
* Used if NewPipe was called through share menu.
|
||||||
|
@@ -21,6 +21,7 @@ import android.util.Log;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -30,7 +31,6 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.google.android.exoplayer.util.Util;
|
import com.google.android.exoplayer.util.Util;
|
||||||
@@ -39,25 +39,29 @@ import com.nostra13.universalimageloader.core.ImageLoader;
|
|||||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||||
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
||||||
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.ActivityCommunicator;
|
import org.schabi.newpipe.ActivityCommunicator;
|
||||||
import org.schabi.newpipe.ChannelActivity;
|
import org.schabi.newpipe.ChannelActivity;
|
||||||
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
|
||||||
import org.schabi.newpipe.extractor.stream_info.StreamPreviewInfo;
|
|
||||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
|
||||||
import org.schabi.newpipe.ImageErrorLoadingListener;
|
import org.schabi.newpipe.ImageErrorLoadingListener;
|
||||||
import org.schabi.newpipe.Localization;
|
import org.schabi.newpipe.Localization;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
import org.schabi.newpipe.ReCaptchaActivity;
|
||||||
import org.schabi.newpipe.download.DownloadDialog;
|
import org.schabi.newpipe.download.DownloadDialog;
|
||||||
import org.schabi.newpipe.extractor.stream_info.AudioStream;
|
|
||||||
import org.schabi.newpipe.extractor.MediaFormat;
|
import org.schabi.newpipe.extractor.MediaFormat;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.extractor.stream_info.AudioStream;
|
||||||
|
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
||||||
|
import org.schabi.newpipe.extractor.stream_info.StreamPreviewInfo;
|
||||||
import org.schabi.newpipe.extractor.stream_info.VideoStream;
|
import org.schabi.newpipe.extractor.stream_info.VideoStream;
|
||||||
|
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||||
import org.schabi.newpipe.player.BackgroundPlayer;
|
import org.schabi.newpipe.player.BackgroundPlayer;
|
||||||
import org.schabi.newpipe.player.PlayVideoActivity;
|
|
||||||
import org.schabi.newpipe.player.ExoPlayerActivity;
|
import org.schabi.newpipe.player.ExoPlayerActivity;
|
||||||
|
import org.schabi.newpipe.player.PlayVideoActivity;
|
||||||
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
|
import java.util.Vector;
|
||||||
|
import org.schabi.newpipe.util.PermissionHelper;
|
||||||
|
|
||||||
|
import static android.app.Activity.RESULT_OK;
|
||||||
|
import static org.schabi.newpipe.ReCaptchaActivity.RECAPTCHA_REQUEST;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -389,6 +393,10 @@ public class VideoItemDetailFragment extends Fragment {
|
|||||||
actionBarHandler.setOnDownloadListener(new ActionBarHandler.OnActionListener() {
|
actionBarHandler.setOnDownloadListener(new ActionBarHandler.OnActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onActionSelected(int selectedStreamId) {
|
public void onActionSelected(int selectedStreamId) {
|
||||||
|
if(!PermissionHelper.checkStoragePermissions(getActivity())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
|
|
||||||
@@ -579,11 +587,6 @@ public class VideoItemDetailFragment extends Fragment {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mandatory empty constructor for the fragment manager to instantiate the
|
|
||||||
* fragment (e.g. upon screen orientation changes).
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -604,6 +607,17 @@ public class VideoItemDetailFragment extends Fragment {
|
|||||||
postNewErrorToast(messageId);
|
postNewErrorToast(messageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReCaptchaException() {
|
||||||
|
Toast.makeText(getActivity(), R.string.recaptcha_request_toast,
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
|
||||||
|
// Starting ReCaptcha Challenge Activity
|
||||||
|
startActivityForResult(
|
||||||
|
new Intent(getActivity(), ReCaptchaActivity.class),
|
||||||
|
RECAPTCHA_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockedByGemaError() {
|
public void onBlockedByGemaError() {
|
||||||
onErrorBlockedByGema();
|
onErrorBlockedByGema();
|
||||||
@@ -619,6 +633,7 @@ public class VideoItemDetailFragment extends Fragment {
|
|||||||
onNotSpecifiedContentError();
|
onNotSpecifiedContentError();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -637,10 +652,9 @@ public class VideoItemDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle savedInstanceBundle) {
|
public void onStart() {
|
||||||
super.onActivityCreated(savedInstanceBundle);
|
super.onStart();
|
||||||
Activity a = getActivity();
|
Activity a = getActivity();
|
||||||
|
|
||||||
infoItemBuilder = new InfoItemBuilder(a, a.findViewById(android.R.id.content));
|
infoItemBuilder = new InfoItemBuilder(a, a.findViewById(android.R.id.content));
|
||||||
|
|
||||||
if (android.os.Build.VERSION.SDK_INT < 18) {
|
if (android.os.Build.VERSION.SDK_INT < 18) {
|
||||||
@@ -769,11 +783,13 @@ public class VideoItemDetailFragment extends Fragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
actionBarHandler.setupMenu(menu, inflater);
|
actionBarHandler.setupMenu(menu, inflater);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
super.onOptionsItemSelected(item);
|
||||||
return actionBarHandler.onItemSelected(item);
|
return actionBarHandler.onItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -793,4 +809,24 @@ public class VideoItemDetailFragment extends Fragment {
|
|||||||
VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId);
|
VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId);
|
||||||
activity.startActivity(detailIntent);
|
activity.startActivity(detailIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
switch (requestCode) {
|
||||||
|
case RECAPTCHA_REQUEST:
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
String videoUrl = getArguments().getString(VIDEO_URL);
|
||||||
|
StreamInfoWorker siw = StreamInfoWorker.getInstance();
|
||||||
|
siw.search(streamingServiceId, videoUrl, getActivity());
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "ReCaptcha failed");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Log.e(TAG, "Request code from activity not supported [" + requestCode + "]");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -13,8 +13,8 @@ import android.os.IBinder;
|
|||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@@ -28,8 +28,10 @@ import android.widget.SeekBar;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.ThemableActivity;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
import org.schabi.newpipe.settings.NewPipeSettings;
|
||||||
import org.schabi.newpipe.settings.SettingsActivity;
|
import org.schabi.newpipe.settings.SettingsActivity;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -42,7 +44,7 @@ import us.shandian.giga.ui.fragment.MissionsFragment;
|
|||||||
import us.shandian.giga.util.CrashHandler;
|
import us.shandian.giga.util.CrashHandler;
|
||||||
import us.shandian.giga.util.Utility;
|
import us.shandian.giga.util.Utility;
|
||||||
|
|
||||||
public class DownloadActivity extends AppCompatActivity implements AdapterView.OnItemClickListener{
|
public class DownloadActivity extends ThemableActivity implements AdapterView.OnItemClickListener{
|
||||||
|
|
||||||
public static final String INTENT_DOWNLOAD = "us.shandian.giga.intent.DOWNLOAD";
|
public static final String INTENT_DOWNLOAD = "us.shandian.giga.intent.DOWNLOAD";
|
||||||
|
|
||||||
@@ -53,26 +55,11 @@ public class DownloadActivity extends AppCompatActivity implements AdapterView.O
|
|||||||
|
|
||||||
|
|
||||||
private MissionsFragment mFragment;
|
private MissionsFragment mFragment;
|
||||||
private DownloadManager mManager;
|
|
||||||
private DownloadManagerService.DMBinder mBinder;
|
|
||||||
|
|
||||||
private String mPendingUrl;
|
private String mPendingUrl;
|
||||||
private SharedPreferences mPrefs;
|
private SharedPreferences mPrefs;
|
||||||
|
|
||||||
private ServiceConnection mConnection = new ServiceConnection() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onServiceConnected(ComponentName p1, IBinder binder) {
|
|
||||||
mBinder = (DownloadManagerService.DMBinder) binder;
|
|
||||||
mManager = mBinder.getDownloadManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onServiceDisconnected(ComponentName p1) {
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@TargetApi(21)
|
@TargetApi(21)
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -83,7 +70,6 @@ public class DownloadActivity extends AppCompatActivity implements AdapterView.O
|
|||||||
Intent i = new Intent();
|
Intent i = new Intent();
|
||||||
i.setClass(this, DownloadManagerService.class);
|
i.setClass(this, DownloadManagerService.class);
|
||||||
startService(i);
|
startService(i);
|
||||||
bindService(i, mConnection, Context.BIND_AUTO_CREATE);
|
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_downloader);
|
setContentView(R.layout.activity_downloader);
|
||||||
@@ -91,7 +77,7 @@ public class DownloadActivity extends AppCompatActivity implements AdapterView.O
|
|||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
|
|
||||||
// its ok if this failes, we will catch that error later, and send it as report
|
// its ok if this fails, we will catch that error later, and send it as report
|
||||||
ActionBar actionBar = getSupportActionBar();
|
ActionBar actionBar = getSupportActionBar();
|
||||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
actionBar.setTitle(R.string.downloads_title);
|
actionBar.setTitle(R.string.downloads_title);
|
||||||
@@ -202,22 +188,24 @@ public class DownloadActivity extends AppCompatActivity implements AdapterView.O
|
|||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
if (item.getItemId() == R.id.okay) {
|
if (item.getItemId() == R.id.okay) {
|
||||||
|
|
||||||
|
String location;
|
||||||
|
if(audioButton.isChecked()) {
|
||||||
|
location = NewPipeSettings.getAudioDownloadPath(DownloadActivity.this);
|
||||||
|
} else {
|
||||||
|
location = NewPipeSettings.getVideoDownloadPath(DownloadActivity.this);
|
||||||
|
}
|
||||||
|
|
||||||
String fName = name.getText().toString().trim();
|
String fName = name.getText().toString().trim();
|
||||||
|
|
||||||
File f = new File(mManager.getLocation() + "/" + fName);
|
File f = new File(location, fName);
|
||||||
|
|
||||||
if (f.exists()) {
|
if (f.exists()) {
|
||||||
Toast.makeText(DownloadActivity.this, R.string.msg_exists, Toast.LENGTH_SHORT).show();
|
Toast.makeText(DownloadActivity.this, R.string.msg_exists, Toast.LENGTH_SHORT).show();
|
||||||
} else {
|
} else {
|
||||||
|
DownloadManagerService.startMission(
|
||||||
while (mBinder == null);
|
DownloadActivity.this,
|
||||||
|
getIntent().getData().toString(), location, fName,
|
||||||
int res = mManager.startMission(
|
audioButton.isChecked(), threads.getProgress() + 1);
|
||||||
getIntent().getData().toString(),
|
|
||||||
fName,
|
|
||||||
audioButton.isChecked(),
|
|
||||||
threads.getProgress() + 1);
|
|
||||||
mBinder.onMissionAdded(mManager.getMission(res));
|
|
||||||
mFragment.notifyChange();
|
mFragment.notifyChange();
|
||||||
|
|
||||||
mPrefs.edit().putInt(THREADS, threads.getProgress() + 1).commit();
|
mPrefs.edit().putInt(THREADS, threads.getProgress() + 1).commit();
|
||||||
@@ -273,8 +261,8 @@ public class DownloadActivity extends AppCompatActivity implements AdapterView.O
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return mFragment.onOptionsItemSelected(item) ||
|
return super.onOptionsItemSelected(item);
|
||||||
super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,8 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import org.schabi.newpipe.App;
|
import org.schabi.newpipe.App;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.settings.NewPipeSettings;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -65,24 +67,6 @@ public class DownloadDialog extends DialogFragment {
|
|||||||
public static final String AUDIO_URL = "audio_url";
|
public static final String AUDIO_URL = "audio_url";
|
||||||
public static final String VIDEO_URL = "video_url";
|
public static final String VIDEO_URL = "video_url";
|
||||||
|
|
||||||
private DownloadManager mManager;
|
|
||||||
private DownloadManagerService.DMBinder mBinder;
|
|
||||||
|
|
||||||
private ServiceConnection mConnection = new ServiceConnection() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onServiceConnected(ComponentName p1, IBinder binder) {
|
|
||||||
mBinder = (DownloadManagerService.DMBinder) binder;
|
|
||||||
mManager = mBinder.getDownloadManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onServiceDisconnected(ComponentName p1) {
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
public DownloadDialog() {
|
public DownloadDialog() {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -102,12 +86,6 @@ public class DownloadDialog extends DialogFragment {
|
|||||||
if(ContextCompat.checkSelfPermission(this.getContext(),Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
|
if(ContextCompat.checkSelfPermission(this.getContext(),Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
|
||||||
ActivityCompat.requestPermissions(getActivity(),new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},0);
|
ActivityCompat.requestPermissions(getActivity(),new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},0);
|
||||||
|
|
||||||
Intent i = new Intent();
|
|
||||||
i.setClass(getContext(), DownloadManagerService.class);
|
|
||||||
getContext().startService(i);
|
|
||||||
getContext().bindService(i, mConnection, Context.BIND_AUTO_CREATE);
|
|
||||||
|
|
||||||
|
|
||||||
return inflater.inflate(R.layout.dialog_url, container);
|
return inflater.inflate(R.layout.dialog_url, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,36 +197,22 @@ public class DownloadDialog extends DialogFragment {
|
|||||||
|
|
||||||
String fName = name.getText().toString().trim();
|
String fName = name.getText().toString().trim();
|
||||||
|
|
||||||
// todo: add timeout? would be bad if the thread gets locked dueto this.
|
boolean isAudio = audioButton.isChecked();
|
||||||
while (mBinder == null);
|
String url, location, filename;
|
||||||
|
if(isAudio) {
|
||||||
if(audioButton.isChecked()){
|
url = arguments.getString(AUDIO_URL);
|
||||||
int res = mManager.startMission(
|
location = NewPipeSettings.getAudioDownloadPath(getContext());
|
||||||
arguments.getString(AUDIO_URL),
|
filename = fName + arguments.getString(FILE_SUFFIX_AUDIO);
|
||||||
fName + arguments.getString(FILE_SUFFIX_AUDIO),
|
} else {
|
||||||
audioButton.isChecked(),
|
url = arguments.getString(VIDEO_URL);
|
||||||
threads.getProgress() + 1);
|
location = NewPipeSettings.getVideoDownloadPath(getContext());
|
||||||
DownloadMission mission = mManager.getMission(res);
|
filename = fName + arguments.getString(FILE_SUFFIX_VIDEO);
|
||||||
mBinder.onMissionAdded(mission);
|
|
||||||
// add download listener to allow media scan notification
|
|
||||||
DownloadListener listener = new DownloadListener(getContext(), mission);
|
|
||||||
mission.addListener(listener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(videoButton.isChecked()){
|
DownloadManagerService.startMission(getContext(), url, location, filename, isAudio,
|
||||||
int res = mManager.startMission(
|
|
||||||
arguments.getString(VIDEO_URL),
|
|
||||||
fName + arguments.getString(FILE_SUFFIX_VIDEO),
|
|
||||||
audioButton.isChecked(),
|
|
||||||
threads.getProgress() + 1);
|
threads.getProgress() + 1);
|
||||||
DownloadMission mission = mManager.getMission(res);
|
|
||||||
mBinder.onMissionAdded(mission);
|
|
||||||
// add download listener to allow media scan notification
|
|
||||||
DownloadListener listener = new DownloadListener(getContext(), mission);
|
|
||||||
mission.addListener(listener);
|
|
||||||
}
|
|
||||||
getDialog().dismiss();
|
getDialog().dismiss();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void download(String url, String title,
|
private void download(String url, String title,
|
||||||
|
@@ -1,62 +0,0 @@
|
|||||||
package org.schabi.newpipe.download;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
import us.shandian.giga.get.DownloadMission;
|
|
||||||
import us.shandian.giga.get.DownloadMission.MissionListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by erwin on 06.11.16.
|
|
||||||
*
|
|
||||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
|
||||||
* DownloadListener.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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class DownloadListener implements MissionListener
|
|
||||||
{
|
|
||||||
DownloadMission mMission;
|
|
||||||
Context mContext;
|
|
||||||
|
|
||||||
public DownloadListener(Context context, DownloadMission mission)
|
|
||||||
{
|
|
||||||
super();
|
|
||||||
mMission = mission;
|
|
||||||
mContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProgressUpdate(long done, long total)
|
|
||||||
{
|
|
||||||
// do nothing special ...
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFinish()
|
|
||||||
{
|
|
||||||
// notify media scanner on downloaded media file ...
|
|
||||||
mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
|
|
||||||
Uri.parse( "file://" + mMission.location
|
|
||||||
+ "/" + mMission.name)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(int errCode)
|
|
||||||
{
|
|
||||||
// do nothing special ...
|
|
||||||
}
|
|
||||||
}
|
|
@@ -42,7 +42,7 @@ import info.guardianproject.netcipher.NetCipher;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// TODO: FOR HEVEN SAKE !!! DO NOT SIMPLY USE ASYNCTASK. MAKE THIS A PROPER SERVICE !!!
|
// TODO: FOR HEAVEN SAKE !!! DO NOT SIMPLY USE ASYNCTASK. MAKE THIS A PROPER SERVICE !!!
|
||||||
public class FileDownloader extends AsyncTask<Void, Integer, Void> {
|
public class FileDownloader extends AsyncTask<Void, Integer, Void> {
|
||||||
public static final String TAG = "FileDownloader";
|
public static final String TAG = "FileDownloader";
|
||||||
|
|
||||||
|
@@ -4,7 +4,6 @@ import org.schabi.newpipe.extractor.UrlIdHandler;
|
|||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Christian Schabesberger on 10.08.15.
|
* Created by Christian Schabesberger on 10.08.15.
|
||||||
@@ -26,7 +25,6 @@ import java.util.List;
|
|||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@SuppressWarnings("ALL")
|
|
||||||
public abstract class SearchEngine {
|
public abstract class SearchEngine {
|
||||||
public static class NothingFoundException extends ExtractionException {
|
public static class NothingFoundException extends ExtractionException {
|
||||||
public NothingFoundException(String message) {
|
public NothingFoundException(String message) {
|
||||||
|
@@ -85,18 +85,18 @@ public class YoutubeSearchEngine extends SearchEngine {
|
|||||||
Element el;
|
Element el;
|
||||||
|
|
||||||
// both types of spell correction item
|
// both types of spell correction item
|
||||||
if (!((el = item.select("div[class*=\"spell-correction\"]").first()) == null)) {
|
if ((el = item.select("div[class*=\"spell-correction\"]").first()) != null) {
|
||||||
collector.setSuggestion(el.select("a").first().text());
|
collector.setSuggestion(el.select("a").first().text());
|
||||||
if(list.children().size() == 1) {
|
if(list.children().size() == 1) {
|
||||||
throw new NothingFoundException("Did you mean: " + el.select("a").first().text());
|
throw new NothingFoundException("Did you mean: " + el.select("a").first().text());
|
||||||
}
|
}
|
||||||
// search message item
|
// search message item
|
||||||
} else if (!((el = item.select("div[class*=\"search-message\"]").first()) == null)) {
|
} else if ((el = item.select("div[class*=\"search-message\"]").first()) != null) {
|
||||||
//result.errorMessage = el.text();
|
//result.errorMessage = el.text();
|
||||||
throw new NothingFoundException(el.text());
|
throw new NothingFoundException(el.text());
|
||||||
|
|
||||||
// video item type
|
// video item type
|
||||||
} else if (!((el = item.select("div[class*=\"yt-lockup-video\"").first()) == null)) {
|
} else if ((el = item.select("div[class*=\"yt-lockup-video\"").first()) != null) {
|
||||||
collector.commit(extractPreviewInfo(el));
|
collector.commit(extractPreviewInfo(el));
|
||||||
} else {
|
} else {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
|
@@ -46,7 +46,7 @@ public class YoutubeService extends StreamingService {
|
|||||||
@Override
|
@Override
|
||||||
public StreamExtractor getExtractorInstance(String url)
|
public StreamExtractor getExtractorInstance(String url)
|
||||||
throws ExtractionException, IOException {
|
throws ExtractionException, IOException {
|
||||||
UrlIdHandler urlIdHandler = new YoutubeStreamUrlIdHandler();
|
UrlIdHandler urlIdHandler = YoutubeStreamUrlIdHandler.getInstance();
|
||||||
if(urlIdHandler.acceptUrl(url)) {
|
if(urlIdHandler.acceptUrl(url)) {
|
||||||
return new YoutubeStreamExtractor(urlIdHandler, url, getServiceId());
|
return new YoutubeStreamExtractor(urlIdHandler, url, getServiceId());
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ public class YoutubeService extends StreamingService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UrlIdHandler getUrlIdHandlerInstance() {
|
public UrlIdHandler getUrlIdHandlerInstance() {
|
||||||
return new YoutubeStreamUrlIdHandler();
|
return YoutubeStreamUrlIdHandler.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -88,7 +88,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
|||||||
// $$el_type$$ will be replaced by the actual el_type (se the declarations below)
|
// $$el_type$$ will be replaced by the actual el_type (se the declarations below)
|
||||||
private static final String GET_VIDEO_INFO_URL =
|
private static final String GET_VIDEO_INFO_URL =
|
||||||
"https://www.youtube.com/get_video_info?video_id=%%video_id%%$$el_type$$&ps=default&eurl=&gl=US&hl=en";
|
"https://www.youtube.com/get_video_info?video_id=%%video_id%%$$el_type$$&ps=default&eurl=&gl=US&hl=en";
|
||||||
// eltype is nececeary for the url aboth
|
// eltype is necessary for the url above
|
||||||
private static final String EL_INFO = "el=info";
|
private static final String EL_INFO = "el=info";
|
||||||
|
|
||||||
public enum ItagType {
|
public enum ItagType {
|
||||||
@@ -184,7 +184,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
|||||||
// cached values
|
// cached values
|
||||||
private static volatile String decryptionCode = "";
|
private static volatile String decryptionCode = "";
|
||||||
|
|
||||||
UrlIdHandler urlidhandler = new YoutubeStreamUrlIdHandler();
|
UrlIdHandler urlidhandler = YoutubeStreamUrlIdHandler.getInstance();
|
||||||
String pageUrl = "";
|
String pageUrl = "";
|
||||||
|
|
||||||
public YoutubeStreamExtractor(UrlIdHandler urlIdHandler, String pageUrl, int serviceId)
|
public YoutubeStreamExtractor(UrlIdHandler urlIdHandler, String pageUrl, int serviceId)
|
||||||
|
@@ -1,12 +1,21 @@
|
|||||||
package org.schabi.newpipe.extractor.services.youtube;
|
package org.schabi.newpipe.extractor.services.youtube;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.Downloader;
|
||||||
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.Parser;
|
import org.schabi.newpipe.extractor.Parser;
|
||||||
import org.schabi.newpipe.extractor.UrlIdHandler;
|
import org.schabi.newpipe.extractor.UrlIdHandler;
|
||||||
import org.schabi.newpipe.extractor.exceptions.FoundAdException;
|
import org.schabi.newpipe.extractor.exceptions.FoundAdException;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Christian Schabesberger on 02.02.16.
|
* Created by Christian Schabesberger on 02.02.16.
|
||||||
@@ -29,45 +38,55 @@ import java.net.URLDecoder;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class YoutubeStreamUrlIdHandler implements UrlIdHandler {
|
public class YoutubeStreamUrlIdHandler implements UrlIdHandler {
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
|
private static final YoutubeStreamUrlIdHandler instance = new YoutubeStreamUrlIdHandler();
|
||||||
|
private static final String ID_PATTERN = "([\\-a-zA-Z0-9_]{11})";
|
||||||
|
|
||||||
|
private YoutubeStreamUrlIdHandler() {}
|
||||||
|
|
||||||
|
public static YoutubeStreamUrlIdHandler getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUrl(String videoId) {
|
public String getUrl(String videoId) {
|
||||||
return "https://www.youtube.com/watch?v=" + videoId;
|
return "https://www.youtube.com/watch?v=" + videoId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
@Override
|
@Override
|
||||||
public String getId(String url) throws ParsingException, IllegalArgumentException {
|
public String getId(String url) throws ParsingException, IllegalArgumentException {
|
||||||
if(url.isEmpty())
|
if(url.isEmpty()) {
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("The url parameter should not be empty");
|
throw new IllegalArgumentException("The url parameter should not be empty");
|
||||||
}
|
}
|
||||||
String id;
|
|
||||||
|
|
||||||
if(url.contains("youtube")) {
|
String id;
|
||||||
|
String lowercaseUrl = url.toLowerCase();
|
||||||
|
if(lowercaseUrl.contains("youtube")) {
|
||||||
if (url.contains("attribution_link")) {
|
if (url.contains("attribution_link")) {
|
||||||
try {
|
try {
|
||||||
String escapedQuery = Parser.matchGroup1("u=(.[^&|$]*)", url);
|
String escapedQuery = Parser.matchGroup1("u=(.[^&|$]*)", url);
|
||||||
String query = URLDecoder.decode(escapedQuery, "UTF-8");
|
String query = URLDecoder.decode(escapedQuery, "UTF-8");
|
||||||
id = Parser.matchGroup1("v=([\\-a-zA-Z0-9_]{11})", query);
|
id = Parser.matchGroup1("v=" + ID_PATTERN, query);
|
||||||
} catch (UnsupportedEncodingException uee) {
|
} catch (UnsupportedEncodingException uee) {
|
||||||
throw new ParsingException("Could not parse attribution_link", uee);
|
throw new ParsingException("Could not parse attribution_link", uee);
|
||||||
}
|
}
|
||||||
}
|
} else if(lowercaseUrl.contains("youtube.com/shared?ci=")) {
|
||||||
else if(url.contains("vnd.youtube"))
|
return getRealIdFromSharedLink(url);
|
||||||
{
|
} else if (url.contains("vnd.youtube")) {
|
||||||
id = Parser.matchGroup1("([\\-a-zA-Z0-9_]{11}).*", url);
|
id = Parser.matchGroup1(ID_PATTERN, url);
|
||||||
|
} else if (url.contains("embed")) {
|
||||||
|
id = Parser.matchGroup1("embed/" + ID_PATTERN, url);
|
||||||
} else if(url.contains("googleads")) {
|
} else if(url.contains("googleads")) {
|
||||||
throw new FoundAdException("Error found add: " + url);
|
throw new FoundAdException("Error found add: " + url);
|
||||||
} else {
|
} else {
|
||||||
id = Parser.matchGroup1("[?&]v=([\\-a-zA-Z0-9_]{11})", url);
|
id = Parser.matchGroup1("[?&]v=" + ID_PATTERN, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(url.contains("youtu.be")) {
|
else if(lowercaseUrl.contains("youtu.be")) {
|
||||||
if(url.contains("v=")) {
|
if(url.contains("v=")) {
|
||||||
id = Parser.matchGroup1("v=([\\-a-zA-Z0-9_]{11})", url);
|
id = Parser.matchGroup1("v=" + ID_PATTERN, url);
|
||||||
} else {
|
} else {
|
||||||
id = Parser.matchGroup1("youtu\\.be/([a-zA-Z0-9_-]{11})", url);
|
id = Parser.matchGroup1("[Yy][Oo][Uu][Tt][Uu]\\.[Bb][Ee]/" + ID_PATTERN, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -82,12 +101,55 @@ public class YoutubeStreamUrlIdHandler implements UrlIdHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the real url from a shared uri.
|
||||||
|
*
|
||||||
|
* Shared URI's look like this:
|
||||||
|
* <pre>
|
||||||
|
* * https://www.youtube.com/shared?ci=PJICrTByb3E
|
||||||
|
* * vnd.youtube://www.youtube.com/shared?ci=PJICrTByb3E&feature=twitter-deep-link
|
||||||
|
* </pre>
|
||||||
|
* @param url The shared url
|
||||||
|
* @return the id of the stream
|
||||||
|
* @throws ParsingException
|
||||||
|
*/
|
||||||
|
private @NonNull String getRealIdFromSharedLink(String url) throws ParsingException {
|
||||||
|
URI uri;
|
||||||
|
try {
|
||||||
|
uri = new URI(url);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new ParsingException("Invalid shared link", e);
|
||||||
|
}
|
||||||
|
String sharedId = getSharedId(uri);
|
||||||
|
Downloader downloader = NewPipe.getDownloader();
|
||||||
|
String content;
|
||||||
|
try {
|
||||||
|
content = downloader.download("https://www.youtube.com/shared?ci=" + sharedId);
|
||||||
|
} catch (IOException | ReCaptchaException e) {
|
||||||
|
throw new ParsingException("Unable to resolve shared link", e);
|
||||||
|
}
|
||||||
|
// is this bad? is this fragile?:
|
||||||
|
String realId = Parser.matchGroup1("rel=\"shortlink\" href=\"https://youtu.be/" + ID_PATTERN, content);
|
||||||
|
if(sharedId.equals(realId)) {
|
||||||
|
throw new ParsingException("Got same id for as shared id: " + sharedId);
|
||||||
|
}
|
||||||
|
return realId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private @NonNull String getSharedId(URI uri) throws ParsingException {
|
||||||
|
if (!"/shared".equals(uri.getPath())) {
|
||||||
|
throw new ParsingException("Not a shared link: " + uri.toString() + " (path != " + uri.getPath() + ")");
|
||||||
|
}
|
||||||
|
return Parser.matchGroup1("ci=" + ID_PATTERN, uri.getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
public String cleanUrl(String complexUrl) throws ParsingException {
|
public String cleanUrl(String complexUrl) throws ParsingException {
|
||||||
return getUrl(getId(complexUrl));
|
return getUrl(getId(complexUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptUrl(String videoUrl) {
|
public boolean acceptUrl(String videoUrl) {
|
||||||
|
videoUrl = videoUrl.toLowerCase();
|
||||||
return videoUrl.contains("youtube") ||
|
return videoUrl.contains("youtube") ||
|
||||||
videoUrl.contains("youtu.be");
|
videoUrl.contains("youtu.be");
|
||||||
}
|
}
|
||||||
|
@@ -31,14 +31,14 @@ public class AudioStream {
|
|||||||
this.bandwidth = bandwidth; this.sampling_rate = samplingRate;
|
this.bandwidth = bandwidth; this.sampling_rate = samplingRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reveals wether two streams are the same, but have diferent urls
|
// reveals whether two streams are the same, but have different urls
|
||||||
public boolean equalStats(AudioStream cmp) {
|
public boolean equalStats(AudioStream cmp) {
|
||||||
return format == cmp.format
|
return format == cmp.format
|
||||||
&& bandwidth == cmp.bandwidth
|
&& bandwidth == cmp.bandwidth
|
||||||
&& sampling_rate == cmp.sampling_rate;
|
&& sampling_rate == cmp.sampling_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// revelas wether two streams are equal
|
// reveals whether two streams are equal
|
||||||
public boolean equals(AudioStream cmp) {
|
public boolean equals(AudioStream cmp) {
|
||||||
return cmp != null && equalStats(cmp)
|
return cmp != null && equalStats(cmp)
|
||||||
&& url == cmp.url;
|
&& url == cmp.url;
|
||||||
|
@@ -37,14 +37,14 @@ public abstract class StreamExtractor {
|
|||||||
private UrlIdHandler urlIdHandler;
|
private UrlIdHandler urlIdHandler;
|
||||||
private StreamPreviewInfoCollector previewInfoCollector;
|
private StreamPreviewInfoCollector previewInfoCollector;
|
||||||
|
|
||||||
public class ExctractorInitException extends ExtractionException {
|
public class ExtractorInitException extends ExtractionException {
|
||||||
public ExctractorInitException(String message) {
|
public ExtractorInitException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
public ExctractorInitException(Throwable cause) {
|
public ExtractorInitException(Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
public ExctractorInitException(String message, Throwable cause) {
|
public ExtractorInitException(String message, Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -86,8 +86,8 @@ public class StreamInfo extends AbstractStreamInfo {
|
|||||||
private static StreamInfo extractImportantData(
|
private static StreamInfo extractImportantData(
|
||||||
StreamInfo streamInfo, StreamExtractor extractor)
|
StreamInfo streamInfo, StreamExtractor extractor)
|
||||||
throws ExtractionException, IOException {
|
throws ExtractionException, IOException {
|
||||||
/* ---- importand data, withoug the video can't be displayed goes here: ---- */
|
/* ---- important data, withoug the video can't be displayed goes here: ---- */
|
||||||
// if one of these is not available an exception is ment to be thrown directly into the frontend.
|
// if one of these is not available an exception is meant to be thrown directly into the frontend.
|
||||||
|
|
||||||
UrlIdHandler uiconv = extractor.getUrlIdHandler();
|
UrlIdHandler uiconv = extractor.getUrlIdHandler();
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ public class StreamInfo extends AbstractStreamInfo {
|
|||||||
streamInfo.audio_streams = new Vector<>();
|
streamInfo.audio_streams = new Vector<>();
|
||||||
}
|
}
|
||||||
//todo: make this quick and dirty solution a real fallback
|
//todo: make this quick and dirty solution a real fallback
|
||||||
// same as the quick and dirty aboth
|
// same as the quick and dirty above
|
||||||
try {
|
try {
|
||||||
streamInfo.audio_streams.addAll(
|
streamInfo.audio_streams.addAll(
|
||||||
DashMpdParser.getAudioStreams(streamInfo.dashMpdUrl));
|
DashMpdParser.getAudioStreams(streamInfo.dashMpdUrl));
|
||||||
@@ -173,9 +173,9 @@ public class StreamInfo extends AbstractStreamInfo {
|
|||||||
private static StreamInfo extractOptionalData(
|
private static StreamInfo extractOptionalData(
|
||||||
StreamInfo streamInfo, StreamExtractor extractor) {
|
StreamInfo streamInfo, StreamExtractor extractor) {
|
||||||
/* ---- optional data goes here: ---- */
|
/* ---- optional data goes here: ---- */
|
||||||
// If one of these failes, the frontend neets to handle that they are not available.
|
// If one of these fails, the frontend needs to handle that they are not available.
|
||||||
// Exceptions are therfore not thrown into the frontend, but stored into the error List,
|
// Exceptions are therefore not thrown into the frontend, but stored into the error List,
|
||||||
// so the frontend can afterwads check where errors happend.
|
// so the frontend can afterwards check where errors happened.
|
||||||
|
|
||||||
try {
|
try {
|
||||||
streamInfo.thumbnail_url = extractor.getThumbnailUrl();
|
streamInfo.thumbnail_url = extractor.getThumbnailUrl();
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package org.schabi.newpipe.extractor.stream_info;
|
package org.schabi.newpipe.extractor.stream_info;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.UrlIdHandler;
|
import org.schabi.newpipe.extractor.UrlIdHandler;
|
||||||
import org.schabi.newpipe.extractor.exceptions.FoundAdException;
|
import org.schabi.newpipe.extractor.exceptions.FoundAdException;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
@@ -60,7 +61,7 @@ public class StreamPreviewInfoCollector {
|
|||||||
if (urlIdHandler == null) {
|
if (urlIdHandler == null) {
|
||||||
throw new ParsingException("Error: UrlIdHandler not set");
|
throw new ParsingException("Error: UrlIdHandler not set");
|
||||||
} else if(!resultItem.webpage_url.isEmpty()) {
|
} else if(!resultItem.webpage_url.isEmpty()) {
|
||||||
resultItem.id = (new YoutubeStreamUrlIdHandler()).getId(resultItem.webpage_url);
|
resultItem.id = NewPipe.getService(serviceId).getUrlIdHandlerInstance().getId(resultItem.webpage_url);
|
||||||
}
|
}
|
||||||
resultItem.title = extractor.getTitle();
|
resultItem.title = extractor.getTitle();
|
||||||
resultItem.stream_type = extractor.getStreamType();
|
resultItem.stream_type = extractor.getStreamType();
|
||||||
|
@@ -30,13 +30,13 @@ import org.schabi.newpipe.R;
|
|||||||
|
|
||||||
public class InfoItemHolder extends RecyclerView.ViewHolder {
|
public class InfoItemHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
public ImageView itemThumbnailView;
|
public final ImageView itemThumbnailView;
|
||||||
public TextView itemVideoTitleView,
|
public final TextView itemVideoTitleView,
|
||||||
itemUploaderView,
|
itemUploaderView,
|
||||||
itemDurationView,
|
itemDurationView,
|
||||||
itemUploadDateView,
|
itemUploadDateView,
|
||||||
itemViewCountView;
|
itemViewCountView;
|
||||||
public Button itemButton;
|
public final Button itemButton;
|
||||||
|
|
||||||
public InfoItemHolder(View v) {
|
public InfoItemHolder(View v) {
|
||||||
super(v);
|
super(v);
|
||||||
@@ -48,4 +48,5 @@ public class InfoItemHolder extends RecyclerView.ViewHolder {
|
|||||||
itemViewCountView = (TextView) v.findViewById(R.id.itemViewCountView);
|
itemViewCountView = (TextView) v.findViewById(R.id.itemViewCountView);
|
||||||
itemButton = (Button) v.findViewById(R.id.item_button);
|
itemButton = (Button) v.findViewById(R.id.item_button);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -34,11 +34,12 @@ import java.util.Vector;
|
|||||||
|
|
||||||
public class InfoListAdapter extends RecyclerView.Adapter<InfoItemHolder> {
|
public class InfoListAdapter extends RecyclerView.Adapter<InfoItemHolder> {
|
||||||
|
|
||||||
InfoItemBuilder infoItemBuilder = null;
|
private final InfoItemBuilder infoItemBuilder;
|
||||||
List<StreamPreviewInfo> streamList = new Vector<>();
|
private final List<StreamPreviewInfo> streamList;
|
||||||
|
|
||||||
public InfoListAdapter(Activity a, View rootView) {
|
public InfoListAdapter(Activity a, View rootView) {
|
||||||
infoItemBuilder = new InfoItemBuilder(a, rootView);
|
infoItemBuilder = new InfoItemBuilder(a, rootView);
|
||||||
|
streamList = new Vector<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnItemSelectedListener
|
public void setOnItemSelectedListener
|
||||||
@@ -54,7 +55,7 @@ public class InfoListAdapter extends RecyclerView.Adapter<InfoItemHolder> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void clearSteamItemList() {
|
public void clearSteamItemList() {
|
||||||
streamList = new Vector<>();
|
streamList.clear();
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,6 @@ import android.preference.PreferenceManager;
|
|||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -35,6 +34,7 @@ import org.schabi.newpipe.BuildConfig;
|
|||||||
import org.schabi.newpipe.Downloader;
|
import org.schabi.newpipe.Downloader;
|
||||||
import org.schabi.newpipe.MainActivity;
|
import org.schabi.newpipe.MainActivity;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
import org.schabi.newpipe.ThemableActivity;
|
||||||
import org.schabi.newpipe.extractor.Parser;
|
import org.schabi.newpipe.extractor.Parser;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -65,7 +65,7 @@ import java.util.Vector;
|
|||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ErrorActivity extends AppCompatActivity {
|
public class ErrorActivity extends ThemableActivity {
|
||||||
public static class ErrorInfo implements Parcelable {
|
public static class ErrorInfo implements Parcelable {
|
||||||
public int userAction;
|
public int userAction;
|
||||||
public String request;
|
public String request;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -25,8 +25,8 @@ import android.support.v7.widget.SearchView;
|
|||||||
|
|
||||||
public class SearchSuggestionListener implements SearchView.OnSuggestionListener{
|
public class SearchSuggestionListener implements SearchView.OnSuggestionListener{
|
||||||
|
|
||||||
private SearchView searchView;
|
private final SearchView searchView;
|
||||||
private SuggestionListAdapter adapter;
|
private final SuggestionListAdapter adapter;
|
||||||
|
|
||||||
public SearchSuggestionListener(SearchView searchView, SuggestionListAdapter adapter) {
|
public SearchSuggestionListener(SearchView searchView, SuggestionListAdapter adapter) {
|
||||||
this.searchView = searchView;
|
this.searchView = searchView;
|
||||||
|
@@ -82,6 +82,7 @@ public class SearchWorker {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
final String serviceName = NewPipe.getNameOfService(serviceId);
|
||||||
SearchResult result = null;
|
SearchResult result = null;
|
||||||
SearchEngine engine = null;
|
SearchEngine engine = null;
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ public class SearchWorker {
|
|||||||
View rootView = a.findViewById(android.R.id.content);
|
View rootView = a.findViewById(android.R.id.content);
|
||||||
ErrorActivity.reportError(h, a, result.errors, null, rootView,
|
ErrorActivity.reportError(h, a, result.errors, null, rootView,
|
||||||
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
|
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
|
||||||
/* todo: this shoudl not be assigned static */ YOUTUBE, query, R.string.light_parsing_error));
|
serviceName, query, R.string.light_parsing_error));
|
||||||
|
|
||||||
}
|
}
|
||||||
// hard errors:
|
// hard errors:
|
||||||
@@ -148,8 +149,7 @@ public class SearchWorker {
|
|||||||
} catch(ExtractionException e) {
|
} catch(ExtractionException e) {
|
||||||
ErrorActivity.reportError(h, a, e, null, null,
|
ErrorActivity.reportError(h, a, e, null, null,
|
||||||
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
|
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
|
||||||
/* todo: this shoudl not be assigned static */
|
serviceName, query, R.string.parsing_error));
|
||||||
YOUTUBE, query, R.string.parsing_error));
|
|
||||||
//postNewErrorToast(h, R.string.parsing_error);
|
//postNewErrorToast(h, R.string.parsing_error);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
||||||
|
@@ -3,10 +3,8 @@ package org.schabi.newpipe.search_fragment;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.MatrixCursor;
|
import android.database.MatrixCursor;
|
||||||
import android.support.v4.widget.CursorAdapter;
|
import android.support.v4.widget.ResourceCursorAdapter;
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -31,52 +29,56 @@ import java.util.List;
|
|||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class SuggestionListAdapter extends CursorAdapter {
|
/**
|
||||||
|
* {@link ResourceCursorAdapter} to display suggestions.
|
||||||
|
*/
|
||||||
|
public class SuggestionListAdapter extends ResourceCursorAdapter {
|
||||||
|
|
||||||
|
private static final String[] columns = new String[]{"_id", "title"};
|
||||||
|
private static final int INDEX_ID = 0;
|
||||||
|
private static final int INDEX_TITLE = 1;
|
||||||
|
|
||||||
private String[] columns = new String[]{"_id", "title"};
|
|
||||||
|
|
||||||
public SuggestionListAdapter(Context context) {
|
public SuggestionListAdapter(Context context) {
|
||||||
super(context, null, false);
|
super(context, android.R.layout.simple_list_item_1, null, 0);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
|
||||||
ViewHolder viewHolder;
|
|
||||||
|
|
||||||
View view = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false);
|
|
||||||
viewHolder = new ViewHolder();
|
|
||||||
viewHolder.suggestionTitle = (TextView) view.findViewById(android.R.id.text1);
|
|
||||||
view.setTag(viewHolder);
|
|
||||||
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bindView(View view, Context context, Cursor cursor) {
|
public void bindView(View view, Context context, Cursor cursor) {
|
||||||
ViewHolder viewHolder = (ViewHolder) view.getTag();
|
ViewHolder viewHolder = new ViewHolder(view);
|
||||||
viewHolder.suggestionTitle.setText(cursor.getString(1));
|
viewHolder.suggestionTitle.setText(cursor.getString(INDEX_TITLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the suggestion list
|
||||||
|
* @param suggestions the list of suggestions
|
||||||
|
*/
|
||||||
public void updateAdapter(List<String> suggestions) {
|
public void updateAdapter(List<String> suggestions) {
|
||||||
MatrixCursor cursor = new MatrixCursor(columns);
|
MatrixCursor cursor = new MatrixCursor(columns, suggestions.size());
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (String s : suggestions) {
|
for (String suggestion : suggestions) {
|
||||||
String[] temp = new String[2];
|
String[] columnValues = new String[columns.length];
|
||||||
temp[0] = Integer.toString(i);
|
columnValues[INDEX_TITLE] = suggestion;
|
||||||
temp[1] = s;
|
columnValues[INDEX_ID] = Integer.toString(i);
|
||||||
|
cursor.addRow(columnValues);
|
||||||
i++;
|
i++;
|
||||||
cursor.addRow(temp);
|
|
||||||
}
|
}
|
||||||
changeCursor(cursor);
|
changeCursor(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the suggestion for a position
|
||||||
|
* @param position the position of the suggestion
|
||||||
|
* @return the suggestion
|
||||||
|
*/
|
||||||
public String getSuggestion(int position) {
|
public String getSuggestion(int position) {
|
||||||
return ((Cursor) getItem(position)).getString(1);
|
return ((Cursor) getItem(position)).getString(INDEX_TITLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ViewHolder {
|
private class ViewHolder {
|
||||||
public TextView suggestionTitle;
|
private final TextView suggestionTitle;
|
||||||
|
private ViewHolder(View view) {
|
||||||
|
this.suggestionTitle = (TextView) view.findViewById(android.R.id.text1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user