pull/46/head
kunfei 5 years ago
parent 07dc68c3f7
commit d4f44e77cb
  1. 1
      app/src/main/AndroidManifest.xml
  2. 220
      app/src/main/java/io/legado/app/service/AudioPlayService.kt
  3. 5
      app/src/main/java/io/legado/app/service/BaseReadAloudService.kt
  4. 11
      app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt

@ -105,6 +105,7 @@
<service android:name=".service.WebService" /> <service android:name=".service.WebService" />
<service android:name=".service.TTSReadAloudService" /> <service android:name=".service.TTSReadAloudService" />
<service android:name=".service.HttpReadAloudService" /> <service android:name=".service.HttpReadAloudService" />
<service android:name=".service.AudioPlayService" />
<receiver android:name=".receiver.MediaButtonReceiver"> <receiver android:name=".receiver.MediaButtonReceiver">
<intent-filter> <intent-filter>

@ -0,0 +1,220 @@
package io.legado.app.service
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.BitmapFactory
import android.media.AudioFocusRequest
import android.media.AudioManager
import android.media.MediaPlayer
import android.os.Build
import android.support.v4.media.session.MediaSessionCompat
import android.support.v4.media.session.PlaybackStateCompat
import androidx.core.app.NotificationCompat
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.BaseService
import io.legado.app.constant.Action
import io.legado.app.constant.AppConst
import io.legado.app.help.IntentHelp
import io.legado.app.help.MediaHelp
import io.legado.app.receiver.MediaButtonReceiver
import io.legado.app.ui.book.read.ReadBookActivity
class AudioPlayService : BaseService(), AudioManager.OnAudioFocusChangeListener {
var pause = false
private lateinit var audioManager: AudioManager
private lateinit var mFocusRequest: AudioFocusRequest
private var title: String = ""
private var subtitle: String = ""
private val mediaPlayer = MediaPlayer()
private var mediaSessionCompat: MediaSessionCompat? = null
private var broadcastReceiver: BroadcastReceiver? = null
private var position = 0
override fun onCreate() {
super.onCreate()
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mFocusRequest = MediaHelp.getFocusRequest(this)
}
initMediaSession()
initBroadcastReceiver()
upMediaSessionPlaybackState(PlaybackStateCompat.STATE_PLAYING)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
super.onDestroy()
mediaSessionCompat?.release()
}
private fun pause() {
mediaPlayer.pause()
}
private fun resume() {
mediaPlayer.start()
}
/**
* @return 音频焦点
*/
fun requestFocus(): Boolean {
val request: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
audioManager.requestAudioFocus(mFocusRequest)
} else {
@Suppress("DEPRECATION")
audioManager.requestAudioFocus(
this,
AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN
)
}
return request == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
}
/**
* 更新媒体状态
*/
private fun upMediaSessionPlaybackState(state: Int) {
mediaSessionCompat?.setPlaybackState(
PlaybackStateCompat.Builder()
.setActions(MediaHelp.MEDIA_SESSION_ACTIONS)
.setState(state, position.toLong(), 1f)
.build()
)
}
/**
* 初始化MediaSession, 注册多媒体按钮
*/
private fun initMediaSession() {
mediaSessionCompat = MediaSessionCompat(this, "readAloud")
mediaSessionCompat?.setCallback(object : MediaSessionCompat.Callback() {
override fun onMediaButtonEvent(mediaButtonEvent: Intent): Boolean {
return MediaButtonReceiver.handleIntent(this@AudioPlayService, mediaButtonEvent)
}
})
mediaSessionCompat?.setMediaButtonReceiver(
PendingIntent.getBroadcast(
this,
0,
Intent(
Intent.ACTION_MEDIA_BUTTON,
null,
App.INSTANCE,
MediaButtonReceiver::class.java
),
PendingIntent.FLAG_CANCEL_CURRENT
)
)
mediaSessionCompat?.isActive = true
}
/**
* 断开耳机监听
*/
private fun initBroadcastReceiver() {
broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY == intent.action) {
pause()
}
}
}
val intentFilter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
registerReceiver(broadcastReceiver, intentFilter)
}
/**
* 音频焦点变化
*/
override fun onAudioFocusChange(focusChange: Int) {
when (focusChange) {
AudioManager.AUDIOFOCUS_GAIN -> {
// 重新获得焦点, 可做恢复播放,恢复后台音量的操作
if (!pause) resume()
}
AudioManager.AUDIOFOCUS_LOSS -> {
// 永久丢失焦点除非重新主动获取,这种情况是被其他播放器抢去了焦点, 为避免与其他播放器混音,可将音乐暂停
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
// 暂时丢失焦点,这种情况是被其他应用申请了短暂的焦点,可压低后台音量
if (!pause) pause()
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
// 短暂丢失焦点,这种情况是被其他应用申请了短暂的焦点希望其他声音能压低音量(或者关闭声音)凸显这个声音(比如短信提示音),
}
}
}
/**
* 更新通知
*/
private fun upNotification() {
var nTitle: String = when {
pause -> getString(R.string.read_aloud_pause)
BaseReadAloudService.timeMinute in 1..60 -> getString(
R.string.read_aloud_timer,
BaseReadAloudService.timeMinute
)
else -> getString(R.string.read_aloud_t)
}
nTitle += ": $title"
var nSubtitle = subtitle
if (subtitle.isEmpty())
nSubtitle = getString(R.string.read_aloud_s)
val builder = NotificationCompat.Builder(this, AppConst.channelIdReadAloud)
.setSmallIcon(R.drawable.ic_volume_up)
.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.icon_read_book))
.setOngoing(true)
.setContentTitle(nTitle)
.setContentText(nSubtitle)
.setContentIntent(
IntentHelp.activityPendingIntent<ReadBookActivity>(this, "activity")
)
if (pause) {
builder.addAction(
R.drawable.ic_play_24dp,
getString(R.string.resume),
thisPendingIntent(Action.resume)
)
} else {
builder.addAction(
R.drawable.ic_pause_24dp,
getString(R.string.pause),
thisPendingIntent(Action.pause)
)
}
builder.addAction(
R.drawable.ic_stop_black_24dp,
getString(R.string.stop),
thisPendingIntent(Action.stop)
)
builder.addAction(
R.drawable.ic_time_add_24dp,
getString(R.string.set_timer),
thisPendingIntent(Action.addTimer)
)
builder.setStyle(
androidx.media.app.NotificationCompat.MediaStyle()
.setMediaSession(mediaSessionCompat?.sessionToken)
.setShowActionsInCompactView(0, 1, 2)
)
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
val notification = builder.build()
startForeground(112201, notification)
}
private fun thisPendingIntent(action: String): PendingIntent? {
return IntentHelp.servicePendingIntent<AudioPlayService>(this, action)
}
}

