How to put media controller button on notification bar?
Asked Answered
U

4

27

I am creating a music player application. I want to show the media controller on notification bar while my application is running in background. It looks like Google player.

enter image description here

How to do this?

Unweighed answered 21/9, 2012 at 7:42 Comment(0)
B
17

For getting media player controller in your app simply follow this:

Call this method in your MainActivity

public void showNotification(View view){
        new MyNotification(this);
        finish();
    }

Create a new MynotificationClass

public class MyNotification extends Notification {

private Context ctx;
private NotificationManager mNotificationManager;

@SuppressLint("NewApi")
public MyNotification(Context ctx){
    super();
    this.ctx=ctx;
    String ns = Context.NOTIFICATION_SERVICE;
    mNotificationManager = (NotificationManager) ctx.getSystemService(ns);
    CharSequence tickerText = "Shortcuts";
    long when = System.currentTimeMillis();
    Notification.Builder builder = new Notification.Builder(ctx);
    @SuppressWarnings("deprecation")
    Notification notification=builder.getNotification();
    notification.when=when;
    notification.tickerText=tickerText;
    notification.icon=R.drawable.ic_launcher;

    RemoteViews contentView=new RemoteViews(ctx.getPackageName(), R.layout.messageview);

    //set the button listeners
    setListeners(contentView);

    notification.contentView = contentView;
    notification.flags |= Notification.FLAG_ONGOING_EVENT;
    CharSequence contentTitle = "From Shortcuts";
    mNotificationManager.notify(548853, notification);
}

public void setListeners(RemoteViews view){
    //radio listener
    Intent radio=new Intent(ctx,HelperActivity.class);
    radio.putExtra("DO", "radio");
    PendingIntent pRadio = PendingIntent.getActivity(ctx, 0, radio, 0);
    view.setOnClickPendingIntent(R.id.radio, pRadio);

    //volume listener
    Intent volume=new Intent(ctx, HelperActivity.class);
    volume.putExtra("DO", "volume");
    PendingIntent pVolume = PendingIntent.getActivity(ctx, 1, volume, 0);
    view.setOnClickPendingIntent(R.id.volume, pVolume);

    //reboot listener
    Intent reboot=new Intent(ctx, HelperActivity.class);
    reboot.putExtra("DO", "reboot");
    PendingIntent pReboot = PendingIntent.getActivity(ctx, 5, reboot, 0);
    view.setOnClickPendingIntent(R.id.reboot, pReboot);

    //top listener
    Intent top=new Intent(ctx, HelperActivity.class);
    top.putExtra("DO", "top");
    PendingIntent pTop = PendingIntent.getActivity(ctx, 3, top, 0);
    view.setOnClickPendingIntent(R.id.top, pTop);*/

    //app listener
    Intent app=new Intent(ctx, com.example.demo.HelperActivity.class);
    app.putExtra("DO", "app");
    PendingIntent pApp = PendingIntent.getActivity(ctx, 4, app, 0);
    view.setOnClickPendingIntent(R.id.btn1, pApp);
}

}

Create a HelperActivity class

public class HelperActivity extends Activity {

private HelperActivity ctx;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    ctx = this;
    String action = (String) getIntent().getExtras().get("DO");
    if (action.equals("radio")) {
        //Your code
    } else if (action.equals("volume")) {
        //Your code
    } else if (action.equals("reboot")) {
        //Your code
    } else if (action.equals("top")) {
        //Your code
    } else if (action.equals("app")) {
        //Your code
    }

    if (!action.equals("reboot"))
        finish();
}

@Override
protected void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
}
}

XML layout for Notificationlayout.xml

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >

<TextView
    android:id="@+id/msglbl"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="test" />

<TextView
    android:id="@+id/message"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/msglbl" />

<Button
    android:id="@+id/btn1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="play" android:layout_margin="10dp"/>

</RelativeLayout>
Baby answered 19/8, 2014 at 9:0 Comment(4)
great, but what do i have to deliver as "view" to showNotification() ?Dyson
@texNewbie View is needed if you use this function with an android:onClick listener. If not, you can remove it.Bordy
How can I disable the notification bar from closing when I press any of the buttons, just as Google Music is capable of?Malversation
It's better that HelperActivity extends IntentServiceNguyetni
H
21

Here is the example above done correctly to the new API

In your main, when you want to start a notification instantiate the class:

NotificationPanel nPanel = new NotificationPanel(MyActivity);

And when you want to cancel notification: (as it is an onGoing notification)

nPanel.notificationCancel();    

Then create the class for the notification caller:

