Update extractor and refactored NewPipe

pull/669/head
Mauricio Colli 5 years ago
parent bddd9b3409
commit 146d4a8365
  1. 34
      app/build.gradle
  2. 20
      app/src/debug/AndroidManifest.xml
  3. 18
      app/src/debug/java/org/schabi/newpipe/DebugApp.java
  4. 36
      app/src/main/AndroidManifest.xml
  5. 2
      app/src/main/java/org/schabi/newpipe/ActivityCommunicator.java
  6. 129
      app/src/main/java/org/schabi/newpipe/App.java
  7. 121
      app/src/main/java/org/schabi/newpipe/BaseFragment.java
  8. 101
      app/src/main/java/org/schabi/newpipe/Downloader.java
  9. 2
      app/src/main/java/org/schabi/newpipe/ExitActivity.java
  10. 65
      app/src/main/java/org/schabi/newpipe/ImageErrorLoadingListener.java
  11. 146
      app/src/main/java/org/schabi/newpipe/MainActivity.java
  12. 33
      app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java
  13. 3
      app/src/main/java/org/schabi/newpipe/PanicResponderActivity.java
  14. 6
      app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
  15. 8
      app/src/main/java/org/schabi/newpipe/RouterActivity.java
  16. 9
      app/src/main/java/org/schabi/newpipe/RouterPopupActivity.java
  17. 9
      app/src/main/java/org/schabi/newpipe/about/AboutActivity.java
  18. 3
      app/src/main/java/org/schabi/newpipe/about/License.java
  19. 6
      app/src/main/java/org/schabi/newpipe/about/LicenseFragment.java
  20. 4
      app/src/main/java/org/schabi/newpipe/database/AppDatabase.java
  21. 2
      app/src/main/java/org/schabi/newpipe/database/BasicDAO.java
  22. 2
      app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.java
  23. 2
      app/src/main/java/org/schabi/newpipe/database/history/dao/WatchHistoryDAO.java
  24. 12
      app/src/main/java/org/schabi/newpipe/database/history/model/WatchHistoryEntry.java
  25. 4
      app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionDAO.java
  26. 50
      app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java
  27. 2
      app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java
  28. 34
      app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java
  29. 1
      app/src/main/java/org/schabi/newpipe/extractor
  30. 13
      app/src/main/java/org/schabi/newpipe/fragments/BackPressable.java
  31. 177
      app/src/main/java/org/schabi/newpipe/fragments/BaseFragment.java
  32. 235
      app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java
  33. 6
      app/src/main/java/org/schabi/newpipe/fragments/BlankFragment.java
  34. 495
      app/src/main/java/org/schabi/newpipe/fragments/FeedFragment.java
  35. 46
      app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java
  36. 43
      app/src/main/java/org/schabi/newpipe/fragments/OnScrollBelowItemsListener.java
  37. 278
      app/src/main/java/org/schabi/newpipe/fragments/SubscriptionFragment.java
  38. 10
      app/src/main/java/org/schabi/newpipe/fragments/ViewContract.java
  39. 570
      app/src/main/java/org/schabi/newpipe/fragments/channel/ChannelFragment.java
  40. 8
      app/src/main/java/org/schabi/newpipe/fragments/detail/ActionBarHandler.java
  41. 6
      app/src/main/java/org/schabi/newpipe/fragments/detail/SpinnerToolbarAdapter.java
  42. 27
      app/src/main/java/org/schabi/newpipe/fragments/detail/StackItem.java
  43. 85
      app/src/main/java/org/schabi/newpipe/fragments/detail/StreamInfoCache.java
  44. 1186
      app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
  45. 239
      app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java
  46. 216
      app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java
  47. 9
      app/src/main/java/org/schabi/newpipe/fragments/list/ListViewContract.java
  48. 383
      app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
  49. 445
      app/src/main/java/org/schabi/newpipe/fragments/list/feed/FeedFragment.java
  50. 174
      app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
  51. 695
      app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
  52. 6
      app/src/main/java/org/schabi/newpipe/fragments/list/search/SuggestionListAdapter.java
  53. 33
      app/src/main/java/org/schabi/newpipe/fragments/search/OnScrollBelowItemsListener.java
  54. 642
      app/src/main/java/org/schabi/newpipe/fragments/search/SearchFragment.java
  55. 240
      app/src/main/java/org/schabi/newpipe/fragments/subscription/SubscriptionFragment.java
  56. 115
      app/src/main/java/org/schabi/newpipe/fragments/subscription/SubscriptionService.java
  57. 53
      app/src/main/java/org/schabi/newpipe/history/HistoryActivity.java
  58. 6
      app/src/main/java/org/schabi/newpipe/history/HistoryEntryAdapter.java
  59. 119
      app/src/main/java/org/schabi/newpipe/history/HistoryFragment.java
  60. 31
      app/src/main/java/org/schabi/newpipe/history/HistoryListener.java
  61. 5
      app/src/main/java/org/schabi/newpipe/history/SearchHistoryFragment.java
  62. 13
      app/src/main/java/org/schabi/newpipe/history/WatchedHistoryFragment.java
  63. 52
      app/src/main/java/org/schabi/newpipe/info_list/ChannelInfoItemHolder.java
  64. 267
      app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java
  65. 33
      app/src/main/java/org/schabi/newpipe/info_list/InfoItemHolder.java
  66. 189
      app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java
  67. 53
      app/src/main/java/org/schabi/newpipe/info_list/StreamInfoItemHolder.java
  68. 65
      app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelInfoItemHolder.java
  69. 73
      app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java
  70. 53
      app/src/main/java/org/schabi/newpipe/info_list/holder/InfoItemHolder.java
  71. 62
      app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistInfoItemHolder.java
  72. 66
      app/src/main/java/org/schabi/newpipe/info_list/holder/StreamInfoItemHolder.java
  73. 82
      app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java
  74. 25
      app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java
  75. 69
      app/src/main/java/org/schabi/newpipe/player/BasePlayer.java
  76. 35
      app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java
  77. 187
      app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java
  78. 68
      app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java
  79. 10
      app/src/main/java/org/schabi/newpipe/player/old/PlayVideoActivity.java
  80. 2
      app/src/main/java/org/schabi/newpipe/report/AcraReportSender.java
  81. 3
      app/src/main/java/org/schabi/newpipe/report/AcraReportSenderFactory.java
  82. 81
      app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java
  83. 14
      app/src/main/java/org/schabi/newpipe/report/UserAction.java
  84. 42
      app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java
  85. 45
      app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java
  86. 12
      app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
  87. 79
      app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java
  88. 12
      app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java
  89. 12
      app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java
  90. 19
      app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java
  91. 37
      app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java
  92. 142
      app/src/main/java/org/schabi/newpipe/settings/SettingsFragment.java
  93. 12
      app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java
  94. 138
      app/src/main/java/org/schabi/newpipe/util/AnimationUtils.java
  95. 236
      app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java
  96. 100
      app/src/main/java/org/schabi/newpipe/util/InfoCache.java
  97. 269
      app/src/main/java/org/schabi/newpipe/util/ListHelper.java
  98. 106
      app/src/main/java/org/schabi/newpipe/util/Localization.java
  99. 148
      app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java
  100. 319
      app/src/main/java/org/schabi/newpipe/util/StateSaver.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -44,27 +44,22 @@ dependencies {
exclude module: 'support-annotations'
}
compile "android.arch.persistence.room:runtime:1.0.0-alpha3"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha3"
compile 'com.github.TeamNewPipe:NewPipeExtractor:97ad1a2'
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'
testCompile 'org.json:json:20160810'
compile 'com.android.support:appcompat-v7:26.0.0'
compile 'com.android.support:support-v4:26.0.0'
compile 'com.android.support:design:26.0.0'
compile 'com.android.support:recyclerview-v7:26.0.0'
compile 'com.android.support:appcompat-v7:26.0.1'
compile 'com.android.support:support-v4:26.0.1'
compile 'com.android.support:design:26.0.1'
compile 'com.android.support:recyclerview-v7:26.0.1'
compile 'com.android.support:preference-v14:26.0.1'
compile 'com.google.code.gson:gson:2.7'
compile 'org.jsoup:jsoup:1.8.3'
compile 'org.mozilla:rhino:1.7.7'
compile 'ch.acra:acra:4.9.0'
compile 'info.guardianproject.netcipher:netcipher:1.2'
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
compile 'de.hdodenhof:circleimageview:2.0.0'
compile 'de.hdodenhof:circleimageview:2.1.0'
compile 'com.github.nirhart:parallaxscroll:1.0'
compile 'com.nononsenseapps:filepicker:3.0.0'
compile 'com.google.android.exoplayer:exoplayer:r2.5.1'
@ -73,11 +68,14 @@ dependencies {
debugCompile 'com.facebook.stetho:stetho-urlconnection:1.5.0'
debugCompile 'com.android.support:multidex:1.0.1'
compile "android.arch.persistence.room:runtime:1.0.0-alpha8"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha8"
compile "io.reactivex.rxjava2:rxjava:2.1.2"
compile "io.reactivex.rxjava2:rxandroid:2.0.1"
compile 'io.reactivex.rxjava2:rxjava:2.1.2'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
compile "android.arch.persistence.room:rxjava2:1.0.0-alpha8"
compile 'android.arch.persistence.room:runtime:1.0.0-alpha8'
compile 'android.arch.persistence.room:rxjava2:1.0.0-alpha8'
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0-alpha8'
compile 'frankiesardo:icepick:3.2.0'
provided 'frankiesardo:icepick-processor:3.2.0'
}

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="org.schabi.newpipe"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
xmlns:tools="http://schemas.android.com/tools"
package="org.schabi.newpipe">
<application
tools:replace="android:name"
android:name=".DebugApp"/>
android:name=".DebugApp"
android:label="NewPipe Debug"
tools:replace="android:name, android:label">
<activity
android:name=".MainActivity"
android:label="NewPipe Debug"
tools:replace="android:label"/>
</application>
</manifest>

