From d4f44e77cbafeda08bb93a23bfeb140c0717c4d1 Mon Sep 17 00:00:00 2001 From: kunfei Date: Sun, 3 Nov 2019 19:31:38 +0800 Subject: [PATCH] up --- app/src/main/AndroidManifest.xml | 1 + .../io/legado/app/service/AudioPlayService.kt | 220 ++++++++++++++++++ .../app/service/BaseReadAloudService.kt | 5 +- .../legado/app/ui/audio/AudioPlayActivity.kt | 11 +- 4 files changed, 231 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/io/legado/app/service/AudioPlayService.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dc9705e30..8ce35a34b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -105,6 +105,7 @@ + diff --git a/app/src/main/java/io/legado/app/service/AudioPlayService.kt b/app/src/main/java/io/legado/app/service/AudioPlayService.kt new file mode 100644 index 000000000..331ed63da --- /dev/null +++ b/app/src/main/java/io/legado/app/service/AudioPlayService.kt @@ -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(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(this, action) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/service/BaseReadAloudService.kt b/app/src/main/java/io/legado/app/service/BaseReadAloudService.kt index db9df4596..906884091 100644 --- a/app/src/main/java/io/legado/app/service/BaseReadAloudService.kt +++ b/app/src/main/java/io/legado/app/service/BaseReadAloudService.kt @@ -36,7 +36,6 @@ abstract class BaseReadAloudService : BaseService(), companion object { var isRun = false var timeMinute: Int = 0 - } private val handler = Handler() @@ -44,9 +43,9 @@ abstract class BaseReadAloudService : BaseService(), private lateinit var mFocusRequest: AudioFocusRequest private var broadcastReceiver: BroadcastReceiver? = null private var mediaSessionCompat: MediaSessionCompat? = null - var pause = false - var title: String = "" + private var title: String = "" private var subtitle: String = "" + var pause = false val contentList = arrayListOf() var nowSpeak: Int = 0 var readAloudNumber: Int = 0 diff --git a/app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt b/app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt index 9cf576e38..dc198a3a5 100644 --- a/app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt +++ b/app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt @@ -16,18 +16,23 @@ class AudioPlayActivity : VMBaseActivity(R.layout.activity_a override fun onActivityCreated(savedInstanceState: Bundle?) { setSupportActionBar(toolbar) viewModel.initData(intent) + initView() + } + + private fun initView() { + } override fun loadContent() { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } override fun contentLoadFinish(bookChapter: BookChapter, content: String) { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } override fun upContent() { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } } \ No newline at end of file