11.Notification通知控制播放

yangchong211 / 文 发表于2018-03-09 16:15 次阅读

目录介绍

  • 1.Notification通知
  • 1.1 为什么需要通知栏
  • 1.2 创建通知栏工具类
  • 2.代码逻辑展示
  • 2.1 初始化通知工具类
  • 2.2 在通知工具类中创建播放暂停方法
  • 2.3 完整的工具类代码
  • 3.点击通知栏根布局操作
  • 3.1 点击根布局回主页面
  • 3.2 在主页面做的操作
  • 3.3

1.Notification通知

1.1 为什么需要通知栏

  • 一般音频类播放器,都会有通知栏,当程序切换到后台时,可以通过通知栏来控制音频的播放暂停,上一首,下一首,或者其他的功能

1.2 创建通知栏工具类

  • 为了方便管理,可以创建一个通知栏工具类。这个很有必要。因为通知栏中信息和音频播放界面的信息要同步,因此在播放service服务中,通过调用通知工具类即可达到效果

2.代码逻辑展示

2.1 初始化通知工具类

  • 在PlayService类中初始化,代码如下所示:
/**
 * 首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或 onBind() 之前)。
 * 如果服务已在运行,则不会调用此方法。该方法只被调用一次
 */
@Override
public void onCreate() {
    super.onCreate();
    audioMusics = new ArrayList<>();
    NotificationUtils.init(this);
    createMediaPlayer();
    initMediaSessionManager();
    initAudioFocusManager();
    initEarPhoneBroadcastReceiver();
    initAudioBroadcastReceiver();
    initQuitTimer();
}

2.2 在通知工具类中创建播放暂停方法

  • 通过通知栏中按钮,可以控制音频播放与暂停的功能。
/**
 * 开始播放
 * @param music             music
 */
public static void showPlay(AudioMusic music) {
    playService.startForeground(NOTIFICATION_ID, buildNotification(playService, music, true));
}

/**
 * 暂停
 * @param music             music
 */
public static void showPause(AudioMusic music) {
    playService.stopForeground(false);
    notificationManager.notify(NOTIFICATION_ID, buildNotification(playService, music, false));
}

2.3 完整的工具类代码

public class NotificationUtils {

    /**
     * NotificationManager的引用
     */
    private static NotificationManager notificationManager;
    private static PlayService playService;
    private static final int NOTIFICATION_ID = 0x1314;

    /**
     * 1.创建一个NotificationManager的引用
     * @param playService           PlayService对象
     */
    public static void init(PlayService playService) {
        NotificationUtils.playService = playService;
        notificationManager = (NotificationManager) playService.getSystemService(Context.NOTIFICATION_SERVICE);
    }

    /**
     * 开始播放
     * @param music             music
     */
    public static void showPlay(AudioMusic music) {
        playService.startForeground(NOTIFICATION_ID, buildNotification(playService, music, true));
    }

    /**
     * 暂停
     * @param music             music
     */
    public static void showPause(AudioMusic music) {
        playService.stopForeground(false);
        notificationManager.notify(NOTIFICATION_ID, buildNotification(playService, music, false));
    }

    /**
     * 结束所有的
     */
    public static void cancelAll() {
        notificationManager.cancelAll();
    }

    /**
     * 2.创建Notification对象,定义Notification的各种属性
     * @return                      Notification对象
     */
    private static Notification buildNotification(PlayService context , AudioMusic music , boolean isPlaying){
        Intent intent = new Intent(context, MainHomeActivity.class);
        intent.putExtra(Constant.EXTRA_NOTIFICATION, true);
        intent.setAction(Intent.ACTION_VIEW);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
                intent, PendingIntent.FLAG_UPDATE_CURRENT);

