/* * Copyright (c) 2020 Hemanth Savarla. * * Licensed under the GNU General Public License v3 * * This is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * */ package code.name.monkey.retromusic.activities.base import android.Manifest import android.content.BroadcastReceiver import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.ServiceConnection import android.os.Bundle import android.os.IBinder import androidx.lifecycle.lifecycleScope import code.name.monkey.retromusic.R import code.name.monkey.retromusic.db.toPlayCount import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.interfaces.IMusicServiceEventListener import code.name.monkey.retromusic.repository.RealRepository import code.name.monkey.retromusic.service.MusicService.* import java.lang.ref.WeakReference import java.util.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.koin.android.ext.android.inject abstract class AbsMusicServiceActivity : AbsBaseActivity(), IMusicServiceEventListener { private val mMusicServiceEventListeners = ArrayList() private val repository: RealRepository by inject() private var serviceToken: MusicPlayerRemote.ServiceToken? = null private var musicStateReceiver: MusicStateReceiver? = null private var receiverRegistered: Boolean = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) serviceToken = MusicPlayerRemote.bindToService(this, object : ServiceConnection { override fun onServiceConnected(name: ComponentName, service: IBinder) { this@AbsMusicServiceActivity.onServiceConnected() } override fun onServiceDisconnected(name: ComponentName) { this@AbsMusicServiceActivity.onServiceDisconnected() } }) setPermissionDeniedMessage(getString(R.string.permission_external_storage_denied)) } override fun onDestroy() { super.onDestroy() MusicPlayerRemote.unbindFromService(serviceToken) if (receiverRegistered) { unregisterReceiver(musicStateReceiver) receiverRegistered = false } } fun addMusicServiceEventListener(listenerI: IMusicServiceEventListener?) { if (listenerI != null) { mMusicServiceEventListeners.add(listenerI) } } fun removeMusicServiceEventListener(listenerI: IMusicServiceEventListener?) { if (listenerI != null) { mMusicServiceEventListeners.remove(listenerI) } } override fun onServiceConnected() { if (!receiverRegistered) { musicStateReceiver = MusicStateReceiver(this) val filter = IntentFilter() filter.addAction(PLAY_STATE_CHANGED) filter.addAction(SHUFFLE_MODE_CHANGED) filter.addAction(REPEAT_MODE_CHANGED) filter.addAction(META_CHANGED) filter.addAction(QUEUE_CHANGED) filter.addAction(MEDIA_STORE_CHANGED) filter.addAction(FAVORITE_STATE_CHANGED) registerReceiver(musicStateReceiver, filter) receiverRegistered = true } for (listener in mMusicServiceEventListeners) { listener.onServiceConnected() } } override fun onServiceDisconnected() { if (receiverRegistered) { unregisterReceiver(musicStateReceiver) receiverRegistered = false } for (listener in mMusicServiceEventListeners) { listener.onServiceDisconnected() } } override fun onPlayingMetaChanged() { for (listener in mMusicServiceEventListeners) { listener.onPlayingMetaChanged() } lifecycleScope.launch(Dispatchers.IO) { val entity = repository.songPresentInHistory(MusicPlayerRemote.currentSong) if (entity != null) { repository.updateHistorySong(MusicPlayerRemote.currentSong) } else { repository.addSongToHistory(MusicPlayerRemote.currentSong) } val songs = repository.checkSongExistInPlayCount(MusicPlayerRemote.currentSong.id) if (songs.isNotEmpty()) { repository.updateSongInPlayCount(songs.first().apply { playCount += 1 }) } else { repository.insertSongInPlayCount(MusicPlayerRemote.currentSong.toPlayCount()) } } } override fun onQueueChanged() { for (listener in mMusicServiceEventListeners) { listener.onQueueChanged() } } override fun onPlayStateChanged() { for (listener in mMusicServiceEventListeners) { listener.onPlayStateChanged() } } override fun onMediaStoreChanged() { for (listener in mMusicServiceEventListeners) { listener.onMediaStoreChanged() } } override fun onRepeatModeChanged() { for (listener in mMusicServiceEventListeners) { listener.onRepeatModeChanged() } } override fun onShuffleModeChanged() { for (listener in mMusicServiceEventListeners) { listener.onShuffleModeChanged() } } override fun onHasPermissionsChanged(hasPermissions: Boolean) { super.onHasPermissionsChanged(hasPermissions) val intent = Intent(MEDIA_STORE_CHANGED) intent.putExtra( "from_permissions_changed", true ) // just in case we need to know this at some point sendBroadcast(intent) println("sendBroadcast $hasPermissions") } override fun getPermissionsToRequest(): Array { return arrayOf( Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.BLUETOOTH ) } private class MusicStateReceiver(activity: AbsMusicServiceActivity) : BroadcastReceiver() { private val reference: WeakReference = WeakReference(activity) override fun onReceive(context: Context, intent: Intent) { val action = intent.action val activity = reference.get() if (activity != null && action != null) { when (action) { FAVORITE_STATE_CHANGED, META_CHANGED -> activity.onPlayingMetaChanged() QUEUE_CHANGED -> activity.onQueueChanged() PLAY_STATE_CHANGED -> activity.onPlayStateChanged() REPEAT_MODE_CHANGED -> activity.onRepeatModeChanged() SHUFFLE_MODE_CHANGED -> activity.onShuffleModeChanged() MEDIA_STORE_CHANGED -> activity.onMediaStoreChanged() } } } } companion object { val TAG: String = AbsMusicServiceActivity::class.java.simpleName } }