public class NotificationPanel {

private Context parent;
private NotificationManager nManager;
private NotificationCompat.Builder nBuilder;
private RemoteViews remoteView;

public NotificationPanel(Context parent) {
    // TODO Auto-generated constructor stub
    this.parent = parent;
    nBuilder = new NotificationCompat.Builder(parent)
    .setContentTitle("Parking Meter")
    .setSmallIcon(R.drawable.ic_launcher)
    .setOngoing(true);

    remoteView = new RemoteViews(parent.getPackageName(), R.layout.notificationview);

    //set the button listeners
    setListeners(remoteView);
    nBuilder.setContent(remoteView);

    nManager = (NotificationManager) parent.getSystemService(Context.NOTIFICATION_SERVICE);
    nManager.notify(2, nBuilder.build());
}

public void setListeners(RemoteViews view){
    //listener 1
    Intent volume = new Intent(parent,NotificationReturnSlot.class);
    volume.putExtra("DO", "volume");
    PendingIntent btn1 = PendingIntent.getActivity(parent, 0, volume, 0);
    view.setOnClickPendingIntent(R.id.btn1, btn1);

    //listener 2
    Intent stop = new Intent(parent, NotificationReturnSlot.class);
    stop.putExtra("DO", "stop");
    PendingIntent btn2 = PendingIntent.getActivity(parent, 1, stop, 0);
    view.setOnClickPendingIntent(R.id.btn2, btn2);
}

public void notificationCancel() {
    nManager.cancel(2);
}
}    

Then add the return class that accept the pending intent:

public class NotificationReturnSlot extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    String action = (String) getIntent().getExtras().get("DO");
    if (action.equals("volume")) {
        Log.i("NotificationReturnSlot", "volume");
        //Your code
     } else if (action.equals("stopNotification")) {
         //Your code
        Log.i("NotificationReturnSlot", "stopNotification");
     }
     finish();
    }
}

Then you need to make a XML file for the button. This is a simple one:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >

<Button
    android:id="@+id/btn1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:text="volume" />

<Button
    android:id="@+id/btn2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:text="Stop" />

<TextView
    android:id="@+id/message"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/msglbl" />

Last and not least, the Manifest file:

   <activity android:name=".NotificationReturnSlot"
        android:launchMode="singleTask"
        android:taskAffinity=""
        android:excludeFromRecents="true"/>
Holmgren answered 15/10, 2014 at 9:27 Comment(6)
How to create the Notification? Just use "new NotificationPanel(this);" ?Dyson
I am not able to open new activity on click of button of layout.Sequin
Thanks, this worked for me..How can I provide play/pause functionality with single button using this code?Inbeing
Thanks! your last piece of code help me to prevent activity from relaunch every time that button pressed in notification. I search for hours after solution.Ali
Thanks! please note that there is typo... GIVEN: android:excludeFromRecents="true"> SHOULD BE: android:excludeFromRecents="true"/>, see the "/" at the endUnbalanced
For this case, Its better that NotificationReturnSlot extends IntentService. If it extends Activity, it will display a layout being created and removedNguyetni
B
17

For getting media player controller in your app simply follow this:

Call this method in your MainActivity

public void showNotification(View view){
        new MyNotification(this);
        finish();
    }

Create a new MynotificationClass

public class MyNotification extends Notification {

private Context ctx;
private NotificationManager mNotificationManager;

@SuppressLint("NewApi")
public MyNotification(Context ctx){
    super();
    this.ctx=ctx;
    String ns = Context.NOTIFICATION_SERVICE;
    mNotificationManager = (NotificationManager) ctx.getSystemService(ns);
    CharSequence tickerText = "Shortcuts";
    long when = System.currentTimeMillis();
    Notification.Builder builder = new Notification.Builder(ctx);
    @SuppressWarnings("deprecation")
    Notification notification=builder.getNotification();
    notification.when=when;
    notification.tickerText=tickerText;
    notification.icon=R.drawable.ic_launcher;

    RemoteViews contentView=new RemoteViews(ctx.getPackageName(), R.layout.messageview);

    //set the button listeners
    setListeners(contentView);

    notification.contentView = contentView;
    notification.flags |= Notification.FLAG_ONGOING_EVENT;
    CharSequence contentTitle = "From Shortcuts";
    mNotificationManager.notify(548853, notification);
}

public void setListeners(RemoteViews view){
    //radio listener
    Intent radio=new Intent(ctx,HelperActivity.class);
    radio.putExtra("DO", "radio");
    PendingIntent pRadio = PendingIntent.getActivity(ctx, 0, radio, 0);
    view.setOnClickPendingIntent(R.id.radio, pRadio);

    //volume listener
    Intent volume=new Intent(ctx, HelperActivity.class);
    volume.putExtra("DO", "volume");
    PendingIntent pVolume = PendingIntent.getActivity(ctx, 1, volume, 0);
    view.setOnClickPendingIntent(R.id.volume, pVolume);

    //reboot listener
    Intent reboot=new Intent(ctx, HelperActivity.class);
    reboot.putExtra("DO", "reboot");
    PendingIntent pReboot = PendingIntent.getActivity(ctx, 5, reboot, 0);
    view.setOnClickPendingIntent(R.id.reboot, pReboot);

    //top listener
    Intent top=new Intent(ctx, HelperActivity.class);
    top.putExtra("DO", "top");
    PendingIntent pTop = PendingIntent.getActivity(ctx, 3, top, 0);
    view.setOnClickPendingIntent(R.id.top, pTop);*/

    //app listener
    Intent app=new Intent(ctx, com.example.demo.HelperActivity.class);
    app.putExtra("DO", "app");
    PendingIntent pApp = PendingIntent.getActivity(ctx, 4, app, 0);
    view.setOnClickPendingIntent(R.id.btn1, pApp);
}

}

