android 有声小说播放器(可以离线在线播放)
使用service实现播放器
播放器:bilibili IJKplayer 的 exoplayer 框架
播放器
播放器service代码:
public class PlayerService extends Service {
private IjkExoMediaPlayer player;
public static final int PLAYING = 1;//正在播放
public static final int PLAYSTOP = 2;//停止
public static final int PLAYPAUSE = 3;// 暂停
public int playerState = PLAYSTOP;
public ArrayList<ChapterItem> playerList;//播放资源列表
public int position;
public int currentTime;
public int seekTime = 0;
public int update = 0;
public int intenetState = NOINTENET;
public static final int NOINTENET = 0;//网络状态
public static final int WIFY = 1;
public static final int PHONE = 2;
public int buffering = 0;//缓冲进度
public int clock = 0; // 定时
public boolean isPauseForCall = false; //是否因为来电导致播放暂停
public int allTims=0; //播放总时长
PhoneStateListener phoneStateListener = new PhoneStateListener() {// 来电监听 来电暂停 结束继续播放
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
if (state == TelephonyManager.CALL_STATE_RINGING) {
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int ringvolume = audioManager
.getStreamVolume(AudioManager.STREAM_RING);
if (ringvolume > 0) {
if (player != null && player.isPlaying()) {
isPauseForCall = true;
pause();
}
}
} else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
if (player != null && player.isPlaying()) {
isPauseForCall = true;
pause();
}
} else if (state == TelephonyManager.CALL_STATE_IDLE) {
if (isPauseForCall) { //是否是电话导致播放器暂停
reStart();
isPauseForCall = false;
}
}
}
};
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Common.GET_OK:
setData(msg.obj.toString());
break;
case Common.INIT_OK:
handler.sendEmptyMessageDelayed(Common.INIT_OK, 1000);
if (player != null && player.getCurrentPosition() > 0) {//广播发送 缓冲 和播放时间
buffering=player.getBufferedPercentage();
currentTime = (int) player.getCurrentPosition();
Intent intent = new Intent();
intent.setAction(Common.PlayerTime);
intent.putExtra("currentTime", currentTime);
intent.putExtra("buffering", buffering);
sendBroadcast(intent);
}
if (update == 0) {//播放记录
update++;
if (sharedPreferences != null) {// 用户最后一次播放记录
sharedPreferences.edit().putString("bookid", currentBookId).putString("cid", currentCid).putInt("time", currentTime).putInt("position", position).apply();
}
} else {
if (update >= 6) {
update = 0;
if (sharedPreferences != null) {//每本书的最后的播放记录 6秒更新一次
sharedPreferences.edit().putString("bookid", currentBookId).putString("cid", currentCid).putInt("time", currentTime).putInt("position", position).apply();
}
if (player!=null&&changeHistoryDao != null&& player.getCurrentPosition() > 0) {
changeHistoryDao.updateHistory(currentCid, currentTime + "", currentBookId);
}
} else {
update++;
}
}
if (Common.clock != 1) {//定时器 到时间自动停止播放
switch (Common.clock) {
case 2:
if (clock < 600) {
clock++;
} else {
Common.clock = 1;
clock = 0;
pause();
}
break;
case 3:
if (clock < 12000) {
clock++;
} else {
Common.clock = 1;
clock = 0;
pause();
}
break;
case 4:
if (clock < 18000) {
clock++;
} else {
Common.clock = 1;
clock = 0;
pause();
}
break;
case 5:
if (clock < 36000) {
clock++;
} else {
Common.clock = 1;
clock = 0;
pause();
}
break;
case 6:
if (clock < 54000) {
clock++;
} else {
Common.clock = 1;
clock = 0;
pause();
}
break;
}
}
break;
case Common.NETWORK_STATE:// 查询网络状态
intenetLisenter();
handler.sendEmptyMessageDelayed(Common.NETWORK_STATE, 1000);
break;
}
}
};
private SharedPreferences sharedPreferences;
private String bookname;
public PlayerService() {
}
NotificationManager nm;
@Override
public void onCreate() {
super.onCreate();
changeHistoryDao = new BookLibDao(getApplicationContext());
changeHistoryDao.open();
player = new MediaPlayer(getApplicationContext());
handler.obtainMessage(Common.INIT_OK).sendToTarget();// 时间间隔1秒 查询当前播放时间
handler.obtainMessage(Common.NETWORK_STATE).sendToTarget();// 查询网络状态
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
registerReceiver();
player.setKeepInBackground(true);
player.setOnPreparedListener(new IMediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(IMediaPlayer iMediaPlayer) {
allTims=(int) player.getDuration()/1000;//加载成功 获取音频文件总时长
player.start();
player.setVolume(1f, 1f);音量
sendPlayerChangeBroacast();通知 播放器和更新通知栏 播放状态发生变化
Intent intent = new Intent();
intent.setAction(Common.InitPlayAllTime);
intent.putExtra("allTims", allTims);
sendBroadcast(intent); 发送播放总时长
}
});
播放完成监听
player.setOnCompletionListener(new IMediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(IMediaPlayer iMediaPlayer) {//此状态可能有误差 播放器error后也会回掉此方法所以加上个时间匹配
if (allTims* 1000 - 5000 <= currentTime && currentTime <= allTims * 1000 + 5000) {
next();
}
}
});
player.setOnErrorListener(new IMediaPlayer.OnErrorListener() {
@Override
public boolean onError(IMediaPlayer iMediaPlayer, int i, int i1) {
sendPlayerChangeBroacast();
return false;
}
});
sharedPreferences = getSharedPreferences(Common.LastPlayerHistory, MODE_PRIVATE);
TelephonyManager tmgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
tmgr.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
// 从通知栏跳到播放器
BroadcastReceiver NMReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String ctrl_code = intent.getAction();
if (player != null) {
if ("play".equals(ctrl_code)) {
pauseOrPlayer();
} else if ("next".equals(ctrl_code)) {
next();
} else if ("delete".equals(ctrl_code)) {
if (nm != null) {
nm.cancelAll();
android.os.Process.killProcess(android.os.Process.myPid());
}
} else if ("open".equals(ctrl_code)) {
startActivity(new Intent(context, PlayerAty.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
Class clazz = null;
try {
Object statusBarManager = context.getSystemService("statusbar");
Method collapse;
if (Build.VERSION.SDK_INT <= 16) {
collapse = statusBarManager.getClass().getMethod("collapse");
} else {
collapse = statusBarManager.getClass().getMethod("collapsePanels");
}
collapse.invoke(statusBarManager);
} catch (Exception localException) {
localException.printStackTrace();
}
}
}
}
};
void registerReceiver() {接受通知栏 的命令
IntentFilter intentFilter4 = new IntentFilter();
intentFilter4.addAction("play");
intentFilter4.addAction("next");
intentFilter4.addAction("delete");
intentFilter4.addAction("open");
registerReceiver(NMReceiver, intentFilter4);
}
播放状态变化时要通知 播放器和通知栏
void sendPlayerChangeBroacast() {
if (player != null) {
Intent intent = new Intent();
intent.setAction(Common.PlaerStateChange);
intent.putExtra("PlaerStateChange", player.isPlaying());
sendBroadcast(intent);
if (bookname != null) {
ChapterDao dao1 = new ChapterDao(getApplicationContext());
dao1.open();
ChapterItem query = dao1.query(currentCid);
dao1.close();
initNotificationBar(bookname, query.getTitle(), player.isPlaying());
}
}
}
void intenetLisenter() {//网络状态监听
ConnectivityManager manager = (ConnectivityManager) getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
if (activeNetwork != null) { // connected to the internet
if (activeNetwork.isConnected()) {
if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
if (intenetState != WIFY) {
//切换到wify
} else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
if (intenetState != PHONE) {
intenetState = PHONE
}
} else {
} else {
}
}
@Override
public IBinder onBind(Intent intent) {
return new PlayerIBinder();
}
public class PlayerIBinder extends Binder {
public PlayerService getService() {
return PlayerService.this;
}
}
设置 播放资源 path 可以是本地文件目录也可以是网络url
private void setData(String path) {
player.reset();
sendPlayerChangeBroacast();
if (Utils.isNull(path)) {
return;
}
try {
player.setDataSource(path);
player.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
}
public void seekTo(int presess) {
player.seekTo(presess);
}
public void pause() {
if (player != null) {
player.pause();
playerState = PLAYPAUSE;
}
sendPlayerChangeBroacast();
}
public void next() {
if (playerList == null) {
return;
}
if (position < playerList.size() - 1) {
Intent intent = new Intent();
intent.setAction(Common.PlayerTime);
intent.putExtra("currentTime", 0);
intent.putExtra("buffering", 0);
sendBroadcast(intent);
player.reset();
ChapterItem item = playerList.get(++position);
start(item.getCid(), item.getBookId(), position, 0, true);
sendPlayerChangeBroacast();
}
}
public void upOne() {
if (playerList == null) {
return;
}
if (position > 0) {
currentTime = 0;
player.reset();
ChapterItem item = playerList.get(--position);
start(item.getCid(), item.getBookId(), position, 0, true);
sendPlayerChangeBroacast();
}
}
public void playOrPause() {
if (player != null) {
if (player.isPlaying()) {
pause();
} else {
reStart();
}
}
}
public boolean isplaying() {
if (player != null) {
return player.isPlaying();
} else {
return false;
}
}
public void stop(){
if (player!=null){
player.stop();
player.reset();
}
}
public ArrayList<ChapterItem> getPlayerList() {
return playerList;
}
public void setPlayerList(ArrayList<ChapterItem> playerList) {
this.playerList = playerList;
}
通知栏
public void initNotificationBar(String name, String chapterName, boolean isplaying) {
Notification notification = new Notification();
notification.icon = R.mipmap.nm;
RemoteViews contentView = new RemoteViews(getPackageName(),
R.layout.notafitycation);
notification.contentView = contentView;
contentView.setTextViewText(R.id.name, name);
contentView.setTextViewText(R.id.chapterName, chapterName);
contentView.setImageViewResource(R.id.next, R.mipmap.next);
if (isplaying) {
contentView.setImageViewResource(R.id.player, R.mipmap.n_player);
} else {
contentView.setImageViewResource(R.id.player, R.mipmap.n_pause);
}
Intent intentPlay = new Intent("play");
PendingIntent pIntentPlay = PendingIntent.getBroadcast(this, 0,
intentPlay, 0);
contentView.setOnClickPendingIntent(R.id.player, pIntentPlay);
Intent intentPause = new Intent("next");
PendingIntent pIntentPause = PendingIntent.getBroadcast(this, 0,
intentPause, 0);
contentView.setOnClickPendingIntent(R.id.next, pIntentPause);
Intent intentOpen = new Intent("open");
PendingIntent pIntentOpen = PendingIntent.getBroadcast(this, 0,
intentOpen, 0);
contentView.setOnClickPendingIntent(R.id.rl, pIntentOpen);
Intent intentNext = new Intent("delete");
PendingIntent pIntentNext = PendingIntent.getBroadcast(this, 0,
intentNext, 0);
contentView.setOnClickPendingIntent(R.id.delete, pIntentNext);
notification.flags = Notification.FLAG_NO_CLEAR;
nm.notify(100001, notification);
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(NMReceiver);
}
}
android 有声小说播放器(可以离线在线播放)相关推荐
- android xml mpg格式,急求: android如何对mpg格式视频实现在线播放?
急求: android怎么对mpg格式视频实现在线播放??? 对于3GP格式的视频都直接可以进行播放,但是对mpg格式谈话对话框提示无法播放此视频.是不是mpg格式的还需要我特别进行格式转化呢? 播放 ...
- 借用 potplayer 播放器,在本地播放 b 站视频也能看弹幕了
苏生不惑第164 篇原创文章,将本公众号设为星标,第一时间看最新文章. 关于b站之前已经写过了下列文章,有兴趣可以点击阅读: 那些我关注的 b 站 up 主 bilibili(b站)升级到BV号了,还 ...
- FFmpeg音频播放器(8)-创建FFmpeg播放器
原文地址::https://www.jianshu.com/p/73b0a0a9bb0d 相关文章 1.FFmpeg音频解码播放----https://www.jianshu.com/p/76562a ...
- 搭建rtmp直播流服务之4:videojs和ckPlayer开源播放器二次开发(播放rtmp、hls直播流及普通视频)...
前面几章讲解了使用 nginx-rtmp搭建直播流媒体服务器; ffmpeg推流到nginx-rtmp服务器; java通过命令行调用ffmpeg实现推流服务; 从数据源获取,到使用ffmpeg推流, ...
- SkeyeWebPlayer免费网页RTSP/RTMP/FLV/HLS/H265/M3U8直播点播播放器-页面动态多播放器添加代码示例
强大的网页直播/点播播放器 SkeyeWebPlayer,使用简单,功能强大, 终身免费使用,支持Windows. Android.iOS平台. SkeyeWebPlayer.js H5播放器是由成都 ...
- Ubuntu16.04下使用VLC media player播放器实现倍速播放
Ubuntu16.04下使用VLC media player播放器实现倍速播放 打开软件 开启倍速功能 打开软件 视频文件右键"属性"-"打开方式"-" ...
- 网页播放器自定义倍速播放
网页播放器自定义倍速播放,可设置播放器的播放速度为1,2,3,5,6,7等自定义播放速度.利用html5的特性进行处理. 一般网页播放器的速度限制在最高两倍速播放,通常这就符合一般的要求了.但是确实有 ...
- 如何给播放器增加倍速播放
1.一般网页上播放的播放器没有倍速播放,有时候需要这样的功能 2.演示:http://www.gehweb.top/b.html 3.例如这样写就可以实现这个功能: <video id=&quo ...
- html 音乐 QQ播放器 外链 代码 播放器 外链 代码
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha QQ播放器 外链 代码 播放器 外链 代码 ======== 歌曲链接 QQ播放器 外链 ...
最新文章
- [转]PDO防注入原理分析以及使用PDO的注意事项
- 不输GPS!30颗卫星全部就位!北斗三号全球卫星导航星座部署顺利收官
- Node.js 安装---环境配置---输出Hello World !
- ConstraintLayout如何优化布局性能
- Java 关于中文乱码处理的经验总结
- html标签acronym没用,acronym_废弃 | Obsolete_HTML_参考手册_非常教程
- LinkedHashMap+Iterable实现LRU算法(简单易懂)
- Oracle LiveLabs实验:Introduction to Oracle Spatial
- web功能测试工具_Web辅助功能:工具和注意事项
- ps去水印教程_ps怎么去水印?ps去水印的三种方法
- 使用PS更改照片的背景色
- Jmeter 线程数、Ramp-Up、循环次数 详解
- ucharts 柱状图圆角_调整柱状图圆角弧度
- 功能测试与性能测试常见方法
- 子类、父类各种方法的执行顺序
- SpellGCN:将语音学和视觉相似性结合到汉语拼写检查的语言模型
- 机器学习——概率图模型
- 数字滚动插件——CountUp.js
- 【智能工厂】PPT案例分享:智慧工厂解决方案
- 基于AT89C51单片机的智能浇花系统设计