{"id":271242,"date":"2025-02-18T03:55:32","date_gmt":"2025-02-18T03:55:32","guid":{"rendered":"https:\/\/michigandigitalnews.com\/index.php\/2025\/02\/18\/introducing-a-reliable-approach-to-time-keeping-for-your-apps\/"},"modified":"2025-06-25T17:09:20","modified_gmt":"2025-06-25T17:09:20","slug":"introducing-a-reliable-approach-to-time-keeping-for-your-apps","status":"publish","type":"post","link":"https:\/\/michigandigitalnews.com\/index.php\/2025\/02\/18\/introducing-a-reliable-approach-to-time-keeping-for-your-apps\/","title":{"rendered":"Introducing a reliable approach to time keeping for your apps"},"content":{"rendered":"<p> [ad_1]<br \/>\n<\/p>\n<div>\n<meta content=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEh0UZZO5-XiLRAFvsQtFzrCTgx3EVxc28LVd47UIJX6oGOe_dYepqtdEq_5Gfzh4flK1ce-OOXYlfs9NdqLshidZbqlxR-wj2XSESzOhMhlUltFAj2V5UDZHafKHdaiA-6G3MkwgWnly4pAL74Y04FA2nJ5xKy_l42TAwp6DLuf3Q_XeTxD9pWjwE7GI6Y\/s1600\/0023-Afd-Android%20_%20Trusted%20Time%20API%20Blog%20Assets_meta%20card.png\" name=\"twitter:image\"\/><br \/>\n<img decoding=\"async\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEh0UZZO5-XiLRAFvsQtFzrCTgx3EVxc28LVd47UIJX6oGOe_dYepqtdEq_5Gfzh4flK1ce-OOXYlfs9NdqLshidZbqlxR-wj2XSESzOhMhlUltFAj2V5UDZHafKHdaiA-6G3MkwgWnly4pAL74Y04FA2nJ5xKy_l42TAwp6DLuf3Q_XeTxD9pWjwE7GI6Y\/s1600\/0023-Afd-Android%20_%20Trusted%20Time%20API%20Blog%20Assets_meta%20card.png\" style=\"display: none;\"\/><\/p>\n<p><em>Posted by Kanyinsola Fapohunda \u2013 Software Engineer, and Geoffrey Boullanger \u2013 Technical Lead<\/em><\/p>\n<p><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhuc-0p88UHusJx-dKztBNDs5S7kpMNisco_cLqKzeSfMpVsPVJxTYsQI3Gdao_ep0ox1_AUpG5FFRMqEAfs6pW5NXtytBAWGAW617_eoPVo5Ya6sU3ValgUoURU-pG0OVQwGkXnvp6aRfqCaa20MC1ANWRKt7wLvKa3MzT2UgshiazAyvfXIpMgZfgy2Q\/s1600\/0023-Afd-Android%20_%20Trusted%20Time%20API%20Blog%20Assets_banner.png\"><img decoding=\"async\" border=\"0\" data-original-height=\"800\" data-original-width=\"100%\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhuc-0p88UHusJx-dKztBNDs5S7kpMNisco_cLqKzeSfMpVsPVJxTYsQI3Gdao_ep0ox1_AUpG5FFRMqEAfs6pW5NXtytBAWGAW617_eoPVo5Ya6sU3ValgUoURU-pG0OVQwGkXnvp6aRfqCaa20MC1ANWRKt7wLvKa3MzT2UgshiazAyvfXIpMgZfgy2Q\/s1600\/0023-Afd-Android%20_%20Trusted%20Time%20API%20Blog%20Assets_banner.png\"\/><\/a><\/p>\n<p>Accurate time is crucial for a wide variety of app functionalities, from scheduling and event management to transaction logging and security protocols. However, a user can change the device\u2019s time, so a more accurate source of time than the device\u2019s local system time may be required. That&#8217;s why we&#8217;re introducing the <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> API that leverages Google&#8217;s infrastructure to deliver a trustworthy timestamp, independent of the device&#8217;s potentially manipulated local time settings.<\/p>\n<h2><span style=\"font-size: x-large;\">How does TrustedTime work?<\/span><\/h2>\n<p>The new API leverages Google&#8217;s secure infrastructure to provide a trusted time source to your app. <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> periodically syncs its clock to <a href=\"https:\/\/developers.google.com\/time\" target=\"_blank\" rel=\"noopener\">Google&#8217;s servers<\/a>, which have access to a highly accurate time source, so that you do not need to make a server request every time you want to know the current network time. Additionally, we&#8217;ve integrated a unique model that calculates the device&#8217;s clock drift. This will inform you when the time may be inaccurate between network synchronizations.<\/p>\n<h2><span style=\"font-size: x-large;\">Why is an accurate source of time important?<\/span><\/h2>\n<p>Many apps rely on the device&#8217;s clock for various features. However, users can change their device&#8217;s time settings, either intentionally or unintentionally, therefore changing the time that your app gets. This can lead to problems such as:<\/p>\n<ul>\n<ul>\n<li><b>Data Inconsistency:<\/b> Apps relying on chronological event ordering are vulnerable to data corruption if users manipulate device time. <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> mitigates this risk by providing a trustworthy time source.<\/li>\n<\/ul>\n<ul>\n<li><b>Security Gaps:<\/b> Time-based security measures, like one-time passwords or timed access controls require an unaltered time source to be effective.<\/li>\n<\/ul>\n<ul>\n<li><b>Unreliable Scheduling:<\/b> Apps that depend on accurate scheduling, like calendar or reminder apps, can malfunction if the device clock (i.e. Unix timestamp) is incorrect.<\/li>\n<\/ul>\n<ul>\n<li><b>Inaccurate Time:<\/b> The device&#8217;s internal clock can drift due to various factors, such as temperature, doze mode, battery level, etc. This can lead to problems in applications that require more precision. The <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> API also provides the estimated error with the timestamps, so that you can ensure your app&#8217;s time-sensitive operations are performed correctly.<\/li>\n<\/ul>\n<ul>\n<li><b>Lack of Consistency Between Devices:<\/b> Inconsistent time across devices can cause problems in multi-device scenarios, such as gaming or collaborative applications. The <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span>  API helps ensure that all devices have a consistent view of time, improving the user experience.<\/li>\n<\/ul>\n<ul>\n<li><b>Unnecessary Power and Data Consumption:<\/b> <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> is designed to be more efficient than calling an NTP server every time an app needs the current time. It avoids the overhead of repeated network requests by periodically syncing its clock with time servers. This synced time is then used as a reference point, and the <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> API calculates the current time based on the device&#8217;s internal clock. This approach reduces network usage and improves performance for apps that need frequent time checks.<\/li>\n<\/ul>\n<\/ul>\n<h2><span style=\"font-size: x-large;\">TrustedTime Use Cases<\/span><\/h2>\n<p>The <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> API opens up a range of possibilities for enhancing the reliability and security of your apps, with use cases in areas such as:<\/p>\n<ul>\n<ul>\n<li><b>Financial Applications:<\/b> Ensure the accuracy of transaction timestamps even when the device is offline, preventing fraud and disputes.<\/li>\n<\/ul>\n<ul>\n<li><b>Gaming:<\/b> Implement fair play by preventing users from manipulating the game clock to gain an unfair advantage.<\/li>\n<\/ul>\n<ul>\n<li><b>Limited-Time Offers:<\/b> Guarantee that promotions and offers expire at the correct time, regardless of the user&#8217;s device settings.<\/li>\n<\/ul>\n<ul>\n<li><b>E-commerce:<\/b> Accurately track order processing and delivery times.<\/li>\n<\/ul>\n<ul>\n<li><b>Content Licensing:<\/b> Enforce time-based restrictions on digital content, like rentals or subscriptions.<\/li>\n<\/ul>\n<ul>\n<li><b>IoT Devices:<\/b> Synchronize clocks across multiple devices for consistent data logging and control.<\/li>\n<\/ul>\n<ul>\n<li><b>Productivity apps:<\/b> Accurately record the time of any changes made to cloud documents while offline.<\/li>\n<\/ul>\n<\/ul>\n<h2><span style=\"font-size: x-large;\">Getting started with the TrustedTime API<\/span><\/h2>\n<p>The <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> API is built on top of Google Play services, making integration seamless for most Android developers.<\/p>\n<p>The simplest way to integrate is to initialize the <span style=\"color: #0d904f; font-family: Courier;\">TrustedTimeClient<\/span> early in your app lifecycle, such as in the <span style=\"color: #0d904f; font-family: Courier;\">onCreate()<\/span> method of your Application class. The following example uses <a href=\"https:\/\/developer.android.com\/training\/dependency-injection\" target=\"_blank\" rel=\"noopener\">dependency injection<\/a> with Hilt to make the time client available to  components throughout the app.<\/p>\n<h3><span style=\"font-size: large;\">[Optional] Setup dependency injection<\/span><\/h3>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span style=\"color: #408080; font-style: italic;\">\/\/ TrustedTimeClientAccessor.kt<\/span>\nimport com.google.android.gms.tasks.Task\nimport com.google.android.gms.time.TrustedTimeClient\n\n<span style=\"color: green; font-weight: bold;\">interface<\/span> TrustedTimeClientAccessor {\n  <span style=\"color: green; font-weight: bold;\">fun<\/span> <span style=\"color: blue;\">createClient<\/span>(): Task<trustedtimeclient>\n}\n\n<span style=\"color: #408080; font-style: italic;\">\/\/ TrustedTimeModule.kt<\/span>\n@Module\n<span style=\"color: blue;\">@InstallIn<\/span>(SingletonComponent::class)\n<span style=\"color: green; font-weight: bold;\">class<\/span> <span style=\"color: blue; font-weight: bold;\">TrustedTimeModule<\/span> {\n  @Provides\n  <span style=\"color: green; font-weight: bold;\">fun<\/span> <span style=\"color: blue;\">provideTrustedTimeClientAccessor<\/span>(\n    @ApplicationContext context: Context\n  ): TrustedTimeClientAccessor {\n    <span style=\"color: green; font-weight: bold;\">return<\/span> object : TrustedTimeClientAccessor {\n      <span style=\"color: green; font-weight: bold;\">override<\/span> <span style=\"color: green; font-weight: bold;\">fun<\/span> <span style=\"color: blue;\">createClient<\/span>(): Task<trustedtimeclient> {\n        <span style=\"color: green; font-weight: bold;\">return<\/span> TrustedTime.createClient(context)\n      }\n    }\n  }\n}\n<\/trustedtimeclient><\/trustedtimeclient><\/pre>\n<\/div>\n<p><\/p>\n<h3><span style=\"font-size: large;\">Initialize early in your app&#8217;s lifecycle<\/span><\/h3>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span style=\"color: #408080; font-style: italic;\">\/\/ TrustedTimeDemoApplication.kt<\/span>\n@HiltAndroidApp\n<span style=\"color: green; font-weight: bold;\">class<\/span> <span style=\"color: blue; font-weight: bold;\">TrustedTimeDemoApplication<\/span> : Application() {\n\n  @Inject\n  lateinit <span style=\"color: green; font-weight: bold;\">var<\/span> trustedTimeClientAccessor: TrustedTimeClientAccessor\n\n  <span style=\"color: green; font-weight: bold;\">var<\/span> trustedTimeClient: TrustedTimeClient? = <span style=\"color: green; font-weight: bold;\">null<\/span>\n    <span style=\"color: green; font-weight: bold;\">private<\/span> <span style=\"color: green; font-weight: bold;\">set<\/span>\n\n  <span style=\"color: green; font-weight: bold;\">override<\/span> <span style=\"color: green; font-weight: bold;\">fun<\/span> <span style=\"color: blue;\">onCreate<\/span>() {\n    super.onCreate()\n    trustedTimeClientAccessor.createClient().addOnCompleteListener { task -&gt;\n      <span style=\"color: green; font-weight: bold;\">if<\/span> (task.isSuccessful) {\n        <span style=\"color: #408080; font-style: italic;\">\/\/ Stash the client<\/span>\n        trustedTimeClient = task.result\n      } <span style=\"color: green; font-weight: bold;\">else<\/span> {\n        <span style=\"color: #408080; font-style: italic;\">\/\/ Handle error, maybe retry later<\/span>\n        <span style=\"color: green; font-weight: bold;\">val<\/span> exception = task.exception\n      }\n    }\n    <span style=\"color: #408080; font-style: italic;\">\/\/ To use Kotlin Coroutine, you can use the await() method, <\/span>\n    <span style=\"color: #408080; font-style: italic;\">\/\/ see https:\/\/developers.google.com\/android\/guides\/tasks#kotlin_coroutine for more info.<\/span>\n  }\n}\n\nNOTE: If you don't use dependency injection <span style=\"color: green; font-weight: bold;\">in<\/span> your app. You can simply call\n`TrustedTime.createClient(context)` instead of <span style=\"color: green; font-weight: bold;\">using<\/span> <span style=\"color: blue; font-weight: bold;\">a<\/span> TrustedTimeClientAccessor.\n<\/pre>\n<\/div>\n<p><\/p>\n<h3><span style=\"font-size: large;\">Use TrustedTimeClient anywhere in your app<\/span><\/h3>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span style=\"color: #408080; font-style: italic;\">\/\/ Retrieve the TrustedTimeClient from your application class<\/span>\n  <span style=\"color: green; font-weight: bold;\">val<\/span> myApp = applicationContext <span style=\"color: green; font-weight: bold;\">as<\/span> TrustedTimeDemoApplication\n\n  <span style=\"color: #408080; font-style: italic;\">\/\/ In this example, System.currentTimeMillis() is used as a fallback if the<\/span>\n  <span style=\"color: #408080; font-style: italic;\">\/\/ client is null (i.e. client creation task failed) or when there is no time<\/span>\n  <span style=\"color: #408080; font-style: italic;\">\/\/ signal available. You may not want to do this if using the system clock is<\/span>\n  <span style=\"color: #408080; font-style: italic;\">\/\/ not suitable for your use case.<\/span>\n  <span style=\"color: green; font-weight: bold;\">val<\/span> currentTimeMillis =\n    myApp.trustedTimeClient?.computeCurrentUnixEpochMillis()\n        ?: System.currentTimeMillis()\n  <span style=\"color: #408080; font-style: italic;\">\/\/ trustedTimeClient.computeCurrentInstant() can be used if Instant is<\/span>\n  <span style=\"color: #408080; font-style: italic;\">\/\/ preferred to long for Unix epoch times and you are able to use the APIs.<\/span>\n<\/pre>\n<\/div>\n<h3><span style=\"font-size: large;\">Use in short-lived components like Activity<\/span><\/h3>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\">@AndroidEntryPoint\n<span style=\"color: green; font-weight: bold;\">class<\/span> <span style=\"color: blue; font-weight: bold;\">MainActivity<\/span> : AppCompatActivity() {\n  @Inject\n  lateinit <span style=\"color: green; font-weight: bold;\">var<\/span> trustedTimeAccessor: TrustedTimeAccessor\n\n   <span style=\"color: green; font-weight: bold;\">private<\/span> <span style=\"color: green; font-weight: bold;\">var<\/span> trustedTimeClient: TrustedTimeClient? = <span style=\"color: green; font-weight: bold;\">null<\/span>\n\n  <span style=\"color: green; font-weight: bold;\">override<\/span> <span style=\"color: green; font-weight: bold;\">fun<\/span> <span style=\"color: blue;\">onCreate<\/span>(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n    ...\n    trustedTimeAccessor.createClient().addOnCompleteListener { task -&gt;\n      <span style=\"color: green; font-weight: bold;\">if<\/span> (task.isSuccessful) {\n          <span style=\"color: #408080; font-style: italic;\">\/\/ Stash the client<\/span>\n          trustedTimeClient = task.result\n        } <span style=\"color: green; font-weight: bold;\">else<\/span> {\n         <span style=\"color: #408080; font-style: italic;\">\/\/ Handle error, maybe retry later or use another time source.<\/span>\n          <span style=\"color: green; font-weight: bold;\">val<\/span> exception = task.exception\n        }\n    }\n  }\n\n  <span style=\"color: green; font-weight: bold;\">private<\/span> <span style=\"color: green; font-weight: bold;\">fun<\/span> <span style=\"color: blue;\">getCurrentTimeInMillis<\/span>() : Long? {\n    <span style=\"color: green; font-weight: bold;\">return<\/span> trustedTimeClient?.computeCurrentUnixEpochMillis()\n  }\n}\n<\/pre>\n<\/div>\n<h2><span style=\"font-size: x-large;\">TrustedTime API availability and limitations<\/span><\/h2>\n<p>The <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> API is available on all devices running Google Play services on Android 5 (Lollipop) and above. You need to add the dependency <span style=\"color: #0d904f; font-family: Courier;\">com.google.android.gms:play-services-time:16.0.1<\/span> (or above) to access the new API. No additional permission is required to use this API. However, <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> needs an internet connection after the device starts up to provide timestamps. If the device hasn&#8217;t connected to the internet since booting, the <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> APIs won&#8217;t return timestamps.<\/p>\n<p>It\u2019s important to note that the device&#8217;s internal clock can drift due to factors like temperature, doze mode, and battery level. <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> doesn&#8217;t prevent this drift, but its APIs provide an error estimate for each timestamp. Use this estimate to determine if the timestamp&#8217;s accuracy meets your application&#8217;s requirements. While <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> makes it more difficult for users to manipulate the time accessed by your app, it does not guarantee complete safety. Advanced techniques can still be used to tamper with the device\u2019s time.<\/p>\n<h2><span style=\"font-size: x-large;\">Next steps<\/span><\/h2>\n<p>To learn more about the <span style=\"color: #0d904f; font-family: Courier;\">TrustedTime<\/span> API, check out the following resources:<\/p>\n<\/div>\n<p>[ad_2]<br \/>\n<br \/><a href=\"http:\/\/android-developers.googleblog.com\/2025\/02\/trustedtime-api-introducing-reliable-approach-to-time-keeping-for-apps.html\">Source link <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>[ad_1] Posted by Kanyinsola Fapohunda \u2013 Software Engineer, and Geoffrey Boullanger \u2013 Technical Lead Accurate time is crucial for a wide variety of app functionalities,<\/p>\n","protected":false},"author":1,"featured_media":271243,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[146],"tags":[],"_links":{"self":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts\/271242"}],"collection":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/comments?post=271242"}],"version-history":[{"count":0,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts\/271242\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/media\/271243"}],"wp:attachment":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/media?parent=271242"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/categories?post=271242"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/tags?post=271242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}