【问题标题】:How to put media controller button on notification bar?如何将媒体控制器按钮放在通知栏上?
【发布时间】:2012-09-21 07:42:30
【问题描述】:

我正在创建一个音乐播放器应用程序。当我的应用程序在后台运行时,我想在通知栏上显示媒体控制器。它看起来像 Google 播放器。

如何做到这一点?

【问题讨论】:

    标签: android mediacontroller android-music-player


    【解决方案1】:

    这是上面对新 API 正确完成的示例

    在你的 main 中,当你想启动通知时实例化类:

    NotificationPanel nPanel = new NotificationPanel(MyActivity);
    

    当你想取消通知时:(因为它是一个正在进行的通知)

    nPanel.notificationCancel();    
    

    然后为通知调用者创建类:

    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);
    }
    }    
    

    然后添加接受待处理意图的返回类:

    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();
        }
    }
    

    然后您需要为按钮制作一个 XML 文件。这是一个简单的:

    <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" />
    

    最后也是最重要的,Manifest 文件:

       <activity android:name=".NotificationReturnSlot"
            android:launchMode="singleTask"
            android:taskAffinity=""
            android:excludeFromRecents="true"/>
    

    【讨论】:

    • 如何创建通知?只需使用“new NotificationPanel(this);” ?
    • 我无法在点击布局按钮时打开新活动。
    • 谢谢,这对我有用..如何使用此代码通过单个按钮提供播放/暂停功能?
    • 谢谢!您的最后一段代码帮助我防止每次在通知中按下该按钮时重新启动活动。我在解决后搜索了几个小时。
    • 谢谢!请注意有错别字... GIVEN: android:excludeFromRecents="true"> 应该是: android:excludeFromRecents="true"/>,见末尾的“/”
    【解决方案2】:

    要在您的应用中获取媒体播放器控制器,只需执行以下操作:

    在您的 MainActivity 中调用此方法

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

    创建一个新的 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);
    }
    
    }
    

    创建一个 HelperActivity 类

    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();
    }
    }
    

    Notificationlayout.xml 的 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>
    

    【讨论】:

    • 很好,但是我必须将什么作为“视图”提供给 showNotification() ?
    • @texNewbie 如果您将此函数与 android:onClick 侦听器一起使用,则需要查看。如果没有,您可以将其删除。
    • 当我按下任何按钮时,如何禁止通知栏关闭,就像 Google Music 一样?
    • HelperActivity扩展IntentService比较好
    【解决方案3】:

    您需要创建一个 RemoteView 并将其显示为通知。

    请参考以下文档

    Status Notifications(创建自定义通知布局)

    【讨论】:

    • 通过实现它,我只能显示那些按钮。但是如何为他们使用事件监听器呢?
    • 请检查“setOnClickPendingIntent”。
    【解决方案4】:

    将通知中的数据返回/发送到您的原始活动;上述示例所需的更改:

    NotificationPanel nPanel = new NotificationPanel(MyActivity)
    

    如何使用通知按钮来恢复创建通知的同一个堆栈和活动:

    1) 确保 Activity 没有被销毁(可选),更改 Back 按钮以将任务放在后面而不是销毁它:

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

    2) 在 Menifest 中将其添加到 Activity:

    android:launchMode="singleTop"
    

    3) 为您的 Intent 实例添加这些标志:(volume 是 Intent 实例)

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

    您还可以添加以下内容(可选):

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

    4) 在 PendingIntent 实例中不要使用任何标志:

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

    5) 并通过 onNewIntent(Intent intent) 回调捕获 Activity 中的意图:

    @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");
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多