2019-03-03 09:20:15 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2019 Hemanth Savarala.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2018-12-08 03:33:02 +00:00
|
|
|
package code.name.monkey.retromusic.appwidgets.base
|
|
|
|
|
|
|
|
import android.app.PendingIntent
|
|
|
|
import android.appwidget.AppWidgetManager
|
|
|
|
import android.appwidget.AppWidgetProvider
|
|
|
|
import android.content.ComponentName
|
|
|
|
import android.content.Context
|
|
|
|
import android.content.Intent
|
|
|
|
import android.content.res.Resources
|
|
|
|
import android.graphics.*
|
|
|
|
import android.graphics.drawable.BitmapDrawable
|
|
|
|
import android.graphics.drawable.Drawable
|
|
|
|
import android.os.Build
|
|
|
|
import android.text.TextUtils
|
|
|
|
import android.widget.RemoteViews
|
|
|
|
import androidx.core.content.ContextCompat
|
|
|
|
import code.name.monkey.retromusic.App
|
|
|
|
import code.name.monkey.retromusic.R
|
|
|
|
import code.name.monkey.retromusic.model.Song
|
|
|
|
import code.name.monkey.retromusic.service.MusicService
|
2019-08-02 08:59:40 +00:00
|
|
|
import code.name.monkey.retromusic.service.MusicService.*
|
2018-12-08 03:33:02 +00:00
|
|
|
|
|
|
|
abstract class BaseAppWidget : AppWidgetProvider() {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* {@inheritDoc}
|
|
|
|
*/
|
|
|
|
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager,
|
|
|
|
appWidgetIds: IntArray) {
|
|
|
|
defaultAppWidget(context, appWidgetIds)
|
2019-08-02 08:59:40 +00:00
|
|
|
val updateIntent = Intent(APP_WIDGET_UPDATE)
|
|
|
|
updateIntent.putExtra(EXTRA_APP_WIDGET_NAME, NAME)
|
2018-12-08 03:33:02 +00:00
|
|
|
updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds)
|
|
|
|
updateIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
|
|
|
|
context.sendBroadcast(updateIntent)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle a change notification coming over from [MusicService]
|
|
|
|
*/
|
|
|
|
fun notifyChange(service: MusicService, what: String) {
|
|
|
|
if (hasInstances(service)) {
|
2019-08-02 08:59:40 +00:00
|
|
|
if (META_CHANGED == what || PLAY_STATE_CHANGED == what) {
|
2018-12-08 03:33:02 +00:00
|
|
|
performUpdate(service, null)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected fun pushUpdate(context: Context, appWidgetIds: IntArray?,
|
|
|
|
views: RemoteViews) {
|
|
|
|
val appWidgetManager = AppWidgetManager.getInstance(context)
|
|
|
|
if (appWidgetIds != null) {
|
|
|
|
appWidgetManager.updateAppWidget(appWidgetIds, views)
|
|
|
|
} else {
|
|
|
|
appWidgetManager.updateAppWidget(ComponentName(context, javaClass), views)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check against [AppWidgetManager] if there are any instances of this widget.
|
|
|
|
*/
|
2019-11-08 17:07:30 +00:00
|
|
|
private fun hasInstances(context: Context): Boolean {
|
2018-12-08 03:33:02 +00:00
|
|
|
val appWidgetManager = AppWidgetManager.getInstance(context)
|
|
|
|
val mAppWidgetIds = appWidgetManager.getAppWidgetIds(ComponentName(context,
|
|
|
|
javaClass))
|
2019-11-08 17:07:30 +00:00
|
|
|
return mAppWidgetIds.isNotEmpty()
|
2018-12-08 03:33:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected fun buildPendingIntent(context: Context, action: String,
|
|
|
|
serviceName: ComponentName): PendingIntent {
|
|
|
|
val intent = Intent(action)
|
|
|
|
intent.component = serviceName
|
|
|
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
|
|
PendingIntent.getForegroundService(context, 0, intent, 0)
|
|
|
|
} else {
|
|
|
|
PendingIntent.getService(context, 0, intent, 0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected abstract fun defaultAppWidget(context: Context, appWidgetIds: IntArray)
|
|
|
|
|
|
|
|
abstract fun performUpdate(service: MusicService, appWidgetIds: IntArray?)
|
|
|
|
|
|
|
|
protected fun getAlbumArtDrawable(resources: Resources, bitmap: Bitmap?): Drawable {
|
|
|
|
return if (bitmap == null) {
|
2019-09-09 13:04:53 +00:00
|
|
|
ContextCompat.getDrawable(App.getContext(), R.drawable.default_album_art)!!
|
2018-12-08 03:33:02 +00:00
|
|
|
} else {
|
|
|
|
BitmapDrawable(resources, bitmap)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected fun getSongArtistAndAlbum(song: Song): String {
|
|
|
|
val builder = StringBuilder()
|
|
|
|
builder.append(song.artistName)
|
|
|
|
if (!TextUtils.isEmpty(song.artistName) && !TextUtils.isEmpty(song.albumName)) {
|
|
|
|
builder.append(" • ")
|
|
|
|
}
|
|
|
|
builder.append(song.albumName)
|
|
|
|
return builder.toString()
|
|
|
|
}
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
|
|
|
|
const val NAME: String = "app_widget"
|
|
|
|
|
|
|
|
|
|
|
|
fun createRoundedBitmap(drawable: Drawable?, width: Int, height: Int, tl: Float,
|
|
|
|
tr: Float, bl: Float, br: Float): Bitmap? {
|
|
|
|
if (drawable == null) {
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
|
|
val c = Canvas(bitmap)
|
|
|
|
drawable.setBounds(0, 0, width, height)
|
|
|
|
drawable.draw(c)
|
|
|
|
|
|
|
|
val rounded = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
|
|
|
|
|
|
val canvas = Canvas(rounded)
|
|
|
|
val paint = Paint()
|
|
|
|
paint.shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
|
|
|
|
paint.isAntiAlias = true
|
|
|
|
canvas.drawPath(composeRoundedRectPath(RectF(0f, 0f, width.toFloat(), height.toFloat()), tl, tr, bl, br), paint)
|
|
|
|
|
|
|
|
return rounded
|
|
|
|
}
|
|
|
|
|
|
|
|
fun createBitmap(drawable: Drawable, sizeMultiplier: Float): Bitmap {
|
|
|
|
val bitmap = Bitmap.createBitmap((drawable.intrinsicWidth * sizeMultiplier).toInt(),
|
|
|
|
(drawable.intrinsicHeight * sizeMultiplier).toInt(), Bitmap.Config.ARGB_8888)
|
|
|
|
val c = Canvas(bitmap)
|
|
|
|
drawable.setBounds(0, 0, c.width, c.height)
|
|
|
|
drawable.draw(c)
|
|
|
|
return bitmap
|
|
|
|
}
|
|
|
|
|
|
|
|
protected fun composeRoundedRectPath(rect: RectF, tl: Float, tr: Float, bl: Float, br: Float): Path {
|
|
|
|
val path = Path()
|
|
|
|
path.moveTo(rect.left + tl, rect.top)
|
|
|
|
path.lineTo(rect.right - tr, rect.top)
|
|
|
|
path.quadTo(rect.right, rect.top, rect.right, rect.top + tr)
|
|
|
|
path.lineTo(rect.right, rect.bottom - br)
|
|
|
|
path.quadTo(rect.right, rect.bottom, rect.right - br, rect.bottom)
|
|
|
|
path.lineTo(rect.left + bl, rect.bottom)
|
|
|
|
path.quadTo(rect.left, rect.bottom, rect.left, rect.bottom - bl)
|
|
|
|
path.lineTo(rect.left, rect.top + tl)
|
|
|
|
path.quadTo(rect.left, rect.top, rect.left + tl, rect.top)
|
|
|
|
path.close()
|
|
|
|
|
|
|
|
return path
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|