Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@
</activity>
<service
android:name=".RouterActivity$FetcherService"
android:foregroundServiceType="dataSync"
android:exported="false" />

<!-- opting out of sending metrics to Google in Android System WebView -->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.schabi.newpipe.local.feed.notifications

import android.content.Context
import android.content.pm.ServiceInfo
import android.os.Build
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.work.Constraints
Expand Down Expand Up @@ -83,7 +85,9 @@ class NotificationWorker(
.setPriority(NotificationCompat.PRIORITY_LOW)
.setContentTitle(applicationContext.getString(R.string.feed_notification_loading))
.build()
setForegroundAsync(ForegroundInfo(FeedLoadService.NOTIFICATION_ID, notification))
// ServiceInfo constants are not used below Android Q, so 0 is set here
val serviceType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC else 0
setForegroundAsync(ForegroundInfo(FeedLoadService.NOTIFICATION_ID, notification, serviceType))
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,19 +167,17 @@ public boolean shouldUpdateBufferingSlot() {
&& notificationBuilder.mActions.get(2).actionIntent != null);
}


public void createNotificationAndStartForeground() {
if (notificationBuilder == null) {
notificationBuilder = createNotification();
}
updateNotification();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
player.getService().startForeground(NOTIFICATION_ID, notificationBuilder.build(),
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
} else {
player.getService().startForeground(NOTIFICATION_ID, notificationBuilder.build());
}
// ServiceInfo constants are not used below Android Q, so 0 is set here
final int serviceType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
? ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK : 0;
ServiceCompat.startForeground(player.getService(), NOTIFICATION_ID,
notificationBuilder.build(), serviceType);
}

public void cancelNotificationAndStopForeground() {
Expand Down
49 changes: 42 additions & 7 deletions app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.text.Html;
import android.widget.Toast;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

Expand Down Expand Up @@ -113,14 +115,47 @@ public static boolean checkPostNotificationsPermission(final Activity activity,
@RequiresApi(api = Build.VERSION_CODES.M)
public static boolean checkSystemAlertWindowPermission(final Context context) {
if (!Settings.canDrawOverlays(context)) {
final Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + context.getPackageName()));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
context.startActivity(i);
} catch (final ActivityNotFoundException ignored) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
final Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + context.getPackageName()));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
context.startActivity(i);
} catch (final ActivityNotFoundException ignored) {
}
return false;
// from Android R the ACTION_MANAGE_OVERLAY_PERMISSION will only point to the menu,
// so let’s add a dialog that points the user to the right setting.
} else {
final String appName = context.getApplicationInfo()
.loadLabel(context.getPackageManager()).toString();
final String title = context.getString(R.string.permission_display_over_apps);
final String permissionName =
context.getString(R.string.permission_display_over_apps_permission_name);
final String appNameItalic = "<i>" + appName + "</i>";
final String permissionNameItalic = "<i>" + permissionName + "</i>";
final String message =
context.getString(R.string.permission_display_over_apps_message,
appNameItalic,
permissionNameItalic
);
new AlertDialog.Builder(context)
.setTitle(title)
.setMessage(Html.fromHtml(message, Html.FROM_HTML_MODE_COMPACT))
.setPositiveButton("OK", (dialog, which) -> {
// we don’t need the package name here, since it won’t do anything on >R
final Intent intent =
new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
try {
context.startActivity(intent);
} catch (final ActivityNotFoundException ignored) {
}
})
.setCancelable(true)
.show();
return false;
}
return false;

} else {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ public void pauseMission(DownloadMission mission) {
}
}

