Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
d2dc20c
SearchFragment: show service name in search hint
Profpatsch May 7, 2025
769e98a
Show search filter in search bar hint
Stypox Jun 4, 2025
16e32df
SearchFragment: show filter in brackets behind service name
Profpatsch Jun 5, 2025
705b5e5
Fix ghost notifications on Android 10
Stypox Jul 6, 2025
f119a36
Added support for importing Soundcloud likes as a new tab before `Abo…
watermelon42 Jun 18, 2025
1c0eabf
Updated extractor version to latest commit
watermelon42 Jun 18, 2025
4c920a4
Merge pull request #12367 from watermelon42/3783_Import_Soundcloud_likes
TobiGr Jul 14, 2025
4ddc064
Merge pull request #12412 from Stypox/fix-ghost-notifications
Stypox Jul 14, 2025
4e94b26
Merge pull request #12258 from Profpatsch/show-service-name-in-search
Stypox Jul 16, 2025
58b5ccb
Translated using Weblate (Czech)
weblate Jul 17, 2025
ba4e7a3
Add changelog for v0.28.0 (1005)
Stypox Jul 17, 2025
938265d
Update NewPipeExtractor
Stypox Jul 17, 2025
4a41214
Do not capitalize "page" for main page content options
TobiGr Jul 18, 2025
f938062
Merge branch 'dev' into Merge-dev-to-refactor
Isira-Seneviratne Jul 18, 2025
7e0ee4e
Update Extractor and add migration to remove SoundCloud Top 50 kiosk
TobiGr Jul 18, 2025
941f857
Display dialog informing the user about the removal of the Top 50 kiosk
TobiGr Jul 18, 2025
fe58ec8
Fix error detection when loading main page tabs
TobiGr Jul 18, 2025
474efbe
Merge pull request #12437 from TeamNewPipe/localization-main-page-con…
Stypox Jul 19, 2025
9bf01e1
Fix new badge links on Readme being rendered incorrectly
litetex Jul 16, 2025
f64dba0
Fix new badge links on Readme being rendered incorrectly
litetex Jul 17, 2025
9697112
Show error panel in EmptyFragment
Stypox Jul 19, 2025
f948921
Improve comment
Stypox Jul 19, 2025
991d9ea
Fix state not saved
Stypox Jul 19, 2025
e61f98b
Merge pull request #12434 from TeamNewPipe/fix-new-badge-links-on-readme
Stypox Jul 19, 2025
0db859e
Merge pull request #12438 from TeamNewPipe/soundcloud/top_50
Stypox Jul 19, 2025
893a227
Enable per-app language preferences for Android < 13
Isira-Seneviratne Jul 19, 2025
b8f9c12
Add link for future reference
Isira-Seneviratne Jul 19, 2025
abd9aad
Update AppCompat
Isira-Seneviratne Jul 19, 2025
1f2e579
Merge branch 'dev' into Merge-dev-to-refactor
Isira-Seneviratne Jul 20, 2025
9e14f93
Properly handle when system language is selected
Isira-Seneviratne Jul 20, 2025
99003ba
Clean up imports
Isira-Seneviratne Jul 20, 2025
f48e73e
Cleaned up some code related to app language
litetex Jul 20, 2025
99ae3fd
Removed no longer needed translation key
litetex Jul 20, 2025
45589db
Merge pull request #12444 from Isira-Seneviratne/Per-app-language
litetex Jul 20, 2025
ded7205
Merge branch 'dev' into Merge-dev-to-refactor
Isira-Seneviratne Jul 21, 2025
1534c88
Fix compilation errors
Isira-Seneviratne Jul 21, 2025
a4bd82b
fix: handle nullable nextPage behavior when searching albums #12401 (…
koukibadr Jul 22, 2025
04ef608
Specify RECEIVER_EXPORTED/RECEIVER_NOT_EXPORTED for sdk34
mikooomich Jun 25, 2025
14cd562
Update manifest for sdk34 FGS changes
mikooomich Jun 25, 2025
4c8d44b
Bump compileSdk to 36 and targetSdk to 35
mikooomich Jun 25, 2025
366129e
Fix error toast crash
mikooomich Jun 25, 2025
26443f9
WIP: Fix compile
mikooomich Jul 15, 2025
50caba6
Fix compile
mikooomich Jul 23, 2025
329d76c
Bump emulator target 33 -> 35
mikooomich Jul 24, 2025
22a709d
Merge pull request #12388 from mikooomich/sdk35
Isira-Seneviratne Jul 24, 2025
be662a9
Merge branch 'dev' into Merge-dev-to-refactor
Isira-Seneviratne Jul 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ jobs:
- api-level: 21
target: default
arch: x86
- api-level: 33
target: google_apis # emulator API 33 only exists with Google APIs
- api-level: 35
target: default
arch: x86_64

permissions:
Expand Down
8 changes: 2 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@

<p align="center">
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub NewPipe releases"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
<a href="https://github.com/TeamNewPipe/NewPipe-nightly/releases" alt="GitHub NewPipe nightly releases">
<img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe-nightly.svg?labelColor=purple&label=dev%20nightly" >
</a>
<a href="https://github.com/TeamNewPipe/NewPipe-refactor-nightly/releases" alt="GitHub NewPipe refactor nightly releases">
<img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe-refactor-nightly.svg?labelColor=purple&label=refactor%20nightly" >
</a>
<a href="https://github.com/TeamNewPipe/NewPipe-nightly/releases" alt="GitHub NewPipe nightly releases"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe-nightly.svg?labelColor=purple&label=dev%20nightly"></a>
<a href="https://github.com/TeamNewPipe/NewPipe-refactor-nightly/releases" alt="GitHub NewPipe refactor nightly releases"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe-refactor-nightly.svg?labelColor=purple&label=refactor%20nightly"></a>
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Build Status"><img src="https://github.com/TeamNewPipe/NewPipe/actions/workflows/ci.yml/badge.svg?branch=dev&event=push"></a>
<a href="https://hosted.weblate.org/engage/newpipe/" alt="Translation Status"><img src="https://hosted.weblate.org/widgets/newpipe/-/svg-badge.svg"></a>
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ plugins {
}

android {
compileSdk 35
compileSdk 36
namespace 'org.schabi.newpipe'

defaultConfig {
applicationId "org.schabi.newpipe"
resValue "string", "app_name", "NewPipe"
minSdk 21
targetSdk 33
targetSdk 35
if (System.properties.containsKey('versionCodeOverride')) {
versionCode System.getProperty('versionCodeOverride') as Integer
} else {
Expand Down
19 changes: 17 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

<!-- We need to be able to open links in the browser on API 30+ -->
Expand Down Expand Up @@ -58,6 +59,15 @@
</intent-filter>
</receiver>

<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
android:exported="false">
<meta-data
android:name="autoStoreLocales"
android:value="true" />
</service>

<service
android:name=".player.PlayerService"
android:exported="true"
Expand Down Expand Up @@ -95,7 +105,10 @@
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:foregroundServiceType="dataSync"
tools:node="merge" />
<service android:name=".local.feed.service.FeedLoadService" />

<service
android:name=".local.feed.service.FeedLoadService"
android:foregroundServiceType="dataSync" />

<activity
android:name=".PanicResponderActivity"
Expand Down Expand Up @@ -127,7 +140,9 @@
android:label="@string/app_name"
android:launchMode="singleTask" />

<service android:name="us.shandian.giga.service.DownloadManagerService" />
<service
android:name="us.shandian.giga.service.DownloadManagerService"
android:foregroundServiceType="dataSync" />

<activity
android:name=".util.FilePickerActivityHelper"
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/org/schabi/newpipe/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ open class App :
Localization.getPreferredLocalization(this),
Localization.getPreferredContentCountry(this),
)
Localization.initPrettyTime(Localization.resolvePrettyTime(this))
Localization.initPrettyTime(Localization.resolvePrettyTime())

BridgeStateSaverInitializer.init(this)
StateSaver.init(this)
Expand Down
14 changes: 7 additions & 7 deletions app/src/main/java/org/schabi/newpipe/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@

package org.schabi.newpipe;

import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
Expand Down Expand Up @@ -49,6 +47,7 @@
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
Expand Down Expand Up @@ -76,6 +75,7 @@
import org.schabi.newpipe.player.event.OnKeyDownListener;
import org.schabi.newpipe.player.helper.PlayerHolder;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.settings.SettingMigrations;
import org.schabi.newpipe.settings.UpdateSettingsFragment;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.DeviceUtils;
Expand Down Expand Up @@ -137,6 +137,7 @@ protected void onCreate(final Bundle savedInstanceState) {
+ "savedInstanceState = [" + savedInstanceState + "]");
}

Localization.migrateAppLanguageSettingIfNecessary(getApplicationContext());
ThemeHelper.setDayNightMode(this);
ThemeHelper.setTheme(this, ServiceHelper.getSelectedServiceId(this));

Expand All @@ -153,7 +154,6 @@ protected void onCreate(final Bundle savedInstanceState) {
}
}

assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState);
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
sharedPrefEditor = sharedPreferences.edit();
Expand Down Expand Up @@ -192,7 +192,7 @@ protected void onCreate(final Bundle savedInstanceState) {
UpdateSettingsFragment.askForConsentToUpdateChecks(this);
}

Localization.migrateAppLanguageSettingIfNecessary(getApplicationContext());
SettingMigrations.showUserInfoIfPresent(this);
}

@Override
Expand Down Expand Up @@ -498,9 +498,8 @@ protected void onDestroy() {

@Override
protected void onResume() {
assureCorrectAppLanguage(this);
// Change the date format to match the selected language on resume
Localization.initPrettyTime(Localization.resolvePrettyTime(getApplicationContext()));
Localization.initPrettyTime(Localization.resolvePrettyTime());
super.onResume();

// Close drawer on return, and don't show animation,
Expand Down Expand Up @@ -870,7 +869,8 @@ public void onReceive(final Context context, final Intent intent) {
};
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(VideoDetailFragment.ACTION_PLAYER_STARTED);
registerReceiver(broadcastReceiver, intentFilter);
ContextCompat.registerReceiver(this, broadcastReceiver, intentFilter,
ContextCompat.RECEIVER_EXPORTED);

// If the PlayerHolder is not bound yet, but the service is running, try to bind to it.
// Once the connection is established, the ACTION_PLAYER_STARTED will be sent.
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/java/org/schabi/newpipe/RouterActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.ThemeHelper;
Expand Down Expand Up @@ -132,7 +131,6 @@ protected void onCreate(final Bundle savedInstanceState) {
ThemeHelper.setDayNightMode(this);
setTheme(ThemeHelper.isLightThemeSelected(this)
? R.style.RouterActivityThemeLight : R.style.RouterActivityThemeDark);
Localization.assureCorrectAppLanguage(this);

// Pass-through touch events to background activities
// so that our transparent window won't lock UI in the mean time
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import org.schabi.newpipe.R
import org.schabi.newpipe.ui.components.common.ScaffoldWithToolbar
import org.schabi.newpipe.ui.screens.AboutScreen
import org.schabi.newpipe.ui.theme.AppTheme
import org.schabi.newpipe.util.Localization

class AboutActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Localization.assureCorrectAppLanguage(this)
enableEdgeToEdge()
super.onCreate(savedInstanceState)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
import us.shandian.giga.service.DownloadManagerService;
import us.shandian.giga.ui.fragment.MissionsFragment;

import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;

public class DownloadActivity extends AppCompatActivity {

private static final String MISSIONS_FRAGMENT_TAG = "fragment_tag";
Expand All @@ -33,7 +31,6 @@ protected void onCreate(final Bundle savedInstanceState) {
i.setClass(this, DownloadManagerService.class);
startService(i);

assureCorrectAppLanguage(this);
ThemeHelper.setTheme(this);

super.onCreate(savedInstanceState);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import static org.schabi.newpipe.extractor.stream.DeliveryMethod.PROGRESSIVE_HTTP;
import static org.schabi.newpipe.util.ListHelper.getStreamsOfSpecifiedDelivery;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;

import android.app.Activity;
import android.content.ComponentName;
Expand Down Expand Up @@ -751,7 +750,6 @@ private String getNameEditText() {
}

private void showFailedDialog(@StringRes final int msg) {
assureCorrectAppLanguage(requireContext());
new AlertDialog.Builder(context)
.setTitle(R.string.general_error)
.setMessage(msg)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.schabi.newpipe.error;

import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
Expand Down Expand Up @@ -79,7 +77,6 @@ public class ErrorActivity extends AppCompatActivity {

@Override
protected void onCreate(final Bundle savedInstanceState) {
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState);

ThemeHelper.setDayNightMode(this);
Expand Down Expand Up @@ -306,7 +303,7 @@ private String getContentLanguageString() {
}

private String getAppLanguage() {
return Localization.getAppLocale(getApplicationContext()).toString();
return Localization.getAppLocale().toString();
}

private String getOsString() {
Expand Down
17 changes: 10 additions & 7 deletions app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import java.util.concurrent.TimeUnit
class ErrorPanelHelper(
private val fragment: Fragment,
rootView: View,
onRetry: Runnable
onRetry: Runnable?,
) {
private val context: Context = rootView.context!!

Expand All @@ -56,12 +56,15 @@ class ErrorPanelHelper(
errorPanelRoot.findViewById(R.id.error_open_in_browser)

private var errorDisposable: Disposable? = null
private var retryShouldBeShown: Boolean = (onRetry != null)

init {
errorDisposable = errorRetryButton.clicks()
.debounce(300, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { onRetry.run() }
if (onRetry != null) {
errorDisposable = errorRetryButton.clicks()
.debounce(300, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { onRetry.run() }
}
}

private fun ensureDefaultVisibility() {
Expand Down Expand Up @@ -101,7 +104,7 @@ class ErrorPanelHelper(
errorActionButton.setOnClickListener(null)
}

errorRetryButton.isVisible = true
errorRetryButton.isVisible = retryShouldBeShown
showAndSetOpenInBrowserButtonAction(errorInfo)
} else if (errorInfo.throwable is AccountTerminatedException) {
errorTextView.setText(R.string.account_terminated)
Expand Down Expand Up @@ -130,7 +133,7 @@ class ErrorPanelHelper(
errorInfo.throwable !is ContentNotSupportedException
) {
// show retry button only for content which is not unavailable or unsupported
errorRetryButton.isVisible = true
errorRetryButton.isVisible = retryShouldBeShown
}
showAndSetOpenInBrowserButtonAction(errorInfo)
}
Expand Down
9 changes: 6 additions & 3 deletions app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ 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.fragment.app.Fragment
import androidx.preference.PreferenceManager
import com.google.android.material.snackbar.Snackbar
Expand Down Expand Up @@ -136,9 +137,11 @@ class ErrorUtil {
NotificationManagerCompat.from(context)
.notify(ERROR_REPORT_NOTIFICATION_ID, notificationBuilder.build())

// since the notification is silent, also show a toast, otherwise the user is confused
Toast.makeText(context, R.string.error_report_notification_toast, Toast.LENGTH_SHORT)
.show()
ContextCompat.getMainExecutor(context).execute {
// since the notification is silent, also show a toast, otherwise the user is confused
Toast.makeText(context, R.string.error_report_notification_toast, Toast.LENGTH_SHORT)
.show()
}
}

private fun getErrorActivityIntent(context: Context, errorInfo: ErrorInfo): Intent {
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/org/schabi/newpipe/error/UserAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public enum UserAction {
PREFERENCES_MIGRATION("migration of preferences"),
SHARE_TO_NEWPIPE("share to newpipe"),
CHECK_FOR_NEW_APP_VERSION("check for new app version"),
OPEN_INFO_ITEM_DIALOG("open info item dialog");
OPEN_INFO_ITEM_DIALOG("open info item dialog"),
GETTING_MAIN_SCREEN_TAB("getting main screen tab");

private final String message;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,57 @@

import androidx.annotation.Nullable;

import com.evernote.android.state.State;

import org.schabi.newpipe.BaseFragment;
import org.schabi.newpipe.R;
import org.schabi.newpipe.error.ErrorInfo;
import org.schabi.newpipe.error.ErrorPanelHelper;

public class BlankFragment extends BaseFragment {

@State
@Nullable
ErrorInfo errorInfo;
@Nullable
ErrorPanelHelper errorPanel = null;

/**
* Builds a blank fragment that just says the app name and suggests clicking on search.
*/
public BlankFragment() {
this(null);
}

/**
* @param errorInfo if null acts like {@link BlankFragment}, else shows an error panel.
*/
public BlankFragment(@Nullable final ErrorInfo errorInfo) {
this.errorInfo = errorInfo;
}

@Nullable
@Override
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
final Bundle savedInstanceState) {
setTitle("NewPipe");
return inflater.inflate(R.layout.fragment_blank, container, false);
final View view = inflater.inflate(R.layout.fragment_blank, container, false);
if (errorInfo != null) {
errorPanel = new ErrorPanelHelper(this, view, null);
errorPanel.showError(errorInfo);
view.findViewById(R.id.blank_page_content).setVisibility(View.GONE);
}
return view;
}

@Override
public void onDestroyView() {
super.onDestroyView();

if (errorPanel != null) {
errorPanel.dispose();
errorPanel = null;
}
}

@Override
Expand Down
Loading