我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android媒体通知栏多系统适配怎么实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android媒体通知栏多系统适配怎么实现

今天小编给大家分享一下Android媒体通知栏多系统适配怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

需要考虑的问题如下:

1,通知栏适配,音乐播放需要常驻,所以要维护一个通知栏。

2,音控处理,在安卓7.0及以下,通过MediaSessionCompat可控制锁屏页音乐播放。

3,对于耳机的处理,不管是线耳机还是蓝牙耳机,耳机控制播放暂停,下一曲上一曲等操作。

4,打电话处理,在听音乐的同时如果电话进来后挂断,希望可以自动播放。

5,音频播放焦点处理,如果有别的应用抢占焦点可进行暂停播放。还有就是进入APP时想拥有音频焦点,都可以通过AudioManager进行处理。

实现方式

创建通知管理类NotifyBuilderManager代码如下:

package com.idujing.myapplication.manager;import android.annotation.SuppressLint;import android.app.Notification;import android.app.NotificationChannel;import android.app.NotificationManager;import android.app.PendingIntent;import android.app.Service;import android.content.Context;import android.content.Intent;import android.os.Build;import androidx.core.app.NotificationCompat;import com.idujing.myapplication.R;public class NotifyBuilderManager {    private final String TAG = getClass().getSimpleName();    public static final String ACTION_NEXT = "com.idujing.play.notify.next";// 下一首    public static final String ACTION_PREV = "com.idujing.play.notify.prev";// 上一首    public static final String ACTION_PLAY_PAUSE = "com.idujing.play.notify.play_state";// 播放暂停广播    private static final int NOTIFICATION_ID = 0x123;    private Service mContext;    private Notification mNotification;    private NotificationManager mNotificationManager;    private NotificationCompat.Builder mNotificationBuilder;    private MediaSessionManager mSessionManager;    private PendingIntent mPendingPlay;    private PendingIntent mPendingPre;    private PendingIntent mPendingNext;    private boolean isRunningForeground = false;    public boolean isRunningForeground() {        return isRunningForeground;    }    public NotifyBuilderManager(Service context) {        this.mContext = context;        mSessionManager = new MediaSessionManager(context, null);    }        private void initNotify() {        mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);        Class<?> clazz = null;        try {            clazz = Class.forName("具体的播放器类名");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        // 适配12.0及以上        int flag;        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {            flag = PendingIntent.FLAG_IMMUTABLE;        } else {            flag = PendingIntent.FLAG_UPDATE_CURRENT;        }        //绑定事件通过创建的具体广播去接收即可。        Intent infoIntent = new Intent(mContext, clazz);        PendingIntent pendingInfo = PendingIntent.getActivity(mContext, 0, infoIntent, flag);        Intent preIntent = new Intent();        preIntent.setAction(ACTION_PREV);        mPendingPre = PendingIntent.getBroadcast(mContext, 1, preIntent, flag);        Intent playIntent = new Intent();        playIntent.setAction(ACTION_PLAY_PAUSE);        mPendingPlay = PendingIntent.getBroadcast(mContext, 2, playIntent, flag);        Intent nextIntent = new Intent();        nextIntent.setAction(ACTION_NEXT);        mPendingNext = PendingIntent.getBroadcast(mContext, 3, nextIntent, PendingIntent.FLAG_IMMUTABLE);        androidx.media.app.NotificationCompat.MediaStyle style = new androidx.media.app.NotificationCompat.MediaStyle()                .setShowActionsInCompactView(0, 1, 2)                .setMediaSession(mSessionManager.getMediaSession());        mNotificationBuilder = new NotificationCompat.Builder(mContext, initChannelId())                .setSmallIcon(R.mipmap.ic_launcher)                .setPriority(NotificationCompat.PRIORITY_MAX)                .setContentIntent(pendingInfo)                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)                .setStyle(style);        isRunningForeground = true;    }        private String initChannelId() {        // 通知渠道的id        String id = "music_01";        // 用户可以看到的通知渠道的名字.        CharSequence name = mContext.getString(R.string.app_name);        // 用户可以看到的通知渠道的描述        String description = "通知栏播放控制";        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {            int importance = NotificationManager.IMPORTANCE_LOW;            NotificationChannel channel = new NotificationChannel(id, name, importance);            channel.setDescription(description);            channel.enableLights(false);            channel.enableVibration(false);            mNotificationManager.createNotificationChannel(channel);        }        return id;    }        public void cancelNotification() {        if (mNotificationManager != null) {            mContext.stopForeground(true);            mNotificationManager.cancel(NOTIFICATION_ID);            isRunningForeground = false;        }    }        private void updateCoverSmall() {        Glide.with(mContext).asBitmap()                .load(url)                .into(new CustomTarget<Bitmap>() {                    @Override                    public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {                        mNotificationBuilder.setLargeIcon(resource);                        mNotification = mNotificationBuilder.build();                        mNotificationManager.notify(NOTIFICATION_ID, mNotification);                    }                    @Override                    public void onLoadCleared(@Nullable Drawable placeholder) {                    }                    @Override                    public void onLoadFailed(@Nullable Drawable errorDrawable) {                        super.onLoadFailed(errorDrawable);                        Log.e(TAG, "onLoadFailed: ");                    }                });    }        @SuppressLint("RestrictedApi")    public void updateNotification(boolean isMusicPlaying) {        if (mNotification == null) {            initNotify();        }        mSessionManager.updateMetaData();        if (mNotificationBuilder != null) {            int playButtonResId = isMusicPlaying                    ? android.R.drawable.ic_media_pause : android.R.drawable.ic_media_play;            if (!mNotificationBuilder.mActions.isEmpty()) {                mNotificationBuilder.mActions.clear();            }            mNotificationBuilder                    .addAction(android.R.drawable.ic_media_previous, "Previous", mPendingPre) // #0                    .addAction(playButtonResId, "Pause", mPendingPlay)  // #1                    .addAction(android.R.drawable.ic_media_next, "Next", mPendingNext);            mNotificationBuilder.setContentTitle("主标题");            mNotificationBuilder.setContentText("副标题");            updateCoverSmall();            mNotification = mNotificationBuilder.build();            mContext.startForeground(NOTIFICATION_ID, mNotification);            mNotificationManager.notify(NOTIFICATION_ID, mNotification);        }    }}

创建音控管理类MediaSessionManager代码如下:

package com.idujing.myapplication.manager;import android.content.Context;import android.os.Handler;import android.support.v4.media.MediaMetadataCompat;import android.support.v4.media.session.MediaSessionCompat;import android.support.v4.media.session.PlaybackStateCompat;public class MediaSessionManager {    private static final String TAG = "MediaSessionManager";    //指定可以接收的来自锁屏页面的按键信息    private static final long MEDIA_SESSION_ACTIONS =            PlaybackStateCompat.ACTION_PLAY                    | PlaybackStateCompat.ACTION_PAUSE                    | PlaybackStateCompat.ACTION_PLAY_PAUSE                    | PlaybackStateCompat.ACTION_SKIP_TO_NEXT                    | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS                    | PlaybackStateCompat.ACTION_STOP                    | PlaybackStateCompat.ACTION_SEEK_TO;    private final Context mContext;    private MediaSessionCompat mMediaSession;    private Handler mHandler;    public MediaSessionManager(Context context, Handler handler) {        this.mContext = context;        this.mHandler = handler;        setupMediaSession();    }        protected boolean isPlaying() {        //具体去实现        return false;    }        private void setupMediaSession() {        mMediaSession = new MediaSessionCompat(mContext, TAG);        //指明支持的按键信息类型        mMediaSession.setFlags(                MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |                        MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS        );        mMediaSession.setCallback(callback, mHandler);        mMediaSession.setActive(true);    }        public void updateMetaData() {        MediaMetadataCompat.Builder metaDta = new MediaMetadataCompat.Builder()                .putString(MediaMetadataCompat.METADATA_KEY_TITLE, "title")                .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, "Artist")                .putString(MediaMetadataCompat.METADATA_KEY_ALBUM, "Album")                .putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ARTIST, "Artist")                .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, 100);        mMediaSession.setMetadata(metaDta.build());        int state = isPlaying() ? PlaybackStateCompat.STATE_PLAYING :                PlaybackStateCompat.STATE_PAUSED;        mMediaSession.setPlaybackState(new PlaybackStateCompat.Builder()                .setActions(MEDIA_SESSION_ACTIONS)                .setState(state, 0, 1)                .build());   //锁屏页封面设置,高本版没有效果,因为通知栏权限调整。        Glide.with(mContext).asBitmap().                load(url)                .into(new CustomTarget<Bitmap>() {                    @Override                    public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {                        metaDta.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, resource);                        mMediaSession.setMetadata(metaDta.build());                    }                    @Override                    public void onLoadCleared(@Nullable Drawable placeholder) {                    }                });    }    public MediaSessionCompat.Token getMediaSession() {        return mMediaSession.getSessionToken();    }        public void release() {        mMediaSession.setCallback(null);        mMediaSession.setActive(false);        mMediaSession.release();    }        private MediaSessionCompat.Callback callback = new MediaSessionCompat.Callback() {        @Override        public void onPlay() {           //具体自己实现        }        @Override        public void onPause() {        }        @Override        public void onSkipToNext() {        }        @Override        public void onSkipToPrevious() {        }        @Override        public void onStop() {        }        @Override        public void onSeekTo(long pos) {        }    };}

创建音频焦点控制类AudioAndFocusManager

通过音频焦点控制,不管是别的应用抢占焦点,还是打电话都可以接收到状态。

package com.idujing.myapplication.manager;import android.content.Context;import android.media.AudioFocusRequest;import android.media.AudioManager;import android.os.Build;import android.util.Log;import androidx.annotation.RequiresApi;public class AudioAndFocusManager {    private static final String TAG = "AudioAndFocusManager";    private AudioManager mAudioManager;    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)    public AudioAndFocusManager(Context mContext) {        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);    }        public void requestAudioFocus() {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {            AudioFocusRequest mAudioFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)                    .setOnAudioFocusChangeListener(audioFocusChangeListener)                    .build();            int res = mAudioManager.requestAudioFocus(mAudioFocusRequest);            if (res == 1) {                Log.e(TAG, "res=" + true);            }        } else {            if (audioFocusChangeListener != null) {                boolean result = AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==                        mAudioManager.requestAudioFocus(audioFocusChangeListener,                                AudioManager.STREAM_MUSIC,                                AudioManager.AUDIOFOCUS_GAIN);                Log.e(TAG, "requestAudioFocus result=" + result);            }        }    }        public void abandonAudioFocus() {        if (audioFocusChangeListener != null) {            boolean result = AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==                    mAudioManager.abandonAudioFocus(audioFocusChangeListener);            Log.e(TAG, "abandonAudioFocus result=" + result);        }    }        private AudioManager.OnAudioFocusChangeListener audioFocusChangeListener = focusChange -> {        switch (focusChange) {            case AudioManager.AUDIOFOCUS_LOSS://失去音频焦点            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT://暂时失去焦点                break;            case AudioManager.AUDIOFOCUS_GAIN://获取焦点                break;            default:        }    };}

以上就是“Android媒体通知栏多系统适配怎么实现”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android媒体通知栏多系统适配怎么实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android媒体通知栏多系统适配怎么实现

今天小编给大家分享一下Android媒体通知栏多系统适配怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。需要考虑的问题
2023-07-05

Android媒体通知栏多系统适配实例讲解

对于Android来说其中一项很方便的操作便是下拉菜单,下拉菜单栏可以快捷打开某项设置,这篇文章主要给大家介绍了关于Android通知栏增加快捷开关的功能实现,需要的朋友可以参考下
2023-05-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录