summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Charles Lombardo2023-03-14 20:23:00 -0400
committerGravatar bunnei2023-06-03 00:05:43 -0700
commit3fcc6b11042e86ef05d074fe287a02a40ed4d76e (patch)
tree94fc69a57087c07d8fa67f612eb32fce72ad3c26 /src
parentandroid: New swipe to refresh color scheme (diff)
downloadyuzu-3fcc6b11042e86ef05d074fe287a02a40ed4d76e.tar.gz
yuzu-3fcc6b11042e86ef05d074fe287a02a40ed4d76e.tar.xz
yuzu-3fcc6b11042e86ef05d074fe287a02a40ed4d76e.zip
android: Replace Picasso with Coil
Diffstat (limited to 'src')
-rw-r--r--src/android/app/build.gradle4
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt44
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt1
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt3
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconRequestHandler.kt25
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/PicassoRoundedCornersTransformation.java45
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/PicassoUtils.java57
7 files changed, 41 insertions, 138 deletions
diff --git a/src/android/app/build.gradle b/src/android/app/build.gradle
index c0bd7d459..68e11bb66 100644
--- a/src/android/app/build.gradle
+++ b/src/android/app/build.gradle
@@ -135,9 +135,7 @@ dependencies {
135 implementation 'com.google.android.material:material:1.8.0' 135 implementation 'com.google.android.material:material:1.8.0'
136 implementation 'androidx.preference:preference:1.2.0' 136 implementation 'androidx.preference:preference:1.2.0'
137 implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1" 137 implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
138 138 implementation "io.coil-kt:coil:2.2.2"
139 // For loading huge screenshots from the disk.
140 implementation 'com.squareup.picasso:picasso:2.71828'
141 139
142 // Allows FRP-style asynchronous operations in Android. 140 // Allows FRP-style asynchronous operations in Android.
143 implementation 'io.reactivex:rxandroid:1.2.1' 141 implementation 'io.reactivex:rxandroid:1.2.1'
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt
index af4ec63f2..8891705a5 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt
@@ -5,17 +5,27 @@ package org.yuzu.yuzu_emu.adapters
5 5
6import android.database.Cursor 6import android.database.Cursor
7import android.database.DataSetObserver 7import android.database.DataSetObserver
8import android.graphics.Bitmap
9import android.graphics.BitmapFactory
10import android.net.Uri
8import android.view.LayoutInflater 11import android.view.LayoutInflater
9import android.view.View 12import android.view.View
10import android.view.ViewGroup 13import android.view.ViewGroup
14import android.widget.ImageView
15import androidx.appcompat.app.AppCompatActivity
11import androidx.fragment.app.FragmentActivity 16import androidx.fragment.app.FragmentActivity
17import androidx.lifecycle.lifecycleScope
12import androidx.recyclerview.widget.RecyclerView 18import androidx.recyclerview.widget.RecyclerView
19import coil.load
13import com.google.android.material.color.MaterialColors 20import com.google.android.material.color.MaterialColors
21import kotlinx.coroutines.Dispatchers
22import kotlinx.coroutines.launch
23import kotlinx.coroutines.withContext
24import org.yuzu.yuzu_emu.NativeLibrary
14import org.yuzu.yuzu_emu.R 25import org.yuzu.yuzu_emu.R
15import org.yuzu.yuzu_emu.activities.EmulationActivity.Companion.launch 26import org.yuzu.yuzu_emu.activities.EmulationActivity.Companion.launch
16import org.yuzu.yuzu_emu.model.GameDatabase 27import org.yuzu.yuzu_emu.model.GameDatabase
17import org.yuzu.yuzu_emu.utils.Log 28import org.yuzu.yuzu_emu.utils.Log
18import org.yuzu.yuzu_emu.utils.PicassoUtils
19import org.yuzu.yuzu_emu.viewholders.GameViewHolder 29import org.yuzu.yuzu_emu.viewholders.GameViewHolder
20import java.util.* 30import java.util.*
21import java.util.stream.Stream 31import java.util.stream.Stream
@@ -25,7 +35,8 @@ import java.util.stream.Stream
25 * ContentProviders and Loaders, allows for efficient display of a limited view into a (possibly) 35 * ContentProviders and Loaders, allows for efficient display of a limited view into a (possibly)
26 * large dataset. 36 * large dataset.
27 */ 37 */
28class GameAdapter : RecyclerView.Adapter<GameViewHolder>(), View.OnClickListener { 38class GameAdapter(private val activity: AppCompatActivity) : RecyclerView.Adapter<GameViewHolder>(),
39 View.OnClickListener {
29 private var cursor: Cursor? = null 40 private var cursor: Cursor? = null
30 private val observer: GameDataSetObserver? 41 private val observer: GameDataSetObserver?
31 private var isDatasetValid = false 42 private var isDatasetValid = false
@@ -51,10 +62,21 @@ class GameAdapter : RecyclerView.Adapter<GameViewHolder>(), View.OnClickListener
51 override fun onBindViewHolder(holder: GameViewHolder, position: Int) { 62 override fun onBindViewHolder(holder: GameViewHolder, position: Int) {
52 if (isDatasetValid) { 63 if (isDatasetValid) {
53 if (cursor!!.moveToPosition(position)) { 64 if (cursor!!.moveToPosition(position)) {
54 PicassoUtils.loadGameIcon( 65 holder.imageIcon.scaleType = ImageView.ScaleType.CENTER_CROP
55 holder.imageIcon, 66 activity.lifecycleScope.launch {
56 cursor!!.getString(GameDatabase.GAME_COLUMN_PATH) 67 withContext(Dispatchers.IO) {
57 ) 68 val uri =
69 Uri.parse(cursor!!.getString(GameDatabase.GAME_COLUMN_PATH)).toString()
70 val bitmap = decodeGameIcon(uri)
71 withContext(Dispatchers.Main) {
72 holder.imageIcon.load(bitmap) {
73 error(R.drawable.no_icon)
74 crossfade(true)
75 }
76 }
77 }
78 }
79
58 holder.textGameTitle.text = 80 holder.textGameTitle.text =
59 cursor!!.getString(GameDatabase.GAME_COLUMN_TITLE) 81 cursor!!.getString(GameDatabase.GAME_COLUMN_TITLE)
60 .replace("[\\t\\n\\r]+".toRegex(), " ") 82 .replace("[\\t\\n\\r]+".toRegex(), " ")
@@ -165,6 +187,16 @@ class GameAdapter : RecyclerView.Adapter<GameViewHolder>(), View.OnClickListener
165 } 187 }
166 } 188 }
167 189
190 private fun decodeGameIcon(uri: String): Bitmap {
191 val data = NativeLibrary.GetIcon(uri)
192 return BitmapFactory.decodeByteArray(
193 data,
194 0,
195 data.size,
196 BitmapFactory.Options()
197 )
198 }
199
168 private inner class GameDataSetObserver : DataSetObserver() { 200 private inner class GameDataSetObserver : DataSetObserver() {
169 override fun onChanged() { 201 override fun onChanged() {
170 super.onChanged() 202 super.onChanged()
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
index ba60a26e8..768159857 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
@@ -57,7 +57,6 @@ class MainActivity : AppCompatActivity(), MainView {
57 PlatformGamesFragment.TAG 57 PlatformGamesFragment.TAG
58 ) as PlatformGamesFragment? 58 ) as PlatformGamesFragment?
59 } 59 }
60 PicassoUtils.init()
61 60
62 // Dismiss previous notifications (should not happen unless a crash occurred) 61 // Dismiss previous notifications (should not happen unless a crash occurred)
63 EmulationActivity.tryDismissRunningNotification(this) 62 EmulationActivity.tryDismissRunningNotification(this)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt
index 73929e186..40e902a37 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt
@@ -10,6 +10,7 @@ import android.view.View
10import android.view.ViewGroup 10import android.view.ViewGroup
11import android.view.ViewTreeObserver.OnGlobalLayoutListener 11import android.view.ViewTreeObserver.OnGlobalLayoutListener
12import android.widget.TextView 12import android.widget.TextView
13import androidx.appcompat.app.AppCompatActivity
13import androidx.core.view.ViewCompat 14import androidx.core.view.ViewCompat
14import androidx.core.view.WindowInsetsCompat 15import androidx.core.view.WindowInsetsCompat
15import androidx.core.view.updatePadding 16import androidx.core.view.updatePadding
@@ -40,7 +41,7 @@ class PlatformGamesFragment : Fragment(), PlatformGamesView {
40 } 41 }
41 42
42 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 43 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
43 adapter = GameAdapter() 44 adapter = GameAdapter(requireActivity() as AppCompatActivity)
44 45
45 // Organize our grid layout based on the current view. 46 // Organize our grid layout based on the current view.
46 if (isAdded) { 47 if (isAdded) {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconRequestHandler.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconRequestHandler.kt
deleted file mode 100644
index 24ed309a8..000000000
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconRequestHandler.kt
+++ /dev/null
@@ -1,25 +0,0 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.utils
5
6import android.graphics.BitmapFactory
7import com.squareup.picasso.Picasso
8import com.squareup.picasso.Request
9import com.squareup.picasso.RequestHandler
10import org.yuzu.yuzu_emu.NativeLibrary
11
12class GameIconRequestHandler : RequestHandler() {
13 override fun canHandleRequest(data: Request): Boolean {
14 return "content" == data.uri.scheme
15 }
16
17 override fun load(request: Request, networkPolicy: Int): Result {
18 val gamePath = request.uri.toString()
19 val data = NativeLibrary.GetIcon(gamePath)
20 val options = BitmapFactory.Options()
21 options.inMutable = true
22 val bitmap = BitmapFactory.decodeByteArray(data, 0, data.size, options)
23 return Result(bitmap, Picasso.LoadedFrom.DISK)
24 }
25}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/PicassoRoundedCornersTransformation.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/PicassoRoundedCornersTransformation.java
deleted file mode 100644
index 03057b0d5..000000000
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/PicassoRoundedCornersTransformation.java
+++ /dev/null
@@ -1,45 +0,0 @@
1package org.yuzu.yuzu_emu.utils;
2
3import android.graphics.Bitmap;
4import android.graphics.BitmapShader;
5import android.graphics.Canvas;
6import android.graphics.Paint;
7import android.graphics.Rect;
8import android.graphics.RectF;
9
10import com.squareup.picasso.Transformation;
11
12public class PicassoRoundedCornersTransformation implements Transformation {
13 @Override
14 public Bitmap transform(Bitmap icon) {
15 final int width = icon.getWidth();
16 final int height = icon.getHeight();
17 final Rect rect = new Rect(0, 0, width, height);
18 final int size = Math.min(width, height);
19 final int x = (width - size) / 2;
20 final int y = (height - size) / 2;
21
22 Bitmap squaredBitmap = Bitmap.createBitmap(icon, x, y, size, size);
23 if (squaredBitmap != icon) {
24 icon.recycle();
25 }
26
27 Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
28 Canvas canvas = new Canvas(output);
29 BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
30 Paint paint = new Paint();
31 paint.setAntiAlias(true);
32 paint.setShader(shader);
33
34 canvas.drawRoundRect(new RectF(rect), 10, 10, paint);
35
36 squaredBitmap.recycle();
37
38 return output;
39 }
40
41 @Override
42 public String key() {
43 return "circle";
44 }
45} \ No newline at end of file
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/PicassoUtils.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/PicassoUtils.java
deleted file mode 100644
index 504dc5b6d..000000000
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/PicassoUtils.java
+++ /dev/null
@@ -1,57 +0,0 @@
1package org.yuzu.yuzu_emu.utils;
2
3import android.graphics.Bitmap;
4import android.net.Uri;
5import android.widget.ImageView;
6
7import com.squareup.picasso.Picasso;
8
9import org.yuzu.yuzu_emu.YuzuApplication;
10import org.yuzu.yuzu_emu.R;
11
12import java.io.IOException;
13
14import androidx.annotation.Nullable;
15
16public class PicassoUtils {
17 private static boolean mPicassoInitialized = false;
18
19 public static void init() {
20 if (mPicassoInitialized) {
21 return;
22 }
23 Picasso picassoInstance = new Picasso.Builder(YuzuApplication.getAppContext())
24 .addRequestHandler(new GameIconRequestHandler())
25 .build();
26
27 Picasso.setSingletonInstance(picassoInstance);
28 mPicassoInitialized = true;
29 }
30
31 public static void loadGameIcon(ImageView imageView, String gamePath) {
32 Picasso
33 .get()
34 .load(Uri.parse(gamePath))
35 .fit()
36 .centerInside()
37 .config(Bitmap.Config.RGB_565)
38 .error(R.drawable.no_icon)
39 .transform(new PicassoRoundedCornersTransformation())
40 .into(imageView);
41 }
42
43 // Blocking call. Load image from file and crop/resize it to fit in width x height.
44 @Nullable
45 public static Bitmap LoadBitmapFromFile(String uri, int width, int height) {
46 try {
47 return Picasso.get()
48 .load(Uri.parse(uri))
49 .config(Bitmap.Config.ARGB_8888)
50 .centerCrop()
51 .resize(width, height)
52 .get();
53 } catch (IOException e) {
54 return null;
55 }
56 }
57}