<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">
	<channel>
		<title>Author at Infinum</title>
		<atom:link href="https://infinum.com/blog/author/ivan-kocijan/feed/" rel="self" type="application/rss+xml" />
		<link></link>
		<description>Building digital products</description>
		<lastBuildDate>Tue, 14 Apr 2026 10:32:35 +0000</lastBuildDate>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>

					<item>
				<image>
					<url>7984https://infinum.com/uploads/2021/03/unescaping-special-characters-0.webp</url>
				</image>
				<title>Unescaping Special Characters in Android Applications</title>
				<link>https://infinum.com/blog/unescaping-special-characters/</link>
				<pubDate>Fri, 26 Mar 2021 10:45:00 +0000</pubDate>
				<dc:creator>Ivan Kocijan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/unescaping-special-characters/</guid>
				<description>
					<![CDATA[<p>Try these two approaches if you need to escape strings.</p>
<p>The post <a href="https://infinum.com/blog/unescaping-special-characters/">Unescaping Special Characters in Android Applications</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-158"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-92">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-95"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-93">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-94'
	>
	Android being a client-side platform, developers deal with many different APIs on a daily basis. Some of these APIs are great, some of them not really, but we can work with anything that a backend sends us.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-98"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-96">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-97'
	>
	A while ago, we had an atypical request from our backend developers. They asked us to unescape every string in the app.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-101"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-99">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-100'
	>
	This meant that the strings from the backend would contain special characters which we needed to replace. For example, &amp; sign would be &amp;amp;, apostrophe would be &amp;apos; and so on. It was atypical because it’s not often that developers handle such a case in mobile apps. We make an API call and show the string which came from the backend as is.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-104"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-102">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-103'
	>
	Why unescape special characters?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-107"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-105">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-106'
	>
	Although strange at first, the backend guys had a good reason for this. They were developing a platform which can be used by anyone, not only the Android application.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-110"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-108">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-109'
	>
	Other frontend clients could add items to the platform and they didn’t have control over how they would do it. In order to minimize cross-site scripting (XSS) vulnerability, they sanitized strings saved to the backend and they wanted to be sure they don’t send back anything exploitable.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-113"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-111">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-112'
	>
	Another reason why you would want to do this is to save the formatting of a string backend sends. If you want to show a multiline string, then you would format the string so it’s shown as expected.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-116"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-114">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-115'
	>
	Unescaping special characters for every string</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-119"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-117">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-118'
	>
	If your backend escapes every string it returns, you need a method to unescape them all in one place. In Android, if you use Moshi, you can do it by defining an application-wide serializer for the String class.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-121"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">class StringSerializer</span><span class="token">() </span><span class="token">: </span><span class="token" style="color: #6f42c1;">JsonAdapter</span><span class="token">&lt;</span><span class="token" style="color: #6f42c1;">String</span><span class="token">&gt;</span><span class="token">() {
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun fromJson</span><span class="token">(reader</span><span class="token">: </span><span class="token" style="color: #6f42c1;">JsonReader</span><span class="token">)</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">? </span><span class="token">{
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Unescape characters</span><span class="token">
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6f42c1;">@Throws</span><span class="token">(IOException</span><span class="token">::</span><span class="token" style="color: #6f42c1;">class</span><span class="token">)
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun toJson</span><span class="token">(writer</span><span class="token">: </span><span class="token" style="color: #6f42c1;">JsonWriter</span><span class="token">, </span><span class="token" style="color: #d73a49;">value</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">?</span><span class="token">) {
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Escape characters or do nothing </span><span class="token">
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-124"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-122">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-123'
	>
	Then add the serializer when defining Moshi.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-126"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">Moshi</span><span class="token">.Builder</span><span class="token">()</span><span class="token">.add</span><span class="token">(String</span><span class="token">::</span><span class="token" style="color: #6f42c1;">class</span><span class="token">.java, </span><span class="token">StringSerializer</span><span class="token">())
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-129"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-127">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-128'
	>
	If you initialize Moshi in one place and use the same instance across the app all your strings will be unescaped and your work is done.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-132"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-130">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-131'
	>
	Unescaping special characters for certain strings</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-135"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-133">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-134'
	>
	Sometimes, you might need to unescape special characters only for certain strings in the app. If this is your case, you can do this by defining an annotation which will be used only on those strings.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-137"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Retention</span><span class="token">(AnnotationRetention.RUNTIME)
</span></span><span class="line"><span class="token" style="color: #6f42c1;">@JsonQualifier</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">annotation</span><span class="token"> </span><span class="token">class Escaped
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-140"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-138">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-139'
	>
	Then, create a serializer and annotate the fromJson method and toJson parameter.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-142"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">class EscapedStringSerializer</span><span class="token">() {
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6f42c1;">@FromJson</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6f42c1;">@Escaped</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">fun fromJson</span><span class="token">(reader</span><span class="token">: </span><span class="token" style="color: #6f42c1;">JsonReader</span><span class="token">)</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token"> </span><span class="token">{
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Unescape special characters</span><span class="token">
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6f42c1;">@ToJson</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6f42c1;">@Throws</span><span class="token">(IOException</span><span class="token">::</span><span class="token" style="color: #6f42c1;">class</span><span class="token">)
</span></span><span class="line"><span class="token">    </span><span class="token">fun toJson</span><span class="token">(</span><span class="token" style="color: #6f42c1;">@Escaped</span><span class="token"> </span><span class="token" style="color: #d73a49;">value</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">?</span><span class="token">) </span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token"> </span><span class="token">{
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;"> Escape special characters or do nothing</span><span class="token">
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-145"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-143">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-144'
	>
	After defining the annotation and serializer you can annotate any escaped string in your models.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-147"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">class MyClass </span><span class="token">(</span><span class="token" style="color: #6f42c1;">@Escaped</span><span class="token"> </span><span class="token" style="color: #6f42c1;">@Json</span><span class="token">(name </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">description</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">) </span><span class="token">val </span><span class="token">description</span><span class="token">: </span><span class="token" style="color: #6f42c1;">String</span><span class="token">) 
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-150"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-148">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-149'
	>
	Is unescaping for me?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-153"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-151">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-152'
	>
	Unless you load strings in a WebView, you probably don’t have a problem with XSS in your Android app.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-156"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-154">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-155'
	>
	In most cases, mobile apps get a string from an API and show it in a TextView. However, if you really need to escape strings, it’s good to know you can use one of these two approaches.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/unescaping-special-characters/">Unescaping Special Characters in Android Applications</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>7966https://infinum.com/uploads/2020/12/secrets-android-projects-0.webp</url>
				</image>
				<title>Keeping Secrets Safe in Android Projects</title>
				<link>https://infinum.com/blog/secrets-android-projects/</link>
				<pubDate>Mon, 21 Dec 2020 15:40:00 +0000</pubDate>
				<dc:creator>Mladen Rakonjac</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/secrets-android-projects/</guid>
				<description>
					<![CDATA[<p>You can never be too cautious with your secrets.</p>
<p>The post <a href="https://infinum.com/blog/secrets-android-projects/">Keeping Secrets Safe in Android Projects</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-283"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-159">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-162"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-160">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-161'
	>
	My Cryptography course professor used to say: “Nothing is 100% secure. Even if you go to the farthest place to hide the key for a safe, there is still a small percentage of probability that somebody will find it”.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-165"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-163">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-164'
	>
	Making something more secure actually means making sure that percentage is as low as possible.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-168"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-166">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-167'
	>
	What can we do to make secrets more secure in Android projects?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-171"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-169">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-170'
	>
	The secret in Android projects can be an API key, Keystore, credentials for publishing, credentials for some special access to the 3rd party SDK, etc. If we want to secure a secret in an Android project, we usually ignore it in Git. When somebody new jumps into the project, those ignored files should be added manually.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-174"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-172">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-173'
	>
	Usually, secrets, like credentials, are inside the <code>build.gradle</code> file because they are environment-specific. For simplicity, let’s say that we have an environment called <code>preproduction</code> in which we have credentials to log in automatically into the application tapping on the login button multiple times.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-177"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-175">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-176'
	>
	This environment acts the same as <code>production</code> plus this log in automatically feature. This is good to have for fast internal testing in the <code>production</code> environment before production release. However, this secret should never be visible in the final production apk. For simplicity, let’s say that we have <code>CREDENTIALS</code> that we use only in the preproduction environment.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-180"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-178">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-179'
	>
	We can add it to the <code>build.gradle</code> file:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-182"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-groovy github-light" data-language="groovy" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">defaultConfig </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">    resValue </span><span class="token" style="color: #005cc5;">RES_STRING</span><span class="token">, ‘</span><span class="token" style="color: #005cc5;">CREDENTIALS_USERNAME</span><span class="token">’,’’
</span></span><span class="line"><span class="token">    resValue </span><span class="token" style="color: #005cc5;">RES_STRING</span><span class="token">, ‘</span><span class="token" style="color: #005cc5;">CREDENTIALS_PASSWORD</span><span class="token">’,’’
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">productFlavors </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    preproduction </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">            resValue </span><span class="token" style="color: #005cc5;">RES_STRING</span><span class="token">, ‘</span><span class="token" style="color: #005cc5;">CREDENTIALS_USERNAME</span><span class="token">’,’mladen’
</span></span><span class="line"><span class="token">            resValue </span><span class="token" style="color: #005cc5;">RES_STRING</span><span class="token">, ‘</span><span class="token" style="color: #005cc5;">CREDENTIALS_PASSWORD</span><span class="token">’,’str0ngP4ssw0rd’
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-185"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-183">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-184'
	>
	When we build the project, the credentials strings are located in <code>gradleResValues.xml</code> and we can access them using <code>@string/</code> in XML files or <code>getString</code> function in Kotlin/Java classes as we do for any other string from resources.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-188"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-186">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-187'
	>
	The<code>build.gradle</code> file should not be ignored in the version-control system cause all developers in the team should have the same version. With the current implementation, <code>‘CREDENTIALS_USERNAME’</code> and <code>‘CREDENTIALS_PASSWORD’</code> as part of the <code>build.gradle</code> file, will be included in git. This is not safe.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-191"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-189">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-190'
	>
	We want to make it more secure, so if somebody gets access to the repository that person should not get access to our production credentials.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-194"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-192"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-193">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2020/12/secrets-android-projects-1-1400x349.webp				media='(max-width: 699px)'
				type=image/webp								height="349"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2020/12/secrets-android-projects-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="390"
															width="1566"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-197"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-195">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-196'
	>
	To avoid that, we can store this key in the local.properties file:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-199"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-groovy github-light" data-language="groovy" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #005cc5;">CREDENTIALS_USERNAME</span><span class="token" style="color: #d73a49;">=</span><span class="token">mladen
</span></span><span class="line"><span class="token" style="color: #005cc5;">CREDENTIALS_PASSWORD</span><span class="token" style="color: #d73a49;">=</span><span class="token">str0ngP4ssw0rd
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-202"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-200">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-201'
	>
	The local.properties file should not be included in the version-control system.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-205"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-203">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-204'
	>
	To make keys from <code>local.properties</code> accessible in <code>build.gradle</code> we can add the following function:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-207"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-groovy github-light" data-language="groovy" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">def getLocalProperties() {
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">Properties</span><span class="token"> </span><span class="token">props</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #d73a49;">new</span><span class="token"> </span><span class="token" style="color: #d73a49;">Properties</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">if</span><span class="token"> </span><span class="token">(</span><span class="token">file</span><span class="token">(</span><span class="token">’</span><span class="token" style="color: #d73a49;">..</span><span class="token" style="color: #d73a49;">/</span><span class="token">local</span><span class="token" style="color: #d73a49;">.</span><span class="token">properties’</span><span class="token">)</span><span class="token" style="color: #d73a49;">.</span><span class="token">ex</span><span class="token">i</span><span class="token">sts</span><span class="token">(</span><span class="token">)</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        props</span><span class="token" style="color: #d73a49;">.</span><span class="token">load</span><span class="token">(</span><span class="token" style="color: #d73a49;">new</span><span class="token"> </span><span class="token" style="color: #d73a49;">FileInputStream</span><span class="token">(</span><span class="token">file</span><span class="token">(</span><span class="token">’</span><span class="token" style="color: #d73a49;">..</span><span class="token" style="color: #d73a49;">/</span><span class="token">local</span><span class="token" style="color: #d73a49;">.</span><span class="token">properties’</span><span class="token">)</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">return</span><span class="token"> props
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-210"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-208">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-209'
	>
	Next, we should create a build config field this way:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-212"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-groovy github-light" data-language="groovy" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">preproduction </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">Properties</span><span class="token"> localProperties </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">getLocalProperties</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">    resValue </span><span class="token" style="color: #005cc5;">RES_STRING</span><span class="token">, ‘</span><span class="token" style="color: #005cc5;">CREDENTIALS_USERNAME</span><span class="token">’, localProperties</span><span class="token">[</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">CREDENTIALS_USERNAME</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="token">    resValue </span><span class="token" style="color: #005cc5;">RES_STRING</span><span class="token">, ‘</span><span class="token" style="color: #005cc5;">CREDENTIALS_PASSWORD</span><span class="token">’, localProperties</span><span class="token">[</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">CREDENTIALS_PASSWORD</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-215"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-213">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-214'
	>
	How will CI know about this secret?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-218"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-216">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-217'
	>
	At Infinum, we switched from <a href="https://infinum.com/blog/bitrise-vs-circleci-for-android-in-a-head-to-head-battle/">CircleCI to Bitrise</a>, so in this blog post, I’ll show you how to do this on Bitrise, but it’s similar to any other CI.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-221"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-219">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-220'
	>
	We should copy the key from our local.properties file and add it inside Bitrise Secret ( Project -&gt; Workflow -&gt; Secrets -&gt; Add New). Let’s name it <code>CREDENTIALS_USERNAME</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-224"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-222">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-223'
	>
	Next, we should change build config field:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-226"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">
</span></span><span class="line"><span class="token">resValue RES_STRING, ‘CREDENTIALS_USERNAME’, System</span><span class="token">.getenv</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">CREDENTIALS_USERNAME</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">) ?: project.properties[</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">CREDENTIALS_USERNAME</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">]
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-229"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-227">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-228'
	>
	If we run the build on CI, it will get <code>CREDENTIALS_USERNAME</code> from Secrets, if we run it locally it will get <code>API_KEY</code> from <code>local.properties</code> file.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-232"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-230">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-231'
	>
	What if we want to have a special credentials.properties file with all API keys?</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-235"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-233">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-234'
	>
	If we want to separate API keys from other properties in the <code>local.properties</code> file, we can create a new <code>credentials.properties</code> file. Moreover, instead of storing key by key in Bitrise Secrets, we can store the whole content of the<code>credentials.properties</code> file in one Bitrise secret called <code>CREDENTIALS_PROPERTIES</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-238"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-236">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-237'
	>
	Then, we can make a special workflow step that will create credentials.properties file and fill it with data stored in Bitrise Secret. That step should be called before any other step.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-241"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-239"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-240">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2020/12/secrets-android-projects-2-1400x261.webp				media='(max-width: 699px)'
				type=image/webp								height="261"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2020/12/secrets-android-projects-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="298"
															width="1600"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-244"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-242">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-243'
	>
	A script could be made as follows:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-246"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-shellscript github-light" data-language="shellscript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">set</span><span class="token"> </span><span class="token" style="color: #005cc5;">-</span><span class="token" style="color: #005cc5;">e</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #005cc5;">echo</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">$</span><span class="token" style="color: #032f62;">{</span><span class="token" style="color: #24292e;">CREDENTIALS_PROPERTIES</span><span class="token" style="color: #032f62;">}</span><span class="token" style="color: #032f62;">&quot;</span><span class="token"> </span><span class="token" style="color: #d73a49;">&gt;</span><span class="token"> </span><span class="token" style="color: #032f62;">credentials.properties</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-249"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-247">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-248'
	>
	In that case, we should have only the following, without fetching the key from the system envs.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-251"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-groovy github-light" data-language="groovy" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">resValue </span><span class="token" style="color: #005cc5;">RES_STRING</span><span class="token">, ‘</span><span class="token" style="color: #005cc5;">CREDENTIALS_USERNAME</span><span class="token">’, project</span><span class="token" style="color: #d73a49;">.</span><span class="token">properties</span><span class="token">[</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">CREDENTIALS_USERNAME</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-254"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-252">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-253'
	>
	You can choose one of the two approaches depending on what works for you.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-257"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-255">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-256'
	>
	Sharing secrets between team members with Vault</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-260"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-258">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-259'
	>
	Adding secrets to the CI is a one-time thing. You add them and you won’t change them ever, but what if you need to share them with your colleagues? It’s possible to use a password manager, but when someone joins the project, they have to add a new file and copy-paste the credentials. If you have a lot of them, this can be tedious.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-263"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-261">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-262'
	>
	A better way to share secrets is by using <a href="https://www.vaultproject.io/">Vault</a>. This tool enables you to have secrets for all your projects in one place. It has a command-line tool, so you can integrate it with your continuous integration script. That way, you do not expose secrets on your CI as they will be fetched only when you need them.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-266"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-264">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-265'
	>
	Any colleague who joins the project can have access to the Vault and will be able to fetch all or only one secret.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-269"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-267">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-268'
	>
	There are other tools that you can use instead of Vault, but the idea is the same. You have one tool which will help you share those secrets with your team.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-272"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-270">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-271'
	>
	Is this secure enough?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-275"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-273">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-274'
	>
	If someone wants to, they can still do reverse engineering of the apk file and find keys, so it is really important what you have in a final production apk. If somebody gets access to the repository, credentials that are not included in the final production apk but are used during the development should not be exposed to that person.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-278"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-276">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-277'
	>
	Also, it is really important that those apks for preproduction environment will be stored in some internal host.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-281"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-279">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-280'
	>
	This was just one example of how we make Android projects more secure. In the end, everything is vulnerable, but we should try to make it harder for the bad guys. By introducing more layers of security, we reduce the vulnerability.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/secrets-android-projects/">Keeping Secrets Safe in Android Projects</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>7963https://infinum.com/uploads/2020/11/google-in-app-updates-0.webp</url>
				</image>
				<title>Implementing Google&#039;s New In-App Updates</title>
				<link>https://infinum.com/blog/google-in-app-updates/</link>
				<pubDate>Tue, 27 Oct 2020 13:25:00 +0000</pubDate>
				<dc:creator>Ivan Kocijan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/google-in-app-updates/</guid>
				<description>
					<![CDATA[<p>The good and the bad of in-app updates, and tackling those issues using our open-source libraries for update handling.</p>
<p>The post <a href="https://infinum.com/blog/google-in-app-updates/">Implementing Google&#039;s New In-App Updates</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-430"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-284">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-287"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-285">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-286'
	>
	Keeping all your users updated with your latest features can be tricky business.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-290"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-288">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-289'
	>
	At the moment, Google Play’s updates can be unreliable as they depend on the users to update the app independently most of the time. However, recent updates, like Google’s in-app updates, are planning to change that.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-293"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-291">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-292'
	>
	This article will explore the benefits and drawbacks of in-app updates and how we are tackling mentioned issues using one of our open-source libraries for handling updates, <a href="https://github.com/infinum/Android-Prince-of-Versions">Prince of Versions</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-296"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-294">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-295'
	>
	What are Google’s in-app updates?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-299"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-297">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-298'
	>
	In an effort to change the current way of handling things, Google revealed a brand new way of handling updates at its I/O event last year. This concept was innovatively named Google’s in-app updates and brought us a lot of requested changes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-302"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-300">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-301'
	>
	So, what are the new changes?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-305"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-303">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-304'
	>
	Firstly, as the name suggests, updates are now more interactive. Users will be notified in the application about an available update on the Google Play store (hence the name).</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-308"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-306">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-307'
	>
	Furthermore, there is now one crucial distinction between updates. An update can be classified as flexible or as immediate, depending on various factors determined by developers or the Google Play store. The major difference between these two is the way the update is going to be handled.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-311"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-309">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-310'
	>
	On the one hand, the flexible update, recognizable by its specific UI, allows the user to keep using the application while the update is downloading in the background. Because of this, the flexible update is usually used for smaller updates, like adding a neat feature or some other non-essential bugfix.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-314"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-312">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-313'
	>
	In contrast, the immediate update is primarily used for essential app updates. Without these updates, applications probably won’t work the way they are supposed to for some or all users. Because of this, UI on immediate updates will be blocking, meaning that users won’t be able to continue using the application while the update is being downloaded and installed.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-317"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-315">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-316'
	>
	All in all, it is noticeable that this update from Google brought us some highly desirable changes that will make the entire updating process easier and more fluid for the user. Also, with Google providing its UI and handling the update, the updating process will be easier for developers, too.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-320"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-318">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-319'
	>
	How to use Google’s in-app updates, and what are the drawbacks?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-323"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-321">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-322'
	>
	Following that compellingly positive introduction, it’s time to show how to use Google’s in-app updates and what are its disadvantages.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-326"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-324">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-325'
	>
	For starters, using this new update mechanism requires the Play Core library. Furthermore, this library requires API level 21 or higher, so devices below that limit won’t be able to use it. The Play Core library offers all the mentioned benefits, meaning that after adding this library as a dependency, you are ready to go!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-329"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-327">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-328'
	>
	Checking for an update</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-332"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-330">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-331'
	>
	We must begin by demonstrating how you are going to check if there is an update on the Google Play Store. The code for doing that is simple and it looks like so:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-334"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">val </span><span class="token">updateManager </span><span class="token" style="color: #d73a49;">=</span><span class="token"> AppUpdateManagerFactory</span><span class="token">.create</span><span class="token">(</span><span class="token" style="color: #005cc5;">this</span><span class="token">)
</span></span><span class="line"><span class="token">updateManager.appUpdateInfo</span><span class="token">.addOnSuccessListener </span><span class="token">{
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">if</span><span class="token"> (it</span><span class="token">.updateAvailability</span><span class="token">() </span><span class="token" style="color: #d73a49;">==</span><span class="token"> UpdateAvailability.UPDATE_AVAILABLE </span><span class="token" style="color: #d73a49;">&amp;&amp;</span><span class="token">
</span></span><span class="line"><span class="token">      it</span><span class="token">.isUpdateTypeAllowed</span><span class="token">(AppUpdateType.IMMEDIATE)) {
</span></span><span class="line"><span class="token">      }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-337"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-335">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-336'
	>
	The process begins by creating an instance of AppUpdateManager. This instance will be in charge of handling all of the update information and the flow. Within that instance, there is a method to get AppUpdateInfo task that will supply us with all the necessary information about the update state. One of the typical usages of AppUpdateInfo is checking update availability and whether that kind of update is allowed.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-340"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-338">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-339'
	>
	Now is the time to discuss the first and only shortcoming we have identified using this new library.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-343"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-341">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-342'
	>
	Essentially, at the moment of writing this, the Google Play Store offers limited means of action by which we could manually set what kind of update we are looking for. In other words, Google’s API is currently not entirely user-friendly, as it doesn’t allow publishers to easily specify update type per application version in the release track. This system could result in a possibly painful adjustment because, for the time being, Google doesn’t offer a better way of handling this matter.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-346"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-344">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-345'
	>
	Starting the update flow</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-349"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-347">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-348'
	>
	After checking, depending on update availability, we can continue with the invocation of the update. To invoke the update flow, we use the following code:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-351"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">updateManager</span><span class="token">.startUpdateFlowForResult</span><span class="token">(
</span></span><span class="line"><span class="token">  appUpdateInfo,
</span></span><span class="line"><span class="token">  AppUpdateType.IMMEDIATE, 
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #005cc5;">this</span><span class="token">,
</span></span><span class="line"><span class="token">    REQUEST_CODE_UPDATE)
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-354"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-352">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-353'
	>
	As we can see from the code snippet above, the AppUpdateManager invokes the update flow. To invoke it, we need to pass a couple of parameters.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-357"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-355">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-356'
	>
	Firstly, we are passing appUpdateInfo, which is Google’s object that we got from the update check itself. Moreover, we are sending some application-related parameters like the current activity and the request code to monitor the update process later. Lastly, there is AppUpdateType.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-360"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-358">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-359'
	>
	With this parameter, we are ultimately deciding on what kind of update we will invoke on users’ phones. That means that just by knowing what kind of an update we have on Google Play Store, we can “ask” Google for it through this parameter.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-363"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-361">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-362'
	>
	Currently, Google only allows for priority change per release, whereas naturally, developers would welcome the ability to change priority per version. For this inconvenience, we can use this mentioned parameter to our advantage.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-366"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-364">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-365'
	>
	Our solution was to find a way of knowing what kind of update we are putting on the Google Play Store. If we know what kind of update we are putting there, we can “ask” Google for it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-369"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-367">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-368'
	>
	In other words, we will know exactly what update is there on Google Play Store, and by knowing it, we are going to invoke that kind of update through the AppUpdateManager instance.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-372"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-370">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-371'
	>
	Now how exactly are we going to do that? With Prince of Versions.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-375"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-373">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-374'
	>
	Prince of Versions == Solution?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-378"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-376">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-377'
	>
	<a href="https://github.com/infinum/Android-Prince-of-Versions">Prince of Versions</a> is an open-source library for practical and easy update handling. It was created a few years ago, with the desire for an improved way to classify updates.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-381"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-379">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-380'
	>
	As mentioned, Google’s past way of handling updates was not satisfying because it relied too much on the user. As a partial solution to this, Google presented its new in-app way of handling updates. Nevertheless, as we saw, it still has a few significant issues.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-384"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-382">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-383'
	>
	In our pursuit of an ideal combination of Google’s fancy UI and Prince of Versions’ reliable update handling, we have decided to merge these two into the latest Prince of Versions sibling: Queen of Versions.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-387"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-385">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-386'
	>
	So, how will Queen of Versions solve Google’s issues?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-390"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-388">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-389'
	>
	Firstly, we need to understand how the Prince of Versions operates. It works by fetching the JSON file and then parsing it to retrieve all the necessary details about the current update. The details comprise of information like the latest application version, minimum required version, and any additional data that we would need.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-393"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-391">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-392'
	>
	Example of the JSON file:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-395"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-json github-light" data-language="json" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">android</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">: </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">required_version</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">12</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">last_version_available</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">12</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">notify_last_version_frequency</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">ONCE</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-398"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-396">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-397'
	>
	Afterward, Prince starts the update classification process. It begins by making several comparisons between extracted JSON values, and it finishes with one of three classification outcomes – required (immediate), new (flexible), or no update. The code for starting that process is nicely explained here.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-401"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-399">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-400'
	>
	There, we can notice a similarity with new Google’s in-app updates. Their main feature is the latest update classification. However, this is also Google’s most significant shortcoming. To reiterate, Google currently doesn’t offer an easy way of specifying update type per application version in the release track.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-404"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-402">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-403'
	>
	The proposed solution</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-407"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-405">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-406'
	>
	To begin with, we have to push our latest update on Google Play. In the meantime, all the update information should be accessible through the JSON file somewhere on the internet. This step usually consists of just writing some new numbers in the JSON and uploading it somewhere on the internet ( e.g. your server/API/any public domain ). This last step ends our job outside of the application.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-410"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-408">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-409'
	>
	Inside the application, we begin by utilizing Prince’s ability to acquire update information from a JSON file. Thus, with Prince’s help, we have all the essential information about an update which is also on the Google Play Store at that same moment.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-413"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-411">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-412'
	>
	In other words, we know precisely whether the update is required or optional. With that knowledge, we can “ask” Google for precisely what we want. Finally, we proceed by requesting the desired type of update with Google’s Play Core API.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-416"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-414">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-415'
	>
	In a nutshell, that is it – we have successfully bypassed Google’s complicated API and created a simplistic way of specifying the right kind of an update.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-419"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-417">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-418'
	>
	Naturally, there is a lot more to this story. <a href="https://github.com/infinum/Android-Prince-of-Versions">We have created a rich library</a> with a user-friendly API that offers a bundle of update handling customization and runs on top of this latest Google’s in-app update.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-422"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-420">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-421'
	>
	A step towards the desired way of handling updates on Android</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-425"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-423">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-424'
	>
	Overall, Google’s in-app updates are the right step toward the desired way of handling updates on Android. Certainly, there is still a lot of room for improvement, as there are some drawbacks to the current practice of handling things.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-428"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-426">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-427'
	>
	If you favor the simplistic update handling and want to try something different, feel free to try out our <a href="https://github.com/infinum/Android-Prince-of-Versions#queen-of-versions–">Queen of Versions</a> and let us know your feedback. Whether you love it or if there is something else you would like to see in our next update, please let us know.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/google-in-app-updates/">Implementing Google&#039;s New In-App Updates</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>8091https://infinum.com/uploads/2017/03/make-sure-users-have-the-latest-app-version-installed-0.webp</url>
				</image>
				<title>Make Sure Your Users Have the Latest App Version Installed</title>
				<link>https://infinum.com/blog/make-sure-users-have-the-latest-app-version-installed/</link>
				<pubDate>Mon, 06 Mar 2017 18:40:00 +0000</pubDate>
				<dc:creator>Ivan Kocijan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/make-sure-users-have-the-latest-app-version-installed/</guid>
				<description>
					<![CDATA[<p>In today’s mobile ecosystem it&#8217;s easy to publish an updated version of your application. Making sure users download it is more difficult. </p>
<p>The post <a href="https://infinum.com/blog/make-sure-users-have-the-latest-app-version-installed/">Make Sure Your Users Have the Latest App Version Installed</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-523"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-431">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-434"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-432">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-433'
	>
	In today’s mobile ecosystem it’s easy to publish an updated version of your application. Making sure users download it is more difficult. Google and Apple provide notifications via their app stores, but more often than not, users tend to ignore them.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-437"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-435"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-436">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/03/make-sure-users-have-the-latest-app-version-installed-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="600"
															width="1000"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-440"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-438">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-439'
	>
	You can argue that it’s the users’ loss if they’re not interested in new features, but what if the new version fixes an important security issue? You need to make sure <strong>every user downloads the update</strong>. This can be accomplished within the application by disabling usage if it is not updated.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-443"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-441">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-442'
	>
	But how will the application know when a new update is available? Easily, with some help from our new open-source library.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-446"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-444">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-445'
	>
	Meet the prince</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-449"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-447">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-448'
	>
	<strong>An Android and iOS open-source library</strong> dubbed Prince of Versions standardizes notifications about application updates. The library does all the hard work: <strong>connecting to the server, parsing the configuration file, and comparing the new version with the current one</strong>. It doesn’t contain any UI, so developers can choose what to show when an update is available.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-452"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-450">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-451'
	>
	To use the library, you need to host a <strong>JSON configuration file</strong> on a server. The minimum and the current version of the application are defined in that file. When you publish a new update on Google Play, change one or both versions, and the next time the user opens your application, the library will serve a notification informing him about the new update. It is up to you to decide how the update will be shown. You can show a dialog with a button which takes the user to the app store, open a new screen, or perform some other action.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-455"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-453">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-454'
	>
	The library has <strong>three basic features</strong>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-458"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-456">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-457'
	>
	<li>It loads a configuration file from the network and notifies the user if a new update is available</li><li>Based on the minimum version in the file, it will show whether an update is mandatory</li><li>It will notify the user about the update based on the notification type parameter you set up.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-461"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-459">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-460'
	>
	This library is built by developers for developers, so the implementation is straightforward.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-464"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-462">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-463'
	>
	How to use it</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-467"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-465"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-466">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/03/make-sure-users-have-the-latest-app-version-installed-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="600"
															width="1000"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-470"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-468">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-469'
	>
	1. Put a JSON configuration file on a server</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-473"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-471">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-472'
	>
	The version in your application and in the <strong>JSON file</strong> has to follow <strong><a href="http://semver.org/">Semantic Versioning</a></strong>. If you are using a built-in JSON parser your configuration file has to look like this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-475"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-json github-light" data-language="json" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">ios</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">minimum_version</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">1.2.3</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">latest_version</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">version</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">2.4.5</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">notification_type</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">ALWAYS</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">android</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">minimum_version</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">1.2.3</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">latest_version</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">version</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">2.4.5</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">notification_type</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">ONCE</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">meta</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">key1</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">value1</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #005cc5;">&quot;</span><span class="token" style="color: #005cc5;">key2</span><span class="token" style="color: #005cc5;">&quot;</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">value2</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-478"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-476">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-477'
	>
	2. Add the library to your project</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-481"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-479">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-480'
	>
	<strong>Android</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-483"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-groovy github-light" data-language="groovy" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">compile &amp;#</span><span class="token" style="color: #005cc5;">8217</span><span class="token">;co</span><span class="token" style="color: #d73a49;">.</span><span class="token" style="color: #005cc5;">infinum</span><span class="token">:</span><span class="token">prince</span><span class="token" style="color: #d73a49;">-</span><span class="token">of</span><span class="token" style="color: #d73a49;">-</span><span class="token" style="color: #005cc5;">versions</span><span class="token">:</span><span class="token">latest_version&amp;#</span><span class="token" style="color: #005cc5;">8217</span><span class="token">;
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-486"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-484">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-485'
	>
	<strong>iOS</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-488"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">platform </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">ios</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #d73a49;">&amp;</span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">8217;8.0&amp;#8217;</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">use_frameworks!
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">pod </span><span class="token" style="color: #d73a49;">&amp;</span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">8217;PrinceOfVersions&amp;#8217;</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-491"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-489">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-490'
	>
	run pod install</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-493"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-shellscript github-light" data-language="shellscript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">pod</span><span class="token"> </span><span class="token" style="color: #032f62;">install</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-496"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-494">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-495'
	>
	3. Check for updates</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-499"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-497">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-498'
	>
	<strong>Android</strong></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-501"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-java github-light" data-language="java" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #24292e;">PrinceOfVersions</span><span class="token"> </span><span class="token" style="color: #24292e;">updater</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #d73a49;">new</span><span class="token"> </span><span class="token" style="color: #6f42c1;">PrinceOfVersions</span><span class="token">(</span><span class="token">context</span><span class="token">)</span><span class="token">;</span><span class="token"> 
</span></span><span class="line"><span class="token" style="color: #24292e;">LoaderFactory</span><span class="token"> </span><span class="token" style="color: #24292e;">loaderFactory</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #d73a49;">new</span><span class="token"> </span><span class="token" style="color: #6f42c1;">NetworkLoaderFactory</span><span class="token">(</span><span class="token">URL</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #24292e;">UpdaterResult</span><span class="token"> </span><span class="token" style="color: #24292e;">result</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #24292e;">updater</span><span class="token">.</span><span class="token" style="color: #6f42c1;">checkForUpdates</span><span class="token">(</span><span class="token">loaderFactory</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #d73a49;">new</span><span class="token"> </span><span class="token" style="color: #6f42c1;">UpdaterCallback</span><span class="token">(</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">@</span><span class="token" style="color: #d73a49;">Override</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">public</span><span class="token"> </span><span class="token" style="color: #d73a49;">void</span><span class="token"> </span><span class="token" style="color: #6f42c1;">onNewUpdate</span><span class="token">(</span><span class="token" style="color: #24292e;">String</span><span class="token"> </span><span class="token" style="color: #e36209;">version</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #d73a49;">boolean</span><span class="token"> </span><span class="token" style="color: #e36209;">isMandatory</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #24292e;">Map</span><span class="token">&lt;</span><span class="token" style="color: #d73a49;">String</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #d73a49;">String</span><span class="token">&gt;</span><span class="token"> </span><span class="token" style="color: #e36209;">metadata</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">@</span><span class="token" style="color: #d73a49;">Override</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">public</span><span class="token"> </span><span class="token" style="color: #d73a49;">void</span><span class="token"> </span><span class="token" style="color: #6f42c1;">onNoUpdate</span><span class="token">(</span><span class="token" style="color: #24292e;">Map</span><span class="token">&lt;</span><span class="token" style="color: #d73a49;">String</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #d73a49;">String</span><span class="token">&gt;</span><span class="token"> </span><span class="token" style="color: #e36209;">metadata</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">@</span><span class="token" style="color: #d73a49;">Override</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">public</span><span class="token"> </span><span class="token" style="color: #d73a49;">void</span><span class="token"> </span><span class="token" style="color: #6f42c1;">onError</span><span class="token">(</span><span class="token">@</span><span class="token" style="color: #d73a49;">ErrorCode</span><span class="token"> </span><span class="token" style="color: #d73a49;">int</span><span class="token"> </span><span class="token" style="color: #e36209;">error</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-503"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-swift github-light" data-language="swift" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">let</span><span class="token"> url </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">URL(</span><span class="token">string:</span><span class="token"> URL</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">PrinceOfVersions(</span><span class="token">)</span><span class="token">.</span><span class="token">checkForUpdates(</span><span class="token">from:</span><span class="token"> url</span><span class="token">,
</span></span><span class="line"><span class="token">    </span><span class="token">newVersion:</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">(</span><span class="token">latestVersion</span><span class="token">, </span><span class="token">isMinimumVersionSatisfied</span><span class="token">, </span><span class="token">metadata</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">in</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">,
</span></span><span class="line"><span class="token">    </span><span class="token">noNewVersion:</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">(</span><span class="token">isMinimumVersionSatisfied</span><span class="token">, </span><span class="token">metadata</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">in</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">,
</span></span><span class="line"><span class="token">    </span><span class="token">error:</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token">(</span><span class="token">error</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #d73a49;">in</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-506"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-504">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-505'
	>
	There is more</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-509"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-507">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-508'
	>
	We have been using the library in production for a while and it made implementing application updates a breeze.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-512"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-510">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-511'
	>
	We all know that testing is a vital part of your development process. With the library, you can load a configuration file from the application resources. By doing this, you can test your UI implementation without making an API call.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-515"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-513">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-514'
	>
	Everybody hates constraints, so if you don’t like our JSON configuration file, you can define your own and implement a custom parser.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-518"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-516">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-517'
	>
	At the moment, these features are only available in the Android library, but they are on the roadmap for iOS and will be available soon.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-521"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-519">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-520'
	>
	If you want to contribute or have any questions about the library visit our <a href="https://github.com/infinum/Android-Prince-of-Versions">Android</a> or <a href="https://github.com/infinum/iOS-prince-of-versions">iOS</a> repositories on GitHub.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/make-sure-users-have-the-latest-app-version-installed/">Make Sure Your Users Have the Latest App Version Installed</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>8075https://infinum.com/uploads/2017/02/say-hello-to-a-faster-android-emulator-0.webp</url>
				</image>
				<title>Say Hello to a Faster Android Emulator</title>
				<link>https://infinum.com/blog/say-hello-to-a-faster-android-emulator/</link>
				<pubDate>Tue, 15 Dec 2015 08:51:00 +0000</pubDate>
				<dc:creator>Ivan Kocijan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/say-hello-to-a-faster-android-emulator/</guid>
				<description>
					<![CDATA[<p>For years, Android developers have been struggling with the Android emulator. Two years ago we switched to Genymontion which is both fast and reliable. </p>
<p>The post <a href="https://infinum.com/blog/say-hello-to-a-faster-android-emulator/">Say Hello to a Faster Android Emulator</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-634"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-524">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-527"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-525">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-526'
	>
	For years, Android developers have been struggling with the Android emulator. The emulator was so bad that it was almost impossible to use it. It took ages to start, and even when (or if) it started, it would crash a lot and applications would load forever. That’s why, 2 years ago we switched to Genymontion which is both fast and reliable. We wrote a blog post about it, so if you want you can read it <a href="https://infinum.com/blog/is-your-android-emulator-just-too-slow/">here</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-530"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-528">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-529'
	>
	However, Genymotion has a big problem – the lack of support for Google applications. There is no straightforward way to add them to the emulator and you have to do it for every emulator you create.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-533"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-531">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-532'
	>
	Luckily, Google listens to developers. As it turns out, their engineers had been working on a brand new Android <a href="https://en.wikipedia.org/wiki/Emulator">emulator</a>, that was released to the public a few days ago. I took it for a spin and here’s what it offers:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-536"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-534">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-535'
	>
	New features</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-539"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-537">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-538'
	>
	Speeeeeed</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-542"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-540">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-541'
	>
	When you start the emulator, it loads in less than 10 seconds. The first time I started it, I thought I did something wrong. But I didn’t, it actually loads that fast. If you’ve tried out the old Android emulator, then you know that launching it used to take at least several minutes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-545"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-543">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-544'
	>
	Side toolbar</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-548"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-546">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-547'
	>
	The first thing you’ll notice is the new side toolbar which has some default controls. If you click on the three dots, an extended controls window with new features will open.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-551"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-549"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-550">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/02/say-hello-to-a-faster-android-emulator-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="753"
															width="508"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-554"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-552">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-553'
	>
	Fake GPS data points</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-557"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-555">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-556'
	>
	With the new emulator, you can easily fake users’ movement by importing GPX or KML file. This is a great and easy way to test location-based applications.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-560"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-558"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-559">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/02/say-hello-to-a-faster-android-emulator-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="564"
															width="1000"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-563"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-561">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-562'
	>
	Fake cellular connection</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-566"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-564">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-565'
	>
	Testing different cellular network types has been a real pain until now. Now you can choose between several network types and set the status of voice and data service. If you’ve always wanted to test your application in roaming, on EDGE data connection, now you can do it from the comfort of your chair instead of going to another country.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-569"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-567"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-568">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/02/say-hello-to-a-faster-android-emulator-3.webp"
					class="image__img block-media__image-img"
					alt=""
										height="568"
															width="1000"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-572"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-570">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-571'
	>
	Changing battery status</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-575"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-573">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-574'
	>
	You probably noticed that the only way so set the battery level on the old emulator was through the <a href="http://developer.android.com/intl/es/tools/devices/emulator.html#power">command line</a>. Now you can set several options like charge level, charger connection, battery status, and even battery health. And if you are wondering, like I was, what would happen if you disabled charging and set battery level to 0%, I have an answer for you. The phone shuts down and the emulator closes. Mystery solved.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-578"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-576"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-577">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/02/say-hello-to-a-faster-android-emulator-4.webp"
					class="image__img block-media__image-img"
					alt=""
										height="573"
															width="1000"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-581"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-579">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-580'
	>
	Call or text yourself</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-584"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-582">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-583'
	>
	Testing how your app behaves when the user receives a phone call or text is now a lot easier. With new “Phone” options, you can send texts or fake a call from the emulator.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-587"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-585"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-586">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2017/02/say-hello-to-a-faster-android-emulator-5.webp"
					class="image__img block-media__image-img"
					alt=""
										height="577"
															width="1000"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-590"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-588">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-589'
	>
	Fingerprint sensor</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-593"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-591">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-592'
	>
	Until now, there has been no way to test fingerprint authentication without a real device. The latest Android emulator allows you to test your app with up to 10 different fingerprints.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-596"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-594">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-595'
	>
	Where can I get it?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-599"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-597">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-598'
	>
	The new emulator is available only in Android Studio 2.0 Preview 3b and it won’t work as fast as I mentioned if you emulate an ARM processor. You need to emulate an x86 processor if you want to enjoy the awesome performance.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-602"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-600">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-601'
	>
	AS 2.0 Preview 3b can be downloaded from the Canary Channel. The Canary Channel delivers bleeding edge updates for Android Studio on an almost weekly basis. In other words, this is far from a stable version and bugs are expected. After downloading, you will have to open the SDK Manager and install two things:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-605"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-603">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-604'
	>
	<li>SDK tool 25-rc1</li><li>Intel x86 Emulator Accelerator</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-608"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-606">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-607'
	>
	Just one important note: if you are using Mac and you already have Intel x86 Emulator Accelerator installed, you might get an error like this when starting the emulator:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-611"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-609">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-610'
	>
	<strong>emulator: ERROR: x86 emulation currently requires hardware acceleration</strong>!<br><strong>Please ensure Intel HAXM is properly installed and usable</strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-614"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-612">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-613'
	>
	To fix this, you have to manually reinstall the x86 Accelerator. You can do this by navigating to this folder:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-617"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-615">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-616'
	>
	<em>”path_to_your_sdk/extras/intel/Hardware_Accelerated_Execution_Manager”</em></p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-620"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-618">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-619'
	>
	Open the IntelHAXM_6.0.1.dmg file and reinstall the x86 Accelerator.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-623"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-621">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-622'
	>
	After that, you just have to create a new x86 virtual device, press the Run button, sit back and your new emulator will be ready in a few seconds.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-626"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-624">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-625'
	>
	Should I say goodbye to Genymotion?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-629"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-627">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-628'
	>
	The new emulator is packed with new features and it works really fast, so the question is, do you still need Genymotion? The answer is yes, at least for a few more months. The new Android emulator is still in beta and there are some bugs which will drive you crazy. For example, sometimes setting the user’s location doesn’t work and faking a call freezes the emulator. Also, when the emulator freezes, you have to force close it because pressing the Quit button doesn’t work.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-632"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-630">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-631'
	>
	Despite those bugs, the new emulator shows great promise. It’s cool and usable, so I encourage you to try it out.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/say-hello-to-a-faster-android-emulator/">Say Hello to a Faster Android Emulator</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>7876https://infinum.com/uploads/2014/08/make-your-app-work-with-android-wear-in-4-easy-steps-0.webp</url>
				</image>
				<title>Make Your App Work with Android Wear in 4 Easy Steps</title>
				<link>https://infinum.com/blog/make-your-app-work-with-android-wear-in-4-easy-steps/</link>
				<pubDate>Mon, 25 Aug 2014 22:13:00 +0000</pubDate>
				<dc:creator>Ivan Kocijan</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/make-your-app-work-with-android-wear-in-4-easy-steps/</guid>
				<description>
					<![CDATA[<p>Google introduced the full Android Wear SDK and now developers can finally start building awesome smartwatch applications. </p>
<p>The post <a href="https://infinum.com/blog/make-your-app-work-with-android-wear-in-4-easy-steps/">Make Your App Work with Android Wear in 4 Easy Steps</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-729"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-635">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-638"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-636">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-637'
	>
	This July, at its annual developer conference, Google introduced the full Android Wear SDK and now developers can finally start building awesome smartwatch applications. Want to learn how to make your existing apps work with Android Wear? Then read on!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-641"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-639">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-640'
	>
	Unless you’ve spent the last year on a deserted island, you’ve probably heard about Android Wear. It’s an extension of the Android operating system for wearable devices. Although there should be many different wearable devices in the future, the industry is focused on smartwatches at the moment.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-644"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-642"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-643">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/08/make-your-app-work-with-android-wear-in-4-easy-steps-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="500"
															width="700"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-647"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-645">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-646'
	>
	Several big players have already launched their devices that support the Wear SDK – for example LG with its <a href="http://www.lg.com/global/gwatch/index.html#main">G watch</a> or Samsung with <a href="http://www.samsung.com/us/mobile/wearable-tech/all-products?filter=gear-2">Gear 2</a>. Probably the most anticipated smartwatch, the one we use in visual illustrations for this article, is <a href="https://moto360.motorola.com/">Moto 360</a> by Motorola Mobility. Luckily for all of us geeks out there, it should be launched in a few weeks.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-650"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-648">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-649'
	>
	If you are a developer, Android Wear gives you a chance to <strong>improve mobile experience</strong> and make your applications more <strong>accessible for users</strong>. If you want, you can develop Android Wear applications in the same way you develop smartphone applications, but SDK also allows you to extend your current applications. In this blog post, I will show you how to extend your application notifications to Android Wear and add some cool wear actions.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-653"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-651">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-652'
	>
	What are we modifying?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-656"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-654">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-655'
	>
	I’ll be modifying one of our existing apps called the Queueing app.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-659"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-657">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-658'
	>
	This app was developed for Erste &amp; Steiermärkische Bank and it allows anyone with a smartphone to find the nearest branch office and remotely reserve a spot in the queue. The Queueing app can send a notification when users are next in line so they can head to the bank and grab their spot. If users change their mind, they have an option to delete their ticket and leave the queue. In order to use these features, they need to take out their mobile phones and open the app.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-662"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-660"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-661">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/08/make-your-app-work-with-android-wear-in-4-easy-steps-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="500"
															width="700"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-665"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-663">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-664'
	>
	Android wear makes things a lot easier</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-668"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-666">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-667'
	>
	With Android wear, we can give our users the ability to use these features without reaching for their phones. We are going to modify the existing application and users with a smartwatch will get a notification on their wrists with information on how many people are in front of them.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-671"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-669">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-670'
	>
	Notifications are a cool addition, but we can do better. We will also add two more custom wear actions:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-674"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-672">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-673'
	>
	<li><strong>”Snooze” notification</strong> – If users swipe the notification to the right, they will be offered the possibility to “snooze” it. For example, if there are 9 people in front of you, you can choose to be reminded when you’re 6th in line.</li><li><strong>Cancel ticket</strong> – By swiping to the right once more, users will be able to cancel their current ticket and remove themselves from the queue.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-677"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-675">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-676'
	>
	The main idea behind these actions is to give our users the ability to interact with our application without the need to pull their smartphones out of their pockets. Just bear in mind that users will be able to use these actions only if they are not next in line. If they are, they will only get a notification indicating that there are no more people in front of them.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-680"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-678">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-679'
	>
	Modifying the existing app</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-683"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-681">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-682'
	>
	Here is what you need to do in order to get the most out of Android Wear notifications:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-686"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-684">
	<h3	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-685'
	>
	1. Add the latest support library to your application’s build.gradle file</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-689"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-687">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-688'
	>
	I hope you use Android Studio because the <a href="https://infinum.com/blog/eclipse-is-dead-for-android-development-and-i-helped-kill-it/">Eclipse is dead</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-691"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-java github-light" data-language="java" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">dependencies </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">    compile ’</span><span class="token" style="color: #24292e;">com</span><span class="token">.andro</span><span class="token" style="color: #24292e;">i</span><span class="token">d</span><span class="token" style="color: #24292e;">.suppor</span><span class="token">t</span><span class="token" style="color: #d73a49;">:</span><span class="token">support</span><span class="token" style="color: #d73a49;">-</span><span class="token">v4</span><span class="token" style="color: #d73a49;">:</span><span class="token" style="color: #005cc5;">20.0</span><span class="token" style="color: #d73a49;">+</span><span class="token">’
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-694"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-692">
	<h3	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-693'
	>
	2. Add Android wear specific actions to existing notification</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-697"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-695">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-696'
	>
	We are using NotificationCompat.Builder class because, when building with this class, the system takes care of displaying notifications properly, whether they appear on a phone or smartwatch.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-699"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-java github-light" data-language="java" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">standard notification code</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token" style="color: #24292e;">NotificationCompat</span><span class="token">.</span><span class="token" style="color: #24292e;">Builder</span><span class="token"> </span><span class="token" style="color: #24292e;">mBuilder</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #d73a49;">new</span><span class="token"> NotificationCompat</span><span class="token">.</span><span class="token" style="color: #6f42c1;">Builder</span><span class="token">(</span><span class="token">mContext</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">.</span><span class="token" style="color: #6f42c1;">setSmallIcon</span><span class="token">(</span><span class="token" style="color: #24292e;">R</span><span class="token">.</span><span class="token" style="color: #24292e;">drawable</span><span class="token">.</span><span class="token" style="color: #24292e;">icon_notification_queueing_seethrough</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">.</span><span class="token" style="color: #6f42c1;">setContentTitle</span><span class="token">(</span><span class="token" style="color: #24292e;">mContext</span><span class="token">.</span><span class="token" style="color: #6f42c1;">getString</span><span class="token">(</span><span class="token" style="color: #24292e;">R</span><span class="token">.</span><span class="token" style="color: #24292e;">string</span><span class="token">.</span><span class="token" style="color: #24292e;">redomat</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">.</span><span class="token" style="color: #6f42c1;">setContentText</span><span class="token">(</span><span class="token">message</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">Actions &quot;Snooze&quot; notification and delete ticket (remove from queue) are only available if user is not next in line</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token" style="color: #d73a49;">if</span><span class="token"> </span><span class="token">(</span><span class="token" style="color: #d73a49;">!</span><span class="token" style="color: #6f42c1;">getIsUserNextInLine</span><span class="token">(</span><span class="token">)</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">User click on action triggers broadcast which is received by WearActionReceiver.class</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">Put notification id and flag WEAR_ACTION. </span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">Using these parameters WearActionReceiver.class will know which action was clicked</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">Intent</span><span class="token"> </span><span class="token" style="color: #24292e;">notifyNextTimeIntent</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #d73a49;">new</span><span class="token"> </span><span class="token" style="color: #6f42c1;">Intent</span><span class="token">(</span><span class="token">mContext</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #24292e;">WearActionReceiver</span><span class="token">.</span><span class="token" style="color: #24292e;">class</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">notifyNextTimeIntent</span><span class="token">.</span><span class="token" style="color: #6f42c1;">putExtra</span><span class="token">(</span><span class="token" style="color: #24292e;">WearActionReceiver</span><span class="token">.</span><span class="token" style="color: #24292e;">NOTIFICATION_ID_STRING</span><span class="token">,</span><span class="token"> NOTIFICATION_ID</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">notifyNextTimeIntent</span><span class="token">.</span><span class="token" style="color: #6f42c1;">putExtra</span><span class="token">(</span><span class="token" style="color: #24292e;">WearActionReceiver</span><span class="token">.</span><span class="token" style="color: #24292e;">WEAR_ACTION</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #24292e;">WearActionReceiver</span><span class="token">.</span><span class="token" style="color: #24292e;">SNOOZE_NOTIFICATION</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">PendingIntent</span><span class="token"> </span><span class="token" style="color: #24292e;">pendingIntentNotify</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #24292e;">PendingIntent</span><span class="token">.</span><span class="token" style="color: #6f42c1;">getBroadcast</span><span class="token">(</span><span class="token">mContext</span><span class="token">,</span><span class="token"> WEAR_REQUEST_CODE</span><span class="token">,</span><span class="token"> notifyNextTimeIntent</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #24292e;">PendingIntent</span><span class="token">.</span><span class="token" style="color: #24292e;">FLAG_UPDATE_CURRENT</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">text shown in notification</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">String</span><span class="token"> </span><span class="token" style="color: #24292e;">notifyAgainText</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #24292e;">String</span><span class="token">.</span><span class="token" style="color: #6f42c1;">format</span><span class="token">(</span><span class="token" style="color: #24292e;">mContext</span><span class="token">.</span><span class="token" style="color: #6f42c1;">getString</span><span class="token">(</span><span class="token" style="color: #24292e;">R</span><span class="token">.</span><span class="token" style="color: #24292e;">string</span><span class="token">.</span><span class="token" style="color: #24292e;">notification_next_in_line</span><span class="token">)</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #6f42c1;">getNumberInLine</span><span class="token">(</span><span class="token">)</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">Wear action - this action will be shown only on Android Wear devices</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">Set action icon, text and pending intent which will be executed on click</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">When user clicks on this icon he will &quot;snooze&quot; notification</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">NotificationCompat</span><span class="token">.</span><span class="token" style="color: #24292e;">Action</span><span class="token"> </span><span class="token" style="color: #24292e;">actionNotifyNextTime</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #d73a49;">new</span><span class="token"> NotificationCompat</span><span class="token">.</span><span class="token" style="color: #24292e;">Action</span><span class="token">.</span><span class="token" style="color: #6f42c1;">Builder</span><span class="token">(</span><span class="token" style="color: #24292e;">R</span><span class="token">.</span><span class="token" style="color: #24292e;">drawable</span><span class="token">.</span><span class="token" style="color: #24292e;">ic_launcher</span><span class="token">,</span><span class="token"> notifyAgainText</span><span class="token">,</span><span class="token"> pendingIntentNotify</span><span class="token">)</span><span class="token">.</span><span class="token" style="color: #6f42c1;">build</span><span class="token">(</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">The same as Intent for &quot;snooze&quot; but this time set another flag</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">Intent</span><span class="token"> </span><span class="token" style="color: #24292e;">cancelTicketIntent</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #d73a49;">new</span><span class="token"> </span><span class="token" style="color: #6f42c1;">Intent</span><span class="token">(</span><span class="token">mContext</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #24292e;">WearActionReceiver</span><span class="token">.</span><span class="token" style="color: #24292e;">class</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">cancelTicketIntent</span><span class="token">.</span><span class="token" style="color: #6f42c1;">putExtra</span><span class="token">(</span><span class="token" style="color: #24292e;">WearActionReceiver</span><span class="token">.</span><span class="token" style="color: #24292e;">NOTIFICATION_ID_STRING</span><span class="token">,</span><span class="token"> NOTIFICATION_ID</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">cancelTicketIntent</span><span class="token">.</span><span class="token" style="color: #6f42c1;">putExtra</span><span class="token">(</span><span class="token" style="color: #24292e;">WearActionReceiver</span><span class="token">.</span><span class="token" style="color: #24292e;">WEAR_ACTION</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #24292e;">WearActionReceiver</span><span class="token">.</span><span class="token" style="color: #24292e;">CANCEL_TICKET</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">PendingIntent</span><span class="token"> </span><span class="token" style="color: #24292e;">pendingIntentCancel</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #24292e;">PendingIntent</span><span class="token">.</span><span class="token" style="color: #6f42c1;">getBroadcast</span><span class="token">(</span><span class="token">mContext</span><span class="token">,</span><span class="token"> WEAR_REQUEST_CODE_2</span><span class="token">,</span><span class="token"> cancelTicketIntent</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #24292e;">PendingIntent</span><span class="token">.</span><span class="token" style="color: #24292e;">FLAG_UPDATE_CURRENT</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">     </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">When user clicks on this icon he will cancel his ticket and remove himself from the queue</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">     </span><span class="token" style="color: #24292e;">NotificationCompat</span><span class="token">.</span><span class="token" style="color: #24292e;">Action</span><span class="token"> </span><span class="token" style="color: #24292e;">actionCancel</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #d73a49;">new</span><span class="token"> NotificationCompat</span><span class="token">.</span><span class="token" style="color: #24292e;">Action</span><span class="token">.</span><span class="token" style="color: #6f42c1;">Builder</span><span class="token">(</span><span class="token" style="color: #24292e;">R</span><span class="token">.</span><span class="token" style="color: #24292e;">drawable</span><span class="token">.</span><span class="token" style="color: #24292e;">actionbar_icon_delete</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="token">                    </span><span class="token" style="color: #24292e;">mContext</span><span class="token">.</span><span class="token" style="color: #6f42c1;">getString</span><span class="token">(</span><span class="token" style="color: #24292e;">R</span><span class="token">.</span><span class="token" style="color: #24292e;">string</span><span class="token">.</span><span class="token" style="color: #24292e;">cancel_ticket</span><span class="token">)</span><span class="token">,</span><span class="token"> pendingIntentCancel</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">                    </span><span class="token">.</span><span class="token" style="color: #6f42c1;">build</span><span class="token">(</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">Create new WearableExtender object and add actions</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">NotificationCompat</span><span class="token">.</span><span class="token" style="color: #24292e;">WearableExtender</span><span class="token"> </span><span class="token" style="color: #24292e;">extender</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #d73a49;">new</span><span class="token"> NotificationCompat</span><span class="token">.</span><span class="token" style="color: #6f42c1;">WearableExtender</span><span class="token">(</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">extender</span><span class="token">.</span><span class="token" style="color: #6f42c1;">addAction</span><span class="token">(</span><span class="token">actionNotifyNextTime</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">extender</span><span class="token">.</span><span class="token" style="color: #6f42c1;">addAction</span><span class="token">(</span><span class="token">actionCancel</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">Extend Notification builder</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #24292e;">mBuilder</span><span class="token">.</span><span class="token" style="color: #6f42c1;">extend</span><span class="token">(</span><span class="token">extender</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">Get notification manager</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token" style="color: #24292e;">NotificationManager</span><span class="token"> </span><span class="token" style="color: #24292e;">mNotificationManager</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token">
</span></span><span class="line"><span class="token">                </span><span class="token">(</span><span class="token">NotificationManager</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #24292e;">mContext</span><span class="token">.</span><span class="token" style="color: #6f42c1;">getSystemService</span><span class="token">(</span><span class="token" style="color: #24292e;">Context</span><span class="token">.</span><span class="token" style="color: #24292e;">NOTIFICATION_SERVICE</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">show notification</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token" style="color: #24292e;">mNotificationManager</span><span class="token">.</span><span class="token" style="color: #6f42c1;">notify</span><span class="token">(</span><span class="token">NOTIFICATION_ID</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #24292e;">mBuilder</span><span class="token">.</span><span class="token" style="color: #6f42c1;">build</span><span class="token">(</span><span class="token">)</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-702"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-700">
	<h3	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-701'
	>
	3. Add Broadcast Receiver</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-705"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-703">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-704'
	>
	This class will receive the clicked wear action and either “snooze” the notification or remove the user from the queue. It will also dismiss notifications on Android Wear.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-707"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-java github-light" data-language="java" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">public</span><span class="token"> </span><span class="token" style="color: #d73a49;">class</span><span class="token"> </span><span class="token" style="color: #6f42c1;">WearActionReceiver</span><span class="token"> </span><span class="token" style="color: #d73a49;">extends</span><span class="token"> </span><span class="token" style="color: #6f42c1;">BroadcastReceiver</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">public</span><span class="token"> </span><span class="token" style="color: #d73a49;">static</span><span class="token"> </span><span class="token" style="color: #d73a49;">final</span><span class="token"> </span><span class="token" style="color: #24292e;">String</span><span class="token"> </span><span class="token" style="color: #24292e;">NOTIFICATION_ID_STRING</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">NotificationId</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">public</span><span class="token"> </span><span class="token" style="color: #d73a49;">static</span><span class="token"> </span><span class="token" style="color: #d73a49;">final</span><span class="token"> </span><span class="token" style="color: #24292e;">String</span><span class="token"> </span><span class="token" style="color: #24292e;">WEAR_ACTION</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">WearAction</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">public</span><span class="token"> </span><span class="token" style="color: #d73a49;">static</span><span class="token"> </span><span class="token" style="color: #d73a49;">final</span><span class="token"> </span><span class="token" style="color: #d73a49;">int</span><span class="token"> </span><span class="token" style="color: #24292e;">SNOOZE_NOTIFICATION</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">1</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">public</span><span class="token"> </span><span class="token" style="color: #d73a49;">static</span><span class="token"> </span><span class="token" style="color: #d73a49;">final</span><span class="token"> </span><span class="token" style="color: #d73a49;">int</span><span class="token"> </span><span class="token" style="color: #24292e;">CANCEL_TICKET</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">2</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">@</span><span class="token" style="color: #d73a49;">Override</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">public</span><span class="token"> </span><span class="token" style="color: #d73a49;">void</span><span class="token"> </span><span class="token" style="color: #6f42c1;">onReceive</span><span class="token"> </span><span class="token">(</span><span class="token" style="color: #24292e;">Context</span><span class="token"> </span><span class="token" style="color: #e36209;">context</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #24292e;">Intent</span><span class="token"> </span><span class="token" style="color: #e36209;">intent</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">if</span><span class="token"> </span><span class="token">(</span><span class="token">intent </span><span class="token" style="color: #d73a49;">!=</span><span class="token"> </span><span class="token" style="color: #005cc5;">null</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #d73a49;">int</span><span class="token"> </span><span class="token" style="color: #24292e;">notificationId</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #24292e;">intent</span><span class="token">.</span><span class="token" style="color: #6f42c1;">getIntExtra</span><span class="token">(</span><span class="token">NOTIFICATION_ID_STRING</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">0</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #24292e;">NotificationManager</span><span class="token"> </span><span class="token" style="color: #24292e;">manager</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">(</span><span class="token">NotificationManager</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #24292e;">context</span><span class="token">.</span><span class="token" style="color: #6f42c1;">getSystemService</span><span class="token">(</span><span class="token" style="color: #24292e;">Context</span><span class="token">.</span><span class="token" style="color: #24292e;">NOTIFICATION_SERVICE</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #24292e;">manager</span><span class="token">.</span><span class="token" style="color: #6f42c1;">cancel</span><span class="token">(</span><span class="token">notificationId</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #d73a49;">int</span><span class="token"> </span><span class="token" style="color: #24292e;">action</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #24292e;">intent</span><span class="token">.</span><span class="token" style="color: #6f42c1;">getIntExtra</span><span class="token">(</span><span class="token">WEAR_ACTION</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">0</span><span class="token">)</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token" style="color: #d73a49;">switch</span><span class="token"> </span><span class="token">(</span><span class="token">action</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token">
</span></span><span class="line"><span class="token">                </span><span class="token" style="color: #d73a49;">case</span><span class="token"> SNOOZE_NOTIFICATION</span><span class="token" style="color: #d73a49;">:</span><span class="token">
</span></span><span class="line"><span class="token">                    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">Code for notification snooze</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">                    </span><span class="token" style="color: #d73a49;">break</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">                </span><span class="token" style="color: #d73a49;">case</span><span class="token"> CANCEL_TICKET</span><span class="token" style="color: #d73a49;">:</span><span class="token">
</span></span><span class="line"><span class="token">                    </span><span class="token" style="color: #6a737d;">//</span><span class="token" style="color: #6a737d;">code for removing the user from the queue</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">                    </span><span class="token" style="color: #d73a49;">break</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">                </span><span class="token" style="color: #d73a49;">default</span><span class="token" style="color: #d73a49;">:</span><span class="token">
</span></span><span class="line"><span class="token">                    </span><span class="token" style="color: #d73a49;">break</span><span class="token">;</span><span class="token">
</span></span><span class="line"><span class="token">            </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">       </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-710"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-708">
	<h3	class='typography typography--size-24-text js-typography block-heading__heading'
	data-id='es-709'
	>
	4. Declare WearActionReceiver in the manifest file</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-712"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-java github-light" data-language="java" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token"> </span><span class="token" style="color: #d73a49;">&lt;</span><span class="token">receiver android</span><span class="token" style="color: #d73a49;">:</span><span class="token">name</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">co.infinum.WearActionReceiver</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #d73a49;">/</span><span class="token" style="color: #d73a49;">&gt;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-715"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-713"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-714">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/08/make-your-app-work-with-android-wear-in-4-easy-steps-3.webp"
					class="image__img block-media__image-img"
					alt=""
										height="500"
															width="700"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-718"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-716">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-717'
	>
	Updates – Make them happen</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-721"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-719">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-720'
	>
	As you can see, with just a few extra lines of code, we gave our users an option to interact with our application without reaching for their phones. Considering the fact that implementing support for Android Wear is really easy, I believe that every Android dev should be aiming to update their apps as soon as possible.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-724"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-722">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-723'
	>
	Maybe now you are thinking; “Heck, why would I do that when the majority of users won’t buy a fancy smartwatch?” That’s a valid concern, especially when we know that the current generation of smartwatches costs between $200 and $300.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-727"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-725">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-726'
	>
	But like with any other technology, the price of Android Wear devices will go down and they will become more widespread. Making sure your app supports this innovative technology is a smart investment for the future.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/make-your-app-work-with-android-wear-in-4-easy-steps/">Make Your App Work with Android Wear in 4 Easy Steps</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>