Add TitleId TextView in App Dialog

This commit is contained in:
Dima 2022-11-22 19:11:37 +03:00 committed by Billy Laws
parent b08fcd7027
commit 5a9a2861df
9 changed files with 54 additions and 6 deletions

View File

@ -51,6 +51,7 @@ extern "C" JNIEXPORT jint JNICALL Java_emu_skyline_loader_RomFile_populate(JNIEn
jclass clazz{env->GetObjectClass(thiz)}; jclass clazz{env->GetObjectClass(thiz)};
jfieldID applicationNameField{env->GetFieldID(clazz, "applicationName", "Ljava/lang/String;")}; jfieldID applicationNameField{env->GetFieldID(clazz, "applicationName", "Ljava/lang/String;")};
jfieldID applicationTitleIdField{env->GetFieldID(clazz, "applicationTitleId", "Ljava/lang/String;")};
jfieldID applicationAuthorField{env->GetFieldID(clazz, "applicationAuthor", "Ljava/lang/String;")}; jfieldID applicationAuthorField{env->GetFieldID(clazz, "applicationAuthor", "Ljava/lang/String;")};
jfieldID rawIconField{env->GetFieldID(clazz, "rawIcon", "[B")}; jfieldID rawIconField{env->GetFieldID(clazz, "rawIcon", "[B")};
jfieldID applicationVersionField{env->GetFieldID(clazz, "applicationVersion", "Ljava/lang/String;")}; jfieldID applicationVersionField{env->GetFieldID(clazz, "applicationVersion", "Ljava/lang/String;")};
@ -62,6 +63,7 @@ extern "C" JNIEXPORT jint JNICALL Java_emu_skyline_loader_RomFile_populate(JNIEn
env->SetObjectField(thiz, applicationNameField, env->NewStringUTF(loader->nacp->GetApplicationName(language).c_str())); env->SetObjectField(thiz, applicationNameField, env->NewStringUTF(loader->nacp->GetApplicationName(language).c_str()));
env->SetObjectField(thiz, applicationVersionField, env->NewStringUTF(loader->nacp->GetApplicationVersion().c_str())); env->SetObjectField(thiz, applicationVersionField, env->NewStringUTF(loader->nacp->GetApplicationVersion().c_str()));
env->SetObjectField(thiz, applicationTitleIdField, env->NewStringUTF(loader->nacp->GetSaveDataOwnerId().c_str()));
env->SetObjectField(thiz, applicationAuthorField, env->NewStringUTF(loader->nacp->GetApplicationPublisher(language).c_str())); env->SetObjectField(thiz, applicationAuthorField, env->NewStringUTF(loader->nacp->GetApplicationPublisher(language).c_str()));
auto icon{loader->GetIcon(language)}; auto icon{loader->GetIcon(language)};

View File

@ -61,7 +61,7 @@ namespace skyline::kernel {
name = nacp->GetApplicationName(nacp->GetFirstSupportedTitleLanguage()); name = nacp->GetApplicationName(nacp->GetFirstSupportedTitleLanguage());
if (publisher.empty()) if (publisher.empty())
publisher = nacp->GetApplicationPublisher(nacp->GetFirstSupportedTitleLanguage()); publisher = nacp->GetApplicationPublisher(nacp->GetFirstSupportedTitleLanguage());
Logger::InfoNoPrefix(R"(Starting "{}" v{} by "{}")", name, nacp->GetApplicationVersion(), publisher); Logger::InfoNoPrefix(R"(Starting "{}" ({}) v{} by "{}")", name, nacp->GetSaveDataOwnerId(), nacp->GetApplicationVersion(), publisher);
} }
process->InitializeHeapTls(); process->InitializeHeapTls();

View File

@ -34,6 +34,11 @@ namespace skyline::vfs {
return std::string(applicationPublisher.as_string(true)); return std::string(applicationPublisher.as_string(true));
} }
std::string NACP::GetSaveDataOwnerId() {
auto applicationTitleId{nacpContents.saveDataOwnerId};
return fmt::format("{:016X}", applicationTitleId);
}
std::string NACP::GetApplicationPublisher(language::ApplicationLanguage language) { std::string NACP::GetApplicationPublisher(language::ApplicationLanguage language) {
auto applicationPublisher{span(nacpContents.titleEntries.at(static_cast<size_t>(language)).applicationPublisher)}; auto applicationPublisher{span(nacpContents.titleEntries.at(static_cast<size_t>(language)).applicationPublisher)};
return std::string(applicationPublisher.as_string(true)); return std::string(applicationPublisher.as_string(true));

View File

@ -49,6 +49,8 @@ namespace skyline::vfs {
std::string GetApplicationVersion(); std::string GetApplicationVersion();
std::string GetSaveDataOwnerId();
std::string GetApplicationPublisher(language::ApplicationLanguage language); std::string GetApplicationPublisher(language::ApplicationLanguage language);
}; };
} }

View File

@ -19,6 +19,7 @@ import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.snackbar.Snackbar
import emu.skyline.data.AppItem import emu.skyline.data.AppItem
import emu.skyline.databinding.AppDialogBinding import emu.skyline.databinding.AppDialogBinding
import emu.skyline.loader.LoaderResult import emu.skyline.loader.LoaderResult
@ -66,6 +67,7 @@ class AppDialog : BottomSheetDialogFragment() {
binding.gameIcon.setImageBitmap(item.icon ?: missingIcon) binding.gameIcon.setImageBitmap(item.icon ?: missingIcon)
binding.gameTitle.text = item.title binding.gameTitle.text = item.title
binding.gameVersion.text = item.version ?: item.loaderResultString(requireContext()) binding.gameVersion.text = item.version ?: item.loaderResultString(requireContext())
binding.gameTitleId.text = item.titleId
binding.gameAuthor.text = item.author binding.gameAuthor.text = item.author
binding.gamePlay.isEnabled = item.loaderResult == LoaderResult.Success binding.gamePlay.isEnabled = item.loaderResult == LoaderResult.Success
@ -91,6 +93,13 @@ class AppDialog : BottomSheetDialogFragment() {
shortcutManager.requestPinShortcut(info.build(), null) shortcutManager.requestPinShortcut(info.build(), null)
} }
binding.gameTitleId.setOnLongClickListener {
val clipboard = requireActivity().getSystemService(android.content.Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager
clipboard.setPrimaryClip(android.content.ClipData.newPlainText("Title ID", item.titleId))
Snackbar.make(binding.root, getString(R.string.copied_to_clipboard), Snackbar.LENGTH_SHORT).show()
true
}
dialog?.setOnKeyListener { _, keyCode, event -> dialog?.setOnKeyListener { _, keyCode, event ->
if (keyCode == KeyEvent.KEYCODE_BUTTON_B && event.action == KeyEvent.ACTION_UP) { if (keyCode == KeyEvent.KEYCODE_BUTTON_B && event.action == KeyEvent.ACTION_UP) {
dialog?.onBackPressed() dialog?.onBackPressed()

View File

@ -29,6 +29,11 @@ data class AppItem(private val meta : AppEntry) : DataItem() {
*/ */
val title get() = meta.name val title get() = meta.name
/**
* The title ID of the application
*/
val titleId get() = meta.titleId
/** /**
* The application version * The application version
*/ */

View File

@ -66,6 +66,7 @@ enum class LoaderResult(val value : Int) {
data class AppEntry( data class AppEntry(
var name : String, var name : String,
var version : String?, var version : String?,
var titleId : String?,
var author : String?, var author : String?,
var icon : Bitmap?, var icon : Bitmap?,
var format : RomFormat, var format : RomFormat,
@ -76,7 +77,7 @@ data class AppEntry(
val nameIndex : Int = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) val nameIndex : Int = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
cursor.moveToFirst() cursor.moveToFirst()
cursor.getString(nameIndex) cursor.getString(nameIndex)
}!!.dropLast(format.name.length + 1), null, null, null, format, uri, loaderResult) }!!.dropLast(format.name.length + 1), null, null, null, null, format, uri, loaderResult)
private fun writeObject(output : ObjectOutputStream) { private fun writeObject(output : ObjectOutputStream) {
output.writeUTF(name) output.writeUTF(name)
@ -85,6 +86,9 @@ data class AppEntry(
output.writeBoolean(version != null) output.writeBoolean(version != null)
if (version != null) if (version != null)
output.writeUTF(version) output.writeUTF(version)
output.writeBoolean(titleId != null)
if (titleId != null)
output.writeUTF(titleId)
output.writeBoolean(author != null) output.writeBoolean(author != null)
if (author != null) if (author != null)
output.writeUTF(author) output.writeUTF(author)
@ -105,6 +109,8 @@ data class AppEntry(
uri = Uri.parse(input.readUTF()) uri = Uri.parse(input.readUTF())
if (input.readBoolean()) if (input.readBoolean())
version = input.readUTF() version = input.readUTF()
if (input.readBoolean())
titleId = input.readUTF()
if (input.readBoolean()) if (input.readBoolean())
author = input.readUTF() author = input.readUTF()
loaderResult = LoaderResult.get(input.readInt()) loaderResult = LoaderResult.get(input.readInt())
@ -129,6 +135,11 @@ internal class RomFile(context : Context, format : RomFormat, uri : Uri, systemL
*/ */
private var applicationName : String? = null private var applicationName : String? = null
/**
* @note This field is filled in by native code
*/
private var applicationTitleId : String? = null
/** /**
* @note This field is filled in by native code * @note This field is filled in by native code
*/ */
@ -158,9 +169,11 @@ internal class RomFile(context : Context, format : RomFormat, uri : Uri, systemL
appEntry = applicationName?.let { name -> appEntry = applicationName?.let { name ->
applicationVersion?.let { version -> applicationVersion?.let { version ->
applicationAuthor?.let { author -> applicationTitleId?.let { titleId ->
rawIcon?.let { icon -> applicationAuthor?.let { author ->
AppEntry(name, version, author, BitmapFactory.decodeByteArray(icon, 0, icon.size), format, uri, result) rawIcon?.let { icon ->
AppEntry(name, version, titleId, author, BitmapFactory.decodeByteArray(icon, 0, icon.size), format, uri, result)
}
} }
} }
} }

View File

@ -54,7 +54,7 @@
tools:text="The Legend of Zelda: Breath of the Wild" /> tools:text="The Legend of Zelda: Breath of the Wild" />
<TextView <TextView
android:id="@+id/game_version" android:id="@+id/game_title_id"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSecondary" android:textAppearance="?android:attr/textAppearanceListItemSecondary"
@ -62,6 +62,17 @@
android:textSize="14sp" android:textSize="14sp"
app:layout_constraintStart_toStartOf="@id/game_title" app:layout_constraintStart_toStartOf="@id/game_title"
app:layout_constraintTop_toBottomOf="@id/game_title" app:layout_constraintTop_toBottomOf="@id/game_title"
tools:text="0100000000010000" />
<TextView
android:id="@+id/game_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="@android:color/tertiary_text_light"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@id/game_title_id"
app:layout_constraintTop_toBottomOf="@id/game_title_id"
tools:text="1.0.0" /> tools:text="1.0.0" />
<TextView <TextView

View File

@ -3,6 +3,7 @@
<!-- Common --> <!-- Common -->
<string name="search">Search</string> <string name="search">Search</string>
<string name="error">An error has occurred</string> <string name="error">An error has occurred</string>
<string name="copied_to_clipboard">Copied to clipboard</string>
<!-- Toolbar Main --> <!-- Toolbar Main -->
<string name="settings">Settings</string> <string name="settings">Settings</string>
<string name="share_logs">Share Logs</string> <string name="share_logs">Share Logs</string>