diff options
21 files changed, 227 insertions, 121 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index f1d96dc7a..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve existing features -labels: 'Type: Possible bug' ---- - -# Checklist -<!-- Place an x in the boxes to tick them: [x] --> - -- [ ] I have used the search function to see if someone else has already submitted the same bug report. -- [ ] I will describe the problem with as much detail as possible. -- [ ] If the bug only to occurs with a certain podcast, I will include the URL of that podcast. - -# System info -<!-- The following information is very important to fill out because some bugs may only occur on certain devices or versions of Android. --> - -**App version**: x.y.z -<!-- The latest version may be different depending on your device. You can find the version in AntennaPod's settings. --> - -**App source**: Google Play / F-Droid / ... -<!-- Please delete irrelevant answer or fill in the blank --> - -**Android version**: 5.x (Please mention if you are using a custom rom!) - -**Device model**: - -# Bug description - -**Steps to reproduce**: -1. This -2. Then that -3. Then this -4. Etc. - -**Expected behaviour**: -<!-- After following the steps, what did you think AntennaPod would do? --> - -**Current behaviour**: -<!-- What did AntennaPod do instead? Screenshots might help. Usually, you can take a screenshot of your smartphone by pressing *Power* + *Volume down* for a few seconds. --> - -**First occurred**: (e.g. about x days/weeks ago) - -**Environment**: -<!-- Settings you have changed (e.g. Auto Download, changed media player). "Unusual" devices you use (e.g. Bluetooth headphones). --> - -**Stacktrace/Logcat**: -<!-- If you are experiencing a crash, including the stacktrace will likely get it fixed sooner. AntennaPod has an `export logs` feature for this. --> -``` -[if available] -``` diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000..96c33d973 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,78 @@ +name: Bug report +description: Create a report to help us improve existing features +labels: ["Type: Possible bug"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: I have used the search function to see if someone else has already submitted the same bug report. + required: true + - label: I will describe the problem with as much detail as possible. + required: true + - label: If the bug only to occurs with a certain podcast, I will include the URL of that podcast. + required: true + - type: input + id: version + attributes: + label: App version + description: The latest version is different on each device, so we need the actual version number found on the settings screen. + placeholder: x.y.z + validations: + required: true + - type: dropdown + id: source + attributes: + label: Where did you get the app from + multiple: false + options: + - Google Play + - F-Droid + - Other + validations: + required: true + - type: input + id: android_version + attributes: + label: Android version + description: Please mention if you are using a custom rom! + validations: + required: true + - type: input + id: device + attributes: + label: Device model + - type: input + id: first + attributes: + label: First occurred + placeholder: about x days/weeks ago + - type: textarea + id: steps + attributes: + label: Steps to reproduce + placeholder: | + 1. This + 2. Then that + 3. Then this + 4. Etc. + - type: textarea + id: expected + attributes: + label: Expected behaviour + description: After following the steps, what did you think AntennaPod would do? + - type: textarea + id: current + attributes: + label: Current behaviour + description: What did AntennaPod do instead? Screenshots might help. Usually, you can take a screenshot of your smartphone by pressing *Power* + *Volume down* for a few seconds. + - type: textarea + id: logs + attributes: + label: Logs + description: If you are experiencing a crash, including the stacktrace will likely get it fixed sooner. AntennaPod has an `export logs` feature for this. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 24f2f5772..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: Feature request -about: Request a new feature or enhancement - ---- - -# Checklist -<!-- Place an x in the boxes to tick them: [x] --> - -- [ ] I have used the search function to see if someone else has already submitted the same feature request. -- [ ] I will only create one feature request per issue. -- [ ] I will describe the problem with as much detail as possible. - -# System info - -**App version**: x.y.z -<!-- The latest version may be different depending on your device. You can find the version in AntennaPod's settings. --> - -**App source**: Google Play / F-Droid / ... -<!-- Please delete irrelevant answer or fill in the blank --> - -# Feature description - -**Problem you may be having, or feature you want**: -<!-- Give a brief explanation about the problem that may currently exist --> - -**Suggested solution**: -<!-- Describe how your requested feature solves this problem. Try to be as specific as possible. Please not only explain what the feature does, but also how. --> - -**Screenshots / Drawings / Technical details**: -<!-- If your request is about (or includes) changing or extending the UI, describe what the UI would look like and how the user would interact with it. --> diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 000000000..58ac86f8b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,48 @@ +name: Feature request +description: Request a new feature or enhancement +body: + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: I have used the search function to see if someone else has already submitted the same feature request. + required: true + - label: I will describe the problem with as much detail as possible. + required: true + - label: This request contains only one single feature, **not** a list of multiple (related) features. + required: true + - type: input + id: version + attributes: + label: App version + description: The latest version is different on each device, so we need the actual version number found on the settings screen. + placeholder: x.y.z + validations: + required: true + - type: dropdown + id: source + attributes: + label: Where did you get the app from + multiple: false + options: + - Google Play + - F-Droid + - Other + validations: + required: true + - type: textarea + id: problem + attributes: + label: Problem you may be having, or feature you want + description: Give a brief explanation about the problem that may currently exist + - type: textarea + id: solution + attributes: + label: Suggested solution + description: Describe how your requested feature solves this problem. Try to be as specific as possible. Please not only explain what the feature does, but also how. + - type: textarea + id: screenshots + attributes: + label: Screenshots / Drawings / Technical details + description: If your request is about (or includes) changing or extending the UI, describe what the UI would look like and how the user would interact with it. diff --git a/.github/workflows/android-emulator.yml b/.github/workflows/android-emulator.yml index eed69911a..c8e66e14f 100644 --- a/.github/workflows/android-emulator.yml +++ b/.github/workflows/android-emulator.yml @@ -9,11 +9,11 @@ jobs: runs-on: macOS-latest steps: - uses: actions/checkout@v2 - - name: Set up JDK 8 + - name: Set up JDK 11 uses: actions/setup-java@v2 with: distribution: 'adopt' - java-version: '8' + java-version: '11' - name: Wrapper validation uses: gradle/wrapper-validation-action@v1 - name: Build with Gradle diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 47648f9d3..f611cc791 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -40,7 +40,8 @@ android:supportsRtl="true" android:logo="@mipmap/ic_launcher" android:resizeableActivity="true" - android:allowAudioPlaybackCapture="true"> + android:allowAudioPlaybackCapture="true" + android:networkSecurityConfig="@xml/network_security_config"> <meta-data android:name="android.webkit.WebView.MetricsOptOut" @@ -315,6 +316,18 @@ </intent-filter> <intent-filter> + <action android:name="android.intent.action.VIEW" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + + <data android:pathPattern="/.*/podcast/.*" /> + <data android:host="podcasts.apple.com" /> + <data android:scheme="http" /> + <data android:scheme="https" /> + </intent-filter> + + <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> diff --git a/app/src/main/java/de/danoeh/antennapod/config/DownloadServiceCallbacksImpl.java b/app/src/main/java/de/danoeh/antennapod/config/DownloadServiceCallbacksImpl.java index 938bb5931..590b7c897 100644 --- a/app/src/main/java/de/danoeh/antennapod/config/DownloadServiceCallbacksImpl.java +++ b/app/src/main/java/de/danoeh/antennapod/config/DownloadServiceCallbacksImpl.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.config; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import de.danoeh.antennapod.R; @@ -24,7 +25,8 @@ public class DownloadServiceCallbacksImpl implements DownloadServiceCallbacks { args.putInt(DownloadsFragment.ARG_SELECTED_TAB, DownloadsFragment.POS_LOG); intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args); return PendingIntent.getActivity(context, - R.id.pending_intent_download_service_notification, intent, PendingIntent.FLAG_UPDATE_CURRENT); + R.id.pending_intent_download_service_notification, intent, + PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); } @Override @@ -33,7 +35,8 @@ public class DownloadServiceCallbacksImpl implements DownloadServiceCallbacks { activityIntent.setAction("request" + request.getFeedfileId()); activityIntent.putExtra(DownloadAuthenticationActivity.ARG_DOWNLOAD_REQUEST, request); return PendingIntent.getActivity(context.getApplicationContext(), - R.id.pending_intent_download_service_auth, activityIntent, PendingIntent.FLAG_ONE_SHOT); + R.id.pending_intent_download_service_auth, activityIntent, + PendingIntent.FLAG_ONE_SHOT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); } @Override @@ -43,15 +46,15 @@ public class DownloadServiceCallbacksImpl implements DownloadServiceCallbacks { Bundle args = new Bundle(); args.putInt(DownloadsFragment.ARG_SELECTED_TAB, DownloadsFragment.POS_LOG); intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args); - return PendingIntent.getActivity(context, R.id.pending_intent_download_service_report, - intent, PendingIntent.FLAG_UPDATE_CURRENT); + return PendingIntent.getActivity(context, R.id.pending_intent_download_service_report, intent, + PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); } @Override public PendingIntent getAutoDownloadReportNotificationContentIntent(Context context) { Intent intent = new Intent(context, MainActivity.class); intent.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, QueueFragment.TAG); - return PendingIntent.getActivity(context, R.id.pending_intent_download_service_autodownload_report, - intent, PendingIntent.FLAG_UPDATE_CURRENT); + return PendingIntent.getActivity(context, R.id.pending_intent_download_service_autodownload_report, intent, + PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); } } diff --git a/app/src/main/java/de/danoeh/antennapod/discovery/ItunesPodcastSearcher.java b/app/src/main/java/de/danoeh/antennapod/discovery/ItunesPodcastSearcher.java index 6e894176f..5f3dd5f61 100644 --- a/app/src/main/java/de/danoeh/antennapod/discovery/ItunesPodcastSearcher.java +++ b/app/src/main/java/de/danoeh/antennapod/discovery/ItunesPodcastSearcher.java @@ -17,9 +17,12 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class ItunesPodcastSearcher implements PodcastSearcher { private static final String ITUNES_API_URL = "https://itunes.apple.com/search?media=podcast&term=%s"; + private static final String PATTERN_BY_ID = ".*/podcasts\\.apple\\.com/.*/podcast/.*/id(\\d+).*"; public ItunesPodcastSearcher() { } @@ -70,9 +73,12 @@ public class ItunesPodcastSearcher implements PodcastSearcher { @Override public Single<String> lookupUrl(String url) { + Pattern pattern = Pattern.compile(PATTERN_BY_ID); + Matcher matcher = pattern.matcher(url); + final String lookupUrl = matcher.find() ? ("https://itunes.apple.com/lookup?id=" + matcher.group(1)) : url; return Single.create(emitter -> { OkHttpClient client = AntennapodHttpClient.getHttpClient(); - Request.Builder httpReq = new Request.Builder().url(url); + Request.Builder httpReq = new Request.Builder().url(lookupUrl); try { Response response = client.newCall(httpReq.build()).execute(); if (response.isSuccessful()) { @@ -92,7 +98,7 @@ public class ItunesPodcastSearcher implements PodcastSearcher { @Override public boolean urlNeedsLookup(String url) { - return url.contains("itunes.apple.com"); + return url.contains("itunes.apple.com") || url.matches(PATTERN_BY_ID); } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java index af502ce13..c2c5adc9a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java @@ -101,7 +101,7 @@ public abstract class PodcastListFragment extends Fragment { }, error -> { gridView.setVisibility(View.GONE); progressBar.setVisibility(View.GONE); - txtvError.setText(getString(R.string.error_msg_prefix) + error.getMessage()); + txtvError.setText(error.getMessage()); txtvError.setVisibility(View.VISIBLE); butRetry.setVisibility(View.VISIBLE); Log.e(TAG, Log.getStackTraceString(error)); diff --git a/app/src/main/res/xml/network_security_config.xml b/app/src/main/res/xml/network_security_config.xml new file mode 100644 index 000000000..d4c3fc996 --- /dev/null +++ b/app/src/main/res/xml/network_security_config.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<network-security-config xmlns:tools="http://schemas.android.com/tools"> + <base-config cleartextTrafficPermitted="true" tools:ignore="InsecureBaseConfiguration"> + <trust-anchors> + <certificates src="user" tools:ignore="AcceptsUserCertificates"/> + <certificates src="system" /> + </trust-anchors> + </base-config> +</network-security-config> diff --git a/common.gradle b/common.gradle index 0300ed534..8063952ce 100644 --- a/common.gradle +++ b/common.gradle @@ -1,5 +1,5 @@ android { - compileSdkVersion 30 + compileSdkVersion 31 defaultConfig { minSdkVersion 16 diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java index 63e005927..f7ed049cd 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java @@ -8,6 +8,7 @@ import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; +import android.os.Build; import android.util.Log; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; @@ -68,7 +69,8 @@ public class NewEpisodesNotification { intent.setComponent(new ComponentName(context, "de.danoeh.antennapod.activity.MainActivity")); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); intent.putExtra("fragment_feed_id", feed.getId()); - PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, + (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); Notification notification = new NotificationCompat.Builder( context, NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS) @@ -93,7 +95,8 @@ public class NewEpisodesNotification { intent.setComponent(new ComponentName(context, "de.danoeh.antennapod.activity.MainActivity")); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); intent.putExtra("fragment_tag", "EpisodesFragment"); - PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, + (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); Notification notificationGroupSummary = new NotificationCompat.Builder( context, NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS) diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 3465d952d..84a9c429f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -286,7 +286,8 @@ public class PlaybackService extends MediaBrowserServiceCompat { ComponentName eventReceiver = new ComponentName(getApplicationContext(), MediaButtonReceiver.class); Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); mediaButtonIntent.setComponent(eventReceiver); - PendingIntent buttonReceiverIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent buttonReceiverIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, + PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 31 ? PendingIntent.FLAG_MUTABLE : 0)); mediaSession = new MediaSessionCompat(getApplicationContext(), TAG, eventReceiver, buttonReceiverIntent); setSessionToken(mediaSession.getSessionToken()); @@ -598,10 +599,12 @@ public class PlaybackService extends MediaBrowserServiceCompat { PendingIntent pendingIntentAllowThisTime; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { pendingIntentAllowThisTime = PendingIntent.getForegroundService(this, - R.id.pending_intent_allow_stream_this_time, intentAllowThisTime, PendingIntent.FLAG_UPDATE_CURRENT); + R.id.pending_intent_allow_stream_this_time, intentAllowThisTime, + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); } else { pendingIntentAllowThisTime = PendingIntent.getService(this, - R.id.pending_intent_allow_stream_this_time, intentAllowThisTime, PendingIntent.FLAG_UPDATE_CURRENT); + R.id.pending_intent_allow_stream_this_time, intentAllowThisTime, PendingIntent.FLAG_UPDATE_CURRENT + | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); } Intent intentAlwaysAllow = new Intent(intentAllowThisTime); @@ -610,10 +613,12 @@ public class PlaybackService extends MediaBrowserServiceCompat { PendingIntent pendingIntentAlwaysAllow; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { pendingIntentAlwaysAllow = PendingIntent.getForegroundService(this, - R.id.pending_intent_allow_stream_always, intentAlwaysAllow, PendingIntent.FLAG_UPDATE_CURRENT); + R.id.pending_intent_allow_stream_always, intentAlwaysAllow, + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); } else { pendingIntentAlwaysAllow = PendingIntent.getService(this, - R.id.pending_intent_allow_stream_always, intentAlwaysAllow, PendingIntent.FLAG_UPDATE_CURRENT); + R.id.pending_intent_allow_stream_always, intentAlwaysAllow, PendingIntent.FLAG_UPDATE_CURRENT + | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); } NotificationCompat.Builder builder = new NotificationCompat.Builder(this, @@ -1302,7 +1307,8 @@ public class PlaybackService extends MediaBrowserServiceCompat { if (stateManager.hasReceivedValidStartCommand()) { mediaSession.setSessionActivity(PendingIntent.getActivity(this, R.id.pending_intent_player_activity, - PlaybackService.getPlayerActivityIntent(this), PendingIntent.FLAG_UPDATE_CURRENT)); + PlaybackService.getPlayerActivityIntent(this), PendingIntent.FLAG_UPDATE_CURRENT + | (Build.VERSION.SDK_INT >= 31 ? PendingIntent.FLAG_MUTABLE : 0))); try { mediaSession.setMetadata(builder.build()); } catch (OutOfMemoryError e) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java index e7dea192a..5aee8c24c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java @@ -170,7 +170,8 @@ public class PlaybackServiceNotificationBuilder { private PendingIntent getPlayerActivityPendingIntent() { return PendingIntent.getActivity(context, R.id.pending_intent_player_activity, - PlaybackService.getPlayerActivityIntent(context), PendingIntent.FLAG_UPDATE_CURRENT); + PlaybackService.getPlayerActivityIntent(context), PendingIntent.FLAG_UPDATE_CURRENT + | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); } private void addActions(NotificationCompat.Builder notification, MediaSessionCompat.Token mediaSessionToken, @@ -183,7 +184,8 @@ public class PlaybackServiceNotificationBuilder { Intent stopCastingIntent = new Intent(context, PlaybackService.class); stopCastingIntent.putExtra(PlaybackService.EXTRA_CAST_DISCONNECT, true); PendingIntent stopCastingPendingIntent = PendingIntent.getService(context, - numActions, stopCastingIntent, PendingIntent.FLAG_UPDATE_CURRENT); + numActions, stopCastingIntent, PendingIntent.FLAG_UPDATE_CURRENT + | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); notification.addAction(R.drawable.ic_notification_cast_off, context.getString(R.string.cast_disconnect_label), stopCastingPendingIntent); @@ -252,9 +254,11 @@ public class PlaybackServiceNotificationBuilder { intent.putExtra(MediaButtonReceiver.EXTRA_KEYCODE, keycodeValue); if (Build.VERSION.SDK_INT >= 26) { - return PendingIntent.getForegroundService(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); + return PendingIntent.getForegroundService(context, requestCode, intent, + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); } else { - return PendingIntent.getService(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); + return PendingIntent.getService(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT + | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java b/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java index 35b60ca4b..e6496bb7d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java @@ -5,6 +5,7 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.util.Log; import androidx.annotation.NonNull; @@ -302,7 +303,8 @@ public class SyncService extends Worker { Intent intent = getApplicationContext().getPackageManager().getLaunchIntentForPackage( getApplicationContext().getPackageName()); PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), - R.id.pending_intent_sync_error, intent, PendingIntent.FLAG_UPDATE_CURRENT); + R.id.pending_intent_sync_error, intent, PendingIntent.FLAG_UPDATE_CURRENT + | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); Notification notification = new NotificationCompat.Builder(getApplicationContext(), NotificationUtils.CHANNEL_ID_SYNC_ERROR) .setContentTitle(getApplicationContext().getString(R.string.gpodnetsync_error_title)) diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemPermutors.java b/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemPermutors.java index e5f60d64b..09161ca7b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemPermutors.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemPermutors.java @@ -9,6 +9,7 @@ import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import de.danoeh.antennapod.model.feed.FeedItem; @@ -77,25 +78,22 @@ public class FeedItemPermutors { @NonNull private static Date pubDate(@Nullable FeedItem item) { - return (item != null && item.getPubDate() != null) ? - item.getPubDate() : new Date(0); + return (item != null && item.getPubDate() != null) ? item.getPubDate() : new Date(0); } @NonNull private static String itemTitle(@Nullable FeedItem item) { - return (item != null && item.getTitle() != null) ? - item.getTitle() : ""; + return (item != null && item.getTitle() != null) ? item.getTitle().toLowerCase(Locale.getDefault()) : ""; } private static int duration(@Nullable FeedItem item) { - return (item != null && item.getMedia() != null) ? - item.getMedia().getDuration() : 0; + return (item != null && item.getMedia() != null) ? item.getMedia().getDuration() : 0; } @NonNull private static String feedTitle(@Nullable FeedItem item) { - return (item != null && item.getFeed() != null && item.getFeed().getTitle() != null) ? - item.getFeed().getTitle() : ""; + return (item != null && item.getFeed() != null && item.getFeed().getTitle() != null) + ? item.getFeed().getTitle().toLowerCase(Locale.getDefault()) : ""; } /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index 649e97c42..11a3ad9b3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -12,8 +12,11 @@ import android.util.Log; import android.util.Pair; import android.view.SurfaceHolder; import androidx.annotation.NonNull; +import de.danoeh.antennapod.core.event.playback.PlaybackPositionEvent; import de.danoeh.antennapod.core.event.playback.PlaybackServiceEvent; import de.danoeh.antennapod.core.event.playback.SpeedChangedEvent; +import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.model.playback.MediaType; import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; @@ -420,6 +423,11 @@ public abstract class PlaybackController { public void seekTo(int time) { if (playbackService != null) { playbackService.seekTo(time); + } else if (getMedia() instanceof FeedMedia) { + FeedMedia media = (FeedMedia) getMedia(); + media.setPosition(time); + DBWriter.setFeedItem(media.getItem()); + EventBus.getDefault().post(new PlaybackPositionEvent(time, getMedia().getDuration())); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdater.java b/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdater.java index cecd4b3b6..62d56521c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdater.java +++ b/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdater.java @@ -7,6 +7,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; +import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; @@ -212,7 +213,8 @@ public abstract class WidgetUpdater { startingIntent.setAction(MediaButtonReceiver.NOTIFY_BUTTON_RECEIVER); startingIntent.putExtra(Intent.EXTRA_KEY_EVENT, event); - return PendingIntent.getBroadcast(context, eventCode, startingIntent, 0); + return PendingIntent.getBroadcast(context, eventCode, startingIntent, + (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); } private static String getProgressString(int position, int duration, float speed) { diff --git a/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetService.java b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetService.java index 439a528b7..21a362a40 100644 --- a/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetService.java +++ b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetService.java @@ -588,7 +588,13 @@ public class GpodnetService implements ISyncService { e.printStackTrace(); } } - throw new GpodnetServiceBadStatusCodeException("Bad response code: " + responseCode, responseCode); + if (responseCode >= 500) { + throw new GpodnetServiceBadStatusCodeException("Gpodder.net is currently unavailable (code " + + responseCode + ")", responseCode); + } else { + throw new GpodnetServiceBadStatusCodeException("Unable to connect to Gpodder.net (code " + + responseCode + ": " + response.message() + ")", responseCode); + } } } } diff --git a/ui/app-start-intent/src/main/java/de/danoeh/antennapod/ui/appstartintent/MainActivityStarter.java b/ui/app-start-intent/src/main/java/de/danoeh/antennapod/ui/appstartintent/MainActivityStarter.java index 33f96f141..88c0378c1 100644 --- a/ui/app-start-intent/src/main/java/de/danoeh/antennapod/ui/appstartintent/MainActivityStarter.java +++ b/ui/app-start-intent/src/main/java/de/danoeh/antennapod/ui/appstartintent/MainActivityStarter.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.ui.appstartintent; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.os.Build; /** * Launches the main activity of the app with specific arguments. @@ -26,8 +27,8 @@ public class MainActivityStarter { } public PendingIntent getPendingIntent() { - return PendingIntent.getActivity(context, R.id.pending_intent_player_activity, - getIntent(), PendingIntent.FLAG_UPDATE_CURRENT); + return PendingIntent.getActivity(context, R.id.pending_intent_player_activity, getIntent(), + PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); } public void start() { diff --git a/ui/app-start-intent/src/main/java/de/danoeh/antennapod/ui/appstartintent/VideoPlayerActivityStarter.java b/ui/app-start-intent/src/main/java/de/danoeh/antennapod/ui/appstartintent/VideoPlayerActivityStarter.java index 7536d34b6..53f8719de 100644 --- a/ui/app-start-intent/src/main/java/de/danoeh/antennapod/ui/appstartintent/VideoPlayerActivityStarter.java +++ b/ui/app-start-intent/src/main/java/de/danoeh/antennapod/ui/appstartintent/VideoPlayerActivityStarter.java @@ -28,8 +28,8 @@ public class VideoPlayerActivityStarter { } public PendingIntent getPendingIntent() { - return PendingIntent.getActivity(context, R.id.pending_intent_video_player, - getIntent(), PendingIntent.FLAG_UPDATE_CURRENT); + return PendingIntent.getActivity(context, R.id.pending_intent_video_player, getIntent(), + PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)); } public void start() { |