@ -5,24 +5,6 @@ import android.support.multidex.MultiDex;
import com.facebook.stetho.Stetho;
/**
* 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 DebugApp extends App {
private static final String TAG = DebugApp.class.toString();

@ -16,7 +16,7 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:logo="@mipmap/ic_launcher"
android:theme="@style/AppTheme"
android:theme="@style/DarkTheme"
tools:ignore="AllowBackup">
<activity
android:name=".MainActivity"
@ -29,7 +29,7 @@
</activity>
<activity
android:name=".player.PlayVideoActivity"
android:name=".player.old.PlayVideoActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/VideoPlayerTheme"
tools:ignore="UnusedAttribute"/>
@ -52,6 +52,15 @@
<activity
android:name=".settings.SettingsActivity"
android:label="@string/settings"/>
<activity
android:name=".about.AboutActivity"
android:label="@string/title_activity_about"/>
<activity
android:name=".history.HistoryActivity"
android:label="@string/title_activity_history"/>
<activity
android:name=".PanicResponderActivity"
android:launchMode="singleInstance"
@ -63,6 +72,7 @@
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity
android:name=".ExitActivity"
android:label="@string/general_error"
@ -73,8 +83,7 @@
<activity
android:name=".download.DownloadActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:theme="@style/AppTheme"/>
android:launchMode="singleTask"/>
<service android:name="us.shandian.giga.service.DownloadManagerService"/>
@ -83,6 +92,7 @@
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/FilePickerTheme"/>
<activity
android:name=".ReCaptchaActivity"
android:label="@string/reCaptchaActivity"/>
@ -122,6 +132,8 @@
<!-- channel prefix -->
<data android:pathPrefix="/channel/"/>
<data android:pathPrefix="/user/"/>
<!-- playlist prefix -->
<data android:pathPrefix="/playlist"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
@ -155,12 +167,11 @@
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
<activity
android:name=".RouterPopupActivity"
android:label="@string/popup_mode_share_menu_title"
android:taskAffinity=""
android:theme="@android:style/Theme.NoDisplay"
android:label="@string/popup_mode_share_menu_title">
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH"/>
@ -210,14 +221,5 @@
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
<activity
android:name=".about.AboutActivity"
android:label="@string/title_activity_about"
android:theme="@style/AppTheme" />
<activity
android:name=".history.HistoryActivity"
android:label="@string/title_activity_history"
android:theme="@style/AppTheme" />
</application>
</manifest>
</manifest>

@ -1,6 +1,6 @@
package org.schabi.newpipe;
/**
/*
* Created by Christian Schabesberger on 24.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>

@ -5,8 +5,8 @@ import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import com.facebook.stetho.Stetho;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
@ -20,12 +20,20 @@ import org.schabi.newpipe.report.AcraReportSenderFactory;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.settings.SettingsActivity;
import org.schabi.newpipe.util.ThemeHelper;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.StateSaver;
import info.guardianproject.netcipher.NetCipher;
import info.guardianproject.netcipher.proxy.OrbotHelper;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.SocketException;
/**
import io.reactivex.annotations.NonNull;
import io.reactivex.exceptions.CompositeException;
import io.reactivex.exceptions.UndeliverableException;
import io.reactivex.functions.Consumer;
import io.reactivex.plugins.RxJavaPlugins;
/*
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
* App.java is part of NewPipe.
*
@ -44,78 +52,83 @@ import info.guardianproject.netcipher.proxy.OrbotHelper;
*/
public class App extends Application {
private static final String TAG = App.class.toString();
protected static final String TAG = App.class.toString();
@SuppressWarnings("unchecked")
private static final Class<? extends ReportSenderFactory>[] reportSenderFactoryClasses = new Class[]{AcraReportSenderFactory.class};
private static boolean useTor;
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
final Class<? extends ReportSenderFactory>[] reportSenderFactoryClasses
= new Class[]{AcraReportSenderFactory.class};
initACRA();
}
@Override
public void onCreate() {
super.onCreate();
// init crashreport
try {
final ACRAConfiguration acraConfig = new ConfigurationBuilder(this)
.setReportSenderFactoryClasses(reportSenderFactoryClasses)
.build();
ACRA.init(this, acraConfig);
} catch(ACRAConfigurationException ace) {
ace.printStackTrace();
ErrorActivity.reportError(this, ace, null, null,
ErrorActivity.ErrorInfo.make(UserAction.SEARCHED,"none",
"Could not initialize ACRA crash report", R.string.app_ui_crash));
}
NewPipeDatabase.getInstance( getApplicationContext() );
// Initialize settings first because others inits can use its values
SettingsActivity.initSettings(this);
//init NewPipe
NewPipe.init(Downloader.getInstance());
NewPipeDatabase.init(this);
StateSaver.init(this);
initNotificationChannel();
// Initialize image loader
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this).build();
ImageLoader.getInstance().init(config);
/*
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if(prefs.getBoolean(getString(R.string.use_tor_key), false)) {
OrbotHelper.requestStartTor(this);
configureTor(true);
} else {
configureTor(false);
}*/
configureTor(false);
// DO NOT REMOVE THIS FUNCTION!!!
// Otherwise downloadPathPreference has invalid value.
SettingsActivity.initSettings(this);
ThemeHelper.setTheme(getApplicationContext());
initNotificationChannel();
configureRxJavaErrorHandler();
}
/**
* Set the proxy settings based on whether Tor should be enabled or not.
*/
public static void configureTor(boolean enabled) {
useTor = enabled;
if (useTor) {
NetCipher.useTor();
} else {
NetCipher.setProxy(null);
}
private void configureRxJavaErrorHandler() {
// https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling
RxJavaPlugins.setErrorHandler(new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
Log.e(TAG, "RxJavaPlugins.ErrorHandler called with -> : throwable = [" + throwable.getClass().getName() + "]");
if (throwable instanceof UndeliverableException) {
// As UndeliverableException is a wrapper, get the cause of it to get the "real" exception
throwable = throwable.getCause();
}
if (throwable instanceof CompositeException) {
for (Throwable element : ((CompositeException) throwable).getExceptions()) {
if (checkThrowable(element)) return;
}
}
if (checkThrowable(throwable)) return;
// Throw uncaught exception that will trigger the report system
Thread.currentThread().getUncaughtExceptionHandler()
.uncaughtException(Thread.currentThread(), throwable);
}
private boolean checkThrowable(@NonNull Throwable throwable) {
// Don't crash the application over a simple network problem
return ExtractorHelper.hasAssignableCauseThrowable(throwable,
IOException.class, SocketException.class, InterruptedException.class, InterruptedIOException.class);
}
});
}
public static void checkStartTor(Context context) {
if (useTor) {
OrbotHelper.requestStartTor(context);
}
}
public static boolean isUsingTor() {
return useTor;
private void initACRA() {
try {
final ACRAConfiguration acraConfig = new ConfigurationBuilder(this)
.setReportSenderFactoryClasses(reportSenderFactoryClasses)
.setBuildConfigClass(BuildConfig.class)
.build();
ACRA.init(this, acraConfig);
} catch (ACRAConfigurationException ace) {
ace.printStackTrace();
ErrorActivity.reportError(this, ace, null, null, ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
"Could not initialize ACRA crash report", R.string.app_ui_crash));
}
}
public void initNotificationChannel() {

@ -0,0 +1,121 @@
package org.schabi.newpipe;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import icepick.Icepick;
public abstract class BaseFragment extends Fragment {
protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode());
protected boolean DEBUG = MainActivity.DEBUG;
protected AppCompatActivity activity;
public static final ImageLoader imageLoader = ImageLoader.getInstance();
/*//////////////////////////////////////////////////////////////////////////
// Fragment's Lifecycle
//////////////////////////////////////////////////////////////////////////*/
@Override
public void onAttach(Context context) {
super.onAttach(context);
activity = (AppCompatActivity) context;
}
@Override
public void onDetach() {
super.onDetach();
activity = null;
}
@Override
public void onCreate(Bundle savedInstanceState) {
if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
super.onCreate(savedInstanceState);
Icepick.restoreInstanceState(this, savedInstanceState);
if (savedInstanceState != null) onRestoreInstanceState(savedInstanceState);
}
@Override
public void onViewCreated(View rootView, Bundle savedInstanceState) {
super.onViewCreated(rootView, savedInstanceState);
if (DEBUG) {
Log.d(TAG, "onViewCreated() called with: rootView = [" + rootView + "], savedInstanceState = [" + savedInstanceState + "]");
}
initViews(rootView, savedInstanceState);
initListeners();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Icepick.saveInstanceState(this, outState);
}
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
}
/*//////////////////////////////////////////////////////////////////////////
// Init
//////////////////////////////////////////////////////////////////////////*/
protected void initViews(View rootView, Bundle savedInstanceState) {
}
protected void initListeners() {
}
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
protected final int resolveResourceIdFromAttr(@AttrRes int attr) {
TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{attr});
int attributeResourceId = a.getResourceId(0, 0);
a.recycle();
return attributeResourceId;
}
/*//////////////////////////////////////////////////////////////////////////
// DisplayImageOptions default configurations
//////////////////////////////////////////////////////////////////////////*/
public static final DisplayImageOptions BASE_OPTIONS =
new DisplayImageOptions.Builder().cacheInMemory(true).build();
public static final DisplayImageOptions DISPLAY_AVATAR_OPTIONS =
new DisplayImageOptions.Builder()
.cloneFrom(BASE_OPTIONS)
.showImageOnLoading(R.drawable.buddy)
.showImageForEmptyUri(R.drawable.buddy)
.showImageOnFail(R.drawable.buddy)
.build();
public static final DisplayImageOptions DISPLAY_THUMBNAIL_OPTIONS =
new DisplayImageOptions.Builder()
.cloneFrom(BASE_OPTIONS)
.displayer(new FadeInBitmapDisplayer(250))
.showImageForEmptyUri(R.drawable.dummy_thumbnail)
.showImageOnFail(R.drawable.dummy_thumbnail)
.build();
public static final DisplayImageOptions DISPLAY_BANNER_OPTIONS =
new DisplayImageOptions.Builder()
.cloneFrom(BASE_OPTIONS)
.showImageOnLoading(R.drawable.channel_banner)
.showImageForEmptyUri(R.drawable.channel_banner)
.showImageOnFail(R.drawable.channel_banner)
.build();
}