        Notification.Builder mBuilder = new Notification.Builder(context)
                //.setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI)
                //设置通知的图标
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(pendingIntent)
                .setContent(getCustomViews(context,music,isPlaying))
                //设置状态栏的标题
                //.setTicker("有新消息呢")
                //设置标题
                //.setContentTitle("这个是标题2")
                //消息内容
                //.setContentText("这个是内容2")
                //在右边显示一个数量,等价于setContentInfo函数.如果有设置setContentInfo函数,那么本函数会给覆盖
                //.setNumber(12)
                //是否提示一次.true - 如果Notification已经存在状态栏即使在调用notify函数也不会更新
                //.setOnlyAlertOnce(true)
                //滚动条,indeterminate true - 不确定的,不会显示进度,false - 根据max和progress情况显示进度条
                //.setProgress (100, 50, true)
                //设置默认的提示音
                //.setDefaults(Notification.DEFAULT_ALL)
                //设置该通知的优先级
                //.setPriority(Notification.PRIORITY_DEFAULT)
                //让通知左右滑的时候不能取消通知
                .setOngoing(true)
                //设置该通知的优先级
                //.setPriority(Notification.PRIORITY_DEFAULT)
                //设置通知时间,默认为系统发出通知的时间,通常不用设置
                //.setWhen(System.currentTimeMillis())
                //打开程序后图标消失
                .setAutoCancel(false);
        return mBuilder.build();
    }

    /**
     * 设置自定义通知栏布局
     * @param context                   上下文
     * @param music
     * @return                          RemoteViews
     */
    private static RemoteViews getCustomViews(PlayService context, AudioMusic music, boolean isPlaying) {
        String title = music.getTitle();
        String subtitle = FileMusicUtils.getArtistAndAlbum(music.getArtist(), music.getAlbum());
        Bitmap cover = CoverLoader.getInstance().loadThumbnail(music);

        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.notification_player);
        if (cover != null) {
            remoteViews.setImageViewBitmap(R.id.iv_image, cover);
        } else {
            remoteViews.setImageViewResource(R.id.iv_image, R.mipmap.ic_launcher);
        }
        remoteViews.setTextViewText(R.id.tv_title, title);
        remoteViews.setTextViewText(R.id.tv_artist, subtitle);
        if(isPlaying){
            remoteViews.setImageViewResource(R.id.btn_start,R.drawable.notify_btn_dark_pause_normal);
        }else {
            remoteViews.setImageViewResource(R.id.btn_start,R.drawable.notify_btn_dark_play_normal);
        }

        // 设置 点击通知栏的上一首按钮时要执行的意图
        remoteViews.setOnClickPendingIntent(R.id.btn_pre, getReceiverPendingIntent(context, MusicPlayAction.TYPE_PRE,1));
        // 设置 点击通知栏的下一首按钮时要执行的意图
        remoteViews.setOnClickPendingIntent(R.id.btn_next, getReceiverPendingIntent(context, MusicPlayAction.TYPE_NEXT,2));
        // 设置 点击通知栏的播放暂停按钮时要执行的意图
        remoteViews.setOnClickPendingIntent(R.id.btn_start, getReceiverPendingIntent(context, MusicPlayAction.TYPE_START_PAUSE,3));
        // 设置 点击通知栏的根容器时要执行的意图
        //remoteViews.setOnClickPendingIntent(R.id.ll_root, getActivityPendingIntent(context));
        return remoteViews;
    }

    private static PendingIntent getActivityPendingIntent(PlayService context) {
        Intent intent = new Intent(context, MainHomeActivity.class);
        intent.putExtra(Constant.EXTRA_NOTIFICATION, true);
        intent.setAction(Intent.ACTION_VIEW);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        return PendingIntent.getActivity(context, 0,
                intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    private static PendingIntent getReceiverPendingIntent(PlayService context, String type , int code) {
        Intent intent = new Intent(NotificationStatusBarReceiver.ACTION_STATUS_BAR);
        intent.putExtra(NotificationStatusBarReceiver.EXTRA, type);
        return PendingIntent.getBroadcast(context, code, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }
}

3.点击通知栏根布局操作

3.1 点击根布局回主页面

  • 3.1.1 在通知工具类中
  • image

3.2 在主页面做的操作

  • 代码如下所示
/**
 * 处理onNewIntent(),以通知碎片管理器 状态未保存。
 * 如果您正在处理新的意图,并且可能是 对碎片状态进行更改时,要确保调用先到这里。
 * 否则,如果你的状态保存,但活动未停止,则可以获得 onNewIntent()调用,发生在onResume()之前,
 * 并试图 此时执行片段操作将引发IllegalStateException。 因为碎片管理器认为状态仍然保存。
 * @param intent intent
 */
@Override
protected void onNewIntent(Intent intent) {
    setIntent(intent);
    parseIntent();
}
  • 接着看parseIntent()代码
  • 这里我写的逻辑是回到主页面并且展示播放音频详情页面Fragment。具体你可以根据自己情况来定。
/**
 * 从通知栏点击进入音频播放详情页面
 */
private void parseIntent() {
    Intent intent = getIntent();
    if (intent.hasExtra(Constant.EXTRA_NOTIFICATION)) {
        showPlayingFragment();
        setIntent(new Intent());
    }
}
收藏 赞 (0) 踩 (0)