@ -36,7 +36,6 @@ abstract class BaseReadAloudService : BaseService(),
companion object { companion object {
var isRun = false var isRun = false
var timeMinute: Int = 0 var timeMinute: Int = 0
} }
private val handler = Handler() private val handler = Handler()
@ -44,9 +43,9 @@ abstract class BaseReadAloudService : BaseService(),
private lateinit var mFocusRequest: AudioFocusRequest private lateinit var mFocusRequest: AudioFocusRequest
private var broadcastReceiver: BroadcastReceiver? = null private var broadcastReceiver: BroadcastReceiver? = null
private var mediaSessionCompat: MediaSessionCompat? = null private var mediaSessionCompat: MediaSessionCompat? = null
var pause = false private var title: String = ""
var title: String = ""
private var subtitle: String = "" private var subtitle: String = ""
var pause = false
val contentList = arrayListOf<String>() val contentList = arrayListOf<String>()
var nowSpeak: Int = 0 var nowSpeak: Int = 0
var readAloudNumber: Int = 0 var readAloudNumber: Int = 0

@ -16,18 +16,23 @@ class AudioPlayActivity : VMBaseActivity<AudioPlayViewModel>(R.layout.activity_a
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
setSupportActionBar(toolbar) setSupportActionBar(toolbar)
viewModel.initData(intent) viewModel.initData(intent)
initView()
}
private fun initView() {
} }
override fun loadContent() { override fun loadContent() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
} }
override fun contentLoadFinish(bookChapter: BookChapter, content: String) { override fun contentLoadFinish(bookChapter: BookChapter, content: String) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
} }
override fun upContent() { override fun upContent() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
} }
} }
Loading…
Cancel
Save