@ -1,20 +1,24 @@
package org.schabi.newpipe;
import android.util.Log;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.util.ExtractorHelper;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
/**
/*
* Created by Christian Schabesberger on 28.01.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
@ -35,16 +39,17 @@ import javax.net.ssl.HttpsURLConnection;
*/
public class Downloader implements org.schabi.newpipe.extractor.Downloader {
private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0";
public static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0";
private static String mCookies = "";
private static Downloader instance = null;
private Downloader() {}
private Downloader() {
}
public static Downloader getInstance() {
if(instance == null) {
if (instance == null) {
synchronized (Downloader.class) {
if (instance == null) {
instance = new Downloader();
@ -62,41 +67,66 @@ public class Downloader implements org.schabi.newpipe.extractor.Downloader {
return Downloader.mCookies;
}
/**Download the text file at the supplied URL as in download(String),
/**
* Download the text file at the supplied URL as in download(String),
* but set the HTTP header field "Accept-Language" to the supplied string.
* @param siteUrl the URL of the text file to return the contents of
*
* @param siteUrl the URL of the text file to return the contents of
* @param language the language (usually a 2-character code) to set as the preferred language
* @return the contents of the specified text file*/
* @return the contents of the specified text file
*/
@Override
public String download(String siteUrl, String language) throws IOException, ReCaptchaException {
Map<String, String> requestProperties = new HashMap<>();
requestProperties.put("Accept-Language", language);
return download(siteUrl, requestProperties);
}
/**Download the text file at the supplied URL as in download(String),
* but set the HTTP header field "Accept-Language" to the supplied string.
* @param siteUrl the URL of the text file to return the contents of
/**
* Download the text file at the supplied URL as in download(String),
* but set the HTTP headers included in the customProperties map.
*
* @param siteUrl the URL of the text file to return the contents of
* @param customProperties set request header properties
* @return the contents of the specified text file
* @throws IOException*/
* @throws IOException
*/
@Override
public String download(String siteUrl, Map<String, String> customProperties) throws IOException, ReCaptchaException {
URL url = new URL(siteUrl);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
Iterator it = customProperties.entrySet().iterator();
while(it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
con.setRequestProperty((String)pair.getKey(), (String)pair.getValue());
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
con.setRequestProperty((String) pair.getKey(), (String) pair.getValue());
}
return dl(con);
}
/**Common functionality between download(String url) and download(String url, String language)*/
/**
* Download (via HTTP) the text file located at the supplied URL, and return its contents.
* Primarily intended for downloading web pages.
*
* @param siteUrl the URL of the text file to download
* @return the contents of the specified text file
*/
@Override
public String download(String siteUrl) throws IOException, ReCaptchaException {
URL url = new URL(siteUrl);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
//HttpsURLConnection con = NetCipher.getHttpsURLConnection(url);
return dl(con);
}
/**
* Common functionality between download(String url) and download(String url, String language)
*/
private static String dl(HttpsURLConnection con) throws IOException, ReCaptchaException {
StringBuilder response = new StringBuilder();
BufferedReader in = null;
try {
con.setReadTimeout(30 * 1000);// 30s
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", USER_AGENT);
@ -104,17 +134,22 @@ public class Downloader implements org.schabi.newpipe.extractor.Downloader {
con.setRequestProperty("Cookie", getCookies());
}
in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
in = new BufferedReader(new InputStreamReader(con.getInputStream()));
for (Map.Entry<String, List<String>> entry : con.getHeaderFields().entrySet()) {
System.err.println(entry.getKey() + ": " + entry.getValue());
}
String inputLine;
while((inputLine = in.readLine()) != null) {
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
} catch(UnknownHostException uhe) {//thrown when there's no internet connection
throw new IOException("unknown host or no network", uhe);
//Toast.makeText(getActivity(), uhe.getMessage(), Toast.LENGTH_LONG).show();
} catch(Exception e) {
} catch (Exception e) {
Log.e("Downloader", "dl() ----- Exception thrown → " + e.getClass().getName());
if (ExtractorHelper.isInterruptedCaused(e)) {
throw new InterruptedIOException(e.getMessage());
}
/*
* HTTP 429 == Too Many Request
* Receive from Youtube.com = ReCaptcha challenge request
@ -123,24 +158,14 @@ public class Downloader implements org.schabi.newpipe.extractor.Downloader {
if (con.getResponseCode() == 429) {
throw new ReCaptchaException("reCaptcha Challenge requested");
}
throw new IOException(e);
throw new IOException(con.getResponseCode() + " " + con.getResponseMessage(), e);
} finally {
if(in != null) {
if (in != null) {
in.close();
}
}
return response.toString();
}
/**Download (via HTTP) the text file located at the supplied URL, and return its contents.
* Primarily intended for downloading web pages.
* @param siteUrl the URL of the text file to download
* @return the contents of the specified text file*/
public String download(String siteUrl) throws IOException, ReCaptchaException {
URL url = new URL(siteUrl);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
//HttpsURLConnection con = NetCipher.getHttpsURLConnection(url);
return dl(con);
}
}

@ -7,7 +7,7 @@ import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
/**
/*
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
* ExitActivity.java is part of NewPipe.
*

@ -1,65 +0,0 @@
package org.schabi.newpipe;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.View;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction;
/**
* Created by Christian Schabesberger on 01.08.16.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* StreamInfoItemViewCreator.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 ImageErrorLoadingListener implements ImageLoadingListener {
private int serviceId = -1;
private Context context = null;
private View rootView = null;
public ImageErrorLoadingListener(Context context, View rootView, int serviceId) {
this.context = context;
this.serviceId= serviceId;
this.rootView = rootView;
}
@Override
public void onLoadingStarted(String imageUri, View view) {}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
ErrorActivity.reportError(context,
failReason.getCause(), null, rootView,
ErrorActivity.ErrorInfo.make(UserAction.LOAD_IMAGE,
NewPipe.getNameOfService(serviceId), imageUri,
R.string.could_not_load_image));
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
}
@Override
public void onLoadingCancelled(String imageUri, View view) {}
}

@ -23,6 +23,8 @@ package org.schabi.newpipe;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
@ -43,31 +45,29 @@ import org.schabi.newpipe.database.history.model.HistoryEntry;
import org.schabi.newpipe.database.history.model.SearchHistoryEntry;
import org.schabi.newpipe.database.history.model.WatchHistoryEntry;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.stream_info.AudioStream;
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
import org.schabi.newpipe.extractor.stream_info.VideoStream;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.fragments.BackPressable;
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
import org.schabi.newpipe.fragments.search.SearchFragment;
import org.schabi.newpipe.history.HistoryActivity;
import org.schabi.newpipe.fragments.list.search.SearchFragment;
import org.schabi.newpipe.history.HistoryListener;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.StateSaver;
import org.schabi.newpipe.util.ThemeHelper;
import java.util.Date;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
public class MainActivity extends AppCompatActivity implements
VideoDetailFragment.OnVideoPlayListener,
SearchFragment.OnSearchListener {
public static final boolean DEBUG = false;
public class MainActivity extends AppCompatActivity implements HistoryListener {
private static final String TAG = "MainActivity";
private WatchHistoryDAO watchHistoryDAO;
private SearchHistoryDAO searchHistoryDAO;
public static final boolean DEBUG = false;
private SharedPreferences sharedPreferences;
private PublishSubject<HistoryEntry> historyEntrySubject;
/*//////////////////////////////////////////////////////////////////////////
// Activity's LifeCycle
@ -75,8 +75,7 @@ public class MainActivity extends AppCompatActivity implements
@Override
protected void onCreate(Bundle savedInstanceState) {
if (DEBUG)
Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
ThemeHelper.setTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
@ -87,52 +86,37 @@ public class MainActivity extends AppCompatActivity implements
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
AppDatabase database = NewPipeDatabase.getInstance(this);
watchHistoryDAO = database.watchHistoryDAO();
searchHistoryDAO = database.searchHistoryDAO();
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
historyEntrySubject = PublishSubject.create();
historyEntrySubject
.observeOn(Schedulers.io())
.subscribe(createHistoryEntryConsumer());
}
@NonNull
private Consumer<HistoryEntry> createHistoryEntryConsumer() {
return new Consumer<HistoryEntry>() {
@Override
public void accept(HistoryEntry historyEntry) throws Exception {
//noinspection unchecked
HistoryDAO<HistoryEntry> historyDAO = (HistoryDAO<HistoryEntry>)
(historyEntry instanceof SearchHistoryEntry ? searchHistoryDAO : watchHistoryDAO);
HistoryEntry latestEntry = historyDAO.getLatestEntry();
if (historyEntry.hasEqualValues(latestEntry)) {
latestEntry.setCreationDate(historyEntry.getCreationDate());
historyDAO.update(latestEntry);
} else {
historyDAO.insert(historyEntry);
}
}
};
initHistory();
}
@Override
protected void onDestroy() {
super.onDestroy();
watchHistoryDAO = null;
searchHistoryDAO = null;
if (!isChangingConfigurations()) {
StateSaver.clearStateFiles();
}
disposeHistory();
}
@Override
protected void onResume() {
super.onResume();
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
if (sharedPreferences.getBoolean(Constants.KEY_THEME_CHANGE, false)) {
if (DEBUG) Log.d(TAG, "Theme has changed, recreating activity...");
sharedPreferences.edit().putBoolean(Constants.KEY_THEME_CHANGE, false).apply();
this.recreate();
// https://stackoverflow.com/questions/10844112/runtimeexception-performing-pause-of-activity-that-is-not-resumed
// Briefly, let the activity resume properly posting the recreate call to end of the message queue
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
MainActivity.this.recreate();
}
});
}
}
@ -144,8 +128,7 @@ public class MainActivity extends AppCompatActivity implements
// Return if launched from a launcher (e.g. Nova Launcher, Pixel Launcher ...)
// to not destroy the already created backstack
String action = intent.getAction();
if ((action != null && action.equals(Intent.ACTION_MAIN)) && intent.hasCategory(Intent.CATEGORY_LAUNCHER))
return;
if ((action != null && action.equals(Intent.ACTION_MAIN)) && intent.hasCategory(Intent.CATEGORY_LAUNCHER)) return;
}
super.onNewIntent(intent);
@ -158,8 +141,10 @@ public class MainActivity extends AppCompatActivity implements
if (DEBUG) Log.d(TAG, "onBackPressed() called");
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
if (fragment instanceof VideoDetailFragment)
if (((VideoDetailFragment) fragment).onActivityBackPressed()) return;
// If current fragment implements BackPressable (i.e. can/wanna handle back press) delegate the back press to it
if (fragment instanceof BackPressable) {
if (((BackPressable) fragment).onBackPressed()) return;
}
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
@ -202,23 +187,19 @@ public class MainActivity extends AppCompatActivity implements
int id = item.getItemId();
switch (id) {
case android.R.id.home: {
case android.R.id.home:
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
return true;
}
case R.id.action_settings: {
case R.id.action_settings:
NavigationHelper.openSettings(this);
return true;
}
case R.id.action_show_downloads: {
case R.id.action_show_downloads:
return NavigationHelper.openDownloads(this);
}
case R.id.action_about:
NavigationHelper.openAbout(this);
return true;
case R.id.action_history:
Intent intent = new Intent(this, HistoryActivity.class);
startActivity(intent);
NavigationHelper.openHistory(this);
return true;
default:
return super.onOptionsItemSelected(item);
@ -230,6 +211,8 @@ public class MainActivity extends AppCompatActivity implements
//////////////////////////////////////////////////////////////////////////*/
private void initFragments() {
if (DEBUG) Log.d(TAG, "initFragments() called");
StateSaver.clearStateFiles();
if (getIntent() != null && getIntent().hasExtra(Constants.KEY_LINK_TYPE)) {
handleIntent(getIntent());
} else NavigationHelper.gotoMainFragment(getSupportFragmentManager());
@ -254,6 +237,9 @@ public class MainActivity extends AppCompatActivity implements
case CHANNEL:
NavigationHelper.openChannelFragment(getSupportFragmentManager(), serviceId, url, title);
break;
case PLAYLIST:
NavigationHelper.openPlaylistFragment(getSupportFragmentManager(), serviceId, url, title);
break;
}
} else if (intent.hasExtra(Constants.KEY_OPEN_SEARCH)) {
String searchQuery = intent.getStringExtra(Constants.KEY_QUERY);
@ -265,6 +251,50 @@ public class MainActivity extends AppCompatActivity implements
}
}
/*//////////////////////////////////////////////////////////////////////////
// History
//////////////////////////////////////////////////////////////////////////*/
private WatchHistoryDAO watchHistoryDAO;
private SearchHistoryDAO searchHistoryDAO;
private PublishSubject<HistoryEntry> historyEntrySubject;
private Disposable disposable;
private void initHistory() {
final AppDatabase database = NewPipeDatabase.getInstance();
watchHistoryDAO = database.watchHistoryDAO();
searchHistoryDAO = database.searchHistoryDAO();
historyEntrySubject = PublishSubject.create();
disposable = historyEntrySubject
.observeOn(Schedulers.io())
.subscribe(getHistoryEntryConsumer());
}
private void disposeHistory() {
if (disposable != null) disposable.dispose();
watchHistoryDAO = null;
searchHistoryDAO = null;
}
@NonNull
private Consumer<HistoryEntry> getHistoryEntryConsumer() {
return new Consumer<HistoryEntry>() {
@Override
public void accept(HistoryEntry historyEntry) throws Exception {
//noinspection unchecked
HistoryDAO<HistoryEntry> historyDAO = (HistoryDAO<HistoryEntry>)
(historyEntry instanceof SearchHistoryEntry ? searchHistoryDAO : watchHistoryDAO);
HistoryEntry latestEntry = historyDAO.getLatestEntry();
if (historyEntry.hasEqualValues(latestEntry)) {
latestEntry.setCreationDate(historyEntry.getCreationDate());
historyDAO.update(latestEntry);
} else {
historyDAO.insert(historyEntry);
}
}
};
}
private void addWatchHistoryEntry(StreamInfo streamInfo) {
if (sharedPreferences.getBoolean(getString(R.string.enable_watch_history_key), true)) {
@ -274,12 +304,12 @@ public class MainActivity extends AppCompatActivity implements
}
@Override
public void onVideoPlayed(VideoStream videoStream, StreamInfo streamInfo) {
public void onVideoPlayed(StreamInfo streamInfo, VideoStream videoStream) {
addWatchHistoryEntry(streamInfo);
}
@Override
public void onBackgroundPlayed(StreamInfo streamInfo, AudioStream audioStream) {
public void onAudioPlayed(StreamInfo streamInfo, AudioStream audioStream) {
addWatchHistoryEntry(streamInfo);
}

@ -8,27 +8,24 @@ import org.schabi.newpipe.database.AppDatabase;
import static org.schabi.newpipe.database.AppDatabase.DATABASE_NAME;
public class NewPipeDatabase {
public final class NewPipeDatabase {
private static AppDatabase sInstance;
private static AppDatabase databaseInstance;
// For Singleton instantiation
private static final Object LOCK = new Object();
private NewPipeDatabase() {
//no instance
}
public static void init(Context context) {
databaseInstance = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, DATABASE_NAME
).build();
}
@NonNull
public synchronized static AppDatabase getInstance(Context context) {
if (sInstance == null) {
synchronized (LOCK) {
if (sInstance == null) {
sInstance = Room.databaseBuilder(
context.getApplicationContext(),
AppDatabase.class,
DATABASE_NAME
).build();
}
}
}
return sInstance;
public static AppDatabase getInstance() {
if (databaseInstance == null) throw new RuntimeException("Database not initialized");
return databaseInstance;
}
}

@ -6,9 +6,8 @@ import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.media.AudioManager;
/**
/*
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
* PanicResponderActivity.java is part of NewPipe.
*

@ -16,7 +16,7 @@ import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
/**
/*
* Created by beneth <bmauduit@beneth.fr> on 06.12.16.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
@ -49,7 +49,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
// Set return to Cancel by default
setResult(RESULT_CANCELED);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
@ -59,7 +59,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
actionBar.setDisplayShowTitleEnabled(true);
}
WebView myWebView = (WebView) findViewById(R.id.reCaptchaWebView);
WebView myWebView = findViewById(R.id.reCaptchaWebView);
// Enable Javascript
WebSettings webSettings = myWebView.getSettings();

@ -1,8 +1,8 @@
package org.schabi.newpipe;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
import org.schabi.newpipe.util.NavigationHelper;
@ -32,7 +32,7 @@ import java.util.HashSet;
* This Acitivty is designed to route share/open intents to the specified service, and
* to the part of the service which can handle the url.
*/
public class RouterActivity extends Activity {
public class RouterActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -40,8 +40,6 @@ public class RouterActivity extends Activity {
String videoUrl = getUrl(getIntent());
handleUrl(videoUrl);
finish();
}
protected void handleUrl(String url) {
@ -50,6 +48,8 @@ public class RouterActivity extends Activity {
} catch (Exception e) {
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
}
finish();
}
/*//////////////////////////////////////////////////////////////////////////

@ -6,6 +6,7 @@ import android.widget.Toast;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.player.PopupVideoPlayer;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.PermissionHelper;
@ -22,8 +23,10 @@ public class RouterPopupActivity extends RouterActivity {
Toast.makeText(this, R.string.msg_popup_permission, Toast.LENGTH_LONG).show();
return;
}
StreamingService service = NewPipe.getServiceByUrl(url);
if (service == null) {
StreamingService service;
try {
service = NewPipe.getServiceByUrl(url);
} catch (ExtractionException e) {
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
return;
}
@ -40,5 +43,7 @@ public class RouterPopupActivity extends RouterActivity {
callIntent.putExtra(Constants.KEY_URL, url);
callIntent.putExtra(Constants.KEY_SERVICE_ID, service.getServiceId());
startService(callIntent);
finish();
}
}

@ -36,7 +36,6 @@ public class AboutActivity extends AppCompatActivity {
new SoftwareComponent("Rhino", "2015", "Mozilla", "https://www.mozilla.org/rhino/", StandardLicenses.MPL2),
new SoftwareComponent("ACRA", "2013", "Kevin Gaudin", "http://www.acra.ch", StandardLicenses.APACHE2),
new SoftwareComponent("Universal Image Loader", "2011 - 2015", "Sergey Tarasevich", "https://github.com/nostra13/Android-Universal-Image-Loader", StandardLicenses.APACHE2),
new SoftwareComponent("Netcipher", "2015", "The Guardian Project", "https://guardianproject.info/code/netcipher/", StandardLicenses.APACHE2),
new SoftwareComponent("CircleImageView", "2014 - 2017", "Henning Dodenhof", "https://github.com/hdodenhof/CircleImageView", StandardLicenses.APACHE2),
new SoftwareComponent("ParalaxScrollView", "2014", "Nir Hartmann", "https://github.com/nirhart/ParallaxScroll", StandardLicenses.MIT),
new SoftwareComponent("NoNonsense-FilePicker", "2016", "Jonas Kalderstam", "https://github.com/spacecowboy/NoNonsense-FilePicker", StandardLicenses.MPL2),
@ -68,7 +67,7 @@ public class AboutActivity extends AppCompatActivity {
setContentView(R.layout.activity_about);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Create the adapter that will return a fragment for each of the three
@ -76,10 +75,10 @@ public class AboutActivity extends AppCompatActivity {
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager = findViewById(R.id.container);</