Create a HelperActivity class

public class HelperActivity extends Activity {

private HelperActivity ctx;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    ctx = this;
    String action = (String) getIntent().getExtras().get("DO");
    if (action.equals("radio")) {
        //Your code
    } else if (action.equals("volume")) {
        //Your code
    } else if (action.equals("reboot")) {
        //Your code
    } else if (action.equals("top")) {
        //Your code
    } else if (action.equals("app")) {
        //Your code
    }

    if (!action.equals("reboot"))
        finish();
}

@Override
protected void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
}
}

XML layout for Notificationlayout.xml

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >

<TextView
    android:id="@+id/msglbl"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="test" />

<TextView
    android:id="@+id/message"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/msglbl" />

<Button
    android:id="@+id/btn1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="play" android:layout_margin="10dp"/>

</RelativeLayout>
Baby answered 19/8, 2014 at 9:0 Comment(4)
great, but what do i have to deliver as "view" to showNotification() ?Dyson
@texNewbie View is needed if you use this function with an android:onClick listener. If not, you can remove it.Bordy
How can I disable the notification bar from closing when I press any of the buttons, just as Google Music is capable of?Malversation
It's better that HelperActivity extends IntentServiceNguyetni
H
1

Return/send data from notification to your original Activity; the changes needed for the Example above:

NotificationPanel nPanel = new NotificationPanel(MyActivity)

How to use the Notification Button to resume the same Stack and Activity that created the Notification:

1) Make sure the Activity is not Destroyed (optional), change the Back button to put the task in the back and not destroy it:

@Override    
void onBackPressed() {
   Log.d("onBackPressed", "onBackPressed Called");
   moveTaskToBack(true);
}

2) In the Menifest add this to the Activity:

android:launchMode="singleTop"

3) Add those flags for your Intent Instance: (volume is the Intent instance)

Intent volume = new Intent(....);
....
volume.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
volume.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

and as well you can add the following (optional):

volume.setAction(Intent.ACTION_MAIN);
volume.addCategory(Intent.CATEGORY_LAUNCHER)

4) In the PendingIntent instance don't use any flags:

PendingIntent btn1 = PendingIntent.getActivity(parent, 0, volume, 0);

5) And catch the intent in your Activity with onNewIntent(Intent intent) call back:

@Override
protected void onNewIntent(Intent intent) {
    // TODO Auto-generated method stub
    super.onNewIntent(intent);
    setIntent(intent);
    Log.i("onNewIntent", intent.toString());    // DEBUG - very useful
    if (intent.getExtras() != null) {   // As the Intent we send back has extras, if it don't, it is a different Intent. it is possible to use TRY {} CATCH{} for this as well to find if Extras is NULL.
        String tmp;
        tmp = intent.getExtras().getString("DO");
        if (tmp != null) {  
            if (tmp.equals("volume"))
                Log.i("onNewIntent", "Volume");
            else if (tmp.equals("stop"))
                Log.i("onNewIntent", "Stop");
            else
                Log.i("onNewIntent", "Didnt capture the extras of the Intent - " + tmp);
        } else {
            Log.i("onNewIntent", "No new Intent");
        }
    }
}
Holmgren answered 17/10, 2014 at 4:0 Comment(0)
P
0

You need to create a RemoteView and show it as a notification.

Please refer to the follow document

Status Notifications (Creating a Custom Notification Layout)

Pepita answered 21/9, 2012 at 7:49 Comment(2)
By implementing it, I could only display those buttons. But how to use event listener for them?Unweighed
Please check "setOnClickPendingIntent".Pepita

© 2022 - 2024 — McMap. All rights reserved.