public void deleteMission(Mission mission) {
public void deleteMission(Mission mission, boolean alsoDeleteFile) {
synchronized (this) {
if (mission instanceof DownloadMission) {
mMissionsPending.remove(mission);
Expand All @@ -274,7 +274,9 @@ public void deleteMission(Mission mission) {
mFinishedMissionStore.deleteMission(mission);
}

mission.delete();
if (alsoDeleteFile) {
mission.delete();
}
}
}

Expand Down
13 changes: 10 additions & 3 deletions app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ private void deleteFinishedDownloads() {
while (i.hasNext()) {
Mission mission = i.next();
if (mission != null) {
mDownloadManager.deleteMission(mission);
mDownloadManager.deleteMission(mission, true);
mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mission.storage.getUri()));
}
i.remove();
Expand Down Expand Up @@ -667,7 +667,14 @@ private boolean handlePopupItem(@NonNull ViewHolderItem h, @NonNull MenuItem opt
shareFile(h.item.mission);
return true;
case R.id.delete:
mDeleter.append(h.item.mission);
// delete the entry and the file
mDeleter.append(h.item.mission, true);
applyChanges();
checkMasterButtonsVisibility();
return true;
case R.id.delete_entry:
// just delete the entry
mDeleter.append(h.item.mission, false);
applyChanges();
checkMasterButtonsVisibility();
return true;
Expand All @@ -676,7 +683,7 @@ private boolean handlePopupItem(@NonNull ViewHolderItem h, @NonNull MenuItem opt
final StoredFileHelper storage = h.item.mission.storage;
if (!storage.existsAsFile()) {
Toast.makeText(mContext, R.string.missing_file, Toast.LENGTH_SHORT).show();
mDeleter.append(h.item.mission);
mDeleter.append(h.item.mission, true);
applyChanges();
return true;
}
Expand Down
37 changes: 29 additions & 8 deletions app/src/main/java/us/shandian/giga/ui/common/Deleter.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
import org.schabi.newpipe.R;

import java.util.ArrayList;
import java.util.Optional;

import kotlin.Pair;
import us.shandian.giga.get.FinishedMission;
import us.shandian.giga.get.Mission;
import us.shandian.giga.service.DownloadManager;
Expand All @@ -30,7 +32,8 @@ public class Deleter {
private static final int DELAY_RESUME = 400;// ms

private Snackbar snackbar;
private ArrayList<Mission> items;
// list of missions to be deleted, and whether to also delete the corresponding file
private ArrayList<Pair<Mission, Boolean>> items;
private boolean running = true;

private final Context mContext;
Expand All @@ -51,7 +54,7 @@ public Deleter(View v, Context c, MissionAdapter a, DownloadManager d, MissionIt
items = new ArrayList<>(2);
}

public void append(Mission item) {
public void append(Mission item, boolean alsoDeleteFile) {
/* If a mission is removed from the list while the Snackbar for a previously
* removed item is still showing, commit the action for the previous item
* immediately. This prevents Snackbars from stacking up in reverse order.
Expand All @@ -60,13 +63,13 @@ public void append(Mission item) {
commit();

mIterator.hide(item);
items.add(0, item);
items.add(0, new Pair<>(item, alsoDeleteFile));

show();
}

private void forget() {
mIterator.unHide(items.remove(0));
mIterator.unHide(items.remove(0).getFirst());
mAdapter.applyChanges();

show();
Expand All @@ -84,7 +87,19 @@ private void show() {
private void next() {
if (items.size() < 1) return;

String msg = mContext.getString(R.string.file_deleted).concat(":\n").concat(items.get(0).storage.getName());
final Optional<String> fileToBeDeleted = items.stream()
.filter(Pair::getSecond)
.map(p -> p.getFirst().storage.getName())
.findFirst();

String msg;
if (fileToBeDeleted.isPresent()) {
msg = mContext.getString(R.string.file_deleted)
.concat(":\n")
.concat(fileToBeDeleted.get());
} else {
msg = mContext.getString(R.string.entry_deleted);
}

snackbar = Snackbar.make(mView, msg, Snackbar.LENGTH_INDEFINITE);
snackbar.setAction(R.string.undo, s -> forget());
Expand All @@ -98,11 +113,13 @@ private void commit() {
if (items.size() < 1) return;

while (items.size() > 0) {
Mission mission = items.remove(0);
Pair<Mission, Boolean> missionAndAlsoDeleteFile = items.remove(0);
Mission mission = missionAndAlsoDeleteFile.getFirst();
boolean alsoDeleteFile = missionAndAlsoDeleteFile.getSecond();
if (mission.deleted) continue;

mIterator.unHide(mission);
mDownloadManager.deleteMission(mission);
mDownloadManager.deleteMission(mission, alsoDeleteFile);

if (mission instanceof FinishedMission) {
mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mission.storage.getUri()));
Expand Down Expand Up @@ -137,7 +154,11 @@ public void dispose() {

pause();

for (Mission mission : items) mDownloadManager.deleteMission(mission);
for (Pair<Mission, Boolean> missionAndAlsoDeleteFile : items) {
Mission mission = missionAndAlsoDeleteFile.getFirst();
boolean alsoDeleteFile = missionAndAlsoDeleteFile.getSecond();
mDownloadManager.deleteMission(mission, alsoDeleteFile);
}
items = null;
}
}
6 changes: 5 additions & 1 deletion app/src/main/res/menu/mission.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@

<item
android:id="@+id/delete"
android:title="@string/delete" />
android:title="@string/delete_file" />

<item
android:id="@+id/delete_entry"
android:title="@string/delete_entry" />

<item
android:id="@+id/error_message_view"
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@
<string name="restore_defaults">Restore defaults</string>
<string name="restore_defaults_confirmation">Do you want to restore defaults?</string>
<string name="permission_display_over_apps">Give permission to display over other apps</string>
<string name="permission_display_over_apps_message">In order to use the Popup Player, please select %1$s in the following Android settings menu and enable %2$s.</string>
<string name="permission_display_over_apps_permission_name">“Allow display over other apps”</string>
<!-- error activity -->
<string name="error_report_notification_title">NewPipe encountered an error, tap to report</string>
<string name="error_report_notification_toast">An error occurred, see the notification</string>
Expand Down Expand Up @@ -333,6 +335,8 @@
<string name="pause">Pause</string>
<string name="create">Create</string>
<string name="delete">Delete</string>
<string name="delete_file">Delete file</string>
<string name="delete_entry">Delete entry</string>
<string name="checksum">Checksum</string>
<string name="dismiss">Dismiss</string>
<string name="rename">Rename</string>
Expand Down Expand Up @@ -889,4 +893,5 @@
<string name="trending_podcasts">Trending podcasts</string>
<string name="trending_movies">Trending movies and shows</string>
<string name="trending_music">Trending music</string>
<string name="entry_deleted">Entry deleted</string>
</resources>