Add ability to create per-game shortcuts.

This commit is contained in:
Phil Jones 2022-11-17 16:14:55 +00:00
parent d475e13704
commit 0a0312f344
No known key found for this signature in database
GPG Key ID: 7E6F59EE25CDC6A5
9 changed files with 238 additions and 3 deletions

View File

@ -85,8 +85,8 @@ dependencies {
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1")
implementation("androidx.lifecycle:lifecycle-viewmodel:2.5.1")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test:runner:1.4.0")
androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
androidTestImplementation("androidx.test:runner:1.5.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
}
tasks.register<Copy>("copyAssets") {

View File

@ -45,7 +45,13 @@
<activity android:name=".GLActivity"
android:parentActivityName="MainActivity"
android:immersive="true" />
android:immersive="true"
android:exported="true">
<intent-filter>
<action android:name="com.philj56.gbcc.launch_game" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".CheatActivity"
android:parentActivityName="MainActivity"

View File

@ -12,11 +12,15 @@ package com.philj56.gbcc
import android.content.ActivityNotFoundException
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.AdaptiveIconDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.OpenableColumns
import android.util.Log
import android.util.TypedValue
import android.view.MenuItem
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
@ -25,6 +29,9 @@ import android.widget.Toast
import androidx.activity.addCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.core.view.forEach
import androidx.fragment.app.DialogFragment
import androidx.preference.PreferenceManager
@ -421,6 +428,53 @@ class MainActivity : BaseActivity() {
startActivity(intent)
dialog.dismiss()
}
binding.buttonAddShortcut.setOnClickListener {
if (!ShortcutManagerCompat.isRequestPinShortcutSupported(this)) {
return@setOnClickListener
}
val iconResource = if (file.extension == "gbc") {
R.drawable.ic_game_shortcut_gbc
} else {
R.drawable.ic_game_shortcut_dmg
}
val icon =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val iconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 108f, resources.displayMetrics).toInt()
val borderSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 18f, resources.displayMetrics).toInt()
val drawable = AdaptiveIconDrawable(
IconCompat.createWithResource(this, R.drawable.ic_launcher_background).loadDrawable(this),
IconCompat.createWithResource(this, iconResource).loadDrawable(this),
)
drawable.setBounds(borderSize, borderSize, iconSize - borderSize, iconSize - borderSize)
val bitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888)
drawable.draw(Canvas(bitmap))
IconCompat.createWithAdaptiveBitmap(bitmap)
} else {
IconCompat.createWithResource(this, iconResource)
}
val shortcut = ShortcutInfoCompat.Builder(this, "launch_${file.name}")
.setShortLabel(file.name)
.setLongLabel("Open ${file.name}")
.setIcon(icon)
.setIntents(
arrayOf(
/* Clear any existing activities, and launch the game */
Intent(this, MainActivity::class.java).apply {
action = Intent.ACTION_VIEW
flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
},
Intent(this, GLActivity::class.java).apply {
action = resources.getString(R.string.launch_game_intent)
putExtra("file", file.toString())
}
)
)
.build()
ShortcutManagerCompat.requestPinShortcut(this, shortcut, null)
}
}
private fun showRenameDialog(file: File) {

View File

@ -0,0 +1,100 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillAlpha="0.2"
android:pathData="M38,76 L70,32 L108,60 L76,104 Z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="54"
android:startY="54"
android:startColor="#FF000000"
android:endX="92"
android:endY="82"
android:endColor="#00000000"
android:gradientRadius="50"
android:type="linear"/>
</aapt:attr>
</path>
<path
android:pathData="m39.88,31.5c-0.49,0 -0.88,0.4 -0.88,0.89v43.47c0,0.49 0.39,0.89 0.88,0.89h24.71c2.44,0 4.41,-1.98 4.41,-4.43v-39.92c0,-0.49 -0.39,-0.89 -0.88,-0.89z"
android:fillColor="#c6c0bd"/>
<path
android:fillColor="#FF000000"
android:pathData="m69,71.4c0,2.45 -1.97,4.43 -4.41,4.43h-24.71c-0.49,0 -0.88,-0.4 -0.88,-0.89v0.89c0,0.49 0.39,0.89 0.88,0.89h24.71c2.44,0 4.41,-1.98 4.41,-4.43z"
android:strokeAlpha="0.2"
android:fillAlpha="0.2"/>
<path
android:pathData="m39.83,31.5c-0.46,0 -0.83,0.39 -0.83,0.87v1c0,-0.48 0.37,-0.87 0.83,-0.87h28.33c0.46,0 0.83,0.39 0.83,0.87v-1c0,-0.48 -0.37,-0.87 -0.83,-0.87h-28.33z"
android:strokeAlpha="0.2"
android:fillColor="#fff"
android:fillAlpha="0.2"/>
<path
android:pathData="M57.1,67.4m-2.6,0a2.6,2.6 0,1 1,5.2 0a2.6,2.6 0,1 1,-5.2 0"
android:fillColor="#9c2457"/>
<path
android:pathData="m57.1,64.8a2.6,2.6 0,0 0,-2.6 2.6,2.6 2.6,0 0,0 0.01,0.24 2.6,2.6 0,0 1,2.59 -2.34,2.6 2.6,0 0,1 2.59,2.36 2.6,2.6 0,0 0,0.01 -0.26,2.6 2.6,0 0,0 -2.6,-2.6z"
android:strokeAlpha="0.2"
android:fillColor="#fbfbfb"
android:fillAlpha="0.2"/>
<path
android:fillColor="#FF000000"
android:pathData="m54.51,67.15a2.6,2.6 0,0 0,-0.01 0.25,2.6 2.6,0 0,0 2.6,2.6 2.6,2.6 0,0 0,2.6 -2.6,2.6 2.6,0 0,0 -0.01,-0.24 2.6,2.6 0,0 1,-2.59 2.34,2.6 2.6,0 0,1 -2.59,-2.35z"
android:strokeAlpha="0.2"
android:fillAlpha="0.2"/>
<path
android:pathData="M41.64,33.5L66.36,33.5A0.89,0.89 0,0 1,67.25 34.39L67.25,56.61A0.89,0.89 0,0 1,66.36 57.5L41.64,57.5A0.89,0.89 0,0 1,40.75 56.61L40.75,34.39A0.89,0.89 0,0 1,41.64 33.5z"
android:fillColor="#8b888e"/>
<path
android:pathData="M44.63,36.2L63.37,36.2A0.88,0.88 0,0 1,64.25 37.08L64.25,53.82A0.88,0.88 0,0 1,63.37 54.7L44.63,54.7A0.88,0.88 0,0 1,43.75 53.82L43.75,37.08A0.88,0.88 0,0 1,44.63 36.2z"
android:fillColor="#8ac52c"/>
<path
android:pathData="M63.6,63.4m-2.6,0a2.6,2.6 0,1 1,5.2 0a2.6,2.6 0,1 1,-5.2 0"
android:fillColor="#9c2457"/>
<path
android:pathData="m63.6,60.8a2.6,2.6 0,0 0,-2.6 2.6,2.6 2.6,0 0,0 0.01,0.24 2.6,2.6 0,0 1,2.59 -2.34,2.6 2.6,0 0,1 2.59,2.36 2.6,2.6 0,0 0,0.01 -0.26,2.6 2.6,0 0,0 -2.6,-2.6z"
android:strokeAlpha="0.2"
android:fillColor="#fbfbfb"
android:fillAlpha="0.2"/>
<path
android:fillColor="#FF000000"
android:pathData="m61.01,63.15a2.6,2.6 0,0 0,-0.01 0.25,2.6 2.6,0 0,0 2.6,2.6 2.6,2.6 0,0 0,2.6 -2.6,2.6 2.6,0 0,0 -0.01,-0.24 2.6,2.6 0,0 1,-2.59 2.34,2.6 2.6,0 0,1 -2.59,-2.35z"
android:strokeAlpha="0.2"
android:fillAlpha="0.2"/>
<path
android:pathData="m46.05,59.5c-0.58,0 -1.05,0.47 -1.05,1.05v2.45h-2.45c-0.58,0 -1.05,0.47 -1.05,1.05v1.4c0,0.58 0.47,1.05 1.05,1.05h2.45v2.45c0,0.58 0.47,1.05 1.05,1.05h1.4c0.58,0 1.05,-0.47 1.05,-1.05v-2.45h2.45c0.58,0 1.05,-0.47 1.05,-1.05v-1.4c0,-0.58 -0.47,-1.05 -1.05,-1.05h-2.45v-2.45c0,-0.58 -0.47,-1.05 -1.05,-1.05z"
android:fillColor="#373737"/>
<path
android:pathData="m46.05,59.5c-0.58,0 -1.05,0.47 -1.05,1.05v0.5c0,-0.58 0.47,-1.05 1.05,-1.05h1.4c0.58,0 1.05,0.47 1.05,1.05v-0.5c0,-0.58 -0.47,-1.05 -1.05,-1.05zM42.55,63c-0.58,0 -1.05,0.47 -1.05,1.05v0.5c0,-0.58 0.47,-1.05 1.05,-1.05h2.45v-0.5zM48.5,63v0.5h2.45c0.58,0 1.05,0.47 1.05,1.05v-0.5c0,-0.58 -0.47,-1.05 -1.05,-1.05z"
android:strokeAlpha="0.2"
android:fillColor="#fff"
android:fillAlpha="0.2"/>
<path
android:fillColor="#FF000000"
android:pathData="m41.5,64.95v0.5c0,0.58 0.47,1.05 1.05,1.05h2.45v-0.5h-2.45c-0.58,0 -1.05,-0.47 -1.05,-1.05zM52,64.95c0,0.58 -0.47,1.05 -1.05,1.05h-2.45v0.5h2.45c0.58,0 1.05,-0.47 1.05,-1.05zM45,68.45v0.5c0,0.58 0.47,1.05 1.05,1.05h1.4c0.58,0 1.05,-0.47 1.05,-1.05v-0.5c0,0.58 -0.47,1.05 -1.05,1.05h-1.4c-0.58,0 -1.05,-0.47 -1.05,-1.05z"
android:strokeAlpha="0.2"
android:fillAlpha="0.2"/>
<path
android:fillAlpha="0.2"
android:pathData="M-20,30
A50,50 0 1,1 80,30
A50,50 0 1,1 -20,30 Z">
<aapt:attr name="android:fillColor">
<gradient
android:gradientRadius="50"
android:centerX="30"
android:centerY="30"
android:type="radial">
<item
android:color="#FFFFFFFF"
android:offset="0.0"/>
<item
android:color="#00FFFFFF"
android:offset="1.0"/>
</gradient>
</aapt:attr>
</path>
</vector>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_launcher_foreground"/>
</selector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:tint="?attr/colorControlNormal"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V12H19V19Z" />
</vector>

View File

@ -75,6 +75,23 @@
app:icon="@drawable/ic_save_remove_24dp"
app:iconPadding="32dp" />
<Button
android:id="@+id/buttonAddShortcut"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:insetTop="0dp"
android:insetBottom="0dp"
android:paddingStart="32dp"
android:paddingEnd="32dp"
android:text="@string/add_shortcut"
android:textAlignment="viewStart"
android:textAllCaps="false"
android:textAppearance="?attr/textAppearanceBodyLarge"
android:textColor="@color/material_on_surface_emphasis_high_type"
app:icon="@drawable/ic_launch_24dp"
app:iconPadding="32dp" />
<Button
android:id="@+id/buttonEditCheats"
style="@style/Widget.Material3.Button.TextButton"

View File

@ -1,6 +1,7 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">GBCC</string>
<string name="application_id">com.philj56.gbcc</string>
<string name="launch_game_intent">com.philj56.gbcc.launch_game</string>
<!-- MainActivity -->
<string name="base_directory_name">Files</string>
@ -30,6 +31,7 @@
<string name="delete_config_confirmation">Are you sure you wish to delete your config for this game?</string>
<string name="edit_config">Edit game config</string>
<string name="edit_cheats">Edit cheats</string>
<string name="add_shortcut">Add shortcut</string>
<string name="move">Move</string>
<string name="overwrite_confirmation">Select save files to overwrite:</string>
<string name="error_zip_title">Error parsing zip file: <xliff:g>%1$s</xliff:g></string>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="108" height="108" version="1.1" viewBox="0 0 108 108" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<radialGradient id="radialGradient13889" cx="18" cy="395.3" r="42" gradientTransform="matrix(1.548 0 0 1.571 13.14 -587.1)" gradientUnits="userSpaceOnUse">
<stop stop-color="#fff" stop-opacity=".1" offset="0"/>
<stop stop-color="#fff" stop-opacity="0" offset="1"/>
</radialGradient>
<filter id="filter921" x="-.12" y="-.08" width="1.24" height="1.16" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="1.4999999"/>
</filter>
</defs>
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
</cc:Work>
</rdf:RDF>
</metadata>
<g transform="translate(0 -377.3)">
<path d="m41.83 410.8c-0.4617 0-0.8333 0.386-0.8333 0.8654v41.54h0.0032a1.667 1.731 0 0 0 1.094 1.626s3.07 0.9702 13.9 0.9702 13.9-0.9702 13.9-0.9702a1.667 1.731 0 0 0 1.094-1.626h0.0032v-41.54c0-0.4794-0.3717-0.8654-0.8333-0.8654z" filter="url(#filter921)" opacity=".2"/>
<path d="m39.88 408.8c-0.4888 0-0.8824 0.3956-0.8824 0.8871v43.47c0 0.4914 0.3935 0.8871 0.8824 0.8871h24.71c2.444 0 4.412-1.978 4.412-4.435v-39.92c0-0.4914-0.3935-0.8871-0.8824-0.8871z" fill="#c6c0bd" style="paint-order:stroke fill markers"/>
<path d="m69 448.7c0 2.455-1.968 4.432-4.412 4.432h-24.71c-0.4888 0-0.8824-0.3953-0.8824-0.8864v0.8864c0 0.4911 0.3935 0.8864 0.8824 0.8864h24.71c2.444 0 4.412-1.977 4.412-4.432z" opacity=".2" style="paint-order:stroke fill markers"/>
<path transform="translate(0 377.3)" d="m39.83 31.5c-0.4617 0-0.834 0.3858-0.834 0.8652v1c0-0.4794 0.3723-0.8652 0.834-0.8652h28.33c0.4617 0 0.834 0.3858 0.834 0.8652v-1c0-0.4794-0.3723-0.8652-0.834-0.8652h-28.33z" fill="#fff" opacity=".2"/>
<g transform="translate(-6.5 4)">
<circle cx="63.6" cy="440.7" r="2.6" fill="#9c2457"/>
<path transform="translate(0 377.3)" d="m63.6 60.8a2.6 2.6 0 0 0-2.6 2.6 2.6 2.6 0 0 0 0.01367 0.2402 2.6 2.6 0 0 1 2.586-2.34 2.6 2.6 0 0 1 2.588 2.359 2.6 2.6 0 0 0 0.01172-0.2598 2.6 2.6 0 0 0-2.6-2.6z" fill="#fbfbfb" opacity=".2"/>
<path transform="translate(0 377.3)" d="m61.01 63.15a2.6 2.6 0 0 0-0.01367 0.2539 2.6 2.6 0 0 0 2.6 2.6 2.6 2.6 0 0 0 2.6-2.6 2.6 2.6 0 0 0-0.01172-0.2363 2.6 2.6 0 0 1-2.588 2.336 2.6 2.6 0 0 1-2.586-2.354z" opacity=".2"/>
</g>
<rect x="40.75" y="410.8" width="26.5" height="24" ry=".8889" fill="#8b888e"/>
<rect x="43.75" y="413.5" width="20.5" height="18.5" ry=".881" fill="#8ac52c"/>
<circle cx="63.6" cy="440.7" r="2.6" fill="#9c2457"/>
<path transform="translate(0 377.3)" d="m63.6 60.8a2.6 2.6 0 0 0-2.6 2.6 2.6 2.6 0 0 0 0.01367 0.2402 2.6 2.6 0 0 1 2.586-2.34 2.6 2.6 0 0 1 2.588 2.359 2.6 2.6 0 0 0 0.01172-0.2598 2.6 2.6 0 0 0-2.6-2.6z" fill="#fbfbfb" opacity=".2"/>
<path transform="translate(0 377.3)" d="m61.01 63.15a2.6 2.6 0 0 0-0.01367 0.2539 2.6 2.6 0 0 0 2.6 2.6 2.6 2.6 0 0 0 2.6-2.6 2.6 2.6 0 0 0-0.01172-0.2363 2.6 2.6 0 0 1-2.588 2.336 2.6 2.6 0 0 1-2.586-2.354z" opacity=".2"/>
<path d="m46.05 436.8c-0.5817 0-1.05 0.4683-1.05 1.05v2.451h-2.451c-0.5817 0-1.05 0.4683-1.05 1.05v1.399c0 0.5817 0.4683 1.05 1.05 1.05h2.451v2.451c0 0.5817 0.4683 1.05 1.05 1.05h1.399c0.5817 0 1.05-0.4683 1.05-1.05v-2.451h2.451c0.5817 0 1.05-0.4683 1.05-1.05v-1.399c0-0.5817-0.4683-1.05-1.05-1.05h-2.451v-2.451c0-0.5817-0.4683-1.05-1.05-1.05z" fill="#373737"/>
<path transform="translate(0 377.3)" d="m46.05 59.5c-0.5817 0-1.051 0.4691-1.051 1.051v0.5c0-0.5817 0.4691-1.051 1.051-1.051h1.398c0.5817 0 1.051 0.4691 1.051 1.051v-0.5c0-0.5817-0.4691-1.051-1.051-1.051zm-3.5 3.5c-0.5817 0-1.051 0.4691-1.051 1.051v0.5c0-0.5817 0.4691-1.051 1.051-1.051h2.449v-0.5zm5.949 0v0.5h2.449c0.5817 0 1.051 0.4691 1.051 1.051v-0.5c0-0.5817-0.4691-1.051-1.051-1.051z" fill="#fff" opacity=".2"/>
<path transform="translate(0 377.3)" d="m41.5 64.95v0.5c0 0.5817 0.4691 1.051 1.051 1.051h2.449v-0.5h-2.449c-0.5817 0-1.051-0.4691-1.051-1.051zm10.5 0c0 0.5817-0.4691 1.051-1.051 1.051h-2.449v0.5h2.449c0.5817 0 1.051-0.4691 1.051-1.051zm-7 3.5v0.5c0 0.5817 0.4691 1.051 1.051 1.051h1.398c0.5817 0 1.051-0.4691 1.051-1.051v-0.5c0 0.5817-0.4691 1.051-1.051 1.051h-1.398c-0.5817 0-1.051-0.4691-1.051-1.051z" opacity=".2"/>
</g>
<g>
<ellipse cx="41" cy="34" rx="65" ry="66" fill="url(#radialGradient13889)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB