记录开发遇到问题及解决方案:
1.问题:service启动服务,MediaPlayer音频播放10几秒或分把钟未播放结束自动停止播放,服务被销毁,怎么办?
分析问题:经过网上查阅许多资料,综合各大佬所归纳,最后总结app进程被杀死的根本原因:系统内存出现不足时,会被Android的low memory killer杀掉。
解决办法:此处我想到保存活的service办法,想必大家都想到那就是被销毁就重新创建呗。做法如下:
- 调用startForegroundService启动服务
- 在服务的onStartCommand中调用startForeground (5s内调用,否则会导致ANR),并设置Nofitication
- 在onDestroy里判断该音频是否还处于正在播放中,如果是则重启service,否则正常销毁。(此处最好判断是否是手动设置销毁,如果是走正常销毁,否则重新启动)
- 代码实现大致如下:
// 1.启动
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(new Intent(this, PlayService.class));
} else {
startService(new Intent(this, PlayService.class));
}
// 2.service里重写onStartCommand。注意:needDestroyStr改变时必须在调用stopService(new Intent(this, XXXXService.class));由用RxJava实现的EventBus传递过来在onCreate里监听
private String needDestroyStr = "N"; //标记是否走正常销毁
/**
* 在此处调用startForeground
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!"Y".equals(needDestroyStr)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(ID, NAME, NotificationManager.IMPORTANCE_HIGH);
if (manager != null) {
manager.createNotificationChannel(channel);
}
Notification notification = new Notification.Builder(this, ID).build();
startForeground(1, notification);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
stopForeground(true);
}
}, 3000);
}
registerReceiver();// 去注册广播
}
// START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
//
// START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
//
// START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
//
// START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启
return START_STICKY;
}
//3.在onDestroy里做相关判断
@Override
public void onDestroy() {
unregisterReceiver(); // 注销广播
// 不是必须关闭且正在播放或初始化状态
if(!"Y".equals(needDestroyStr) &&
(order == ORDERPLAY || order == ORDERCURSTATE)){ // 正在播放或初始化状态中若突然接收到被销毁后重新启动,其他状态则默认去销毁
Log.d("XXXXService", "onDestroy XXXXService------and order = "+order+" =====needDestroyStr===="+needDestroyStr+"---正在重启中~~~~~");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(new Intent(this, XXXXService.class));
} else {
startService(new Intent(this, XXXXService.class));
}
} else {
Log.d("XXXXService", "onDestroy XXXXService------and order = "+order+" =====needDestroyStr===="+needDestroyStr+"---正在销毁中~~~~~");
super.onDestroy();
Player.getInstance().destroy();
}
}
2. 解决点击edittext,弹出软键盘时布局往上顶的问题
// EditText弹起软键盘时不会将底部的布局顶上来
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
后续待更新。。。。