Android 音乐播放器的开发教程(十)通知栏Notification的使用 ----- 小达

来源:互联网 发布:类似itools的软件 编辑:程序博客网 时间:2024/06/04 23:18

通知栏Notification的使用

        在这一片博客中,小达将自己学习Notification的一些想法和大家分享一哈,学的不是很深,所有有些东西可能解释的不是特别到位,还请各位谅解哈可怜.所谓Notification即通知,是一种让你的应用程序在不使用Activity的情况下警示用户。它是看不见的程序组件(Broadcast Receiver,Service和不活跃的Activity)警示用户有需要注意的事件发生的最好途径。后面的一大段一大段是接着前面的项目在继续,大家可以选择性的看一看.

        Notification 是由NotificationManager(系统服务)统一管理的。挂在下拉通知栏上面,就像下图所示,

       上面显示的都是所谓的Notification,今天我们就来一步步的创建,添加按钮响应,再将Notification和我们的播放器联系起来,话不多说,现在就开始咯.
       
       先给Notification创建了个单独的布局文件,当notification被激活的时候,就在通知栏上面显示这个布局文件的样式,

notification_layout.xml:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/notification_layout"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:background="@drawable/bg_photo_01">    <ImageView                                                                                 //显示歌手头像的,,,,,基本没怎么用上,专辑图片不知道怎么弄得出不来        android:id="@+id/notification_artist_image"        android:layout_width="64.0dip"        android:layout_height="64.0dip"        android:background="#00000000"/>    <TextView                                                                                    //在通知栏上显示音乐名称的TextView        android:id="@+id/notification_music_title"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentTop="true"        android:layout_marginLeft="5dp"        android:layout_marginStart="5.0dp"        android:layout_toRightOf="@+id/notification_artist_image"        android:layout_toEndOf="@+id/notification_artist_image"        android:focusable="true"        android:textColor="#FFADABFF"        android:textSize="18sp"        />    <TextView<span style="font-family: Arial, Helvetica, sans-serif;">                                                                                   //在通知栏上显示歌手的TextView</span>        android:id="@+id/notification_music_Artist"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignLeft="@+id/notification_music_title"        android:layout_alignStart="@+id/notification_music_title"        android:layout_marginTop="5.0dip"        android:layout_below="@id/notification_music_title"        android:textColor="#FFADABFF"        />    <ImageButton                                                                                                      //通知栏上的退出按钮        android:id="@+id/notification_exit_button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:background="@drawable/notification_exit"        android:layout_below="@+id/notification_music_title"        android:layout_alignParentRight="true"        android:layout_alignParentEnd="true" />    <ImageButton        android:id="@+id/notification_next_song_button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:background="@drawable/next_music_photo"        android:layout_toLeftOf="@+id/notification_exit_button"        android:layout_toStartOf="@+id/notification_exit_button"        />    <ImageButton        android:id="@+id/notification_play_button"        android:layout_toLeftOf="@id/notification_next_song_button"        android:layout_toStartOf="@id/notification_next_song_button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:background="#00000000"/>    <ImageButton        android:id="@+id/notification_previous_song_button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_toLeftOf="@id/notification_play_button"        android:layout_toStartOf="@id/notification_play_button"        android:background="@drawable/previous_music_photo"        /></RelativeLayout>

       布局文件大致弄好了后,就在播放歌曲的同时,直接将这个布局文件显示到通知栏上去,这一步需要Notification和NotificationManager,小达这里是将notification放在了service里面进行操作了,其他地方也可以的,这是service里面的一部分代码,后面会有整个service的代码的,:
