文章详情

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

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2023-07-05 23:01

关注

今天小编给大家分享一下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

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