android 以音频播放器为例实现通知栏显示通知,并实现切歌、暂停、播放,并实现加载网络图片,并实现关闭第三方APP音频
首先先给大家看下效果接下来我们看下具体如何实施1、首先我们创建一个音频的单例对象,这样能保证每次在播放的的音频是唯一的(类名如:MediaPlayerUtil.java)package xxx;import android.media.AudioManager;import android.media.MediaPlayer;import android.util.Log...
首先先给大家看下效果
接下来我们看下具体如何实施
1、首先我们创建一个音频的单例对象,这样能保证每次在播放的的音频是唯一的(类名如:MediaPlayerUtil.java)
package xxx;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.util.Log;
import xx.activity.couxrse.SoundPlayerActivity;
import xx.model.bo.AudioBo;
import java.util.List;
/**
*
* 音频播放器
*/
public class MediaPlayerUtil {
private int index=0; // 记录音频重新被加载时上次选中的条目下标,对应集合的下标
private String path; // 对应集合下标index在数据中的音频
private String title;
private int duration; // 时长
private List<AudioBo> audioBoList;
private MediaPlayer mPlayer;
// 类初始化的时候立即加载该对象
private static MediaPlayerUtil mediaPlayerInstance;
// 私有化构造器
public MediaPlayerUtil() {
}
// 提供该对象的获取方法(单例模式)
public synchronized static MediaPlayerUtil getInstance() {
if(mediaPlayerInstance == null)
{
mediaPlayerInstance = new MediaPlayerUtil();
}
return mediaPlayerInstance;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public int getDuration() { return duration; }
public void setDuration(int duration) { this.duration = duration; }
public List<AudioBo> getAudioBoList() { return audioBoList; }
public void setAudioBoList(List<AudioBo> audioBoList) { this.audioBoList = audioBoList; }
public MediaPlayer getmPlayer() { return mPlayer; }
public void setmPlayer(MediaPlayer mPlayer) { this.mPlayer = mPlayer; }
//播放方法
public void play() {
if(mPlayer!=null){
mPlayer.stop();
mPlayer.release(); // 释放相关的资源。
mPlayer=null;
}
try {
mPlayer = new MediaPlayer();
// 设置指定的流媒体地址
mPlayer.setDataSource(path);
// 设置音频流的类型
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
/* 准备播放 */
mPlayer.prepare();
mPlayer.start();
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
System.out.println(title+"播放完毕");
Log.d("tag", title+"播放完毕");
index=index+1;
path=audioBoList.get(index).getUrl();
title=audioBoList.get(index).getTitle();
System.out.println("准备播放"+title);
Log.d("tag", "准备播放"+title);
play();
//根据需要添加自己的代码。。。
if(NotifityActivity.getInstace()!=null){
NotifityActivity.getInstace().updateUI();
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public void replay(String path){
if (mPlayer != null && mPlayer.isPlaying()) {
mPlayer.seekTo(0);
return;
}
play();
}
//暂停
public void pause() {
mPlayer.pause();
}
//判断是否正在播放中
public boolean isplay() {
return mPlayer.isPlaying();
}
//获取播放时长
public long getduring() {
// TODO Auto-generated method stub
return mPlayer.getDuration();
}
//停止
public void stop() {
if(mPlayer!=null){
mPlayer.stop();
}
}
public void setPosition (int position) {
mPlayer.seekTo(position);//重新设定播放进度
}
/**
* 关闭播放器
*/
public void closeMedia() {
if (mPlayer != null ) {
mPlayer.stop();
mPlayer.release(); // 释放相关的资源。
mPlayer=null;
}
}
}
2、音频实体类
private Long id;
private String catalog; // 类别
private String title; // 标题
private int count; // 播放次数
private int duration; // 时长
private String publishTime; // 发布时间
private String url; // 地址
private String createTime; // 创建时间
private String updateTime; // 更新时间
private int delFlag;// 是否删除
private String imgUrl; // 相对应的背景图路径
3、添加一个service服务类,增加音频后台播放功能
package xx.activity.course.audio;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class MediaService extends Service {
public class MusicController extends Binder {
}
/**
* 当绑定服务的时候,自动回调这个方法
* 返回的对象可以直接操作Service内部的内容
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
return new MusicController();
}
@Override
public void onCreate() {
super.onCreate();
}
/**
* 任意一次unbindService()方法,都会触发这个方法
* 用于释放一些绑定时使用的资源
* @param intent
* @return
*/
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
}
4、在AndroidManifest.xml 加入以下代码
<service android:name="文件路径"
android:enabled="true"
android:exported="true"
/>
5、创建广播类(BroadcastReceiver) 实现对通知栏点击事件的实现以及回调(静态注册)
package xx.activity.course.audio;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaPlayer;
import android.widget.Toast;
import xx.activity.course.SoundPlayerActivity;
import xx.fragment.classroom.holder.HomeAudioHolder;
import xx.media.MediaPlayerUtil;
/*
* 通知栏--点击事件之调用广播实现相对应点击事件的逻辑处理
* */
public class NotificationClickReceiver extends BroadcastReceiver {
public static final String TYPE = "type"; //这个type是为了Notification更新信息的
private MediaPlayerUtil mediaPlayerUtil;
private MediaPlayer mediaPlayer;
private int postion;
private int endIndex;
private Context context;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
this.context = context;
mediaPlayerUtil = MediaPlayerUtil.getInstance();
endIndex = mediaPlayerUtil.getAudioBoList().size() - 1;
int type = intent.getIntExtra(TYPE, -1);
if (type != -1) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(type);
}
if (action.equals("stop")) {
//处理停止或播放点击事件
mediaPlayerUtil = MediaPlayerUtil.getInstance();
if (mediaPlayerUtil.getmPlayer()!=null && mediaPlayerUtil.isplay()) {
mediaPlayerUtil.stop();
} else {
mediaPlayerUtil.setPath(mediaPlayerUtil.getAudioBoList().get(mediaPlayerUtil.getIndex()).getUrl());
mediaPlayerUtil.play();
}
}
if (action.equals("next")) {
mediaPlayerUtil.stop();
mediaPlayerUtil = MediaPlayerUtil.getInstance();
int index = mediaPlayerUtil.getIndex();
if ((index + 1) > endIndex) {
Toast.makeText(context, "已经是最后一首了", Toast.LENGTH_SHORT).show();
return;
}
postion = index + 1;
mediaPlayerUtil.setIndex(postion);
mediaPlayerUtil.setPath(mediaPlayerUtil.getAudioBoList().get(postion).getUrl());
mediaPlayerUtil.setTitle(mediaPlayerUtil.getAudioBoList().get(postion).getTitle());
mediaPlayerUtil.play();
}
if (action.equals("last")) {
mediaPlayerUtil.stop();
mediaPlayerUtil = MediaPlayerUtil.getInstance();
//处理上一首
int index = mediaPlayerUtil.getIndex();
if ((index - 1) < 0) {
Toast.makeText(context, "已经是第一首了", Toast.LENGTH_SHORT).show();
return;
}
postion = index - 1;
mediaPlayerUtil.setIndex(postion);
mediaPlayerUtil.setPath(mediaPlayerUtil.getAudioBoList().get(postion).getUrl());
mediaPlayerUtil.setTitle(mediaPlayerUtil.getAudioBoList().get(postion).getTitle());
mediaPlayerUtil.play();
}
// 关闭通知栏
if (action.equals("notification_cancelled")) {
NotifityActivity.getInstace().closeNotifi();
return;
}
// 更新音频页通知栏
if (NotifityActivity.getInstace() != null) {
NotifityActivity.getInstace().updateUI();
}
}
}
5、在AndroidManifest.xml 加入以下代码
<!--通知栏广播 -->
<receiver android:name="xx.activity.course.audio.NotificationClickReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="notification_cancelled"/>
<action android:name="next"/>
<action android:name="stop"/>
<action android:name="last"/>
</intent-filter>
</receiver>
6、创建通知栏远程视图(RemoteViews)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="100dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 音乐播放器 -->
<FrameLayout
android:layout_width="100dp"
android:layout_height="100dp">
<ImageView
android:id="@+id/bgmmMusicImageView"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:scaleType="centerCrop"
android:background="@drawable/test"
/>
<!-- 这里的background设置成了浅色,图标设置为深色,
效果是:在白色的通知栏上图标颜色为深色,在深色图标显示的图标则为浅色,
因为不同手机的通知栏背景色并不是一致的,大概分为两种,白色或黑色,我们这里设置成统一的 -->
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/base_F3F3F3"
android:paddingTop="5dp">
<!--<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:layout_gravity="right">
<ImageView
android:id="@+id/audio_close_btn"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:background="@drawable/player_icon_plays" />
</LinearLayout>-->
<LinearLayout
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="5dp"
android:paddingRight="10dp">
<TextView
android:id="@+id/musicTitleTextView"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="false"
android:focusable="true"
android:paddingLeft="15dp"
android:textColor="@color/black"
android:text="头条"
android:textSize="14sp" />
<ImageView
android:layout_alignParentRight="true"
android:id="@+id/audio_close_btn"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/player_icon_close"
android:gravity="right" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<!--上一首-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/lastImageView"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/player_icon_last" />
/>
</LinearLayout>
<!-- 播放/暂停 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/stopImageView"
android:layout_width="20dp"
android:layout_height="20dp" />
</LinearLayout>
<!-- 下一首 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/nextImageView"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/player_icon_next" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
7、对应的activity中的设置
package com.lidou.quke.activity.course.audio;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.view.View;
import android.widget.Button;
import android.widget.RemoteViews;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.NotificationTarget;
import com.xx.R;
import xx.activity.BusinessActivity;
import com.xx.media.MediaPlayerUtil;
import com.xx.model.bo.AudioBo;
import java.util.ArrayList;
import java.util.List;
/*
* 音频列表activity
* */
public class NotifityActivity extends BusinessActivity implements ServiceConnection {
private static final int SDK_PAY_FLAG = 1;
private final static String TAG = "加载SoundPlayerActivity类";
private Button mbutton;
private MediaPlayer mPlayer;
// 这里如果不设置为-1 的话,默认是0,会造成进入列表第一条数据就显示为播放状态
private int thisPosition;
String channelId = "音频会话";//渠道id
private MediaPlayerUtil mediaPlayerUtil;
private Notification notification;
private RemoteViews contentView;
private NotificationTarget notificationTarget;
private AudioManager mAudioManager;
// 检索了NotifityActivity的运行实例,以方便广播接收成功时处理activity相对应的逻辑处理(如:更新UI)
private static NotifityActivity notifityActivity;
public static NotifityActivity getInstace() {
return notifityActivity;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
notifityActivity = this;
setContentView(R.layout.acs);
Intent intent = new Intent(this, MediaService.class);
//增加StartService,来增加后台播放功能
startService(intent);
bindService(intent, this, BIND_AUTO_CREATE);
// 这里只是用来做测试数据
List<AudioBo> audioBoList=new ArrayList<AudioBo>();
AudioBo audioBo=new AudioBo();
int a1 = 0;long b1 = (int)a1;
audioBo.setId(b1);
audioBo.setTitle("音频1");
audioBo.setUrl("音频路径地址");
audioBo.setImgUrl("网络图片地址");
audioBoList.add(audioBo);
AudioBo audioBo2=new AudioBo();
int a = 1;long b = (int)a;
audioBo2.setId(b);
audioBo2.setTitle("音频2");
audioBo2.setUrl("音频路径地址");
audioBo2.setImgUrl("网络图片地址");
audioBoList.add(audioBo2);
mediaPlayerUtil=MediaPlayerUtil.getInstance();
mediaPlayerUtil.setAudioBoList(audioBoList);
initView();
}
private void initView() {
// 我这里是在一个页面中的button事件唤起通知栏
mbutton=findViewById(R.id.notifyButton);
mbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mediaPlayerUtil=MediaPlayerUtil.getInstance();
// 调用通知栏加载方法
initNotificationBar();
// 1.上下文 2.图标控件的ResID 2.RemoteView ,4 Notification 5 Notification_ID
notificationTarget = new NotificationTarget(mContext, R.id.bgmmMusicImageView, contentView, notification, R.string.app_name);
Glide.with(mContext).asBitmap().load(mediaPlayerUtil.getAudioBoList().get(0).getImgUrl())
.placeholder(R.drawable.test).into(notificationTarget);
}
});
//1 初始化AudioManager对象
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
//2 申请焦点(关闭其它音频通道)
mAudioManager.requestAudioFocus(mAudioFocusChange, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
mediaPlayerUtil = MediaPlayerUtil.getInstance();
if (mediaPlayerUtil != null) {
thisPosition = mediaPlayerUtil.getIndex();
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
/*
* 创建自定义远程视图RemoteView
* */
private void initRemoteView() {
contentView = new RemoteViews(getPackageName(), R.layout.audio_music_notifi);// 远程视图
mediaPlayerUtil = MediaPlayerUtil.getInstance();
contentView.setTextViewText(R.id.musicTitleTextView, mediaPlayerUtil.getAudioBoList().get(mediaPlayerUtil.getIndex()).getTitle());
contentView.setImageViewResource(R.id.audio_close_btn, R.drawable.player_icon_close);
contentView.setImageViewResource(R.id.lastImageView, R.drawable.player_icon_last);
contentView.setImageViewResource(R.id.nextImageView, R.drawable.player_icon_next);
contentView.setImageViewResource(R.id.stopImageView, R.drawable.player_icon_stop);
if (mediaPlayerUtil.getmPlayer()!=null && mediaPlayerUtil.isplay()) {
contentView.setImageViewResource(R.id.stopImageView, R.drawable.player_icon_plays);
} else {
contentView.setImageViewResource(R.id.stopImageView, R.drawable.player_icon_stop);
}
// 实现停止/播放
Intent intentStop = new Intent("stop");
PendingIntent pIntentStop = PendingIntent.getBroadcast(this, 0, intentStop, 0);
contentView.setOnClickPendingIntent(R.id.stopImageView, pIntentStop);
//下一首事件
Intent intentNext = new Intent("next");//发送播放下一曲的通知
PendingIntent pIntentNext = PendingIntent.getBroadcast(this, 0, intentNext, 0);
contentView.setOnClickPendingIntent(R.id.nextImageView, pIntentNext);
//上一首事件
Intent intentLast = new Intent("last");//发送播放上一曲的通知
PendingIntent pIntentLast = PendingIntent.getBroadcast(this, 0, intentLast, 0);
contentView.setOnClickPendingIntent(R.id.lastImageView, pIntentLast);
// 关闭通知栏
Intent intentCancelled = new Intent("notification_cancelled");
PendingIntent pIntentCancelled = PendingIntent.getBroadcast(this, 0, intentCancelled, 0);
contentView.setOnClickPendingIntent(R.id.audio_close_btn, pIntentCancelled);
}
/*
* 创建通知栏
* */
private void initNotificationBar() {
initRemoteView();
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notification=new Notification();
Intent intent = new Intent(mContext, NotificationClickReceiver.class); // 创建一个跳转到活动页面的意图
PendingIntent pendingIntent = PendingIntent.getActivity(NotifityActivity.this, R.string.app_name, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification.Builder builder = null; // 创建一个通知消息的构造器
// 判断是否是android 8以上的版本,因为从8.0版本后唤起通知栏必须要填写渠道id和渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String description = "有趣,有用,有未来";
int importance = NotificationManager.IMPORTANCE_LOW;//重要性级别
// getPackageName() 获取APP渠道名称
NotificationChannel mChannel = new NotificationChannel(channelId, "音频", importance);
mChannel.setDescription(description);//渠道描述
manager.createNotificationChannel(mChannel);//创建通知渠道
mChannel.setSound(null,null);
builder = new Notification.Builder(this, channelId);
builder.setContentIntent(pendingIntent)
.setCustomContentView(contentView)
.setCustomBigContentView(contentView)
.setShowWhen(false)
.setSmallIcon(R.drawable.notification_icon) // 必填
.build();
notification = builder.build();
}else{ // 这里要兼顾android 8以下的版本
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(mContext,channelId);
notificationBuilder.setCustomBigContentView(contentView)
.setCustomContentView(contentView)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.notification_icon)
.build();
notification = notificationBuilder.build();
}
notification.flags = notification.FLAG_NO_CLEAR;//设置通知点击或滑动时不被清除*/
manager.notify(R.string.app_name, notification);
}
/**
* [获取应用程序版本名称信息]
*
* @param context
* @return 当前应用的版本名称
*/
public static synchronized String getPackageName(Context context) {
try {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(
context.getPackageName(), 0);
return packageInfo.packageName;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onDestroy() {
unbindService(this);
super.onDestroy();
}
// 调用广播回调来更新activity中相关事件
public void updateUI() {
NotifityActivity.this.runOnUiThread(new Runnable() {
public void run() {
initView();
initNotificationBar();
mediaPlayerUtil = MediaPlayerUtil.getInstance();
boolean isdestory;
if (mActivity== null || mActivity.isFinishing() || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && mActivity.isDestroyed())) {
isdestory=true;
} else {
isdestory=false;
}
// 由于图片使用Glide异步加载图片activity已销毁时时发生的崩溃
if(isdestory==false){
// 此处为Glide的notificationTarget回调,当网络图片加载成功更新通知栏相对应控件的图像
notificationTarget = new NotificationTarget(mContext, R.id.bgmmMusicImageView, contentView, notification, R.string.app_name);
// 加载网络图片
Glide.with(mContext).asBitmap().load(mediaPlayerUtil.getAudioBoList().get(mediaPlayerUtil.getIndex()).getImgUrl()).placeholder(R.drawable.test).into(notificationTarget);
}
mAudioManager.abandonAudioFocus(mAudioFocusChange);
}
});
}
/*
* 关闭、清楚通知栏
* */
public void closeNotifi() {
NotifityActivity.this.runOnUiThread(new Runnable() {
public void run() {
mediaPlayerUtil = MediaPlayerUtil.getInstance();
mediaPlayerUtil.closeMedia();
mAudioManager.abandonAudioFocus(mAudioFocusChange);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(R.string.app_name);
}
});
}
// 焦点监听
AudioManager.OnAudioFocusChangeListener mAudioFocusChange = new AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int focusChange) {
mediaPlayerUtil=MediaPlayerUtil.getInstance();
if(focusChange==AudioManager.AUDIOFOCUS_LOSS) {
//长时间丢失焦点,当其他应用如播放QQ音乐,网易云音乐播放时
if (mediaPlayerUtil.isplay()) {
closeNotifi();
}
mAudioManager.abandonAudioFocus(mAudioFocusChange);
}else if(focusChange== AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
if (mediaPlayerUtil.isplay()) {
mediaPlayerUtil.stop();
updateUI();
}
}
}
};
}
再次捋下思路,
1、通知栏实现音频播放,主要使用到的是MediaPlayer播放器,
2、切歌我这里主要用到的是 静态广播来实现对通知栏点击事件的逻辑处理
3、加载网络图片主要用到的是Glide的NotificationTarget对象来及时更新相对应的图像,这里需要注意的是由于图片使用Glide异步加载图片,一定要在合适的地方去判断activity是否已销毁,不然会发生崩溃报错
4、在广播里触发不同的事件时,有时需要通知栏的图标或样式发生改变,那如何保证及时更新呢,我这里是在activity里创建一个它的实例,并写一个更新通知栏UI的方法,在广播需要用到的地方调用即可
5,说到音频就不得不说如何在播放自己项目的时候或接听电话、视频时关闭音频,或关闭第三方的音频了,这里主要要到的是AudioManager(音频管理器)
至此一个完整的通知栏实现音频播放示例已完成,我也是第一次写,关于中间的service服务还不是很了解,代码还有很大的优化空间,具体到大家的项目中可根据需要灵活放入改变就好,如果您有更好的更简洁的方法,也欢迎分享,如果代码有哪里写的不好,更欢迎大家指正,
更多推荐
所有评论(0)