diff --git a/app/build.gradle b/app/build.gradle index ec7a99bee..a70965c2b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -79,11 +79,12 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" //androidX - implementation 'androidx.core:core-ktx:1.2.0-alpha02' + implementation 'androidx.core:core-ktx:1.2.0-alpha03' implementation 'androidx.appcompat:appcompat:1.1.0-rc01' implementation 'androidx.preference:preference:1.1.0-rc01' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0' + implementation 'androidx.media:media:1.1.0-rc01' implementation 'com.google.android.material:material:1.1.0-alpha09' implementation 'com.google.android:flexbox:1.1.0' @@ -134,4 +135,5 @@ dependencies { //颜色选择 implementation 'com.jaredrummler:colorpicker:1.1.0' + } diff --git a/app/src/main/java/io/legado/app/receiver/MediaButtonIntentReceiver.kt b/app/src/main/java/io/legado/app/receiver/MediaButtonIntentReceiver.kt new file mode 100644 index 000000000..829a4d40d --- /dev/null +++ b/app/src/main/java/io/legado/app/receiver/MediaButtonIntentReceiver.kt @@ -0,0 +1,55 @@ +package io.legado.app.receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.view.KeyEvent + + +/** + * Created by GKF on 2018/1/6. + * 监听耳机键 + */ + +class MediaButtonIntentReceiver : BroadcastReceiver() { + + companion object { + val TAG = MediaButtonIntentReceiver::class.java.simpleName + + fun handleIntent(context: Context, intent: Intent): Boolean { + val intentAction = intent.action + if (Intent.ACTION_MEDIA_BUTTON == intentAction) { + val event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT) ?: return false + + val keycode = event.keyCode + val action = event.action + + val command: String? = null + when (keycode) { + KeyEvent.KEYCODE_MEDIA_STOP, KeyEvent.KEYCODE_MEDIA_PAUSE, KeyEvent.KEYCODE_MEDIA_PLAY, KeyEvent.KEYCODE_HEADSETHOOK, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> { + } + else -> { + } + }// command = ReadAloudService.ActionMediaButton; + if (command != null) { + if (action == KeyEvent.ACTION_DOWN) { + readAloud(context, command) + return true + } + } + } + return false + } + + private fun readAloud(context: Context, command: String?) { + + } + } + + override fun onReceive(context: Context, intent: Intent) { + if (handleIntent(context, intent) && isOrderedBroadcast) { + abortBroadcast() + } + } + +} diff --git a/app/src/main/java/io/legado/app/service/ReadAloudService.kt b/app/src/main/java/io/legado/app/service/ReadAloudService.kt index d3d28a16d..bbfa3525d 100644 --- a/app/src/main/java/io/legado/app/service/ReadAloudService.kt +++ b/app/src/main/java/io/legado/app/service/ReadAloudService.kt @@ -1,12 +1,19 @@ package io.legado.app.service +import android.app.PendingIntent +import android.content.ComponentName import android.content.Context import android.content.Intent +import android.media.AudioAttributes +import android.media.AudioFocusRequest import android.media.AudioManager +import android.os.Build import android.speech.tts.TextToSpeech import android.speech.tts.UtteranceProgressListener +import android.support.v4.media.session.MediaSessionCompat import io.legado.app.R import io.legado.app.base.BaseService +import io.legado.app.receiver.MediaButtonIntentReceiver import io.legado.app.utils.toast import kotlinx.coroutines.launch import java.util.* @@ -14,6 +21,7 @@ import java.util.* class ReadAloudService : BaseService(), TextToSpeech.OnInitListener, AudioManager.OnAudioFocusChangeListener { companion object { + val tag = ReadAloudService::class.java.simpleName var isRun = false fun paly(context: Context, title: String, body: String) { @@ -46,11 +54,17 @@ class ReadAloudService : BaseService(), TextToSpeech.OnInitListener, AudioManage private var textToSpeech: TextToSpeech? = null private var ttsIsSuccess: Boolean = false + private lateinit var audioManager: AudioManager + private lateinit var mFocusRequest: AudioFocusRequest + private var mediaSessionCompat: MediaSessionCompat? = null override fun onCreate() { super.onCreate() isRun = true textToSpeech = TextToSpeech(this, this) + audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager + initFocusRequest() + initMediaSession() } @@ -96,12 +110,63 @@ class ReadAloudService : BaseService(), TextToSpeech.OnInitListener, AudioManage } } + /** + * 初始化MediaSession + */ + private fun initMediaSession() { + val mComponent = ComponentName(packageName, MediaButtonIntentReceiver::class.java.name) + val mediaButtonIntent = Intent(Intent.ACTION_MEDIA_BUTTON) + mediaButtonIntent.component = mComponent + val mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast( + this, 0, + mediaButtonIntent, PendingIntent.FLAG_CANCEL_CURRENT + ) + + mediaSessionCompat = MediaSessionCompat(this, tag, mComponent, mediaButtonReceiverPendingIntent) + mediaSessionCompat?.setCallback(object : MediaSessionCompat.Callback() { + override fun onMediaButtonEvent(mediaButtonEvent: Intent): Boolean { + return MediaButtonIntentReceiver.handleIntent(this@ReadAloudService, mediaButtonEvent) + } + }) + mediaSessionCompat?.setMediaButtonReceiver(mediaButtonReceiverPendingIntent) + } + + private fun initFocusRequest() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val mPlaybackAttributes = AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_MEDIA) + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) + .build() + mFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) + .setAudioAttributes(mPlaybackAttributes) + .setAcceptsDelayedFocusGain(true) + .setOnAudioFocusChangeListener(this) + .build() + } + } + + /** + * @return 音频焦点 + */ + private 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 + } + override fun onAudioFocusChange(focusChange: Int) { when (focusChange) { AudioManager.AUDIOFOCUS_GAIN -> { // 重新获得焦点, 可做恢复播放,恢复后台音量的操作 } - AudioManager.AUDIOFOCUS_LOSS -> { // 永久丢失焦点除非重新主动获取,这种情况是被其他播放器抢去了焦点, 为避免与其他播放器混音,可将音乐暂停 }