private void initMyNotification() {        /*        第一个参数是显示在通知栏上的小图标的图片        第二个参数是在启动notification时,在状态栏上滚动的一句话        第三个参数是在状态栏上显示的时间         */        myNotification = new Notification(R.drawable.notification_artist_default_image, "小卷毛音乐", System.currentTimeMillis());        /*        NotificationManager用来管理notification的显示和消失等         */        myNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);        /*        对刚才创建的一个notification实例设置各种参数        其中的一个参数是flags        这个参数可以设置该notification是何种状态        这里设置的是ONGOING,表示这个notification会一直呆在通知栏上面        也可以设置滑动后就消失的样式,看个人的不同需求         */        myNotification.flags = Notification.FLAG_ONGOING_EVENT;        /*        在我们创建的notification中有一个View子类的实例        下面创建了一个RemoteViews的实例        并且配置好各种显示的信息后        将该实例传给notification        往后面看会有一句        myNotification.contentView = contentViews;        这个就是传递实例了         */        RemoteViews contentViews = new RemoteViews(getPackageName(), R.layout.notification_layout);        contentViews.setImageViewResource                (R.id.notification_artist_image, R.drawable.notification_artist_default_image);        if(mediaPlayer.isPlaying()){            contentViews.setImageViewResource(R.id.notification_play_button,R.drawable.play_photo);        }        else{            contentViews.setImageViewResource(R.id.notification_play_button,R.drawable.pause_photo);        }        /*        将处理好了的一个View传给notification        让其在通知栏上显示         */
        myNotification.contentView = contentViews;        /*        在创建的notification中还有一个intent        Intent :意图,即告诉系统我要干什么,然后系统根据这个Intent做对应的事。        如startActivity相当于发送消息,而Intent是消息的内容。        PendingIntent :包装Intent,Intent 是我们直接使用 startActivity , startService 或 sendBroadcast 启动某项工作的意图。        而某些时候,我们并不能直接调用startActivity , startServide 或 sendBroadcast ,而是当程序或系统达到某一条件才发送Intent。        如这里的Notification,当用户点击Notification之后,由系统发出一条Activity 的 Intent 。        因此如果我们不用某种方法来告诉系统的话,系统是不知道是使用 startActivity ,startService 还是 sendBroadcast 来启动Intent 的(当然还有其他的“描述”),        因此这里便需要PendingIntent。        PendingIntent.getActivity的参数依次为:Context,发送者的请求码(可以填0),用于系统发送的Intent,标志位         */
</pre><pre name="code" class="java">        Intent notificationIntent = new Intent(this, MainActivity.class);        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);        myNotification.contentIntent = contentIntent;        /*        用notificationManager来启动notification        通过调用notify这个函数来启动         */
        myNotificationManager.notify(0, myNotification);    }
</pre></div><div style="text-align:left"><span style="font-size:14px"></span></div><div style="text-align:left"><span style="font-size:14px">        这个函数是一个自定义的初始化函数,需要显示notification的时候直接调用就可以了,里面的注释还是比较详细的,有什么看不懂的地方可以给我留言.</span></div><p></p><p><span style="font-size:14px">        上面显示出来的Notification只能看,上面有几个按钮还不能点击,在这个上面的按钮点击监听器和普通的有点区别,由于notification经常和activity独立的存在,没有什么直接的关联,需要通过broadcast机制来互相传递信息,notification上的按钮点击之后,会发送一个指定了的广播,只需要接收后再做处理,就能达到按钮监听器的效果了,在notification上面按钮点击需要简单的三个步骤:</span></p><p><span style="font-size:14px">         第一步:          实例化一个intent,作为发送广播的intent,里面存放action,也就是需要传递给activity或者service的提示信息.</span></p><p><span style="font-size:14px"></span><pre name="code" class="java">        Intent previousButtonIntent = new Intent(NotificationMsg.NOTIFICATION_PREVIOUS_MUSIC);
      

         第二步:          实例化一个PendingIntent,把上面的intent包装起来,并说明是用来发广播的intent,

 

        PendingIntent pendPreviousButtonIntent = PendingIntent.getBroadcast(this, 0, previousButtonIntent, 0);


         第三步:          都猜中了把,就是将pendingIntent和notification上的按钮联系起来

        contentViews.setOnClickPendingIntent(R.id.notification_previous_song_button, pendPreviousButtonIntent);

         有没有很快,,,,这样点击之后就可以发送一个广播出去了,再怎么接受纯属个人喜好问题了哈.....

          下面是service的源码,好像有点长额,重点看红色的地方,是关于notification的:

