1
0
Fork 0
mirror of https://github.com/TeamNewPipe/NewPipe.git synced 2025-10-05 02:39:29 +02:00

Merge branch 'dev' into alang-selector

This commit is contained in:
ThetaDev 2023-04-17 23:01:07 +02:00
commit 2edc223e77
59 changed files with 214 additions and 185 deletions

View file

@ -6,6 +6,7 @@ import android.util.Log
import android.widget.Toast
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.PendingIntentCompat
import androidx.core.content.ContextCompat
import androidx.core.content.edit
import androidx.core.net.toUri
@ -19,7 +20,6 @@ import com.grack.nanojson.JsonParser
import com.grack.nanojson.JsonParserException
import org.schabi.newpipe.extractor.downloader.Response
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException
import org.schabi.newpipe.util.PendingIntentCompat
import org.schabi.newpipe.util.ReleaseVersionUtil.coerceUpdateCheckExpiry
import org.schabi.newpipe.util.ReleaseVersionUtil.isLastUpdateCheckExpired
import org.schabi.newpipe.util.ReleaseVersionUtil.isReleaseApk
@ -60,7 +60,7 @@ class NewVersionWorker(
val intent = Intent(Intent.ACTION_VIEW, apkLocationUrl?.toUri())
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val pendingIntent = PendingIntentCompat.getActivity(
applicationContext, 0, intent, 0
applicationContext, 0, intent, 0, false
)
val channelId = applicationContext.getString(R.string.app_update_notification_channel_id)
val notificationBuilder = NotificationCompat.Builder(applicationContext, channelId)

View file

@ -9,10 +9,10 @@ import android.view.View
import android.widget.Toast
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.PendingIntentCompat
import androidx.fragment.app.Fragment
import com.google.android.material.snackbar.Snackbar
import org.schabi.newpipe.R
import org.schabi.newpipe.util.PendingIntentCompat
/**
* This class contains all of the methods that should be used to let the user know that an error has
@ -118,7 +118,8 @@ class ErrorUtil {
context,
0,
getErrorActivityIntent(context, errorInfo),
PendingIntent.FLAG_UPDATE_CURRENT
PendingIntent.FLAG_UPDATE_CURRENT,
false
)
)

View file

@ -10,6 +10,7 @@ import android.os.Build
import android.provider.Settings
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.PendingIntentCompat
import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import com.squareup.picasso.Picasso
@ -19,7 +20,6 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.local.feed.service.FeedUpdateInfo
import org.schabi.newpipe.util.Localization
import org.schabi.newpipe.util.NavigationHelper
import org.schabi.newpipe.util.PendingIntentCompat
import org.schabi.newpipe.util.PicassoHelper
/**
@ -76,7 +76,8 @@ class NotificationHelper(val context: Context) {
NavigationHelper
.getChannelIntent(context, data.listInfo.serviceId, data.listInfo.url)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
0
0,
false
)
)

View file

@ -29,6 +29,7 @@ import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.PendingIntentCompat
import androidx.core.app.ServiceCompat
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Flowable
@ -42,7 +43,6 @@ import org.schabi.newpipe.extractor.ListInfo
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.ErrorResultEvent
import org.schabi.newpipe.local.feed.service.FeedEventManager.postEvent
import org.schabi.newpipe.util.PendingIntentCompat
import java.util.concurrent.TimeUnit
class FeedLoadService : Service() {
@ -152,8 +152,8 @@ class FeedLoadService : Service() {
private lateinit var notificationBuilder: NotificationCompat.Builder
private fun createNotification(): NotificationCompat.Builder {
val cancelActionIntent =
PendingIntentCompat.getBroadcast(this, NOTIFICATION_ID, Intent(ACTION_CANCEL), 0)
val cancelActionIntent = PendingIntentCompat
.getBroadcast(this, NOTIFICATION_ID, Intent(ACTION_CANCEL), 0, false)
return NotificationCompat.Builder(this, getString(R.string.notification_channel_id))
.setOngoing(true)

View file

@ -69,7 +69,6 @@ import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player.PositionInfo;
import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.source.MediaSource;
@ -77,7 +76,6 @@ import com.google.android.exoplayer2.text.CueGroup;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoSize;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target;
@ -97,6 +95,7 @@ import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.player.event.PlayerEventListener;
import org.schabi.newpipe.player.event.PlayerServiceEventListener;
import org.schabi.newpipe.player.helper.AudioReactor;
import org.schabi.newpipe.player.helper.CustomRenderersFactory;
import org.schabi.newpipe.player.helper.LoadController;
import org.schabi.newpipe.player.helper.PlayerDataSource;
import org.schabi.newpipe.player.helper.PlayerHelper;
@ -116,7 +115,6 @@ import org.schabi.newpipe.player.ui.PlayerUiList;
import org.schabi.newpipe.player.ui.PopupPlayerUi;
import org.schabi.newpipe.player.ui.VideoPlayerUi;
import org.schabi.newpipe.util.DependentPreferenceHelper;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PicassoHelper;
@ -199,7 +197,7 @@ public final class Player implements PlaybackListener, Listener {
@NonNull private final DefaultTrackSelector trackSelector;
@NonNull private final LoadController loadController;
@NonNull private final RenderersFactory renderFactory;
@NonNull private final DefaultRenderersFactory renderFactory;
@NonNull private final VideoPlaybackResolver videoResolver;
@NonNull private final AudioPlaybackResolver audioResolver;
@ -264,7 +262,16 @@ public final class Player implements PlaybackListener, Listener {
final PlayerDataSource dataSource = new PlayerDataSource(context,
new DefaultBandwidthMeter.Builder(context).build());
loadController = new LoadController();
renderFactory = new DefaultRenderersFactory(context);
renderFactory = prefs.getBoolean(
context.getString(
R.string.always_use_exoplayer_set_output_surface_workaround_key), false)
? new CustomRenderersFactory(context) : new DefaultRenderersFactory(context);
renderFactory.setEnableDecoderFallback(
prefs.getBoolean(
context.getString(
R.string.use_exoplayer_decoder_fallback_key), false));
videoResolver = new VideoPlaybackResolver(context, dataSource, getQualityResolver());
audioResolver = new AudioPlaybackResolver(context, dataSource);
@ -521,16 +528,11 @@ public final class Player implements PlaybackListener, Listener {
// Setup UIs
UIs.call(PlayerUi::initPlayer);
// enable media tunneling
if (DEBUG && PreferenceManager.getDefaultSharedPreferences(context)
// Disable media tunneling if requested by the user from ExoPlayer settings
if (!PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(context.getString(R.string.disable_media_tunneling_key), false)) {
Log.d(TAG, "[" + Util.DEVICE_DEBUG_INFO + "] "
+ "media tunneling disabled in debug preferences");
} else if (DeviceUtils.shouldSupportMediaTunneling()) {
trackSelector.setParameters(trackSelector.buildUponParameters()
.setTunnelingEnabled(true));
} else if (DEBUG) {
Log.d(TAG, "[" + Util.DEVICE_DEBUG_INFO + "] does not support media tunneling");
}
}
//endregion

View file

@ -0,0 +1,54 @@
package org.schabi.newpipe.player.helper;
import android.content.Context;
import android.os.Handler;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.mediacodec.MediaCodecAdapter;
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
import com.google.android.exoplayer2.video.MediaCodecVideoRenderer;
import com.google.android.exoplayer2.video.VideoRendererEventListener;
/**
* A {@link MediaCodecVideoRenderer} which always enable the output surface workaround that
* ExoPlayer enables on several devices which are known to implement
* {@link android.media.MediaCodec#setOutputSurface(android.view.Surface)
* MediaCodec.setOutputSurface(Surface)} incorrectly.
*
* <p>
* See {@link MediaCodecVideoRenderer#codecNeedsSetOutputSurfaceWorkaround(String)} for more
* details.
* </p>
*
* <p>
* This custom {@link MediaCodecVideoRenderer} may be useful in the case a device is affected by
* this issue but is not present in ExoPlayer's list.
* </p>
*
* <p>
* This class has only effect on devices with Android 6 and higher, as the {@code setOutputSurface}
* method is only implemented in these Android versions and the method used as a workaround is
* always applied on older Android versions (releasing and re-instantiating video codec instances).
* </p>
*/
public final class CustomMediaCodecVideoRenderer extends MediaCodecVideoRenderer {
@SuppressWarnings({"checkstyle:ParameterNumber", "squid:S107"})
public CustomMediaCodecVideoRenderer(final Context context,
final MediaCodecAdapter.Factory codecAdapterFactory,
final MediaCodecSelector mediaCodecSelector,
final long allowedJoiningTimeMs,
final boolean enableDecoderFallback,
@Nullable final Handler eventHandler,
@Nullable final VideoRendererEventListener eventListener,
final int maxDroppedFramesToNotify) {
super(context, codecAdapterFactory, mediaCodecSelector, allowedJoiningTimeMs,
enableDecoderFallback, eventHandler, eventListener, maxDroppedFramesToNotify);
}
@Override
protected boolean codecNeedsSetOutputSurfaceWorkaround(final String name) {
return true;
}
}

View file

@ -0,0 +1,43 @@
package org.schabi.newpipe.player.helper;
import android.content.Context;
import android.os.Handler;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
import com.google.android.exoplayer2.video.VideoRendererEventListener;
import java.util.ArrayList;
/**
* A {@link DefaultRenderersFactory} which only uses {@link CustomMediaCodecVideoRenderer} as an
* implementation of video codec renders.
*
* <p>
* As no ExoPlayer extension is currently used, the reflection code used by ExoPlayer to try to
* load video extension libraries is not needed in our case and has been removed. This should be
* changed in the case an extension is shipped with the app, such as the AV1 one.
* </p>
*/
public final class CustomRenderersFactory extends DefaultRenderersFactory {
public CustomRenderersFactory(final Context context) {
super(context);
}
@SuppressWarnings("checkstyle:ParameterNumber")
@Override
protected void buildVideoRenderers(final Context context,
@ExtensionRendererMode final int extensionRendererMode,
final MediaCodecSelector mediaCodecSelector,
final boolean enableDecoderFallback,
final Handler eventHandler,
final VideoRendererEventListener eventListener,
final long allowedVideoJoiningTimeMs,
final ArrayList<Renderer> out) {
out.add(new CustomMediaCodecVideoRenderer(context, getCodecAdapterFactory(),
mediaCodecSelector, allowedVideoJoiningTimeMs, enableDecoderFallback, eventHandler,
eventListener, MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY));
}
}

View file

@ -13,6 +13,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.app.PendingIntentCompat;
import androidx.core.app.ServiceCompat;
import androidx.core.content.ContextCompat;
@ -21,7 +22,6 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.player.Player;
import org.schabi.newpipe.player.mediasession.MediaSessionPlayerUi;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PendingIntentCompat;
import java.util.List;
import java.util.Objects;
@ -134,7 +134,7 @@ public final class NotificationUtil {
.setColorized(player.getPrefs().getBoolean(
player.getContext().getString(R.string.notification_colorize_key), true))
.setDeleteIntent(PendingIntentCompat.getBroadcast(player.getContext(),
NOTIFICATION_ID, new Intent(ACTION_CLOSE), FLAG_UPDATE_CURRENT));
NOTIFICATION_ID, new Intent(ACTION_CLOSE), FLAG_UPDATE_CURRENT, false));
// set the initial value for the video thumbnail, updatable with updateNotificationThumbnail
setLargeIcon(builder);
@ -152,7 +152,7 @@ public final class NotificationUtil {
// also update content intent, in case the user switched players
notificationBuilder.setContentIntent(PendingIntentCompat.getActivity(player.getContext(),
NOTIFICATION_ID, getIntentForNotification(), FLAG_UPDATE_CURRENT));
NOTIFICATION_ID, getIntentForNotification(), FLAG_UPDATE_CURRENT, false));
notificationBuilder.setContentTitle(player.getVideoTitle());
notificationBuilder.setContentText(player.getUploaderName());
notificationBuilder.setTicker(player.getVideoTitle());
@ -335,7 +335,7 @@ public final class NotificationUtil {
final String intentAction) {
return new NotificationCompat.Action(drawable, player.getContext().getString(title),
PendingIntentCompat.getBroadcast(player.getContext(), NOTIFICATION_ID,
new Intent(intentAction), FLAG_UPDATE_CURRENT));
new Intent(intentAction), FLAG_UPDATE_CURRENT, false));
}
private Intent getIntentForNotification() {

View file

@ -0,0 +1,14 @@
package org.schabi.newpipe.settings;
import android.os.Bundle;
import androidx.annotation.Nullable;
public class ExoPlayerSettingsFragment extends BasePreferenceFragment {
@Override
public void onCreatePreferences(@Nullable final Bundle savedInstanceState,
@Nullable final String rootKey) {
addPreferencesFromResourceRegistry();
}
}

View file

@ -40,6 +40,7 @@ public final class SettingsResourceRegistry {
add(PlayerNotificationSettingsFragment.class, R.xml.player_notification_settings);
add(UpdateSettingsFragment.class, R.xml.update_settings);
add(VideoAudioSettingsFragment.class, R.xml.video_audio_settings);
add(ExoPlayerSettingsFragment.class, R.xml.exoplayer_settings);
}
private SettingRegistryEntry add(

View file

@ -36,22 +36,6 @@ public final class DeviceUtils {
private static Boolean isTV = null;
private static Boolean isFireTV = null;
/*
* Devices that do not support media tunneling
*/
// Formuler Z8 Pro, Z8, CC, Z Alpha, Z+ Neo
private static final boolean HI3798MV200 = Build.VERSION.SDK_INT == 24
&& Build.DEVICE.equals("Hi3798MV200");
// Zephir TS43UHD-2
private static final boolean CVT_MT5886_EU_1G = Build.VERSION.SDK_INT == 24
&& Build.DEVICE.equals("cvt_mt5886_eu_1g");
// Hilife TV
private static final boolean REALTEKATV = Build.VERSION.SDK_INT == 25
&& Build.DEVICE.equals("RealtekATV");
// Philips QM16XE
private static final boolean QM16XE_U = Build.VERSION.SDK_INT == 23
&& Build.DEVICE.equals("QM16XE_U");
private DeviceUtils() {
}
@ -211,18 +195,6 @@ public final class DeviceUtils {
context.getResources().getDisplayMetrics());
}
/**
* Some devices have broken tunneled video playback but claim to support it.
* See https://github.com/TeamNewPipe/NewPipe/issues/5911
* @return false if affected device
*/
public static boolean shouldSupportMediaTunneling() {
return !HI3798MV200
&& !CVT_MT5886_EU_1G
&& !REALTEKATV
&& !QM16XE_U;
}
public static boolean isLandscape(final Context context) {
return context.getResources().getDisplayMetrics().heightPixels < context.getResources()
.getDisplayMetrics().widthPixels;

View file

@ -1,69 +0,0 @@
package org.schabi.newpipe.util;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.annotation.NonNull;
public final class PendingIntentCompat {
private PendingIntentCompat() {
}
private static int addImmutableFlag(final int flags) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
? flags | PendingIntent.FLAG_IMMUTABLE : flags;
}
/**
* Creates a {@link PendingIntent} to start an activity. It is immutable on API level 23 and
* greater.
*
* @param context The context in which the activity should be started.
* @param requestCode The request code
* @param intent The Intent of the activity to be launched.
* @param flags The flags for the intent.
* @return The pending intent.
* @see PendingIntent#getActivity(Context, int, Intent, int)
*/
@NonNull
public static PendingIntent getActivity(@NonNull final Context context, final int requestCode,
@NonNull final Intent intent, final int flags) {
return PendingIntent.getActivity(context, requestCode, intent, addImmutableFlag(flags));
}
/**
* Creates a {@link PendingIntent} to start a service. It is immutable on API level 23 and
* greater.
*
* @param context The context in which the service should be started.
* @param requestCode The request code
* @param intent The Intent of the service to be launched.
* @param flags The flags for the intent.
* @return The pending intent.
* @see PendingIntent#getService(Context, int, Intent, int)
*/
@NonNull
public static PendingIntent getService(@NonNull final Context context, final int requestCode,
@NonNull final Intent intent, final int flags) {
return PendingIntent.getService(context, requestCode, intent, addImmutableFlag(flags));
}
/**
* Creates a {@link PendingIntent} to perform a broadcast. It is immutable on API level 23 and
* greater.
*
* @param context The context in which the broadcast should be performed.
* @param requestCode The request code
* @param intent The Intent to be broadcast.
* @param flags The flags for the intent.
* @return The pending intent.
* @see PendingIntent#getBroadcast(Context, int, Intent, int)
*/
@NonNull
public static PendingIntent getBroadcast(@NonNull final Context context, final int requestCode,
@NonNull final Intent intent, final int flags) {
return PendingIntent.getBroadcast(context, requestCode, intent, addImmutableFlag(flags));
}
}