diff --git a/app/src/main/java/com/hiddenramblings/tagmo/BrowserActivity.kt b/app/src/main/java/com/hiddenramblings/tagmo/BrowserActivity.kt index 0d4c9f979..be1c4c02a 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/BrowserActivity.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/BrowserActivity.kt @@ -1878,16 +1878,20 @@ class BrowserActivity : AppCompatActivity(), BrowserSettingsListener, val binFile = resources.getStringArray(R.array.mimetype_bin) if (binFile.contains(intent.type)) { val length = getUriFIleSize(uri) - if (length >= NfcByte.TAG_DATA_SIZE) { - val data = TagReader.readTagDocument(uri) - updateAmiiboView(data, AmiiboFile( - uri.path?.let { File(it) }, Amiibo.dataToId(data), data - )) - } else if (getUriFIleSize(uri) > NfcByte.KEY_FILE_SIZE) { - onLoadSettingsFragment() - fragmentSettings?.validateKeys(intent.parcelable(Intent.EXTRA_STREAM) as Uri?) - } else { - Toasty(this@BrowserActivity).Short(R.string.error_uri_size) + when { + length >= NfcByte.TAG_DATA_SIZE -> { + val data = TagReader.readTagDocument(uri) + updateAmiiboView(data, AmiiboFile( + uri.path?.let { File(it) }, Amiibo.dataToId(data), data + )) + } + length >= NfcByte.KEY_FILE_SIZE -> { + onLoadSettingsFragment() + fragmentSettings?.validateKeys(intent.parcelable(Intent.EXTRA_STREAM) as Uri?) + } + else -> { + Toasty(this@BrowserActivity).Short(R.string.error_uri_size) + } } } else if (intent.type == getString(R.string.mimetype_zip)) { decompressArchive(uri) diff --git a/app/src/main/java/com/hiddenramblings/tagmo/bluetooth/GattService.kt b/app/src/main/java/com/hiddenramblings/tagmo/bluetooth/GattService.kt index 1d4c884ee..46f148f3c 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/bluetooth/GattService.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/bluetooth/GattService.kt @@ -578,7 +578,9 @@ class GattService : Service() { if (emptyAdapater || address == null) return false // Previously connected device. Try to reconnect. - if (address == mBluetoothDeviceAddress) mBluetoothGatt?.let { return it.connect() } + mBluetoothGatt?.let { + if (address == mBluetoothDeviceAddress && it.connect()) return true + } val device = mBluetoothAdapter?.getRemoteDevice(address) ?: return false // We want to directly connect to the device, so we are setting the autoConnect // parameter to false. diff --git a/app/src/main/java/com/hiddenramblings/tagmo/eightbit/util/UnZip.kt b/app/src/main/java/com/hiddenramblings/tagmo/eightbit/util/UnZip.kt new file mode 100644 index 000000000..49c90093b --- /dev/null +++ b/app/src/main/java/com/hiddenramblings/tagmo/eightbit/util/UnZip.kt @@ -0,0 +1,107 @@ +package com.hiddenramblings.tagmo.eightbit.util + +import android.content.Context +import android.os.Build +import android.os.Handler +import android.os.Looper +import androidx.annotation.RequiresApi +import com.hiddenramblings.tagmo.R +import com.hiddenramblings.tagmo.eightbit.io.Debug +import com.hiddenramblings.tagmo.eightbit.os.Version +import com.hiddenramblings.tagmo.eightbit.widget.ProgressAlert +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Paths +import java.util.zip.ZipFile + +class UnZip(var context: Context, var archive: File, var outputDir: File) : Runnable { + private val zipHandler = Handler(Looper.getMainLooper()) + private var dialog: ProgressAlert? = null + + @RequiresApi(Build.VERSION_CODES.KITKAT) + private fun decompress() { + ZipFile(archive).use { zipFile -> + val entries = zipFile.entries() + while (entries.hasMoreElements()) { + // get the zip entry + val finalEntry = entries.nextElement() + zipHandler.post { + dialog?.setMessage(context.getString(R.string.unzip_item, finalEntry.name)) + } + if (finalEntry.isDirectory) { + val dir = File( + outputDir, finalEntry.name.replace(File.separator, "") + ) + if (!dir.exists() && !dir.mkdirs()) + throw RuntimeException(context.getString(R.string.mkdir_failed, dir.name)) + } else { + zipFile.getInputStream(finalEntry).use { zipInStream -> + if (Version.isOreo) { + Files.copy( + zipInStream, + Paths.get(outputDir.absolutePath, finalEntry.name) + ) + } else { + FileOutputStream(File(outputDir, finalEntry.name)).use { fileOut -> + val buffer = ByteArray(8192) + var len: Int + while (zipInStream.read(buffer).also { len = it } != -1) + fileOut.write(buffer, 0, len) + } + } + } + } + } + } + } + @Throws(IOException::class) + private fun decompressLegacy() { + val zipFile = ZipFile(archive) + val entries = zipFile.entries() + while (entries.hasMoreElements()) { + // get the zip entry + val finalEntry = entries.nextElement() + zipHandler.post { + dialog?.setMessage(context.getString(R.string.unzip_item, finalEntry.name)) + } + if (finalEntry.isDirectory) { + val dir = File( + outputDir, finalEntry.name.replace(File.separator, "") + ) + if (!dir.exists() && !dir.mkdirs()) + throw RuntimeException(context.getString(R.string.mkdir_failed, dir.name)) + } else { + val zipInStream = zipFile.getInputStream(finalEntry) + if (Version.isOreo) { + Files.copy(zipInStream, Paths.get(outputDir.absolutePath, finalEntry.name)) + } else { + val fileOut = FileOutputStream(File(outputDir, finalEntry.name)) + val buffer = ByteArray(8192) + var len: Int + while (zipInStream.read(buffer).also { len = it } != -1) + fileOut.write(buffer, 0, len) + fileOut.close() + } + zipInStream.close() + } + } + zipFile.close() + } + + override fun run() { + zipHandler.post { dialog = ProgressAlert.show(context, "") } + try { + if (Version.isKitKat) + decompress() + else + decompressLegacy() + } catch (e: IOException) { + Debug.warn(e) + } finally { + zipHandler.post { dialog?.dismiss() } + archive.delete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/hiddenramblings/tagmo/fragment/WebsiteFragment.kt b/app/src/main/java/com/hiddenramblings/tagmo/fragment/WebsiteFragment.kt index 47cd47371..4d3ba4d28 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/fragment/WebsiteFragment.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/fragment/WebsiteFragment.kt @@ -10,6 +10,7 @@ import android.view.View import android.view.ViewGroup import android.webkit.* import android.widget.EditText +import androidx.annotation.RequiresApi import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment import androidx.webkit.* @@ -21,6 +22,7 @@ import com.hiddenramblings.tagmo.amiibo.AmiiboManager.getAmiiboManager import com.hiddenramblings.tagmo.eightbit.io.Debug import com.hiddenramblings.tagmo.eightbit.os.Storage import com.hiddenramblings.tagmo.eightbit.os.Version +import com.hiddenramblings.tagmo.eightbit.util.UnZip import com.hiddenramblings.tagmo.eightbit.widget.ProgressAlert import com.hiddenramblings.tagmo.nfctech.TagArray import com.hiddenramblings.tagmo.security.SecurityHandler @@ -38,7 +40,6 @@ import java.util.zip.ZipFile class WebsiteFragment : Fragment() { private val webHandler = Handler(Looper.getMainLooper()) private var mWebView: WebView? = null - private var dialog: ProgressAlert? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -165,58 +166,6 @@ class WebsiteFragment : Fragment() { } } - private inner class UnZip(var archive: File, var outputDir: File) : Runnable { - @Throws(IOException::class) - private fun decompress() { - val zipFile = ZipFile(archive) - val entries = zipFile.entries() - while (entries.hasMoreElements()) { - // get the zip entry - val finalEntry = entries.nextElement() - webHandler.post { - dialog?.setMessage(getString(R.string.unzip_item, finalEntry.name)) - } - if (finalEntry.isDirectory) { - val dir = File( - outputDir, finalEntry.name.replace(File.separator, "") - ) - if (!dir.exists() && !dir.mkdirs()) - throw RuntimeException(getString(R.string.mkdir_failed, dir.name)) - } else { - val zipInStream = zipFile.getInputStream(finalEntry) - if (Version.isOreo) { - Files.copy(zipInStream, Paths.get(outputDir.absolutePath, finalEntry.name)) - } else { - val fileOut = FileOutputStream( - File(outputDir, finalEntry.name) - ) - val buffer = ByteArray(8192) - var len: Int - while (zipInStream.read(buffer).also { len = it } != -1) fileOut.write( - buffer, - 0, - len - ) - fileOut.close() - } - zipInStream.close() - } - } - zipFile.close() - } - - override fun run() { - try { - decompress() - } catch (e: IOException) { - Debug.warn(e) - } finally { - dialog?.dismiss() - archive.delete() - } - } - } - private fun saveBinFile(tagData: ByteArray, name: String) { try { val filePath = File( @@ -295,9 +244,10 @@ class WebsiteFragment : Fragment() { ), 0)) it.flush() } - webHandler.post { dialog = ProgressAlert.show(requireContext(), "") } Thread(UnZip( - filePath, Storage.getDownloadDir("TagMo", "Downloads") + requireContext(), + filePath, + Storage.getDownloadDir("TagMo", "Downloads") )).start() } else { resources.getStringArray(R.array.mimetype_bin).find { binType -> diff --git a/app/src/main/res/raw/amiibo.json b/app/src/main/res/raw/amiibo.json index fba833e9d..64a4816f6 100644 --- a/app/src/main/res/raw/amiibo.json +++ b/app/src/main/res/raw/amiibo.json @@ -7462,7 +7462,7 @@ } }, "0x3802000103951702": { - "name": "Daijobu", + "name": "Yabe", "release": { "au": null, "eu": null, @@ -7480,7 +7480,7 @@ } }, "0x3804000103971702": { - "name": "Yabe", + "name": "Ganda", "release": { "au": null, "eu": null, @@ -7489,7 +7489,7 @@ } }, "0x3805000103981702": { - "name": "Ganda", + "name": "Daijobu", "release": { "au": null, "eu": null, @@ -8237,10 +8237,10 @@ "0x37c1": "Richter", "0x3800": "Pawapuro", "0x3801": "Ikari", - "0x3802": "Daijobu", + "0x3802": "Yabe", "0x3803": "Hayakawa", - "0x3804": "Yabe", - "0x3805": "Ganda", + "0x3804": "Ganda", + "0x3805": "Daijobu", "0x3840": "Yuga Ohdo", "0x3841": "Tatsuhisa \u201cLuke\u201d Kamij\u014d", "0x3842": "Gakuto S\u014dgetsu", diff --git a/app/src/main/res/raw/games_info.json b/app/src/main/res/raw/games_info.json index 6a20f4241..d008c6494 100644 --- a/app/src/main/res/raw/games_info.json +++ b/app/src/main/res/raw/games_info.json @@ -3673,7 +3673,7 @@ ], "amiiboUsage": [ { - "Usage": "Receive a character-based costume", + "Usage": "Gain temporary invincibility", "write": false } ] @@ -3685,7 +3685,7 @@ ], "amiiboUsage": [ { - "Usage": "Gain temporary invincibility", + "Usage": "Receive a character-based costume", "write": false } ] @@ -3820,6 +3820,18 @@ } ] }, + { + "gameName": "Super Smash Bros. Ultimate", + "gameID": [ + "01006A800016E000" + ], + "amiiboUsage": [ + { + "Usage": "Battle and train up a computer-controlled Figure Player of the character", + "write": true + } + ] + }, { "gameName": "Yoshi's Crafted World", "gameID": [ @@ -17213,6 +17225,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Bring Epona into the game as a rideable horse", "write": false @@ -17610,6 +17626,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -18003,6 +18023,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -18404,6 +18428,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Bring Epona into the game as a rideable horse", "write": false @@ -18801,6 +18829,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -19194,6 +19226,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -19587,6 +19623,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -19980,6 +20020,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -20361,6 +20405,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -20766,6 +20814,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -21159,6 +21211,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -21550,6 +21606,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -21953,6 +22013,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -22293,6 +22357,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -22645,6 +22713,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -22997,6 +23069,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -23337,6 +23413,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -23701,6 +23781,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -24014,6 +24098,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -24247,6 +24335,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -24381,6 +24473,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -24515,6 +24611,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -24649,6 +24749,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -24783,6 +24887,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -24932,6 +25040,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -25081,6 +25193,10 @@ "0100F2C0115B6000" ], "amiiboUsage": [ + { + "Usage": "Unlock an amiibo-exclusive character-specific paraglider fabric", + "write": false + }, { "Usage": "Receive materials and a weapon or rare item", "write": false @@ -35937,18 +36053,6 @@ "write": false } ] - }, - { - "gameName": "Style Savvy: Styling Star", - "gameID": [ - "00040000001C2500" - ], - "amiiboUsage": [ - { - "Usage": "Unlock an Animal Crossing pattern", - "write": false - } - ] } ], "gamesWiiU": [ @@ -49184,6 +49288,21 @@ }, "0x0286000103130502": { "games3DS": [ + { + "gameName": "Animal Crossing: New Leaf", + "gameID": [ + "0004000000086400", + "0004000000086300", + "0004000000198F00", + "0004000000198E00" + ], + "amiiboUsage": [ + { + "Usage": "Invite the character to visit your RV campsite, give you an item, and/or move to your town", + "write": false + } + ] + }, { "gameName": "Kirby: Planet Robobot", "gameID": [ @@ -102490,6 +102609,66 @@ } ] }, + "0x22410000041e0002": { + "games3DS": [], + "gamesWiiU": [], + "gamesSwitch": [ + { + "gameName": "Super Smash Bros. Ultimate", + "gameID": [ + "01006A800016E000" + ], + "amiiboUsage": [ + { + "Usage": "Battle and train up a computer-controlled Figure Player of the character", + "write": true + } + ] + }, + { + "gameName": "Xenoblade Chronicles 3", + "gameID": [ + "010074F013262000" + ], + "amiiboUsage": [ + { + "Usage": "Unlock a character-specific weapon skin for characters using the Swordfighter Class", + "write": false + } + ] + } + ] + }, + "0x22420000041f0002": { + "games3DS": [], + "gamesWiiU": [], + "gamesSwitch": [ + { + "gameName": "Super Smash Bros. Ultimate", + "gameID": [ + "01006A800016E000" + ], + "amiiboUsage": [ + { + "Usage": "Battle and train up a computer-controlled Figure Player of the character", + "write": true + } + ] + }, + { + "gameName": "Xenoblade Chronicles 3", + "gameID": [ + "010074F013262000" + ], + "amiiboUsage": [ + { + "Usage": "Unlock a character-specific weapon skin for characters using the Swordfighter Class", + "write": false + } + ] + } + ] + }, "0x22800000002c0002": { "games3DS": [ { @@ -104778,6 +104957,18 @@ } ] }, + { + "gameName": "Shovel Knight Dig", + "gameID": [ + "0100B62017E68000" + ], + "amiiboUsage": [ + { + "Usage": "Summon a fairy friend", + "write": false + } + ] + }, { "gameName": "Shovel Knight Pocket Dungeon", "gameID": [ @@ -104936,6 +105127,18 @@ } ] }, + { + "gameName": "Shovel Knight Dig", + "gameID": [ + "0100B62017E68000" + ], + "amiiboUsage": [ + { + "Usage": "Summon a fairy friend", + "write": false + } + ] + }, { "gameName": "Shovel Knight Pocket Dungeon", "gameID": [ @@ -105058,6 +105261,18 @@ } ] }, + { + "gameName": "Shovel Knight Dig", + "gameID": [ + "0100B62017E68000" + ], + "amiiboUsage": [ + { + "Usage": "Summon a fairy friend", + "write": false + } + ] + }, { "gameName": "Shovel Knight Pocket Dungeon", "gameID": [ @@ -105192,6 +105407,18 @@ } ] }, + { + "gameName": "Shovel Knight Dig", + "gameID": [ + "0100B62017E68000" + ], + "amiiboUsage": [ + { + "Usage": "Summon a fairy friend", + "write": false + } + ] + }, { "gameName": "Shovel Knight Pocket Dungeon", "gameID": [ @@ -105326,6 +105553,18 @@ } ] }, + { + "gameName": "Shovel Knight Dig", + "gameID": [ + "0100B62017E68000" + ], + "amiiboUsage": [ + { + "Usage": "Summon a fairy friend", + "write": false + } + ] + }, { "gameName": "Shovel Knight Pocket Dungeon", "gameID": [ @@ -105907,16 +106146,6 @@ ] } ] - }, - "0x22410000041e0002": { - "games3DS": [], - "gamesWiiU": [], - "gamesSwitch": [] - }, - "0x22420000041f0002": { - "games3DS": [], - "gamesWiiU": [], - "gamesSwitch": [] } }, "0x0100000004190902": {