Merge branch 'feature/min-sdk-26' into 'develop'
Updated Min SDK to 26 Closes #1319 See merge request ultrasonic/ultrasonic!1195
1
.gitignore
vendored
@ -18,6 +18,7 @@ out/
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
.kotlin/
|
||||
build/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
|
@ -1,5 +1,5 @@
|
||||
ext.versions = [
|
||||
minSdk : 21,
|
||||
minSdk : 26,
|
||||
targetSdk : 33,
|
||||
compileSdk : 35,
|
||||
]
|
||||
|
@ -227,7 +227,7 @@ class NavigationActivity : ScopeActivity() {
|
||||
|
||||
// Setup app shortcuts on supported devices, but not on first start, when the server
|
||||
// is not configured yet.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 && !UApp.instance!!.isFirstRun) {
|
||||
if (!UApp.instance!!.isFirstRun) {
|
||||
ShortcutUtil.registerShortcuts(this)
|
||||
}
|
||||
|
||||
|
@ -114,10 +114,8 @@ private fun VmPolicy.Builder.detectAllExceptSocket(): VmPolicy.Builder {
|
||||
detectLeakedClosableObjects()
|
||||
detectLeakedRegistrationObjects()
|
||||
detectFileUriExposure()
|
||||
detectContentUriWithoutPermission()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
detectContentUriWithoutPermission()
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
detectCredentialProtectedWhileLocked()
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package org.moire.ultrasonic.imageloader
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.os.Build
|
||||
import com.squareup.picasso.Picasso.LoadedFrom.DISK
|
||||
import com.squareup.picasso.Picasso.LoadedFrom.NETWORK
|
||||
import com.squareup.picasso.Request
|
||||
@ -85,12 +84,6 @@ class CoverArtRequestHandler(private val client: SubsonicAPIClient) : RequestHan
|
||||
BitmapFactory.decodeFile(path, opt)
|
||||
|
||||
// Now set the remaining flags
|
||||
@Suppress("DEPRECATION")
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||
opt.inDither = true
|
||||
opt.inPreferQualityOverSpeed = true
|
||||
}
|
||||
|
||||
opt.inSampleSize = Util.calculateInSampleSize(
|
||||
opt,
|
||||
size,
|
||||
|
@ -13,7 +13,6 @@ import android.appwidget.AppWidgetProvider
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.view.KeyEvent
|
||||
@ -218,10 +217,8 @@ open class UltrasonicAppWidgetProvider : AppWidgetProvider() {
|
||||
intent.action = Intent.ACTION_MAIN
|
||||
intent.addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
var flags = PendingIntent.FLAG_UPDATE_CURRENT
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
// needed starting Android 12 (S = 31)
|
||||
flags = flags or PendingIntent.FLAG_IMMUTABLE
|
||||
}
|
||||
// needed starting Android 12 (S = 31)
|
||||
flags = flags or PendingIntent.FLAG_IMMUTABLE
|
||||
var pendingIntent =
|
||||
PendingIntent.getActivity(context, 10, intent, flags)
|
||||
views.setOnClickPendingIntent(R.id.appwidget_coverart, pendingIntent)
|
||||
@ -235,10 +232,8 @@ open class UltrasonicAppWidgetProvider : AppWidgetProvider() {
|
||||
KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)
|
||||
)
|
||||
flags = 0
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
// needed starting Android 12 (S = 31)
|
||||
flags = PendingIntent.FLAG_IMMUTABLE
|
||||
}
|
||||
// needed starting Android 12 (S = 31)
|
||||
flags = PendingIntent.FLAG_IMMUTABLE
|
||||
pendingIntent = PendingIntent.getBroadcast(context, 11, intent, flags)
|
||||
views.setOnClickPendingIntent(R.id.control_play, pendingIntent)
|
||||
intent = Intent(Constants.CMD_PROCESS_KEYCODE)
|
||||
|
@ -12,7 +12,6 @@ import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.net.wifi.WifiManager
|
||||
import android.os.Binder
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.IBinder
|
||||
import android.os.Looper
|
||||
@ -509,11 +508,7 @@ class DownloadService : Service(), KoinComponent {
|
||||
try {
|
||||
val context = UApp.applicationContext()
|
||||
val intent = Intent(context, DownloadService::class.java)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
context.startForegroundService(intent)
|
||||
} else {
|
||||
context.startService(intent)
|
||||
}
|
||||
context.startForegroundService(intent)
|
||||
} catch (e: IllegalStateException) {
|
||||
Timber.w(e, "Failed to start download service: the app is in the background")
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
package org.moire.ultrasonic.service
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.car.app.connection.CarConnection
|
||||
@ -268,40 +267,36 @@ class MediaLibrarySessionCallback :
|
||||
}
|
||||
|
||||
private fun configureRepeatMode(player: Player) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
Timber.d("Car app library available, observing CarConnection")
|
||||
Timber.d("Car app library available, observing CarConnection")
|
||||
|
||||
val originalRepeatMode = player.repeatMode
|
||||
val originalRepeatMode = player.repeatMode
|
||||
|
||||
var lastCarConnectionType = -1
|
||||
var lastCarConnectionType = -1
|
||||
|
||||
CarConnection(UApp.applicationContext()).type.observeForever {
|
||||
if (lastCarConnectionType == it) {
|
||||
return@observeForever
|
||||
}
|
||||
|
||||
lastCarConnectionType = it
|
||||
|
||||
Timber.d("CarConnection type changed to %s", it)
|
||||
|
||||
when (it) {
|
||||
CarConnection.CONNECTION_TYPE_PROJECTION ->
|
||||
if (!customRepeatModeSet) {
|
||||
Timber.d("[CarConnection] Setting repeat mode to ALL")
|
||||
player.repeatMode = Player.REPEAT_MODE_ALL
|
||||
customRepeatModeSet = true
|
||||
}
|
||||
|
||||
CarConnection.CONNECTION_TYPE_NOT_CONNECTED ->
|
||||
if (customRepeatModeSet) {
|
||||
Timber.d("[CarConnection] Resetting repeat mode")
|
||||
player.repeatMode = originalRepeatMode
|
||||
customRepeatModeSet = false
|
||||
}
|
||||
}
|
||||
CarConnection(UApp.applicationContext()).type.observeForever {
|
||||
if (lastCarConnectionType == it) {
|
||||
return@observeForever
|
||||
}
|
||||
|
||||
lastCarConnectionType = it
|
||||
|
||||
Timber.d("CarConnection type changed to %s", it)
|
||||
|
||||
when (it) {
|
||||
CarConnection.CONNECTION_TYPE_PROJECTION ->
|
||||
if (!customRepeatModeSet) {
|
||||
Timber.d("[CarConnection] Setting repeat mode to ALL")
|
||||
player.repeatMode = Player.REPEAT_MODE_ALL
|
||||
customRepeatModeSet = true
|
||||
}
|
||||
|
||||
CarConnection.CONNECTION_TYPE_NOT_CONNECTED ->
|
||||
if (customRepeatModeSet) {
|
||||
Timber.d("[CarConnection] Resetting repeat mode")
|
||||
player.repeatMode = originalRepeatMode
|
||||
customRepeatModeSet = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Timber.d("Car app library not available")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@ import android.app.PendingIntent
|
||||
import android.app.PendingIntent.FLAG_IMMUTABLE
|
||||
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.app.TaskStackBuilder
|
||||
@ -337,11 +336,7 @@ class PlaybackService :
|
||||
private fun getPendingIntentForContent(): PendingIntent {
|
||||
val intent = Intent(this, NavigationActivity::class.java)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
var flags = FLAG_UPDATE_CURRENT
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
// needed starting Android 12 (S = 31)
|
||||
flags = flags or FLAG_IMMUTABLE
|
||||
}
|
||||
val flags = FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
|
||||
intent.action = Intent.ACTION_MAIN
|
||||
intent.putExtra(Constants.INTENT_SHOW_PLAYER, true)
|
||||
return PendingIntent.getActivity(this, 0, intent, flags)
|
||||
@ -382,12 +377,8 @@ class PlaybackService :
|
||||
TaskStackBuilder.create(this@PlaybackService).run {
|
||||
addNextIntent(Intent(this@PlaybackService, NavigationActivity::class.java))
|
||||
|
||||
val immutableFlag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
FLAG_IMMUTABLE
|
||||
} else {
|
||||
0
|
||||
}
|
||||
getPendingIntent(0, immutableFlag or FLAG_UPDATE_CURRENT)
|
||||
val immutableFlag = FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT
|
||||
getPendingIntent(0, immutableFlag)
|
||||
}
|
||||
val builder =
|
||||
NotificationCompat.Builder(this@PlaybackService, NOTIFICATION_CHANNEL_ID)
|
||||
|
@ -8,8 +8,6 @@
|
||||
package org.moire.ultrasonic.util
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.text.TextUtils
|
||||
import android.util.Pair
|
||||
import java.io.BufferedWriter
|
||||
@ -259,16 +257,7 @@ object FileUtil {
|
||||
get() {
|
||||
// Return cached if possible
|
||||
if (cachedUltrasonicDirectory != null) return cachedUltrasonicDirectory!!
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
cachedUltrasonicDirectory = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
File(
|
||||
Environment.getExternalStorageDirectory(),
|
||||
"Android/data/org.moire.ultrasonic"
|
||||
)
|
||||
} else {
|
||||
UApp.applicationContext().getExternalFilesDir(null)!!
|
||||
}
|
||||
cachedUltrasonicDirectory = UApp.applicationContext().getExternalFilesDir(null)!!
|
||||
|
||||
return cachedUltrasonicDirectory!!
|
||||
}
|
||||
|
@ -10,8 +10,6 @@ package org.moire.ultrasonic.util
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
@ -25,11 +23,7 @@ class LocaleHelper(base: Context?) : ContextWrapper(base) {
|
||||
val config = context.resources.configuration
|
||||
val locale = Locale.forLanguageTag(language)
|
||||
Locale.setDefault(locale)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
setSystemLocale(config, locale)
|
||||
} else {
|
||||
setSystemLocaleLegacy(config, locale)
|
||||
}
|
||||
setSystemLocale(config, locale)
|
||||
|
||||
config.setLayoutDirection(locale)
|
||||
context = context.createConfigurationContext(config)
|
||||
@ -37,13 +31,7 @@ class LocaleHelper(base: Context?) : ContextWrapper(base) {
|
||||
return LocaleHelper(context)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private fun setSystemLocaleLegacy(config: Configuration, locale: Locale?) {
|
||||
config.locale = locale
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
fun setSystemLocale(config: Configuration, locale: Locale?) {
|
||||
private fun setSystemLocale(config: Configuration, locale: Locale?) {
|
||||
config.setLocale(locale)
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.DocumentsContract
|
||||
import androidx.activity.result.contract.ActivityResultContract
|
||||
import org.moire.ultrasonic.fragment.SettingsFragment
|
||||
@ -19,7 +18,7 @@ import org.moire.ultrasonic.fragment.SettingsFragment
|
||||
class SelectCacheActivityContract : ActivityResultContract<String?, Uri?>() {
|
||||
override fun createIntent(context: Context, input: String?): Intent {
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||
if (Settings.cacheLocationUri != "" && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (Settings.cacheLocationUri != "") {
|
||||
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, input)
|
||||
}
|
||||
intent.addFlags(SettingsFragment.RW_FLAG)
|
||||
|
@ -12,13 +12,10 @@ import android.content.Intent
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.content.pm.ShortcutManager
|
||||
import android.graphics.drawable.Icon
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.activity.NavigationActivity
|
||||
|
||||
object ShortcutUtil {
|
||||
@RequiresApi(Build.VERSION_CODES.N_MR1)
|
||||
fun registerShortcuts(activity: Activity) {
|
||||
val shortcutIntent = Intent(activity, NavigationActivity::class.java).apply {
|
||||
action = Constants.INTENT_PLAY_RANDOM_SONGS
|
||||
|
@ -303,16 +303,14 @@ object Util {
|
||||
|
||||
private fun isNetworkMetered(): Boolean {
|
||||
val connManager = connectivityManager
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
val capabilities = connManager.getNetworkCapabilities(
|
||||
connManager.activeNetwork
|
||||
)
|
||||
if (capabilities != null &&
|
||||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
|
||||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
val capabilities = connManager.getNetworkCapabilities(
|
||||
connManager.activeNetwork
|
||||
)
|
||||
if (capabilities != null &&
|
||||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
|
||||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
return connManager.isActiveNetworkMetered
|
||||
}
|
||||
@ -320,21 +318,13 @@ object Util {
|
||||
@Suppress("DEPRECATION")
|
||||
private fun isNetworkCellular(): Boolean {
|
||||
val connManager = connectivityManager
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
val network = connManager.activeNetwork
|
||||
?: return false // Nothing connected
|
||||
connManager.getNetworkInfo(network)
|
||||
?: return true // Better be safe than sorry
|
||||
val capabilities = connManager.getNetworkCapabilities(network)
|
||||
?: return true // Better be safe than sorry
|
||||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
|
||||
} else {
|
||||
// if the default network is a VPN,
|
||||
// this method will return the NetworkInfo for one of its underlying networks
|
||||
val info = connManager.activeNetworkInfo
|
||||
?: return false // Nothing connected
|
||||
info.type == ConnectivityManager.TYPE_MOBILE
|
||||
}
|
||||
val network = connManager.activeNetwork
|
||||
?: return false // Nothing connected
|
||||
connManager.getNetworkInfo(network)
|
||||
?: return true // Better be safe than sorry
|
||||
val capabilities = connManager.getNetworkCapabilities(network)
|
||||
?: return true // Better be safe than sorry
|
||||
return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -502,20 +492,18 @@ object Util {
|
||||
importance: Int? = null,
|
||||
notificationManager: NotificationManagerCompat
|
||||
) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// The suggested importance of a startForeground service notification is IMPORTANCE_LOW
|
||||
val channel = NotificationChannel(
|
||||
id,
|
||||
name,
|
||||
importance ?: NotificationManager.IMPORTANCE_DEFAULT
|
||||
)
|
||||
// The suggested importance of a startForeground service notification is IMPORTANCE_LOW
|
||||
val channel = NotificationChannel(
|
||||
id,
|
||||
name,
|
||||
importance ?: NotificationManager.IMPORTANCE_DEFAULT
|
||||
)
|
||||
|
||||
channel.lightColor = android.R.color.holo_blue_dark
|
||||
channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
|
||||
channel.setShowBadge(false)
|
||||
channel.lightColor = android.R.color.holo_blue_dark
|
||||
channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
|
||||
channel.setShowBadge(false)
|
||||
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
fun ensurePermissionToPostNotification(
|
||||
@ -773,10 +761,8 @@ object Util {
|
||||
val intent = Intent(context, NavigationActivity::class.java)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
var flags = PendingIntent.FLAG_UPDATE_CURRENT
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
// needed starting Android 12 (S = 31)
|
||||
flags = flags or PendingIntent.FLAG_IMMUTABLE
|
||||
}
|
||||
// needed starting Android 12 (S = 31)
|
||||
flags = flags or PendingIntent.FLAG_IMMUTABLE
|
||||
intent.putExtra(Constants.INTENT_SHOW_PLAYER, true)
|
||||
return PendingIntent.getActivity(context, 0, intent, flags)
|
||||
}
|
||||
@ -809,12 +795,7 @@ object Util {
|
||||
}
|
||||
|
||||
fun Service.stopForegroundRemoveNotification() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
stopForeground(true)
|
||||
}
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
}
|
||||
|
||||
fun dumpSettingsToLog() {
|
||||
|
@ -32,6 +32,7 @@
|
||||
a:gravity="bottom" >
|
||||
<EditText
|
||||
a:id="@+id/chat_edittext"
|
||||
a:importantForAutofill="no"
|
||||
a:layout_width="0dp"
|
||||
a:layout_height="wrap_content"
|
||||
a:layout_weight="1"
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
<EditText
|
||||
a:id="@+id/save_playlist_name"
|
||||
a:importantForAutofill="no"
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="wrap_content"
|
||||
a:inputType="text"
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
<EditText
|
||||
a:id="@+id/share_description"
|
||||
a:importantForAutofill="no"
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="50dp"
|
||||
a:layout_marginTop="4dip"
|
||||
|
@ -35,6 +35,7 @@
|
||||
android:layout_alignParentEnd="false"
|
||||
android:ems="5"
|
||||
android:gravity="left"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="numberSigned" />
|
||||
|
||||
<Spinner
|
||||
|
@ -1,48 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ rating.xml
|
||||
~ Copyright (C) 2009-2023 Ultrasonic developers
|
||||
~
|
||||
~ Distributed under terms of the GNU GPLv3 license.
|
||||
-->
|
||||
|
||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item android:id="@+id/popup_rate_5"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_5"
|
||||
android:title="@string/menu.rating_5" />
|
||||
|
||||
<item android:id="@+id/popup_rate_4"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_4"
|
||||
android:title="@string/menu.rating_4" />
|
||||
|
||||
<item android:id="@+id/popup_rate_3"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_3"
|
||||
android:title="@string/menu.rating_3" />
|
||||
|
||||
<item android:id="@+id/popup_rate_2"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_2"
|
||||
android:title="@string/menu.rating_2" />
|
||||
|
||||
<item android:id="@+id/popup_rate_1"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_1"
|
||||
android:title="@string/menu.rating_1" />
|
||||
|
||||
<item android:id="@+id/popup_rate_0"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_0"
|
||||
android:title="@string/menu.rating_no_rating" />
|
||||
|
||||
</menu>
|
@ -10,31 +10,37 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item android:id="@+id/popup_rate_5"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_5"
|
||||
android:title="@string/menu.rating_5" />
|
||||
|
||||
<item android:id="@+id/popup_rate_4"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_4"
|
||||
android:title="@string/menu.rating_4" />
|
||||
|
||||
<item android:id="@+id/popup_rate_3"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_3"
|
||||
android:title="@string/menu.rating_3" />
|
||||
|
||||
<item android:id="@+id/popup_rate_2"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_2"
|
||||
android:title="@string/menu.rating_2" />
|
||||
|
||||
<item android:id="@+id/popup_rate_1"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_1"
|
||||
android:title="@string/menu.rating_1" />
|
||||
|
||||
<item android:id="@+id/popup_rate_0"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_0"
|
||||
android:title="@string/menu.rating_no_rating" />
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 13 KiB |
@ -1,8 +1,10 @@
|
||||
package org.moire.ultrasonic.imageloader
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import com.squareup.picasso.Picasso
|
||||
import com.squareup.picasso.Request
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import org.amshove.kluent.`should be equal to`
|
||||
import org.amshove.kluent.`should not be`
|
||||
@ -16,6 +18,7 @@ import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.whenever
|
||||
import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient
|
||||
import org.moire.ultrasonic.api.subsonic.response.StreamResponse
|
||||
import org.moire.ultrasonic.util.FileUtil
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@ -55,6 +58,10 @@ class CoverArtRequestHandlerTest {
|
||||
@Test
|
||||
fun `Should throw IOException when request to api failed`() {
|
||||
val streamResponse = StreamResponse(null, null, 500)
|
||||
FileUtil.cachedUltrasonicDirectory = File(
|
||||
Environment.getExternalStorageDirectory(),
|
||||
"Android/data/org.moire.ultrasonic"
|
||||
)
|
||||
|
||||
whenever(
|
||||
mockApiClient.toStreamResponse(any())
|
||||
@ -74,6 +81,10 @@ class CoverArtRequestHandlerTest {
|
||||
apiError = null,
|
||||
responseHttpCode = 200
|
||||
)
|
||||
FileUtil.cachedUltrasonicDirectory = File(
|
||||
Environment.getExternalStorageDirectory(),
|
||||
"Android/data/org.moire.ultrasonic"
|
||||
)
|
||||
|
||||
whenever(
|
||||
mockApiClient.toStreamResponse(any())
|
||||
|