package com.example.dada.myapplication;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.app.Service;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.media.MediaPlayer;import android.os.Handler;import android.os.IBinder;import android.os.Looper;import android.os.Message;import android.view.animation.AnimationUtils;import android.widget.RemoteViews;import java.io.IOException;import java.util.ArrayList;import java.util.List;public class PlayerService extends Service implements AppConstant {    private int current_position;    private String musicPath;    private String music_artist;    private String music_title;<span style="color:#ff0000;">    private String notification_msg;</span>    private boolean isPause = true;    private boolean isChangToNext;<span style="color:#ff0000;">    private NotificationManager myNotificationManager;                     //通知栏    private Notification myNotification;</span>    private ChangeToNextReceiver changeToNextReceiver;    private PlayReceiver playReceiver;    private ProgressChangeReceiver progressChangeReceiver;    public static MediaPlayer mediaPlayer = new MediaPlayer();    private Intent intent_to_activity = new Intent("com.example.communication.RECEIVER");    private Intent intent_to_progressBar = new Intent("com.example.communication.BAR");<span style="color:#ff0000;">    private Intent notification_to_activity = new Intent("com.example.communication.NOTIFICATION_TO_ACTIVITY");</span>    private Handler myHandler = new Handler() {        public void handleMessage(Message msg) {            if (msg.what == PlayerMsg.PLAY_MSG) {                current_position = mediaPlayer.getCurrentPosition();                intent_to_progressBar.putExtra("position",  current_position);                sendBroadcast(intent_to_progressBar);                myHandler.sendEmptyMessageDelayed(PlayerMsg.PLAY_MSG, 1000);            }            if (msg.what == PlayerMsg.PAUSE) {                stopMusic();            }        }    };    @Override    public IBinder onBind(Intent intent) {        return null;    }    public int onStartCommand(Intent intent, int flags, int startId) {        notification_msg = null;        playReceiver = new PlayReceiver();        changeToNextReceiver = new ChangeToNextReceiver();        progressChangeReceiver = new ProgressChangeReceiver();        IntentFilter intentChangeFilter = new IntentFilter();        IntentFilter intentPlayFilter = new IntentFilter();        IntentFilter intentProgressChangeFilter = new IntentFilter();        intentChangeFilter.addAction("com.example.communication.ChANGE_MUSIC");        intentPlayFilter.addAction("com.example.communication.PLAY");        intentProgressChangeFilter.addAction("com.example.communication.PROGRESS_BAR");<span style="color:#ff0000;">        IntentFilter previousMusicFilter = new IntentFilter();        previousMusicFilter.addAction(NotificationMsg.NOTIFICATION_PREVIOUS_MUSIC);        registerReceiver(onClickReceiver, previousMusicFilter);        IntentFilter nextMusicFilter = new IntentFilter();        nextMusicFilter.addAction(NotificationMsg.NOTIFICATION_NEXT_MUSIC);        registerReceiver(onClickReceiver,nextMusicFilter);        IntentFilter pauseMusicFilter = new IntentFilter();        pauseMusicFilter.addAction(NotificationMsg.NOTIFICATION_PAUSE_MUSIC);        registerReceiver(onClickReceiver,pauseMusicFilter);        IntentFilter exitFilter = new IntentFilter();        exitFilter.addAction(NotificationMsg.NOTIFICATION_EXIT);        registerReceiver(onClickReceiver,exitFilter);</span><span style="color:#ff0000;">        registerReceiver(playReceiver, intentPlayFilter);        registerReceiver(changeToNextReceiver, intentChangeFilter);        registerReceiver(progressChangeReceiver, intentProgressChangeFilter);</span>        try {            int msg = intent.getIntExtra("MSG", 0);            musicPath = intent.getStringExtra("url");            SendBroadcastToActivity(intent);            if (msg == AppConstant.PlayerMsg.PLAY_MSG) {                myHandler.sendEmptyMessage(PlayerMsg.PLAY_MSG);                playMusic(0);            }        } catch (Exception e) {            e.printStackTrace();        }        return 0;    }    private void playMusic(int position) {        try {            mediaPlayer.reset();            mediaPlayer.setDataSource(musicPath);            mediaPlayer.prepare();            mediaPlayer.setOnPreparedListener(new MyPreparedListener(position));<span style="color:#ff0000;">            initMyNotification();</span>        } catch (IOException e) {            e.printStackTrace();        }    }    private class MyPreparedListener implements MediaPlayer.OnPreparedListener {        private int position;        public MyPreparedListener(int position) {            this.position = position;        }        public void onPrepared(MediaPlayer mp) {            if (position > 0)                mediaPlayer.seekTo(position);            mediaPlayer.start();        }    }    private void stopMusic() {        if (mediaPlayer != null) {            mediaPlayer.pause();        }    }    public void onDestory() {        if (mediaPlayer != null) {            mediaPlayer.stop();            mediaPlayer.release();        }    }    private void SendBroadcastToActivity(Intent intent) {                                //向activity发送广播的函数        music_title = intent.getStringExtra("title");        music_artist = intent.getStringExtra("artist");<span style="color:#ff0000;">        initMyNotification();</span>        intent_to_activity.putExtra("title", intent.getStringExtra("title"));        intent_to_activity.putExtra("artist", intent.getStringExtra("artist"));        intent_to_activity.putExtra("album", intent.getStringExtra("album"));        intent_to_activity.putExtra("album_id", intent.getLongExtra("album_id", 0));        sendBroadcast(intent_to_activity);    }    private class PlayReceiver extends BroadcastReceiver {                             //播放与暂停广播接收器        public PlayReceiver() {            super();        }        @Override        public void onReceive(Context context, Intent intent) {            isPause = intent.getBooleanExtra("isPause", true);            isChangToNext = intent.getBooleanExtra("isChangeToNext", false);            if (isPause) {                myHandler.sendEmptyMessage(PlayerMsg.PAUSE);            } else {                current_position = intent.getIntExtra("position", 0);                playMusic(current_position);                myHandler.sendEmptyMessage(PlayerMsg.PLAY_MSG);            }        }    }    private class ChangeToNextReceiver extends BroadcastReceiver {                        //换歌广播接收器        public ChangeToNextReceiver() {            super();        }        @Override        public void onReceive(Context context, Intent intent) {            isChangToNext = intent.getBooleanExtra("isChangeToNext", false);            if (isChangToNext) {                musicPath = intent.getStringExtra("music_url");                music_artist = intent.getStringExtra("music_artist");                music_title = intent.getStringExtra("music_title");                playMusic(0);<span style="color:#ff0000;">                initMyNotification();</span>            }        }    }    private class ProgressChangeReceiver extends BroadcastReceiver {        @Override        public void onReceive(Context context, Intent intent) {            current_position = intent.getIntExtra("current_position", 0);            playMusic(current_position);        }    } <span style="color:#ff0000;">   private void initMyNotification() {        /*        第一个参数是显示在通知栏上的小图标的图片        第二个参数是在启动notification时,在状态栏上滚动的一句话        第三个参数是在状态栏上显示的时间         */        myNotification = new Notification(R.drawable.notification_artist_default_image, "小卷毛音乐", System.currentTimeMillis());        /*        NotificationManager用来管理notification的显示和消失等         */        myNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);        /*        对刚才创建的一个notification实例设置各种参数        其中的一个参数是flags        这个参数可以设置该notification是何种状态        这里设置的是ONGOING,表示这个notification会一直呆在通知栏上面        也可以设置滑动后就消失的样式,看个人的不同需求         */        myNotification.flags = Notification.FLAG_ONGOING_EVENT;        /*        在我们创建的notification中有一个View子类的实例        下面创建了一个RemoteViews的实例        并且配置好各种显示的信息后        将该实例传给notification        往后面看会有一句        myNotification.contentView = contentViews;        这个就是传递实例了         */        RemoteViews contentViews = new RemoteViews(getPackageName(), R.layout.notification_layout);        contentViews.setImageViewResource                (R.id.notification_artist_image, R.drawable.notification_artist_default_image);        contentViews.setTextViewText(R.id.notification_music_title, music_title);        contentViews.setTextViewText(R.id.notification_music_Artist, music_artist);        if(mediaPlayer.isPlaying()){            contentViews.setImageViewResource(R.id.notification_play_button,R.drawable.play_photo);        }        else{            contentViews.setImageViewResource(R.id.notification_play_button,R.drawable.pause_photo);        }        /*        将处理好了的一个View传给notification        让其在通知栏上显示         */        myNotification.contentView = contentViews;        Intent previousButtonIntent = new Intent(NotificationMsg.NOTIFICATION_PREVIOUS_MUSIC);        PendingIntent pendPreviousButtonIntent = PendingIntent.getBroadcast(this, 0, previousButtonIntent, 0);        contentViews.setOnClickPendingIntent(R.id.notification_previous_song_button, pendPreviousButtonIntent);        Intent nextButtonIntent = new Intent(NotificationMsg.NOTIFICATION_NEXT_MUSIC);        PendingIntent pendNextButtonIntent = PendingIntent.getBroadcast(this, 0, nextButtonIntent, 0);        contentViews.setOnClickPendingIntent(R.id.notification_next_song_button, pendNextButtonIntent);        Intent playButtonIntent = new Intent(NotificationMsg.NOTIFICATION_PAUSE_MUSIC);        PendingIntent pendPlayButtonIntent = PendingIntent.getBroadcast(this, 0, playButtonIntent, 0);        contentViews.setOnClickPendingIntent(R.id.notification_play_button, pendPlayButtonIntent);        Intent exitButton = new Intent(NotificationMsg.NOTIFICATION_EXIT);        PendingIntent pendingExitButtonIntent = PendingIntent.getBroadcast(this,0,exitButton,0);        contentViews.setOnClickPendingIntent(R.id.notification_exit_button,pendingExitButtonIntent);        /*        在创建的notification中还有一个intent        Intent :意图,即告诉系统我要干什么,然后系统根据这个Intent做对应的事。        如startActivity相当于发送消息,而Intent是消息的内容。        PendingIntent :包装Intent,Intent 是我们直接使用 startActivity , startService 或 sendBroadcast 启动某项工作的意图。        而某些时候,我们并不能直接调用startActivity , startServide 或 sendBroadcast ,而是当程序或系统达到某一条件才发送Intent。        如这里的Notification,当用户点击Notification之后,由系统发出一条Activity 的 Intent 。        因此如果我们不用某种方法来告诉系统的话,系统是不知道是使用 startActivity ,startService 还是 sendBroadcast 来启动Intent 的(当然还有其他的“描述”),        因此这里便需要PendingIntent。        PendingIntent.getActivity的参数依次为:Context,发送者的请求码(可以填0),用于系统发送的Intent,标志位         */        Intent notificationIntent = new Intent(this, MainActivity.class);        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);        myNotification.contentIntent = contentIntent;        /*        用notificationManager来启动notification        通过调用notify这个函数来启动         */        myNotificationManager.notify(0, myNotification);    }</span>    <span style="color:#ff0000;">BroadcastReceiver onClickReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            Boolean notification_previous_music = false;            Boolean notification_next_music = false;            Boolean notification_pause_music = false;            Boolean notification_exit = false;            notification_msg = intent.getAction();            if (notification_msg.equals(NotificationMsg.NOTIFICATION_PREVIOUS_MUSIC)) {                notification_previous_music = true;            }            if(notification_msg.equals(NotificationMsg.NOTIFICATION_NEXT_MUSIC)){                notification_next_music = true;            }            if(notification_msg.equals(NotificationMsg.NOTIFICATION_PAUSE_MUSIC)){                if(mediaPlayer.isPlaying()){                    notification_pause_music = true;                    initMyNotification();                    stopMusic();                }                else{                    playMusic(current_position);                    initMyNotification();                }            }            if(notification_msg.equals(NotificationMsg.NOTIFICATION_EXIT)){                notification_exit = true;                myNotificationManager.cancelAll();            }            notification_to_activity.putExtra("notification_previous_music",notification_previous_music);            notification_to_activity.putExtra("notification_next_music",notification_next_music);            notification_to_activity.putExtra("notification_pause_music",notification_pause_music);            notification_to_activity.putExtra("notification_exit",notification_exit);            sendBroadcast(notification_to_activity);        }    };</span>}

上面在notification的按钮点击之后,先在service里面做了处理,然后再发广播通知activity做出相应的处理.(
<span style="color:#ff0000;">sendBroadcast(notification_to_activity);</span>
)

在activity中的部分代码如下:

    private boolean notification_previous_music;                           //通知栏上一首    private boolean notification_next_music;                               //通知栏下一首    private boolean notification_pause_music;                              //通知栏停止播放    private boolean notification_exit;                                     //通知栏退出    private NotificationReceiver notificationReceiver;                     //通知栏广播接收器        notificationReceiver = new NotificationReceiver();        IntentFilter intentNotificationFilter = new IntentFilter();        intentNotificationFilter.addAction("com.example.communication.NOTIFICATION_TO_ACTIVITY");        registerReceiver(notificationReceiver,intentNotificationFilter);    private class NotificationReceiver extends BroadcastReceiver{        @Override        public void onReceive(Context context, Intent intent) {            notification_previous_music = intent.getBooleanExtra("notification_previous_music",false);            notification_next_music = intent.getBooleanExtra("notification_next_music",false);            notification_pause_music = intent.getBooleanExtra("notification_pause_music",false);            notification_exit = intent.getBooleanExtra("notification_exit",false);            if(notification_previous_music){                changeMusic(play_mode,AppConstant.PlayerMsg.PREVIOUS_MUSIC,mp3Infos);            }            if(notification_next_music){                changeMusic(play_mode,AppConstant.PlayerMsg.NEXT_MUSIC,mp3Infos);            }            if(notification_pause_music){                play_button.setImageResource(R.drawable.play_photo);            }            else{                play_button.setImageResource(R.drawable.pause_photo);            }            if(notification_exit){                System.exit(0);            }        }    }

        代码很简单,读读就能懂哈,这篇给的代码有点长了,主要介绍的notification的用法,后面的一大段一大段是接着前面的项目在继续,大家可以选择性的看一看.

         

         在下一期博客中,我们将介绍android上的数据库使用,记录最近播放的音乐,也差不多快到尾声了,这个小系列从2014年写到了2015年,估计是最长时间的了,,,23333大笑.今天就写到这里咯,明天见~~~~~88


0 0