Merge pull request #4138 from XiangRongLin/checkstyle_final
Add checkstyle rule to show final local variable violations as warning
This commit is contained in:
commit
5485e994ee
|
@ -21,13 +21,13 @@ public class ErrorInfoTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void errorInfoTestParcelable() {
|
public void errorInfoTestParcelable() {
|
||||||
ErrorInfo info = ErrorInfo.make(UserAction.USER_REPORT, "youtube", "request",
|
final ErrorInfo info = ErrorInfo.make(UserAction.USER_REPORT, "youtube", "request",
|
||||||
R.string.general_error);
|
R.string.general_error);
|
||||||
// Obtain a Parcel object and write the parcelable object to it:
|
// Obtain a Parcel object and write the parcelable object to it:
|
||||||
Parcel parcel = Parcel.obtain();
|
final Parcel parcel = Parcel.obtain();
|
||||||
info.writeToParcel(parcel, 0);
|
info.writeToParcel(parcel, 0);
|
||||||
parcel.setDataPosition(0);
|
parcel.setDataPosition(0);
|
||||||
ErrorInfo infoFromParcel = ErrorInfo.CREATOR.createFromParcel(parcel);
|
final ErrorInfo infoFromParcel = ErrorInfo.CREATOR.createFromParcel(parcel);
|
||||||
|
|
||||||
assertEquals(UserAction.USER_REPORT, infoFromParcel.userAction);
|
assertEquals(UserAction.USER_REPORT, infoFromParcel.userAction);
|
||||||
assertEquals("youtube", infoFromParcel.serviceName);
|
assertEquals("youtube", infoFromParcel.serviceName);
|
||||||
|
|
|
@ -150,7 +150,7 @@ public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapt
|
||||||
// from its saved state, where the fragment manager has already
|
// from its saved state, where the fragment manager has already
|
||||||
// taken care of restoring the fragments we previously had instantiated.
|
// taken care of restoring the fragments we previously had instantiated.
|
||||||
if (mFragments.size() > position) {
|
if (mFragments.size() > position) {
|
||||||
Fragment f = mFragments.get(position);
|
final Fragment f = mFragments.get(position);
|
||||||
if (f != null) {
|
if (f != null) {
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
@ -160,12 +160,12 @@ public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapt
|
||||||
mCurTransaction = mFragmentManager.beginTransaction();
|
mCurTransaction = mFragmentManager.beginTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
Fragment fragment = getItem(position);
|
final Fragment fragment = getItem(position);
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
|
Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
|
||||||
}
|
}
|
||||||
if (mSavedState.size() > position) {
|
if (mSavedState.size() > position) {
|
||||||
Fragment.SavedState fss = mSavedState.get(position);
|
final Fragment.SavedState fss = mSavedState.get(position);
|
||||||
if (fss != null) {
|
if (fss != null) {
|
||||||
fragment.setInitialSavedState(fss);
|
fragment.setInitialSavedState(fss);
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapt
|
||||||
@Override
|
@Override
|
||||||
public void destroyItem(@NonNull final ViewGroup container, final int position,
|
public void destroyItem(@NonNull final ViewGroup container, final int position,
|
||||||
@NonNull final Object object) {
|
@NonNull final Object object) {
|
||||||
Fragment fragment = (Fragment) object;
|
final Fragment fragment = (Fragment) object;
|
||||||
|
|
||||||
if (mCurTransaction == null) {
|
if (mCurTransaction == null) {
|
||||||
mCurTransaction = mFragmentManager.beginTransaction();
|
mCurTransaction = mFragmentManager.beginTransaction();
|
||||||
|
@ -217,7 +217,7 @@ public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapt
|
||||||
@SuppressWarnings({"ReferenceEquality", "deprecation"})
|
@SuppressWarnings({"ReferenceEquality", "deprecation"})
|
||||||
public void setPrimaryItem(@NonNull final ViewGroup container, final int position,
|
public void setPrimaryItem(@NonNull final ViewGroup container, final int position,
|
||||||
@NonNull final Object object) {
|
@NonNull final Object object) {
|
||||||
Fragment fragment = (Fragment) object;
|
final Fragment fragment = (Fragment) object;
|
||||||
if (fragment != mCurrentPrimaryItem) {
|
if (fragment != mCurrentPrimaryItem) {
|
||||||
if (mCurrentPrimaryItem != null) {
|
if (mCurrentPrimaryItem != null) {
|
||||||
mCurrentPrimaryItem.setMenuVisibility(false);
|
mCurrentPrimaryItem.setMenuVisibility(false);
|
||||||
|
@ -267,17 +267,17 @@ public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapt
|
||||||
Bundle state = null;
|
Bundle state = null;
|
||||||
if (mSavedState.size() > 0) {
|
if (mSavedState.size() > 0) {
|
||||||
state = new Bundle();
|
state = new Bundle();
|
||||||
Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
|
final Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
|
||||||
mSavedState.toArray(fss);
|
mSavedState.toArray(fss);
|
||||||
state.putParcelableArray("states", fss);
|
state.putParcelableArray("states", fss);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < mFragments.size(); i++) {
|
for (int i = 0; i < mFragments.size(); i++) {
|
||||||
Fragment f = mFragments.get(i);
|
final Fragment f = mFragments.get(i);
|
||||||
if (f != null && f.isAdded()) {
|
if (f != null && f.isAdded()) {
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
state = new Bundle();
|
state = new Bundle();
|
||||||
}
|
}
|
||||||
String key = "f" + i;
|
final String key = "f" + i;
|
||||||
mFragmentManager.putFragment(state, key, f);
|
mFragmentManager.putFragment(state, key, f);
|
||||||
|
|
||||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
@ -294,9 +294,9 @@ public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapt
|
||||||
@Override
|
@Override
|
||||||
public void restoreState(@Nullable final Parcelable state, @Nullable final ClassLoader loader) {
|
public void restoreState(@Nullable final Parcelable state, @Nullable final ClassLoader loader) {
|
||||||
if (state != null) {
|
if (state != null) {
|
||||||
Bundle bundle = (Bundle) state;
|
final Bundle bundle = (Bundle) state;
|
||||||
bundle.setClassLoader(loader);
|
bundle.setClassLoader(loader);
|
||||||
Parcelable[] fss = bundle.getParcelableArray("states");
|
final Parcelable[] fss = bundle.getParcelableArray("states");
|
||||||
mSavedState.clear();
|
mSavedState.clear();
|
||||||
mFragments.clear();
|
mFragments.clear();
|
||||||
if (fss != null) {
|
if (fss != null) {
|
||||||
|
@ -304,11 +304,11 @@ public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapt
|
||||||
mSavedState.add((Fragment.SavedState) fss[i]);
|
mSavedState.add((Fragment.SavedState) fss[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Iterable<String> keys = bundle.keySet();
|
final Iterable<String> keys = bundle.keySet();
|
||||||
for (String key: keys) {
|
for (final String key : keys) {
|
||||||
if (key.startsWith("f")) {
|
if (key.startsWith("f")) {
|
||||||
int index = Integer.parseInt(key.substring(1));
|
final int index = Integer.parseInt(key.substring(1));
|
||||||
Fragment f = mFragmentManager.getFragment(bundle, key);
|
final Fragment f = mFragmentManager.getFragment(bundle, key);
|
||||||
if (f != null) {
|
if (f != null) {
|
||||||
while (mFragments.size() <= index) {
|
while (mFragments.size() <= index) {
|
||||||
mFragments.add(null);
|
mFragments.add(null);
|
||||||
|
|
|
@ -30,19 +30,18 @@ public final class FlingBehavior extends AppBarLayout.Behavior {
|
||||||
public boolean onRequestChildRectangleOnScreen(
|
public boolean onRequestChildRectangleOnScreen(
|
||||||
@NonNull final CoordinatorLayout coordinatorLayout, @NonNull final AppBarLayout child,
|
@NonNull final CoordinatorLayout coordinatorLayout, @NonNull final AppBarLayout child,
|
||||||
@NonNull final Rect rectangle, final boolean immediate) {
|
@NonNull final Rect rectangle, final boolean immediate) {
|
||||||
|
|
||||||
focusScrollRect.set(rectangle);
|
focusScrollRect.set(rectangle);
|
||||||
|
|
||||||
coordinatorLayout.offsetDescendantRectToMyCoords(child, focusScrollRect);
|
coordinatorLayout.offsetDescendantRectToMyCoords(child, focusScrollRect);
|
||||||
|
|
||||||
int height = coordinatorLayout.getHeight();
|
final int height = coordinatorLayout.getHeight();
|
||||||
|
|
||||||
if (focusScrollRect.top <= 0 && focusScrollRect.bottom >= height) {
|
if (focusScrollRect.top <= 0 && focusScrollRect.bottom >= height) {
|
||||||
// the child is too big to fit inside ourselves completely, ignore request
|
// the child is too big to fit inside ourselves completely, ignore request
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dy;
|
final int dy;
|
||||||
|
|
||||||
if (focusScrollRect.bottom > height) {
|
if (focusScrollRect.bottom > height) {
|
||||||
dy = focusScrollRect.top;
|
dy = focusScrollRect.top;
|
||||||
|
@ -54,7 +53,7 @@ public final class FlingBehavior extends AppBarLayout.Behavior {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int consumed = scroll(coordinatorLayout, child, dy, getMaxDragOffset(child), 0);
|
final int consumed = scroll(coordinatorLayout, child, dy, getMaxDragOffset(child), 0);
|
||||||
|
|
||||||
return consumed == dy;
|
return consumed == dy;
|
||||||
}
|
}
|
||||||
|
@ -106,14 +105,14 @@ public final class FlingBehavior extends AppBarLayout.Behavior {
|
||||||
@Nullable
|
@Nullable
|
||||||
private OverScroller getScrollerField() {
|
private OverScroller getScrollerField() {
|
||||||
try {
|
try {
|
||||||
Class<?> headerBehaviorType = this.getClass()
|
final Class<?> headerBehaviorType = this.getClass()
|
||||||
.getSuperclass().getSuperclass().getSuperclass();
|
.getSuperclass().getSuperclass().getSuperclass();
|
||||||
if (headerBehaviorType != null) {
|
if (headerBehaviorType != null) {
|
||||||
Field field = headerBehaviorType.getDeclaredField("scroller");
|
final Field field = headerBehaviorType.getDeclaredField("scroller");
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
return ((OverScroller) field.get(this));
|
return ((OverScroller) field.get(this));
|
||||||
}
|
}
|
||||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
} catch (final NoSuchFieldException | IllegalAccessException e) {
|
||||||
// ?
|
// ?
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -122,34 +121,35 @@ public final class FlingBehavior extends AppBarLayout.Behavior {
|
||||||
@Nullable
|
@Nullable
|
||||||
private Field getLastNestedScrollingChildRefField() {
|
private Field getLastNestedScrollingChildRefField() {
|
||||||
try {
|
try {
|
||||||
Class<?> headerBehaviorType = this.getClass().getSuperclass().getSuperclass();
|
final Class<?> headerBehaviorType = this.getClass().getSuperclass().getSuperclass();
|
||||||
if (headerBehaviorType != null) {
|
if (headerBehaviorType != null) {
|
||||||
Field field = headerBehaviorType.getDeclaredField("lastNestedScrollingChildRef");
|
final Field field
|
||||||
|
= headerBehaviorType.getDeclaredField("lastNestedScrollingChildRef");
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (final NoSuchFieldException e) {
|
||||||
// ?
|
// ?
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetNestedScrollingChild() {
|
private void resetNestedScrollingChild() {
|
||||||
Field field = getLastNestedScrollingChildRefField();
|
final Field field = getLastNestedScrollingChildRefField();
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
try {
|
try {
|
||||||
Object value = field.get(this);
|
final Object value = field.get(this);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
field.set(this, null);
|
field.set(this, null);
|
||||||
}
|
}
|
||||||
} catch (IllegalAccessException e) {
|
} catch (final IllegalAccessException e) {
|
||||||
// ?
|
// ?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopAppBarLayoutFling() {
|
private void stopAppBarLayoutFling() {
|
||||||
OverScroller scroller = getScrollerField();
|
final OverScroller scroller = getScrollerField();
|
||||||
if (scroller != null) {
|
if (scroller != null) {
|
||||||
scroller.forceFinished(true);
|
scroller.forceFinished(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ public class App extends Application {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Downloader getDownloader() {
|
protected Downloader getDownloader() {
|
||||||
DownloaderImpl downloader = DownloaderImpl.init(null);
|
final DownloaderImpl downloader = DownloaderImpl.init(null);
|
||||||
setCookiesToDownloader(downloader);
|
setCookiesToDownloader(downloader);
|
||||||
return downloader;
|
return downloader;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ public class App extends Application {
|
||||||
.setBuildConfigClass(BuildConfig.class)
|
.setBuildConfigClass(BuildConfig.class)
|
||||||
.build();
|
.build();
|
||||||
ACRA.init(this, acraConfig);
|
ACRA.init(this, acraConfig);
|
||||||
} catch (ACRAConfigurationException ace) {
|
} catch (final ACRAConfigurationException ace) {
|
||||||
ace.printStackTrace();
|
ace.printStackTrace();
|
||||||
ErrorActivity.reportError(this,
|
ErrorActivity.reportError(this,
|
||||||
ace,
|
ace,
|
||||||
|
@ -231,10 +231,10 @@ public class App extends Application {
|
||||||
// Keep this below DEFAULT to avoid making noise on every notification update
|
// Keep this below DEFAULT to avoid making noise on every notification update
|
||||||
final int importance = NotificationManager.IMPORTANCE_LOW;
|
final int importance = NotificationManager.IMPORTANCE_LOW;
|
||||||
|
|
||||||
NotificationChannel mChannel = new NotificationChannel(id, name, importance);
|
final NotificationChannel mChannel = new NotificationChannel(id, name, importance);
|
||||||
mChannel.setDescription(description);
|
mChannel.setDescription(description);
|
||||||
|
|
||||||
NotificationManager mNotificationManager =
|
final NotificationManager mNotificationManager =
|
||||||
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
mNotificationManager.createNotificationChannel(mChannel);
|
mNotificationManager.createNotificationChannel(mChannel);
|
||||||
|
|
||||||
|
@ -255,11 +255,11 @@ public class App extends Application {
|
||||||
final String appUpdateDescription
|
final String appUpdateDescription
|
||||||
= getString(R.string.app_update_notification_channel_description);
|
= getString(R.string.app_update_notification_channel_description);
|
||||||
|
|
||||||
NotificationChannel appUpdateChannel
|
final NotificationChannel appUpdateChannel
|
||||||
= new NotificationChannel(appUpdateId, appUpdateName, importance);
|
= new NotificationChannel(appUpdateId, appUpdateName, importance);
|
||||||
appUpdateChannel.setDescription(appUpdateDescription);
|
appUpdateChannel.setDescription(appUpdateDescription);
|
||||||
|
|
||||||
NotificationManager appUpdateNotificationManager
|
final NotificationManager appUpdateNotificationManager
|
||||||
= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
appUpdateNotificationManager.createNotificationChannel(appUpdateChannel);
|
appUpdateNotificationManager.createNotificationChannel(appUpdateChannel);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
packageInfo = pm.getPackageInfo(packageName, flags);
|
packageInfo = pm.getPackageInfo(packageName, flags);
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (final PackageManager.NameNotFoundException e) {
|
||||||
ErrorActivity.reportError(APP, e, null, null,
|
ErrorActivity.reportError(APP, e, null, null,
|
||||||
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
||||||
"Could not find package info", R.string.app_ui_crash));
|
"Could not find package info", R.string.app_ui_crash));
|
||||||
|
@ -77,7 +77,7 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
|
||||||
try {
|
try {
|
||||||
final CertificateFactory cf = CertificateFactory.getInstance("X509");
|
final CertificateFactory cf = CertificateFactory.getInstance("X509");
|
||||||
c = (X509Certificate) cf.generateCertificate(input);
|
c = (X509Certificate) cf.generateCertificate(input);
|
||||||
} catch (CertificateException e) {
|
} catch (final CertificateException e) {
|
||||||
ErrorActivity.reportError(APP, e, null, null,
|
ErrorActivity.reportError(APP, e, null, null,
|
||||||
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
||||||
"Certificate error", R.string.app_ui_crash));
|
"Certificate error", R.string.app_ui_crash));
|
||||||
|
@ -86,7 +86,7 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
|
||||||
String hexString = null;
|
String hexString = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
MessageDigest md = MessageDigest.getInstance("SHA1");
|
final MessageDigest md = MessageDigest.getInstance("SHA1");
|
||||||
final byte[] publicKey = md.digest(c.getEncoded());
|
final byte[] publicKey = md.digest(c.getEncoded());
|
||||||
hexString = byte2HexFormatted(publicKey);
|
hexString = byte2HexFormatted(publicKey);
|
||||||
} catch (NoSuchAlgorithmException | CertificateEncodingException e) {
|
} catch (NoSuchAlgorithmException | CertificateEncodingException e) {
|
||||||
|
@ -167,7 +167,7 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
|
||||||
|
|
||||||
compareAppVersionAndShowNotification(versionName, apkLocationUrl, versionCode);
|
compareAppVersionAndShowNotification(versionName, apkLocationUrl, versionCode);
|
||||||
|
|
||||||
} catch (JsonParserException e) {
|
} catch (final JsonParserException e) {
|
||||||
// connectivity problems, do not alarm user and fail silently
|
// connectivity problems, do not alarm user and fail silently
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.w(TAG, Log.getStackTraceString(e));
|
Log.w(TAG, Log.getStackTraceString(e));
|
||||||
|
@ -187,7 +187,7 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
|
||||||
private void compareAppVersionAndShowNotification(final String versionName,
|
private void compareAppVersionAndShowNotification(final String versionName,
|
||||||
final String apkLocationUrl,
|
final String apkLocationUrl,
|
||||||
final int versionCode) {
|
final int versionCode) {
|
||||||
int notificationId = 2000;
|
final int notificationId = 2000;
|
||||||
|
|
||||||
if (BuildConfig.VERSION_CODE < versionCode) {
|
if (BuildConfig.VERSION_CODE < versionCode) {
|
||||||
|
|
||||||
|
|
|
@ -94,18 +94,18 @@ public final class DownloaderImpl extends Downloader {
|
||||||
private static void enableModernTLS(final OkHttpClient.Builder builder) {
|
private static void enableModernTLS(final OkHttpClient.Builder builder) {
|
||||||
try {
|
try {
|
||||||
// get the default TrustManager
|
// get the default TrustManager
|
||||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
|
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
|
||||||
TrustManagerFactory.getDefaultAlgorithm());
|
TrustManagerFactory.getDefaultAlgorithm());
|
||||||
trustManagerFactory.init((KeyStore) null);
|
trustManagerFactory.init((KeyStore) null);
|
||||||
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
|
final TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
|
||||||
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
|
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
|
||||||
throw new IllegalStateException("Unexpected default trust managers:"
|
throw new IllegalStateException("Unexpected default trust managers:"
|
||||||
+ Arrays.toString(trustManagers));
|
+ Arrays.toString(trustManagers));
|
||||||
}
|
}
|
||||||
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
|
final X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
|
||||||
|
|
||||||
// insert our own TLSSocketFactory
|
// insert our own TLSSocketFactory
|
||||||
SSLSocketFactory sslSocketFactory = TLSSocketFactoryCompat.getInstance();
|
final SSLSocketFactory sslSocketFactory = TLSSocketFactoryCompat.getInstance();
|
||||||
|
|
||||||
builder.sslSocketFactory(sslSocketFactory, trustManager);
|
builder.sslSocketFactory(sslSocketFactory, trustManager);
|
||||||
|
|
||||||
|
@ -114,16 +114,16 @@ public final class DownloaderImpl extends Downloader {
|
||||||
// Necessary because some servers (e.g. Framatube.org)
|
// Necessary because some servers (e.g. Framatube.org)
|
||||||
// don't support the old cipher suites.
|
// don't support the old cipher suites.
|
||||||
// https://github.com/square/okhttp/issues/4053#issuecomment-402579554
|
// https://github.com/square/okhttp/issues/4053#issuecomment-402579554
|
||||||
List<CipherSuite> cipherSuites = new ArrayList<>();
|
final List<CipherSuite> cipherSuites = new ArrayList<>();
|
||||||
cipherSuites.addAll(ConnectionSpec.MODERN_TLS.cipherSuites());
|
cipherSuites.addAll(ConnectionSpec.MODERN_TLS.cipherSuites());
|
||||||
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
|
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
|
||||||
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
|
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
|
||||||
ConnectionSpec legacyTLS = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
final ConnectionSpec legacyTLS = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
||||||
.cipherSuites(cipherSuites.toArray(new CipherSuite[0]))
|
.cipherSuites(cipherSuites.toArray(new CipherSuite[0]))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
builder.connectionSpecs(Arrays.asList(legacyTLS, ConnectionSpec.CLEARTEXT));
|
builder.connectionSpecs(Arrays.asList(legacyTLS, ConnectionSpec.CLEARTEXT));
|
||||||
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
|
} catch (final KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -131,15 +131,15 @@ public final class DownloaderImpl extends Downloader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCookies(final String url) {
|
public String getCookies(final String url) {
|
||||||
List<String> resultCookies = new ArrayList<>();
|
final List<String> resultCookies = new ArrayList<>();
|
||||||
if (url.contains(YOUTUBE_DOMAIN)) {
|
if (url.contains(YOUTUBE_DOMAIN)) {
|
||||||
String youtubeCookie = getCookie(YOUTUBE_RESTRICTED_MODE_COOKIE_KEY);
|
final String youtubeCookie = getCookie(YOUTUBE_RESTRICTED_MODE_COOKIE_KEY);
|
||||||
if (youtubeCookie != null) {
|
if (youtubeCookie != null) {
|
||||||
resultCookies.add(youtubeCookie);
|
resultCookies.add(youtubeCookie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Recaptcha cookie is always added TODO: not sure if this is necessary
|
// Recaptcha cookie is always added TODO: not sure if this is necessary
|
||||||
String recaptchaCookie = getCookie(ReCaptchaActivity.RECAPTCHA_COOKIES_KEY);
|
final String recaptchaCookie = getCookie(ReCaptchaActivity.RECAPTCHA_COOKIES_KEY);
|
||||||
if (recaptchaCookie != null) {
|
if (recaptchaCookie != null) {
|
||||||
resultCookies.add(recaptchaCookie);
|
resultCookies.add(recaptchaCookie);
|
||||||
}
|
}
|
||||||
|
@ -159,9 +159,9 @@ public final class DownloaderImpl extends Downloader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateYoutubeRestrictedModeCookies(final Context context) {
|
public void updateYoutubeRestrictedModeCookies(final Context context) {
|
||||||
String restrictedModeEnabledKey =
|
final String restrictedModeEnabledKey =
|
||||||
context.getString(R.string.youtube_restricted_mode_enabled);
|
context.getString(R.string.youtube_restricted_mode_enabled);
|
||||||
boolean restrictedModeEnabled = PreferenceManager.getDefaultSharedPreferences(context)
|
final boolean restrictedModeEnabled = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
.getBoolean(restrictedModeEnabledKey, false);
|
.getBoolean(restrictedModeEnabledKey, false);
|
||||||
updateYoutubeRestrictedModeCookies(restrictedModeEnabled);
|
updateYoutubeRestrictedModeCookies(restrictedModeEnabled);
|
||||||
}
|
}
|
||||||
|
@ -186,9 +186,9 @@ public final class DownloaderImpl extends Downloader {
|
||||||
try {
|
try {
|
||||||
final Response response = head(url);
|
final Response response = head(url);
|
||||||
return Long.parseLong(response.getHeader("Content-Length"));
|
return Long.parseLong(response.getHeader("Content-Length"));
|
||||||
} catch (NumberFormatException e) {
|
} catch (final NumberFormatException e) {
|
||||||
throw new IOException("Invalid content length", e);
|
throw new IOException("Invalid content length", e);
|
||||||
} catch (ReCaptchaException e) {
|
} catch (final ReCaptchaException e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ public final class DownloaderImpl extends Downloader {
|
||||||
.method("GET", null).url(siteUrl)
|
.method("GET", null).url(siteUrl)
|
||||||
.addHeader("User-Agent", USER_AGENT);
|
.addHeader("User-Agent", USER_AGENT);
|
||||||
|
|
||||||
String cookies = getCookies(siteUrl);
|
final String cookies = getCookies(siteUrl);
|
||||||
if (!cookies.isEmpty()) {
|
if (!cookies.isEmpty()) {
|
||||||
requestBuilder.addHeader("Cookie", cookies);
|
requestBuilder.addHeader("Cookie", cookies);
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,7 @@ public final class DownloaderImpl extends Downloader {
|
||||||
}
|
}
|
||||||
|
|
||||||
return body.byteStream();
|
return body.byteStream();
|
||||||
} catch (ReCaptchaException e) {
|
} catch (final ReCaptchaException e) {
|
||||||
throw new IOException(e.getMessage(), e.getCause());
|
throw new IOException(e.getMessage(), e.getCause());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,18 +240,18 @@ public final class DownloaderImpl extends Downloader {
|
||||||
.method(httpMethod, requestBody).url(url)
|
.method(httpMethod, requestBody).url(url)
|
||||||
.addHeader("User-Agent", USER_AGENT);
|
.addHeader("User-Agent", USER_AGENT);
|
||||||
|
|
||||||
String cookies = getCookies(url);
|
final String cookies = getCookies(url);
|
||||||
if (!cookies.isEmpty()) {
|
if (!cookies.isEmpty()) {
|
||||||
requestBuilder.addHeader("Cookie", cookies);
|
requestBuilder.addHeader("Cookie", cookies);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, List<String>> pair : headers.entrySet()) {
|
for (final Map.Entry<String, List<String>> pair : headers.entrySet()) {
|
||||||
final String headerName = pair.getKey();
|
final String headerName = pair.getKey();
|
||||||
final List<String> headerValueList = pair.getValue();
|
final List<String> headerValueList = pair.getValue();
|
||||||
|
|
||||||
if (headerValueList.size() > 1) {
|
if (headerValueList.size() > 1) {
|
||||||
requestBuilder.removeHeader(headerName);
|
requestBuilder.removeHeader(headerName);
|
||||||
for (String headerValue : headerValueList) {
|
for (final String headerValue : headerValueList) {
|
||||||
requestBuilder.addHeader(headerName, headerValue);
|
requestBuilder.addHeader(headerName, headerValue);
|
||||||
}
|
}
|
||||||
} else if (headerValueList.size() == 1) {
|
} else if (headerValueList.size() == 1) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ import android.os.Bundle;
|
||||||
public class ExitActivity extends Activity {
|
public class ExitActivity extends Activity {
|
||||||
|
|
||||||
public static void exitAndRemoveFromRecentApps(final Activity activity) {
|
public static void exitAndRemoveFromRecentApps(final Activity activity) {
|
||||||
Intent intent = new Intent(activity, ExitActivity.class);
|
final Intent intent = new Intent(activity, ExitActivity.class);
|
||||||
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
|
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
|
||||||
|
|
|
@ -140,7 +140,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
setSupportActionBar(findViewById(R.id.toolbar));
|
setSupportActionBar(findViewById(R.id.toolbar));
|
||||||
try {
|
try {
|
||||||
setupDrawer();
|
setupDrawer();
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError(this, e);
|
ErrorActivity.reportUiError(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,8 +155,8 @@ public class MainActivity extends AppCompatActivity {
|
||||||
drawerItems = findViewById(R.id.navigation);
|
drawerItems = findViewById(R.id.navigation);
|
||||||
|
|
||||||
//Tabs
|
//Tabs
|
||||||
int currentServiceId = ServiceHelper.getSelectedServiceId(this);
|
final int currentServiceId = ServiceHelper.getSelectedServiceId(this);
|
||||||
StreamingService service = NewPipe.getService(currentServiceId);
|
final StreamingService service = NewPipe.getService(currentServiceId);
|
||||||
|
|
||||||
int kioskId = 0;
|
int kioskId = 0;
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
case R.id.menu_tabs_group:
|
case R.id.menu_tabs_group:
|
||||||
try {
|
try {
|
||||||
tabSelected(item);
|
tabSelected(item);
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError(this, e);
|
ErrorActivity.reportUiError(this, e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -269,8 +269,8 @@ public class MainActivity extends AppCompatActivity {
|
||||||
NavigationHelper.openStatisticFragment(getSupportFragmentManager());
|
NavigationHelper.openStatisticFragment(getSupportFragmentManager());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
int currentServiceId = ServiceHelper.getSelectedServiceId(this);
|
final int currentServiceId = ServiceHelper.getSelectedServiceId(this);
|
||||||
StreamingService service = NewPipe.getService(currentServiceId);
|
final StreamingService service = NewPipe.getService(currentServiceId);
|
||||||
String serviceName = "";
|
String serviceName = "";
|
||||||
|
|
||||||
int kioskId = 0;
|
int kioskId = 0;
|
||||||
|
@ -299,8 +299,8 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupDrawerHeader() {
|
private void setupDrawerHeader() {
|
||||||
NavigationView navigationView = findViewById(R.id.navigation);
|
final NavigationView navigationView = findViewById(R.id.navigation);
|
||||||
View hView = navigationView.getHeaderView(0);
|
final View hView = navigationView.getHeaderView(0);
|
||||||
|
|
||||||
serviceArrow = hView.findViewById(R.id.drawer_arrow);
|
serviceArrow = hView.findViewById(R.id.drawer_arrow);
|
||||||
headerServiceIcon = hView.findViewById(R.id.drawer_header_service_icon);
|
headerServiceIcon = hView.findViewById(R.id.drawer_header_service_icon);
|
||||||
|
@ -335,7 +335,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
showTabs();
|
showTabs();
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError(this, e);
|
ErrorActivity.reportUiError(this, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,11 +344,11 @@ public class MainActivity extends AppCompatActivity {
|
||||||
private void showServices() {
|
private void showServices() {
|
||||||
serviceArrow.setImageResource(R.drawable.ic_arrow_drop_up_white_24dp);
|
serviceArrow.setImageResource(R.drawable.ic_arrow_drop_up_white_24dp);
|
||||||
|
|
||||||
for (StreamingService s : NewPipe.getServices()) {
|
for (final StreamingService s : NewPipe.getServices()) {
|
||||||
final String title = s.getServiceInfo().getName()
|
final String title = s.getServiceInfo().getName()
|
||||||
+ (ServiceHelper.isBeta(s) ? " (beta)" : "");
|
+ (ServiceHelper.isBeta(s) ? " (beta)" : "");
|
||||||
|
|
||||||
MenuItem menuItem = drawerItems.getMenu()
|
final MenuItem menuItem = drawerItems.getMenu()
|
||||||
.add(R.id.menu_services_group, s.getServiceId(), ORDER, title)
|
.add(R.id.menu_services_group, s.getServiceId(), ORDER, title)
|
||||||
.setIcon(ServiceHelper.getIcon(s.getServiceId()));
|
.setIcon(ServiceHelper.getIcon(s.getServiceId()));
|
||||||
|
|
||||||
|
@ -362,20 +362,20 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enhancePeertubeMenu(final StreamingService s, final MenuItem menuItem) {
|
private void enhancePeertubeMenu(final StreamingService s, final MenuItem menuItem) {
|
||||||
PeertubeInstance currentInstace = PeertubeHelper.getCurrentInstance();
|
final PeertubeInstance currentInstace = PeertubeHelper.getCurrentInstance();
|
||||||
menuItem.setTitle(currentInstace.getName() + (ServiceHelper.isBeta(s) ? " (beta)" : ""));
|
menuItem.setTitle(currentInstace.getName() + (ServiceHelper.isBeta(s) ? " (beta)" : ""));
|
||||||
Spinner spinner = (Spinner) LayoutInflater.from(this)
|
final Spinner spinner = (Spinner) LayoutInflater.from(this)
|
||||||
.inflate(R.layout.instance_spinner_layout, null);
|
.inflate(R.layout.instance_spinner_layout, null);
|
||||||
List<PeertubeInstance> instances = PeertubeHelper.getInstanceList(this);
|
final List<PeertubeInstance> instances = PeertubeHelper.getInstanceList(this);
|
||||||
List<String> items = new ArrayList<>();
|
final List<String> items = new ArrayList<>();
|
||||||
int defaultSelect = 0;
|
int defaultSelect = 0;
|
||||||
for (PeertubeInstance instance : instances) {
|
for (final PeertubeInstance instance : instances) {
|
||||||
items.add(instance.getName());
|
items.add(instance.getName());
|
||||||
if (instance.getUrl().equals(currentInstace.getUrl())) {
|
if (instance.getUrl().equals(currentInstace.getUrl())) {
|
||||||
defaultSelect = items.size() - 1;
|
defaultSelect = items.size() - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
|
final ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
|
||||||
R.layout.instance_spinner_item, items);
|
R.layout.instance_spinner_item, items);
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
spinner.setAdapter(adapter);
|
spinner.setAdapter(adapter);
|
||||||
|
@ -384,7 +384,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(final AdapterView<?> parent, final View view,
|
public void onItemSelected(final AdapterView<?> parent, final View view,
|
||||||
final int position, final long id) {
|
final int position, final long id) {
|
||||||
PeertubeInstance newInstance = instances.get(position);
|
final PeertubeInstance newInstance = instances.get(position);
|
||||||
if (newInstance.getUrl().equals(PeertubeHelper.getCurrentInstance().getUrl())) {
|
if (newInstance.getUrl().equals(PeertubeHelper.getCurrentInstance().getUrl())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -410,8 +410,8 @@ public class MainActivity extends AppCompatActivity {
|
||||||
serviceArrow.setImageResource(R.drawable.ic_arrow_drop_down_white_24dp);
|
serviceArrow.setImageResource(R.drawable.ic_arrow_drop_down_white_24dp);
|
||||||
|
|
||||||
//Tabs
|
//Tabs
|
||||||
int currentServiceId = ServiceHelper.getSelectedServiceId(this);
|
final int currentServiceId = ServiceHelper.getSelectedServiceId(this);
|
||||||
StreamingService service = NewPipe.getService(currentServiceId);
|
final StreamingService service = NewPipe.getService(currentServiceId);
|
||||||
|
|
||||||
int kioskId = 0;
|
int kioskId = 0;
|
||||||
|
|
||||||
|
@ -476,11 +476,12 @@ public class MainActivity extends AppCompatActivity {
|
||||||
headerServiceView.post(() -> headerServiceView.setSelected(true));
|
headerServiceView.post(() -> headerServiceView.setSelected(true));
|
||||||
toggleServiceButton.setContentDescription(
|
toggleServiceButton.setContentDescription(
|
||||||
getString(R.string.drawer_header_description) + selectedServiceName);
|
getString(R.string.drawer_header_description) + selectedServiceName);
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError(this, e);
|
ErrorActivity.reportUiError(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
final SharedPreferences sharedPreferences
|
||||||
|
= PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
if (sharedPreferences.getBoolean(Constants.KEY_THEME_CHANGE, false)) {
|
if (sharedPreferences.getBoolean(Constants.KEY_THEME_CHANGE, false)) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "Theme has changed, recreating activity...");
|
Log.d(TAG, "Theme has changed, recreating activity...");
|
||||||
|
@ -513,7 +514,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
// Return if launched from a launcher (e.g. Nova Launcher, Pixel Launcher ...)
|
// Return if launched from a launcher (e.g. Nova Launcher, Pixel Launcher ...)
|
||||||
// to not destroy the already created backstack
|
// to not destroy the already created backstack
|
||||||
String action = intent.getAction();
|
final String action = intent.getAction();
|
||||||
if ((action != null && action.equals(Intent.ACTION_MAIN))
|
if ((action != null && action.equals(Intent.ACTION_MAIN))
|
||||||
&& intent.hasCategory(Intent.CATEGORY_LAUNCHER)) {
|
&& intent.hasCategory(Intent.CATEGORY_LAUNCHER)) {
|
||||||
return;
|
return;
|
||||||
|
@ -546,7 +547,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DeviceUtils.isTv(this)) {
|
if (DeviceUtils.isTv(this)) {
|
||||||
View drawerPanel = findViewById(R.id.navigation);
|
final View drawerPanel = findViewById(R.id.navigation);
|
||||||
if (drawer.isDrawerOpen(drawerPanel)) {
|
if (drawer.isDrawerOpen(drawerPanel)) {
|
||||||
drawer.closeDrawers();
|
drawer.closeDrawers();
|
||||||
return;
|
return;
|
||||||
|
@ -594,7 +595,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
public void onRequestPermissionsResult(final int requestCode,
|
public void onRequestPermissionsResult(final int requestCode,
|
||||||
@NonNull final String[] permissions,
|
@NonNull final String[] permissions,
|
||||||
@NonNull final int[] grantResults) {
|
@NonNull final int[] grantResults) {
|
||||||
for (int i : grantResults) {
|
for (final int i : grantResults) {
|
||||||
if (i == PackageManager.PERMISSION_DENIED) {
|
if (i == PackageManager.PERMISSION_DENIED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -604,7 +605,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
NavigationHelper.openDownloads(this);
|
NavigationHelper.openDownloads(this);
|
||||||
break;
|
break;
|
||||||
case PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE:
|
case PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE:
|
||||||
Fragment fragment = getSupportFragmentManager()
|
final Fragment fragment = getSupportFragmentManager()
|
||||||
.findFragmentById(R.id.fragment_player_holder);
|
.findFragmentById(R.id.fragment_player_holder);
|
||||||
if (fragment instanceof VideoDetailFragment) {
|
if (fragment instanceof VideoDetailFragment) {
|
||||||
((VideoDetailFragment) fragment).openDownloadDialog();
|
((VideoDetailFragment) fragment).openDownloadDialog();
|
||||||
|
@ -656,13 +657,14 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
super.onCreateOptionsMenu(menu);
|
super.onCreateOptionsMenu(menu);
|
||||||
|
|
||||||
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
|
final Fragment fragment
|
||||||
|
= getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
|
||||||
if (!(fragment instanceof SearchFragment)) {
|
if (!(fragment instanceof SearchFragment)) {
|
||||||
findViewById(R.id.toolbar).findViewById(R.id.toolbar_search_container)
|
findViewById(R.id.toolbar).findViewById(R.id.toolbar_search_container)
|
||||||
.setVisibility(View.GONE);
|
.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionBar actionBar = getSupportActionBar();
|
final ActionBar actionBar = getSupportActionBar();
|
||||||
if (actionBar != null) {
|
if (actionBar != null) {
|
||||||
actionBar.setDisplayHomeAsUpEnabled(false);
|
actionBar.setDisplayHomeAsUpEnabled(false);
|
||||||
}
|
}
|
||||||
|
@ -677,7 +679,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "onOptionsItemSelected() called with: item = [" + item + "]");
|
Log.d(TAG, "onOptionsItemSelected() called with: item = [" + item + "]");
|
||||||
}
|
}
|
||||||
int id = item.getItemId();
|
final int id = item.getItemId();
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case android.R.id.home:
|
case android.R.id.home:
|
||||||
|
@ -745,13 +747,13 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intent.hasExtra(Constants.KEY_LINK_TYPE)) {
|
if (intent.hasExtra(Constants.KEY_LINK_TYPE)) {
|
||||||
String url = intent.getStringExtra(Constants.KEY_URL);
|
final String url = intent.getStringExtra(Constants.KEY_URL);
|
||||||
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
|
final int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
|
||||||
String title = intent.getStringExtra(Constants.KEY_TITLE);
|
final String title = intent.getStringExtra(Constants.KEY_TITLE);
|
||||||
switch (((StreamingService.LinkType) intent
|
switch (((StreamingService.LinkType) intent
|
||||||
.getSerializableExtra(Constants.KEY_LINK_TYPE))) {
|
.getSerializableExtra(Constants.KEY_LINK_TYPE))) {
|
||||||
case STREAM:
|
case STREAM:
|
||||||
boolean autoPlay = intent
|
final boolean autoPlay = intent
|
||||||
.getBooleanExtra(VideoDetailFragment.AUTO_PLAY, false);
|
.getBooleanExtra(VideoDetailFragment.AUTO_PLAY, false);
|
||||||
final String intentCacheKey = intent
|
final String intentCacheKey = intent
|
||||||
.getStringExtra(VideoPlayer.PLAY_QUEUE_KEY);
|
.getStringExtra(VideoPlayer.PLAY_QUEUE_KEY);
|
||||||
|
@ -780,7 +782,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
if (searchString == null) {
|
if (searchString == null) {
|
||||||
searchString = "";
|
searchString = "";
|
||||||
}
|
}
|
||||||
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
|
final int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
|
||||||
NavigationHelper.openSearchFragment(
|
NavigationHelper.openSearchFragment(
|
||||||
getSupportFragmentManager(),
|
getSupportFragmentManager(),
|
||||||
serviceId,
|
serviceId,
|
||||||
|
@ -789,7 +791,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
} else {
|
} else {
|
||||||
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
|
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError(this, e);
|
ErrorActivity.reportUiError(this, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ public final class NewPipeDatabase {
|
||||||
if (databaseInstance == null) {
|
if (databaseInstance == null) {
|
||||||
throw new IllegalStateException("database is not initialized");
|
throw new IllegalStateException("database is not initialized");
|
||||||
}
|
}
|
||||||
Cursor c = databaseInstance.query("pragma wal_checkpoint(full)", null);
|
final Cursor c = databaseInstance.query("pragma wal_checkpoint(full)", null);
|
||||||
if (c.moveToFirst() && c.getInt(0) == 1) {
|
if (c.moveToFirst() && c.getInt(0) == 1) {
|
||||||
throw new RuntimeException("Checkpoint was blocked from completing");
|
throw new RuntimeException("Checkpoint was blocked from completing");
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class PanicResponderActivity extends Activity {
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
protected void onCreate(final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
Intent intent = getIntent();
|
final Intent intent = getIntent();
|
||||||
if (intent != null && PANIC_TRIGGER_ACTION.equals(intent.getAction())) {
|
if (intent != null && PANIC_TRIGGER_ACTION.equals(intent.getAction())) {
|
||||||
// TODO: Explicitly clear the search results
|
// TODO: Explicitly clear the search results
|
||||||
// once they are restored when the app restarts
|
// once they are restored when the app restarts
|
||||||
|
|
|
@ -61,7 +61,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
||||||
ThemeHelper.setTheme(this);
|
ThemeHelper.setTheme(this);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_recaptcha);
|
setContentView(R.layout.activity_recaptcha);
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
final Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
String url = getIntent().getStringExtra(RECAPTCHA_URL_EXTRA);
|
String url = getIntent().getStringExtra(RECAPTCHA_URL_EXTRA);
|
||||||
|
@ -76,7 +76,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
||||||
webView = findViewById(R.id.reCaptchaWebView);
|
webView = findViewById(R.id.reCaptchaWebView);
|
||||||
|
|
||||||
// enable Javascript
|
// enable Javascript
|
||||||
WebSettings webSettings = webView.getSettings();
|
final WebSettings webSettings = webView.getSettings();
|
||||||
webSettings.setJavaScriptEnabled(true);
|
webSettings.setJavaScriptEnabled(true);
|
||||||
|
|
||||||
webView.setWebViewClient(new WebViewClient() {
|
webView.setWebViewClient(new WebViewClient() {
|
||||||
|
@ -84,7 +84,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldOverrideUrlLoading(final WebView view,
|
public boolean shouldOverrideUrlLoading(final WebView view,
|
||||||
final WebResourceRequest request) {
|
final WebResourceRequest request) {
|
||||||
String url = request.getUrl().toString();
|
final String url = request.getUrl().toString();
|
||||||
if (MainActivity.DEBUG) {
|
if (MainActivity.DEBUG) {
|
||||||
Log.d(TAG, "shouldOverrideUrlLoading: request.url=" + url);
|
Log.d(TAG, "shouldOverrideUrlLoading: request.url=" + url);
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
||||||
// cleaning cache, history and cookies from webView
|
// cleaning cache, history and cookies from webView
|
||||||
webView.clearCache(true);
|
webView.clearCache(true);
|
||||||
webView.clearHistory();
|
webView.clearHistory();
|
||||||
android.webkit.CookieManager cookieManager = CookieManager.getInstance();
|
final android.webkit.CookieManager cookieManager = CookieManager.getInstance();
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
cookieManager.removeAllCookies(aBoolean -> {
|
cookieManager.removeAllCookies(aBoolean -> {
|
||||||
});
|
});
|
||||||
|
@ -128,7 +128,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
||||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||||
getMenuInflater().inflate(R.menu.menu_recaptcha, menu);
|
getMenuInflater().inflate(R.menu.menu_recaptcha, menu);
|
||||||
|
|
||||||
ActionBar actionBar = getSupportActionBar();
|
final ActionBar actionBar = getSupportActionBar();
|
||||||
if (actionBar != null) {
|
if (actionBar != null) {
|
||||||
actionBar.setDisplayHomeAsUpEnabled(false);
|
actionBar.setDisplayHomeAsUpEnabled(false);
|
||||||
actionBar.setTitle(R.string.title_activity_recaptcha);
|
actionBar.setTitle(R.string.title_activity_recaptcha);
|
||||||
|
@ -145,7 +145,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
int id = item.getItemId();
|
final int id = item.getItemId();
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case R.id.menu_item_done:
|
case R.id.menu_item_done:
|
||||||
saveCookiesAndFinish();
|
saveCookiesAndFinish();
|
||||||
|
@ -173,7 +173,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
||||||
setResult(RESULT_OK);
|
setResult(RESULT_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent intent = new Intent(this, org.schabi.newpipe.MainActivity.class);
|
final Intent intent = new Intent(this, org.schabi.newpipe.MainActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
NavUtils.navigateUpTo(this, intent);
|
NavUtils.navigateUpTo(this, intent);
|
||||||
}
|
}
|
||||||
|
@ -188,13 +188,13 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String cookies = CookieManager.getInstance().getCookie(url);
|
final String cookies = CookieManager.getInstance().getCookie(url);
|
||||||
handleCookies(cookies);
|
handleCookies(cookies);
|
||||||
|
|
||||||
// sometimes cookies are inside the url
|
// sometimes cookies are inside the url
|
||||||
int abuseStart = url.indexOf("google_abuse=");
|
final int abuseStart = url.indexOf("google_abuse=");
|
||||||
if (abuseStart != -1) {
|
if (abuseStart != -1) {
|
||||||
int abuseEnd = url.indexOf("+path");
|
final int abuseEnd = url.indexOf("+path");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String abuseCookie = url.substring(abuseStart + 13, abuseEnd);
|
String abuseCookie = url.substring(abuseStart + 13, abuseEnd);
|
||||||
|
|
|
@ -310,7 +310,7 @@ public class RouterActivity extends AppCompatActivity {
|
||||||
};
|
};
|
||||||
|
|
||||||
int id = 12345;
|
int id = 12345;
|
||||||
for (AdapterChoiceItem item : choices) {
|
for (final AdapterChoiceItem item : choices) {
|
||||||
final RadioButton radioButton
|
final RadioButton radioButton
|
||||||
= (RadioButton) inflater.inflate(R.layout.list_radio_icon_item, null);
|
= (RadioButton) inflater.inflate(R.layout.list_radio_icon_item, null);
|
||||||
radioButton.setText(item.description);
|
radioButton.setText(item.description);
|
||||||
|
@ -330,7 +330,7 @@ public class RouterActivity extends AppCompatActivity {
|
||||||
getString(R.string.preferred_open_action_last_selected_key), null);
|
getString(R.string.preferred_open_action_last_selected_key), null);
|
||||||
if (!TextUtils.isEmpty(lastSelectedPlayer)) {
|
if (!TextUtils.isEmpty(lastSelectedPlayer)) {
|
||||||
for (int i = 0; i < choices.size(); i++) {
|
for (int i = 0; i < choices.size(); i++) {
|
||||||
AdapterChoiceItem c = choices.get(i);
|
final AdapterChoiceItem c = choices.get(i);
|
||||||
if (lastSelectedPlayer.equals(c.key)) {
|
if (lastSelectedPlayer.equals(c.key)) {
|
||||||
selectedRadioPosition = i;
|
selectedRadioPosition = i;
|
||||||
break;
|
break;
|
||||||
|
@ -362,9 +362,9 @@ public class RouterActivity extends AppCompatActivity {
|
||||||
|
|
||||||
final SharedPreferences preferences = PreferenceManager
|
final SharedPreferences preferences = PreferenceManager
|
||||||
.getDefaultSharedPreferences(this);
|
.getDefaultSharedPreferences(this);
|
||||||
boolean isExtVideoEnabled = preferences.getBoolean(
|
final boolean isExtVideoEnabled = preferences.getBoolean(
|
||||||
getString(R.string.use_external_video_player_key), false);
|
getString(R.string.use_external_video_player_key), false);
|
||||||
boolean isExtAudioEnabled = preferences.getBoolean(
|
final boolean isExtAudioEnabled = preferences.getBoolean(
|
||||||
getString(R.string.use_external_audio_player_key), false);
|
getString(R.string.use_external_audio_player_key), false);
|
||||||
|
|
||||||
returnList.add(new AdapterChoiceItem(getString(R.string.show_info_key),
|
returnList.add(new AdapterChoiceItem(getString(R.string.show_info_key),
|
||||||
|
@ -410,9 +410,9 @@ public class RouterActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleText() {
|
private void handleText() {
|
||||||
String searchString = getIntent().getStringExtra(Intent.EXTRA_TEXT);
|
final String searchString = getIntent().getStringExtra(Intent.EXTRA_TEXT);
|
||||||
int serviceId = getIntent().getIntExtra(Constants.KEY_SERVICE_ID, 0);
|
final int serviceId = getIntent().getIntExtra(Constants.KEY_SERVICE_ID, 0);
|
||||||
Intent intent = new Intent(getThemeWrapperContext(), MainActivity.class);
|
final Intent intent = new Intent(getThemeWrapperContext(), MainActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
NavigationHelper.openSearch(getThemeWrapperContext(), serviceId, searchString);
|
NavigationHelper.openSearch(getThemeWrapperContext(), serviceId, searchString);
|
||||||
|
@ -479,14 +479,14 @@ public class RouterActivity extends AppCompatActivity {
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe((@NonNull StreamInfo result) -> {
|
.subscribe((@NonNull StreamInfo result) -> {
|
||||||
List<VideoStream> sortedVideoStreams = ListHelper
|
final List<VideoStream> sortedVideoStreams = ListHelper
|
||||||
.getSortedStreamVideosList(this, result.getVideoStreams(),
|
.getSortedStreamVideosList(this, result.getVideoStreams(),
|
||||||
result.getVideoOnlyStreams(), false);
|
result.getVideoOnlyStreams(), false);
|
||||||
int selectedVideoStreamIndex = ListHelper
|
final int selectedVideoStreamIndex = ListHelper
|
||||||
.getDefaultResolutionIndex(this, sortedVideoStreams);
|
.getDefaultResolutionIndex(this, sortedVideoStreams);
|
||||||
|
|
||||||
FragmentManager fm = getSupportFragmentManager();
|
final FragmentManager fm = getSupportFragmentManager();
|
||||||
DownloadDialog downloadDialog = DownloadDialog.newInstance(result);
|
final DownloadDialog downloadDialog = DownloadDialog.newInstance(result);
|
||||||
downloadDialog.setVideoStreams(sortedVideoStreams);
|
downloadDialog.setVideoStreams(sortedVideoStreams);
|
||||||
downloadDialog.setAudioStreams(result.getAudioStreams());
|
downloadDialog.setAudioStreams(result.getAudioStreams());
|
||||||
downloadDialog.setSelectedVideoStream(selectedVideoStreamIndex);
|
downloadDialog.setSelectedVideoStream(selectedVideoStreamIndex);
|
||||||
|
@ -504,7 +504,7 @@ public class RouterActivity extends AppCompatActivity {
|
||||||
public void onRequestPermissionsResult(final int requestCode,
|
public void onRequestPermissionsResult(final int requestCode,
|
||||||
@NonNull final String[] permissions,
|
@NonNull final String[] permissions,
|
||||||
@NonNull final int[] grantResults) {
|
@NonNull final int[] grantResults) {
|
||||||
for (int i : grantResults) {
|
for (final int i : grantResults) {
|
||||||
if (i == PackageManager.PERMISSION_DENIED) {
|
if (i == PackageManager.PERMISSION_DENIED) {
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
|
@ -634,7 +634,7 @@ public class RouterActivity extends AppCompatActivity {
|
||||||
if (!(serializable instanceof Choice)) {
|
if (!(serializable instanceof Choice)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Choice playerChoice = (Choice) serializable;
|
final Choice playerChoice = (Choice) serializable;
|
||||||
handleChoice(playerChoice);
|
handleChoice(playerChoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,13 +682,13 @@ public class RouterActivity extends AppCompatActivity {
|
||||||
|
|
||||||
final SharedPreferences preferences = PreferenceManager
|
final SharedPreferences preferences = PreferenceManager
|
||||||
.getDefaultSharedPreferences(this);
|
.getDefaultSharedPreferences(this);
|
||||||
boolean isExtVideoEnabled = preferences.getBoolean(
|
final boolean isExtVideoEnabled = preferences.getBoolean(
|
||||||
getString(R.string.use_external_video_player_key), false);
|
getString(R.string.use_external_video_player_key), false);
|
||||||
boolean isExtAudioEnabled = preferences.getBoolean(
|
final boolean isExtAudioEnabled = preferences.getBoolean(
|
||||||
getString(R.string.use_external_audio_player_key), false);
|
getString(R.string.use_external_audio_player_key), false);
|
||||||
|
|
||||||
PlayQueue playQueue;
|
PlayQueue playQueue;
|
||||||
String playerChoice = choice.playerChoice;
|
final String playerChoice = choice.playerChoice;
|
||||||
|
|
||||||
if (info instanceof StreamInfo) {
|
if (info instanceof StreamInfo) {
|
||||||
if (playerChoice.equals(backgroundPlayerKey) && isExtAudioEnabled) {
|
if (playerChoice.equals(backgroundPlayerKey) && isExtAudioEnabled) {
|
||||||
|
|
|
@ -88,7 +88,7 @@ public class AboutActivity extends AppCompatActivity {
|
||||||
|
|
||||||
setContentView(R.layout.activity_about);
|
setContentView(R.layout.activity_about);
|
||||||
|
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
final Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
// Create the adapter that will return a fragment for each of the three
|
// Create the adapter that will return a fragment for each of the three
|
||||||
|
@ -99,13 +99,13 @@ public class AboutActivity extends AppCompatActivity {
|
||||||
mViewPager = findViewById(R.id.container);
|
mViewPager = findViewById(R.id.container);
|
||||||
mViewPager.setAdapter(mSectionsPagerAdapter);
|
mViewPager.setAdapter(mSectionsPagerAdapter);
|
||||||
|
|
||||||
TabLayout tabLayout = findViewById(R.id.tabs);
|
final TabLayout tabLayout = findViewById(R.id.tabs);
|
||||||
tabLayout.setupWithViewPager(mViewPager);
|
tabLayout.setupWithViewPager(mViewPager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
int id = item.getItemId();
|
final int id = item.getItemId();
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case android.R.id.home:
|
case android.R.id.home:
|
||||||
|
@ -134,25 +134,25 @@ public class AboutActivity extends AppCompatActivity {
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
|
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
|
||||||
final Bundle savedInstanceState) {
|
final Bundle savedInstanceState) {
|
||||||
View rootView = inflater.inflate(R.layout.fragment_about, container, false);
|
final View rootView = inflater.inflate(R.layout.fragment_about, container, false);
|
||||||
Context context = this.getContext();
|
final Context context = this.getContext();
|
||||||
|
|
||||||
TextView version = rootView.findViewById(R.id.app_version);
|
final TextView version = rootView.findViewById(R.id.app_version);
|
||||||
version.setText(BuildConfig.VERSION_NAME);
|
version.setText(BuildConfig.VERSION_NAME);
|
||||||
|
|
||||||
View githubLink = rootView.findViewById(R.id.github_link);
|
final View githubLink = rootView.findViewById(R.id.github_link);
|
||||||
githubLink.setOnClickListener(nv ->
|
githubLink.setOnClickListener(nv ->
|
||||||
openUrlInBrowser(context, context.getString(R.string.github_url)));
|
openUrlInBrowser(context, context.getString(R.string.github_url)));
|
||||||
|
|
||||||
View donationLink = rootView.findViewById(R.id.donation_link);
|
final View donationLink = rootView.findViewById(R.id.donation_link);
|
||||||
donationLink.setOnClickListener(v ->
|
donationLink.setOnClickListener(v ->
|
||||||
openUrlInBrowser(context, context.getString(R.string.donation_url)));
|
openUrlInBrowser(context, context.getString(R.string.donation_url)));
|
||||||
|
|
||||||
View websiteLink = rootView.findViewById(R.id.website_link);
|
final View websiteLink = rootView.findViewById(R.id.website_link);
|
||||||
websiteLink.setOnClickListener(nv ->
|
websiteLink.setOnClickListener(nv ->
|
||||||
openUrlInBrowser(context, context.getString(R.string.website_url)));
|
openUrlInBrowser(context, context.getString(R.string.website_url)));
|
||||||
|
|
||||||
View privacyPolicyLink = rootView.findViewById(R.id.privacy_policy_link);
|
final View privacyPolicyLink = rootView.findViewById(R.id.privacy_policy_link);
|
||||||
privacyPolicyLink.setOnClickListener(v ->
|
privacyPolicyLink.setOnClickListener(v ->
|
||||||
openUrlInBrowser(context, context.getString(R.string.privacy_policy_url)));
|
openUrlInBrowser(context, context.getString(R.string.privacy_policy_url)));
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,8 @@ public class LicenseFragment extends Fragment {
|
||||||
if (softwareComponents == null) {
|
if (softwareComponents == null) {
|
||||||
throw new NullPointerException("softwareComponents is null");
|
throw new NullPointerException("softwareComponents is null");
|
||||||
}
|
}
|
||||||
LicenseFragment fragment = new LicenseFragment();
|
final LicenseFragment fragment = new LicenseFragment();
|
||||||
Bundle bundle = new Bundle();
|
final Bundle bundle = new Bundle();
|
||||||
bundle.putParcelableArray(ARG_COMPONENTS, softwareComponents);
|
bundle.putParcelableArray(ARG_COMPONENTS, softwareComponents);
|
||||||
fragment.setArguments(bundle);
|
fragment.setArguments(bundle);
|
||||||
return fragment;
|
return fragment;
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
|
||||||
// split the HTML file and insert the stylesheet into the HEAD of the file
|
// split the HTML file and insert the stylesheet into the HEAD of the file
|
||||||
webViewData = licenseContent.toString().replace("</head>",
|
webViewData = licenseContent.toString().replace("</head>",
|
||||||
"<style>" + getLicenseStylesheet(context) + "</style></head>");
|
"<style>" + getLicenseStylesheet(context) + "</style></head>");
|
||||||
} catch (IOException e) {
|
} catch (final IOException e) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Could not get license file: " + license.getFilename(), e);
|
"Could not get license file: " + license.getFilename(), e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ public final class Converters {
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
public static FeedGroupIcon feedGroupIconOf(final Integer id) {
|
public static FeedGroupIcon feedGroupIconOf(final Integer id) {
|
||||||
for (FeedGroupIcon icon : FeedGroupIcon.values()) {
|
for (final FeedGroupIcon icon : FeedGroupIcon.values()) {
|
||||||
if (icon.getId() == id) {
|
if (icon.getId() == id) {
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class SubscriptionEntity {
|
||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
public static SubscriptionEntity from(@NonNull final ChannelInfo info) {
|
public static SubscriptionEntity from(@NonNull final ChannelInfo info) {
|
||||||
SubscriptionEntity result = new SubscriptionEntity();
|
final SubscriptionEntity result = new SubscriptionEntity();
|
||||||
result.setServiceId(info.getServiceId());
|
result.setServiceId(info.getServiceId());
|
||||||
result.setUrl(info.getUrl());
|
result.setUrl(info.getUrl());
|
||||||
result.setData(info.getName(), info.getAvatarUrl(), info.getDescription(),
|
result.setData(info.getName(), info.getAvatarUrl(), info.getDescription(),
|
||||||
|
@ -124,7 +124,7 @@ public class SubscriptionEntity {
|
||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
public ChannelInfoItem toChannelInfoItem() {
|
public ChannelInfoItem toChannelInfoItem() {
|
||||||
ChannelInfoItem item = new ChannelInfoItem(getServiceId(), getUrl(), getName());
|
final ChannelInfoItem item = new ChannelInfoItem(getServiceId(), getUrl(), getName());
|
||||||
item.setThumbnailUrl(getAvatarUrl());
|
item.setThumbnailUrl(getAvatarUrl());
|
||||||
item.setSubscriberCount(getSubscriberCount());
|
item.setSubscriberCount(getSubscriberCount());
|
||||||
item.setDescription(getDescription());
|
item.setDescription(getDescription());
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class DownloadActivity extends AppCompatActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
protected void onCreate(final Bundle savedInstanceState) {
|
||||||
// Service
|
// Service
|
||||||
Intent i = new Intent();
|
final Intent i = new Intent();
|
||||||
i.setClass(this, DownloadManagerService.class);
|
i.setClass(this, DownloadManagerService.class);
|
||||||
startService(i);
|
startService(i);
|
||||||
|
|
||||||
|
@ -38,10 +38,10 @@ public class DownloadActivity extends AppCompatActivity {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_downloader);
|
setContentView(R.layout.activity_downloader);
|
||||||
|
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
final Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
ActionBar actionBar = getSupportActionBar();
|
final ActionBar actionBar = getSupportActionBar();
|
||||||
if (actionBar != null) {
|
if (actionBar != null) {
|
||||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
actionBar.setTitle(R.string.downloads_title);
|
actionBar.setTitle(R.string.downloads_title);
|
||||||
|
@ -63,7 +63,7 @@ public class DownloadActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFragments() {
|
private void updateFragments() {
|
||||||
MissionsFragment fragment = new MissionsFragment();
|
final MissionsFragment fragment = new MissionsFragment();
|
||||||
|
|
||||||
getSupportFragmentManager().beginTransaction()
|
getSupportFragmentManager().beginTransaction()
|
||||||
.replace(R.id.frame, fragment, MISSIONS_FRAGMENT_TAG)
|
.replace(R.id.frame, fragment, MISSIONS_FRAGMENT_TAG)
|
||||||
|
@ -74,7 +74,7 @@ public class DownloadActivity extends AppCompatActivity {
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||||
super.onCreateOptionsMenu(menu);
|
super.onCreateOptionsMenu(menu);
|
||||||
MenuInflater inflater = getMenuInflater();
|
final MenuInflater inflater = getMenuInflater();
|
||||||
|
|
||||||
inflater.inflate(R.menu.download_menu, menu);
|
inflater.inflate(R.menu.download_menu, menu);
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class DownloadDialog extends DialogFragment
|
||||||
private SharedPreferences prefs;
|
private SharedPreferences prefs;
|
||||||
|
|
||||||
public static DownloadDialog newInstance(final StreamInfo info) {
|
public static DownloadDialog newInstance(final StreamInfo info) {
|
||||||
DownloadDialog dialog = new DownloadDialog();
|
final DownloadDialog dialog = new DownloadDialog();
|
||||||
dialog.setInfo(info);
|
dialog.setInfo(info);
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
@ -208,14 +208,15 @@ public class DownloadDialog extends DialogFragment
|
||||||
setStyle(STYLE_NO_TITLE, ThemeHelper.getDialogTheme(context));
|
setStyle(STYLE_NO_TITLE, ThemeHelper.getDialogTheme(context));
|
||||||
Icepick.restoreInstanceState(this, savedInstanceState);
|
Icepick.restoreInstanceState(this, savedInstanceState);
|
||||||
|
|
||||||
SparseArray<SecondaryStreamHelper<AudioStream>> secondaryStreams = new SparseArray<>(4);
|
final SparseArray<SecondaryStreamHelper<AudioStream>> secondaryStreams
|
||||||
List<VideoStream> videoStreams = wrappedVideoStreams.getStreamsList();
|
= new SparseArray<>(4);
|
||||||
|
final List<VideoStream> videoStreams = wrappedVideoStreams.getStreamsList();
|
||||||
|
|
||||||
for (int i = 0; i < videoStreams.size(); i++) {
|
for (int i = 0; i < videoStreams.size(); i++) {
|
||||||
if (!videoStreams.get(i).isVideoOnly()) {
|
if (!videoStreams.get(i).isVideoOnly()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
AudioStream audioStream = SecondaryStreamHelper
|
final AudioStream audioStream = SecondaryStreamHelper
|
||||||
.getAudioStreamFor(wrappedAudioStreams.getStreamsList(), videoStreams.get(i));
|
.getAudioStreamFor(wrappedAudioStreams.getStreamsList(), videoStreams.get(i));
|
||||||
|
|
||||||
if (audioStream != null) {
|
if (audioStream != null) {
|
||||||
|
@ -232,13 +233,13 @@ public class DownloadDialog extends DialogFragment
|
||||||
this.audioStreamsAdapter = new StreamItemAdapter<>(context, wrappedAudioStreams);
|
this.audioStreamsAdapter = new StreamItemAdapter<>(context, wrappedAudioStreams);
|
||||||
this.subtitleStreamsAdapter = new StreamItemAdapter<>(context, wrappedSubtitleStreams);
|
this.subtitleStreamsAdapter = new StreamItemAdapter<>(context, wrappedSubtitleStreams);
|
||||||
|
|
||||||
Intent intent = new Intent(context, DownloadManagerService.class);
|
final Intent intent = new Intent(context, DownloadManagerService.class);
|
||||||
context.startService(intent);
|
context.startService(intent);
|
||||||
|
|
||||||
context.bindService(intent, new ServiceConnection() {
|
context.bindService(intent, new ServiceConnection() {
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(final ComponentName cname, final IBinder service) {
|
public void onServiceConnected(final ComponentName cname, final IBinder service) {
|
||||||
DownloadManagerBinder mgr = (DownloadManagerBinder) service;
|
final DownloadManagerBinder mgr = (DownloadManagerBinder) service;
|
||||||
|
|
||||||
mainStorageAudio = mgr.getMainStorageAudio();
|
mainStorageAudio = mgr.getMainStorageAudio();
|
||||||
mainStorageVideo = mgr.getMainStorageVideo();
|
mainStorageVideo = mgr.getMainStorageVideo();
|
||||||
|
@ -296,7 +297,7 @@ public class DownloadDialog extends DialogFragment
|
||||||
|
|
||||||
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
|
||||||
int threads = prefs.getInt(getString(R.string.default_download_threads), 3);
|
final int threads = prefs.getInt(getString(R.string.default_download_threads), 3);
|
||||||
threadsCountTextView.setText(String.valueOf(threads));
|
threadsCountTextView.setText(String.valueOf(threads));
|
||||||
threadsSeekBar.setProgress(threads - 1);
|
threadsSeekBar.setProgress(threads - 1);
|
||||||
threadsSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
threadsSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
|
@ -373,13 +374,13 @@ public class DownloadDialog extends DialogFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FilePickerActivityHelper.isOwnFileUri(context, data.getData())) {
|
if (FilePickerActivityHelper.isOwnFileUri(context, data.getData())) {
|
||||||
File file = Utils.getFileForUri(data.getData());
|
final File file = Utils.getFileForUri(data.getData());
|
||||||
checkSelectedDownload(null, Uri.fromFile(file), file.getName(),
|
checkSelectedDownload(null, Uri.fromFile(file), file.getName(),
|
||||||
StoredFileHelper.DEFAULT_MIME);
|
StoredFileHelper.DEFAULT_MIME);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentFile docFile = DocumentFile.fromSingleUri(context, data.getData());
|
final DocumentFile docFile = DocumentFile.fromSingleUri(context, data.getData());
|
||||||
if (docFile == null) {
|
if (docFile == null) {
|
||||||
showFailedDialog(R.string.general_error);
|
showFailedDialog(R.string.general_error);
|
||||||
return;
|
return;
|
||||||
|
@ -564,7 +565,7 @@ public class DownloadDialog extends DialogFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getNameEditText() {
|
private String getNameEditText() {
|
||||||
String str = nameEditText.getText().toString().trim();
|
final String str = nameEditText.getText().toString().trim();
|
||||||
|
|
||||||
return FilenameUtils.createFilename(context, str.isEmpty() ? currentInfo.getName() : str);
|
return FilenameUtils.createFilename(context, str.isEmpty() ? currentInfo.getName() : str);
|
||||||
}
|
}
|
||||||
|
@ -591,9 +592,9 @@ public class DownloadDialog extends DialogFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareSelectedDownload() {
|
private void prepareSelectedDownload() {
|
||||||
StoredDirectoryHelper mainStorage;
|
final StoredDirectoryHelper mainStorage;
|
||||||
MediaFormat format;
|
final MediaFormat format;
|
||||||
String mime;
|
final String mime;
|
||||||
|
|
||||||
// first, build the filename and get the output folder (if possible)
|
// first, build the filename and get the output folder (if possible)
|
||||||
// later, run a very very very large file checking logic
|
// later, run a very very very large file checking logic
|
||||||
|
@ -683,15 +684,17 @@ public class DownloadDialog extends DialogFragment
|
||||||
storage = new StoredFileHelper(context, mainStorage.getUri(), targetFile,
|
storage = new StoredFileHelper(context, mainStorage.getUri(), targetFile,
|
||||||
mainStorage.getTag());
|
mainStorage.getTag());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
showErrorActivity(e);
|
showErrorActivity(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if is our file
|
// check if is our file
|
||||||
MissionState state = downloadManager.checkForExistingMission(storage);
|
final MissionState state = downloadManager.checkForExistingMission(storage);
|
||||||
@StringRes int msgBtn;
|
@StringRes
|
||||||
@StringRes int msgBody;
|
final int msgBtn;
|
||||||
|
@StringRes
|
||||||
|
final int msgBody;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case Finished:
|
case Finished:
|
||||||
|
@ -744,8 +747,7 @@ public class DownloadDialog extends DialogFragment
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final AlertDialog.Builder askDialog = new AlertDialog.Builder(context)
|
||||||
AlertDialog.Builder askDialog = new AlertDialog.Builder(context)
|
|
||||||
.setTitle(R.string.download_dialog_title)
|
.setTitle(R.string.download_dialog_title)
|
||||||
.setMessage(msgBody)
|
.setMessage(msgBody)
|
||||||
.setNegativeButton(android.R.string.cancel, null);
|
.setNegativeButton(android.R.string.cancel, null);
|
||||||
|
@ -787,7 +789,7 @@ public class DownloadDialog extends DialogFragment
|
||||||
// try take (or steal) the file
|
// try take (or steal) the file
|
||||||
storageNew = new StoredFileHelper(context, mainStorage.getUri(),
|
storageNew = new StoredFileHelper(context, mainStorage.getUri(),
|
||||||
targetFile, mainStorage.getTag());
|
targetFile, mainStorage.getTag());
|
||||||
} catch (IOException e) {
|
} catch (final IOException e) {
|
||||||
Log.e(TAG, "Failed to take (or steal) the file in "
|
Log.e(TAG, "Failed to take (or steal) the file in "
|
||||||
+ targetFile.toString());
|
+ targetFile.toString());
|
||||||
storageNew = null;
|
storageNew = null;
|
||||||
|
@ -825,18 +827,18 @@ public class DownloadDialog extends DialogFragment
|
||||||
if (storage.length() > 0) {
|
if (storage.length() > 0) {
|
||||||
storage.truncate();
|
storage.truncate();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (final IOException e) {
|
||||||
Log.e(TAG, "failed to truncate the file: " + storage.getUri().toString(), e);
|
Log.e(TAG, "failed to truncate the file: " + storage.getUri().toString(), e);
|
||||||
showFailedDialog(R.string.overwrite_failed);
|
showFailedDialog(R.string.overwrite_failed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream selectedStream;
|
final Stream selectedStream;
|
||||||
Stream secondaryStream = null;
|
Stream secondaryStream = null;
|
||||||
char kind;
|
final char kind;
|
||||||
int threads = threadsSeekBar.getProgress() + 1;
|
int threads = threadsSeekBar.getProgress() + 1;
|
||||||
String[] urls;
|
final String[] urls;
|
||||||
MissionRecoveryInfo[] recoveryInfo;
|
final MissionRecoveryInfo[] recoveryInfo;
|
||||||
String psName = null;
|
String psName = null;
|
||||||
String[] psArgs = null;
|
String[] psArgs = null;
|
||||||
long nearLength = 0;
|
long nearLength = 0;
|
||||||
|
@ -857,7 +859,7 @@ public class DownloadDialog extends DialogFragment
|
||||||
kind = 'v';
|
kind = 'v';
|
||||||
selectedStream = videoStreamsAdapter.getItem(selectedVideoIndex);
|
selectedStream = videoStreamsAdapter.getItem(selectedVideoIndex);
|
||||||
|
|
||||||
SecondaryStreamHelper<AudioStream> secondary = videoStreamsAdapter
|
final SecondaryStreamHelper<AudioStream> secondary = videoStreamsAdapter
|
||||||
.getAllSecondary()
|
.getAllSecondary()
|
||||||
.get(wrappedVideoStreams.getStreamsList().indexOf(selectedStream));
|
.get(wrappedVideoStreams.getStreamsList().indexOf(selectedStream));
|
||||||
|
|
||||||
|
@ -871,7 +873,7 @@ public class DownloadDialog extends DialogFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
psArgs = null;
|
psArgs = null;
|
||||||
long videoSize = wrappedVideoStreams
|
final long videoSize = wrappedVideoStreams
|
||||||
.getSizeInBytes((VideoStream) selectedStream);
|
.getSizeInBytes((VideoStream) selectedStream);
|
||||||
|
|
||||||
// set nearLength, only, if both sizes are fetched or known. This probably
|
// set nearLength, only, if both sizes are fetched or known. This probably
|
||||||
|
|
|
@ -230,7 +230,7 @@ public abstract class BaseStateFragment<I> extends BaseFragment implements ViewC
|
||||||
}
|
}
|
||||||
Toast.makeText(activity, R.string.recaptcha_request_toast, Toast.LENGTH_LONG).show();
|
Toast.makeText(activity, R.string.recaptcha_request_toast, Toast.LENGTH_LONG).show();
|
||||||
// Starting ReCaptcha Challenge Activity
|
// Starting ReCaptcha Challenge Activity
|
||||||
Intent intent = new Intent(activity, ReCaptchaActivity.class);
|
final Intent intent = new Intent(activity, ReCaptchaActivity.class);
|
||||||
intent.putExtra(ReCaptchaActivity.RECAPTCHA_URL_EXTRA, exception.getUrl());
|
intent.putExtra(ReCaptchaActivity.RECAPTCHA_URL_EXTRA, exception.getUrl());
|
||||||
startActivityForResult(intent, ReCaptchaActivity.RECAPTCHA_REQUEST);
|
startActivityForResult(intent, ReCaptchaActivity.RECAPTCHA_REQUEST);
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
boolean youtubeRestrictedModeEnabled =
|
final boolean youtubeRestrictedModeEnabled =
|
||||||
PreferenceManager.getDefaultSharedPreferences(getContext())
|
PreferenceManager.getDefaultSharedPreferences(getContext())
|
||||||
.getBoolean(youtubeRestrictedModeEnabledKey, false);
|
.getBoolean(youtubeRestrictedModeEnabledKey, false);
|
||||||
if (previousYoutubeRestrictedModeEnabled != youtubeRestrictedModeEnabled) {
|
if (previousYoutubeRestrictedModeEnabled != youtubeRestrictedModeEnabled) {
|
||||||
|
@ -137,7 +137,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||||
}
|
}
|
||||||
inflater.inflate(R.menu.main_fragment_menu, menu);
|
inflater.inflate(R.menu.main_fragment_menu, menu);
|
||||||
|
|
||||||
ActionBar supportActionBar = activity.getSupportActionBar();
|
final ActionBar supportActionBar = activity.getSupportActionBar();
|
||||||
if (supportActionBar != null) {
|
if (supportActionBar != null) {
|
||||||
supportActionBar.setDisplayHomeAsUpEnabled(false);
|
supportActionBar.setDisplayHomeAsUpEnabled(false);
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||||
try {
|
try {
|
||||||
NavigationHelper.openSearchFragment(getFM(),
|
NavigationHelper.openSearchFragment(getFM(),
|
||||||
ServiceHelper.getSelectedServiceId(activity), "");
|
ServiceHelper.getSelectedServiceId(activity), "");
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -237,7 +237,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||||
Fragment fragment = null;
|
Fragment fragment = null;
|
||||||
try {
|
try {
|
||||||
fragment = tab.getFragment(context);
|
fragment = tab.getFragment(context);
|
||||||
} catch (ExtractionException e) {
|
} catch (final ExtractionException e) {
|
||||||
throwable = e;
|
throwable = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,9 @@ public abstract class OnScrollBelowItemsListener extends RecyclerView.OnScrollLi
|
||||||
super.onScrolled(recyclerView, dx, dy);
|
super.onScrolled(recyclerView, dx, dy);
|
||||||
if (dy > 0) {
|
if (dy > 0) {
|
||||||
int pastVisibleItems = 0;
|
int pastVisibleItems = 0;
|
||||||
int visibleItemCount;
|
final int visibleItemCount;
|
||||||
int totalItemCount;
|
final int totalItemCount;
|
||||||
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
||||||
|
|
||||||
visibleItemCount = layoutManager.getChildCount();
|
visibleItemCount = layoutManager.getChildCount();
|
||||||
totalItemCount = layoutManager.getItemCount();
|
totalItemCount = layoutManager.getItemCount();
|
||||||
|
@ -26,7 +26,7 @@ public abstract class OnScrollBelowItemsListener extends RecyclerView.OnScrollLi
|
||||||
pastVisibleItems = ((LinearLayoutManager) layoutManager)
|
pastVisibleItems = ((LinearLayoutManager) layoutManager)
|
||||||
.findFirstVisibleItemPosition();
|
.findFirstVisibleItemPosition();
|
||||||
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
|
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
|
||||||
int[] positions = ((StaggeredGridLayoutManager) layoutManager)
|
final int[] positions = ((StaggeredGridLayoutManager) layoutManager)
|
||||||
.findFirstVisibleItemPositions(null);
|
.findFirstVisibleItemPositions(null);
|
||||||
if (positions != null && positions.length > 0) {
|
if (positions != null && positions.length > 0) {
|
||||||
pastVisibleItems = positions[0];
|
pastVisibleItems = positions[0];
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class TabAdaptor extends FragmentPagerAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateItem(final String title, final Fragment fragment) {
|
public void updateItem(final String title, final Fragment fragment) {
|
||||||
int index = mFragmentTitleList.indexOf(title);
|
final int index = mFragmentTitleList.indexOf(title);
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
updateItem(index, fragment);
|
updateItem(index, fragment);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,12 @@ import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.text.util.Linkify;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -30,31 +36,25 @@ import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.content.res.AppCompatResources;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.viewpager.widget.ViewPager;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer2.PlaybackParameters;
|
import com.google.android.exoplayer2.PlaybackParameters;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.material.appbar.AppBarLayout;
|
import com.google.android.material.appbar.AppBarLayout;
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||||
import com.google.android.material.tabs.TabLayout;
|
import com.google.android.material.tabs.TabLayout;
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.viewpager.widget.ViewPager;
|
|
||||||
import android.text.Html;
|
|
||||||
import android.text.Spanned;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.text.util.Linkify;
|
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.appcompat.content.res.AppCompatResources;
|
|
||||||
|
|
||||||
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 com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
||||||
|
@ -93,8 +93,8 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
||||||
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.DeviceUtils;
|
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
|
import org.schabi.newpipe.util.DeviceUtils;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||||
import org.schabi.newpipe.util.InfoCache;
|
import org.schabi.newpipe.util.InfoCache;
|
||||||
|
@ -124,9 +124,9 @@ import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.COMMENTS;
|
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.COMMENTS;
|
||||||
|
import static org.schabi.newpipe.extractor.stream.StreamExtractor.NO_AGE_LIMIT;
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired;
|
import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired;
|
||||||
import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET;
|
import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET;
|
||||||
import static org.schabi.newpipe.extractor.stream.StreamExtractor.NO_AGE_LIMIT;
|
|
||||||
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
||||||
|
|
||||||
public class VideoDetailFragment
|
public class VideoDetailFragment
|
||||||
|
@ -371,7 +371,7 @@ public class VideoDetailFragment
|
||||||
|
|
||||||
public static VideoDetailFragment getInstance(final int serviceId, final String videoUrl,
|
public static VideoDetailFragment getInstance(final int serviceId, final String videoUrl,
|
||||||
final String name, final PlayQueue playQueue) {
|
final String name, final PlayQueue playQueue) {
|
||||||
VideoDetailFragment instance = new VideoDetailFragment();
|
final VideoDetailFragment instance = new VideoDetailFragment();
|
||||||
instance.setInitialData(serviceId, videoUrl, name, playQueue);
|
instance.setInitialData(serviceId, videoUrl, name, playQueue);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
@ -635,7 +635,7 @@ public class VideoDetailFragment
|
||||||
try {
|
try {
|
||||||
NavigationHelper.openChannelFragment(getFM(), currentInfo.getServiceId(),
|
NavigationHelper.openChannelFragment(getFM(), currentInfo.getServiceId(),
|
||||||
subChannelUrl, subChannelName);
|
subChannelUrl, subChannelName);
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1062,7 +1062,7 @@ public class VideoDetailFragment
|
||||||
if (pageAdapter.getCount() < 2) {
|
if (pageAdapter.getCount() < 2) {
|
||||||
tabLayout.setVisibility(View.GONE);
|
tabLayout.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
int position = pageAdapter.getItemPositionByTitle(selectedTabTag);
|
final int position = pageAdapter.getItemPositionByTitle(selectedTabTag);
|
||||||
if (position != -1) {
|
if (position != -1) {
|
||||||
viewPager.setCurrentItem(position);
|
viewPager.setCurrentItem(position);
|
||||||
}
|
}
|
||||||
|
@ -1076,7 +1076,7 @@ public class VideoDetailFragment
|
||||||
.getServiceInfo()
|
.getServiceInfo()
|
||||||
.getMediaCapabilities()
|
.getMediaCapabilities()
|
||||||
.contains(COMMENTS);
|
.contains(COMMENTS);
|
||||||
} catch (ExtractionException e) {
|
} catch (final ExtractionException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1304,7 +1304,7 @@ public class VideoDetailFragment
|
||||||
if (description.getType() == Description.HTML) {
|
if (description.getType() == Description.HTML) {
|
||||||
disposables.add(Single.just(description.getContent())
|
disposables.add(Single.just(description.getContent())
|
||||||
.map((@NonNull String descriptionText) -> {
|
.map((@NonNull String descriptionText) -> {
|
||||||
Spanned parsedDescription;
|
final Spanned parsedDescription;
|
||||||
if (Build.VERSION.SDK_INT >= 24) {
|
if (Build.VERSION.SDK_INT >= 24) {
|
||||||
parsedDescription = Html.fromHtml(descriptionText, 0);
|
parsedDescription = Html.fromHtml(descriptionText, 0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1409,7 +1409,7 @@ public class VideoDetailFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
IntentFilter intentFilter = new IntentFilter();
|
final IntentFilter intentFilter = new IntentFilter();
|
||||||
intentFilter.addAction(ACTION_SHOW_MAIN_PLAYER);
|
intentFilter.addAction(ACTION_SHOW_MAIN_PLAYER);
|
||||||
intentFilter.addAction(ACTION_HIDE_MAIN_PLAYER);
|
intentFilter.addAction(ACTION_HIDE_MAIN_PLAYER);
|
||||||
activity.registerReceiver(broadcastReceiver, intentFilter);
|
activity.registerReceiver(broadcastReceiver, intentFilter);
|
||||||
|
@ -1512,7 +1512,7 @@ public class VideoDetailFragment
|
||||||
uploaderThumb.setVisibility(View.GONE);
|
uploaderThumb.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Drawable buddyDrawable = AppCompatResources.getDrawable(activity, R.drawable.buddy);
|
final Drawable buddyDrawable = AppCompatResources.getDrawable(activity, R.drawable.buddy);
|
||||||
subChannelThumb.setImageDrawable(buddyDrawable);
|
subChannelThumb.setImageDrawable(buddyDrawable);
|
||||||
uploaderThumb.setImageDrawable(buddyDrawable);
|
uploaderThumb.setImageDrawable(buddyDrawable);
|
||||||
|
|
||||||
|
@ -1676,7 +1676,7 @@ public class VideoDetailFragment
|
||||||
downloadDialog.setSubtitleStreams(currentInfo.getSubtitles());
|
downloadDialog.setSubtitleStreams(currentInfo.getSubtitles());
|
||||||
|
|
||||||
downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog");
|
downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog");
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
final ErrorActivity.ErrorInfo info = ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
|
final ErrorActivity.ErrorInfo info = ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
|
||||||
ServiceList.all()
|
ServiceList.all()
|
||||||
.get(currentInfo
|
.get(currentInfo
|
||||||
|
@ -1702,7 +1702,7 @@ public class VideoDetailFragment
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int errorId = exception instanceof YoutubeStreamExtractor.DecryptException
|
final int errorId = exception instanceof YoutubeStreamExtractor.DecryptException
|
||||||
? R.string.youtube_signature_decryption_error
|
? R.string.youtube_signature_decryption_error
|
||||||
: exception instanceof ExtractionException
|
: exception instanceof ExtractionException
|
||||||
? R.string.parsing_error
|
? R.string.parsing_error
|
||||||
|
@ -2112,11 +2112,11 @@ public class VideoDetailFragment
|
||||||
if (sortedVideoStreams == null) {
|
if (sortedVideoStreams == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CharSequence[] resolutions = new CharSequence[sortedVideoStreams.size()];
|
final CharSequence[] resolutions = new CharSequence[sortedVideoStreams.size()];
|
||||||
for (int i = 0; i < sortedVideoStreams.size(); i++) {
|
for (int i = 0; i < sortedVideoStreams.size(); i++) {
|
||||||
resolutions[i] = sortedVideoStreams.get(i).getResolution();
|
resolutions[i] = sortedVideoStreams.get(i).getResolution();
|
||||||
}
|
}
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity)
|
final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setNeutralButton(R.string.open_in_browser, (dialog, i) ->
|
.setNeutralButton(R.string.open_in_browser, (dialog, i) ->
|
||||||
ShareUtils.openUrlInBrowser(requireActivity(), url)
|
ShareUtils.openUrlInBrowser(requireActivity(), url)
|
||||||
|
|
|
@ -136,7 +136,7 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||||
final RecyclerView.ViewHolder itemHolder =
|
final RecyclerView.ViewHolder itemHolder =
|
||||||
itemsList.findContainingViewHolder(focusedItem);
|
itemsList.findContainingViewHolder(focusedItem);
|
||||||
return itemHolder.getAdapterPosition();
|
return itemHolder.getAdapterPosition();
|
||||||
} catch (NullPointerException e) {
|
} catch (final NullPointerException e) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||||
}
|
}
|
||||||
|
|
||||||
itemsList.post(() -> {
|
itemsList.post(() -> {
|
||||||
RecyclerView.ViewHolder focusedHolder =
|
final RecyclerView.ViewHolder focusedHolder =
|
||||||
itemsList.findViewHolderForAdapterPosition(position);
|
itemsList.findViewHolderForAdapterPosition(position);
|
||||||
|
|
||||||
if (focusedHolder != null) {
|
if (focusedHolder != null) {
|
||||||
|
@ -279,7 +279,7 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||||
selectedItem.getServiceId(),
|
selectedItem.getServiceId(),
|
||||||
selectedItem.getUrl(),
|
selectedItem.getUrl(),
|
||||||
selectedItem.getName());
|
selectedItem.getName());
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,7 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||||
selectedItem.getServiceId(),
|
selectedItem.getServiceId(),
|
||||||
selectedItem.getUrl(),
|
selectedItem.getUrl(),
|
||||||
selectedItem.getName());
|
selectedItem.getName());
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,7 +367,7 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||||
+ "menu = [" + menu + "], inflater = [" + inflater + "]");
|
+ "menu = [" + menu + "], inflater = [" + inflater + "]");
|
||||||
}
|
}
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
ActionBar supportActionBar = activity.getSupportActionBar();
|
final ActionBar supportActionBar = activity.getSupportActionBar();
|
||||||
if (supportActionBar != null) {
|
if (supportActionBar != null) {
|
||||||
supportActionBar.setDisplayShowTitleEnabled(true);
|
supportActionBar.setDisplayShowTitleEnabled(true);
|
||||||
if (useAsFrontPage) {
|
if (useAsFrontPage) {
|
||||||
|
|
|
@ -98,7 +98,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
||||||
|
|
||||||
public static ChannelFragment getInstance(final int serviceId, final String url,
|
public static ChannelFragment getInstance(final int serviceId, final String url,
|
||||||
final String name) {
|
final String name) {
|
||||||
ChannelFragment instance = new ChannelFragment();
|
final ChannelFragment instance = new ChannelFragment();
|
||||||
instance.setInitialData(serviceId, url, name);
|
instance.setInitialData(serviceId, url, name);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
ActionBar supportActionBar = activity.getSupportActionBar();
|
final ActionBar supportActionBar = activity.getSupportActionBar();
|
||||||
if (useAsFrontPage && supportActionBar != null) {
|
if (useAsFrontPage && supportActionBar != null) {
|
||||||
supportActionBar.setDisplayHomeAsUpEnabled(false);
|
supportActionBar.setDisplayHomeAsUpEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -206,7 +206,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
||||||
private void openRssFeed() {
|
private void openRssFeed() {
|
||||||
final ChannelInfo info = currentInfo;
|
final ChannelInfo info = currentInfo;
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(info.getFeedUrl()));
|
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(info.getFeedUrl()));
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -345,7 +345,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "No subscription to this channel!");
|
Log.d(TAG, "No subscription to this channel!");
|
||||||
}
|
}
|
||||||
SubscriptionEntity channel = new SubscriptionEntity();
|
final SubscriptionEntity channel = new SubscriptionEntity();
|
||||||
channel.setServiceId(info.getServiceId());
|
channel.setServiceId(info.getServiceId());
|
||||||
channel.setUrl(info.getUrl());
|
channel.setUrl(info.getUrl());
|
||||||
channel.setData(info.getName(),
|
channel.setData(info.getName(),
|
||||||
|
@ -371,16 +371,16 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
||||||
+ "isSubscribed = [" + isSubscribed + "]");
|
+ "isSubscribed = [" + isSubscribed + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isButtonVisible = headerSubscribeButton.getVisibility() == View.VISIBLE;
|
final boolean isButtonVisible = headerSubscribeButton.getVisibility() == View.VISIBLE;
|
||||||
int backgroundDuration = isButtonVisible ? 300 : 0;
|
final int backgroundDuration = isButtonVisible ? 300 : 0;
|
||||||
int textDuration = isButtonVisible ? 200 : 0;
|
final int textDuration = isButtonVisible ? 200 : 0;
|
||||||
|
|
||||||
int subscribeBackground = ThemeHelper
|
final int subscribeBackground = ThemeHelper
|
||||||
.resolveColorFromAttr(activity, R.attr.colorPrimary);
|
.resolveColorFromAttr(activity, R.attr.colorPrimary);
|
||||||
int subscribeText = ContextCompat.getColor(activity, R.color.subscribe_text_color);
|
final int subscribeText = ContextCompat.getColor(activity, R.color.subscribe_text_color);
|
||||||
int subscribedBackground = ContextCompat
|
final int subscribedBackground = ContextCompat
|
||||||
.getColor(activity, R.color.subscribed_background_color);
|
.getColor(activity, R.color.subscribed_background_color);
|
||||||
int subscribedText = ContextCompat.getColor(activity, R.color.subscribed_text_color);
|
final int subscribedText = ContextCompat.getColor(activity, R.color.subscribed_text_color);
|
||||||
|
|
||||||
if (!isSubscribed) {
|
if (!isSubscribed) {
|
||||||
headerSubscribeButton.setText(R.string.subscribe_button_title);
|
headerSubscribeButton.setText(R.string.subscribe_button_title);
|
||||||
|
@ -429,7 +429,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
||||||
NavigationHelper.openChannelFragment(getFM(), currentInfo.getServiceId(),
|
NavigationHelper.openChannelFragment(getFM(), currentInfo.getServiceId(),
|
||||||
currentInfo.getParentChannelUrl(),
|
currentInfo.getParentChannelUrl(),
|
||||||
currentInfo.getParentChannelName());
|
currentInfo.getParentChannelName());
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
||||||
}
|
}
|
||||||
} else if (DEBUG) {
|
} else if (DEBUG) {
|
||||||
|
@ -490,13 +490,13 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
||||||
|
|
||||||
playlistCtrl.setVisibility(View.VISIBLE);
|
playlistCtrl.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
List<Throwable> errors = new ArrayList<>(result.getErrors());
|
final List<Throwable> errors = new ArrayList<>(result.getErrors());
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
|
|
||||||
// handling ContentNotSupportedException not to show the error but an appropriate string
|
// handling ContentNotSupportedException not to show the error but an appropriate string
|
||||||
// so that crashes won't be sent uselessly and the user will understand what happened
|
// so that crashes won't be sent uselessly and the user will understand what happened
|
||||||
for (Iterator<Throwable> it = errors.iterator(); it.hasNext();) {
|
for (Iterator<Throwable> it = errors.iterator(); it.hasNext();) {
|
||||||
Throwable throwable = it.next();
|
final Throwable throwable = it.next();
|
||||||
if (throwable instanceof ContentNotSupportedException) {
|
if (throwable instanceof ContentNotSupportedException) {
|
||||||
showContentNotSupported();
|
showContentNotSupported();
|
||||||
it.remove();
|
it.remove();
|
||||||
|
@ -549,7 +549,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
||||||
|
|
||||||
private PlayQueue getPlayQueue(final int index) {
|
private PlayQueue getPlayQueue(final int index) {
|
||||||
final List<StreamInfoItem> streamItems = new ArrayList<>();
|
final List<StreamInfoItem> streamItems = new ArrayList<>();
|
||||||
for (InfoItem i : infoListAdapter.getItemsList()) {
|
for (final InfoItem i : infoListAdapter.getItemsList()) {
|
||||||
if (i instanceof StreamInfoItem) {
|
if (i instanceof StreamInfoItem) {
|
||||||
streamItems.add((StreamInfoItem) i);
|
streamItems.add((StreamInfoItem) i);
|
||||||
}
|
}
|
||||||
|
@ -581,7 +581,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int errorId = exception instanceof ExtractionException
|
final int errorId = exception instanceof ExtractionException
|
||||||
? R.string.parsing_error : R.string.general_error;
|
? R.string.parsing_error : R.string.general_error;
|
||||||
|
|
||||||
onUnrecoverableError(exception, UserAction.REQUESTED_CHANNEL,
|
onUnrecoverableError(exception, UserAction.REQUESTED_CHANNEL,
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
|
||||||
|
|
||||||
public static CommentsFragment getInstance(final int serviceId, final String url,
|
public static CommentsFragment getInstance(final int serviceId, final String url,
|
||||||
final String name) {
|
final String name) {
|
||||||
CommentsFragment instance = new CommentsFragment();
|
final CommentsFragment instance = new CommentsFragment();
|
||||||
instance.setInitialData(serviceId, url, name);
|
instance.setInitialData(serviceId, url, name);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class DefaultKioskFragment extends KioskFragment {
|
||||||
|
|
||||||
currentInfo = null;
|
currentInfo = null;
|
||||||
currentNextPage = null;
|
currentNextPage = null;
|
||||||
} catch (ExtractionException e) {
|
} catch (final ExtractionException e) {
|
||||||
onUnrecoverableError(e, UserAction.REQUESTED_KIOSK, "none",
|
onUnrecoverableError(e, UserAction.REQUESTED_KIOSK, "none",
|
||||||
"Loading default kiosk from selected service", 0);
|
"Loading default kiosk from selected service", 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,9 +72,9 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
||||||
|
|
||||||
public static KioskFragment getInstance(final int serviceId, final String kioskId)
|
public static KioskFragment getInstance(final int serviceId, final String kioskId)
|
||||||
throws ExtractionException {
|
throws ExtractionException {
|
||||||
KioskFragment instance = new KioskFragment();
|
final KioskFragment instance = new KioskFragment();
|
||||||
StreamingService service = NewPipe.getService(serviceId);
|
final StreamingService service = NewPipe.getService(serviceId);
|
||||||
ListLinkHandlerFactory kioskLinkHandlerFactory = service.getKioskList()
|
final ListLinkHandlerFactory kioskLinkHandlerFactory = service.getKioskList()
|
||||||
.getListLinkHandlerFactoryByType(kioskId);
|
.getListLinkHandlerFactoryByType(kioskId);
|
||||||
instance.setInitialData(serviceId,
|
instance.setInitialData(serviceId,
|
||||||
kioskLinkHandlerFactory.fromId(kioskId).getUrl(), kioskId);
|
kioskLinkHandlerFactory.fromId(kioskId).getUrl(), kioskId);
|
||||||
|
@ -101,7 +101,7 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
||||||
if (useAsFrontPage && isVisibleToUser && activity != null) {
|
if (useAsFrontPage && isVisibleToUser && activity != null) {
|
||||||
try {
|
try {
|
||||||
setTitle(kioskTranslatedName);
|
setTitle(kioskTranslatedName);
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
onUnrecoverableError(e, UserAction.UI_ERROR,
|
onUnrecoverableError(e, UserAction.UI_ERROR,
|
||||||
"none",
|
"none",
|
||||||
"none", R.string.app_ui_crash);
|
"none", R.string.app_ui_crash);
|
||||||
|
@ -132,7 +132,7 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
ActionBar supportActionBar = activity.getSupportActionBar();
|
final ActionBar supportActionBar = activity.getSupportActionBar();
|
||||||
if (supportActionBar != null && useAsFrontPage) {
|
if (supportActionBar != null && useAsFrontPage) {
|
||||||
supportActionBar.setDisplayHomeAsUpEnabled(false);
|
supportActionBar.setDisplayHomeAsUpEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
||||||
|
|
||||||
public static PlaylistFragment getInstance(final int serviceId, final String url,
|
public static PlaylistFragment getInstance(final int serviceId, final String url,
|
||||||
final String name) {
|
final String name) {
|
||||||
PlaylistFragment instance = new PlaylistFragment();
|
final PlaylistFragment instance = new PlaylistFragment();
|
||||||
instance.setInitialData(serviceId, url, name);
|
instance.setInitialData(serviceId, url, name);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
@ -288,7 +288,7 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
||||||
try {
|
try {
|
||||||
NavigationHelper.openChannelFragment(getFM(), result.getServiceId(),
|
NavigationHelper.openChannelFragment(getFM(), result.getServiceId(),
|
||||||
result.getUploaderUrl(), result.getUploaderName());
|
result.getUploaderUrl(), result.getUploaderName());
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -339,7 +339,7 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
||||||
|
|
||||||
private PlayQueue getPlayQueue(final int index) {
|
private PlayQueue getPlayQueue(final int index) {
|
||||||
final List<StreamInfoItem> infoItems = new ArrayList<>();
|
final List<StreamInfoItem> infoItems = new ArrayList<>();
|
||||||
for (InfoItem i : infoListAdapter.getItemsList()) {
|
for (final InfoItem i : infoListAdapter.getItemsList()) {
|
||||||
if (i instanceof StreamInfoItem) {
|
if (i instanceof StreamInfoItem) {
|
||||||
infoItems.add((StreamInfoItem) i);
|
infoItems.add((StreamInfoItem) i);
|
||||||
}
|
}
|
||||||
|
@ -373,7 +373,7 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int errorId = exception instanceof ExtractionException
|
final int errorId = exception instanceof ExtractionException
|
||||||
? R.string.parsing_error : R.string.general_error;
|
? R.string.parsing_error : R.string.general_error;
|
||||||
onUnrecoverableError(exception, UserAction.REQUESTED_PLAYLIST,
|
onUnrecoverableError(exception, UserAction.REQUESTED_PLAYLIST,
|
||||||
NewPipe.getNameOfService(serviceId), url, errorId);
|
NewPipe.getNameOfService(serviceId), url, errorId);
|
||||||
|
|
|
@ -161,7 +161,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
private TextWatcher textWatcher;
|
private TextWatcher textWatcher;
|
||||||
|
|
||||||
public static SearchFragment getInstance(final int serviceId, final String searchString) {
|
public static SearchFragment getInstance(final int serviceId, final String searchString) {
|
||||||
SearchFragment searchFragment = new SearchFragment();
|
final SearchFragment searchFragment = new SearchFragment();
|
||||||
searchFragment.setQuery(serviceId, searchString, new String[0], "");
|
searchFragment.setQuery(serviceId, searchString, new String[0], "");
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(searchString)) {
|
if (!TextUtils.isEmpty(searchString)) {
|
||||||
|
@ -187,8 +187,9 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
|
|
||||||
suggestionListAdapter = new SuggestionListAdapter(activity);
|
suggestionListAdapter = new SuggestionListAdapter(activity);
|
||||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
final SharedPreferences preferences
|
||||||
boolean isSearchHistoryEnabled = preferences
|
= PreferenceManager.getDefaultSharedPreferences(activity);
|
||||||
|
final boolean isSearchHistoryEnabled = preferences
|
||||||
.getBoolean(getString(R.string.enable_search_history_key), true);
|
.getBoolean(getString(R.string.enable_search_history_key), true);
|
||||||
suggestionListAdapter.setShowSuggestionHistory(isSearchHistoryEnabled);
|
suggestionListAdapter.setShowSuggestionHistory(isSearchHistoryEnabled);
|
||||||
|
|
||||||
|
@ -199,7 +200,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
public void onCreate(final Bundle savedInstanceState) {
|
public void onCreate(final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
final SharedPreferences preferences
|
||||||
|
= PreferenceManager.getDefaultSharedPreferences(activity);
|
||||||
isSuggestionsEnabled = preferences
|
isSuggestionsEnabled = preferences
|
||||||
.getBoolean(getString(R.string.show_search_suggestions_key), true);
|
.getBoolean(getString(R.string.show_search_suggestions_key), true);
|
||||||
contentCountry = preferences.getString(getString(R.string.content_country_key),
|
contentCountry = preferences.getString(getString(R.string.content_country_key),
|
||||||
|
@ -246,7 +248,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
|
|
||||||
try {
|
try {
|
||||||
service = NewPipe.getService(serviceId);
|
service = NewPipe.getService(serviceId);
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportError(getActivity(), e, getActivity().getClass(),
|
ErrorActivity.reportError(getActivity(), e, getActivity().getClass(),
|
||||||
getActivity().findViewById(android.R.id.content),
|
getActivity().findViewById(android.R.id.content),
|
||||||
ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
|
ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
|
||||||
|
@ -413,7 +415,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
|
|
||||||
ActionBar supportActionBar = activity.getSupportActionBar();
|
final ActionBar supportActionBar = activity.getSupportActionBar();
|
||||||
if (supportActionBar != null) {
|
if (supportActionBar != null) {
|
||||||
supportActionBar.setDisplayShowTitleEnabled(false);
|
supportActionBar.setDisplayShowTitleEnabled(false);
|
||||||
supportActionBar.setDisplayHomeAsUpEnabled(true);
|
supportActionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
|
@ -424,16 +426,16 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
int itemId = 0;
|
int itemId = 0;
|
||||||
boolean isFirstItem = true;
|
boolean isFirstItem = true;
|
||||||
final Context c = getContext();
|
final Context c = getContext();
|
||||||
for (String filter : service.getSearchQHFactory().getAvailableContentFilter()) {
|
for (final String filter : service.getSearchQHFactory().getAvailableContentFilter()) {
|
||||||
if (filter.equals("music_songs")) {
|
if (filter.equals("music_songs")) {
|
||||||
MenuItem musicItem = menu.add(2,
|
final MenuItem musicItem = menu.add(2,
|
||||||
itemId++,
|
itemId++,
|
||||||
0,
|
0,
|
||||||
"YouTube Music");
|
"YouTube Music");
|
||||||
musicItem.setEnabled(false);
|
musicItem.setEnabled(false);
|
||||||
}
|
}
|
||||||
menuItemToFilterName.put(itemId, filter);
|
menuItemToFilterName.put(itemId, filter);
|
||||||
MenuItem item = menu.add(1,
|
final MenuItem item = menu.add(1,
|
||||||
itemId++,
|
itemId++,
|
||||||
0,
|
0,
|
||||||
ServiceHelper.getTranslatedFilterString(filter, c));
|
ServiceHelper.getTranslatedFilterString(filter, c));
|
||||||
|
@ -449,7 +451,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
List<String> cf = new ArrayList<>(1);
|
final List<String> cf = new ArrayList<>(1);
|
||||||
cf.add(menuItemToFilterName.get(item.getItemId()));
|
cf.add(menuItemToFilterName.get(item.getItemId()));
|
||||||
changeContentFilter(item, cf);
|
changeContentFilter(item, cf);
|
||||||
|
|
||||||
|
@ -458,7 +460,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
|
|
||||||
private void restoreFilterChecked(final Menu menu, final int itemId) {
|
private void restoreFilterChecked(final Menu menu, final int itemId) {
|
||||||
if (itemId != -1) {
|
if (itemId != -1) {
|
||||||
MenuItem item = menu.findItem(itemId);
|
final MenuItem item = menu.findItem(itemId);
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -578,7 +580,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(final Editable s) {
|
public void afterTextChanged(final Editable s) {
|
||||||
String newText = searchEditText.getText().toString();
|
final String newText = searchEditText.getText().toString();
|
||||||
suggestionPublisher.onNext(newText);
|
suggestionPublisher.onNext(newText);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -644,7 +646,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchEditText.requestFocus()) {
|
if (searchEditText.requestFocus()) {
|
||||||
InputMethodManager imm = (InputMethodManager) activity.getSystemService(
|
final InputMethodManager imm = (InputMethodManager) activity.getSystemService(
|
||||||
Context.INPUT_METHOD_SERVICE);
|
Context.INPUT_METHOD_SERVICE);
|
||||||
imm.showSoftInput(searchEditText, InputMethodManager.SHOW_FORCED);
|
imm.showSoftInput(searchEditText, InputMethodManager.SHOW_FORCED);
|
||||||
}
|
}
|
||||||
|
@ -658,7 +660,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputMethodManager imm = (InputMethodManager) activity
|
final InputMethodManager imm = (InputMethodManager) activity
|
||||||
.getSystemService(Context.INPUT_METHOD_SERVICE);
|
.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
imm.hideSoftInputFromWindow(searchEditText.getWindowToken(),
|
imm.hideSoftInputFromWindow(searchEditText.getWindowToken(),
|
||||||
InputMethodManager.RESULT_UNCHANGED_SHOWN);
|
InputMethodManager.RESULT_UNCHANGED_SHOWN);
|
||||||
|
@ -725,8 +727,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
.getRelatedSearches(query, 3, 25);
|
.getRelatedSearches(query, 3, 25);
|
||||||
final Observable<List<SuggestionItem>> local = flowable.toObservable()
|
final Observable<List<SuggestionItem>> local = flowable.toObservable()
|
||||||
.map(searchHistoryEntries -> {
|
.map(searchHistoryEntries -> {
|
||||||
List<SuggestionItem> result = new ArrayList<>();
|
final List<SuggestionItem> result = new ArrayList<>();
|
||||||
for (SearchHistoryEntry entry : searchHistoryEntries) {
|
for (final SearchHistoryEntry entry : searchHistoryEntries) {
|
||||||
result.add(new SuggestionItem(true, entry.getSearch()));
|
result.add(new SuggestionItem(true, entry.getSearch()));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -742,15 +744,15 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
.suggestionsFor(serviceId, query)
|
.suggestionsFor(serviceId, query)
|
||||||
.toObservable()
|
.toObservable()
|
||||||
.map(strings -> {
|
.map(strings -> {
|
||||||
List<SuggestionItem> result = new ArrayList<>();
|
final List<SuggestionItem> result = new ArrayList<>();
|
||||||
for (String entry : strings) {
|
for (final String entry : strings) {
|
||||||
result.add(new SuggestionItem(false, entry));
|
result.add(new SuggestionItem(false, entry));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
return Observable.zip(local, network, (localResult, networkResult) -> {
|
return Observable.zip(local, network, (localResult, networkResult) -> {
|
||||||
List<SuggestionItem> result = new ArrayList<>();
|
final List<SuggestionItem> result = new ArrayList<>();
|
||||||
if (localResult.size() > 0) {
|
if (localResult.size() > 0) {
|
||||||
result.addAll(localResult);
|
result.addAll(localResult);
|
||||||
}
|
}
|
||||||
|
@ -759,7 +761,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
final Iterator<SuggestionItem> iterator = networkResult.iterator();
|
final Iterator<SuggestionItem> iterator = networkResult.iterator();
|
||||||
while (iterator.hasNext() && localResult.size() > 0) {
|
while (iterator.hasNext() && localResult.size() > 0) {
|
||||||
final SuggestionItem next = iterator.next();
|
final SuggestionItem next = iterator.next();
|
||||||
for (SuggestionItem item : localResult) {
|
for (final SuggestionItem item : localResult) {
|
||||||
if (item.query.equals(next.query)) {
|
if (item.query.equals(next.query)) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
break;
|
break;
|
||||||
|
@ -813,7 +815,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
showError(getString(R.string.url_not_supported_toast), false)));
|
showError(getString(R.string.url_not_supported_toast), false)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
} catch (final Exception ignored) {
|
||||||
// Exception occurred, it's not a url
|
// Exception occurred, it's not a url
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,7 +937,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int errorId = exception instanceof ParsingException
|
final int errorId = exception instanceof ParsingException
|
||||||
? R.string.parsing_error
|
? R.string.parsing_error
|
||||||
: R.string.general_error;
|
: R.string.general_error;
|
||||||
onUnrecoverableError(exception, UserAction.GET_SUGGESTIONS,
|
onUnrecoverableError(exception, UserAction.GET_SUGGESTIONS,
|
||||||
|
@ -1051,7 +1053,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
infoListAdapter.clearStreamItemList();
|
infoListAdapter.clearStreamItemList();
|
||||||
showEmptyState();
|
showEmptyState();
|
||||||
} else {
|
} else {
|
||||||
int errorId = exception instanceof ParsingException
|
final int errorId = exception instanceof ParsingException
|
||||||
? R.string.parsing_error
|
? R.string.parsing_error
|
||||||
: R.string.general_error;
|
: R.string.general_error;
|
||||||
onUnrecoverableError(exception, UserAction.SEARCHED,
|
onUnrecoverableError(exception, UserAction.SEARCHED,
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class SuggestionListAdapter
|
||||||
this.items.addAll(items);
|
this.items.addAll(items);
|
||||||
} else {
|
} else {
|
||||||
// remove history items if history is disabled
|
// remove history items if history is disabled
|
||||||
for (SuggestionItem item : items) {
|
for (final SuggestionItem item : items) {
|
||||||
if (!item.fromHistory) {
|
if (!item.fromHistory) {
|
||||||
this.items.add(item);
|
this.items.add(item);
|
||||||
}
|
}
|
||||||
|
@ -123,8 +123,8 @@ public class SuggestionListAdapter
|
||||||
|
|
||||||
private static int resolveResourceIdFromAttr(final Context context,
|
private static int resolveResourceIdFromAttr(final Context context,
|
||||||
@AttrRes final int attr) {
|
@AttrRes final int attr) {
|
||||||
TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
|
final TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
|
||||||
int attributeResourceId = a.getResourceId(0, 0);
|
final int attributeResourceId = a.getResourceId(0, 0);
|
||||||
a.recycle();
|
a.recycle();
|
||||||
return attributeResourceId;
|
return attributeResourceId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
|
||||||
private Switch autoplaySwitch;
|
private Switch autoplaySwitch;
|
||||||
|
|
||||||
public static RelatedVideosFragment getInstance(final StreamInfo info) {
|
public static RelatedVideosFragment getInstance(final StreamInfo info) {
|
||||||
RelatedVideosFragment instance = new RelatedVideosFragment();
|
final RelatedVideosFragment instance = new RelatedVideosFragment();
|
||||||
instance.setInitialData(info);
|
instance.setInitialData(info);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
|
||||||
protected void onRestoreInstanceState(@NonNull final Bundle savedState) {
|
protected void onRestoreInstanceState(@NonNull final Bundle savedState) {
|
||||||
super.onRestoreInstanceState(savedState);
|
super.onRestoreInstanceState(savedState);
|
||||||
if (savedState != null) {
|
if (savedState != null) {
|
||||||
Serializable serializable = savedState.getSerializable(INFO_KEY);
|
final Serializable serializable = savedState.getSerializable(INFO_KEY);
|
||||||
if (serializable instanceof RelatedStreamInfo) {
|
if (serializable instanceof RelatedStreamInfo) {
|
||||||
this.relatedStreamInfo = (RelatedStreamInfo) serializable;
|
this.relatedStreamInfo = (RelatedStreamInfo) serializable;
|
||||||
}
|
}
|
||||||
|
@ -201,8 +201,8 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences,
|
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences,
|
||||||
final String s) {
|
final String s) {
|
||||||
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getContext());
|
final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
boolean autoplay = pref.getBoolean(getString(R.string.auto_queue_key), false);
|
final boolean autoplay = pref.getBoolean(getString(R.string.auto_queue_key), false);
|
||||||
if (autoplaySwitch != null) {
|
if (autoplaySwitch != null) {
|
||||||
autoplaySwitch.setChecked(autoplay);
|
autoplaySwitch.setChecked(autoplay);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,8 @@ public class InfoItemBuilder {
|
||||||
public View buildView(@NonNull final ViewGroup parent, @NonNull final InfoItem infoItem,
|
public View buildView(@NonNull final ViewGroup parent, @NonNull final InfoItem infoItem,
|
||||||
final HistoryRecordManager historyRecordManager,
|
final HistoryRecordManager historyRecordManager,
|
||||||
final boolean useMiniVariant) {
|
final boolean useMiniVariant) {
|
||||||
InfoItemHolder holder = holderFromInfoType(parent, infoItem.getInfoType(), useMiniVariant);
|
final InfoItemHolder holder
|
||||||
|
= holderFromInfoType(parent, infoItem.getInfoType(), useMiniVariant);
|
||||||
holder.updateFromItem(infoItem, historyRecordManager);
|
holder.updateFromItem(infoItem, historyRecordManager);
|
||||||
return holder.itemView;
|
return holder.itemView;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,10 +31,10 @@ public class InfoItemDialog {
|
||||||
final View bannerView = View.inflate(activity, R.layout.dialog_title, null);
|
final View bannerView = View.inflate(activity, R.layout.dialog_title, null);
|
||||||
bannerView.setSelected(true);
|
bannerView.setSelected(true);
|
||||||
|
|
||||||
TextView titleView = bannerView.findViewById(R.id.itemTitleView);
|
final TextView titleView = bannerView.findViewById(R.id.itemTitleView);
|
||||||
titleView.setText(title);
|
titleView.setText(title);
|
||||||
|
|
||||||
TextView detailsView = bannerView.findViewById(R.id.itemAdditionalDetails);
|
final TextView detailsView = bannerView.findViewById(R.id.itemAdditionalDetails);
|
||||||
if (additionalDetail != null) {
|
if (additionalDetail != null) {
|
||||||
detailsView.setText(additionalDetail);
|
detailsView.setText(additionalDetail);
|
||||||
detailsView.setVisibility(View.VISIBLE);
|
detailsView.setVisibility(View.VISIBLE);
|
||||||
|
|
|
@ -123,7 +123,7 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
||||||
+ infoItemList.size() + ", data.size() = " + data.size());
|
+ infoItemList.size() + ", data.size() = " + data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
int offsetStart = sizeConsideringHeaderOffset();
|
final int offsetStart = sizeConsideringHeaderOffset();
|
||||||
infoItemList.addAll(data);
|
infoItemList.addAll(data);
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -135,7 +135,7 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
||||||
notifyItemRangeInserted(offsetStart, data.size());
|
notifyItemRangeInserted(offsetStart, data.size());
|
||||||
|
|
||||||
if (footer != null && showFooter) {
|
if (footer != null && showFooter) {
|
||||||
int footerNow = sizeConsideringHeaderOffset();
|
final int footerNow = sizeConsideringHeaderOffset();
|
||||||
notifyItemMoved(offsetStart, footerNow);
|
notifyItemMoved(offsetStart, footerNow);
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -160,7 +160,7 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
||||||
+ infoItemList.size() + ", thread = " + Thread.currentThread());
|
+ infoItemList.size() + ", thread = " + Thread.currentThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
int positionInserted = sizeConsideringHeaderOffset();
|
final int positionInserted = sizeConsideringHeaderOffset();
|
||||||
infoItemList.add(data);
|
infoItemList.add(data);
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -172,7 +172,7 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
||||||
notifyItemInserted(positionInserted);
|
notifyItemInserted(positionInserted);
|
||||||
|
|
||||||
if (footer != null && showFooter) {
|
if (footer != null && showFooter) {
|
||||||
int footerNow = sizeConsideringHeaderOffset();
|
final int footerNow = sizeConsideringHeaderOffset();
|
||||||
notifyItemMoved(positionInserted, footerNow);
|
notifyItemMoved(positionInserted, footerNow);
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -191,7 +191,7 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHeader(final View header) {
|
public void setHeader(final View header) {
|
||||||
boolean changed = header != this.header;
|
final boolean changed = header != this.header;
|
||||||
this.header = header;
|
this.header = header;
|
||||||
if (changed) {
|
if (changed) {
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
|
@ -219,7 +219,7 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
||||||
}
|
}
|
||||||
|
|
||||||
private int sizeConsideringHeaderOffset() {
|
private int sizeConsideringHeaderOffset() {
|
||||||
int i = infoItemList.size() + (header != null ? 1 : 0);
|
final int i = infoItemList.size() + (header != null ? 1 : 0);
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "sizeConsideringHeaderOffset() called → " + i);
|
Log.d(TAG, "sizeConsideringHeaderOffset() called → " + i);
|
||||||
}
|
}
|
||||||
|
@ -347,7 +347,7 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
||||||
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position,
|
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position,
|
||||||
@NonNull final List<Object> payloads) {
|
@NonNull final List<Object> payloads) {
|
||||||
if (!payloads.isEmpty() && holder instanceof InfoItemHolder) {
|
if (!payloads.isEmpty() && holder instanceof InfoItemHolder) {
|
||||||
for (Object payload : payloads) {
|
for (final Object payload : payloads) {
|
||||||
if (payload instanceof StreamStateEntity) {
|
if (payload instanceof StreamStateEntity) {
|
||||||
((InfoItemHolder) holder).updateState(infoItemList
|
((InfoItemHolder) holder).updateState(infoItemList
|
||||||
.get(header == null ? position : position - 1), recordManager);
|
.get(header == null ? position : position - 1), recordManager);
|
||||||
|
|
|
@ -56,8 +56,8 @@ public class ChannelInfoItemHolder extends ChannelMiniInfoItemHolder {
|
||||||
String details = super.getDetailLine(item);
|
String details = super.getDetailLine(item);
|
||||||
|
|
||||||
if (item.getStreamCount() >= 0) {
|
if (item.getStreamCount() >= 0) {
|
||||||
String formattedVideoAmount = Localization.localizeStreamCount(itemBuilder.getContext(),
|
final String formattedVideoAmount = Localization.localizeStreamCount(
|
||||||
item.getStreamCount());
|
itemBuilder.getContext(), item.getStreamCount());
|
||||||
|
|
||||||
if (!details.isEmpty()) {
|
if (!details.isEmpty()) {
|
||||||
details += " • " + formattedVideoAmount;
|
details += " • " + formattedVideoAmount;
|
||||||
|
|
|
@ -45,9 +45,9 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
|
||||||
@Override
|
@Override
|
||||||
public String transformUrl(final Matcher match, final String url) {
|
public String transformUrl(final Matcher match, final String url) {
|
||||||
int timestamp = 0;
|
int timestamp = 0;
|
||||||
String hours = match.group(1);
|
final String hours = match.group(1);
|
||||||
String minutes = match.group(2);
|
final String minutes = match.group(2);
|
||||||
String seconds = match.group(3);
|
final String seconds = match.group(3);
|
||||||
if (hours != null) {
|
if (hours != null) {
|
||||||
timestamp += (Integer.parseInt(hours.replace(":", "")) * 3600);
|
timestamp += (Integer.parseInt(hours.replace(":", "")) * 3600);
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
|
||||||
item.getServiceId(),
|
item.getServiceId(),
|
||||||
item.getUploaderUrl(),
|
item.getUploaderUrl(),
|
||||||
item.getUploaderName());
|
item.getUploaderName());
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError((AppCompatActivity) itemBuilder.getContext(), e);
|
ErrorActivity.reportUiError((AppCompatActivity) itemBuilder.getContext(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
URLSpan[] urls = itemContentView.getUrls();
|
final URLSpan[] urls = itemContentView.getUrls();
|
||||||
|
|
||||||
return urls != null && urls.length != 0;
|
return urls != null && urls.length != 0;
|
||||||
}
|
}
|
||||||
|
@ -181,12 +181,13 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
|
||||||
boolean hasEllipsis = false;
|
boolean hasEllipsis = false;
|
||||||
|
|
||||||
if (itemContentView.getLineCount() > COMMENT_DEFAULT_LINES) {
|
if (itemContentView.getLineCount() > COMMENT_DEFAULT_LINES) {
|
||||||
int endOfLastLine = itemContentView.getLayout().getLineEnd(COMMENT_DEFAULT_LINES - 1);
|
final int endOfLastLine
|
||||||
|
= itemContentView.getLayout().getLineEnd(COMMENT_DEFAULT_LINES - 1);
|
||||||
int end = itemContentView.getText().toString().lastIndexOf(' ', endOfLastLine - 2);
|
int end = itemContentView.getText().toString().lastIndexOf(' ', endOfLastLine - 2);
|
||||||
if (end == -1) {
|
if (end == -1) {
|
||||||
end = Math.max(endOfLastLine - 2, 0);
|
end = Math.max(endOfLastLine - 2, 0);
|
||||||
}
|
}
|
||||||
String newVal = itemContentView.getText().subSequence(0, end) + " …";
|
final String newVal = itemContentView.getText().subSequence(0, end) + " …";
|
||||||
itemContentView.setText(newVal);
|
itemContentView.setText(newVal);
|
||||||
hasEllipsis = true;
|
hasEllipsis = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder {
|
||||||
R.color.duration_background_color));
|
R.color.duration_background_color));
|
||||||
itemDurationView.setVisibility(View.VISIBLE);
|
itemDurationView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
StreamStateEntity state2 = historyRecordManager.loadStreamState(infoItem)
|
final StreamStateEntity state2 = historyRecordManager.loadStreamState(infoItem)
|
||||||
.blockingGet()[0];
|
.blockingGet()[0];
|
||||||
if (state2 != null) {
|
if (state2 != null) {
|
||||||
itemProgressView.setVisibility(View.VISIBLE);
|
itemProgressView.setVisibility(View.VISIBLE);
|
||||||
|
@ -113,7 +113,8 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder {
|
||||||
final HistoryRecordManager historyRecordManager) {
|
final HistoryRecordManager historyRecordManager) {
|
||||||
final StreamInfoItem item = (StreamInfoItem) infoItem;
|
final StreamInfoItem item = (StreamInfoItem) infoItem;
|
||||||
|
|
||||||
StreamStateEntity state = historyRecordManager.loadStreamState(infoItem).blockingGet()[0];
|
final StreamStateEntity state
|
||||||
|
= historyRecordManager.loadStreamState(infoItem).blockingGet()[0];
|
||||||
if (state != null && item.getDuration() > 0
|
if (state != null && item.getDuration() > 0
|
||||||
&& item.getStreamType() != StreamType.LIVE_STREAM) {
|
&& item.getStreamType() != StreamType.LIVE_STREAM) {
|
||||||
itemProgressView.setMax((int) item.getDuration());
|
itemProgressView.setMax((int) item.getDuration());
|
||||||
|
|
|
@ -101,7 +101,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
+ localItems.size() + ", data.size() = " + data.size());
|
+ localItems.size() + ", data.size() = " + data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
int offsetStart = sizeConsideringHeader();
|
final int offsetStart = sizeConsideringHeader();
|
||||||
localItems.addAll(data);
|
localItems.addAll(data);
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -113,7 +113,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
notifyItemRangeInserted(offsetStart, data.size());
|
notifyItemRangeInserted(offsetStart, data.size());
|
||||||
|
|
||||||
if (footer != null && showFooter) {
|
if (footer != null && showFooter) {
|
||||||
int footerNow = sizeConsideringHeader();
|
final int footerNow = sizeConsideringHeader();
|
||||||
notifyItemMoved(offsetStart, footerNow);
|
notifyItemMoved(offsetStart, footerNow);
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -158,7 +158,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHeader(final View header) {
|
public void setHeader(final View header) {
|
||||||
boolean changed = header != this.header;
|
final boolean changed = header != this.header;
|
||||||
this.header = header;
|
this.header = header;
|
||||||
if (changed) {
|
if (changed) {
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
|
@ -316,7 +316,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position,
|
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position,
|
||||||
@NonNull final List<Object> payloads) {
|
@NonNull final List<Object> payloads) {
|
||||||
if (!payloads.isEmpty() && holder instanceof LocalItemHolder) {
|
if (!payloads.isEmpty() && holder instanceof LocalItemHolder) {
|
||||||
for (Object payload : payloads) {
|
for (final Object payload : payloads) {
|
||||||
if (payload instanceof StreamStateEntity) {
|
if (payload instanceof StreamStateEntity) {
|
||||||
((LocalItemHolder) holder).updateState(localItems
|
((LocalItemHolder) holder).updateState(localItems
|
||||||
.get(header == null ? position : position - 1), recordManager);
|
.get(header == null ? position : position - 1), recordManager);
|
||||||
|
|
|
@ -265,11 +265,11 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showLocalDialog(final PlaylistMetadataEntry selectedItem) {
|
private void showLocalDialog(final PlaylistMetadataEntry selectedItem) {
|
||||||
View dialogView = View.inflate(getContext(), R.layout.dialog_bookmark, null);
|
final View dialogView = View.inflate(getContext(), R.layout.dialog_bookmark, null);
|
||||||
EditText editText = dialogView.findViewById(R.id.playlist_name_edit_text);
|
final EditText editText = dialogView.findViewById(R.id.playlist_name_edit_text);
|
||||||
editText.setText(selectedItem.name);
|
editText.setText(selectedItem.name);
|
||||||
|
|
||||||
Builder builder = new AlertDialog.Builder(activity);
|
final Builder builder = new AlertDialog.Builder(activity);
|
||||||
builder.setView(dialogView)
|
builder.setView(dialogView)
|
||||||
.setPositiveButton(R.string.rename_playlist, (dialog, which) -> {
|
.setPositiveButton(R.string.rename_playlist, (dialog, which) -> {
|
||||||
changeLocalPlaylistName(selectedItem.uid, editText.getText().toString());
|
changeLocalPlaylistName(selectedItem.uid, editText.getText().toString());
|
||||||
|
|
|
@ -39,14 +39,14 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
|
||||||
private CompositeDisposable playlistDisposables = new CompositeDisposable();
|
private CompositeDisposable playlistDisposables = new CompositeDisposable();
|
||||||
|
|
||||||
public static PlaylistAppendDialog fromStreamInfo(final StreamInfo info) {
|
public static PlaylistAppendDialog fromStreamInfo(final StreamInfo info) {
|
||||||
PlaylistAppendDialog dialog = new PlaylistAppendDialog();
|
final PlaylistAppendDialog dialog = new PlaylistAppendDialog();
|
||||||
dialog.setInfo(Collections.singletonList(new StreamEntity(info)));
|
dialog.setInfo(Collections.singletonList(new StreamEntity(info)));
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlaylistAppendDialog fromStreamInfoItems(final List<StreamInfoItem> items) {
|
public static PlaylistAppendDialog fromStreamInfoItems(final List<StreamInfoItem> items) {
|
||||||
PlaylistAppendDialog dialog = new PlaylistAppendDialog();
|
final PlaylistAppendDialog dialog = new PlaylistAppendDialog();
|
||||||
List<StreamEntity> entities = new ArrayList<>(items.size());
|
final List<StreamEntity> entities = new ArrayList<>(items.size());
|
||||||
for (final StreamInfoItem item : items) {
|
for (final StreamInfoItem item : items) {
|
||||||
entities.add(new StreamEntity(item));
|
entities.add(new StreamEntity(item));
|
||||||
}
|
}
|
||||||
|
@ -55,8 +55,8 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlaylistAppendDialog fromPlayQueueItems(final List<PlayQueueItem> items) {
|
public static PlaylistAppendDialog fromPlayQueueItems(final List<PlayQueueItem> items) {
|
||||||
PlaylistAppendDialog dialog = new PlaylistAppendDialog();
|
final PlaylistAppendDialog dialog = new PlaylistAppendDialog();
|
||||||
List<StreamEntity> entities = new ArrayList<>(items.size());
|
final List<StreamEntity> entities = new ArrayList<>(items.size());
|
||||||
for (final PlayQueueItem item : items) {
|
for (final PlayQueueItem item : items) {
|
||||||
entities.add(new StreamEntity(item));
|
entities.add(new StreamEntity(item));
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
|
||||||
public final class PlaylistCreationDialog extends PlaylistDialog {
|
public final class PlaylistCreationDialog extends PlaylistDialog {
|
||||||
public static PlaylistCreationDialog newInstance(final List<StreamEntity> streams) {
|
public static PlaylistCreationDialog newInstance(final List<StreamEntity> streams) {
|
||||||
PlaylistCreationDialog dialog = new PlaylistCreationDialog();
|
final PlaylistCreationDialog dialog = new PlaylistCreationDialog();
|
||||||
dialog.setInfo(streams);
|
dialog.setInfo(streams);
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,8 @@ public final class PlaylistCreationDialog extends PlaylistDialog {
|
||||||
return super.onCreateDialog(savedInstanceState);
|
return super.onCreateDialog(savedInstanceState);
|
||||||
}
|
}
|
||||||
|
|
||||||
View dialogView = View.inflate(getContext(), R.layout.dialog_playlist_name, null);
|
final View dialogView = View.inflate(getContext(), R.layout.dialog_playlist_name, null);
|
||||||
EditText nameInput = dialogView.findViewById(R.id.playlist_name);
|
final EditText nameInput = dialogView.findViewById(R.id.playlist_name);
|
||||||
|
|
||||||
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getContext())
|
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getContext())
|
||||||
.setTitle(R.string.create_playlist)
|
.setTitle(R.string.create_playlist)
|
||||||
|
|
|
@ -88,7 +88,7 @@ public class HistoryRecordManager {
|
||||||
final Date currentTime = new Date();
|
final Date currentTime = new Date();
|
||||||
return Maybe.fromCallable(() -> database.runInTransaction(() -> {
|
return Maybe.fromCallable(() -> database.runInTransaction(() -> {
|
||||||
final long streamId = streamTable.upsert(new StreamEntity(info));
|
final long streamId = streamTable.upsert(new StreamEntity(info));
|
||||||
StreamHistoryEntity latestEntry = streamHistoryTable.getLatestEntry(streamId);
|
final StreamHistoryEntity latestEntry = streamHistoryTable.getLatestEntry(streamId);
|
||||||
|
|
||||||
if (latestEntry != null) {
|
if (latestEntry != null) {
|
||||||
streamHistoryTable.delete(latestEntry);
|
streamHistoryTable.delete(latestEntry);
|
||||||
|
@ -129,7 +129,7 @@ public class HistoryRecordManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Single<List<Long>> insertStreamHistory(final Collection<StreamHistoryEntry> entries) {
|
public Single<List<Long>> insertStreamHistory(final Collection<StreamHistoryEntry> entries) {
|
||||||
List<StreamHistoryEntity> entities = new ArrayList<>(entries.size());
|
final List<StreamHistoryEntity> entities = new ArrayList<>(entries.size());
|
||||||
for (final StreamHistoryEntry entry : entries) {
|
for (final StreamHistoryEntry entry : entries) {
|
||||||
entities.add(entry.toStreamHistoryEntity());
|
entities.add(entry.toStreamHistoryEntity());
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ public class HistoryRecordManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Single<Integer> deleteStreamHistory(final Collection<StreamHistoryEntry> entries) {
|
public Single<Integer> deleteStreamHistory(final Collection<StreamHistoryEntry> entries) {
|
||||||
List<StreamHistoryEntity> entities = new ArrayList<>(entries.size());
|
final List<StreamHistoryEntity> entities = new ArrayList<>(entries.size());
|
||||||
for (final StreamHistoryEntry entry : entries) {
|
for (final StreamHistoryEntry entry : entries) {
|
||||||
entities.add(entry.toStreamHistoryEntity());
|
entities.add(entry.toStreamHistoryEntity());
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ public class HistoryRecordManager {
|
||||||
final SearchHistoryEntry newEntry = new SearchHistoryEntry(currentTime, serviceId, search);
|
final SearchHistoryEntry newEntry = new SearchHistoryEntry(currentTime, serviceId, search);
|
||||||
|
|
||||||
return Maybe.fromCallable(() -> database.runInTransaction(() -> {
|
return Maybe.fromCallable(() -> database.runInTransaction(() -> {
|
||||||
SearchHistoryEntry latestEntry = searchHistoryTable.getLatestEntry();
|
final SearchHistoryEntry latestEntry = searchHistoryTable.getLatestEntry();
|
||||||
if (latestEntry != null && latestEntry.hasEqualValues(newEntry)) {
|
if (latestEntry != null && latestEntry.hasEqualValues(newEntry)) {
|
||||||
latestEntry.setCreationDate(currentTime);
|
latestEntry.setCreationDate(currentTime);
|
||||||
return (long) searchHistoryTable.update(latestEntry);
|
return (long) searchHistoryTable.update(latestEntry);
|
||||||
|
@ -256,7 +256,7 @@ public class HistoryRecordManager {
|
||||||
public Single<List<StreamStateEntity>> loadStreamStateBatch(final List<InfoItem> infos) {
|
public Single<List<StreamStateEntity>> loadStreamStateBatch(final List<InfoItem> infos) {
|
||||||
return Single.fromCallable(() -> {
|
return Single.fromCallable(() -> {
|
||||||
final List<StreamStateEntity> result = new ArrayList<>(infos.size());
|
final List<StreamStateEntity> result = new ArrayList<>(infos.size());
|
||||||
for (InfoItem info : infos) {
|
for (final InfoItem info : infos) {
|
||||||
final List<StreamEntity> entities = streamTable
|
final List<StreamEntity> entities = streamTable
|
||||||
.getStream(info.getServiceId(), info.getUrl()).blockingFirst();
|
.getStream(info.getServiceId(), info.getUrl()).blockingFirst();
|
||||||
if (entities.isEmpty()) {
|
if (entities.isEmpty()) {
|
||||||
|
@ -279,8 +279,8 @@ public class HistoryRecordManager {
|
||||||
final List<? extends LocalItem> items) {
|
final List<? extends LocalItem> items) {
|
||||||
return Single.fromCallable(() -> {
|
return Single.fromCallable(() -> {
|
||||||
final List<StreamStateEntity> result = new ArrayList<>(items.size());
|
final List<StreamStateEntity> result = new ArrayList<>(items.size());
|
||||||
for (LocalItem item : items) {
|
for (final LocalItem item : items) {
|
||||||
long streamId;
|
final long streamId;
|
||||||
if (item instanceof StreamStatisticsEntry) {
|
if (item instanceof StreamStatisticsEntry) {
|
||||||
streamId = ((StreamStatisticsEntry) item).getStreamId();
|
streamId = ((StreamStatisticsEntry) item).getStreamId();
|
||||||
} else if (item instanceof PlaylistStreamEntity) {
|
} else if (item instanceof PlaylistStreamEntity) {
|
||||||
|
|
|
@ -455,7 +455,7 @@ public class StatisticsPlaylistFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<LocalItem> infoItems = itemListAdapter.getItemsList();
|
final List<LocalItem> infoItems = itemListAdapter.getItemsList();
|
||||||
List<StreamInfoItem> streamInfoItems = new ArrayList<>(infoItems.size());
|
final List<StreamInfoItem> streamInfoItems = new ArrayList<>(infoItems.size());
|
||||||
for (final LocalItem item : infoItems) {
|
for (final LocalItem item : infoItems) {
|
||||||
if (item instanceof StreamStatisticsEntry) {
|
if (item instanceof StreamStatisticsEntry) {
|
||||||
streamInfoItems.add(((StreamStatisticsEntry) item).toStreamInfoItem());
|
streamInfoItems.add(((StreamStatisticsEntry) item).toStreamInfoItem());
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
|
||||||
R.color.duration_background_color));
|
R.color.duration_background_color));
|
||||||
itemDurationView.setVisibility(View.VISIBLE);
|
itemDurationView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
StreamStateEntity state = historyRecordManager
|
final StreamStateEntity state = historyRecordManager
|
||||||
.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{
|
.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{
|
||||||
add(localItem);
|
add(localItem);
|
||||||
}}).blockingGet().get(0);
|
}}).blockingGet().get(0);
|
||||||
|
@ -116,7 +116,7 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
|
||||||
}
|
}
|
||||||
final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem;
|
final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem;
|
||||||
|
|
||||||
StreamStateEntity state = historyRecordManager
|
final StreamStateEntity state = historyRecordManager
|
||||||
.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{
|
.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{
|
||||||
add(localItem);
|
add(localItem);
|
||||||
}}).blockingGet().get(0);
|
}}).blockingGet().get(0);
|
||||||
|
|
|
@ -98,7 +98,7 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
|
||||||
R.color.duration_background_color));
|
R.color.duration_background_color));
|
||||||
itemDurationView.setVisibility(View.VISIBLE);
|
itemDurationView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
StreamStateEntity state = historyRecordManager
|
final StreamStateEntity state = historyRecordManager
|
||||||
.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{
|
.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{
|
||||||
add(localItem);
|
add(localItem);
|
||||||
}}).blockingGet().get(0);
|
}}).blockingGet().get(0);
|
||||||
|
@ -146,7 +146,7 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
|
||||||
}
|
}
|
||||||
final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem;
|
final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem;
|
||||||
|
|
||||||
StreamStateEntity state = historyRecordManager
|
final StreamStateEntity state = historyRecordManager
|
||||||
.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{
|
.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{
|
||||||
add(localItem);
|
add(localItem);
|
||||||
}}).blockingGet().get(0);
|
}}).blockingGet().get(0);
|
||||||
|
|
|
@ -98,7 +98,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
||||||
private boolean isRemovingWatched = false;
|
private boolean isRemovingWatched = false;
|
||||||
|
|
||||||
public static LocalPlaylistFragment getInstance(final long playlistId, final String name) {
|
public static LocalPlaylistFragment getInstance(final long playlistId, final String name) {
|
||||||
LocalPlaylistFragment instance = new LocalPlaylistFragment();
|
final LocalPlaylistFragment instance = new LocalPlaylistFragment();
|
||||||
instance.setInitialData(playlistId, name);
|
instance.setInitialData(playlistId, name);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
@ -411,7 +411,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
||||||
if (removePartiallyWatched) {
|
if (removePartiallyWatched) {
|
||||||
while (playlistIter.hasNext()) {
|
while (playlistIter.hasNext()) {
|
||||||
final PlaylistStreamEntry playlistItem = playlistIter.next();
|
final PlaylistStreamEntry playlistItem = playlistIter.next();
|
||||||
int indexInHistory = Collections.binarySearch(historyStreamIds,
|
final int indexInHistory = Collections.binarySearch(historyStreamIds,
|
||||||
playlistItem.getStreamId());
|
playlistItem.getStreamId());
|
||||||
|
|
||||||
if (indexInHistory < 0) {
|
if (indexInHistory < 0) {
|
||||||
|
@ -427,7 +427,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
||||||
.loadLocalStreamStateBatch(playlist).blockingGet().iterator();
|
.loadLocalStreamStateBatch(playlist).blockingGet().iterator();
|
||||||
|
|
||||||
while (playlistIter.hasNext()) {
|
while (playlistIter.hasNext()) {
|
||||||
PlaylistStreamEntry playlistItem = playlistIter.next();
|
final PlaylistStreamEntry playlistItem = playlistIter.next();
|
||||||
final int indexInHistory = Collections.binarySearch(historyStreamIds,
|
final int indexInHistory = Collections.binarySearch(historyStreamIds,
|
||||||
playlistItem.getStreamId());
|
playlistItem.getStreamId());
|
||||||
|
|
||||||
|
@ -544,7 +544,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
||||||
}
|
}
|
||||||
|
|
||||||
final View dialogView = View.inflate(getContext(), R.layout.dialog_playlist_name, null);
|
final View dialogView = View.inflate(getContext(), R.layout.dialog_playlist_name, null);
|
||||||
EditText nameEdit = dialogView.findViewById(R.id.playlist_name);
|
final EditText nameEdit = dialogView.findViewById(R.id.playlist_name);
|
||||||
nameEdit.setText(name);
|
nameEdit.setText(name);
|
||||||
nameEdit.setSelection(nameEdit.getText().length());
|
nameEdit.setSelection(nameEdit.getText().length());
|
||||||
|
|
||||||
|
@ -601,7 +601,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateThumbnailUrl() {
|
private void updateThumbnailUrl() {
|
||||||
String newThumbnailUrl;
|
final String newThumbnailUrl;
|
||||||
|
|
||||||
if (!itemListAdapter.getItemsList().isEmpty()) {
|
if (!itemListAdapter.getItemsList().isEmpty()) {
|
||||||
newThumbnailUrl = ((PlaylistStreamEntry) itemListAdapter.getItemsList().get(0))
|
newThumbnailUrl = ((PlaylistStreamEntry) itemListAdapter.getItemsList().get(0))
|
||||||
|
@ -662,7 +662,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<LocalItem> items = itemListAdapter.getItemsList();
|
final List<LocalItem> items = itemListAdapter.getItemsList();
|
||||||
List<Long> streamIds = new ArrayList<>(items.size());
|
final List<Long> streamIds = new ArrayList<>(items.size());
|
||||||
for (final LocalItem item : items) {
|
for (final LocalItem item : items) {
|
||||||
if (item instanceof PlaylistStreamEntry) {
|
if (item instanceof PlaylistStreamEntry) {
|
||||||
streamIds.add(((PlaylistStreamEntry) item).getStreamId());
|
streamIds.add(((PlaylistStreamEntry) item).getStreamId());
|
||||||
|
@ -815,7 +815,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<LocalItem> infoItems = itemListAdapter.getItemsList();
|
final List<LocalItem> infoItems = itemListAdapter.getItemsList();
|
||||||
List<StreamInfoItem> streamInfoItems = new ArrayList<>(infoItems.size());
|
final List<StreamInfoItem> streamInfoItems = new ArrayList<>(infoItems.size());
|
||||||
for (final LocalItem item : infoItems) {
|
for (final LocalItem item : infoItems) {
|
||||||
if (item instanceof PlaylistStreamEntry) {
|
if (item instanceof PlaylistStreamEntry) {
|
||||||
streamInfoItems.add(((PlaylistStreamEntry) item).toStreamInfoItem());
|
streamInfoItems.add(((PlaylistStreamEntry) item).toStreamInfoItem());
|
||||||
|
|
|
@ -61,7 +61,7 @@ public class LocalPlaylistManager {
|
||||||
final List<StreamEntity> streams,
|
final List<StreamEntity> streams,
|
||||||
final int indexOffset) {
|
final int indexOffset) {
|
||||||
|
|
||||||
List<PlaylistStreamEntity> joinEntities = new ArrayList<>(streams.size());
|
final List<PlaylistStreamEntity> joinEntities = new ArrayList<>(streams.size());
|
||||||
final List<Long> streamIds = streamTable.upsertAll(streams);
|
final List<Long> streamIds = streamTable.upsertAll(streams);
|
||||||
for (int index = 0; index < streamIds.size(); index++) {
|
for (int index = 0; index < streamIds.size(); index++) {
|
||||||
joinEntities.add(new PlaylistStreamEntity(playlistId, streamIds.get(index),
|
joinEntities.add(new PlaylistStreamEntity(playlistId, streamIds.get(index),
|
||||||
|
@ -71,7 +71,7 @@ public class LocalPlaylistManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Completable updateJoin(final long playlistId, final List<Long> streamIds) {
|
public Completable updateJoin(final long playlistId, final List<Long> streamIds) {
|
||||||
List<PlaylistStreamEntity> joinEntities = new ArrayList<>(streamIds.size());
|
final List<PlaylistStreamEntity> joinEntities = new ArrayList<>(streamIds.size());
|
||||||
for (int i = 0; i < streamIds.size(); i++) {
|
for (int i = 0; i < streamIds.size(); i++) {
|
||||||
joinEntities.add(new PlaylistStreamEntity(playlistId, streamIds.get(i), i));
|
joinEntities.add(new PlaylistStreamEntity(playlistId, streamIds.get(i), i));
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ public class LocalPlaylistManager {
|
||||||
.firstElement()
|
.firstElement()
|
||||||
.filter(playlistEntities -> !playlistEntities.isEmpty())
|
.filter(playlistEntities -> !playlistEntities.isEmpty())
|
||||||
.map(playlistEntities -> {
|
.map(playlistEntities -> {
|
||||||
PlaylistEntity playlist = playlistEntities.get(0);
|
final PlaylistEntity playlist = playlistEntities.get(0);
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
playlist.setName(name);
|
playlist.setName(name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class RemotePlaylistManager {
|
||||||
|
|
||||||
public Single<Integer> onUpdate(final long playlistId, final PlaylistInfo playlistInfo) {
|
public Single<Integer> onUpdate(final long playlistId, final PlaylistInfo playlistInfo) {
|
||||||
return Single.fromCallable(() -> {
|
return Single.fromCallable(() -> {
|
||||||
PlaylistRemoteEntity playlist = new PlaylistRemoteEntity(playlistInfo);
|
final PlaylistRemoteEntity playlist = new PlaylistRemoteEntity(playlistInfo);
|
||||||
playlist.setUid(playlistId);
|
playlist.setUid(playlistId);
|
||||||
return playlistRemoteTable.update(playlist);
|
return playlistRemoteTable.update(playlist);
|
||||||
}).subscribeOn(Schedulers.io());
|
}).subscribeOn(Schedulers.io());
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class SubscriptionsImportFragment extends BaseFragment {
|
||||||
private Button inputButton;
|
private Button inputButton;
|
||||||
|
|
||||||
public static SubscriptionsImportFragment getInstance(final int serviceId) {
|
public static SubscriptionsImportFragment getInstance(final int serviceId) {
|
||||||
SubscriptionsImportFragment instance = new SubscriptionsImportFragment();
|
final SubscriptionsImportFragment instance = new SubscriptionsImportFragment();
|
||||||
instance.setInitialData(serviceId);
|
instance.setInitialData(serviceId);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ public class SubscriptionsImportFragment extends BaseFragment {
|
||||||
setInfoText("");
|
setInfoText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionBar supportActionBar = activity.getSupportActionBar();
|
final ActionBar supportActionBar = activity.getSupportActionBar();
|
||||||
if (supportActionBar != null) {
|
if (supportActionBar != null) {
|
||||||
supportActionBar.setDisplayShowTitleEnabled(true);
|
supportActionBar.setDisplayShowTitleEnabled(true);
|
||||||
setTitle(getString(R.string.import_title));
|
setTitle(getString(R.string.import_title));
|
||||||
|
@ -206,7 +206,7 @@ public class SubscriptionsImportFragment extends BaseFragment {
|
||||||
relatedUrl = extractor.getRelatedUrl();
|
relatedUrl = extractor.getRelatedUrl();
|
||||||
instructionsString = ServiceHelper.getImportInstructions(currentServiceId);
|
instructionsString = ServiceHelper.getImportInstructions(currentServiceId);
|
||||||
return;
|
return;
|
||||||
} catch (ExtractionException ignored) {
|
} catch (final ExtractionException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,12 +86,12 @@ public final class ImportExportJsonHelper {
|
||||||
eventListener.onSizeReceived(channelsArray.size());
|
eventListener.onSizeReceived(channelsArray.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Object o : channelsArray) {
|
for (final Object o : channelsArray) {
|
||||||
if (o instanceof JsonObject) {
|
if (o instanceof JsonObject) {
|
||||||
JsonObject itemObject = (JsonObject) o;
|
final JsonObject itemObject = (JsonObject) o;
|
||||||
int serviceId = itemObject.getInt(JSON_SERVICE_ID_KEY, 0);
|
final int serviceId = itemObject.getInt(JSON_SERVICE_ID_KEY, 0);
|
||||||
String url = itemObject.getString(JSON_URL_KEY);
|
final String url = itemObject.getString(JSON_URL_KEY);
|
||||||
String name = itemObject.getString(JSON_NAME_KEY);
|
final String name = itemObject.getString(JSON_NAME_KEY);
|
||||||
|
|
||||||
if (url != null && name != null && !url.isEmpty() && !name.isEmpty()) {
|
if (url != null && name != null && !url.isEmpty() && !name.isEmpty()) {
|
||||||
channels.add(new SubscriptionItem(serviceId, url, name));
|
channels.add(new SubscriptionItem(serviceId, url, name));
|
||||||
|
@ -101,7 +101,7 @@ public final class ImportExportJsonHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (final Throwable e) {
|
||||||
throw new InvalidSourceException("Couldn't parse json", e);
|
throw new InvalidSourceException("Couldn't parse json", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ public final class ImportExportJsonHelper {
|
||||||
*/
|
*/
|
||||||
public static void writeTo(final List<SubscriptionItem> items, final OutputStream out,
|
public static void writeTo(final List<SubscriptionItem> items, final OutputStream out,
|
||||||
@Nullable final ImportExportEventListener eventListener) {
|
@Nullable final ImportExportEventListener eventListener) {
|
||||||
JsonAppendableWriter writer = JsonWriter.on(out);
|
final JsonAppendableWriter writer = JsonWriter.on(out);
|
||||||
writeTo(items, writer, eventListener);
|
writeTo(items, writer, eventListener);
|
||||||
writer.done();
|
writer.done();
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ public final class ImportExportJsonHelper {
|
||||||
writer.value(JSON_APP_VERSION_INT_KEY, BuildConfig.VERSION_CODE);
|
writer.value(JSON_APP_VERSION_INT_KEY, BuildConfig.VERSION_CODE);
|
||||||
|
|
||||||
writer.array(JSON_SUBSCRIPTIONS_ARRAY_KEY);
|
writer.array(JSON_SUBSCRIPTIONS_ARRAY_KEY);
|
||||||
for (SubscriptionItem item : items) {
|
for (final SubscriptionItem item : items) {
|
||||||
writer.object();
|
writer.object();
|
||||||
writer.value(JSON_SERVICE_ID_KEY, item.getServiceId());
|
writer.value(JSON_SERVICE_ID_KEY, item.getServiceId());
|
||||||
writer.value(JSON_URL_KEY, item.getUrl());
|
writer.value(JSON_URL_KEY, item.getUrl());
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class SubscriptionsExportService extends BaseImportExportService {
|
||||||
try {
|
try {
|
||||||
outFile = new File(path);
|
outFile = new File(path);
|
||||||
outputStream = new FileOutputStream(outFile);
|
outputStream = new FileOutputStream(outFile);
|
||||||
} catch (FileNotFoundException e) {
|
} catch (final FileNotFoundException e) {
|
||||||
handleError(e);
|
handleError(e);
|
||||||
return START_NOT_STICKY;
|
return START_NOT_STICKY;
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ public class SubscriptionsExportService extends BaseImportExportService {
|
||||||
.map(subscriptionEntities -> {
|
.map(subscriptionEntities -> {
|
||||||
final List<SubscriptionItem> result
|
final List<SubscriptionItem> result
|
||||||
= new ArrayList<>(subscriptionEntities.size());
|
= new ArrayList<>(subscriptionEntities.size());
|
||||||
for (SubscriptionEntity entity : subscriptionEntities) {
|
for (final SubscriptionEntity entity : subscriptionEntities) {
|
||||||
result.add(new SubscriptionItem(entity.getServiceId(), entity.getUrl(),
|
result.add(new SubscriptionItem(entity.getServiceId(), entity.getUrl(),
|
||||||
entity.getName()));
|
entity.getName()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ public class SubscriptionsImportService extends BaseImportExportService {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
inputStream = new FileInputStream(new File(filePath));
|
inputStream = new FileInputStream(new File(filePath));
|
||||||
} catch (FileNotFoundException e) {
|
} catch (final FileNotFoundException e) {
|
||||||
handleError(e);
|
handleError(e);
|
||||||
return START_NOT_STICKY;
|
return START_NOT_STICKY;
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ public class SubscriptionsImportService extends BaseImportExportService {
|
||||||
.getChannelInfo(subscriptionItem.getServiceId(),
|
.getChannelInfo(subscriptionItem.getServiceId(),
|
||||||
subscriptionItem.getUrl(), true)
|
subscriptionItem.getUrl(), true)
|
||||||
.blockingGet());
|
.blockingGet());
|
||||||
} catch (Throwable e) {
|
} catch (final Throwable e) {
|
||||||
return Notification.createOnError(e);
|
return Notification.createOnError(e);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -239,7 +239,7 @@ public class SubscriptionsImportService extends BaseImportExportService {
|
||||||
private Consumer<Notification<ChannelInfo>> getNotificationsConsumer() {
|
private Consumer<Notification<ChannelInfo>> getNotificationsConsumer() {
|
||||||
return notification -> {
|
return notification -> {
|
||||||
if (notification.isOnNext()) {
|
if (notification.isOnNext()) {
|
||||||
String name = notification.getValue().getName();
|
final String name = notification.getValue().getName();
|
||||||
eventListener.onItemCompleted(!TextUtils.isEmpty(name) ? name : "");
|
eventListener.onItemCompleted(!TextUtils.isEmpty(name) ? name : "");
|
||||||
} else if (notification.isOnError()) {
|
} else if (notification.isOnError()) {
|
||||||
final Throwable error = notification.getError();
|
final Throwable error = notification.getError();
|
||||||
|
@ -260,7 +260,7 @@ public class SubscriptionsImportService extends BaseImportExportService {
|
||||||
private Function<List<Notification<ChannelInfo>>, List<SubscriptionEntity>> upsertBatch() {
|
private Function<List<Notification<ChannelInfo>>, List<SubscriptionEntity>> upsertBatch() {
|
||||||
return notificationList -> {
|
return notificationList -> {
|
||||||
final List<ChannelInfo> infoList = new ArrayList<>(notificationList.size());
|
final List<ChannelInfo> infoList = new ArrayList<>(notificationList.size());
|
||||||
for (Notification<ChannelInfo> n : notificationList) {
|
for (final Notification<ChannelInfo> n : notificationList) {
|
||||||
if (n.isOnNext()) {
|
if (n.isOnNext()) {
|
||||||
infoList.add(n.getValue());
|
infoList.add(n.getValue());
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,6 @@ 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 io.reactivex.android.schedulers.AndroidSchedulers;
|
|
||||||
import org.schabi.newpipe.BuildConfig;
|
import org.schabi.newpipe.BuildConfig;
|
||||||
import org.schabi.newpipe.DownloaderImpl;
|
import org.schabi.newpipe.DownloaderImpl;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
@ -79,6 +78,7 @@ import org.schabi.newpipe.util.SerializedCache;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.CompositeDisposable;
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.disposables.SerialDisposable;
|
import io.reactivex.disposables.SerialDisposable;
|
||||||
|
@ -280,7 +280,7 @@ public abstract class BasePlayer implements
|
||||||
|
|
||||||
// Resolve append intents
|
// Resolve append intents
|
||||||
if (intent.getBooleanExtra(APPEND_ONLY, false) && playQueue != null) {
|
if (intent.getBooleanExtra(APPEND_ONLY, false) && playQueue != null) {
|
||||||
int sizeBeforeAppend = playQueue.size();
|
final int sizeBeforeAppend = playQueue.size();
|
||||||
playQueue.append(queue.getStreams());
|
playQueue.append(queue.getStreams());
|
||||||
|
|
||||||
if ((intent.getBooleanExtra(SELECT_ON_APPEND, false)
|
if ((intent.getBooleanExtra(SELECT_ON_APPEND, false)
|
||||||
|
@ -1452,7 +1452,7 @@ public abstract class BasePlayer implements
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timeline.Window timelineWindow = new Timeline.Window();
|
final Timeline.Window timelineWindow = new Timeline.Window();
|
||||||
currentTimeline.getWindow(currentWindowIndex, timelineWindow);
|
currentTimeline.getWindow(currentWindowIndex, timelineWindow);
|
||||||
return timelineWindow.getDefaultPositionMs() <= simpleExoPlayer.getCurrentPosition();
|
return timelineWindow.getDefaultPositionMs() <= simpleExoPlayer.getCurrentPosition();
|
||||||
}
|
}
|
||||||
|
@ -1463,7 +1463,7 @@ public abstract class BasePlayer implements
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return simpleExoPlayer.isCurrentWindowDynamic();
|
return simpleExoPlayer.isCurrentWindowDynamic();
|
||||||
} catch (@NonNull IndexOutOfBoundsException e) {
|
} catch (@NonNull final IndexOutOfBoundsException e) {
|
||||||
// Why would this even happen =(
|
// Why would this even happen =(
|
||||||
// But lets log it anyway. Save is save
|
// But lets log it anyway. Save is save
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
|
|
@ -580,7 +580,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void shareUrl(final String subject, final String url) {
|
private void shareUrl(final String subject, final String url) {
|
||||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
final Intent intent = new Intent(Intent.ACTION_SEND);
|
||||||
intent.setType("text/plain");
|
intent.setType("text/plain");
|
||||||
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, url);
|
intent.putExtra(Intent.EXTRA_TEXT, url);
|
||||||
|
@ -734,7 +734,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||||
|
|
||||||
private void onMaybeMuteChanged() {
|
private void onMaybeMuteChanged() {
|
||||||
if (menu != null && player != null) {
|
if (menu != null && player != null) {
|
||||||
MenuItem item = menu.findItem(R.id.action_mute);
|
final MenuItem item = menu.findItem(R.id.action_mute);
|
||||||
|
|
||||||
//Change the mute-button item in ActionBar
|
//Change the mute-button item in ActionBar
|
||||||
//1) Text change:
|
//1) Text change:
|
||||||
|
|
|
@ -167,7 +167,7 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
|
|
||||||
// workaround to match normalized captions like english to English or deutsch to Deutsch
|
// workaround to match normalized captions like english to English or deutsch to Deutsch
|
||||||
private static boolean containsCaseInsensitive(final List<String> list, final String toFind) {
|
private static boolean containsCaseInsensitive(final List<String> list, final String toFind) {
|
||||||
for (String i : list) {
|
for (final String i : list) {
|
||||||
if (i.equalsIgnoreCase(toFind)) {
|
if (i.equalsIgnoreCase(toFind)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -279,7 +279,7 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
|
|
||||||
qualityPopupMenu.getMenu().removeGroup(qualityPopupMenuGroupId);
|
qualityPopupMenu.getMenu().removeGroup(qualityPopupMenuGroupId);
|
||||||
for (int i = 0; i < availableStreams.size(); i++) {
|
for (int i = 0; i < availableStreams.size(); i++) {
|
||||||
VideoStream videoStream = availableStreams.get(i);
|
final VideoStream videoStream = availableStreams.get(i);
|
||||||
qualityPopupMenu.getMenu().add(qualityPopupMenuGroupId, i, Menu.NONE, MediaFormat
|
qualityPopupMenu.getMenu().add(qualityPopupMenuGroupId, i, Menu.NONE, MediaFormat
|
||||||
.getNameById(videoStream.getFormatId()) + " " + videoStream.resolution);
|
.getNameById(videoStream.getFormatId()) + " " + videoStream.resolution);
|
||||||
}
|
}
|
||||||
|
@ -311,7 +311,7 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
}
|
}
|
||||||
captionPopupMenu.getMenu().removeGroup(captionPopupMenuGroupId);
|
captionPopupMenu.getMenu().removeGroup(captionPopupMenuGroupId);
|
||||||
|
|
||||||
String userPreferredLanguage = PreferenceManager.getDefaultSharedPreferences(context)
|
final String userPreferredLanguage = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
.getString(context.getString(R.string.caption_user_set_key), null);
|
.getString(context.getString(R.string.caption_user_set_key), null);
|
||||||
/*
|
/*
|
||||||
* only search for autogenerated cc as fallback
|
* only search for autogenerated cc as fallback
|
||||||
|
@ -323,7 +323,7 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
&& !userPreferredLanguage.contains("(");
|
&& !userPreferredLanguage.contains("(");
|
||||||
|
|
||||||
// Add option for turning off caption
|
// Add option for turning off caption
|
||||||
MenuItem captionOffItem = captionPopupMenu.getMenu().add(captionPopupMenuGroupId,
|
final MenuItem captionOffItem = captionPopupMenu.getMenu().add(captionPopupMenuGroupId,
|
||||||
0, Menu.NONE, R.string.caption_none);
|
0, Menu.NONE, R.string.caption_none);
|
||||||
captionOffItem.setOnMenuItemClickListener(menuItem -> {
|
captionOffItem.setOnMenuItemClickListener(menuItem -> {
|
||||||
final int textRendererIndex = getRendererIndex(C.TRACK_TYPE_TEXT);
|
final int textRendererIndex = getRendererIndex(C.TRACK_TYPE_TEXT);
|
||||||
|
@ -339,7 +339,7 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
// Add all available captions
|
// Add all available captions
|
||||||
for (int i = 0; i < availableLanguages.size(); i++) {
|
for (int i = 0; i < availableLanguages.size(); i++) {
|
||||||
final String captionLanguage = availableLanguages.get(i);
|
final String captionLanguage = availableLanguages.get(i);
|
||||||
MenuItem captionItem = captionPopupMenu.getMenu().add(captionPopupMenuGroupId,
|
final MenuItem captionItem = captionPopupMenu.getMenu().add(captionPopupMenuGroupId,
|
||||||
i + 1, Menu.NONE, captionLanguage);
|
i + 1, Menu.NONE, captionLanguage);
|
||||||
captionItem.setOnMenuItemClickListener(menuItem -> {
|
captionItem.setOnMenuItemClickListener(menuItem -> {
|
||||||
final int textRendererIndex = getRendererIndex(C.TRACK_TYPE_TEXT);
|
final int textRendererIndex = getRendererIndex(C.TRACK_TYPE_TEXT);
|
||||||
|
@ -579,7 +579,7 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
.getTrackGroups(textRenderer);
|
.getTrackGroups(textRenderer);
|
||||||
|
|
||||||
// Extract all loaded languages
|
// Extract all loaded languages
|
||||||
List<String> availableLanguages = new ArrayList<>(textTracks.length);
|
final List<String> availableLanguages = new ArrayList<>(textTracks.length);
|
||||||
for (int i = 0; i < textTracks.length; i++) {
|
for (int i = 0; i < textTracks.length; i++) {
|
||||||
final TrackGroup textTrack = textTracks.get(i);
|
final TrackGroup textTrack = textTracks.get(i);
|
||||||
if (textTrack.length > 0 && textTrack.getFormat(0) != null) {
|
if (textTrack.length > 0 && textTrack.getFormat(0) != null) {
|
||||||
|
@ -729,8 +729,8 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
qualityTextView.setText(menuItem.getTitle());
|
qualityTextView.setText(menuItem.getTitle());
|
||||||
return true;
|
return true;
|
||||||
} else if (playbackSpeedPopupMenuGroupId == menuItem.getGroupId()) {
|
} else if (playbackSpeedPopupMenuGroupId == menuItem.getGroupId()) {
|
||||||
int speedIndex = menuItem.getItemId();
|
final int speedIndex = menuItem.getItemId();
|
||||||
float speed = PLAYBACK_SPEEDS[speedIndex];
|
final float speed = PLAYBACK_SPEEDS[speedIndex];
|
||||||
|
|
||||||
setPlaybackSpeed(speed);
|
setPlaybackSpeed(speed);
|
||||||
playbackSpeedTextView.setText(formatSpeed(speed));
|
playbackSpeedTextView.setText(formatSpeed(speed));
|
||||||
|
@ -921,10 +921,10 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float scaleFrom = goneOnEnd ? 1f : 1f;
|
final float scaleFrom = goneOnEnd ? 1f : 1f;
|
||||||
float scaleTo = goneOnEnd ? 1.8f : 1.4f;
|
final float scaleTo = goneOnEnd ? 1.8f : 1.4f;
|
||||||
float alphaFrom = goneOnEnd ? 1f : 0f;
|
final float alphaFrom = goneOnEnd ? 1f : 0f;
|
||||||
float alphaTo = goneOnEnd ? 0f : 1f;
|
final float alphaTo = goneOnEnd ? 0f : 1f;
|
||||||
|
|
||||||
|
|
||||||
controlViewAnimator = ObjectAnimator.ofPropertyValuesHolder(controlAnimationView,
|
controlViewAnimator = ObjectAnimator.ofPropertyValuesHolder(controlAnimationView,
|
||||||
|
|
|
@ -320,7 +320,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
final float captionScale,
|
final float captionScale,
|
||||||
@NonNull final CaptionStyleCompat captionStyle) {
|
@NonNull final CaptionStyleCompat captionStyle) {
|
||||||
if (popupPlayerSelected()) {
|
if (popupPlayerSelected()) {
|
||||||
float captionRatio = (captionScale - 1.0f) / 5.0f + 1.0f;
|
final float captionRatio = (captionScale - 1.0f) / 5.0f + 1.0f;
|
||||||
view.setFractionalTextSize(SubtitleView.DEFAULT_TEXT_SIZE_FRACTION * captionRatio);
|
view.setFractionalTextSize(SubtitleView.DEFAULT_TEXT_SIZE_FRACTION * captionRatio);
|
||||||
view.setApplyEmbeddedStyles(captionStyle.equals(CaptionStyleCompat.DEFAULT));
|
view.setApplyEmbeddedStyles(captionStyle.equals(CaptionStyleCompat.DEFAULT));
|
||||||
view.setStyle(captionStyle);
|
view.setStyle(captionStyle);
|
||||||
|
@ -717,7 +717,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
if (popupPlayerSelected()) {
|
if (popupPlayerSelected()) {
|
||||||
setRecovery();
|
setRecovery();
|
||||||
service.removeViewFromParent();
|
service.removeViewFromParent();
|
||||||
Intent intent = NavigationHelper.getPlayerIntent(
|
final Intent intent = NavigationHelper.getPlayerIntent(
|
||||||
service,
|
service,
|
||||||
MainActivity.class,
|
MainActivity.class,
|
||||||
this.getPlayQueue(),
|
this.getPlayQueue(),
|
||||||
|
@ -894,7 +894,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
onPause();
|
onPause();
|
||||||
try {
|
try {
|
||||||
NavigationHelper.playWithKore(getParentActivity(), Uri.parse(getVideoUrl()));
|
NavigationHelper.playWithKore(getParentActivity(), Uri.parse(getVideoUrl()));
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.i(TAG, "Failed to start kore", e);
|
Log.i(TAG, "Failed to start kore", e);
|
||||||
}
|
}
|
||||||
|
@ -979,9 +979,9 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
if (l != ol || t != ot || r != or || b != ob) {
|
if (l != ol || t != ot || r != or || b != ob) {
|
||||||
// Use smaller value to be consistent between screen orientations
|
// Use smaller value to be consistent between screen orientations
|
||||||
// (and to make usage easier)
|
// (and to make usage easier)
|
||||||
int width = r - l;
|
final int width = r - l;
|
||||||
int height = b - t;
|
final int height = b - t;
|
||||||
int min = Math.min(width, height);
|
final int min = Math.min(width, height);
|
||||||
maxGestureLength = (int) (min * MAX_GESTURE_LENGTH);
|
maxGestureLength = (int) (min * MAX_GESTURE_LENGTH);
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -995,7 +995,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
queueLayout.getLayoutParams().height = height - queueLayout.getTop();
|
queueLayout.getLayoutParams().height = height - queueLayout.getTop();
|
||||||
|
|
||||||
if (popupPlayerSelected()) {
|
if (popupPlayerSelected()) {
|
||||||
float widthDp = Math.abs(r - l) / service.getResources()
|
final float widthDp = Math.abs(r - l) / service.getResources()
|
||||||
.getDisplayMetrics().density;
|
.getDisplayMetrics().density;
|
||||||
final int visibility = widthDp > MINIMUM_SHOW_EXTRA_WIDTH_DP
|
final int visibility = widthDp > MINIMUM_SHOW_EXTRA_WIDTH_DP
|
||||||
? View.VISIBLE
|
? View.VISIBLE
|
||||||
|
|
|
@ -227,8 +227,8 @@ public class PlayerGestureListener
|
||||||
|
|
||||||
isMovingInMain = true;
|
isMovingInMain = true;
|
||||||
|
|
||||||
boolean acceptAnyArea = isVolumeGestureEnabled != isBrightnessGestureEnabled;
|
final boolean acceptAnyArea = isVolumeGestureEnabled != isBrightnessGestureEnabled;
|
||||||
boolean acceptVolumeArea = acceptAnyArea
|
final boolean acceptVolumeArea = acceptAnyArea
|
||||||
|| initialEvent.getX() > playerImpl.getRootView().getWidth() / 2.0;
|
|| initialEvent.getX() > playerImpl.getRootView().getWidth() / 2.0;
|
||||||
|
|
||||||
if (isVolumeGestureEnabled && acceptVolumeArea) {
|
if (isVolumeGestureEnabled && acceptVolumeArea) {
|
||||||
|
@ -563,13 +563,13 @@ public class PlayerGestureListener
|
||||||
private boolean handleMultiDrag(final MotionEvent event) {
|
private boolean handleMultiDrag(final MotionEvent event) {
|
||||||
if (initPointerDistance != -1 && event.getPointerCount() == 2) {
|
if (initPointerDistance != -1 && event.getPointerCount() == 2) {
|
||||||
// get the movements of the fingers
|
// get the movements of the fingers
|
||||||
double firstPointerMove = Math.hypot(event.getX(0) - initFirstPointerX,
|
final double firstPointerMove = Math.hypot(event.getX(0) - initFirstPointerX,
|
||||||
event.getY(0) - initFirstPointerY);
|
event.getY(0) - initFirstPointerY);
|
||||||
double secPointerMove = Math.hypot(event.getX(1) - initSecPointerX,
|
final double secPointerMove = Math.hypot(event.getX(1) - initSecPointerX,
|
||||||
event.getY(1) - initSecPointerY);
|
event.getY(1) - initSecPointerY);
|
||||||
|
|
||||||
// minimum threshold beyond which pinch gesture will work
|
// minimum threshold beyond which pinch gesture will work
|
||||||
int minimumMove = ViewConfiguration.get(service).getScaledTouchSlop();
|
final int minimumMove = ViewConfiguration.get(service).getScaledTouchSlop();
|
||||||
|
|
||||||
if (Math.max(firstPointerMove, secPointerMove) > minimumMove) {
|
if (Math.max(firstPointerMove, secPointerMove) > minimumMove) {
|
||||||
// calculate current distance between the pointers
|
// calculate current distance between the pointers
|
||||||
|
@ -577,9 +577,9 @@ public class PlayerGestureListener
|
||||||
Math.hypot(event.getX(0) - event.getX(1),
|
Math.hypot(event.getX(0) - event.getX(1),
|
||||||
event.getY(0) - event.getY(1));
|
event.getY(0) - event.getY(1));
|
||||||
|
|
||||||
double popupWidth = playerImpl.getPopupWidth();
|
final double popupWidth = playerImpl.getPopupWidth();
|
||||||
// change co-ordinates of popup so the center stays at the same position
|
// change co-ordinates of popup so the center stays at the same position
|
||||||
double newWidth = (popupWidth * currentPointerDistance / initPointerDistance);
|
final double newWidth = (popupWidth * currentPointerDistance / initPointerDistance);
|
||||||
initPointerDistance = currentPointerDistance;
|
initPointerDistance = currentPointerDistance;
|
||||||
playerImpl.getPopupLayoutParams().x += (popupWidth - newWidth) / 2;
|
playerImpl.getPopupLayoutParams().x += (popupWidth - newWidth) / 2;
|
||||||
|
|
||||||
|
@ -601,7 +601,7 @@ public class PlayerGestureListener
|
||||||
* */
|
* */
|
||||||
|
|
||||||
private int getNavigationBarHeight(final Context context) {
|
private int getNavigationBarHeight(final Context context) {
|
||||||
int resId = context.getResources()
|
final int resId = context.getResources()
|
||||||
.getIdentifier("navigation_bar_height", "dimen", "android");
|
.getIdentifier("navigation_bar_height", "dimen", "android");
|
||||||
if (resId > 0) {
|
if (resId > 0) {
|
||||||
return context.getResources().getDimensionPixelSize(resId);
|
return context.getResources().getDimensionPixelSize(resId);
|
||||||
|
@ -610,7 +610,7 @@ public class PlayerGestureListener
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getStatusBarHeight(final Context context) {
|
private int getStatusBarHeight(final Context context) {
|
||||||
int resId = context.getResources()
|
final int resId = context.getResources()
|
||||||
.getIdentifier("status_bar_height", "dimen", "android");
|
.getIdentifier("status_bar_height", "dimen", "android");
|
||||||
if (resId > 0) {
|
if (resId > 0) {
|
||||||
return context.getResources().getDimensionPixelSize(resId);
|
return context.getResources().getDimensionPixelSize(resId);
|
||||||
|
|
|
@ -133,7 +133,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An
|
||||||
}
|
}
|
||||||
|
|
||||||
private void animateAudio(final float from, final float to) {
|
private void animateAudio(final float from, final float to) {
|
||||||
ValueAnimator valueAnimator = new ValueAnimator();
|
final ValueAnimator valueAnimator = new ValueAnimator();
|
||||||
valueAnimator.setFloatValues(from, to);
|
valueAnimator.setFloatValues(from, to);
|
||||||
valueAnimator.setDuration(AudioReactor.DUCK_DURATION);
|
valueAnimator.setDuration(AudioReactor.DUCK_DURATION);
|
||||||
valueAnimator.addListener(new AnimatorListenerAdapter() {
|
valueAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
|
|
|
@ -80,13 +80,13 @@ import java.io.File;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (File file : cacheDir.listFiles()) {
|
for (final File file : cacheDir.listFiles()) {
|
||||||
final String filePath = file.getAbsolutePath();
|
final String filePath = file.getAbsolutePath();
|
||||||
final boolean deleteSuccessful = file.delete();
|
final boolean deleteSuccessful = file.delete();
|
||||||
|
|
||||||
Log.d(TAG, "tryDeleteCacheFiles: " + filePath + " deleted = " + deleteSuccessful);
|
Log.d(TAG, "tryDeleteCacheFiles: " + filePath + " deleted = " + deleteSuccessful);
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
} catch (final Exception ignored) {
|
||||||
Log.e(TAG, "Failed to delete file.", ignored);
|
Log.e(TAG, "Failed to delete file.", ignored);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class LoadController implements LoadControl {
|
||||||
final int optimalPlaybackBufferMs) {
|
final int optimalPlaybackBufferMs) {
|
||||||
this.initialPlaybackBufferUs = initialPlaybackBufferMs * 1000;
|
this.initialPlaybackBufferUs = initialPlaybackBufferMs * 1000;
|
||||||
|
|
||||||
DefaultLoadControl.Builder builder = new DefaultLoadControl.Builder();
|
final DefaultLoadControl.Builder builder = new DefaultLoadControl.Builder();
|
||||||
builder.setBufferDurationsMs(minimumPlaybackbufferMs, optimalPlaybackBufferMs,
|
builder.setBufferDurationsMs(minimumPlaybackbufferMs, optimalPlaybackBufferMs,
|
||||||
initialPlaybackBufferMs, initialPlaybackBufferMs);
|
initialPlaybackBufferMs, initialPlaybackBufferMs);
|
||||||
internalLoadControl = builder.createDefaultLoadControl();
|
internalLoadControl = builder.createDefaultLoadControl();
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class MediaSessionManager {
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
MediaStyle mediaStyle = new MediaStyle()
|
final MediaStyle mediaStyle = new MediaStyle()
|
||||||
.setMediaSession(mediaSession.getSessionToken());
|
.setMediaSession(mediaSession.getSessionToken());
|
||||||
|
|
||||||
builder.setStyle(mediaStyle);
|
builder.setStyle(mediaStyle);
|
||||||
|
@ -76,7 +76,7 @@ public class MediaSessionManager {
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
MediaStyle mediaStyle = new MediaStyle()
|
final MediaStyle mediaStyle = new MediaStyle()
|
||||||
.setMediaSession(mediaSession.getSessionToken());
|
.setMediaSession(mediaSession.getSessionToken());
|
||||||
|
|
||||||
builder.setStyle(mediaStyle);
|
builder.setStyle(mediaStyle);
|
||||||
|
|
|
@ -94,7 +94,7 @@ public class PlaybackParameterDialog extends DialogFragment {
|
||||||
final double playbackPitch,
|
final double playbackPitch,
|
||||||
final boolean playbackSkipSilence,
|
final boolean playbackSkipSilence,
|
||||||
final Callback callback) {
|
final Callback callback) {
|
||||||
PlaybackParameterDialog dialog = new PlaybackParameterDialog();
|
final PlaybackParameterDialog dialog = new PlaybackParameterDialog();
|
||||||
dialog.callback = callback;
|
dialog.callback = callback;
|
||||||
dialog.initialTempo = playbackTempo;
|
dialog.initialTempo = playbackTempo;
|
||||||
dialog.initialPitch = playbackPitch;
|
dialog.initialPitch = playbackPitch;
|
||||||
|
@ -187,8 +187,8 @@ public class PlaybackParameterDialog extends DialogFragment {
|
||||||
|
|
||||||
private void setupTempoControl(@NonNull final View rootView) {
|
private void setupTempoControl(@NonNull final View rootView) {
|
||||||
tempoSlider = rootView.findViewById(R.id.tempoSeekbar);
|
tempoSlider = rootView.findViewById(R.id.tempoSeekbar);
|
||||||
TextView tempoMinimumText = rootView.findViewById(R.id.tempoMinimumText);
|
final TextView tempoMinimumText = rootView.findViewById(R.id.tempoMinimumText);
|
||||||
TextView tempoMaximumText = rootView.findViewById(R.id.tempoMaximumText);
|
final TextView tempoMaximumText = rootView.findViewById(R.id.tempoMaximumText);
|
||||||
tempoCurrentText = rootView.findViewById(R.id.tempoCurrentText);
|
tempoCurrentText = rootView.findViewById(R.id.tempoCurrentText);
|
||||||
tempoStepUpText = rootView.findViewById(R.id.tempoStepUp);
|
tempoStepUpText = rootView.findViewById(R.id.tempoStepUp);
|
||||||
tempoStepDownText = rootView.findViewById(R.id.tempoStepDown);
|
tempoStepDownText = rootView.findViewById(R.id.tempoStepDown);
|
||||||
|
@ -212,8 +212,8 @@ public class PlaybackParameterDialog extends DialogFragment {
|
||||||
|
|
||||||
private void setupPitchControl(@NonNull final View rootView) {
|
private void setupPitchControl(@NonNull final View rootView) {
|
||||||
pitchSlider = rootView.findViewById(R.id.pitchSeekbar);
|
pitchSlider = rootView.findViewById(R.id.pitchSeekbar);
|
||||||
TextView pitchMinimumText = rootView.findViewById(R.id.pitchMinimumText);
|
final TextView pitchMinimumText = rootView.findViewById(R.id.pitchMinimumText);
|
||||||
TextView pitchMaximumText = rootView.findViewById(R.id.pitchMaximumText);
|
final TextView pitchMaximumText = rootView.findViewById(R.id.pitchMaximumText);
|
||||||
pitchCurrentText = rootView.findViewById(R.id.pitchCurrentText);
|
pitchCurrentText = rootView.findViewById(R.id.pitchCurrentText);
|
||||||
pitchStepDownText = rootView.findViewById(R.id.pitchStepDown);
|
pitchStepDownText = rootView.findViewById(R.id.pitchStepDown);
|
||||||
pitchStepUpText = rootView.findViewById(R.id.pitchStepUp);
|
pitchStepUpText = rootView.findViewById(R.id.pitchStepUp);
|
||||||
|
@ -269,12 +269,12 @@ public class PlaybackParameterDialog extends DialogFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupStepSizeSelector(@NonNull final View rootView) {
|
private void setupStepSizeSelector(@NonNull final View rootView) {
|
||||||
TextView stepSizeOnePercentText = rootView.findViewById(R.id.stepSizeOnePercent);
|
final TextView stepSizeOnePercentText = rootView.findViewById(R.id.stepSizeOnePercent);
|
||||||
TextView stepSizeFivePercentText = rootView.findViewById(R.id.stepSizeFivePercent);
|
final TextView stepSizeFivePercentText = rootView.findViewById(R.id.stepSizeFivePercent);
|
||||||
TextView stepSizeTenPercentText = rootView.findViewById(R.id.stepSizeTenPercent);
|
final TextView stepSizeTenPercentText = rootView.findViewById(R.id.stepSizeTenPercent);
|
||||||
TextView stepSizeTwentyFivePercentText = rootView
|
final TextView stepSizeTwentyFivePercentText = rootView
|
||||||
.findViewById(R.id.stepSizeTwentyFivePercent);
|
.findViewById(R.id.stepSizeTwentyFivePercent);
|
||||||
TextView stepSizeOneHundredPercentText = rootView
|
final TextView stepSizeOneHundredPercentText = rootView
|
||||||
.findViewById(R.id.stepSizeOneHundredPercent);
|
.findViewById(R.id.stepSizeOneHundredPercent);
|
||||||
|
|
||||||
if (stepSizeOnePercentText != null) {
|
if (stepSizeOnePercentText != null) {
|
||||||
|
|
|
@ -76,10 +76,10 @@ public final class PlayerHelper {
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public static String getTimeString(final int milliSeconds) {
|
public static String getTimeString(final int milliSeconds) {
|
||||||
int seconds = (milliSeconds % 60000) / 1000;
|
final int seconds = (milliSeconds % 60000) / 1000;
|
||||||
int minutes = (milliSeconds % 3600000) / 60000;
|
final int minutes = (milliSeconds % 3600000) / 60000;
|
||||||
int hours = (milliSeconds % 86400000) / 3600000;
|
final int hours = (milliSeconds % 86400000) / 3600000;
|
||||||
int days = (milliSeconds % (86400000 * 7)) / 86400000;
|
final int days = (milliSeconds % (86400000 * 7)) / 86400000;
|
||||||
|
|
||||||
STRING_BUILDER.setLength(0);
|
STRING_BUILDER.setLength(0);
|
||||||
return days > 0
|
return days > 0
|
||||||
|
@ -405,7 +405,7 @@ public final class PlayerHelper {
|
||||||
|
|
||||||
private static void setScreenBrightness(@NonNull final Context context,
|
private static void setScreenBrightness(@NonNull final Context context,
|
||||||
final float screenBrightness, final long timestamp) {
|
final float screenBrightness, final long timestamp) {
|
||||||
SharedPreferences.Editor editor = getPreferences(context).edit();
|
final SharedPreferences.Editor editor = getPreferences(context).edit();
|
||||||
editor.putFloat(context.getString(R.string.screen_brightness_key), screenBrightness);
|
editor.putFloat(context.getString(R.string.screen_brightness_key), screenBrightness);
|
||||||
editor.putLong(context.getString(R.string.screen_brightness_timestamp_key), timestamp);
|
editor.putLong(context.getString(R.string.screen_brightness_timestamp_key), timestamp);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
|
@ -413,8 +413,8 @@ public final class PlayerHelper {
|
||||||
|
|
||||||
private static float getScreenBrightness(@NonNull final Context context,
|
private static float getScreenBrightness(@NonNull final Context context,
|
||||||
final float screenBrightness) {
|
final float screenBrightness) {
|
||||||
SharedPreferences sp = getPreferences(context);
|
final SharedPreferences sp = getPreferences(context);
|
||||||
long timestamp = sp
|
final long timestamp = sp
|
||||||
.getLong(context.getString(R.string.screen_brightness_timestamp_key), 0);
|
.getLong(context.getString(R.string.screen_brightness_timestamp_key), 0);
|
||||||
// Hypothesis: 4h covers a viewing block, e.g. evening.
|
// Hypothesis: 4h covers a viewing block, e.g. evening.
|
||||||
// External lightning conditions will change in the next
|
// External lightning conditions will change in the next
|
||||||
|
@ -441,7 +441,7 @@ public final class PlayerHelper {
|
||||||
|
|
||||||
private static SinglePlayQueue getAutoQueuedSinglePlayQueue(
|
private static SinglePlayQueue getAutoQueuedSinglePlayQueue(
|
||||||
final StreamInfoItem streamInfoItem) {
|
final StreamInfoItem streamInfoItem) {
|
||||||
SinglePlayQueue singlePlayQueue = new SinglePlayQueue(streamInfoItem);
|
final SinglePlayQueue singlePlayQueue = new SinglePlayQueue(streamInfoItem);
|
||||||
singlePlayQueue.getItem().setAutoQueued(true);
|
singlePlayQueue.getItem().setAutoQueued(true);
|
||||||
return singlePlayQueue;
|
return singlePlayQueue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,13 +87,13 @@ public class PlayQueueNavigator implements MediaSessionConnector.QueueNavigator
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yes this is almost a copypasta, got a problem with that? =\
|
// Yes this is almost a copypasta, got a problem with that? =\
|
||||||
int windowCount = callback.getQueueSize();
|
final int windowCount = callback.getQueueSize();
|
||||||
int currentWindowIndex = callback.getCurrentPlayingIndex();
|
final int currentWindowIndex = callback.getCurrentPlayingIndex();
|
||||||
int queueSize = Math.min(maxQueueSize, windowCount);
|
final int queueSize = Math.min(maxQueueSize, windowCount);
|
||||||
int startIndex = Util.constrainValue(currentWindowIndex - ((queueSize - 1) / 2), 0,
|
final int startIndex = Util.constrainValue(currentWindowIndex - ((queueSize - 1) / 2), 0,
|
||||||
windowCount - queueSize);
|
windowCount - queueSize);
|
||||||
|
|
||||||
List<MediaSessionCompat.QueueItem> queue = new ArrayList<>();
|
final List<MediaSessionCompat.QueueItem> queue = new ArrayList<>();
|
||||||
for (int i = startIndex; i < startIndex + queueSize; i++) {
|
for (int i = startIndex; i < startIndex + queueSize; i++) {
|
||||||
queue.add(new MediaSessionCompat.QueueItem(callback.getQueueMetadata(i), i));
|
queue.add(new MediaSessionCompat.QueueItem(callback.getQueueMetadata(i), i));
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,13 +57,14 @@ public class BasePlayerMediaSession implements MediaSessionCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
final PlayQueueItem item = player.getPlayQueue().getItem(index);
|
final PlayQueueItem item = player.getPlayQueue().getItem(index);
|
||||||
MediaDescriptionCompat.Builder descriptionBuilder = new MediaDescriptionCompat.Builder()
|
final MediaDescriptionCompat.Builder descriptionBuilder
|
||||||
|
= new MediaDescriptionCompat.Builder()
|
||||||
.setMediaId(String.valueOf(index))
|
.setMediaId(String.valueOf(index))
|
||||||
.setTitle(item.getTitle())
|
.setTitle(item.getTitle())
|
||||||
.setSubtitle(item.getUploader());
|
.setSubtitle(item.getUploader());
|
||||||
|
|
||||||
// set additional metadata for A2DP/AVRCP
|
// set additional metadata for A2DP/AVRCP
|
||||||
Bundle additionalMetadata = new Bundle();
|
final Bundle additionalMetadata = new Bundle();
|
||||||
additionalMetadata.putString(MediaMetadataCompat.METADATA_KEY_TITLE, item.getTitle());
|
additionalMetadata.putString(MediaMetadataCompat.METADATA_KEY_TITLE, item.getTitle());
|
||||||
additionalMetadata.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, item.getUploader());
|
additionalMetadata.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, item.getUploader());
|
||||||
additionalMetadata
|
additionalMetadata
|
||||||
|
|
|
@ -60,14 +60,14 @@ public class CustomTrackSelector extends DefaultTrackSelector {
|
||||||
TextTrackScore selectedTrackScore = null;
|
TextTrackScore selectedTrackScore = null;
|
||||||
|
|
||||||
for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) {
|
for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) {
|
||||||
TrackGroup trackGroup = groups.get(groupIndex);
|
final TrackGroup trackGroup = groups.get(groupIndex);
|
||||||
@Capabilities int[] trackFormatSupport = formatSupport[groupIndex];
|
@Capabilities final int[] trackFormatSupport = formatSupport[groupIndex];
|
||||||
|
|
||||||
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
||||||
if (isSupported(trackFormatSupport[trackIndex],
|
if (isSupported(trackFormatSupport[trackIndex],
|
||||||
params.exceedRendererCapabilitiesIfNecessary)) {
|
params.exceedRendererCapabilitiesIfNecessary)) {
|
||||||
Format format = trackGroup.getFormat(trackIndex);
|
final Format format = trackGroup.getFormat(trackIndex);
|
||||||
TextTrackScore trackScore = new TextTrackScore(format, params,
|
final TextTrackScore trackScore = new TextTrackScore(format, params,
|
||||||
trackFormatSupport[trackIndex], selectedAudioLanguage);
|
trackFormatSupport[trackIndex], selectedAudioLanguage);
|
||||||
|
|
||||||
if (formatHasLanguage(format, preferredTextLanguage)) {
|
if (formatHasLanguage(format, preferredTextLanguage)) {
|
||||||
|
|
|
@ -129,7 +129,7 @@ abstract class AbstractInfoPlayQueue<T extends ListInfo, U extends InfoItem> ext
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<PlayQueueItem> extractListItems(final List<StreamInfoItem> infos) {
|
private static List<PlayQueueItem> extractListItems(final List<StreamInfoItem> infos) {
|
||||||
List<PlayQueueItem> result = new ArrayList<>();
|
final List<PlayQueueItem> result = new ArrayList<>();
|
||||||
for (final InfoItem stream : infos) {
|
for (final InfoItem stream : infos) {
|
||||||
if (stream instanceof StreamInfoItem) {
|
if (stream instanceof StreamInfoItem) {
|
||||||
result.add(new PlayQueueItem((StreamInfoItem) stream));
|
result.add(new PlayQueueItem((StreamInfoItem) stream));
|
||||||
|
|
|
@ -26,7 +26,7 @@ public final class SinglePlayQueue extends PlayQueue {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<PlayQueueItem> playQueueItemsOf(final List<StreamInfoItem> items) {
|
private static List<PlayQueueItem> playQueueItemsOf(final List<StreamInfoItem> items) {
|
||||||
List<PlayQueueItem> playQueueItems = new ArrayList<>(items.size());
|
final List<PlayQueueItem> playQueueItems = new ArrayList<>(items.size());
|
||||||
for (final StreamInfoItem item : items) {
|
for (final StreamInfoItem item : items) {
|
||||||
playQueueItems.add(new PlayQueueItem(item));
|
playQueueItems.add(new PlayQueueItem(item));
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class VideoPlaybackResolver implements PlaybackResolver {
|
||||||
return liveSource;
|
return liveSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MediaSource> mediaSources = new ArrayList<>();
|
final List<MediaSource> mediaSources = new ArrayList<>();
|
||||||
|
|
||||||
// Create video stream source
|
// Create video stream source
|
||||||
final List<VideoStream> videos = ListHelper.getSortedStreamVideosList(context,
|
final List<VideoStream> videos = ListHelper.getSortedStreamVideosList(context,
|
||||||
|
|
|
@ -112,9 +112,9 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private static void startErrorActivity(final Class returnActivity, final Context context,
|
private static void startErrorActivity(final Class returnActivity, final Context context,
|
||||||
final ErrorInfo errorInfo, final List<Throwable> el) {
|
final ErrorInfo errorInfo, final List<Throwable> el) {
|
||||||
ActivityCommunicator ac = ActivityCommunicator.getCommunicator();
|
final ActivityCommunicator ac = ActivityCommunicator.getCommunicator();
|
||||||
ac.setReturnActivity(returnActivity);
|
ac.setReturnActivity(returnActivity);
|
||||||
Intent intent = new Intent(context, ErrorActivity.class);
|
final Intent intent = new Intent(context, ErrorActivity.class);
|
||||||
intent.putExtra(ERROR_INFO, errorInfo);
|
intent.putExtra(ERROR_INFO, errorInfo);
|
||||||
intent.putExtra(ERROR_LIST, elToSl(el));
|
intent.putExtra(ERROR_LIST, elToSl(el));
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
@ -154,9 +154,9 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
|
|
||||||
public static void reportError(final Context context, final CrashReportData report,
|
public static void reportError(final Context context, final CrashReportData report,
|
||||||
final ErrorInfo errorInfo) {
|
final ErrorInfo errorInfo) {
|
||||||
String[] el = new String[]{report.getString(ReportField.STACK_TRACE)};
|
final String[] el = new String[]{report.getString(ReportField.STACK_TRACE)};
|
||||||
|
|
||||||
Intent intent = new Intent(context, ErrorActivity.class);
|
final Intent intent = new Intent(context, ErrorActivity.class);
|
||||||
intent.putExtra(ERROR_INFO, errorInfo);
|
intent.putExtra(ERROR_INFO, errorInfo);
|
||||||
intent.putExtra(ERROR_LIST, el);
|
intent.putExtra(ERROR_LIST, el);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
@ -172,7 +172,7 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
|
|
||||||
// errorList to StringList
|
// errorList to StringList
|
||||||
private static String[] elToSl(final List<Throwable> stackTraces) {
|
private static String[] elToSl(final List<Throwable> stackTraces) {
|
||||||
String[] out = new String[stackTraces.size()];
|
final String[] out = new String[stackTraces.size()];
|
||||||
for (int i = 0; i < stackTraces.size(); i++) {
|
for (int i = 0; i < stackTraces.size(); i++) {
|
||||||
out[i] = getStackTrace(stackTraces.get(i));
|
out[i] = getStackTrace(stackTraces.get(i));
|
||||||
}
|
}
|
||||||
|
@ -186,12 +186,12 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
ThemeHelper.setTheme(this);
|
ThemeHelper.setTheme(this);
|
||||||
setContentView(R.layout.activity_error);
|
setContentView(R.layout.activity_error);
|
||||||
|
|
||||||
Intent intent = getIntent();
|
final Intent intent = getIntent();
|
||||||
|
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
final Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
ActionBar actionBar = getSupportActionBar();
|
final ActionBar actionBar = getSupportActionBar();
|
||||||
if (actionBar != null) {
|
if (actionBar != null) {
|
||||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
actionBar.setTitle(R.string.error_report_title);
|
actionBar.setTitle(R.string.error_report_title);
|
||||||
|
@ -203,11 +203,11 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
final Button reportGithubButton = findViewById(R.id.errorReportGitHubButton);
|
final Button reportGithubButton = findViewById(R.id.errorReportGitHubButton);
|
||||||
|
|
||||||
userCommentBox = findViewById(R.id.errorCommentBox);
|
userCommentBox = findViewById(R.id.errorCommentBox);
|
||||||
TextView errorView = findViewById(R.id.errorView);
|
final TextView errorView = findViewById(R.id.errorView);
|
||||||
TextView infoView = findViewById(R.id.errorInfosView);
|
final TextView infoView = findViewById(R.id.errorInfosView);
|
||||||
TextView errorMessageView = findViewById(R.id.errorMessageView);
|
final TextView errorMessageView = findViewById(R.id.errorMessageView);
|
||||||
|
|
||||||
ActivityCommunicator ac = ActivityCommunicator.getCommunicator();
|
final ActivityCommunicator ac = ActivityCommunicator.getCommunicator();
|
||||||
returnActivity = ac.getReturnActivity();
|
returnActivity = ac.getReturnActivity();
|
||||||
errorInfo = intent.getParcelableExtra(ERROR_INFO);
|
errorInfo = intent.getParcelableExtra(ERROR_INFO);
|
||||||
errorList = intent.getStringArrayExtra(ERROR_LIST);
|
errorList = intent.getStringArrayExtra(ERROR_LIST);
|
||||||
|
@ -242,27 +242,27 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
errorView.setText(formErrorText(errorList));
|
errorView.setText(formErrorText(errorList));
|
||||||
|
|
||||||
// print stack trace once again for debugging:
|
// print stack trace once again for debugging:
|
||||||
for (String e : errorList) {
|
for (final String e : errorList) {
|
||||||
Log.e(TAG, e);
|
Log.e(TAG, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||||
MenuInflater inflater = getMenuInflater();
|
final MenuInflater inflater = getMenuInflater();
|
||||||
inflater.inflate(R.menu.error_menu, menu);
|
inflater.inflate(R.menu.error_menu, menu);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
int id = item.getItemId();
|
final int id = item.getItemId();
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case android.R.id.home:
|
case android.R.id.home:
|
||||||
goToReturnActivity();
|
goToReturnActivity();
|
||||||
break;
|
break;
|
||||||
case R.id.menu_item_share_error:
|
case R.id.menu_item_share_error:
|
||||||
Intent intent = new Intent();
|
final Intent intent = new Intent();
|
||||||
intent.setAction(Intent.ACTION_SEND);
|
intent.setAction(Intent.ACTION_SEND);
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, buildJson());
|
intent.putExtra(Intent.EXTRA_TEXT, buildJson());
|
||||||
intent.setType("text/plain");
|
intent.setType("text/plain");
|
||||||
|
@ -304,9 +304,9 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formErrorText(final String[] el) {
|
private String formErrorText(final String[] el) {
|
||||||
StringBuilder text = new StringBuilder();
|
final StringBuilder text = new StringBuilder();
|
||||||
if (el != null) {
|
if (el != null) {
|
||||||
for (String e : el) {
|
for (final String e : el) {
|
||||||
text.append("-------------------------------------\n").append(e);
|
text.append("-------------------------------------\n").append(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,19 +334,19 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void goToReturnActivity() {
|
private void goToReturnActivity() {
|
||||||
Class<? extends Activity> checkedReturnActivity = getReturnActivity(returnActivity);
|
final Class<? extends Activity> checkedReturnActivity = getReturnActivity(returnActivity);
|
||||||
if (checkedReturnActivity == null) {
|
if (checkedReturnActivity == null) {
|
||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
} else {
|
} else {
|
||||||
Intent intent = new Intent(this, checkedReturnActivity);
|
final Intent intent = new Intent(this, checkedReturnActivity);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
NavUtils.navigateUpTo(this, intent);
|
NavUtils.navigateUpTo(this, intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildInfo(final ErrorInfo info) {
|
private void buildInfo(final ErrorInfo info) {
|
||||||
TextView infoLabelView = findViewById(R.id.errorInfoLabelsView);
|
final TextView infoLabelView = findViewById(R.id.errorInfoLabelsView);
|
||||||
TextView infoView = findViewById(R.id.errorInfosView);
|
final TextView infoView = findViewById(R.id.errorInfosView);
|
||||||
String text = "";
|
String text = "";
|
||||||
|
|
||||||
infoLabelView.setText(getString(R.string.info_labels).replace("\\n", "\n"));
|
infoLabelView.setText(getString(R.string.info_labels).replace("\\n", "\n"));
|
||||||
|
@ -383,7 +383,7 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
.value("user_comment", userCommentBox.getText().toString())
|
.value("user_comment", userCommentBox.getText().toString())
|
||||||
.end()
|
.end()
|
||||||
.done();
|
.done();
|
||||||
} catch (Throwable e) {
|
} catch (final Throwable e) {
|
||||||
Log.e(TAG, "Error while erroring: Could not build json");
|
Log.e(TAG, "Error while erroring: Could not build json");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -441,7 +441,7 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
htmlErrorReport.append("<hr>\n");
|
htmlErrorReport.append("<hr>\n");
|
||||||
return htmlErrorReport.toString();
|
return htmlErrorReport.toString();
|
||||||
} catch (Throwable e) {
|
} catch (final Throwable e) {
|
||||||
Log.e(TAG, "Error while erroring: Could not build markdown");
|
Log.e(TAG, "Error while erroring: Could not build markdown");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "";
|
return "";
|
||||||
|
@ -478,7 +478,7 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private void addGuruMeditation() {
|
private void addGuruMeditation() {
|
||||||
//just an easter egg
|
//just an easter egg
|
||||||
TextView sorryView = findViewById(R.id.errorSorryView);
|
final TextView sorryView = findViewById(R.id.errorSorryView);
|
||||||
String text = sorryView.getText().toString();
|
String text = sorryView.getText().toString();
|
||||||
text += "\n" + getString(R.string.guru_meditation);
|
text += "\n" + getString(R.string.guru_meditation);
|
||||||
sorryView.setText(text);
|
sorryView.setText(text);
|
||||||
|
@ -491,7 +491,7 @@ public class ErrorActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCurrentTimeStamp() {
|
public String getCurrentTimeStamp() {
|
||||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
df.setTimeZone(TimeZone.getTimeZone("GMT"));
|
df.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
return df.format(new Date());
|
return df.format(new Date());
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
String themeKey = getString(R.string.theme_key);
|
final String themeKey = getString(R.string.theme_key);
|
||||||
startThemeKey = defaultPreferences
|
startThemeKey = defaultPreferences
|
||||||
.getString(themeKey, getString(R.string.default_theme_value));
|
.getString(themeKey, getString(R.string.default_theme_value));
|
||||||
findPreference(themeKey).setOnPreferenceChangeListener(themePreferenceChange);
|
findPreference(themeKey).setOnPreferenceChangeListener(themePreferenceChange);
|
||||||
|
@ -64,7 +64,7 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment {
|
||||||
if (preference.getKey().equals(captionSettingsKey) && CAPTIONING_SETTINGS_ACCESSIBLE) {
|
if (preference.getKey().equals(captionSettingsKey) && CAPTIONING_SETTINGS_ACCESSIBLE) {
|
||||||
try {
|
try {
|
||||||
startActivity(new Intent(Settings.ACTION_CAPTIONING_SETTINGS));
|
startActivity(new Intent(Settings.ACTION_CAPTIONING_SETTINGS));
|
||||||
} catch (ActivityNotFoundException e) {
|
} catch (final ActivityNotFoundException e) {
|
||||||
Toast.makeText(getActivity(), R.string.general_error, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), R.string.general_error, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ public abstract class BasePreferenceFragment extends PreferenceFragmentCompat {
|
||||||
|
|
||||||
private void updateTitle() {
|
private void updateTitle() {
|
||||||
if (getActivity() instanceof AppCompatActivity) {
|
if (getActivity() instanceof AppCompatActivity) {
|
||||||
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
final ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||||
if (actionBar != null) {
|
if (actionBar != null) {
|
||||||
actionBar.setTitle(getPreferenceScreen().getTitle());
|
actionBar.setTitle(getPreferenceScreen().getTitle());
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ import org.schabi.newpipe.util.ZipHelper;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
|
@ -91,7 +90,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preference.getKey().equals(youtubeRestrictedModeEnabledKey)) {
|
if (preference.getKey().equals(youtubeRestrictedModeEnabledKey)) {
|
||||||
Context context = getContext();
|
final Context context = getContext();
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
DownloaderImpl.getInstance().updateYoutubeRestrictedModeCookies(context);
|
DownloaderImpl.getInstance().updateYoutubeRestrictedModeCookies(context);
|
||||||
} else {
|
} else {
|
||||||
|
@ -105,7 +104,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
||||||
|
|
||||||
String homeDir = getActivity().getApplicationInfo().dataDir;
|
final String homeDir = getActivity().getApplicationInfo().dataDir;
|
||||||
databasesDir = new File(homeDir + "/databases");
|
databasesDir = new File(homeDir + "/databases");
|
||||||
newpipeDb = new File(homeDir + "/databases/newpipe.db");
|
newpipeDb = new File(homeDir + "/databases/newpipe.db");
|
||||||
newpipeDbJournal = new File(homeDir + "/databases/newpipe.db-journal");
|
newpipeDbJournal = new File(homeDir + "/databases/newpipe.db-journal");
|
||||||
|
@ -117,9 +116,9 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
|
|
||||||
addPreferencesFromResource(R.xml.content_settings);
|
addPreferencesFromResource(R.xml.content_settings);
|
||||||
|
|
||||||
Preference importDataPreference = findPreference(getString(R.string.import_data));
|
final Preference importDataPreference = findPreference(getString(R.string.import_data));
|
||||||
importDataPreference.setOnPreferenceClickListener((Preference p) -> {
|
importDataPreference.setOnPreferenceClickListener((Preference p) -> {
|
||||||
Intent i = new Intent(getActivity(), FilePickerActivityHelper.class)
|
final Intent i = new Intent(getActivity(), FilePickerActivityHelper.class)
|
||||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
|
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
|
||||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, false)
|
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, false)
|
||||||
.putExtra(FilePickerActivityHelper.EXTRA_MODE,
|
.putExtra(FilePickerActivityHelper.EXTRA_MODE,
|
||||||
|
@ -128,9 +127,9 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
Preference exportDataPreference = findPreference(getString(R.string.export_data));
|
final Preference exportDataPreference = findPreference(getString(R.string.export_data));
|
||||||
exportDataPreference.setOnPreferenceClickListener((Preference p) -> {
|
exportDataPreference.setOnPreferenceClickListener((Preference p) -> {
|
||||||
Intent i = new Intent(getActivity(), FilePickerActivityHelper.class)
|
final Intent i = new Intent(getActivity(), FilePickerActivityHelper.class)
|
||||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
|
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
|
||||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, true)
|
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, true)
|
||||||
.putExtra(FilePickerActivityHelper.EXTRA_MODE,
|
.putExtra(FilePickerActivityHelper.EXTRA_MODE,
|
||||||
|
@ -175,12 +174,12 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
|
|
||||||
if ((requestCode == REQUEST_IMPORT_PATH || requestCode == REQUEST_EXPORT_PATH)
|
if ((requestCode == REQUEST_IMPORT_PATH || requestCode == REQUEST_EXPORT_PATH)
|
||||||
&& resultCode == Activity.RESULT_OK && data.getData() != null) {
|
&& resultCode == Activity.RESULT_OK && data.getData() != null) {
|
||||||
String path = Utils.getFileForUri(data.getData()).getAbsolutePath();
|
final String path = Utils.getFileForUri(data.getData()).getAbsolutePath();
|
||||||
if (requestCode == REQUEST_EXPORT_PATH) {
|
if (requestCode == REQUEST_EXPORT_PATH) {
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US);
|
final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US);
|
||||||
exportDatabase(path + "/NewPipeData-" + sdf.format(new Date()) + ".zip");
|
exportDatabase(path + "/NewPipeData-" + sdf.format(new Date()) + ".zip");
|
||||||
} else {
|
} else {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
builder.setMessage(R.string.override_current_data)
|
builder.setMessage(R.string.override_current_data)
|
||||||
.setPositiveButton(getString(R.string.finish),
|
.setPositiveButton(getString(R.string.finish),
|
||||||
(DialogInterface d, int id) -> importDatabase(path))
|
(DialogInterface d, int id) -> importDatabase(path))
|
||||||
|
@ -196,7 +195,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
//checkpoint before export
|
//checkpoint before export
|
||||||
NewPipeDatabase.checkpoint();
|
NewPipeDatabase.checkpoint();
|
||||||
|
|
||||||
ZipOutputStream outZip = new ZipOutputStream(
|
final ZipOutputStream outZip = new ZipOutputStream(
|
||||||
new BufferedOutputStream(
|
new BufferedOutputStream(
|
||||||
new FileOutputStream(path)));
|
new FileOutputStream(path)));
|
||||||
ZipHelper.addFileToZip(outZip, newpipeDb.getPath(), "newpipe.db");
|
ZipHelper.addFileToZip(outZip, newpipeDb.getPath(), "newpipe.db");
|
||||||
|
@ -208,7 +207,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
|
|
||||||
Toast.makeText(getContext(), R.string.export_complete_toast, Toast.LENGTH_SHORT)
|
Toast.makeText(getContext(), R.string.export_complete_toast, Toast.LENGTH_SHORT)
|
||||||
.show();
|
.show();
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
onError(e);
|
onError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,12 +216,11 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
ObjectOutputStream output = null;
|
ObjectOutputStream output = null;
|
||||||
try {
|
try {
|
||||||
output = new ObjectOutputStream(new FileOutputStream(dst));
|
output = new ObjectOutputStream(new FileOutputStream(dst));
|
||||||
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getContext());
|
final SharedPreferences pref
|
||||||
|
= PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
output.writeObject(pref.getAll());
|
output.writeObject(pref.getAll());
|
||||||
|
|
||||||
} catch (FileNotFoundException e) {
|
} catch (final IOException e) {
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
|
@ -230,7 +228,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
output.flush();
|
output.flush();
|
||||||
output.close();
|
output.close();
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (final IOException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,14 +239,14 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
ZipFile zipFile = null;
|
ZipFile zipFile = null;
|
||||||
try {
|
try {
|
||||||
zipFile = new ZipFile(filePath);
|
zipFile = new ZipFile(filePath);
|
||||||
} catch (IOException ioe) {
|
} catch (final IOException ioe) {
|
||||||
Toast.makeText(getContext(), R.string.no_valid_zip_file, Toast.LENGTH_SHORT)
|
Toast.makeText(getContext(), R.string.no_valid_zip_file, Toast.LENGTH_SHORT)
|
||||||
.show();
|
.show();
|
||||||
return;
|
return;
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
zipFile.close();
|
zipFile.close();
|
||||||
} catch (Exception ignored) {
|
} catch (final Exception ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +270,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
//If settings file exist, ask if it should be imported.
|
//If settings file exist, ask if it should be imported.
|
||||||
if (ZipHelper.extractFileFromZip(filePath, newpipeSettings.getPath(),
|
if (ZipHelper.extractFileFromZip(filePath, newpipeSettings.getPath(),
|
||||||
"newpipe.settings")) {
|
"newpipe.settings")) {
|
||||||
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
final AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
||||||
alert.setTitle(R.string.import_settings);
|
alert.setTitle(R.string.import_settings);
|
||||||
|
|
||||||
alert.setNegativeButton(android.R.string.no, (dialog, which) -> {
|
alert.setNegativeButton(android.R.string.no, (dialog, which) -> {
|
||||||
|
@ -291,7 +289,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
// restart app to properly load db
|
// restart app to properly load db
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
onError(e);
|
onError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,13 +298,13 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
ObjectInputStream input = null;
|
ObjectInputStream input = null;
|
||||||
try {
|
try {
|
||||||
input = new ObjectInputStream(new FileInputStream(src));
|
input = new ObjectInputStream(new FileInputStream(src));
|
||||||
SharedPreferences.Editor prefEdit = PreferenceManager
|
final SharedPreferences.Editor prefEdit = PreferenceManager
|
||||||
.getDefaultSharedPreferences(getContext()).edit();
|
.getDefaultSharedPreferences(getContext()).edit();
|
||||||
prefEdit.clear();
|
prefEdit.clear();
|
||||||
Map<String, ?> entries = (Map<String, ?>) input.readObject();
|
final Map<String, ?> entries = (Map<String, ?>) input.readObject();
|
||||||
for (Map.Entry<String, ?> entry : entries.entrySet()) {
|
for (final Map.Entry<String, ?> entry : entries.entrySet()) {
|
||||||
Object v = entry.getValue();
|
final Object v = entry.getValue();
|
||||||
String key = entry.getKey();
|
final String key = entry.getKey();
|
||||||
|
|
||||||
if (v instanceof Boolean) {
|
if (v instanceof Boolean) {
|
||||||
prefEdit.putBoolean(key, (Boolean) v);
|
prefEdit.putBoolean(key, (Boolean) v);
|
||||||
|
@ -321,18 +319,14 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prefEdit.commit();
|
prefEdit.commit();
|
||||||
} catch (FileNotFoundException e) {
|
} catch (final IOException | ClassNotFoundException e) {
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (input != null) {
|
if (input != null) {
|
||||||
input.close();
|
input.close();
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (final IOException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
rawUri = URLDecoder.decode(rawUri, StandardCharsets.UTF_8.name());
|
rawUri = URLDecoder.decode(rawUri, StandardCharsets.UTF_8.name());
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (final UnsupportedEncodingException e) {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasInvalidPath(final String prefKey) {
|
private boolean hasInvalidPath(final String prefKey) {
|
||||||
String value = defaultPreferences.getString(prefKey, null);
|
final String value = defaultPreferences.getString(prefKey, null);
|
||||||
return value == null || value.isEmpty();
|
return value == null || value.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,20 +152,20 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Uri uri = Uri.parse(oldPath);
|
final Uri uri = Uri.parse(oldPath);
|
||||||
|
|
||||||
context.getContentResolver()
|
context.getContentResolver()
|
||||||
.releasePersistableUriPermission(uri, StoredDirectoryHelper.PERMISSION_FLAGS);
|
.releasePersistableUriPermission(uri, StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||||
context.revokeUriPermission(uri, StoredDirectoryHelper.PERMISSION_FLAGS);
|
context.revokeUriPermission(uri, StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||||
|
|
||||||
Log.i(TAG, "Revoke old path permissions success on " + oldPath);
|
Log.i(TAG, "Revoke old path permissions success on " + oldPath);
|
||||||
} catch (Exception err) {
|
} catch (final Exception err) {
|
||||||
Log.e(TAG, "Error revoking old path permissions on " + oldPath, err);
|
Log.e(TAG, "Error revoking old path permissions on " + oldPath, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showMessageDialog(@StringRes final int title, @StringRes final int message) {
|
private void showMessageDialog(@StringRes final int title, @StringRes final int message) {
|
||||||
AlertDialog.Builder msg = new AlertDialog.Builder(ctx);
|
final AlertDialog.Builder msg = new AlertDialog.Builder(ctx);
|
||||||
msg.setTitle(title);
|
msg.setTitle(title);
|
||||||
msg.setMessage(message);
|
msg.setMessage(message);
|
||||||
msg.setPositiveButton(getString(R.string.finish), null);
|
msg.setPositiveButton(getString(R.string.finish), null);
|
||||||
|
@ -179,8 +179,8 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
||||||
+ "preference = [" + preference + "]");
|
+ "preference = [" + preference + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = preference.getKey();
|
final String key = preference.getKey();
|
||||||
int request;
|
final int request;
|
||||||
|
|
||||||
if (key.equals(storageUseSafPreference)) {
|
if (key.equals(storageUseSafPreference)) {
|
||||||
Toast.makeText(getContext(), R.string.download_choose_new_path,
|
Toast.makeText(getContext(), R.string.download_choose_new_path,
|
||||||
|
@ -194,7 +194,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
||||||
return super.onPreferenceTreeClick(preference);
|
return super.onPreferenceTreeClick(preference);
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent i;
|
final Intent i;
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
||||||
&& NewPipeSettings.useStorageAccessFramework(ctx)) {
|
&& NewPipeSettings.useStorageAccessFramework(ctx)) {
|
||||||
i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
|
@ -229,7 +229,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String key;
|
final String key;
|
||||||
if (requestCode == REQUEST_DOWNLOAD_VIDEO_PATH) {
|
if (requestCode == REQUEST_DOWNLOAD_VIDEO_PATH) {
|
||||||
key = downloadPathVideoPreference;
|
key = downloadPathVideoPreference;
|
||||||
} else if (requestCode == REQUEST_DOWNLOAD_AUDIO_PATH) {
|
} else if (requestCode == REQUEST_DOWNLOAD_AUDIO_PATH) {
|
||||||
|
@ -262,19 +262,20 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
||||||
context.grantUriPermission(context.getPackageName(), uri,
|
context.grantUriPermission(context.getPackageName(), uri,
|
||||||
StoredDirectoryHelper.PERMISSION_FLAGS);
|
StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||||
|
|
||||||
StoredDirectoryHelper mainStorage = new StoredDirectoryHelper(context, uri, null);
|
final StoredDirectoryHelper mainStorage
|
||||||
|
= new StoredDirectoryHelper(context, uri, null);
|
||||||
Log.i(TAG, "Acquiring tree success from " + uri.toString());
|
Log.i(TAG, "Acquiring tree success from " + uri.toString());
|
||||||
|
|
||||||
if (!mainStorage.canWrite()) {
|
if (!mainStorage.canWrite()) {
|
||||||
throw new IOException("No write permissions on " + uri.toString());
|
throw new IOException("No write permissions on " + uri.toString());
|
||||||
}
|
}
|
||||||
} catch (IOException err) {
|
} catch (final IOException err) {
|
||||||
Log.e(TAG, "Error acquiring tree from " + uri.toString(), err);
|
Log.e(TAG, "Error acquiring tree from " + uri.toString(), err);
|
||||||
showMessageDialog(R.string.general_error, R.string.no_available_dir);
|
showMessageDialog(R.string.general_error, R.string.no_available_dir);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
File target = Utils.getFileForUri(uri);
|
final File target = Utils.getFileForUri(uri);
|
||||||
if (!target.canWrite()) {
|
if (!target.canWrite()) {
|
||||||
showMessageDialog(R.string.download_to_sdcard_error_title,
|
showMessageDialog(R.string.download_to_sdcard_error_title,
|
||||||
R.string.download_to_sdcard_error_message);
|
R.string.download_to_sdcard_error_message);
|
||||||
|
|
|
@ -60,14 +60,14 @@ public final class NewPipeSettings {
|
||||||
|
|
||||||
private static void getDir(final Context context, final int keyID,
|
private static void getDir(final Context context, final int keyID,
|
||||||
final String defaultDirectoryName) {
|
final String defaultDirectoryName) {
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
final String key = context.getString(keyID);
|
final String key = context.getString(keyID);
|
||||||
String downloadPath = prefs.getString(key, null);
|
final String downloadPath = prefs.getString(key, null);
|
||||||
if ((downloadPath != null) && (!downloadPath.isEmpty())) {
|
if ((downloadPath != null) && (!downloadPath.isEmpty())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPreferences.Editor spEditor = prefs.edit();
|
final SharedPreferences.Editor spEditor = prefs.edit();
|
||||||
spEditor.putString(key, getNewPipeChildFolderPathForDir(getDir(defaultDirectoryName)));
|
spEditor.putString(key, getNewPipeChildFolderPathForDir(getDir(defaultDirectoryName)));
|
||||||
spEditor.apply();
|
spEditor.apply();
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,16 +96,16 @@ public class PeertubeInstanceListFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initViews(@NonNull final View rootView) {
|
private void initViews(@NonNull final View rootView) {
|
||||||
TextView instanceHelpTV = rootView.findViewById(R.id.instanceHelpTV);
|
final TextView instanceHelpTV = rootView.findViewById(R.id.instanceHelpTV);
|
||||||
instanceHelpTV.setText(getString(R.string.peertube_instance_url_help,
|
instanceHelpTV.setText(getString(R.string.peertube_instance_url_help,
|
||||||
getString(R.string.peertube_instance_list_url)));
|
getString(R.string.peertube_instance_list_url)));
|
||||||
|
|
||||||
initButton(rootView);
|
initButton(rootView);
|
||||||
|
|
||||||
RecyclerView listInstances = rootView.findViewById(R.id.instances);
|
final RecyclerView listInstances = rootView.findViewById(R.id.instances);
|
||||||
listInstances.setLayoutManager(new LinearLayoutManager(requireContext()));
|
listInstances.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||||
|
|
||||||
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(getItemTouchCallback());
|
final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(getItemTouchCallback());
|
||||||
itemTouchHelper.attachToRecyclerView(listInstances);
|
itemTouchHelper.attachToRecyclerView(listInstances);
|
||||||
|
|
||||||
instanceListAdapter = new InstanceListAdapter(requireContext(), itemTouchHelper);
|
instanceListAdapter = new InstanceListAdapter(requireContext(), itemTouchHelper);
|
||||||
|
@ -178,7 +178,7 @@ public class PeertubeInstanceListFragment extends Fragment {
|
||||||
|
|
||||||
private void updateTitle() {
|
private void updateTitle() {
|
||||||
if (getActivity() instanceof AppCompatActivity) {
|
if (getActivity() instanceof AppCompatActivity) {
|
||||||
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
final ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||||
if (actionBar != null) {
|
if (actionBar != null) {
|
||||||
actionBar.setTitle(R.string.peertube_instance_url_title);
|
actionBar.setTitle(R.string.peertube_instance_url_title);
|
||||||
}
|
}
|
||||||
|
@ -186,14 +186,14 @@ public class PeertubeInstanceListFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveChanges() {
|
private void saveChanges() {
|
||||||
JsonStringWriter jsonWriter = JsonWriter.string().object().array("instances");
|
final JsonStringWriter jsonWriter = JsonWriter.string().object().array("instances");
|
||||||
for (PeertubeInstance instance : instanceList) {
|
for (final PeertubeInstance instance : instanceList) {
|
||||||
jsonWriter.object();
|
jsonWriter.object();
|
||||||
jsonWriter.value("name", instance.getName());
|
jsonWriter.value("name", instance.getName());
|
||||||
jsonWriter.value("url", instance.getUrl());
|
jsonWriter.value("url", instance.getUrl());
|
||||||
jsonWriter.end();
|
jsonWriter.end();
|
||||||
}
|
}
|
||||||
String jsonToSave = jsonWriter.end().end().done();
|
final String jsonToSave = jsonWriter.end().end().done();
|
||||||
sharedPreferences.edit().putString(savedInstanceListKey, jsonToSave).apply();
|
sharedPreferences.edit().putString(savedInstanceListKey, jsonToSave).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,12 +222,12 @@ public class PeertubeInstanceListFragment extends Fragment {
|
||||||
final EditText urlET = new EditText(c);
|
final EditText urlET = new EditText(c);
|
||||||
urlET.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
|
urlET.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
|
||||||
urlET.setHint(R.string.peertube_instance_add_help);
|
urlET.setHint(R.string.peertube_instance_add_help);
|
||||||
AlertDialog dialog = new AlertDialog.Builder(c)
|
final AlertDialog dialog = new AlertDialog.Builder(c)
|
||||||
.setTitle(R.string.peertube_instance_add_title)
|
.setTitle(R.string.peertube_instance_add_title)
|
||||||
.setIcon(R.drawable.place_holder_peertube)
|
.setIcon(R.drawable.place_holder_peertube)
|
||||||
.setNegativeButton(R.string.cancel, null)
|
.setNegativeButton(R.string.cancel, null)
|
||||||
.setPositiveButton(R.string.finish, (dialog1, which) -> {
|
.setPositiveButton(R.string.finish, (dialog1, which) -> {
|
||||||
String url = urlET.getText().toString();
|
final String url = urlET.getText().toString();
|
||||||
addInstance(url);
|
addInstance(url);
|
||||||
})
|
})
|
||||||
.create();
|
.create();
|
||||||
|
@ -236,13 +236,13 @@ public class PeertubeInstanceListFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addInstance(final String url) {
|
private void addInstance(final String url) {
|
||||||
String cleanUrl = cleanUrl(url);
|
final String cleanUrl = cleanUrl(url);
|
||||||
if (cleanUrl == null) {
|
if (cleanUrl == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
Disposable disposable = Single.fromCallable(() -> {
|
final Disposable disposable = Single.fromCallable(() -> {
|
||||||
PeertubeInstance instance = new PeertubeInstance(cleanUrl);
|
final PeertubeInstance instance = new PeertubeInstance(cleanUrl);
|
||||||
instance.fetchInstanceMetaData();
|
instance.fetchInstanceMetaData();
|
||||||
return instance;
|
return instance;
|
||||||
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
||||||
|
@ -273,7 +273,7 @@ public class PeertubeInstanceListFragment extends Fragment {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// only allow if not already exists
|
// only allow if not already exists
|
||||||
for (PeertubeInstance instance : instanceList) {
|
for (final PeertubeInstance instance : instanceList) {
|
||||||
if (instance.getUrl().equals(cleanUrl)) {
|
if (instance.getUrl().equals(cleanUrl)) {
|
||||||
Toast.makeText(getActivity(), R.string.peertube_instance_add_exists,
|
Toast.makeText(getActivity(), R.string.peertube_instance_add_exists,
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
|
@ -331,7 +331,7 @@ public class PeertubeInstanceListFragment extends Fragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int swipeDir) {
|
public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int swipeDir) {
|
||||||
int position = viewHolder.getAdapterPosition();
|
final int position = viewHolder.getAdapterPosition();
|
||||||
// do not allow swiping the selected instance
|
// do not allow swiping the selected instance
|
||||||
if (instanceList.get(position).getUrl().equals(selectedInstance.getUrl())) {
|
if (instanceList.get(position).getUrl().equals(selectedInstance.getUrl())) {
|
||||||
instanceListAdapter.notifyItemChanged(position);
|
instanceListAdapter.notifyItemChanged(position);
|
||||||
|
@ -372,7 +372,7 @@ public class PeertubeInstanceListFragment extends Fragment {
|
||||||
@Override
|
@Override
|
||||||
public InstanceListAdapter.TabViewHolder onCreateViewHolder(@NonNull final ViewGroup parent,
|
public InstanceListAdapter.TabViewHolder onCreateViewHolder(@NonNull final ViewGroup parent,
|
||||||
final int viewType) {
|
final int viewType) {
|
||||||
View view = inflater.inflate(R.layout.item_instance, parent, false);
|
final View view = inflater.inflate(R.layout.item_instance, parent, false);
|
||||||
return new InstanceListAdapter.TabViewHolder(view);
|
return new InstanceListAdapter.TabViewHolder(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,10 +94,10 @@ public class SelectChannelFragment extends DialogFragment {
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container,
|
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container,
|
||||||
final Bundle savedInstanceState) {
|
final Bundle savedInstanceState) {
|
||||||
View v = inflater.inflate(R.layout.select_channel_fragment, container, false);
|
final View v = inflater.inflate(R.layout.select_channel_fragment, container, false);
|
||||||
recyclerView = v.findViewById(R.id.items_list);
|
recyclerView = v.findViewById(R.id.items_list);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
SelectChannelAdapter channelAdapter = new SelectChannelAdapter();
|
final SelectChannelAdapter channelAdapter = new SelectChannelAdapter();
|
||||||
recyclerView.setAdapter(channelAdapter);
|
recyclerView.setAdapter(channelAdapter);
|
||||||
|
|
||||||
progressBar = v.findViewById(R.id.progressBar);
|
progressBar = v.findViewById(R.id.progressBar);
|
||||||
|
@ -107,7 +107,7 @@ public class SelectChannelFragment extends DialogFragment {
|
||||||
emptyView.setVisibility(View.GONE);
|
emptyView.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
|
||||||
SubscriptionManager subscriptionManager = new SubscriptionManager(getContext());
|
final SubscriptionManager subscriptionManager = new SubscriptionManager(getContext());
|
||||||
subscriptionManager.subscriptions().toObservable()
|
subscriptionManager.subscriptions().toObservable()
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
@ -130,7 +130,7 @@ public class SelectChannelFragment extends DialogFragment {
|
||||||
|
|
||||||
private void clickedItem(final int position) {
|
private void clickedItem(final int position) {
|
||||||
if (onSelectedListener != null) {
|
if (onSelectedListener != null) {
|
||||||
SubscriptionEntity entry = subscriptions.get(position);
|
final SubscriptionEntity entry = subscriptions.get(position);
|
||||||
onSelectedListener
|
onSelectedListener
|
||||||
.onChannelSelected(entry.getServiceId(), entry.getUrl(), entry.getName());
|
.onChannelSelected(entry.getServiceId(), entry.getUrl(), entry.getName());
|
||||||
}
|
}
|
||||||
|
@ -199,14 +199,14 @@ public class SelectChannelFragment extends DialogFragment {
|
||||||
@Override
|
@Override
|
||||||
public SelectChannelItemHolder onCreateViewHolder(final ViewGroup parent,
|
public SelectChannelItemHolder onCreateViewHolder(final ViewGroup parent,
|
||||||
final int viewType) {
|
final int viewType) {
|
||||||
View item = LayoutInflater.from(parent.getContext())
|
final View item = LayoutInflater.from(parent.getContext())
|
||||||
.inflate(R.layout.select_channel_item, parent, false);
|
.inflate(R.layout.select_channel_item, parent, false);
|
||||||
return new SelectChannelItemHolder(item);
|
return new SelectChannelItemHolder(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(final SelectChannelItemHolder holder, final int position) {
|
public void onBindViewHolder(final SelectChannelItemHolder holder, final int position) {
|
||||||
SubscriptionEntity entry = subscriptions.get(position);
|
final SubscriptionEntity entry = subscriptions.get(position);
|
||||||
holder.titleView.setText(entry.getName());
|
holder.titleView.setText(entry.getName());
|
||||||
holder.view.setOnClickListener(new View.OnClickListener() {
|
holder.view.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -76,12 +76,12 @@ public class SelectKioskFragment extends DialogFragment {
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
|
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
|
||||||
final Bundle savedInstanceState) {
|
final Bundle savedInstanceState) {
|
||||||
View v = inflater.inflate(R.layout.select_kiosk_fragment, container, false);
|
final View v = inflater.inflate(R.layout.select_kiosk_fragment, container, false);
|
||||||
recyclerView = v.findViewById(R.id.items_list);
|
recyclerView = v.findViewById(R.id.items_list);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
try {
|
try {
|
||||||
selectKioskAdapter = new SelectKioskAdapter();
|
selectKioskAdapter = new SelectKioskAdapter();
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
onError(e);
|
onError(e);
|
||||||
}
|
}
|
||||||
recyclerView.setAdapter(selectKioskAdapter);
|
recyclerView.setAdapter(selectKioskAdapter);
|
||||||
|
@ -135,9 +135,9 @@ public class SelectKioskFragment extends DialogFragment {
|
||||||
private final List<Entry> kioskList = new Vector<>();
|
private final List<Entry> kioskList = new Vector<>();
|
||||||
|
|
||||||
SelectKioskAdapter() throws Exception {
|
SelectKioskAdapter() throws Exception {
|
||||||
for (StreamingService service : NewPipe.getServices()) {
|
for (final StreamingService service : NewPipe.getServices()) {
|
||||||
for (String kioskId : service.getKioskList().getAvailableKiosks()) {
|
for (final String kioskId : service.getKioskList().getAvailableKiosks()) {
|
||||||
String name = String.format(getString(R.string.service_kiosk_string),
|
final String name = String.format(getString(R.string.service_kiosk_string),
|
||||||
service.getServiceInfo().getName(),
|
service.getServiceInfo().getName(),
|
||||||
KioskTranslator.getTranslatedKioskName(kioskId, getContext()));
|
KioskTranslator.getTranslatedKioskName(kioskId, getContext()));
|
||||||
kioskList.add(new Entry(ServiceHelper.getIcon(service.getServiceId()),
|
kioskList.add(new Entry(ServiceHelper.getIcon(service.getServiceId()),
|
||||||
|
@ -151,7 +151,7 @@ public class SelectKioskFragment extends DialogFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SelectKioskItemHolder onCreateViewHolder(final ViewGroup parent, final int type) {
|
public SelectKioskItemHolder onCreateViewHolder(final ViewGroup parent, final int type) {
|
||||||
View item = LayoutInflater.from(parent.getContext())
|
final View item = LayoutInflater.from(parent.getContext())
|
||||||
.inflate(R.layout.select_kiosk_item, parent, false);
|
.inflate(R.layout.select_kiosk_item, parent, false);
|
||||||
return new SelectKioskItemHolder(item);
|
return new SelectKioskItemHolder(item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class SelectPlaylistFragment extends DialogFragment {
|
||||||
inflater.inflate(R.layout.select_playlist_fragment, container, false);
|
inflater.inflate(R.layout.select_playlist_fragment, container, false);
|
||||||
recyclerView = v.findViewById(R.id.items_list);
|
recyclerView = v.findViewById(R.id.items_list);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
SelectPlaylistAdapter playlistAdapter = new SelectPlaylistAdapter();
|
final SelectPlaylistAdapter playlistAdapter = new SelectPlaylistAdapter();
|
||||||
recyclerView.setAdapter(playlistAdapter);
|
recyclerView.setAdapter(playlistAdapter);
|
||||||
|
|
||||||
progressBar = v.findViewById(R.id.progressBar);
|
progressBar = v.findViewById(R.id.progressBar);
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class SettingsActivity extends AppCompatActivity
|
||||||
super.onCreate(savedInstanceBundle);
|
super.onCreate(savedInstanceBundle);
|
||||||
setContentView(R.layout.settings_layout);
|
setContentView(R.layout.settings_layout);
|
||||||
|
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
final Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
if (savedInstanceBundle == null) {
|
if (savedInstanceBundle == null) {
|
||||||
|
@ -69,7 +69,7 @@ public class SettingsActivity extends AppCompatActivity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||||
ActionBar actionBar = getSupportActionBar();
|
final ActionBar actionBar = getSupportActionBar();
|
||||||
if (actionBar != null) {
|
if (actionBar != null) {
|
||||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
actionBar.setDisplayShowTitleEnabled(true);
|
actionBar.setDisplayShowTitleEnabled(true);
|
||||||
|
@ -80,7 +80,7 @@ public class SettingsActivity extends AppCompatActivity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
int id = item.getItemId();
|
final int id = item.getItemId();
|
||||||
if (id == android.R.id.home) {
|
if (id == android.R.id.home) {
|
||||||
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
|
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
|
||||||
finish();
|
finish();
|
||||||
|
@ -95,7 +95,7 @@ public class SettingsActivity extends AppCompatActivity
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceStartFragment(final PreferenceFragmentCompat caller,
|
public boolean onPreferenceStartFragment(final PreferenceFragmentCompat caller,
|
||||||
final Preference preference) {
|
final Preference preference) {
|
||||||
Fragment fragment = Fragment
|
final Fragment fragment = Fragment
|
||||||
.instantiate(this, preference.getFragment(), preference.getExtras());
|
.instantiate(this, preference.getFragment(), preference.getExtras());
|
||||||
getSupportFragmentManager().beginTransaction()
|
getSupportFragmentManager().beginTransaction()
|
||||||
.setCustomAnimations(R.animator.custom_fade_in, R.animator.custom_fade_out,
|
.setCustomAnimations(R.animator.custom_fade_in, R.animator.custom_fade_out,
|
||||||
|
|
|
@ -19,7 +19,7 @@ public class UpdateSettingsFragment extends BasePreferenceFragment {
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
String updateToggleKey = getString(R.string.update_app_key);
|
final String updateToggleKey = getString(R.string.update_app_key);
|
||||||
findPreference(updateToggleKey).setOnPreferenceChangeListener(updatePreferenceChange);
|
findPreference(updateToggleKey).setOnPreferenceChangeListener(updatePreferenceChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
|
||||||
// show a snackbar to let the user give permission
|
// show a snackbar to let the user give permission
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||||
&& s.equals(getString(R.string.minimize_on_exit_key))) {
|
&& s.equals(getString(R.string.minimize_on_exit_key))) {
|
||||||
String newSetting = sharedPreferences.getString(s, null);
|
final String newSetting = sharedPreferences.getString(s, null);
|
||||||
if (newSetting != null
|
if (newSetting != null
|
||||||
&& newSetting.equals(getString(R.string.minimize_on_exit_popup_key))
|
&& newSetting.equals(getString(R.string.minimize_on_exit_popup_key))
|
||||||
&& !Settings.canDrawOverlays(getContext())) {
|
&& !Settings.canDrawOverlays(getContext())) {
|
||||||
|
@ -68,7 +68,7 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
|
||||||
final boolean inexactSeek = getPreferenceManager().getSharedPreferences()
|
final boolean inexactSeek = getPreferenceManager().getSharedPreferences()
|
||||||
.getBoolean(res.getString(R.string.use_inexact_seek_key), false);
|
.getBoolean(res.getString(R.string.use_inexact_seek_key), false);
|
||||||
|
|
||||||
for (String durationsValue : durationsValues) {
|
for (final String durationsValue : durationsValues) {
|
||||||
currentDurationValue =
|
currentDurationValue =
|
||||||
Integer.parseInt(durationsValue) / (int) DateUtils.SECOND_IN_MILLIS;
|
Integer.parseInt(durationsValue) / (int) DateUtils.SECOND_IN_MILLIS;
|
||||||
if (inexactSeek && currentDurationValue % 10 == 5) {
|
if (inexactSeek && currentDurationValue % 10 == 5) {
|
||||||
|
@ -81,7 +81,7 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
|
||||||
res.getQuantityString(R.plurals.seconds,
|
res.getQuantityString(R.plurals.seconds,
|
||||||
currentDurationValue),
|
currentDurationValue),
|
||||||
currentDurationValue));
|
currentDurationValue));
|
||||||
} catch (Resources.NotFoundException ignored) {
|
} catch (final Resources.NotFoundException ignored) {
|
||||||
// if this happens, the translation is missing,
|
// if this happens, the translation is missing,
|
||||||
// and the english string will be displayed instead
|
// and the english string will be displayed instead
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
|
||||||
final int newDuration = selectedDuration / (int) DateUtils.SECOND_IN_MILLIS + 5;
|
final int newDuration = selectedDuration / (int) DateUtils.SECOND_IN_MILLIS + 5;
|
||||||
durations.setValue(Integer.toString(newDuration * (int) DateUtils.SECOND_IN_MILLIS));
|
durations.setValue(Integer.toString(newDuration * (int) DateUtils.SECOND_IN_MILLIS));
|
||||||
|
|
||||||
Toast toast = Toast
|
final Toast toast = Toast
|
||||||
.makeText(getContext(),
|
.makeText(getContext(),
|
||||||
getString(R.string.new_seek_duration_toast, newDuration),
|
getString(R.string.new_seek_duration_toast, newDuration),
|
||||||
Toast.LENGTH_LONG);
|
Toast.LENGTH_LONG);
|
||||||
|
|
|
@ -173,7 +173,7 @@ public class ChooseTabsFragment extends Fragment {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dialog.OnClickListener actionListener = (dialog, which) -> {
|
final Dialog.OnClickListener actionListener = (dialog, which) -> {
|
||||||
final ChooseTabListItem selected = availableTabs[which];
|
final ChooseTabListItem selected = availableTabs[which];
|
||||||
addTab(selected.tabId);
|
addTab(selected.tabId);
|
||||||
};
|
};
|
||||||
|
@ -201,19 +201,19 @@ public class ChooseTabsFragment extends Fragment {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case KIOSK:
|
case KIOSK:
|
||||||
SelectKioskFragment selectKioskFragment = new SelectKioskFragment();
|
final SelectKioskFragment selectKioskFragment = new SelectKioskFragment();
|
||||||
selectKioskFragment.setOnSelectedListener((serviceId, kioskId, kioskName) ->
|
selectKioskFragment.setOnSelectedListener((serviceId, kioskId, kioskName) ->
|
||||||
addTab(new Tab.KioskTab(serviceId, kioskId)));
|
addTab(new Tab.KioskTab(serviceId, kioskId)));
|
||||||
selectKioskFragment.show(requireFragmentManager(), "select_kiosk");
|
selectKioskFragment.show(requireFragmentManager(), "select_kiosk");
|
||||||
return;
|
return;
|
||||||
case CHANNEL:
|
case CHANNEL:
|
||||||
SelectChannelFragment selectChannelFragment = new SelectChannelFragment();
|
final SelectChannelFragment selectChannelFragment = new SelectChannelFragment();
|
||||||
selectChannelFragment.setOnSelectedListener((serviceId, url, name) ->
|
selectChannelFragment.setOnSelectedListener((serviceId, url, name) ->
|
||||||
addTab(new Tab.ChannelTab(serviceId, url, name)));
|
addTab(new Tab.ChannelTab(serviceId, url, name)));
|
||||||
selectChannelFragment.show(requireFragmentManager(), "select_channel");
|
selectChannelFragment.show(requireFragmentManager(), "select_channel");
|
||||||
return;
|
return;
|
||||||
case PLAYLIST:
|
case PLAYLIST:
|
||||||
SelectPlaylistFragment selectPlaylistFragment = new SelectPlaylistFragment();
|
final SelectPlaylistFragment selectPlaylistFragment = new SelectPlaylistFragment();
|
||||||
selectPlaylistFragment.setOnSelectedListener(
|
selectPlaylistFragment.setOnSelectedListener(
|
||||||
new SelectPlaylistFragment.OnSelectedListener() {
|
new SelectPlaylistFragment.OnSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -238,7 +238,7 @@ public class ChooseTabsFragment extends Fragment {
|
||||||
private ChooseTabListItem[] getAvailableTabs(final Context context) {
|
private ChooseTabListItem[] getAvailableTabs(final Context context) {
|
||||||
final ArrayList<ChooseTabListItem> returnList = new ArrayList<>();
|
final ArrayList<ChooseTabListItem> returnList = new ArrayList<>();
|
||||||
|
|
||||||
for (Tab.Type type : Tab.Type.values()) {
|
for (final Tab.Type type : Tab.Type.values()) {
|
||||||
final Tab tab = type.getTab();
|
final Tab tab = type.getTab();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BLANK:
|
case BLANK:
|
||||||
|
@ -329,7 +329,7 @@ public class ChooseTabsFragment extends Fragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int swipeDir) {
|
public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int swipeDir) {
|
||||||
int position = viewHolder.getAdapterPosition();
|
final int position = viewHolder.getAdapterPosition();
|
||||||
tabList.remove(position);
|
tabList.remove(position);
|
||||||
selectedTabsAdapter.notifyItemRemoved(position);
|
selectedTabsAdapter.notifyItemRemoved(position);
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ public abstract class Tab {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Type typeFrom(final int tabId) {
|
public static Type typeFrom(final int tabId) {
|
||||||
for (Type available : Type.values()) {
|
for (final Type available : Type.values()) {
|
||||||
if (available.getTabId() == tabId) {
|
if (available.getTabId() == tabId) {
|
||||||
return available;
|
return available;
|
||||||
}
|
}
|
||||||
|
@ -481,7 +481,7 @@ public abstract class Tab {
|
||||||
try {
|
try {
|
||||||
final StreamingService service = NewPipe.getService(kioskServiceId);
|
final StreamingService service = NewPipe.getService(kioskServiceId);
|
||||||
kioskId = service.getKioskList().getDefaultKioskId();
|
kioskId = service.getKioskList().getDefaultKioskId();
|
||||||
} catch (ExtractionException e) {
|
} catch (final ExtractionException e) {
|
||||||
ErrorActivity.reportError(context, e, null, null,
|
ErrorActivity.reportError(context, e, null, null,
|
||||||
ErrorActivity.ErrorInfo.make(UserAction.REQUESTED_KIOSK, "none",
|
ErrorActivity.ErrorInfo.make(UserAction.REQUESTED_KIOSK, "none",
|
||||||
"Loading default kiosk from selected service", 0));
|
"Loading default kiosk from selected service", 0));
|
||||||
|
|
|
@ -59,7 +59,7 @@ public final class TabsJsonHelper {
|
||||||
|
|
||||||
final JsonArray tabsArray = outerJsonObject.getArray(JSON_TABS_ARRAY_KEY);
|
final JsonArray tabsArray = outerJsonObject.getArray(JSON_TABS_ARRAY_KEY);
|
||||||
|
|
||||||
for (Object o : tabsArray) {
|
for (final Object o : tabsArray) {
|
||||||
if (!(o instanceof JsonObject)) {
|
if (!(o instanceof JsonObject)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ public final class TabsJsonHelper {
|
||||||
returnTabs.add(tab);
|
returnTabs.add(tab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (JsonParserException e) {
|
} catch (final JsonParserException e) {
|
||||||
throw new InvalidJsonException(e);
|
throw new InvalidJsonException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ public final class TabsJsonHelper {
|
||||||
|
|
||||||
jsonWriter.array(JSON_TABS_ARRAY_KEY);
|
jsonWriter.array(JSON_TABS_ARRAY_KEY);
|
||||||
if (tabList != null) {
|
if (tabList != null) {
|
||||||
for (Tab tab : tabList) {
|
for (final Tab tab : tabList) {
|
||||||
tab.writeJsonOn(jsonWriter);
|
tab.writeJsonOn(jsonWriter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ public final class TabsManager {
|
||||||
final String savedJson = sharedPreferences.getString(savedTabsKey, null);
|
final String savedJson = sharedPreferences.getString(savedTabsKey, null);
|
||||||
try {
|
try {
|
||||||
return TabsJsonHelper.getTabsFromJson(savedJson);
|
return TabsJsonHelper.getTabsFromJson(savedJson);
|
||||||
} catch (TabsJsonHelper.InvalidJsonException e) {
|
} catch (final TabsJsonHelper.InvalidJsonException e) {
|
||||||
Toast.makeText(context, R.string.saved_tabs_invalid_json, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.saved_tabs_invalid_json, Toast.LENGTH_SHORT).show();
|
||||||
return getDefaultTabs();
|
return getDefaultTabs();
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class DataReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public long readUnsignedInt() throws IOException {
|
public long readUnsignedInt() throws IOException {
|
||||||
long value = readInt();
|
final long value = readInt();
|
||||||
return value & 0xffffffffL;
|
return value & 0xffffffffL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,8 +82,9 @@ public class DataReader {
|
||||||
|
|
||||||
public long readLong() throws IOException {
|
public long readLong() throws IOException {
|
||||||
primitiveRead(LONG_SIZE);
|
primitiveRead(LONG_SIZE);
|
||||||
long high = primitive[0] << 24 | primitive[1] << 16 | primitive[2] << 8 | primitive[3];
|
final long high
|
||||||
long low = primitive[4] << 24 | primitive[5] << 16 | primitive[6] << 8 | primitive[7];
|
= primitive[0] << 24 | primitive[1] << 16 | primitive[2] << 8 | primitive[3];
|
||||||
|
final long low = primitive[4] << 24 | primitive[5] << 16 | primitive[6] << 8 | primitive[7];
|
||||||
return high << 32 | low;
|
return high << 32 | low;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +115,7 @@ public class DataReader {
|
||||||
total += Math.max(stream.read(buffer, offset, count), 0);
|
total += Math.max(stream.read(buffer, offset, count), 0);
|
||||||
} else {
|
} else {
|
||||||
while (count > 0 && !fillBuffer()) {
|
while (count > 0 && !fillBuffer()) {
|
||||||
int read = Math.min(readCount, count);
|
final int read = Math.min(readCount, count);
|
||||||
System.arraycopy(readBuffer, readOffset, buffer, offset, read);
|
System.arraycopy(readBuffer, readOffset, buffer, offset, read);
|
||||||
|
|
||||||
readOffset += read;
|
readOffset += read;
|
||||||
|
@ -169,7 +170,7 @@ public class DataReader {
|
||||||
if (viewSize < 1) {
|
if (viewSize < 1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int res = DataReader.this.read();
|
final int res = DataReader.this.read();
|
||||||
if (res > 0) {
|
if (res > 0) {
|
||||||
viewSize--;
|
viewSize--;
|
||||||
}
|
}
|
||||||
|
@ -188,7 +189,7 @@ public class DataReader {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = DataReader.this.read(buffer, offset, Math.min(viewSize, count));
|
final int res = DataReader.this.read(buffer, offset, Math.min(viewSize, count));
|
||||||
viewSize -= res;
|
viewSize -= res;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -199,7 +200,7 @@ public class DataReader {
|
||||||
if (viewSize < 1) {
|
if (viewSize < 1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int res = (int) DataReader.this.skipBytes(Math.min(amount, viewSize));
|
final int res = (int) DataReader.this.skipBytes(Math.min(amount, viewSize));
|
||||||
viewSize -= res;
|
viewSize -= res;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -230,8 +231,8 @@ public class DataReader {
|
||||||
private final short[] primitive = new short[LONG_SIZE];
|
private final short[] primitive = new short[LONG_SIZE];
|
||||||
|
|
||||||
private void primitiveRead(final int amount) throws IOException {
|
private void primitiveRead(final int amount) throws IOException {
|
||||||
byte[] buffer = new byte[amount];
|
final byte[] buffer = new byte[amount];
|
||||||
int read = read(buffer, 0, amount);
|
final int read = read(buffer, 0, amount);
|
||||||
|
|
||||||
if (read != amount) {
|
if (read != amount) {
|
||||||
throw new EOFException("Truncated stream, missing "
|
throw new EOFException("Truncated stream, missing "
|
||||||
|
|
|
@ -116,7 +116,7 @@ public class Mp4DashReader {
|
||||||
tracks[i].trak = moov.trak[i];
|
tracks[i].trak = moov.trak[i];
|
||||||
|
|
||||||
if (moov.mvexTrex != null) {
|
if (moov.mvexTrex != null) {
|
||||||
for (Trex mvexTrex : moov.mvexTrex) {
|
for (final Trex mvexTrex : moov.mvexTrex) {
|
||||||
if (tracks[i].trak.tkhd.trackId == mvexTrex.trackId) {
|
if (tracks[i].trak.tkhd.trackId == mvexTrex.trackId) {
|
||||||
tracks[i].trex = mvexTrex;
|
tracks[i].trex = mvexTrex;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mp4DashChunk getNextChunk(final boolean infoOnly) throws IOException {
|
public Mp4DashChunk getNextChunk(final boolean infoOnly) throws IOException {
|
||||||
Mp4Track track = tracks[selectedTrack];
|
final Mp4Track track = tracks[selectedTrack];
|
||||||
|
|
||||||
while (stream.available()) {
|
while (stream.available()) {
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ public class Mp4DashReader {
|
||||||
continue; // find another chunk
|
continue; // find another chunk
|
||||||
}
|
}
|
||||||
|
|
||||||
Mp4DashChunk chunk = new Mp4DashChunk();
|
final Mp4DashChunk chunk = new Mp4DashChunk();
|
||||||
chunk.moof = moof;
|
chunk.moof = moof;
|
||||||
if (!infoOnly) {
|
if (!infoOnly) {
|
||||||
chunk.data = stream.getView(moof.traf.trun.chunkSize);
|
chunk.data = stream.getView(moof.traf.trun.chunkSize);
|
||||||
|
@ -261,13 +261,13 @@ public class Mp4DashReader {
|
||||||
private String boxName(final int type) {
|
private String boxName(final int type) {
|
||||||
try {
|
try {
|
||||||
return new String(ByteBuffer.allocate(4).putInt(type).array(), "UTF-8");
|
return new String(ByteBuffer.allocate(4).putInt(type).array(), "UTF-8");
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (final UnsupportedEncodingException e) {
|
||||||
return "0x" + Integer.toHexString(type);
|
return "0x" + Integer.toHexString(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Box readBox() throws IOException {
|
private Box readBox() throws IOException {
|
||||||
Box b = new Box();
|
final Box b = new Box();
|
||||||
b.offset = stream.position();
|
b.offset = stream.position();
|
||||||
b.size = stream.readUnsignedInt();
|
b.size = stream.readUnsignedInt();
|
||||||
b.type = stream.readInt();
|
b.type = stream.readInt();
|
||||||
|
@ -280,7 +280,7 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Box readBox(final int expected) throws IOException {
|
private Box readBox(final int expected) throws IOException {
|
||||||
Box b = readBox();
|
final Box b = readBox();
|
||||||
if (b.type != expected) {
|
if (b.type != expected) {
|
||||||
throw new NoSuchElementException("expected " + boxName(expected)
|
throw new NoSuchElementException("expected " + boxName(expected)
|
||||||
+ " found " + boxName(b));
|
+ " found " + boxName(b));
|
||||||
|
@ -290,13 +290,13 @@ public class Mp4DashReader {
|
||||||
|
|
||||||
private byte[] readFullBox(final Box ref) throws IOException {
|
private byte[] readFullBox(final Box ref) throws IOException {
|
||||||
// full box reading is limited to 2 GiB, and should be enough
|
// full box reading is limited to 2 GiB, and should be enough
|
||||||
int size = (int) ref.size;
|
final int size = (int) ref.size;
|
||||||
|
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(size);
|
final ByteBuffer buffer = ByteBuffer.allocate(size);
|
||||||
buffer.putInt(size);
|
buffer.putInt(size);
|
||||||
buffer.putInt(ref.type);
|
buffer.putInt(ref.type);
|
||||||
|
|
||||||
int read = size - 8;
|
final int read = size - 8;
|
||||||
|
|
||||||
if (stream.read(buffer.array(), 8, read) != read) {
|
if (stream.read(buffer.array(), 8, read) != read) {
|
||||||
throw new EOFException(String.format("EOF reached in box: type=%s offset=%s size=%s",
|
throw new EOFException(String.format("EOF reached in box: type=%s offset=%s size=%s",
|
||||||
|
@ -307,7 +307,7 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensure(final Box ref) throws IOException {
|
private void ensure(final Box ref) throws IOException {
|
||||||
long skip = ref.offset + ref.size - stream.position();
|
final long skip = ref.offset + ref.size - stream.position();
|
||||||
|
|
||||||
if (skip == 0) {
|
if (skip == 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -325,7 +325,7 @@ public class Mp4DashReader {
|
||||||
Box b;
|
Box b;
|
||||||
while (stream.position() < (ref.offset + ref.size)) {
|
while (stream.position() < (ref.offset + ref.size)) {
|
||||||
b = readBox();
|
b = readBox();
|
||||||
for (int type : expected) {
|
for (final int type : expected) {
|
||||||
if (b.type == type) {
|
if (b.type == type) {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
@ -345,7 +345,7 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Moof parseMoof(final Box ref, final int trackId) throws IOException {
|
private Moof parseMoof(final Box ref, final int trackId) throws IOException {
|
||||||
Moof obj = new Moof();
|
final Moof obj = new Moof();
|
||||||
|
|
||||||
Box b = readBox(ATOM_MFHD);
|
Box b = readBox(ATOM_MFHD);
|
||||||
obj.mfhdSequenceNumber = parseMfhd();
|
obj.mfhdSequenceNumber = parseMfhd();
|
||||||
|
@ -372,7 +372,7 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Traf parseTraf(final Box ref, final int trackId) throws IOException {
|
private Traf parseTraf(final Box ref, final int trackId) throws IOException {
|
||||||
Traf traf = new Traf();
|
final Traf traf = new Traf();
|
||||||
|
|
||||||
Box b = readBox(ATOM_TFHD);
|
Box b = readBox(ATOM_TFHD);
|
||||||
traf.tfhd = parseTfhd(trackId);
|
traf.tfhd = parseTfhd(trackId);
|
||||||
|
@ -397,7 +397,7 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tfhd parseTfhd(final int trackId) throws IOException {
|
private Tfhd parseTfhd(final int trackId) throws IOException {
|
||||||
Tfhd obj = new Tfhd();
|
final Tfhd obj = new Tfhd();
|
||||||
|
|
||||||
obj.bFlags = stream.readInt();
|
obj.bFlags = stream.readInt();
|
||||||
obj.trackId = stream.readInt();
|
obj.trackId = stream.readInt();
|
||||||
|
@ -426,13 +426,13 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private long parseTfdt() throws IOException {
|
private long parseTfdt() throws IOException {
|
||||||
int version = stream.read();
|
final int version = stream.read();
|
||||||
stream.skipBytes(3); // flags
|
stream.skipBytes(3); // flags
|
||||||
return version == 0 ? stream.readUnsignedInt() : stream.readLong();
|
return version == 0 ? stream.readUnsignedInt() : stream.readLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Trun parseTrun() throws IOException {
|
private Trun parseTrun() throws IOException {
|
||||||
Trun obj = new Trun();
|
final Trun obj = new Trun();
|
||||||
obj.bFlags = stream.readInt();
|
obj.bFlags = stream.readInt();
|
||||||
obj.entryCount = stream.readInt(); // unsigned int
|
obj.entryCount = stream.readInt(); // unsigned int
|
||||||
|
|
||||||
|
@ -461,7 +461,7 @@ public class Mp4DashReader {
|
||||||
stream.read(obj.bEntries);
|
stream.read(obj.bEntries);
|
||||||
|
|
||||||
for (int i = 0; i < obj.entryCount; i++) {
|
for (int i = 0; i < obj.entryCount; i++) {
|
||||||
TrunEntry entry = obj.getEntry(i);
|
final TrunEntry entry = obj.getEntry(i);
|
||||||
if (hasFlag(obj.bFlags, 0x0100)) {
|
if (hasFlag(obj.bFlags, 0x0100)) {
|
||||||
obj.chunkDuration += entry.sampleDuration;
|
obj.chunkDuration += entry.sampleDuration;
|
||||||
}
|
}
|
||||||
|
@ -480,7 +480,7 @@ public class Mp4DashReader {
|
||||||
|
|
||||||
private int[] parseFtyp(final Box ref) throws IOException {
|
private int[] parseFtyp(final Box ref) throws IOException {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int[] list = new int[(int) ((ref.offset + ref.size - stream.position() - 4) / 4)];
|
final int[] list = new int[(int) ((ref.offset + ref.size - stream.position() - 4) / 4)];
|
||||||
|
|
||||||
list[i++] = stream.readInt(); // major brand
|
list[i++] = stream.readInt(); // major brand
|
||||||
|
|
||||||
|
@ -494,14 +494,14 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mvhd parseMvhd() throws IOException {
|
private Mvhd parseMvhd() throws IOException {
|
||||||
int version = stream.read();
|
final int version = stream.read();
|
||||||
stream.skipBytes(3); // flags
|
stream.skipBytes(3); // flags
|
||||||
|
|
||||||
// creation entries_time
|
// creation entries_time
|
||||||
// modification entries_time
|
// modification entries_time
|
||||||
stream.skipBytes(2 * (version == 0 ? 4 : 8));
|
stream.skipBytes(2 * (version == 0 ? 4 : 8));
|
||||||
|
|
||||||
Mvhd obj = new Mvhd();
|
final Mvhd obj = new Mvhd();
|
||||||
obj.timeScale = stream.readUnsignedInt();
|
obj.timeScale = stream.readUnsignedInt();
|
||||||
|
|
||||||
// chunkDuration
|
// chunkDuration
|
||||||
|
@ -520,9 +520,9 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tkhd parseTkhd() throws IOException {
|
private Tkhd parseTkhd() throws IOException {
|
||||||
int version = stream.read();
|
final int version = stream.read();
|
||||||
|
|
||||||
Tkhd obj = new Tkhd();
|
final Tkhd obj = new Tkhd();
|
||||||
|
|
||||||
// flags
|
// flags
|
||||||
// creation entries_time
|
// creation entries_time
|
||||||
|
@ -553,7 +553,7 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Trak parseTrak(final Box ref) throws IOException {
|
private Trak parseTrak(final Box ref) throws IOException {
|
||||||
Trak trak = new Trak();
|
final Trak trak = new Trak();
|
||||||
|
|
||||||
Box b = readBox(ATOM_TKHD);
|
Box b = readBox(ATOM_TKHD);
|
||||||
trak.tkhd = parseTkhd();
|
trak.tkhd = parseTkhd();
|
||||||
|
@ -576,7 +576,7 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mdia parseMdia(final Box ref) throws IOException {
|
private Mdia parseMdia(final Box ref) throws IOException {
|
||||||
Mdia obj = new Mdia();
|
final Mdia obj = new Mdia();
|
||||||
|
|
||||||
Box b;
|
Box b;
|
||||||
while ((b = untilBox(ref, ATOM_MDHD, ATOM_HDLR, ATOM_MINF)) != null) {
|
while ((b = untilBox(ref, ATOM_MDHD, ATOM_HDLR, ATOM_MINF)) != null) {
|
||||||
|
@ -585,8 +585,8 @@ public class Mp4DashReader {
|
||||||
obj.mdhd = readFullBox(b);
|
obj.mdhd = readFullBox(b);
|
||||||
|
|
||||||
// read time scale
|
// read time scale
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(obj.mdhd);
|
final ByteBuffer buffer = ByteBuffer.wrap(obj.mdhd);
|
||||||
byte version = buffer.get(8);
|
final byte version = buffer.get(8);
|
||||||
buffer.position(12 + ((version == 0 ? 4 : 8) * 2));
|
buffer.position(12 + ((version == 0 ? 4 : 8) * 2));
|
||||||
obj.mdhdTimeScale = buffer.getInt();
|
obj.mdhdTimeScale = buffer.getInt();
|
||||||
break;
|
break;
|
||||||
|
@ -608,7 +608,7 @@ public class Mp4DashReader {
|
||||||
// flags
|
// flags
|
||||||
stream.skipBytes(4);
|
stream.skipBytes(4);
|
||||||
|
|
||||||
Hdlr obj = new Hdlr();
|
final Hdlr obj = new Hdlr();
|
||||||
obj.bReserved = new byte[12];
|
obj.bReserved = new byte[12];
|
||||||
|
|
||||||
obj.type = stream.readInt();
|
obj.type = stream.readInt();
|
||||||
|
@ -623,11 +623,11 @@ public class Mp4DashReader {
|
||||||
|
|
||||||
private Moov parseMoov(final Box ref) throws IOException {
|
private Moov parseMoov(final Box ref) throws IOException {
|
||||||
Box b = readBox(ATOM_MVHD);
|
Box b = readBox(ATOM_MVHD);
|
||||||
Moov moov = new Moov();
|
final Moov moov = new Moov();
|
||||||
moov.mvhd = parseMvhd();
|
moov.mvhd = parseMvhd();
|
||||||
ensure(b);
|
ensure(b);
|
||||||
|
|
||||||
ArrayList<Trak> tmp = new ArrayList<>((int) moov.mvhd.nextTrackId);
|
final ArrayList<Trak> tmp = new ArrayList<>((int) moov.mvhd.nextTrackId);
|
||||||
while ((b = untilBox(ref, ATOM_TRAK, ATOM_MVEX)) != null) {
|
while ((b = untilBox(ref, ATOM_TRAK, ATOM_MVEX)) != null) {
|
||||||
|
|
||||||
switch (b.type) {
|
switch (b.type) {
|
||||||
|
@ -648,7 +648,7 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Trex[] parseMvex(final Box ref, final int possibleTrackCount) throws IOException {
|
private Trex[] parseMvex(final Box ref, final int possibleTrackCount) throws IOException {
|
||||||
ArrayList<Trex> tmp = new ArrayList<>(possibleTrackCount);
|
final ArrayList<Trex> tmp = new ArrayList<>(possibleTrackCount);
|
||||||
|
|
||||||
Box b;
|
Box b;
|
||||||
while ((b = untilBox(ref, ATOM_TREX)) != null) {
|
while ((b = untilBox(ref, ATOM_TREX)) != null) {
|
||||||
|
@ -664,7 +664,7 @@ public class Mp4DashReader {
|
||||||
// flags
|
// flags
|
||||||
stream.skipBytes(4);
|
stream.skipBytes(4);
|
||||||
|
|
||||||
Trex obj = new Trex();
|
final Trex obj = new Trex();
|
||||||
obj.trackId = stream.readInt();
|
obj.trackId = stream.readInt();
|
||||||
obj.defaultSampleDescriptionIndex = stream.readInt();
|
obj.defaultSampleDescriptionIndex = stream.readInt();
|
||||||
obj.defaultSampleDuration = stream.readInt();
|
obj.defaultSampleDuration = stream.readInt();
|
||||||
|
@ -675,17 +675,17 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Elst parseEdts(final Box ref) throws IOException {
|
private Elst parseEdts(final Box ref) throws IOException {
|
||||||
Box b = untilBox(ref, ATOM_ELST);
|
final Box b = untilBox(ref, ATOM_ELST);
|
||||||
if (b == null) {
|
if (b == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Elst obj = new Elst();
|
final Elst obj = new Elst();
|
||||||
|
|
||||||
boolean v1 = stream.read() == 1;
|
final boolean v1 = stream.read() == 1;
|
||||||
stream.skipBytes(3); // flags
|
stream.skipBytes(3); // flags
|
||||||
|
|
||||||
int entryCount = stream.readInt();
|
final int entryCount = stream.readInt();
|
||||||
if (entryCount < 1) {
|
if (entryCount < 1) {
|
||||||
obj.bMediaRate = 0x00010000; // default media rate (1.0)
|
obj.bMediaRate = 0x00010000; // default media rate (1.0)
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -707,7 +707,7 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Minf parseMinf(final Box ref) throws IOException {
|
private Minf parseMinf(final Box ref) throws IOException {
|
||||||
Minf obj = new Minf();
|
final Minf obj = new Minf();
|
||||||
|
|
||||||
Box b;
|
Box b;
|
||||||
while ((b = untilAnyBox(ref)) != null) {
|
while ((b = untilAnyBox(ref)) != null) {
|
||||||
|
@ -738,7 +738,7 @@ public class Mp4DashReader {
|
||||||
* @return stsd box inside
|
* @return stsd box inside
|
||||||
*/
|
*/
|
||||||
private byte[] parseStbl(final Box ref) throws IOException {
|
private byte[] parseStbl(final Box ref) throws IOException {
|
||||||
Box b = untilBox(ref, ATOM_STSD);
|
final Box b = untilBox(ref, ATOM_STSD);
|
||||||
|
|
||||||
if (b == null) {
|
if (b == null) {
|
||||||
return new byte[0]; // this never should happens (missing codec startup data)
|
return new byte[0]; // this never should happens (missing codec startup data)
|
||||||
|
@ -796,8 +796,8 @@ public class Mp4DashReader {
|
||||||
int entriesRowSize;
|
int entriesRowSize;
|
||||||
|
|
||||||
public TrunEntry getEntry(final int i) {
|
public TrunEntry getEntry(final int i) {
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(bEntries, i * entriesRowSize, entriesRowSize);
|
final ByteBuffer buffer = ByteBuffer.wrap(bEntries, i * entriesRowSize, entriesRowSize);
|
||||||
TrunEntry entry = new TrunEntry();
|
final TrunEntry entry = new TrunEntry();
|
||||||
|
|
||||||
if (hasFlag(bFlags, 0x0100)) {
|
if (hasFlag(bFlags, 0x0100)) {
|
||||||
entry.sampleDuration = buffer.getInt();
|
entry.sampleDuration = buffer.getInt();
|
||||||
|
@ -819,7 +819,7 @@ public class Mp4DashReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TrunEntry getAbsoluteEntry(final int i, final Tfhd header) {
|
public TrunEntry getAbsoluteEntry(final int i, final Tfhd header) {
|
||||||
TrunEntry entry = getEntry(i);
|
final TrunEntry entry = getEntry(i);
|
||||||
|
|
||||||
if (!hasFlag(bFlags, 0x0100) && hasFlag(header.bFlags, 0x20)) {
|
if (!hasFlag(bFlags, 0x0100) && hasFlag(header.bFlags, 0x20)) {
|
||||||
entry.sampleFlags = header.defaultSampleFlags;
|
entry.sampleFlags = header.defaultSampleFlags;
|
||||||
|
@ -928,7 +928,7 @@ public class Mp4DashReader {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mp4DashSample sample = new Mp4DashSample();
|
final Mp4DashSample sample = new Mp4DashSample();
|
||||||
sample.info = moof.traf.trun.getAbsoluteEntry(i++, moof.traf.tfhd);
|
sample.info = moof.traf.trun.getAbsoluteEntry(i++, moof.traf.tfhd);
|
||||||
sample.data = new byte[sample.info.sampleSize];
|
sample.data = new byte[sample.info.sampleSize];
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class Mp4FromDashWriter {
|
||||||
private final ArrayList<Integer> compatibleBrands = new ArrayList<>(5);
|
private final ArrayList<Integer> compatibleBrands = new ArrayList<>(5);
|
||||||
|
|
||||||
public Mp4FromDashWriter(final SharpStream... sources) throws IOException {
|
public Mp4FromDashWriter(final SharpStream... sources) throws IOException {
|
||||||
for (SharpStream src : sources) {
|
for (final SharpStream src : sources) {
|
||||||
if (!src.canRewind() && !src.canRead()) {
|
if (!src.canRewind() && !src.canRead()) {
|
||||||
throw new IOException("All sources must be readable and allow rewind");
|
throw new IOException("All sources must be readable and allow rewind");
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ public class Mp4FromDashWriter {
|
||||||
done = true;
|
done = true;
|
||||||
parsed = true;
|
parsed = true;
|
||||||
|
|
||||||
for (SharpStream src : sourceTracks) {
|
for (final SharpStream src : sourceTracks) {
|
||||||
src.close();
|
src.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,17 +157,17 @@ public class Mp4FromDashWriter {
|
||||||
outStream = output;
|
outStream = output;
|
||||||
long read = 8; // mdat box header size
|
long read = 8; // mdat box header size
|
||||||
long totalSampleSize = 0;
|
long totalSampleSize = 0;
|
||||||
int[] sampleExtra = new int[readers.length];
|
final int[] sampleExtra = new int[readers.length];
|
||||||
int[] defaultMediaTime = new int[readers.length];
|
final int[] defaultMediaTime = new int[readers.length];
|
||||||
int[] defaultSampleDuration = new int[readers.length];
|
final int[] defaultSampleDuration = new int[readers.length];
|
||||||
int[] sampleCount = new int[readers.length];
|
final int[] sampleCount = new int[readers.length];
|
||||||
|
|
||||||
TablesInfo[] tablesInfo = new TablesInfo[tracks.length];
|
final TablesInfo[] tablesInfo = new TablesInfo[tracks.length];
|
||||||
for (int i = 0; i < tablesInfo.length; i++) {
|
for (int i = 0; i < tablesInfo.length; i++) {
|
||||||
tablesInfo[i] = new TablesInfo();
|
tablesInfo[i] = new TablesInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
int singleSampleBuffer;
|
final int singleSampleBuffer;
|
||||||
if (tracks.length == 1 && tracks[0].kind == TrackKind.Audio) {
|
if (tracks.length == 1 && tracks[0].kind == TrackKind.Audio) {
|
||||||
// near 1 second of audio data per chunk, avoid split the audio stream in large chunks
|
// near 1 second of audio data per chunk, avoid split the audio stream in large chunks
|
||||||
singleSampleBuffer = tracks[0].trak.mdia.mdhdTimeScale / 1000;
|
singleSampleBuffer = tracks[0].trak.mdia.mdhdTimeScale / 1000;
|
||||||
|
@ -250,10 +250,10 @@ public class Mp4FromDashWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boolean is64 = read > THRESHOLD_FOR_CO64;
|
final boolean is64 = read > THRESHOLD_FOR_CO64;
|
||||||
|
|
||||||
// calculate the moov size
|
// calculate the moov size
|
||||||
int auxSize = makeMoov(defaultMediaTime, tablesInfo, is64);
|
final int auxSize = makeMoov(defaultMediaTime, tablesInfo, is64);
|
||||||
|
|
||||||
if (auxSize < THRESHOLD_MOOV_LENGTH) {
|
if (auxSize < THRESHOLD_MOOV_LENGTH) {
|
||||||
auxBuffer = ByteBuffer.allocate(auxSize); // cache moov in the memory
|
auxBuffer = ByteBuffer.allocate(auxSize); // cache moov in the memory
|
||||||
|
@ -267,9 +267,9 @@ public class Mp4FromDashWriter {
|
||||||
// reserve moov space in the output stream
|
// reserve moov space in the output stream
|
||||||
if (auxSize > 0) {
|
if (auxSize > 0) {
|
||||||
int length = auxSize;
|
int length = auxSize;
|
||||||
byte[] buffer = new byte[64 * 1024]; // 64 KiB
|
final byte[] buffer = new byte[64 * 1024]; // 64 KiB
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
int count = Math.min(length, buffer.length);
|
final int count = Math.min(length, buffer.length);
|
||||||
outWrite(buffer, count);
|
outWrite(buffer, count);
|
||||||
length -= count;
|
length -= count;
|
||||||
}
|
}
|
||||||
|
@ -305,9 +305,10 @@ public class Mp4FromDashWriter {
|
||||||
|
|
||||||
outWrite(makeMdat(totalSampleSize, is64));
|
outWrite(makeMdat(totalSampleSize, is64));
|
||||||
|
|
||||||
int[] sampleIndex = new int[readers.length];
|
final int[] sampleIndex = new int[readers.length];
|
||||||
int[] sizes = new int[singleSampleBuffer > 0 ? singleSampleBuffer : SAMPLES_PER_CHUNK];
|
final int[] sizes
|
||||||
int[] sync = new int[singleSampleBuffer > 0 ? singleSampleBuffer : SAMPLES_PER_CHUNK];
|
= new int[singleSampleBuffer > 0 ? singleSampleBuffer : SAMPLES_PER_CHUNK];
|
||||||
|
final int[] sync = new int[singleSampleBuffer > 0 ? singleSampleBuffer : SAMPLES_PER_CHUNK];
|
||||||
|
|
||||||
int written = readers.length;
|
int written = readers.length;
|
||||||
while (written > 0) {
|
while (written > 0) {
|
||||||
|
@ -318,9 +319,9 @@ public class Mp4FromDashWriter {
|
||||||
continue; // track is done
|
continue; // track is done
|
||||||
}
|
}
|
||||||
|
|
||||||
long chunkOffset = writeOffset;
|
final long chunkOffset = writeOffset;
|
||||||
int syncCount = 0;
|
int syncCount = 0;
|
||||||
int limit;
|
final int limit;
|
||||||
if (singleSampleBuffer > 0) {
|
if (singleSampleBuffer > 0) {
|
||||||
limit = singleSampleBuffer;
|
limit = singleSampleBuffer;
|
||||||
} else {
|
} else {
|
||||||
|
@ -329,7 +330,7 @@ public class Mp4FromDashWriter {
|
||||||
|
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (; j < limit; j++) {
|
for (; j < limit; j++) {
|
||||||
Mp4DashSample sample = getNextSample(i);
|
final Mp4DashSample sample = getNextSample(i);
|
||||||
|
|
||||||
if (sample == null) {
|
if (sample == null) {
|
||||||
if (tablesInfo[i].ctts > 0 && sampleExtra[i] >= 0) {
|
if (tablesInfo[i].ctts > 0 && sampleExtra[i] >= 0) {
|
||||||
|
@ -409,7 +410,7 @@ public class Mp4FromDashWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mp4DashSample sample = readersChunks[track].getNextSample();
|
final Mp4DashSample sample = readersChunks[track].getNextSample();
|
||||||
if (sample == null) {
|
if (sample == null) {
|
||||||
readersChunks[track] = null;
|
readersChunks[track] = null;
|
||||||
return getNextSample(track);
|
return getNextSample(track);
|
||||||
|
@ -434,8 +435,8 @@ public class Mp4FromDashWriter {
|
||||||
|
|
||||||
auxSeek(offset);
|
auxSeek(offset);
|
||||||
|
|
||||||
int size = count * 4;
|
final int size = count * 4;
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(size);
|
final ByteBuffer buffer = ByteBuffer.allocate(size);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
buffer.putInt(values[i]);
|
buffer.putInt(values[i]);
|
||||||
|
@ -466,10 +467,10 @@ public class Mp4FromDashWriter {
|
||||||
private void initChunkTables(final TablesInfo tables, final int firstCount,
|
private void initChunkTables(final TablesInfo tables, final int firstCount,
|
||||||
final int successiveCount) {
|
final int successiveCount) {
|
||||||
// tables.stsz holds amount of samples of the track (total)
|
// tables.stsz holds amount of samples of the track (total)
|
||||||
int totalSamples = (tables.stsz - firstCount);
|
final int totalSamples = (tables.stsz - firstCount);
|
||||||
float chunkAmount = totalSamples / (float) successiveCount;
|
final float chunkAmount = totalSamples / (float) successiveCount;
|
||||||
int remainChunkOffset = (int) Math.ceil(chunkAmount);
|
final int remainChunkOffset = (int) Math.ceil(chunkAmount);
|
||||||
boolean remain = remainChunkOffset != (int) chunkAmount;
|
final boolean remain = remainChunkOffset != (int) chunkAmount;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
tables.stsc = 1;
|
tables.stsc = 1;
|
||||||
|
@ -529,7 +530,7 @@ public class Mp4FromDashWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int lengthFor(final int offset) throws IOException {
|
private int lengthFor(final int offset) throws IOException {
|
||||||
int size = auxOffset() - offset;
|
final int size = auxOffset() - offset;
|
||||||
|
|
||||||
if (moovSimulation) {
|
if (moovSimulation) {
|
||||||
return size;
|
return size;
|
||||||
|
@ -545,7 +546,7 @@ public class Mp4FromDashWriter {
|
||||||
private int make(final int type, final int extra, final int columns, final int rows)
|
private int make(final int type, final int extra, final int columns, final int rows)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final byte base = 16;
|
final byte base = 16;
|
||||||
int size = columns * rows * 4;
|
final int size = columns * rows * 4;
|
||||||
int total = size + base;
|
int total = size + base;
|
||||||
int offset = auxOffset();
|
int offset = auxOffset();
|
||||||
|
|
||||||
|
@ -618,7 +619,7 @@ public class Mp4FromDashWriter {
|
||||||
size += 4;
|
size += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(size);
|
final ByteBuffer buffer = ByteBuffer.allocate(size);
|
||||||
buffer.putInt(size);
|
buffer.putInt(size);
|
||||||
buffer.putInt(0x66747970); // "ftyp"
|
buffer.putInt(0x66747970); // "ftyp"
|
||||||
|
|
||||||
|
@ -631,7 +632,7 @@ public class Mp4FromDashWriter {
|
||||||
buffer.putInt(0x6D703432); // "mp42" compatible brand
|
buffer.putInt(0x6D703432); // "mp42" compatible brand
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Integer brand : compatibleBrands) {
|
for (final Integer brand : compatibleBrands) {
|
||||||
buffer.putInt(brand); // compatible brand
|
buffer.putInt(brand); // compatible brand
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,7 +649,7 @@ public class Mp4FromDashWriter {
|
||||||
size += 8;
|
size += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(is64 ? 16 : 8)
|
final ByteBuffer buffer = ByteBuffer.allocate(is64 ? 16 : 8)
|
||||||
.putInt(is64 ? 0x01 : (int) size)
|
.putInt(is64 ? 0x01 : (int) size)
|
||||||
.putInt(0x6D646174); // mdat
|
.putInt(0x6D646174); // mdat
|
||||||
|
|
||||||
|
@ -689,14 +690,14 @@ public class Mp4FromDashWriter {
|
||||||
|
|
||||||
private int makeMoov(final int[] defaultMediaTime, final TablesInfo[] tablesInfo,
|
private int makeMoov(final int[] defaultMediaTime, final TablesInfo[] tablesInfo,
|
||||||
final boolean is64) throws RuntimeException, IOException {
|
final boolean is64) throws RuntimeException, IOException {
|
||||||
int start = auxOffset();
|
final int start = auxOffset();
|
||||||
|
|
||||||
auxWrite(new byte[]{
|
auxWrite(new byte[]{
|
||||||
0x00, 0x00, 0x00, 0x00, 0x6D, 0x6F, 0x6F, 0x76
|
0x00, 0x00, 0x00, 0x00, 0x6D, 0x6F, 0x6F, 0x76
|
||||||
});
|
});
|
||||||
|
|
||||||
long longestTrack = 0;
|
long longestTrack = 0;
|
||||||
long[] durations = new long[tracks.length];
|
final long[] durations = new long[tracks.length];
|
||||||
|
|
||||||
for (int i = 0; i < durations.length; i++) {
|
for (int i = 0; i < durations.length; i++) {
|
||||||
durations[i] = (long) Math.ceil(
|
durations[i] = (long) Math.ceil(
|
||||||
|
@ -723,7 +724,7 @@ public class Mp4FromDashWriter {
|
||||||
|
|
||||||
private void makeTrak(final int index, final long duration, final int defaultMediaTime,
|
private void makeTrak(final int index, final long duration, final int defaultMediaTime,
|
||||||
final TablesInfo tables, final boolean is64) throws IOException {
|
final TablesInfo tables, final boolean is64) throws IOException {
|
||||||
int start = auxOffset();
|
final int start = auxOffset();
|
||||||
|
|
||||||
auxWrite(new byte[]{
|
auxWrite(new byte[]{
|
||||||
// trak header
|
// trak header
|
||||||
|
@ -732,7 +733,7 @@ public class Mp4FromDashWriter {
|
||||||
0x00, 0x00, 0x00, 0x68, 0x74, 0x6B, 0x68, 0x64, 0x01, 0x00, 0x00, 0x03
|
0x00, 0x00, 0x00, 0x68, 0x74, 0x6B, 0x68, 0x64, 0x01, 0x00, 0x00, 0x03
|
||||||
});
|
});
|
||||||
|
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(48);
|
final ByteBuffer buffer = ByteBuffer.allocate(48);
|
||||||
buffer.putLong(time);
|
buffer.putLong(time);
|
||||||
buffer.putLong(time);
|
buffer.putLong(time);
|
||||||
buffer.putInt(index + 1);
|
buffer.putInt(index + 1);
|
||||||
|
@ -757,8 +758,8 @@ public class Mp4FromDashWriter {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 // elst header
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 // elst header
|
||||||
});
|
});
|
||||||
|
|
||||||
int bMediaRate;
|
final int bMediaRate;
|
||||||
int mediaTime;
|
final int mediaTime;
|
||||||
|
|
||||||
if (tracks[index].trak.edstElst == null) {
|
if (tracks[index].trak.edstElst == null) {
|
||||||
// is a audio track ¿is edst/elst optional for audio tracks?
|
// is a audio track ¿is edst/elst optional for audio tracks?
|
||||||
|
@ -784,17 +785,17 @@ public class Mp4FromDashWriter {
|
||||||
|
|
||||||
private void makeMdia(final Mdia mdia, final TablesInfo tablesInfo, final boolean is64,
|
private void makeMdia(final Mdia mdia, final TablesInfo tablesInfo, final boolean is64,
|
||||||
final boolean isAudio) throws IOException {
|
final boolean isAudio) throws IOException {
|
||||||
int startMdia = auxOffset();
|
final int startMdia = auxOffset();
|
||||||
auxWrite(new byte[]{0x00, 0x00, 0x00, 0x00, 0x6D, 0x64, 0x69, 0x61}); // mdia
|
auxWrite(new byte[]{0x00, 0x00, 0x00, 0x00, 0x6D, 0x64, 0x69, 0x61}); // mdia
|
||||||
auxWrite(mdia.mdhd);
|
auxWrite(mdia.mdhd);
|
||||||
auxWrite(makeHdlr(mdia.hdlr));
|
auxWrite(makeHdlr(mdia.hdlr));
|
||||||
|
|
||||||
int startMinf = auxOffset();
|
final int startMinf = auxOffset();
|
||||||
auxWrite(new byte[]{0x00, 0x00, 0x00, 0x00, 0x6D, 0x69, 0x6E, 0x66}); // minf
|
auxWrite(new byte[]{0x00, 0x00, 0x00, 0x00, 0x6D, 0x69, 0x6E, 0x66}); // minf
|
||||||
auxWrite(mdia.minf.mhd);
|
auxWrite(mdia.minf.mhd);
|
||||||
auxWrite(mdia.minf.dinf);
|
auxWrite(mdia.minf.dinf);
|
||||||
|
|
||||||
int startStbl = auxOffset();
|
final int startStbl = auxOffset();
|
||||||
auxWrite(new byte[]{0x00, 0x00, 0x00, 0x00, 0x73, 0x74, 0x62, 0x6C}); // stbl
|
auxWrite(new byte[]{0x00, 0x00, 0x00, 0x00, 0x73, 0x74, 0x62, 0x6C}); // stbl
|
||||||
auxWrite(mdia.minf.stblStsd);
|
auxWrite(mdia.minf.stblStsd);
|
||||||
|
|
||||||
|
@ -838,7 +839,7 @@ public class Mp4FromDashWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] makeHdlr(final Hdlr hdlr) {
|
private byte[] makeHdlr(final Hdlr hdlr) {
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(new byte[]{
|
final ByteBuffer buffer = ByteBuffer.wrap(new byte[]{
|
||||||
0x00, 0x00, 0x00, 0x21, 0x68, 0x64, 0x6C, 0x72, // hdlr
|
0x00, 0x00, 0x00, 0x21, 0x68, 0x64, 0x6C, 0x72, // hdlr
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
@ -854,7 +855,7 @@ public class Mp4FromDashWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int makeSbgp() throws IOException {
|
private int makeSbgp() throws IOException {
|
||||||
int offset = auxOffset();
|
final int offset = auxOffset();
|
||||||
|
|
||||||
auxWrite(new byte[] {
|
auxWrite(new byte[] {
|
||||||
0x00, 0x00, 0x00, 0x1C, // box size
|
0x00, 0x00, 0x00, 0x1C, // box size
|
||||||
|
@ -883,7 +884,7 @@ public class Mp4FromDashWriter {
|
||||||
* most of m4a encoders and ffmpeg uses this box with dummy values (same values)
|
* most of m4a encoders and ffmpeg uses this box with dummy values (same values)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(new byte[] {
|
final ByteBuffer buffer = ByteBuffer.wrap(new byte[] {
|
||||||
0x00, 0x00, 0x00, 0x1A, // box size
|
0x00, 0x00, 0x00, 0x1A, // box size
|
||||||
0x73, 0x67, 0x70, 0x64, // "sgpd"
|
0x73, 0x67, 0x70, 0x64, // "sgpd"
|
||||||
0x01, 0x00, 0x00, 0x00, // box flags (unknown flag sets)
|
0x01, 0x00, 0x00, 0x00, // box flags (unknown flag sets)
|
||||||
|
|
|
@ -145,10 +145,10 @@ public class OggFromWebMWriter implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void build() throws IOException {
|
public void build() throws IOException {
|
||||||
float resolution;
|
final float resolution;
|
||||||
SimpleBlock bloq;
|
SimpleBlock bloq;
|
||||||
ByteBuffer header = ByteBuffer.allocate(27 + (255 * 255));
|
final ByteBuffer header = ByteBuffer.allocate(27 + (255 * 255));
|
||||||
ByteBuffer page = ByteBuffer.allocate(64 * 1024);
|
final ByteBuffer page = ByteBuffer.allocate(64 * 1024);
|
||||||
|
|
||||||
header.order(ByteOrder.LITTLE_ENDIAN);
|
header.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ public class OggFromWebMWriter implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* step 3: create packet with metadata */
|
/* step 3: create packet with metadata */
|
||||||
byte[] buffer = makeMetadata();
|
final byte[] buffer = makeMetadata();
|
||||||
if (buffer != null) {
|
if (buffer != null) {
|
||||||
addPacketSegment(buffer.length);
|
addPacketSegment(buffer.length);
|
||||||
makePacketheader(0x00, header, buffer);
|
makePacketheader(0x00, header, buffer);
|
||||||
|
@ -194,7 +194,7 @@ public class OggFromWebMWriter implements Closeable {
|
||||||
bloq = getNextBlock();
|
bloq = getNextBlock();
|
||||||
|
|
||||||
if (bloq != null && addPacketSegment(bloq)) {
|
if (bloq != null && addPacketSegment(bloq)) {
|
||||||
int pos = page.position();
|
final int pos = page.position();
|
||||||
//noinspection ResultOfMethodCallIgnored
|
//noinspection ResultOfMethodCallIgnored
|
||||||
bloq.data.read(page.array(), pos, bloq.dataSize);
|
bloq.data.read(page.array(), pos, bloq.dataSize);
|
||||||
page.position(pos + bloq.dataSize);
|
page.position(pos + bloq.dataSize);
|
||||||
|
@ -334,10 +334,10 @@ public class OggFromWebMWriter implements Closeable {
|
||||||
|
|
||||||
private float getSampleFrequencyFromTrack(final byte[] bMetadata) {
|
private float getSampleFrequencyFromTrack(final byte[] bMetadata) {
|
||||||
// hardcoded way
|
// hardcoded way
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(bMetadata);
|
final ByteBuffer buffer = ByteBuffer.wrap(bMetadata);
|
||||||
|
|
||||||
while (buffer.remaining() >= 6) {
|
while (buffer.remaining() >= 6) {
|
||||||
int id = buffer.getShort() & 0xFFFF;
|
final int id = buffer.getShort() & 0xFFFF;
|
||||||
if (id == 0x0000B584) {
|
if (id == 0x0000B584) {
|
||||||
return buffer.getFloat();
|
return buffer.getFloat();
|
||||||
}
|
}
|
||||||
|
@ -353,7 +353,7 @@ public class OggFromWebMWriter implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean addPacketSegment(final SimpleBlock block) {
|
private boolean addPacketSegment(final SimpleBlock block) {
|
||||||
long timestamp = block.absoluteTimeCodeNs + webmTrack.codecDelay;
|
final long timestamp = block.absoluteTimeCodeNs + webmTrack.codecDelay;
|
||||||
|
|
||||||
if (timestamp >= segmentTableNextTimestamp) {
|
if (timestamp >= segmentTableNextTimestamp) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -368,7 +368,7 @@ public class OggFromWebMWriter implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
int available = (segmentTable.length - segmentTableSize) * 255;
|
int available = (segmentTable.length - segmentTableSize) * 255;
|
||||||
boolean extra = (size % 255) == 0;
|
final boolean extra = (size % 255) == 0;
|
||||||
|
|
||||||
if (extra) {
|
if (extra) {
|
||||||
// add a zero byte entry in the table
|
// add a zero byte entry in the table
|
||||||
|
@ -396,7 +396,7 @@ public class OggFromWebMWriter implements Closeable {
|
||||||
for (int i = 0; i < 0x100; i++) {
|
for (int i = 0; i < 0x100; i++) {
|
||||||
int crc = i << 24;
|
int crc = i << 24;
|
||||||
for (int j = 0; j < 8; j++) {
|
for (int j = 0; j < 8; j++) {
|
||||||
long b = crc >>> 31;
|
final long b = crc >>> 31;
|
||||||
crc <<= 1;
|
crc <<= 1;
|
||||||
crc ^= (int) (0x100000000L - b) & 0x04c11db7;
|
crc ^= (int) (0x100000000L - b) & 0x04c11db7;
|
||||||
}
|
}
|
||||||
|
@ -407,7 +407,7 @@ public class OggFromWebMWriter implements Closeable {
|
||||||
private int calcCrc32(final int initialCrc, final byte[] buffer, final int size) {
|
private int calcCrc32(final int initialCrc, final byte[] buffer, final int size) {
|
||||||
int crc = initialCrc;
|
int crc = initialCrc;
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
int reg = (crc >>> 24) & 0xff;
|
final int reg = (crc >>> 24) & 0xff;
|
||||||
crc = (crc << 8) ^ crc32Table[reg ^ (buffer[i] & 0xff)];
|
crc = (crc << 8) ^ crc32Table[reg ^ (buffer[i] & 0xff)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,23 +65,23 @@ public class SrtFromTtmlWriter {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// parse XML
|
// parse XML
|
||||||
byte[] buffer = new byte[(int) ttml.available()];
|
final byte[] buffer = new byte[(int) ttml.available()];
|
||||||
ttml.read(buffer);
|
ttml.read(buffer);
|
||||||
Document doc = Jsoup.parse(new ByteArrayInputStream(buffer), "UTF-8", "",
|
final Document doc = Jsoup.parse(new ByteArrayInputStream(buffer), "UTF-8", "",
|
||||||
Parser.xmlParser());
|
Parser.xmlParser());
|
||||||
|
|
||||||
StringBuilder text = new StringBuilder(128);
|
final StringBuilder text = new StringBuilder(128);
|
||||||
Elements paragraphList = doc.select("body > div > p");
|
final Elements paragraphList = doc.select("body > div > p");
|
||||||
|
|
||||||
// check if has frames
|
// check if has frames
|
||||||
if (paragraphList.size() < 1) {
|
if (paragraphList.size() < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Element paragraph : paragraphList) {
|
for (final Element paragraph : paragraphList) {
|
||||||
text.setLength(0);
|
text.setLength(0);
|
||||||
|
|
||||||
for (Node children : paragraph.childNodes()) {
|
for (final Node children : paragraph.childNodes()) {
|
||||||
if (children instanceof TextNode) {
|
if (children instanceof TextNode) {
|
||||||
text.append(((TextNode) children).text());
|
text.append(((TextNode) children).text());
|
||||||
} else if (children instanceof Element
|
} else if (children instanceof Element
|
||||||
|
@ -94,8 +94,8 @@ public class SrtFromTtmlWriter {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String begin = getTimestamp(paragraph, "begin");
|
final String begin = getTimestamp(paragraph, "begin");
|
||||||
String end = getTimestamp(paragraph, "end");
|
final String end = getTimestamp(paragraph, "end");
|
||||||
|
|
||||||
writeFrame(begin, end, text);
|
writeFrame(begin, end, text);
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class WebMReader {
|
||||||
|
|
||||||
ensure(segment.ref);
|
ensure(segment.ref);
|
||||||
// WARNING: track cannot be the same or have different index in new segments
|
// WARNING: track cannot be the same or have different index in new segments
|
||||||
Element elem = untilElement(null, ID_SEGMENT);
|
final Element elem = untilElement(null, ID_SEGMENT);
|
||||||
if (elem == null) {
|
if (elem == null) {
|
||||||
done = true;
|
done = true;
|
||||||
return null;
|
return null;
|
||||||
|
@ -113,7 +113,7 @@ public class WebMReader {
|
||||||
int length = (int) parent.contentSize;
|
int length = (int) parent.contentSize;
|
||||||
long value = 0;
|
long value = 0;
|
||||||
while (length-- > 0) {
|
while (length-- > 0) {
|
||||||
int read = stream.read();
|
final int read = stream.read();
|
||||||
if (read == -1) {
|
if (read == -1) {
|
||||||
throw new EOFException();
|
throw new EOFException();
|
||||||
}
|
}
|
||||||
|
@ -127,9 +127,9 @@ public class WebMReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] readBlob(final Element parent) throws IOException {
|
private byte[] readBlob(final Element parent) throws IOException {
|
||||||
long length = parent.contentSize;
|
final long length = parent.contentSize;
|
||||||
byte[] buffer = new byte[(int) length];
|
final byte[] buffer = new byte[(int) length];
|
||||||
int read = stream.read(buffer);
|
final int read = stream.read(buffer);
|
||||||
if (read < length) {
|
if (read < length) {
|
||||||
throw new EOFException();
|
throw new EOFException();
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ public class WebMReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Element readElement() throws IOException {
|
private Element readElement() throws IOException {
|
||||||
Element elem = new Element();
|
final Element elem = new Element();
|
||||||
elem.offset = stream.position();
|
elem.offset = stream.position();
|
||||||
elem.type = (int) readEncodedNumber();
|
elem.type = (int) readEncodedNumber();
|
||||||
elem.contentSize = readEncodedNumber();
|
elem.contentSize = readEncodedNumber();
|
||||||
|
@ -178,7 +178,7 @@ public class WebMReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Element readElement(final int expected) throws IOException {
|
private Element readElement(final int expected) throws IOException {
|
||||||
Element elem = readElement();
|
final Element elem = readElement();
|
||||||
if (expected != 0 && elem.type != expected) {
|
if (expected != 0 && elem.type != expected) {
|
||||||
throw new NoSuchElementException("expected " + elementID(expected)
|
throw new NoSuchElementException("expected " + elementID(expected)
|
||||||
+ " found " + elementID(elem.type));
|
+ " found " + elementID(elem.type));
|
||||||
|
@ -194,7 +194,7 @@ public class WebMReader {
|
||||||
if (expected.length < 1) {
|
if (expected.length < 1) {
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
for (int type : expected) {
|
for (final int type : expected) {
|
||||||
if (elem.type == type) {
|
if (elem.type == type) {
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ public class WebMReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensure(final Element ref) throws IOException {
|
private void ensure(final Element ref) throws IOException {
|
||||||
long skip = (ref.offset + ref.size) - stream.position();
|
final long skip = (ref.offset + ref.size) - stream.position();
|
||||||
|
|
||||||
if (skip == 0) {
|
if (skip == 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -249,7 +249,7 @@ public class WebMReader {
|
||||||
|
|
||||||
private Info readInfo(final Element ref) throws IOException {
|
private Info readInfo(final Element ref) throws IOException {
|
||||||
Element elem;
|
Element elem;
|
||||||
Info info = new Info();
|
final Info info = new Info();
|
||||||
|
|
||||||
while ((elem = untilElement(ref, ID_TIMECODE_SCALE, ID_DURATION)) != null) {
|
while ((elem = untilElement(ref, ID_TIMECODE_SCALE, ID_DURATION)) != null) {
|
||||||
switch (elem.type) {
|
switch (elem.type) {
|
||||||
|
@ -272,7 +272,7 @@ public class WebMReader {
|
||||||
|
|
||||||
private Segment readSegment(final Element ref, final int trackLacingExpected,
|
private Segment readSegment(final Element ref, final int trackLacingExpected,
|
||||||
final boolean metadataExpected) throws IOException {
|
final boolean metadataExpected) throws IOException {
|
||||||
Segment obj = new Segment(ref);
|
final Segment obj = new Segment(ref);
|
||||||
Element elem;
|
Element elem;
|
||||||
while ((elem = untilElement(ref, ID_INFO, ID_TRACKS, ID_CLUSTER)) != null) {
|
while ((elem = untilElement(ref, ID_INFO, ID_TRACKS, ID_CLUSTER)) != null) {
|
||||||
if (elem.type == ID_CLUSTER) {
|
if (elem.type == ID_CLUSTER) {
|
||||||
|
@ -300,11 +300,11 @@ public class WebMReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private WebMTrack[] readTracks(final Element ref, final int lacingExpected) throws IOException {
|
private WebMTrack[] readTracks(final Element ref, final int lacingExpected) throws IOException {
|
||||||
ArrayList<WebMTrack> trackEntries = new ArrayList<>(2);
|
final ArrayList<WebMTrack> trackEntries = new ArrayList<>(2);
|
||||||
Element elemTrackEntry;
|
Element elemTrackEntry;
|
||||||
|
|
||||||
while ((elemTrackEntry = untilElement(ref, ID_TRACK_ENTRY)) != null) {
|
while ((elemTrackEntry = untilElement(ref, ID_TRACK_ENTRY)) != null) {
|
||||||
WebMTrack entry = new WebMTrack();
|
final WebMTrack entry = new WebMTrack();
|
||||||
boolean drop = false;
|
boolean drop = false;
|
||||||
Element elem;
|
Element elem;
|
||||||
while ((elem = untilElement(elemTrackEntry)) != null) {
|
while ((elem = untilElement(elemTrackEntry)) != null) {
|
||||||
|
@ -348,10 +348,10 @@ public class WebMReader {
|
||||||
ensure(elemTrackEntry);
|
ensure(elemTrackEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
WebMTrack[] entries = new WebMTrack[trackEntries.size()];
|
final WebMTrack[] entries = new WebMTrack[trackEntries.size()];
|
||||||
trackEntries.toArray(entries);
|
trackEntries.toArray(entries);
|
||||||
|
|
||||||
for (WebMTrack entry : entries) {
|
for (final WebMTrack entry : entries) {
|
||||||
switch (entry.trackType) {
|
switch (entry.trackType) {
|
||||||
case 1:
|
case 1:
|
||||||
entry.kind = TrackKind.Video;
|
entry.kind = TrackKind.Video;
|
||||||
|
@ -369,7 +369,7 @@ public class WebMReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private SimpleBlock readSimpleBlock(final Element ref) throws IOException {
|
private SimpleBlock readSimpleBlock(final Element ref) throws IOException {
|
||||||
SimpleBlock obj = new SimpleBlock(ref);
|
final SimpleBlock obj = new SimpleBlock(ref);
|
||||||
obj.trackNumber = readEncodedNumber();
|
obj.trackNumber = readEncodedNumber();
|
||||||
obj.relativeTimeCode = stream.readShort();
|
obj.relativeTimeCode = stream.readShort();
|
||||||
obj.flags = (byte) stream.read();
|
obj.flags = (byte) stream.read();
|
||||||
|
@ -385,9 +385,9 @@ public class WebMReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Cluster readCluster(final Element ref) throws IOException {
|
private Cluster readCluster(final Element ref) throws IOException {
|
||||||
Cluster obj = new Cluster(ref);
|
final Cluster obj = new Cluster(ref);
|
||||||
|
|
||||||
Element elem = untilElement(ref, ID_TIMECODE);
|
final Element elem = untilElement(ref, ID_TIMECODE);
|
||||||
if (elem == null) {
|
if (elem == null) {
|
||||||
throw new NoSuchElementException("Cluster at " + String.valueOf(ref.offset)
|
throw new NoSuchElementException("Cluster at " + String.valueOf(ref.offset)
|
||||||
+ " without Timecode element");
|
+ " without Timecode element");
|
||||||
|
@ -443,7 +443,7 @@ public class WebMReader {
|
||||||
}
|
}
|
||||||
ensure(segment.currentCluster);
|
ensure(segment.currentCluster);
|
||||||
|
|
||||||
Element elem = untilElement(segment.ref, ID_CLUSTER);
|
final Element elem = untilElement(segment.ref, ID_CLUSTER);
|
||||||
if (elem == null) {
|
if (elem == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ public class WebMWriter implements Closeable {
|
||||||
done = true;
|
done = true;
|
||||||
parsed = true;
|
parsed = true;
|
||||||
|
|
||||||
for (SharpStream src : sourceTracks) {
|
for (final SharpStream src : sourceTracks) {
|
||||||
src.close();
|
src.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,12 +128,12 @@ public class WebMWriter implements Closeable {
|
||||||
|
|
||||||
makeEBML(out);
|
makeEBML(out);
|
||||||
|
|
||||||
long offsetSegmentSizeSet = written + 5;
|
final long offsetSegmentSizeSet = written + 5;
|
||||||
long offsetInfoDurationSet = written + 94;
|
final long offsetInfoDurationSet = written + 94;
|
||||||
long offsetClusterSet = written + 58;
|
final long offsetClusterSet = written + 58;
|
||||||
long offsetCuesSet = written + 75;
|
final long offsetCuesSet = written + 75;
|
||||||
|
|
||||||
ArrayList<byte[]> listBuffer = new ArrayList<>(4);
|
final ArrayList<byte[]> listBuffer = new ArrayList<>(4);
|
||||||
|
|
||||||
/* segment */
|
/* segment */
|
||||||
listBuffer.add(new byte[]{
|
listBuffer.add(new byte[]{
|
||||||
|
@ -141,7 +141,7 @@ public class WebMWriter implements Closeable {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00// segment content size
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00// segment content size
|
||||||
});
|
});
|
||||||
|
|
||||||
long segmentOffset = written + listBuffer.get(0).length;
|
final long segmentOffset = written + listBuffer.get(0).length;
|
||||||
|
|
||||||
/* seek head */
|
/* seek head */
|
||||||
listBuffer.add(new byte[]{
|
listBuffer.add(new byte[]{
|
||||||
|
@ -177,11 +177,11 @@ public class WebMWriter implements Closeable {
|
||||||
dump(listBuffer, out);
|
dump(listBuffer, out);
|
||||||
|
|
||||||
// reserve space for Cues element
|
// reserve space for Cues element
|
||||||
long cueOffset = written;
|
final long cueOffset = written;
|
||||||
makeEbmlVoid(out, CUE_RESERVE_SIZE, true);
|
makeEbmlVoid(out, CUE_RESERVE_SIZE, true);
|
||||||
|
|
||||||
int[] defaultSampleDuration = new int[infoTracks.length];
|
final int[] defaultSampleDuration = new int[infoTracks.length];
|
||||||
long[] duration = new long[infoTracks.length];
|
final long[] duration = new long[infoTracks.length];
|
||||||
|
|
||||||
for (int i = 0; i < infoTracks.length; i++) {
|
for (int i = 0; i < infoTracks.length; i++) {
|
||||||
if (infoTracks[i].defaultDuration < 0) {
|
if (infoTracks[i].defaultDuration < 0) {
|
||||||
|
@ -194,9 +194,9 @@ public class WebMWriter implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select a track for the cue
|
// Select a track for the cue
|
||||||
int cuesForTrackId = selectTrackForCue();
|
final int cuesForTrackId = selectTrackForCue();
|
||||||
long nextCueTime = infoTracks[cuesForTrackId].trackType == 1 ? -1 : 0;
|
long nextCueTime = infoTracks[cuesForTrackId].trackType == 1 ? -1 : 0;
|
||||||
ArrayList<KeyFrame> keyFrames = new ArrayList<>(32);
|
final ArrayList<KeyFrame> keyFrames = new ArrayList<>(32);
|
||||||
|
|
||||||
int firstClusterOffset = (int) written;
|
int firstClusterOffset = (int) written;
|
||||||
long currentClusterOffset = makeCluster(out, 0, 0, true);
|
long currentClusterOffset = makeCluster(out, 0, 0, true);
|
||||||
|
@ -213,7 +213,7 @@ public class WebMWriter implements Closeable {
|
||||||
blockWritten = 0;
|
blockWritten = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < readers.length) {
|
while (i < readers.length) {
|
||||||
Block bloq = getNextBlockFrom(i);
|
final Block bloq = getNextBlockFrom(i);
|
||||||
if (bloq == null) {
|
if (bloq == null) {
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
|
@ -272,7 +272,7 @@ public class WebMWriter implements Closeable {
|
||||||
|
|
||||||
makeCluster(out, -1, currentClusterOffset, false);
|
makeCluster(out, -1, currentClusterOffset, false);
|
||||||
|
|
||||||
long segmentSize = written - offsetSegmentSizeSet - 7;
|
final long segmentSize = written - offsetSegmentSizeSet - 7;
|
||||||
|
|
||||||
/* Segment size */
|
/* Segment size */
|
||||||
seekTo(out, offsetSegmentSizeSet);
|
seekTo(out, offsetSegmentSizeSet);
|
||||||
|
@ -303,8 +303,8 @@ public class WebMWriter implements Closeable {
|
||||||
short cueSize = 0;
|
short cueSize = 0;
|
||||||
dump(new byte[]{0x1c, 0x53, (byte) 0xbb, 0x6b, 0x20, 0x00, 0x00}, out); // header size is 7
|
dump(new byte[]{0x1c, 0x53, (byte) 0xbb, 0x6b, 0x20, 0x00, 0x00}, out); // header size is 7
|
||||||
|
|
||||||
for (KeyFrame keyFrame : keyFrames) {
|
for (final KeyFrame keyFrame : keyFrames) {
|
||||||
int size = makeCuePoint(cuesForTrackId, keyFrame, outBuffer);
|
final int size = makeCuePoint(cuesForTrackId, keyFrame, outBuffer);
|
||||||
|
|
||||||
if ((cueSize + size + 7 + MINIMUM_EBML_VOID_SIZE) > CUE_RESERVE_SIZE) {
|
if ((cueSize + size + 7 + MINIMUM_EBML_VOID_SIZE) > CUE_RESERVE_SIZE) {
|
||||||
break; // no space left
|
break; // no space left
|
||||||
|
@ -323,7 +323,7 @@ public class WebMWriter implements Closeable {
|
||||||
/* seek head, seek for cues element */
|
/* seek head, seek for cues element */
|
||||||
writeInt(out, offsetCuesSet, (int) (cueOffset - segmentOffset));
|
writeInt(out, offsetCuesSet, (int) (cueOffset - segmentOffset));
|
||||||
|
|
||||||
for (ClusterInfo cluster : clustersOffsetsSizes) {
|
for (final ClusterInfo cluster : clustersOffsetsSizes) {
|
||||||
writeInt(out, cluster.offset, cluster.size | 0x10000000);
|
writeInt(out, cluster.offset, cluster.size | 0x10000000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,13 +344,13 @@ public class WebMWriter implements Closeable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleBlock res = readersCluster[internalTrackId].getNextSimpleBlock();
|
final SimpleBlock res = readersCluster[internalTrackId].getNextSimpleBlock();
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
readersCluster[internalTrackId] = null;
|
readersCluster[internalTrackId] = null;
|
||||||
return new Block(); // fake block to indicate the end of the cluster
|
return new Block(); // fake block to indicate the end of the cluster
|
||||||
}
|
}
|
||||||
|
|
||||||
Block bloq = new Block();
|
final Block bloq = new Block();
|
||||||
bloq.data = res.data;
|
bloq.data = res.data;
|
||||||
bloq.dataSize = res.dataSize;
|
bloq.dataSize = res.dataSize;
|
||||||
bloq.trackNumber = internalTrackId;
|
bloq.trackNumber = internalTrackId;
|
||||||
|
@ -384,13 +384,13 @@ public class WebMWriter implements Closeable {
|
||||||
|
|
||||||
private void writeBlock(final SharpStream stream, final Block bloq, final long clusterTimecode)
|
private void writeBlock(final SharpStream stream, final Block bloq, final long clusterTimecode)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
long relativeTimeCode = bloq.absoluteTimecode - clusterTimecode;
|
final long relativeTimeCode = bloq.absoluteTimecode - clusterTimecode;
|
||||||
|
|
||||||
if (relativeTimeCode < Short.MIN_VALUE || relativeTimeCode > Short.MAX_VALUE) {
|
if (relativeTimeCode < Short.MIN_VALUE || relativeTimeCode > Short.MAX_VALUE) {
|
||||||
throw new IndexOutOfBoundsException("SimpleBlock timecode overflow.");
|
throw new IndexOutOfBoundsException("SimpleBlock timecode overflow.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<byte[]> listBuffer = new ArrayList<>(5);
|
final ArrayList<byte[]> listBuffer = new ArrayList<>(5);
|
||||||
listBuffer.add(new byte[]{(byte) 0xa3});
|
listBuffer.add(new byte[]{(byte) 0xa3});
|
||||||
listBuffer.add(null); // block size
|
listBuffer.add(null); // block size
|
||||||
listBuffer.add(encode(bloq.trackNumber + 1, false));
|
listBuffer.add(encode(bloq.trackNumber + 1, false));
|
||||||
|
@ -458,7 +458,7 @@ public class WebMWriter implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<byte[]> makeTracks() {
|
private ArrayList<byte[]> makeTracks() {
|
||||||
ArrayList<byte[]> buffer = new ArrayList<>(1);
|
final ArrayList<byte[]> buffer = new ArrayList<>(1);
|
||||||
buffer.add(new byte[]{0x16, 0x54, (byte) 0xae, 0x6b});
|
buffer.add(new byte[]{0x16, 0x54, (byte) 0xae, 0x6b});
|
||||||
buffer.add(null);
|
buffer.add(null);
|
||||||
|
|
||||||
|
@ -470,8 +470,8 @@ public class WebMWriter implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<byte[]> makeTrackEntry(final int internalTrackId, final WebMTrack track) {
|
private ArrayList<byte[]> makeTrackEntry(final int internalTrackId, final WebMTrack track) {
|
||||||
byte[] id = encode(internalTrackId + 1, true);
|
final byte[] id = encode(internalTrackId + 1, true);
|
||||||
ArrayList<byte[]> buffer = new ArrayList<>(12);
|
final ArrayList<byte[]> buffer = new ArrayList<>(12);
|
||||||
|
|
||||||
/* track */
|
/* track */
|
||||||
buffer.add(new byte[]{(byte) 0xae});
|
buffer.add(new byte[]{(byte) 0xae});
|
||||||
|
@ -536,7 +536,7 @@ public class WebMWriter implements Closeable {
|
||||||
|
|
||||||
private int makeCuePoint(final int internalTrackId, final KeyFrame keyFrame,
|
private int makeCuePoint(final int internalTrackId, final KeyFrame keyFrame,
|
||||||
final byte[] buffer) {
|
final byte[] buffer) {
|
||||||
ArrayList<byte[]> cue = new ArrayList<>(5);
|
final ArrayList<byte[]> cue = new ArrayList<>(5);
|
||||||
|
|
||||||
/* CuePoint */
|
/* CuePoint */
|
||||||
cue.add(new byte[]{(byte) 0xbb});
|
cue.add(new byte[]{(byte) 0xbb});
|
||||||
|
@ -552,7 +552,7 @@ public class WebMWriter implements Closeable {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
lengthFor(cue);
|
lengthFor(cue);
|
||||||
|
|
||||||
for (byte[] buff : cue) {
|
for (final byte[] buff : cue) {
|
||||||
System.arraycopy(buff, 0, buffer, size, buff.length);
|
System.arraycopy(buff, 0, buffer, size, buff.length);
|
||||||
size += buff.length;
|
size += buff.length;
|
||||||
}
|
}
|
||||||
|
@ -562,7 +562,7 @@ public class WebMWriter implements Closeable {
|
||||||
|
|
||||||
private ArrayList<byte[]> makeCueTrackPosition(final int internalTrackId,
|
private ArrayList<byte[]> makeCueTrackPosition(final int internalTrackId,
|
||||||
final KeyFrame keyFrame) {
|
final KeyFrame keyFrame) {
|
||||||
ArrayList<byte[]> buffer = new ArrayList<>(8);
|
final ArrayList<byte[]> buffer = new ArrayList<>(8);
|
||||||
|
|
||||||
/* CueTrackPositions */
|
/* CueTrackPositions */
|
||||||
buffer.add(new byte[]{(byte) 0xb7});
|
buffer.add(new byte[]{(byte) 0xb7});
|
||||||
|
@ -598,7 +598,7 @@ public class WebMWriter implements Closeable {
|
||||||
if (wipe) {
|
if (wipe) {
|
||||||
size -= 4;
|
size -= 4;
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
int write = Math.min(size, outBuffer.length);
|
final int write = Math.min(size, outBuffer.length);
|
||||||
dump(outBuffer, write, out);
|
dump(outBuffer, write, out);
|
||||||
size -= write;
|
size -= write;
|
||||||
}
|
}
|
||||||
|
@ -617,7 +617,7 @@ public class WebMWriter implements Closeable {
|
||||||
|
|
||||||
private void dump(final ArrayList<byte[]> buffers, final SharpStream stream)
|
private void dump(final ArrayList<byte[]> buffers, final SharpStream stream)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
for (byte[] buffer : buffers) {
|
for (final byte[] buffer : buffers) {
|
||||||
stream.write(buffer);
|
stream.write(buffer);
|
||||||
written += buffer.length;
|
written += buffer.length;
|
||||||
}
|
}
|
||||||
|
@ -649,9 +649,9 @@ public class WebMWriter implements Closeable {
|
||||||
length++;
|
length++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = withLength ? 1 : 0;
|
final int offset = withLength ? 1 : 0;
|
||||||
byte[] buffer = new byte[offset + length];
|
final byte[] buffer = new byte[offset + length];
|
||||||
long marker = (long) Math.floor((length - 1f) / 8f);
|
final long marker = (long) Math.floor((length - 1f) / 8f);
|
||||||
|
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
for (int i = length - 1; i >= 0; i--, shift += 8) {
|
for (int i = length - 1; i >= 0; i--, shift += 8) {
|
||||||
|
@ -670,10 +670,9 @@ public class WebMWriter implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<byte[]> encode(final String value) {
|
private ArrayList<byte[]> encode(final String value) {
|
||||||
byte[] str;
|
final byte[] str = value.getBytes(StandardCharsets.UTF_8); // or use "utf-8"
|
||||||
str = value.getBytes(StandardCharsets.UTF_8); // or use "utf-8"
|
|
||||||
|
|
||||||
ArrayList<byte[]> buffer = new ArrayList<>(2);
|
final ArrayList<byte[]> buffer = new ArrayList<>(2);
|
||||||
buffer.add(encode(str.length, false));
|
buffer.add(encode(str.length, false));
|
||||||
buffer.add(str);
|
buffer.add(str);
|
||||||
|
|
||||||
|
@ -700,7 +699,7 @@ public class WebMWriter implements Closeable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int kind;
|
final int kind;
|
||||||
if (audioTracks == infoTracks.length) {
|
if (audioTracks == infoTracks.length) {
|
||||||
kind = 2;
|
kind = 2;
|
||||||
} else if (videoTracks == infoTracks.length) {
|
} else if (videoTracks == infoTracks.length) {
|
||||||
|
|
|
@ -84,11 +84,11 @@ public final class AnimationUtils {
|
||||||
String id;
|
String id;
|
||||||
try {
|
try {
|
||||||
id = view.getResources().getResourceEntryName(view.getId());
|
id = view.getResources().getResourceEntryName(view.getId());
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
id = view.getId() + "";
|
id = view.getId() + "";
|
||||||
}
|
}
|
||||||
|
|
||||||
String msg = String.format("%8s → [%s:%s] [%s %s:%s] execOnEnd=%s", enterOrExit,
|
final String msg = String.format("%8s → [%s:%s] [%s %s:%s] execOnEnd=%s", enterOrExit,
|
||||||
view.getClass().getSimpleName(), id, animationType, duration, delay, execOnEnd);
|
view.getClass().getSimpleName(), id, animationType, duration, delay, execOnEnd);
|
||||||
Log.d(TAG, "animateView()" + msg);
|
Log.d(TAG, "animateView()" + msg);
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ public final class AnimationUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
final int[][] empty = new int[][]{new int[0]};
|
final int[][] empty = new int[][]{new int[0]};
|
||||||
ValueAnimator viewPropertyAnimator = ValueAnimator
|
final ValueAnimator viewPropertyAnimator = ValueAnimator
|
||||||
.ofObject(new ArgbEvaluator(), colorStart, colorEnd);
|
.ofObject(new ArgbEvaluator(), colorStart, colorEnd);
|
||||||
viewPropertyAnimator.setInterpolator(new FastOutSlowInInterpolator());
|
viewPropertyAnimator.setInterpolator(new FastOutSlowInInterpolator());
|
||||||
viewPropertyAnimator.setDuration(duration);
|
viewPropertyAnimator.setDuration(duration);
|
||||||
|
@ -201,7 +201,7 @@ public final class AnimationUtils {
|
||||||
+ "colorStart = [" + colorStart + "], colorEnd = [" + colorEnd + "]");
|
+ "colorStart = [" + colorStart + "], colorEnd = [" + colorEnd + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueAnimator viewPropertyAnimator = ValueAnimator
|
final ValueAnimator viewPropertyAnimator = ValueAnimator
|
||||||
.ofObject(new ArgbEvaluator(), colorStart, colorEnd);
|
.ofObject(new ArgbEvaluator(), colorStart, colorEnd);
|
||||||
viewPropertyAnimator.setInterpolator(new FastOutSlowInInterpolator());
|
viewPropertyAnimator.setInterpolator(new FastOutSlowInInterpolator());
|
||||||
viewPropertyAnimator.setDuration(duration);
|
viewPropertyAnimator.setDuration(duration);
|
||||||
|
@ -233,7 +233,7 @@ public final class AnimationUtils {
|
||||||
+ "from " + height + " to → " + targetHeight + " in: " + view);
|
+ "from " + height + " to → " + targetHeight + " in: " + view);
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueAnimator animator = ValueAnimator.ofFloat(height, targetHeight);
|
final ValueAnimator animator = ValueAnimator.ofFloat(height, targetHeight);
|
||||||
animator.setInterpolator(new FastOutSlowInInterpolator());
|
animator.setInterpolator(new FastOutSlowInInterpolator());
|
||||||
animator.setDuration(duration);
|
animator.setDuration(duration);
|
||||||
animator.addUpdateListener(animation -> {
|
animator.addUpdateListener(animation -> {
|
||||||
|
@ -462,7 +462,7 @@ public final class AnimationUtils {
|
||||||
public static void slideUp(final View view, final long duration, final long delay,
|
public static void slideUp(final View view, final long duration, final long delay,
|
||||||
@FloatRange(from = 0.0f, to = 1.0f)
|
@FloatRange(from = 0.0f, to = 1.0f)
|
||||||
final float translationPercent) {
|
final float translationPercent) {
|
||||||
int translationY = (int) (view.getResources().getDisplayMetrics().heightPixels
|
final int translationY = (int) (view.getResources().getDisplayMetrics().heightPixels
|
||||||
* (translationPercent));
|
* (translationPercent));
|
||||||
|
|
||||||
view.animate().setListener(null).cancel();
|
view.animate().setListener(null).cancel();
|
||||||
|
|
|
@ -14,14 +14,14 @@ public final class BitmapUtils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
float sourceWidth = inputBitmap.getWidth();
|
final float sourceWidth = inputBitmap.getWidth();
|
||||||
float sourceHeight = inputBitmap.getHeight();
|
final float sourceHeight = inputBitmap.getHeight();
|
||||||
|
|
||||||
float xScale = newWidth / sourceWidth;
|
final float xScale = newWidth / sourceWidth;
|
||||||
float yScale = newHeight / sourceHeight;
|
final float yScale = newHeight / sourceHeight;
|
||||||
|
|
||||||
float newXScale;
|
final float newXScale;
|
||||||
float newYScale;
|
final float newYScale;
|
||||||
|
|
||||||
if (yScale > xScale) {
|
if (yScale > xScale) {
|
||||||
newXScale = xScale / yScale;
|
newXScale = xScale / yScale;
|
||||||
|
@ -31,15 +31,14 @@ public final class BitmapUtils {
|
||||||
newYScale = yScale / xScale;
|
newYScale = yScale / xScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
float scaledWidth = newXScale * sourceWidth;
|
final float scaledWidth = newXScale * sourceWidth;
|
||||||
float scaledHeight = newYScale * sourceHeight;
|
final float scaledHeight = newYScale * sourceHeight;
|
||||||
|
|
||||||
int left = (int) ((sourceWidth - scaledWidth) / 2);
|
final int left = (int) ((sourceWidth - scaledWidth) / 2);
|
||||||
int top = (int) ((sourceHeight - scaledHeight) / 2);
|
final int top = (int) ((sourceHeight - scaledHeight) / 2);
|
||||||
int width = (int) scaledWidth;
|
final int width = (int) scaledWidth;
|
||||||
int height = (int) scaledHeight;
|
final int height = (int) scaledHeight;
|
||||||
|
|
||||||
return Bitmap.createBitmap(inputBitmap, left, top, width, height);
|
return Bitmap.createBitmap(inputBitmap, left, top, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,12 +37,12 @@ public class CommentTextOnTouchListener implements View.OnTouchListener {
|
||||||
if (!(v instanceof TextView)) {
|
if (!(v instanceof TextView)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
TextView widget = (TextView) v;
|
final TextView widget = (TextView) v;
|
||||||
Object text = widget.getText();
|
final Object text = widget.getText();
|
||||||
if (text instanceof Spanned) {
|
if (text instanceof Spanned) {
|
||||||
Spannable buffer = (Spannable) text;
|
final Spannable buffer = (Spannable) text;
|
||||||
|
|
||||||
int action = event.getAction();
|
final int action = event.getAction();
|
||||||
|
|
||||||
if (action == MotionEvent.ACTION_UP
|
if (action == MotionEvent.ACTION_UP
|
||||||
|| action == MotionEvent.ACTION_DOWN) {
|
|| action == MotionEvent.ACTION_DOWN) {
|
||||||
|
@ -55,11 +55,11 @@ public class CommentTextOnTouchListener implements View.OnTouchListener {
|
||||||
x += widget.getScrollX();
|
x += widget.getScrollX();
|
||||||
y += widget.getScrollY();
|
y += widget.getScrollY();
|
||||||
|
|
||||||
Layout layout = widget.getLayout();
|
final Layout layout = widget.getLayout();
|
||||||
int line = layout.getLineForVertical(y);
|
final int line = layout.getLineForVertical(y);
|
||||||
int off = layout.getOffsetForHorizontal(line, x);
|
final int off = layout.getOffsetForHorizontal(line, x);
|
||||||
|
|
||||||
ClickableSpan[] link = buffer.getSpans(off, off,
|
final ClickableSpan[] link = buffer.getSpans(off, off,
|
||||||
ClickableSpan.class);
|
ClickableSpan.class);
|
||||||
|
|
||||||
if (link.length != 0) {
|
if (link.length != 0) {
|
||||||
|
@ -86,17 +86,17 @@ public class CommentTextOnTouchListener implements View.OnTouchListener {
|
||||||
private boolean handleUrl(final Context context, final URLSpan urlSpan) {
|
private boolean handleUrl(final Context context, final URLSpan urlSpan) {
|
||||||
String url = urlSpan.getURL();
|
String url = urlSpan.getURL();
|
||||||
int seconds = -1;
|
int seconds = -1;
|
||||||
Matcher matcher = TIMESTAMP_PATTERN.matcher(url);
|
final Matcher matcher = TIMESTAMP_PATTERN.matcher(url);
|
||||||
if (matcher.matches()) {
|
if (matcher.matches()) {
|
||||||
url = matcher.group(1);
|
url = matcher.group(1);
|
||||||
seconds = Integer.parseInt(matcher.group(2));
|
seconds = Integer.parseInt(matcher.group(2));
|
||||||
}
|
}
|
||||||
StreamingService service;
|
final StreamingService service;
|
||||||
StreamingService.LinkType linkType;
|
final StreamingService.LinkType linkType;
|
||||||
try {
|
try {
|
||||||
service = NewPipe.getServiceByUrl(url);
|
service = NewPipe.getServiceByUrl(url);
|
||||||
linkType = service.getLinkTypeByUrl(url);
|
linkType = service.getLinkTypeByUrl(url);
|
||||||
} catch (ExtractionException e) {
|
} catch (final ExtractionException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (linkType == StreamingService.LinkType.NONE) {
|
if (linkType == StreamingService.LinkType.NONE) {
|
||||||
|
@ -112,18 +112,20 @@ public class CommentTextOnTouchListener implements View.OnTouchListener {
|
||||||
|
|
||||||
private boolean playOnPopup(final Context context, final String url,
|
private boolean playOnPopup(final Context context, final String url,
|
||||||
final StreamingService service, final int seconds) {
|
final StreamingService service, final int seconds) {
|
||||||
LinkHandlerFactory factory = service.getStreamLHFactory();
|
final LinkHandlerFactory factory = service.getStreamLHFactory();
|
||||||
String cleanUrl = null;
|
final String cleanUrl;
|
||||||
try {
|
try {
|
||||||
cleanUrl = factory.getUrl(factory.getId(url));
|
cleanUrl = factory.getUrl(factory.getId(url));
|
||||||
} catch (ParsingException e) {
|
} catch (final ParsingException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Single single = ExtractorHelper.getStreamInfo(service.getServiceId(), cleanUrl, false);
|
final Single single
|
||||||
|
= ExtractorHelper.getStreamInfo(service.getServiceId(), cleanUrl, false);
|
||||||
single.subscribeOn(Schedulers.io())
|
single.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(info -> {
|
.subscribe(info -> {
|
||||||
PlayQueue playQueue = new SinglePlayQueue((StreamInfo) info, seconds * 1000);
|
final PlayQueue playQueue
|
||||||
|
= new SinglePlayQueue((StreamInfo) info, seconds * 1000);
|
||||||
NavigationHelper.playOnPopupPlayer(context, playQueue, false);
|
NavigationHelper.playOnPopupPlayer(context, playQueue, false);
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -12,8 +12,8 @@ public final class CookieUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String concatCookies(final Collection<String> cookieStrings) {
|
public static String concatCookies(final Collection<String> cookieStrings) {
|
||||||
Set<String> cookieSet = new HashSet<>();
|
final Set<String> cookieSet = new HashSet<>();
|
||||||
for (String cookies : cookieStrings) {
|
for (final String cookies : cookieStrings) {
|
||||||
cookieSet.addAll(splitCookies(cookies));
|
cookieSet.addAll(splitCookies(cookies));
|
||||||
}
|
}
|
||||||
return TextUtils.join("; ", cookieSet).trim();
|
return TextUtils.join("; ", cookieSet).trim();
|
||||||
|
|
|
@ -27,7 +27,7 @@ public final class DeviceUtils {
|
||||||
return isTV;
|
return isTV;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageManager pm = App.getApp().getPackageManager();
|
final PackageManager pm = App.getApp().getPackageManager();
|
||||||
|
|
||||||
// from doc: https://developer.android.com/training/tv/start/hardware.html#runtime-check
|
// from doc: https://developer.android.com/training/tv/start/hardware.html#runtime-check
|
||||||
boolean isTv = ((UiModeManager) context.getSystemService(UI_MODE_SERVICE))
|
boolean isTv = ((UiModeManager) context.getSystemService(UI_MODE_SERVICE))
|
||||||
|
@ -37,7 +37,8 @@ public final class DeviceUtils {
|
||||||
|
|
||||||
// from https://stackoverflow.com/a/58932366
|
// from https://stackoverflow.com/a/58932366
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
boolean isBatteryAbsent = ((BatteryManager) context.getSystemService(BATTERY_SERVICE))
|
final boolean isBatteryAbsent
|
||||||
|
= ((BatteryManager) context.getSystemService(BATTERY_SERVICE))
|
||||||
.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) == 0;
|
.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) == 0;
|
||||||
isTv = isTv || (isBatteryAbsent
|
isTv = isTv || (isBatteryAbsent
|
||||||
&& !pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
|
&& !pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue