Compare commits

...

4 Commits

Author SHA1 Message Date
81bfec5ac5
Merge pull request #55 from b13st/fix/vitalwear-hce-transfer
Fix VitalWear HCE transfer in both directions
2026-06-23 20:30:46 +00:00
8ec98b9d39
Merge pull request #54 from shiki8826/main
Thank you very much
2026-06-23 20:30:04 +00:00
b13st
e549fb4469 Fix VitalWear HCE transfer in both directions
- Detect ISO-DEP tags (VitalWear watch) vs NFC-A (physical bracelets)
- Watch->Phone: use VitalWearHceReaderClient + VitalWearCharacterImporter
- Phone->Watch: use VitalWearHceReaderClient + VitalWearCharacterExporter
- Add AppDatabase to ScanScreenControllerImpl for HCE import/export
- Extract buildCharacterProto() from VitalWearCharacterExporter
- Add JitPack repository to settings.gradle.kts
2026-06-23 13:44:26 +02:00
shiki8826
8d62437aae 日本語翻訳の修正及び追加項目の翻訳 2026-06-19 20:46:23 +09:00
5 changed files with 239 additions and 135 deletions

View File

@ -49,7 +49,8 @@ class MainActivity : ComponentActivity() {
application.container.dataStoreSecretsRepository.secretsFlow, application.container.dataStoreSecretsRepository.secretsFlow,
this, this,
this::registerActivityLifecycleListener, this::registerActivityLifecycleListener,
this::unregisterActivityLifecycleListener this::unregisterActivityLifecycleListener,
application.container.db,
) )
val settingsScreenController = SettingsScreenControllerImpl(this) val settingsScreenController = SettingsScreenControllerImpl(this)
val itemsScreenController = ItemsScreenControllerImpl(this) val itemsScreenController = ItemsScreenControllerImpl(this)

View File

@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.screens.scanScreen
import android.content.Intent import android.content.Intent
import android.nfc.NfcAdapter import android.nfc.NfcAdapter
import android.nfc.Tag import android.nfc.Tag
import android.nfc.tech.IsoDep
import android.nfc.tech.NfcA import android.nfc.tech.NfcA
import android.os.Bundle import android.os.Bundle
import android.provider.Settings import android.provider.Settings
@ -15,12 +16,16 @@ import com.github.cfogrady.vbnfc.be.BENfcCharacter
import com.github.cfogrady.vbnfc.data.NfcCharacter import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.cfogrady.vbnfc.vb.VBNfcCharacter import com.github.cfogrady.vbnfc.vb.VBNfcCharacter
import com.github.nacabaro.vbhelper.ActivityLifecycleListener import com.github.nacabaro.vbhelper.ActivityLifecycleListener
import com.github.nacabaro.vbhelper.database.AppDatabase
import com.github.nacabaro.vbhelper.domain.card.Card import com.github.nacabaro.vbhelper.domain.card.Card
import com.github.nacabaro.vbhelper.screens.scanScreen.converters.FromNfcConverter import com.github.nacabaro.vbhelper.screens.scanScreen.converters.FromNfcConverter
import com.github.nacabaro.vbhelper.screens.scanScreen.converters.ToNfcConverter import com.github.nacabaro.vbhelper.screens.scanScreen.converters.ToNfcConverter
import com.github.nacabaro.vbhelper.source.VitalWearCharacterExporter
import com.github.nacabaro.vbhelper.source.VitalWearCharacterImporter
import com.github.nacabaro.vbhelper.source.getCryptographicTransformerMap import com.github.nacabaro.vbhelper.source.getCryptographicTransformerMap
import com.github.nacabaro.vbhelper.source.isMissingSecrets import com.github.nacabaro.vbhelper.source.isMissingSecrets
import com.github.nacabaro.vbhelper.source.proto.Secrets import com.github.nacabaro.vbhelper.source.proto.Secrets
import com.github.nacabaro.vbhelper.transfer.hce.VitalWearHceReaderClient
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
@ -32,8 +37,10 @@ class ScanScreenControllerImpl(
private val componentActivity: ComponentActivity, private val componentActivity: ComponentActivity,
private val registerActivityLifecycleListener: (String, ActivityLifecycleListener)->Unit, private val registerActivityLifecycleListener: (String, ActivityLifecycleListener)->Unit,
private val unregisterActivityLifecycleListener: (String)->Unit, private val unregisterActivityLifecycleListener: (String)->Unit,
private val database: AppDatabase,
): ScanScreenController { ): ScanScreenController {
private var lastScannedCharacter: NfcCharacter? = null private var lastScannedCharacter: NfcCharacter? = null
private var pendingExportCharacterId: Long? = null
private val nfcAdapter: NfcAdapter private val nfcAdapter: NfcAdapter
init { init {
@ -46,24 +53,46 @@ class ScanScreenControllerImpl(
} }
override fun onClickRead(secrets: Secrets, onComplete: ()->Unit, onMultipleCards: (List<Card>) -> Unit) { override fun onClickRead(secrets: Secrets, onComplete: ()->Unit, onMultipleCards: (List<Card>) -> Unit) {
handleTag(secrets) { tagCommunicator -> handleTag(
try { secrets,
val character = tagCommunicator.receiveCharacter() handlerFunc = { tagCommunicator ->
val resultMessage = characterFromNfc(character) { cards, nfcCharacter -> try {
lastScannedCharacter = nfcCharacter val character = tagCommunicator.receiveCharacter()
onMultipleCards(cards) val resultMessage = characterFromNfc(character) { cards, nfcCharacter ->
lastScannedCharacter = nfcCharacter
onMultipleCards(cards)
}
onComplete.invoke()
resultMessage
} catch (e: Exception) {
Log.e("NFC_READ", "Error reading character from NFC", e)
componentActivity.runOnUiThread {
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_error_generic) + ": " + (e.message ?: e.javaClass.simpleName), Toast.LENGTH_LONG).show()
}
onComplete.invoke()
componentActivity.getString(R.string.scan_error_generic)
} }
onComplete.invoke() },
resultMessage hceHandler = { isoDep ->
} catch (e: Exception) { try {
Log.e("NFC_READ", "Error reading character from NFC", e) val client = VitalWearHceReaderClient(isoDep)
componentActivity.runOnUiThread { val character = client.receiveCharacterFromWatch()
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_error_generic) + ": " + (e.message ?: e.javaClass.simpleName), Toast.LENGTH_LONG).show() val importer = VitalWearCharacterImporter(database)
val result = importer.importCharacter(character)
Log.i("NFC_READ", "VitalWear HCE import: ${result.message}")
componentActivity.runOnUiThread {
Toast.makeText(componentActivity, result.message, Toast.LENGTH_SHORT).show()
}
} catch (e: Exception) {
Log.e("NFC_READ", "Error reading character from VitalWear HCE", e)
componentActivity.runOnUiThread {
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_error_generic) + ": " + (e.message ?: e.javaClass.simpleName), Toast.LENGTH_LONG).show()
}
} finally {
onComplete()
} }
onComplete.invoke()
componentActivity.getString(R.string.scan_error_generic)
} }
} )
} }
override fun cancelRead() { override fun cancelRead() {
@ -83,35 +112,53 @@ class ScanScreenControllerImpl(
unregisterActivityLifecycleListener.invoke(key) unregisterActivityLifecycleListener.invoke(key)
} }
// EXTRACTED DIRECTLY FROM EXAMPLE APP private fun handleTag(
private fun handleTag(secrets: Secrets, handlerFunc: (TagCommunicator)->String) { secrets: Secrets,
handlerFunc: (TagCommunicator) -> String,
hceHandler: ((IsoDep) -> Unit)? = null,
) {
if (!nfcAdapter.isEnabled) { if (!nfcAdapter.isEnabled) {
showWirelessSettings() showWirelessSettings()
} else { } else {
val options = Bundle() val options = Bundle()
// Work around for some broken Nfc firmware implementations that poll the card too fast // Work around for some broken Nfc firmware implementations that poll the card too fast
options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250) options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250)
nfcAdapter.enableReaderMode(componentActivity, buildOnReadTag(secrets, handlerFunc), NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, nfcAdapter.enableReaderMode(
componentActivity,
buildOnReadTag(secrets, handlerFunc, hceHandler),
NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK,
options options
) )
} }
} }
// EXTRACTED DIRECTLY FROM EXAMPLE APP private fun buildOnReadTag(
private fun buildOnReadTag(secrets: Secrets, handlerFunc: (TagCommunicator)->String): (Tag)->Unit { secrets: Secrets,
return { tag-> handlerFunc: (TagCommunicator) -> String,
val nfcData = NfcA.get(tag) hceHandler: ((IsoDep) -> Unit)? = null,
if (nfcData == null) { ): (Tag) -> Unit {
componentActivity.runOnUiThread { return { tag ->
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_tag_not_vb), Toast.LENGTH_SHORT).show() val isoDep = IsoDep.get(tag)
} if (isoDep != null && hceHandler != null) {
} // VitalWear watch via HCE / ISO-DEP
nfcData.connect() isoDep.connect()
nfcData.use { isoDep.use { hceHandler(isoDep) }
val tagCommunicator = TagCommunicator.getInstance(nfcData, secrets.getCryptographicTransformerMap()) } else {
val successText = handlerFunc(tagCommunicator) // Physical Vital Bracelet via raw NFC-A
componentActivity.runOnUiThread { val nfcData = NfcA.get(tag)
Toast.makeText(componentActivity, successText, Toast.LENGTH_SHORT).show() if (nfcData == null) {
componentActivity.runOnUiThread {
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_tag_not_vb), Toast.LENGTH_SHORT).show()
}
} else {
nfcData.connect()
nfcData.use {
val tagCommunicator = TagCommunicator.getInstance(nfcData, secrets.getCryptographicTransformerMap())
val successText = handlerFunc(tagCommunicator)
componentActivity.runOnUiThread {
Toast.makeText(componentActivity, successText, Toast.LENGTH_SHORT).show()
}
}
} }
} }
} }
@ -132,24 +179,29 @@ class ScanScreenControllerImpl(
nfcCharacter: NfcCharacter, nfcCharacter: NfcCharacter,
onComplete: () -> Unit onComplete: () -> Unit
) { ) {
handleTag(secrets) { tagCommunicator -> handleTag(
try { secrets,
if (nfcCharacter is VBNfcCharacter) { handlerFunc = { tagCommunicator ->
Log.d("SendCharacter", "VBNfcCharacter") try {
val castNfcCharacter: VBNfcCharacter = nfcCharacter if (nfcCharacter is VBNfcCharacter) {
tagCommunicator.sendCharacter(castNfcCharacter) Log.d("SendCharacter", "VBNfcCharacter")
} else if (nfcCharacter is BENfcCharacter) { tagCommunicator.sendCharacter(nfcCharacter)
Log.d("SendCharacter", "BENfcCharacter") } else if (nfcCharacter is BENfcCharacter) {
val castNfcCharacter: BENfcCharacter = nfcCharacter Log.d("SendCharacter", "BENfcCharacter")
tagCommunicator.sendCharacter(castNfcCharacter) tagCommunicator.sendCharacter(nfcCharacter)
}
onComplete.invoke()
componentActivity.getString(R.string.scan_sent_character_success)
} catch (e: Throwable) {
Log.e("TAG", e.stackTraceToString())
componentActivity.getString(R.string.scan_error_generic)
} }
onComplete.invoke() },
componentActivity.getString(R.string.scan_sent_character_success) hceHandler = { _ ->
} catch (e: Throwable) { // Character was already sent in onClickCheckCard's HCE handler.
Log.e("TAG", e.stackTraceToString()) onComplete()
componentActivity.getString(R.string.scan_error_generic)
} }
} )
} }
override fun onClickCheckCard( override fun onClickCheckCard(
@ -157,11 +209,42 @@ class ScanScreenControllerImpl(
nfcCharacter: NfcCharacter, nfcCharacter: NfcCharacter,
onComplete: () -> Unit onComplete: () -> Unit
) { ) {
handleTag(secrets) { tagCommunicator -> handleTag(
tagCommunicator.prepareDIMForCharacter(nfcCharacter.dimId) secrets,
onComplete.invoke() handlerFunc = { tagCommunicator ->
componentActivity.getString(R.string.scan_sent_dim_success) tagCommunicator.prepareDIMForCharacter(nfcCharacter.dimId)
} onComplete.invoke()
componentActivity.getString(R.string.scan_sent_dim_success)
},
hceHandler = { isoDep ->
// VitalWear watch: send the character proto directly via HCE.
val characterId = pendingExportCharacterId
if (characterId == null) {
Log.e("NFC_WRITE", "No pending character to send to VitalWear")
componentActivity.runOnUiThread {
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_error_generic), Toast.LENGTH_SHORT).show()
}
onComplete()
return@handleTag
}
try {
val proto = VitalWearCharacterExporter(componentActivity, database).buildCharacterProto(characterId)
val client = VitalWearHceReaderClient(isoDep)
client.sendCharacterToWatch(proto)
Log.i("NFC_WRITE", "Character sent to VitalWear via HCE")
componentActivity.runOnUiThread {
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_sent_character_success), Toast.LENGTH_SHORT).show()
}
} catch (e: Exception) {
Log.e("NFC_WRITE", "Error sending character to VitalWear HCE", e)
componentActivity.runOnUiThread {
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_error_generic) + ": " + (e.message ?: e.javaClass.simpleName), Toast.LENGTH_LONG).show()
}
} finally {
onComplete()
}
}
)
} }
// EXTRACTED DIRECTLY FROM EXAMPLE APP // EXTRACTED DIRECTLY FROM EXAMPLE APP
@ -181,10 +264,8 @@ class ScanScreenControllerImpl(
} }
override suspend fun characterToNfc(characterId: Long): NfcCharacter { override suspend fun characterToNfc(characterId: Long): NfcCharacter {
val nfcGenerator = ToNfcConverter( pendingExportCharacterId = characterId
componentActivity = componentActivity val nfcGenerator = ToNfcConverter(componentActivity = componentActivity)
)
val character = nfcGenerator.characterToNfc(characterId) val character = nfcGenerator.characterToNfc(characterId)
Log.d("CharacterType", character.toString()) Log.d("CharacterType", character.toString())
return character return character

View File

@ -15,52 +15,56 @@ class VitalWearCharacterExporter(
private val context: Context, private val context: Context,
private val database: AppDatabase private val database: AppDatabase
) { ) {
fun buildCharacterProto(characterId: Long): Character = runBlocking {
val characterWithSprites = database.userCharacterDao().getCharacterWithSprites(characterId)
val userCharacter = database.userCharacterDao().getCharacter(characterId)
val card = database.cardDao().getCardByCharacterIdSync(characterId)
?: error("Card not found for character $characterId")
val cardProgress = database.cardProgressDao().getCardProgressSync(card.id) ?: 0
Character.newBuilder()
.setCardId(card.cardId)
.setCardName(card.name)
.setCharacterStats(
Character.CharacterStats.newBuilder()
.setSlotId(database.userCharacterDao().getCharacterInfo(characterId).charaIndex)
.setVitals(characterWithSprites.vitalPoints)
.setTrainingTimeRemainingInSeconds(resolveTrainingSeconds(characterId, userCharacter.characterType))
.setTimeUntilNextTransformation(characterWithSprites.transformationCountdown.toLong() * 60L)
.setTrainedBp(resolveTrainedBp(characterId, userCharacter.characterType))
.setTrainedHp(resolveTrainedHp(characterId, userCharacter.characterType))
.setTrainedAp(resolveTrainedAp(characterId, userCharacter.characterType))
.setTrainedPp(characterWithSprites.trophies)
.setInjured(characterWithSprites.injuryStatus.name.lowercase().contains("inj"))
.setAccumulatedDailyInjuries(0)
.setTotalBattles(characterWithSprites.totalBattlesWon + characterWithSprites.totalBattlesLost)
.setCurrentPhaseBattles(characterWithSprites.currentPhaseBattlesWon + characterWithSprites.currentPhaseBattlesLost)
.setTotalWins(characterWithSprites.totalBattlesWon)
.setCurrentPhaseWins(characterWithSprites.currentPhaseBattlesWon)
.setMood(characterWithSprites.mood)
.build()
)
.setSettings(
Character.Settings.newBuilder()
.setTrainingInBackground(false)
.setAllowedBattles(Character.Settings.AllowedBattles.CARD_ONLY)
.build()
)
.putMaxAdventureCompletedByCard(card.name, (cardProgress - 1).coerceAtLeast(0))
.addAllTransformationHistory(
database.userCharacterDao().getTransformationHistoryForExport(characterId).map {
Character.TransformationEvent.newBuilder()
.setCardName(it.cardName)
.setPhase(0)
.setSlotId(it.monIndex)
.build()
}
)
.build()
}
fun buildShareIntent(characterId: Long): Intent { fun buildShareIntent(characterId: Long): Intent {
return runBlocking { return runBlocking {
val characterWithSprites = database.userCharacterDao().getCharacterWithSprites(characterId) val proto = buildCharacterProto(characterId)
val userCharacter = database.userCharacterDao().getCharacter(characterId)
val card = database.cardDao().getCardByCharacterIdSync(characterId)
?: error("Card not found for character $characterId")
val cardProgress = database.cardProgressDao().getCardProgressSync(card.id) ?: 0
val proto = Character.newBuilder()
.setCardId(card.cardId)
.setCardName(card.name)
.setCharacterStats(
Character.CharacterStats.newBuilder()
.setSlotId(database.userCharacterDao().getCharacterInfo(characterId).charaIndex)
.setVitals(characterWithSprites.vitalPoints)
.setTrainingTimeRemainingInSeconds(resolveTrainingSeconds(characterId, userCharacter.characterType))
.setTimeUntilNextTransformation(characterWithSprites.transformationCountdown.toLong() * 60L)
.setTrainedBp(resolveTrainedBp(characterId, userCharacter.characterType))
.setTrainedHp(resolveTrainedHp(characterId, userCharacter.characterType))
.setTrainedAp(resolveTrainedAp(characterId, userCharacter.characterType))
.setTrainedPp(characterWithSprites.trophies)
.setInjured(characterWithSprites.injuryStatus.name.lowercase().contains("inj"))
.setAccumulatedDailyInjuries(0)
.setTotalBattles(characterWithSprites.totalBattlesWon + characterWithSprites.totalBattlesLost)
.setCurrentPhaseBattles(characterWithSprites.currentPhaseBattlesWon + characterWithSprites.currentPhaseBattlesLost)
.setTotalWins(characterWithSprites.totalBattlesWon)
.setCurrentPhaseWins(characterWithSprites.currentPhaseBattlesWon)
.setMood(characterWithSprites.mood)
.build()
)
.setSettings(
Character.Settings.newBuilder()
.setTrainingInBackground(false)
.setAllowedBattles(Character.Settings.AllowedBattles.CARD_ONLY)
.build()
)
.putMaxAdventureCompletedByCard(card.name, (cardProgress - 1).coerceAtLeast(0))
.addAllTransformationHistory(
database.userCharacterDao().getTransformationHistoryForExport(characterId).map {
Character.TransformationEvent.newBuilder()
.setCardName(it.cardName)
.setPhase(0)
.setSlotId(it.monIndex)
.build()
}
)
.build()
val exportDir = File(context.cacheDir, "exports").apply { mkdirs() } val exportDir = File(context.cacheDir, "exports").apply { mkdirs() }
val exportFile = File(exportDir, "vbhelper_character_$characterId.vitalwear") val exportFile = File(exportDir, "vbhelper_character_$characterId.vitalwear")

View File

@ -17,21 +17,21 @@
<string name="nav_adventure">アドベンチャー</string> <string name="nav_adventure">アドベンチャー</string>
<string name="nav_credits">クレジット</string> <string name="nav_credits">クレジット</string>
<string name="adventure_title">アドベンチャー</string> <string name="adventure_title">アドベンチャー</string>
<string name="adventure_empty_state">何もありません。</string> <string name="adventure_empty_state">No Data</string>
<string name="home_title">VB Helper</string> <string name="home_title">VB Helper</string>
<string name="scan_secrets_not_imported">" APKの読み込みがされていません。設定から読み込をして下さい。 "</string> <string name="scan_secrets_not_imported">"APKの読み込みがされていません。設定から読み込をして下さい。 "</string>
<string name="scan_title">デバイスをスキャン</string> <string name="scan_title">デバイスをスキャン</string>
<string name="scan_sent_dim_success">DIMの転送に成功しました。</string> <string name="scan_sent_dim_success">DIMの転送に成功しました。</string>
<string name="scan_nfc_must_be_enabled">NFC機能を有効にして下さい。</string> <string name="scan_nfc_must_be_enabled">NFC機能を有効にして下さい。</string>
<string name="settings_title">設定</string> <string name="settings_title">設定</string>
<string name="scan_missing_secrets">必要なデータが不足しています。設定を開き、Vital ArenaのAPKを読み込んでください。</string> <string name="scan_missing_secrets">Vital ArenaのAPKを読み込みして下さい。</string>
<string name="scan_sent_character_success">転送が成功しました。</string> <string name="scan_sent_character_success">転送が成功しました。</string>
<string name="scan_error_generic">エラー</string> <string name="scan_error_generic">エラー</string>
<string name="settings_about_desc">このアプリについて</string> <string name="settings_about_desc">このアプリについて</string>
<string name="settings_export_data_title">データベースの書き出し</string> <string name="settings_export_data_title">データベースのエクスポート</string>
<string name="settings_export_data_desc">" データベースを書き出します。"</string> <string name="settings_export_data_desc">データベースの書き出しをします。</string>
<string name="settings_import_data_title">データベースの読み込み</string> <string name="settings_import_data_title">データベースのインポート</string>
<string name="settings_import_data_desc">" データベースを読み込みます。"</string> <string name="settings_import_data_desc">データベースの読み込みをします。</string>
<string name="credits_title">クレジット</string> <string name="credits_title">クレジット</string>
<string name="battles_coming_soon">Coming soon</string> <string name="battles_coming_soon">Coming soon</string>
<string name="cards_my_cards_title">カードリスト</string> <string name="cards_my_cards_title">カードリスト</string>
@ -42,7 +42,7 @@
<string name="scan_vb_to_app">デバイスからアプリへ</string> <string name="scan_vb_to_app">デバイスからアプリへ</string>
<string name="scan_app_to_vb">アプリからデバイスへ</string> <string name="scan_app_to_vb">アプリからデバイスへ</string>
<string name="read_character_title">キャラクターを読み込みます。</string> <string name="read_character_title">キャラクターを読み込みます。</string>
<string name="read_character_prepare_device">バイタルブレスを準備してください。</string> <string name="read_character_prepare_device">バイスを準備してください。</string>
<string name="read_character_go_to_connect">準備が出来たら転送を押してください。</string> <string name="read_character_go_to_connect">準備が出来たら転送を押してください。</string>
<string name="read_character_confirm">転送</string> <string name="read_character_confirm">転送</string>
<string name="card_adventure_missions_title">アドベンチャーミッション</string> <string name="card_adventure_missions_title">アドベンチャーミッション</string>
@ -54,31 +54,33 @@
<string name="storage_delete_character">削除</string> <string name="storage_delete_character">削除</string>
<string name="storage_close">閉じる</string> <string name="storage_close">閉じる</string>
<string name="storage_character_image_description">キャラクター画像</string> <string name="storage_character_image_description">キャラクター画像</string>
<string name="storage_send_to_watch">転送</string> <string name="storage_send_to_watch">デバイスへ転送</string>
<string name="storage_send_to_vitalwear">VitalWearへ転送</string>
<string name="storage_send_to_vitalwear">VitalWearへ転送</string>
<string name="storage_set_active">選択</string> <string name="storage_set_active">選択</string>
<string name="storage_send_on_adventure">アドベンチャーへ出発</string> <string name="storage_send_on_adventure">アドベンチャーへ出発</string>
<string name="scan_no_nfc_on_device">NFC機能が見つかりません。</string> <string name="scan_no_nfc_on_device">NFC機能が見つかりません。</string>
<string name="scan_tag_not_vb">検出されたタグはバイタルブレスでは使用出来ません。</string> <string name="scan_tag_not_vb">検出されたタグはバイタルブレスでは使用出来ません。</string>
<string name="settings_section_nfc">NFC</string> <string name="settings_section_nfc">NFC通信</string>
<string name="settings_section_dim_bem">DiM / BEm</string> <string name="settings_section_dim_bem">DiM / BEm管理</string>
<string name="settings_section_data">データ管理</string> <string name="settings_section_data">データ管理</string>
<string name="settings_import_apk_title">アプリの読み込み</string> <string name="settings_import_apk_title">アプリのインポート</string>
<string name="settings_import_apk_desc">" Vital Arena 2.1.0のAPKファイルを読み込みします。"</string> <string name="settings_import_apk_desc">Vital Arena 2.1.0のAPKファイルを読み込みします。</string>
<string name="settings_import_card_title">カードの読み込み</string> <string name="settings_import_card_title">カードのインポート</string>
<string name="settings_section_about">概要 / クレジット</string> <string name="settings_section_about">概要 / クレジット</string>
<string name="dex_chara_fusions_button">ジョグレス</string> <string name="dex_chara_fusions_button">ジョグレス</string>
<string name="dex_chara_close_button">閉じる</string> <string name="dex_chara_close_button">閉じる</string>
<string name="settings_import_card_desc">" Dim / BEm カードファイルを読み込みます。"</string> <string name="settings_import_card_desc">Dim / BEm のデータファイルを読み込みします。</string>
<string name="settings_credits_title">クレジット</string> <string name="settings_credits_title">クレジット</string>
<string name="settings_credits_desc">開発者について</string> <string name="settings_credits_desc">開発者について</string>
<string name="settings_about_title">概要</string> <string name="settings_about_title">概要</string>
<string name="beta_warning_message_main">" このアプリは現在アルファ版です。今後のアップデートにより保存されているデータの全てが削除される可能性がある為、大切なデータの保存はしないようにお願い致します。ご不便をおかけして申し訳ございません。 "</string> <string name="beta_warning_message_main">このアプリは現在開発中です。\n今後のアップデートにより、保存されているデータ全ての削除が必要になる場合があります。\nその為、大切なデータの保存には使用しないようお願い致します。\nご不便をおかけして申し訳ございません。</string>
<string name="beta_warning_message_compatibility">" このアプリはオリジナルのVBおよびVHで動作するようになりました。 "</string> <string name="beta_warning_message_compatibility">"このアプリはオリジナルのVBおよびVHで動作するようになりました。 "</string>
<string name="beta_warning_message_thanks">" ご理解とご協力に感謝いたします。\n 開発チーム一同"</string> <string name="beta_warning_message_thanks">ご理解とご協力に感謝致します。\n開発チーム一同</string>
<string name="home_vbdim_vitals">バイタル</string> <string name="home_vbdim_vitals">バイタル</string>
<string name="home_adventure_mission_finished">" 1人のキャラクターがアドベンチャーミッションを完了しました。 "</string> <string name="home_adventure_mission_finished">"1人のキャラクターがアドベンチャーミッションを完了しました。 "</string>
<string name="scan_secrets_not_initialized">" 初期化が出来ませんでした。もう一度試して下さい。 "</string> <string name="scan_secrets_not_initialized">"初期化が出来ませんでした。もう一度試して下さい。 "</string>
<string name="home_special_mission_delete_main">現在の進捗状況が失われますが、本当にこのスペシャルミッションを削除しますか?</string> <string name="home_special_mission_delete_main">現在の進捗状況が失われます。本当にこのミッションを削除しますか?</string>
<string name="home_special_mission_delete_dismiss">閉じる</string> <string name="home_special_mission_delete_dismiss">閉じる</string>
<string name="home_special_mission_delete_remove">削除</string> <string name="home_special_mission_delete_remove">削除</string>
<string name="item_dialog_use">アイテム使用</string> <string name="item_dialog_use">アイテム使用</string>
@ -90,25 +92,26 @@
<string name="obtained_item_you_also_got_credits">%1$d クレジットを獲得しました。</string> <string name="obtained_item_you_also_got_credits">%1$d クレジットを獲得しました。</string>
<string name="obtained_item_dismiss">閉じる</string> <string name="obtained_item_dismiss">閉じる</string>
<string name="nav_dex">図鑑</string> <string name="nav_dex">図鑑</string>
<string name="action_place_near_reader">バイタルブレス本体を近くに置いて下さい。</string> <string name="credits_RedEyez_description">献身的なデバッグ作業を行って頂きました。</string>
<string name="action_place_near_reader">デバイスを近づけて下さい。</string>
<string name="action_cancel">キャンセル</string> <string name="action_cancel">キャンセル</string>
<string name="card_view_discovered_characters">解放済みキャラクター</string> <string name="card_view_discovered_characters">解放済みキャラクター</string>
<string name="dex_chara_icon_description">キャラクターアイコン</string> <string name="dex_chara_icon_description">キャラクターアイコン</string>
<string name="dex_chara_name_icon_description">名前</string> <string name="dex_chara_name_icon_description">名前</string>
<string name="credits_section_reverse_engineering">リバースエンジニアリング</string> <string name="credits_section_reverse_engineering">プログラム解析</string>
<string name="credits_section_app_development">アプリケーション開発</string> <string name="credits_section_app_development">アプリケーション開発</string>
<string name="credits_cyanic_description">" ファームウェアの解析を行い、開発をサポートしてくれました。"</string> <string name="credits_cyanic_description">ファームウェアの解析を行い、開発をサポートしてくれました。</string>
<string name="credits_cfogrady_description">" vb-lib-nfc開発およびアプリの開発に協力して頂きました。"</string> <string name="credits_cfogrady_description">vb-lib-nfc開発およびアプリの開発に協力して頂きました。</string>
<string name="credits_nacabaro_description">" アプリの開発をしました。"</string> <string name="credits_nacabaro_description">本アプリの開発をしました。</string>
<string name="credits_lightheel_description">" アプリのサーバー含む対戦機能を開発して頂きました。現在も開発を継続して頂いています。"</string> <string name="credits_lightheel_description">アプリのサーバー含む対戦機能を開発して頂きました。現在も開発を継続して頂いています。</string>
<string name="credits_shvstrz_description">" アプリのアイコンデザインをして頂きました。"</string> <string name="credits_shvstrz_description">アプリのアイコンデザインをして頂きました。</string>
<string name="write_card_title">カード情報書き込み中</string> <string name="write_card_title">カード情報書き込み中</string>
<string name="write_card_icon_description">カードアイコン</string> <string name="write_card_icon_description">カードアイコン</string>
<string name="write_card_device_ready">デバイスの準備をして下さい。</string> <string name="write_card_device_ready">デバイスの準備をして下さい。</string>
<string name="write_card_required_card">%1$s カードが必要です。</string> <string name="write_card_required_card">%1$s カードが必要です。</string>
<string name="write_card_confirm">転送</string> <string name="write_card_confirm">転送</string>
<string name="write_character_success">" カードの読み込みが完了しました。"</string> <string name="write_character_success">カードの読み込みが完了しました。</string>
<string name="write_character_wait_ready">" デバイスの準備をしてから確認を押して下さい。"</string> <string name="write_character_wait_ready">" デバイスの準備をしてから確認を押して下さい。"</string>
<string name="write_character_confirm">確認</string> <string name="write_character_confirm">確認</string>
<string name="home_vbdim_trophies">トロフィー</string> <string name="home_vbdim_trophies">トロフィー</string>
<string name="items_purchase_success">購入しました。</string> <string name="items_purchase_success">購入しました。</string>
@ -119,10 +122,10 @@
<string name="dex_chara_stats">HP: %1$d, BP: %2$d, AP: %3$d</string> <string name="dex_chara_stats">HP: %1$d, BP: %2$d, AP: %3$d</string>
<string name="dex_chara_stage_attribute_unknown">Stg: -, Atr: -</string> <string name="dex_chara_stage_attribute_unknown">Stg: -, Atr: -</string>
<string name="dex_chara_stats_unknown">HP: -, BP: -, AP: -</string> <string name="dex_chara_stats_unknown">HP: -, BP: -, AP: -</string>
<string name="dex_chara_requirements">" Tr: %1$d; Bt: %2$d; Vr: %3$d; Wr: %4$d%%; Ct: %5$dh "</string> <string name="dex_chara_requirements">\n Tr: %1$d; Bt: %2$d; Vr: %3$d; Wr: %4$d%%; Ct: %5$dh</string>
<string name="dex_chara_adventure_level">AdvLvl %1$d</string> <string name="dex_chara_adventure_level">AdvLvl %1$d</string>
<string name="storage_my_characters_title">キャラクターリスト</string> <string name="storage_my_characters_title">キャラクターリスト</string>
<string name="storage_nothing_to_see_here">表示するデータはありません。</string> <string name="storage_nothing_to_see_here">No Data</string>
<string name="storage_in_adventure_toast">このキャラクターは冒険中です。</string> <string name="storage_in_adventure_toast">このキャラクターは冒険中です。</string>
<string name="home_vbdim_next_timer">次のタイマー</string> <string name="home_vbdim_next_timer">次のタイマー</string>
<string name="home_vbdim_total_battle_win">総勝率 %</string> <string name="home_vbdim_total_battle_win">総勝率 %</string>
@ -143,4 +146,18 @@
<string name="special_mission_steps_progress">歩数 %1$d 歩</string> <string name="special_mission_steps_progress">歩数 %1$d 歩</string>
<string name="special_mission_battles_progress">バトル %1$d 回</string> <string name="special_mission_battles_progress">バトル %1$d 回</string>
<string name="special_mission_wins_progress">勝利 %1$d 回</string> <string name="special_mission_wins_progress">勝利 %1$d 回</string>
<string name="settings_companion_import_card_image_title">カードのインポート</string>
<string name="settings_companion_import_card_image_title">カードのインポート</string>
<string name="companion_validation_connect_vb">デバイスに接続</string>
<string name="companion_card_import_success">カードのインポートに成功しました。</string>
<string name="companion_firmware_no_watch">デバイスが見つかりません。</string>
<string name="companion_validation_insert_card">デバイスへカードを差し込んで下さい。</string>
<string name="companion_validation_success">データチェックが完了しました。</string>
<string name="companion_loading_select_firmware">ファームウェアファイルを選択</string>
<string name="companion_firmware_sent_success">ファームウェアの送信が完了しました。</string>
<string name="companion_logs_receive_failed">ログの受信に失敗しました。</string>
<string name="companion_logs_failed_request">ログの要求に失敗しました。</string>
<string name="companion_logs_warning">注意:ログの転送には時間がかかる場合があります。</string>
<string name="settings_companion_send_watch_logs_title">ログの送信</string>
<string name="companion_transfer_disabled_message">現在、転送は無効になっています。</string>
</resources> </resources>

View File

@ -17,6 +17,7 @@ dependencyResolutionManagement {
mavenLocal() mavenLocal()
google() google()
mavenCentral() mavenCentral()
maven { url = uri("https://jitpack.io") }
} }
} }