4

Here is the problem.

I am currently working on an application that must provide :

A Radio Player (AAC live streaming from an url) And a PodCast player (MP3 Streaming from an url)

The application must be able to run in background (Android Service) and be exposed to the user with a persistant notification in the Notification Bar (Android Foreground Service)

(ONE problem per question so here i'll be asking for the notification)

Since i have several class for managing players, i though creating a generic class for the noticication would be a good idea. Here is the kind of view i would like to create :

enter image description here .

Here is my notification class for now :

public class StreamingNotification extends NotificationCompat {
    /**
     * PRIVATE ATTRIBUTES
     */
    // log
    private static final String         TAG             = StreamingNotification.class.getSimpleName();
    // notification
    private NotificationManager         _notificationManager;
    private NotificationCompat.Builder  _builder        = null;
    private Notification                _notification;
    // data
    public static final int             NOTIFICATION_ID = 1;
    private Class                       _notifActivity;
    private Context                     _context;
    private String                      _notifTitle;
    private String                      _notifText;
    private int                         _notifLayout;

    public StreamingNotification(String _notifActivity, Context _context, String _notifTitle, String _notifText, int _notifLayout) {

        super();
        try {
            this._notifActivity = Class.forName(_notifActivity);
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        this._context = _context;
        this._notifTitle = _notifTitle;
        this._notifText = _notifText;
        this._notifLayout = _notifLayout;
        // manager
        _notificationManager = (NotificationManager)_context.getSystemService(Context.NOTIFICATION_SERVICE);
        // notif builder
        _builder = new NotificationCompat.Builder(_context);
        buildSimpleNotification();
    }

    private void buildSimpleNotification() {

        // notif intent
        final Intent notificationIntent = new Intent(_context, _notifActivity);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        // remote view
        RemoteViews contentView = new RemoteViews(_context.getPackageName(), _notifLayout);
        // pending intent
        final PendingIntent contentIntent = PendingIntent.getActivity(_context, NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        _builder.setContentIntent(contentIntent).setContent(contentView).setOngoing(true).setWhen(System.currentTimeMillis()).setAutoCancel(false).setContentTitle(_notifTitle)
            .setContentText(_notifText);
        // notification build
        _notification = _builder.getNotification();
        _notification.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE | Notification.FLAG_NO_CLEAR;
        _notificationManager.notify(NOTIFICATION_ID, _notification);
    }
    [GETTERS AND SETTERS]
}

Am I doing it right ? How would you manage a RemoteViews custom notification ?

An-droid
  • 6,433
  • 9
  • 48
  • 93
  • gives me a suggestion. I build a notification big view using RemoteView to control play/pause like this link (stackoverflow.com/questions/14508369/…) All are right but when i click device back button and out from the application click event(Play/Pause/Forward/Close) button doesn't work.Please help me. – Helal Khan Mar 11 '14 at 14:03
  • First your link is not full. Then you mean : when you finish() the root activity of your application, your notification is not responding anymore ? – An-droid Mar 11 '14 at 14:06

1 Answers1

5

Asking for an authoritative source is a bit difficult in this case, since most music players are closed-source and virtually no one else uses that sort of expanded controls-in-the-view notification.

From a stylistic point of view, I would delegate to NotificationCompat instead of extend it. That way, you can present a simpler API internally as opposed to exposing the whole of NotificationCompat.

As for RemoteViews, I'm not sure what you're asking exactly. However you do it, as long as you keep the Notification instance, you can keep the instance to RemoteViews (or the individual views) and update them as needed. If you go with delegation instead of inheritance, it would be quite a bit cleaner as it makes sense in a "this field is the notification, this field is its Views" kinda way.

P.S. From a purely syntactical point of view, try to use the framework naming guidelines. Most notably, fields are prefixed with 'm' and use camelCase (e.g., mNotifTitle). Lastly, private fields are the kryptonite of good tests.

Delyan
  • 8,881
  • 4
  • 37
  • 42
  • Thanks for your reply. You are indeed right in a lot of points I'll will have to redo some stuff on my library ^^ Can I ask why are you saying that "private fields are the kryptonite of good tests" ? I use them usualy for some security (even if nothing is really secure). And lastly do you know some tuto/detailed doc on this kind of notification ? (out of the official doc which I use regularly) – An-droid Oct 01 '13 at 09:15
  • Private/public/protected have absolutely ***nothing*** to do with security - you can change the access level of a field at runtime using Reflection. It's about components and what they should know about. Personally, unless I absolutely have to specify it, I leave fields with package visibility (i.e., no specifier). This makes testing far easier, since I can put the tests in the same package as the tested code and can freely inspect the internal state of the unit under test (it's also less text to read). There's no way to do that with private fields (unless you leak all of them with getters). – Delyan Oct 01 '13 at 10:41
  • Nice explanation thanks =). What about my second question please ? – An-droid Oct 01 '13 at 12:07
  • 1
    I can't help you with a tutorial I'm afraid. I don't learn from tutorials, so I don't keep track of them. Judging from the docs, it's not hard to do this - you need two RemoteViews, one for the collapsed and one for the expanded notification. Use NotificiationCompat to build the collapsed notification. Then, set bigContentView on the created notification and that's that (make sure you only do it after the right API level). It's a pain and a hassle to keep track of all the buttons and text fields and images but that's the price of good UX. :) – Delyan Oct 01 '13 at 20:34
  • Thanks a lot. I mark your answer as accepted since it is the only one and a really good one ;) I think i 'll have to write things down on paper with your advices in mind ! – An-droid Oct 02 '13 at 07:34
  • @Delyan gives me a suggestion. I build a notification big view using RemoteView to control play/pause like this link (stackoverflow.com/questions/14508369/…) All are right but when i click device back button and out from the application click event(Play/Pause/Forward/Close) button doesn't work.Please help me. – Helal Khan Mar 11 '14 at 14:03
  • You need to have BroacastReceiver in your service and manage the click events with intents. Sorry for the late reply – An-droid Apr 08 '14 at 15:04