Commit bdc6004f authored by Geoffrey Métais's avatar Geoffrey Métais

Implement Oreo notification channels

parent 5d85b835
package org.videolan.vlc;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
......@@ -13,7 +12,6 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.preference.PreferenceManager;
......@@ -23,6 +21,7 @@ import android.util.Log;
import org.videolan.medialibrary.Medialibrary;
import org.videolan.medialibrary.interfaces.DevicesDiscoveryCb;
import org.videolan.vlc.gui.DialogActivity;
import org.videolan.vlc.gui.helpers.NotificationHelper;
import org.videolan.vlc.util.AndroidDevices;
import org.videolan.vlc.util.FileUtils;
import org.videolan.vlc.util.Strings;
......@@ -248,7 +247,6 @@ public class MediaParsingService extends Service implements DevicesDiscoveryCb {
});
}
private NotificationCompat.Builder builder;
private boolean wasWorking;
final StringBuilder sb = new StringBuilder();
private final Intent progessIntent = new Intent(ACTION_PROGRESS);
......@@ -270,29 +268,11 @@ public class MediaParsingService extends Service implements DevicesDiscoveryCb {
sb.append(getString(R.string.ml_discovering)).append(' ').append(Uri.decode(Strings.removeFileProtocole(mCurrentDiscovery)));
else
sb.append(getString(R.string.ml_parse_media));
if (builder == null) {
builder = new NotificationCompat.Builder(MediaParsingService.this)
.setContentIntent(PendingIntent.getActivity(MediaParsingService.this, 0, new Intent(MediaParsingService.this, StartActivity.class), PendingIntent.FLAG_UPDATE_CURRENT))
.setSmallIcon(R.drawable.ic_notif_scan)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setContentTitle(getString(R.string.ml_scanning))
.setAutoCancel(false)
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
.setOngoing(true);
}
String progressText = sb.toString();
builder.setContentText(progressText);
if (wasWorking != mMedialibrary.isWorking()) {
final String progressText = sb.toString();
final boolean updateAction = wasWorking != mMedialibrary.isWorking();
if (updateAction)
wasWorking = !wasWorking;
notificationIntent.setAction(mScanPaused ? ACTION_RESUME_SCAN : ACTION_PAUSE_SCAN);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action playpause = mScanPaused ? new NotificationCompat.Action(R.drawable.ic_play, getString(R.string.resume), pi)
: new NotificationCompat.Action(R.drawable.ic_pause, getString(R.string.pause), pi);
builder.mActions.clear();
builder.addAction(playpause);
}
final Notification notification = builder.build();
final Notification notification = NotificationHelper.createScanNotification(MediaParsingService.this, progressText, updateAction, mScanPaused);
synchronized (MediaParsingService.this) {
if (mLastNotificationTime != -1L) {
mLocalBroadcastManager.sendBroadcast(progessIntent
......
......@@ -22,6 +22,7 @@ package org.videolan.vlc;
import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
......@@ -58,7 +59,6 @@ import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaButtonReceiver;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v7.app.NotificationCompat;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
......@@ -79,6 +79,7 @@ import org.videolan.medialibrary.media.SearchAggregate;
import org.videolan.vlc.gui.AudioPlayerContainerActivity;
import org.videolan.vlc.gui.helpers.AudioUtil;
import org.videolan.vlc.gui.helpers.BitmapUtil;
import org.videolan.vlc.gui.helpers.NotificationHelper;
import org.videolan.vlc.gui.preferences.PreferencesActivity;
import org.videolan.vlc.gui.preferences.PreferencesFragment;
import org.videolan.vlc.gui.video.PopupManager;
......@@ -91,6 +92,7 @@ import org.videolan.vlc.util.AndroidDevices;
import org.videolan.vlc.util.FileUtils;
import org.videolan.vlc.util.Permissions;
import org.videolan.vlc.util.Strings;
import org.videolan.vlc.util.Util;
import org.videolan.vlc.util.VLCInstance;
import org.videolan.vlc.util.VLCOptions;
import org.videolan.vlc.util.VoiceSearchParams;
......@@ -104,7 +106,6 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
......@@ -886,10 +887,6 @@ public class PlaybackService extends MediaBrowserServiceCompat implements IVLCVo
@Override
public void run() {
try {
NotificationCompat.Builder builder;
//Watch notification dismissed
PendingIntent piStop = PendingIntent.getBroadcast(ctx, 0,
new Intent(ACTION_REMOTE_STOP), PendingIntent.FLAG_UPDATE_CURRENT);
Bitmap cover;
String title, artist, album;
synchronized (mUpdateMeta) {
......@@ -905,51 +902,19 @@ public class PlaybackService extends MediaBrowserServiceCompat implements IVLCVo
metaData.getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART) :
AudioUtil.readCoverBitmap(Uri.decode(mw.getArtworkMrl()), width);
}
if (cover == null || cover.isRecycled())
cover = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.ic_no_media);
boolean video = mw.hasFlag(MediaWrapper.MEDIA_FORCE_AUDIO);
// add notification to status bar
builder = new NotificationCompat.Builder(ctx);
builder.setSmallIcon(video ? R.drawable.ic_notif_video : R.drawable.ic_notif_audio)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setContentTitle(title)
.setContentText(getMediaDescription(artist, album))
.setLargeIcon(cover)
.setTicker(title + " - " + artist)
.setAutoCancel(!playing)
.setOngoing(playing)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setDeleteIntent(piStop);
builder.setContentIntent(getSessionPendingIntent());
PendingIntent piBackward = PendingIntent.getBroadcast(ctx, 0, new Intent(ACTION_REMOTE_BACKWARD), PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent piPlay = PendingIntent.getBroadcast(ctx, 0, new Intent(ACTION_REMOTE_PLAYPAUSE), PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent piForward = PendingIntent.getBroadcast(ctx, 0, new Intent(ACTION_REMOTE_FORWARD), PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(R.drawable.ic_previous_w, getString(R.string.previous), piBackward);
if (mMediaPlayer.isPlaying())
builder.addAction(R.drawable.ic_pause_w, getString(R.string.pause), piPlay);
else
builder.addAction(R.drawable.ic_play_w, getString(R.string.play), piPlay);
builder.addAction(R.drawable.ic_next_w, getString(R.string.next), piForward);
if (AndroidDevices.showMediaStyle) {
builder.setStyle(new NotificationCompat.MediaStyle()
.setMediaSession(sessionToken)
.setShowActionsInCompactView(0,1,2)
.setShowCancelButton(true)
.setCancelButtonIntent(piStop)
);
}
if (cover == null || cover.isRecycled())
cover = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.ic_no_media);
Notification notification = NotificationHelper.createPlaybackNotification(PlaybackService.this,
mw.hasFlag(MediaWrapper.MEDIA_FORCE_AUDIO), title, artist, album,
cover, playing, sessionToken, getSessionPendingIntent());
startService(new Intent(ctx, PlaybackService.class));
if (!AndroidUtil.isLolliPopOrLater || playing)
PlaybackService.this.startForeground(3, builder.build());
PlaybackService.this.startForeground(3, notification);
else {
PlaybackService.this.stopForeground(false);
NotificationManagerCompat.from(ctx).notify(3, builder.build());
NotificationManagerCompat.from(ctx).notify(3, notification);
}
} catch (IllegalArgumentException e){
// On somme crappy firmwares, shit can happen
......@@ -960,15 +925,6 @@ public class PlaybackService extends MediaBrowserServiceCompat implements IVLCVo
}
}
@NonNull
private String getMediaDescription(String artist, String album) {
StringBuilder contentBuilder = new StringBuilder(artist);
if (contentBuilder.length() > 0 && !TextUtils.isEmpty(album))
contentBuilder.append(" - ");
contentBuilder.append(album);
return contentBuilder.toString();
}
private PendingIntent getSessionPendingIntent() {
if (mMediaPlayer.getVLCVout().areViewsAttached()) { //PIP
final Intent notificationIntent = new Intent(this, VideoPlayerActivity.class);
......@@ -1940,7 +1896,7 @@ public class PlaybackService extends MediaBrowserServiceCompat implements IVLCVo
title = media.getTitle();
MediaDescriptionCompat.Builder builder = new MediaDescriptionCompat.Builder();
builder.setTitle(title)
.setDescription(getMediaDescription(MediaUtils.getMediaArtist(this, media), MediaUtils.getMediaAlbum(this, media)))
.setDescription(Util.getMediaDescription(MediaUtils.getMediaArtist(this, media), MediaUtils.getMediaAlbum(this, media)))
.setIconBitmap(BitmapUtil.getPictureFromCache(media))
.setMediaUri(media.getUri())
.setMediaId(BrowserProvider.generateMediaId(media));
......
/*****************************************************************************
* NotificationHelper.java
*****************************************************************************
* Copyright © 2017 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
package org.videolan.vlc.gui.helpers;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.session.MediaSession;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v7.app.NotificationCompat;
import org.videolan.libvlc.util.AndroidUtil;
import org.videolan.vlc.PlaybackService;
import org.videolan.vlc.R;
import org.videolan.vlc.StartActivity;
import org.videolan.vlc.VLCApplication;
import org.videolan.vlc.util.AndroidDevices;
import org.videolan.vlc.util.Util;
import static org.videolan.vlc.MediaParsingService.ACTION_PAUSE_SCAN;
import static org.videolan.vlc.MediaParsingService.ACTION_RESUME_SCAN;
import static org.videolan.vlc.util.Util.getMediaDescription;
public class NotificationHelper {
public final static String TAG = "VLC/NotificationHelper";
public static Notification createPlaybackNotification(Context ctx, boolean video, String title, String artist,
String album, Bitmap cover, boolean playing,
MediaSessionCompat.Token sessionToken,
PendingIntent spi) {
final PendingIntent piStop = PendingIntent.getBroadcast(ctx, 0, new Intent(PlaybackService.ACTION_REMOTE_STOP), PendingIntent.FLAG_UPDATE_CURRENT);
final PendingIntent piBackward = PendingIntent.getBroadcast(ctx, 0, new Intent(PlaybackService.ACTION_REMOTE_BACKWARD), PendingIntent.FLAG_UPDATE_CURRENT);
final PendingIntent piPlay = PendingIntent.getBroadcast(ctx, 0, new Intent(PlaybackService.ACTION_REMOTE_PLAYPAUSE), PendingIntent.FLAG_UPDATE_CURRENT);
final PendingIntent piForward = PendingIntent.getBroadcast(ctx, 0, new Intent(PlaybackService.ACTION_REMOTE_FORWARD), PendingIntent.FLAG_UPDATE_CURRENT);
if (AndroidUtil.isOOrLater) {
createNotificationChannel();
final Notification.Builder builder = new Notification.Builder(ctx, "vlc_channel");
builder.setSmallIcon(video ? R.drawable.ic_notif_video : R.drawable.ic_notif_audio)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setContentTitle(title)
.setContentText(Util.getMediaDescription(artist, album))
.setLargeIcon(cover)
.setTicker(title + " - " + artist)
.setAutoCancel(!playing)
.setOngoing(playing)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setDeleteIntent(piStop)
.setContentIntent(spi)
.addAction(R.drawable.ic_previous_w, ctx.getString(R.string.previous), piBackward);
if (playing)
builder.addAction(R.drawable.ic_pause_w, ctx.getString(R.string.pause), piPlay);
else
builder.addAction(R.drawable.ic_play_w, ctx.getString(R.string.play), piPlay);
builder.addAction(R.drawable.ic_next_w, ctx.getString(R.string.next), piForward);
if (AndroidDevices.showMediaStyle) {
builder.setStyle(new Notification.MediaStyle()
.setMediaSession((MediaSession.Token) sessionToken.getToken())
.setShowActionsInCompactView(0,1,2)
);
}
return builder.build();
} else {
final NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
builder.setSmallIcon(video ? R.drawable.ic_notif_video : R.drawable.ic_notif_audio)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setContentTitle(title)
.setContentText(getMediaDescription(artist, album))
.setLargeIcon(cover)
.setTicker(title + " - " + artist)
.setAutoCancel(!playing)
.setOngoing(playing)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setDeleteIntent(piStop)
.setContentIntent(spi)
.addAction(R.drawable.ic_previous_w, ctx.getString(R.string.previous), piBackward);
if (playing)
builder.addAction(R.drawable.ic_pause_w, ctx.getString(R.string.pause), piPlay);
else
builder.addAction(R.drawable.ic_play_w, ctx.getString(R.string.play), piPlay);
builder.addAction(R.drawable.ic_next_w, ctx.getString(R.string.next), piForward);
if (AndroidDevices.showMediaStyle) {
builder.setStyle(new NotificationCompat.MediaStyle()
.setMediaSession(sessionToken)
.setShowActionsInCompactView(0,1,2)
.setShowCancelButton(true)
.setCancelButtonIntent(piStop)
);
}
return builder.build();
}
}
private static android.support.v4.app.NotificationCompat.Builder scanCompatBuilder;
private static Notification.Builder scanBuilder;
private static final Intent notificationIntent = new Intent();
public static Notification createScanNotification(Context ctx, String progressText, boolean updateActions, boolean paused) {
if (AndroidUtil.isOOrLater) {
createNotificationChannel();
if (scanBuilder == null) {
scanBuilder = new Notification.Builder(ctx, "vlc_channel")
.setContentIntent(PendingIntent.getActivity(ctx, 0, new Intent(ctx, StartActivity.class), PendingIntent.FLAG_UPDATE_CURRENT))
.setSmallIcon(R.drawable.ic_notif_scan)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setContentTitle(VLCApplication.getAppResources().getString(R.string.ml_scanning))
.setAutoCancel(false)
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
.setOngoing(true);
}
scanBuilder.setContentText(progressText);
if (updateActions) {
notificationIntent.setAction(paused ? ACTION_RESUME_SCAN : ACTION_PAUSE_SCAN);
final PendingIntent pi = PendingIntent.getBroadcast(VLCApplication.getAppContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
final Notification.Action playpause = paused ? new Notification.Action(R.drawable.ic_play, VLCApplication.getAppResources().getString(R.string.resume), pi)
: new Notification.Action(R.drawable.ic_pause, VLCApplication.getAppResources().getString(R.string.pause), pi);
scanBuilder.setActions(playpause);
}
return scanBuilder.build();
} else {
if (scanCompatBuilder == null) {
scanCompatBuilder = new NotificationCompat.Builder(ctx)
.setContentIntent(PendingIntent.getActivity(ctx, 0, new Intent(ctx, StartActivity.class), PendingIntent.FLAG_UPDATE_CURRENT))
.setSmallIcon(R.drawable.ic_notif_scan)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setContentTitle(VLCApplication.getAppResources().getString(R.string.ml_scanning))
.setAutoCancel(false)
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
.setOngoing(true);
}
scanCompatBuilder.setContentText(progressText);
if (updateActions) {
notificationIntent.setAction(paused ? ACTION_RESUME_SCAN : ACTION_PAUSE_SCAN);
final PendingIntent pi = PendingIntent.getBroadcast(VLCApplication.getAppContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
final NotificationCompat.Action playpause = paused ? new NotificationCompat.Action(R.drawable.ic_play, VLCApplication.getAppResources().getString(R.string.resume), pi)
: new NotificationCompat.Action(R.drawable.ic_pause, VLCApplication.getAppResources().getString(R.string.pause), pi);
scanCompatBuilder.mActions.clear();
scanCompatBuilder.addAction(playpause);
}
return scanCompatBuilder.build();
}
}
private static NotificationManager sNotificationManager;
@RequiresApi(api = Build.VERSION_CODES.O)
private static void createNotificationChannel() {
if (sNotificationManager == null)
sNotificationManager = (NotificationManager) VLCApplication.getAppContext().getSystemService(Context.NOTIFICATION_SERVICE);
if (sNotificationManager.getNotificationChannel("vlc_channel") == null) {
final CharSequence name = VLCApplication.getAppResources().getString(R.string.app_name);
final String description = VLCApplication.getAppResources().getString(R.string.app_name_full);
final int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel mChannel = new NotificationChannel("vlc_channel", name, importance);
mChannel.setDescription(description);
sNotificationManager.createNotificationChannel(mChannel);
}
}
}
/*****************************************************************************
* UiTools.java
*****************************************************************************
* Copyright © 2011-2014 VLC authors and VideoLAN
* Copyright © 2011-2017 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -23,7 +23,9 @@ package org.videolan.vlc.util;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import org.videolan.medialibrary.Tools;
import org.videolan.medialibrary.media.MediaLibraryItem;
......@@ -155,4 +157,13 @@ public class Util {
}
dataset.addAll(newItems);
}
@NonNull
public static String getMediaDescription(String artist, String album) {
StringBuilder contentBuilder = new StringBuilder(artist);
if (contentBuilder.length() > 0 && !TextUtils.isEmpty(album))
contentBuilder.append(" - ");
contentBuilder.append(album);
return contentBuilder.toString();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment