Skip to content

Conversation

@brijesh025
Copy link

@brijesh025 brijesh025 commented Jan 18, 2026

Explanation

Fixes #6006: Adds the Installation ID to the App Version screen and provides a copy button so users can easily share the ID for debugging and support purposes.

Essential Checklist

  • The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".)
  • Any changes to scripts/assets files have their rationale included in the PR explanation.
  • The PR follows the style guide.
  • The PR does not contain any unnecessary code changes from Android Studio (reference).
  • The PR is made from a branch that's not called "develop" and is up-to-date with "develop".
  • The PR is assigned to the appropriate reviewers (reference).

Screenshots

Tablet

Light mode
image

Dark mode
image

Phone

Light mode
image

Dark mode
image

Demo Video

oppia_pr1_update.mp4

Note: That toast at bottom showing oppia pasted from clipboard.... is not implemented in app, it is android feature as far I have researched, since I have not implemented any toast feature.

Testing

  • Manually tested by uninstalling and reinstalling the app to verify Installation ID is generated correctly
  • Verified Installation ID remains consistent across app restarts
  • Verified copy button copies the correct Installation ID to clipboard
  • Verified UI behavior in light and dark mode on phone and tablet
  • added test for new features.

##Files changed : 4

  • app/src/main/java/org/oppia/android/app/administratorcontrols/appversion/AppVersionViewModel.kt
  • app/src/main/res/layout/app_version_fragment.xml
  • app/src/main/res/values/strings.xml
  • app/src/sharedTest/java/org/oppia/android/app/administratorcontrols/appversion/AppVersionActivityTest.kt

Copilot AI review requested due to automatic review settings January 18, 2026 21:13
@brijesh025 brijesh025 requested a review from a team as a code owner January 18, 2026 21:13
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an Installation ID display with a copy button to the App Version screen to help users share their installation ID for debugging and support purposes.

Changes:

  • Added Installation ID display section with copy functionality to the App Version screen
  • Implemented copy state tracking using a Handler with 2-second reset delay
  • Added three new string resources for Installation ID label, explanation, and copy button

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.

File Description
app/src/main/res/values/strings.xml Added three new string resources for Installation ID UI labels and descriptions
app/src/main/res/layout/app_version_fragment.xml Restructured layout to add Installation ID section above existing app version information, including copy button and info icon
app/src/main/java/org/oppia/android/app/administratorcontrols/appversion/AppVersionViewModel.kt Added Installation ID retrieval, copy functionality with timed state reset, and supporting LiveData/ObservableField properties

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 14 to 15
android:background="@color/component_color_shared_screen_tertiary_background_color"
android:fillViewport="true">
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The android:fillViewport attribute is only applicable to ScrollView and is not valid for ConstraintLayout. This attribute should be removed as it has no effect on ConstraintLayout and may cause confusion.

Suggested change
android:background="@color/component_color_shared_screen_tertiary_background_color"
android:fillViewport="true">
android:background="@color/component_color_shared_screen_tertiary_background_color">

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brijesh025, PTAL.

Comment on lines 62 to 74
).toLiveData().observe(fragment) { result ->
if (result is AsyncResult.Success) {
isInstallationIdCopied.set(true)
handler.postDelayed({
isInstallationIdCopied.set(false)
}, COPY_ICON_RESET_DELAY_MS)
} else {
oppiaLogger.w(
"AppVersionViewModel",
"Encountered unexpected non-successful result when copying to clipboard: $result"
)
}
}
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LiveData observer added to the clipboard operation result is never removed. This creates a potential memory leak because the observer will continue to exist even after the fragment is destroyed. The fragment reference passed to observe() means the observer is tied to the fragment lifecycle, but since this is called within a function that can be invoked multiple times, you may accumulate multiple observers. Consider using observeForever() with proper cleanup in onCleared(), or better yet, return the result as a LiveData that the UI layer observes directly rather than observing within the ViewModel.

Copilot uses AI. Check for mistakes.
Comment on lines 41 to 67
/** Indicates whether the installation ID was recently copied. */
val isInstallationIdCopied = ObservableField(false)

/** The device installation ID. */
val installationId: LiveData<String?> by lazy {
Transformations.map(
loggingIdentifierController.getInstallationId().toLiveData()
) { result ->
(result as? AsyncResult.Success)?.value
}
}

/** Copies the specified installation ID (if non-null) to the user's clipboard. */
fun copyInstallationId(installationId: String?) {
installationId?.let {
val appName = resourceHandler.getStringInLocale(R.string.app_name)
clipboardController.setCurrentClip(
resourceHandler.getStringInLocaleWithWrapping(
R.string.learner_analytics_device_id_clipboard_label_description, appName
),
installationId
).toLiveData().observe(fragment) { result ->
if (result is AsyncResult.Success) {
isInstallationIdCopied.set(true)
handler.postDelayed({
isInstallationIdCopied.set(false)
}, COPY_ICON_RESET_DELAY_MS)
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation approach for tracking copy state differs from the existing pattern used in DeviceIdItemViewModel and ProfileLearnerIdItemViewModel. Those implementations use clipboardController.getCurrentClip() to track the copied state rather than using a Handler with a timed reset. This creates an inconsistent user experience where the Installation ID copy button resets after 2 seconds, while other copy buttons in the learner analytics section stay in the "copied" state until a different ID is copied. Consider following the existing pattern by tracking currentCopiedId via the clipboard controller for consistency.

Copilot uses AI. Check for mistakes.
Comment on lines 41 to 76
/** Indicates whether the installation ID was recently copied. */
val isInstallationIdCopied = ObservableField(false)

/** The device installation ID. */
val installationId: LiveData<String?> by lazy {
Transformations.map(
loggingIdentifierController.getInstallationId().toLiveData()
) { result ->
(result as? AsyncResult.Success)?.value
}
}

/** Copies the specified installation ID (if non-null) to the user's clipboard. */
fun copyInstallationId(installationId: String?) {
installationId?.let {
val appName = resourceHandler.getStringInLocale(R.string.app_name)
clipboardController.setCurrentClip(
resourceHandler.getStringInLocaleWithWrapping(
R.string.learner_analytics_device_id_clipboard_label_description, appName
),
installationId
).toLiveData().observe(fragment) { result ->
if (result is AsyncResult.Success) {
isInstallationIdCopied.set(true)
handler.postDelayed({
isInstallationIdCopied.set(false)
}, COPY_ICON_RESET_DELAY_MS)
} else {
oppiaLogger.w(
"AppVersionViewModel",
"Encountered unexpected non-successful result when copying to clipboard: $result"
)
}
}
}
}
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new Installation ID display and copy functionality lacks test coverage. The existing AppVersionActivityTest does not include tests for the new Installation ID UI element, the copy button behavior, or the state changes when copying. Consider adding tests to verify: 1) Installation ID is displayed correctly, 2) Copy button is enabled when ID is available, 3) Copy button updates its state when clicked, and 4) Copied state resets after the delay period.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@adhiamboperes adhiamboperes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the previously requested changes, @brijesh025! I have left a few more comments, and please add tests in AppVersionActivityTest.

Comment on lines 14 to 15
android:background="@color/component_color_shared_screen_tertiary_background_color"
android:fillViewport="true">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brijesh025, PTAL.

Comment on lines 65 to 67
handler.postDelayed({
isInstallationIdCopied.set(false)
}, COPY_ICON_RESET_DELAY_MS)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

postDelayed is a prohibited method, please see:

file_content_checks {
file_path_regex: ".+?\\.kt$"
prohibited_content_regex: ".+?\\.(post|postDelayed)[\\s]*(\\(|\\{).*?"
failure_message: "Prefer avoiding post() and postDelayed() methods as they can can lead to subtle and difficult-to-debug crashes. Prefer using LifecycleSafeTimerFactory for most cases when an operation needs to run at a future time. For cases when state needs to be synchronized with a view, use doOnPreDraw or doOnLayout instead. For more context on the underlying issue, see: https://betterprogramming.pub/stop-using-post-postdelayed-in-your-android-views-9d1c8eeaadf2."
exempted_file_name: "app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerFragmentPresenter.kt"
exempted_file_name: "app/src/main/java/org/oppia/android/app/player/state/StateFragmentPresenter.kt"
exempted_file_name: "app/src/main/java/org/oppia/android/app/topic/info/TopicInfoFragmentPresenter.kt"
exempted_file_name: "app/src/main/java/org/oppia/android/app/utility/ClickableAreasImage.kt"
exempted_file_name: "scripts/src/javatests/org/oppia/android/scripts/regex/RegexPatternValidationCheckTest.kt"
exempted_file_name: "utility/src/main/java/org/oppia/android/util/parser/image/UrlImageParser.kt"
# These are false positives.
exempted_file_name: "data/src/test/java/org/oppia/android/data/backends/gae/testing/FeedbackReportingServiceTestOrchestratorTest.kt"
exempted_file_name: "data/src/test/java/org/oppia/android/data/backends/gae/testing/PlatformParameterServiceTestOrchestratorTest.kt"

I do not think it is needed here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, i have used

lifecycleSafeTimerFactory.createTimer(COPY_ICON_RESET_DELAY_MS).observe(fragment) {
           isInstallationIdCopied.set(false)
         }

in place of

 handler.postDelayed({
            isInstallationIdCopied.set(false)
          }, COPY_ICON_RESET_DELAY_MS)

@oppiabot
Copy link

oppiabot bot commented Jan 20, 2026

Hi @brijesh025, it looks like some changes were requested on this pull request by @adhiamboperes. PTAL. Thanks!

@swnmn
Copy link

swnmn commented Jan 20, 2026

Hello, hopping in here to ask what the hex value of the green text is. It looks a bit bright. I'm sure it's the provided hex but want to double check (output can always look a bit different) thanks so much!!

brijesh025 and others added 2 commits January 21, 2026 23:35
@brijesh025 brijesh025 requested a review from a team as a code owner January 21, 2026 18:41
@brijesh025 brijesh025 requested a review from BenHenning January 21, 2026 18:41
@brijesh025
Copy link
Author

image I have added 7 test for installation_Id feature in AppVersionActivityTest, i have also provided the screen shot of previous(5) + new(7) = 12 successful test.

@BenHenning
Copy link
Member

We discussed this PR in the CLaM meeting this week and collected some feedback for you @brijesh025. It'd be nice to to refine the UI to be a bit more streamlined, and also consistent for copy functionality and among other settings screens. In particular, please make the following changes:

  • Move the installation ID to be below the app version (since this screen is for app versions primarily.
  • Make 'Installation ID' be a top-level header like 'App Version' so that the screen has two sections: one for app version and one for installation ID.
  • Ensure that the white boxes for both IDs are the same size and have the same spacing, and ditto for the information line underneath them.
  • Please add the copy functionality to the app version, as well (for consistency).
  • Remove the 'App Version' text from the version name box--it should just contain the version name since it's already contextualized with the header and title bar.

Does this all make sense? It should largely clean up the UI, I think.

@BenHenning
Copy link
Member

Hello, hopping in here to ask what the hex value of the green text is. It looks a bit bright. I'm sure it's the provided hex but want to double check (output can always look a bit different) thanks so much!!

@swnmn I think that is #3bd1c4 (color_def_oppia_turquoise since this is color_palette_primary_color). FYI it's maybe a bit hard to follow but you can get a quick glance at used colors with these files:

But we're always happy to look them up, too, since tying these IDs back to the UI isn't easy.

Looks like a bright teal. This has been used for a few years now with dark mode, but it's fortunately very easy for us to change it if that's something the design team would like to consider.

@brijesh025
Copy link
Author

We discussed this PR in the CLaM meeting this week and collected some feedback for you @brijesh025. It'd be nice to to refine the UI to be a bit more streamlined, and also consistent for copy functionality and among other settings screens. In particular, please make the following changes:

  • Move the installation ID to be below the app version (since this screen is for app versions primarily.
  • Make 'Installation ID' be a top-level header like 'App Version' so that the screen has two sections: one for app version and one for installation ID.
  • Ensure that the white boxes for both IDs are the same size and have the same spacing, and ditto for the information line underneath them.
  • Please add the copy functionality to the app version, as well (for consistency).
  • Remove the 'App Version' text from the version name box--it should just contain the version name since it's already contextualized with the header and title bar.

Does this all make sense? It should largely clean up the UI, I think.

Thanks for the detailed feedback, @benhemming!
Yes, the changes make sense and I agree they’ll help streamline the UI and keep it consistent with other screens.

@swnmn
Copy link

swnmn commented Jan 26, 2026

@BenHenning as this is the color we've been using for now, I'd rather approach the update on a larger scale in the near future. For now, I think it looks okay. My general thinking is that it's a bit brighter than the rest of the color palette and can feel disconnected for the user.

@swnmn
Copy link

swnmn commented Jan 26, 2026

@BenHenning is there a particular way I can create a ticket for this without it getting lost? It would be for design to explore the text color in the near future for dark mode. Last time I made a ticket it disappeared and Sean had to help find it, so want to be sure it doesn't get lost.

Appreciate the help!

@adhiamboperes
Copy link
Contributor

Hi @swnmn, could you be referring to the design team repo? Once an issue is created there, we can add the link to the corresponding issue on the android repo.

@brijesh025
Copy link
Author

@BenHenning
Sorry for the late update—I was tied up with some college events.
I’ve attached screenshots showing the UI changes I’ve made. Please take a look and let me know if any further changes are needed. Once confirmed, I’ll push the updates.
Screenshot_20260127_203421

@brijesh025
Copy link
Author

image I have added 2 test for the new copy button feature of version name.

@oppiabot oppiabot bot assigned BenHenning and unassigned brijesh025 Jan 27, 2026
@oppiabot
Copy link

oppiabot bot commented Jan 27, 2026

Unassigning @brijesh025 since a re-review was requested. @brijesh025, please make sure you have addressed all review comments. Thanks!

@BenHenning
Copy link
Member

BenHenning commented Jan 27, 2026

Thanks @brijesh025! Some thoughts:

  • This looks much better.
  • We should keep the other 'App Version' header (so that there's both an 'App Version' and 'Installation ID' section).
  • It feels a bit redundant for both info lines to say to use the ID when filing bugs, so I think we should perhaps reword them. And, I don't think we actually want to proactively encourage people to share their installation ID. I suggest the following rewordings:

App Version:

The app was last updated on . Please share the above version when sending feedback about bugs.

Installation ID:

This ID uniquely identifies this app installation. You may be asked to provide this when filing feedback about the app or using certain features.

Some rewording to the version info to be a bit more correct and clearer, and I reversed the onus for the install ID to make it less actionable.

The only other thing is I don't totally love the way the layout looks, though it is much better than before and probably reasonable for a tertiary user flow like this. I'm curious if you have any specific suggestions for improvements, though, @swnmn.

Finally, please update screenshots in the main PR description once these latest changes are addressed @brijesh025 since I think we'll probably be happy to take them once any other code-related findings are also addressed in subsequent reviews.

@BenHenning BenHenning assigned brijesh025 and unassigned BenHenning Jan 27, 2026
@brijesh025
Copy link
Author

@BenHenning I’ve added the App Version heading as you suggested. Earlier, I thought the heading might be redundant, which is why I hadn’t included it.

Could you please check the main header on the App Version screen as well and let me know if that looks fine?
image
I have updated the PR description please check that also.

@BenHenning
Copy link
Member

Thanks @brijesh025! I think it is a bit redundant for tablet view, but I think it's okay and looks good on the mobile view.

I have no other other concerns on the UI elements. I defer to @adhiamboperes on the code review and @swnmn for any follow-up design suggestions.

@swnmn
Copy link

swnmn commented Jan 29, 2026

Hi @BenHenning let's make note of it. We're working on the Android masterfile, after which I'd love to do an evaluation of where we are today and what screens make sense to refine and test (of course, after we address any backlogged priority tickets from users).

@BenHenning
Copy link
Member

Hi @BenHenning let's make note of it. We're working on the Android masterfile, after which I'd love to do an evaluation of where we are today and what screens make sense to refine and test (of course, after we address any backlogged priority tickets from users).

Sounds good @swnmn. I've filed oppia/design-team#212 to track.

@brijesh025
Copy link
Author

Hi @BenHenning,

Any updates regarding this PR? If any review or changes are required from my side, please let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request]: Add support for displaying the installation ID somewhere in the app

4 participants