tag:www.yannicklemin.com,2005:/feedYannick Lemin2017-04-15T16:05:25-05:00tag:www.yannicklemin.com,2005:Article/259032017-04-15T16:05:25-05:002018-11-16T05:43:57-06:00Android KeyStore Compat<h1 id="context">Context</h1>
<p>This story is non fictional, but for security reasons, name of people and places have been changed to ensure anonymity. We don&#39;t laugh about security around here!</p>
<p>Also this whole story takes place in an Android app, which makes sense as there is &quot;AndroidKeyStore&quot; in the title... but I make that clear just in case.</p>
<p>In order to keep this short, I will not go into all the details of how a certificate work. So I guess you&#39;re supposed to know at least what they are and what they do.</p>
<p>Yes, I will attempt to keep this short, which is going to be difficult as I love to talk!</p>
<p><em>spoiler: check the solution/conclusion at the end of the article if you don&#39;t want to read the whole thing!</em></p>
<h1 id="story">Story</h1>
<p>So a little while back, I ran into this issue where I needed <code>to store a few keys</code> (read here <em>&quot;public certificates which are combined with a private sibling hidden somewhere on the vast land of the interwebs&quot;</em>) received by this amazing channel called &quot;an API&quot;.</p>
<p>The use I have for those keys (certificates) is irrelevant for this post, let&#39;s say I was doing some highly classified processing, way above your pay grade. So don&#39;t ask as if I tell you, I&#39;ll have to kill you.</p>
<p>Anyway, I received those certificates through an API and I needed to store them so that I can reuse them even if the app is restarted. For that, I use ... well ... a <a href="https://developer.android.com/reference/java/security/KeyStore.html">KeyStore</a>. Sure enough, testing this out on my great Nexus 5, big Nexus 6, awesome Nexus 6P and trusty Nexus 9 (see a pattern here?), everything was working just fabulously. Then I got a bug report, a very detailed one, saying, and I quote:</p>
<blockquote>
<p>it doesn&#39;t work on my phone.</p>
</blockquote>
<p>Well it took me a while to figure out that:<br>
1. I was using it wrong<br>
2. I was not handling errors and exceptions properly (sometimes I&#39;m lazy!)<br>
3. The user&#39;s phone was running with Android 4.2 JellyBean (Level 17)</p>
<h1 id="my-mistake">My Mistake</h1>
<p>Well I didn&#39;t know much about KeyStore back then, I was young and inexperienced ... so I did what everyone would have done:<br>
* I found a tutorial online (StackOverflow anyone?) that seemed to be doing what I wanted to do<br>
* I did not read the whole instructions and just copy pasted the code<br>
* I noticed that it was working on my Nexi, I was happy and we went ahead with the release</p>
<p>Well, it turns out that when you google <code>Android KeyStore</code>, you will find a bunch of tutorials that explain how to use the &quot;AndroidKeyStore&quot;, which is nice, but through my personal research (and lack of reading the fine prints), I couldn&#39;t find one that actually mentioned that the &quot;AndroidKeyStore&quot; didn&#39;t exist before Android SDK Level 18 (also known as Android Jelly Bean MR2). And that&#39;s when my story really begins.</p>
<p>Note: the <a href="https://developer.android.com/training/articles/keystore.html">official Android KeyStore System page</a> actually says very clearly:</p>
<blockquote>
<p>the Keystore system is used by the KeyChain API as well as the Android Keystore provider feature that was introduced in Android 4.3 (API level 18).</p>
</blockquote>
<p>So I should have seen this coming... yep, I should have...</p>
<h1 id="the-android-keystore-system">The Android KeyStore System</h1>
<p>And here is what I have learned since then:</p>
<p>So a <code>KeyStore</code> object is doing all sorts of security magic that I will not (read here <em>cannot</em> ;) ) explain right now. However I can show you some things.</p>
<h3 id="instantiation">Instantiation</h3>
<p><em>You do not just <code>new</code> a Keystore, you summon its presence.</em></p>
<div class="highlight"><pre><span class="n">Keystore</span> <span class="n">keystore</span> <span class="o">=</span> <span class="n">KeyStore</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">&quot;AndroidKeyStore&quot;</span><span class="o">);</span>
</pre></div>
<p>This is what you will see in most of the tutorials, which basically says <code>&quot;give me the AndroidKeyStore instance&quot;</code>... for the untrained eye. For the others, you will read <code>&quot;give me an instance of a Keystore of type AndroidKeyStore&quot;</code>, which is a little bit different.</p>
<p>This on devices running Android versions below 4.3 will return actually barf a very lovely exception such as this:</p>
<div class="highlight"><pre><span class="n">java</span><span class="o">.</span><span class="na">security</span><span class="o">.</span><span class="na">KeyStoreException</span><span class="o">:</span> <span class="n">java</span><span class="o">.</span><span class="na">security</span><span class="o">.</span><span class="na">NoSuchAlgorithmException</span><span class="o">:</span> <span class="n">KeyStore</span> <span class="n">AndroidKeyStore</span> <span class="n">implementation</span> <span class="n">not</span> <span class="n">found</span>
<span class="n">at</span> <span class="n">java</span><span class="o">.</span><span class="na">security</span><span class="o">.</span><span class="na">KeyStore</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="n">KeyStore</span><span class="o">.</span><span class="na">java</span><span class="o">:</span><span class="mi">119</span><span class="o">)</span>
<span class="o">...</span>
<span class="n">Caused</span> <span class="nl">by:</span> <span class="n">java</span><span class="o">.</span><span class="na">security</span><span class="o">.</span><span class="na">NoSuchAlgorithmException</span><span class="o">:</span> <span class="n">KeyStore</span> <span class="n">AndroidKeyStore</span> <span class="n">implementation</span> <span class="n">not</span> <span class="n">found</span>
<span class="n">at</span> <span class="n">org</span><span class="o">.</span><span class="na">apache</span><span class="o">.</span><span class="na">harmony</span><span class="o">.</span><span class="na">security</span><span class="o">.</span><span class="na">fortress</span><span class="o">.</span><span class="na">Engine</span><span class="o">.</span><span class="na">notFound</span><span class="o">(</span><span class="n">Engine</span><span class="o">.</span><span class="na">java</span><span class="o">:</span><span class="mi">177</span><span class="o">)</span>
<span class="o">...</span>
</pre></div>
<p>This is quite clear isn&#39;t i? Well it is when you pay attention to the exceptions and you treat the handling properly. It says very clearly &quot;sorry, but I don&#39;t know this AndroidKeyStore you speak of&quot;. Run the same code on a Level 18+, and it will be just fine and return an actual instance.</p>
<h3 id="the-androidkeystore-provider">The AndroidKeyStore Provider</h3>
<p>To make a long story short, the &quot;AndroidKeyStore&quot; string you pass to the <code>KeyStore.getInstance()</code> method tells the system to return the/an instance of that particular provider, which for my little 4.2 device has not been invented yet!</p>
<p>In short, <strong>the provider</strong> allows to declare some certificate storing mechanism in a way that is opaque to the client. some will like this, others won&#39;t. In this case, this provider is <code>very secure</code>, is <code>app specific</code>, <code>handles its own persistance</code>, maybe more?</p>
<p>In code, when you do something like the following, you don&#39;t have to worry about a thing.</p>
<div class="highlight"><pre><span class="n">Certificate</span> <span class="n">cert</span> <span class="o">=</span> <span class="n">getMyVerySpecialCertificateFromSomeVerySecretePlace</span><span class="o">();</span>
<span class="n">String</span> <span class="n">alias</span> <span class="o">=</span> <span class="n">generateAnAliasThatMakesSense</span><span class="o">();</span>
<span class="n">KeyStore</span> <span class="n">keystore</span> <span class="o">=</span> <span class="n">KeyStore</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">&quot;AndroidKeyStore&quot;</span><span class="o">);</span>
<span class="n">keystore</span><span class="o">.</span><span class="na">load</span><span class="o">(</span><span class="kc">null</span><span class="o">);</span>
<span class="n">keystore</span><span class="o">.</span><span class="na">setCertificateEntry</span><span class="o">(</span><span class="n">alias</span><span class="o">,</span> <span class="n">cert</span><span class="o">);</span>
</pre></div>
<p>Well actually, you do have to worry about the potential exceptions that can be thrown, such as <code>KeyStoreException</code>, <code>CertificateException</code>, <code>NoSuchAlgorithmException</code>, <code>IOException</code>... Ho yeah baby, exceptions! Don&#39;t you love them?</p>
<p>But all in all, once you have done this, your certificate is stored in a very secure place that only this particular app can obtain.</p>
<h3 id="so-what-about-level-17-and-below">So what about Level 17 and below?</h3>
<p>Well I still had my issue that my app was to work on Level 16 and up, and I had code that could only work on Level 18 and up. So I had to find the &quot;old way&quot; of doing things, and here it is. For the same 3 lines shown above (I&#39;m not counting the retrieval of the certificate or the alias), you have to do a little bit more.</p>
<p>First, <code>you need to decide on what type of KeyStore to get</code>. The type basically represents the kind of encryption algorithm used to encrypt the data in the store. you can find a list of the available types on the <a href="https://developer.android.com/reference/java/security/KeyStore.html">KeyStore reference page</a>.</p>
<div class="highlight"><pre><span class="n">KeyStore</span> <span class="n">keystore</span> <span class="o">=</span> <span class="n">KeyStore</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">&quot;BKS&quot;</span><span class="o">);</span>
</pre></div>
<p>Or</p>
<div class="highlight"><pre><span class="n">KeyStore</span> <span class="n">keystore</span> <span class="o">=</span> <span class="n">KeyStore</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="n">KeyStore</span><span class="o">.</span><span class="na">getDefaultType</span><span class="o">());</span>
</pre></div>
<p>Then you need to open it properly like so:</p>
<div class="highlight"><pre><span class="n">FileInputStream</span> <span class="n">fis</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">openFileInput</span><span class="o">(</span><span class="n">KEYSTORE_FILE</span><span class="o">);</span>
<span class="n">keyStore</span><span class="o">.</span><span class="na">load</span><span class="o">(</span><span class="n">fis</span><span class="o">,</span> <span class="n">PASSWORD</span><span class="o">);</span>
<span class="n">fis</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
</pre></div>
<p>And finally, you actually need to store the data, because this one won&#39;t do it for you... (don&#39;t be greedy now!).</p>
<div class="highlight"><pre><span class="n">FileOutputStream</span> <span class="n">fos</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">openFileOutput</span><span class="o">(</span><span class="n">KEYSTORE_FILE</span><span class="o">,</span> <span class="n">Context</span><span class="o">.</span><span class="na">MODE_PRIVATE</span><span class="o">);</span>
<span class="n">keyStore</span><span class="o">.</span><span class="na">store</span><span class="o">(</span><span class="n">fos</span><span class="o">,</span> <span class="n">PASSWORD</span><span class="o">);</span>
<span class="n">fos</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
</pre></div>
<p>... And everything else (<code>containAlias</code>, <code>setCertificateEntry</code>, <code>deleteEntry</code>, etc) works the same way.</p>
<h1 id="the-conclusion-solution">The Conclusion / Solution</h1>
<p>So basically, if you&#39;re lucky enough to only make <code>minSdkVersion=18</code> apps, you really don&#39;t care about this. Otherwise, please understand that <strong>it is best to use the AndroidKeyStore whenever you can</strong>, and when you can&#39;t then go back to the dark ages. In other words you need some kind of a <code>KeyStore</code>wrapper that will handle that logic for you. </p>
<p><strong>And surprise: I did it for you and it&#39;s free of charge!!!</strong> And you&#39;ll wonder how you could have ever survived without it (ok it&#39;s maybe a little bit too much there !) --&gt; <strong><a href="https://gist.github.com/theyann/caf2d0d1003e64984be68ed800aeed8d">check this gist out</a>.</strong></p>
<p>I hope this article was useful, leave a comment if you have any remarks, enjoy the rest of your day.</p>
<p>Over and out!</p>
Yannick Lemintag:www.yannicklemin.com,2005:Article/191552015-11-14T13:30:00-06:002018-11-16T05:43:57-06:00All About Configurable Widgets<h1 id="intro">Intro</h1>
<p>A friend of mine told me about this app he&#39;d like to have. It is a very specific need which probably very few people have &#8594; he needed a button that would allow him to start an email with pre-filled data (recipients, subject, etc), so that he could skip a bunch of taps and steps and be as efficient as possible to send himself memos by email.</p>
<p>I like efficiency, I am myself a very big user of such niche and specific apps, and thus I saw this as an opportunity to learn about configurable widgets, and I figured it would be a &quot;<a href="https://play.google.com/store/apps/details?id=com.techyos.oneclickonemail">nice app</a>&quot; to make as a base for an explanation as to how I went about <strong>configurable widgets</strong> on Android because frankly, in 7 years developing for the platform, I had never done any widgets before ... shame on me. Since, I actually have made <a href="https://play.google.com/store/apps/details?id=com.techyos.fitdrinkup">another app</a> with configurable widgets as well &#9996; :).</p>
<p>So let&#39;s get started.</p>
<h1 id="foreword-s">Foreword(s)</h1>
<ul>
<li>The app is built on purpose with minimal dependencies:</li>
</ul>
<div class="highlight"><pre><span class="n">dependencies</span> <span class="o">{</span>
<span class="n">compile</span> <span class="nf">fileTree</span><span class="o">(</span><span class="nl">dir:</span> <span class="s1">&#39;libs&#39;</span><span class="o">,</span> <span class="nl">include:</span> <span class="o">[</span><span class="s1">&#39;*.jar&#39;</span><span class="o">])</span>
<span class="n">compile</span> <span class="s1">&#39;com.android.support:appcompat-v7:23.1.1&#39;</span>
<span class="n">compile</span> <span class="s1">&#39;com.android.support:recyclerview-v7:23.1.1&#39;</span>
<span class="o">}</span>
</pre></div>
<ul>
<li>It is ugly (meaning not well designed), I know, it&#39;s on purpose (that&#39;s my excuse for lacking any kind of UI design genes)</li>
<li>It&#39;s using the best practices that I know, feel free to correct me ... that is how I grow!</li>
<li>It may be buggy, but it&#39;s pretty straight forward so it should be ok.</li>
<li>It is assumed that you have basic knowledge and Android development to understand this post. Meaning you know how to start a project, what an activity is, and so on.</li>
</ul>
<h1 id="where-to-start">Where to start?</h1>
<h3 id="step-1-widget-39-s-ui">Step 1: widget&#39;s UI</h3>
<p>First thing first, you have to understand that a widget UI behave just like any other type of Android UI with I&#39;d say one exception: the size.</p>
<p>Indeed, a widget can have a fixed size, and potentially be expanded. If expansion there is, then you must adapt (or not) the UI accordingly. I will not cover this at the moment (sorry).</p>
<p>So first,you need the widget UI, which is a layout like any other layout file in an app, and it&#39;ll look something <a href="https://github.com/theyann/oneclickonemail/blob/master/app/src/main/res/layout/widget_layout.xml">like this</a>:</p>
<div class="highlight"><pre><span class="cp">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;</span>
<span class="nt">&lt;RelativeLayout</span> <span class="na">xmlns:android=</span><span class="s">&quot;http://schemas.android.com/apk/res/android&quot;</span>
<span class="na">xmlns:tools=</span><span class="s">&quot;http://schemas.android.com/tools&quot;</span>
<span class="na">android:id=</span><span class="s">&quot;@+id/layoutWidget&quot;</span>
<span class="na">android:layout_width=</span><span class="s">&quot;match_parent&quot;</span>
<span class="na">android:layout_height=</span><span class="s">&quot;match_parent&quot;</span>
<span class="na">android:padding=</span><span class="s">&quot;4dp&quot;</span>
<span class="na">android:background=</span><span class="s">&quot;@drawable/bg_widget&quot;</span>
<span class="nt">&gt;</span>
<span class="nt">&lt;ImageView</span>
<span class="na">android:id=</span><span class="s">&quot;@+id/imageIcon&quot;</span>
<span class="na">android:layout_width=</span><span class="s">&quot;40dp&quot;</span>
<span class="na">android:layout_height=</span><span class="s">&quot;40dp&quot;</span>
<span class="na">android:layout_marginTop=</span><span class="s">&quot;5dp&quot;</span>
<span class="na">android:src=</span><span class="s">&quot;@drawable/ic_pen&quot;</span>
<span class="na">android:layout_centerHorizontal=</span><span class="s">&quot;true&quot;</span>
<span class="na">android:contentDescription=</span><span class="s">&quot;@string/app_name&quot;</span>
<span class="nt">/&gt;</span>
<span class="nt">&lt;TextView</span>
<span class="na">android:id=</span><span class="s">&quot;@+id/textLabel&quot;</span>
<span class="na">android:layout_width=</span><span class="s">&quot;wrap_content&quot;</span>
<span class="na">android:layout_height=</span><span class="s">&quot;wrap_content&quot;</span>
<span class="na">android:layout_below=</span><span class="s">&quot;@id/imageIcon&quot;</span>
<span class="na">android:textColor=</span><span class="s">&quot;@color/widgetText&quot;</span>
<span class="na">android:layout_centerHorizontal=</span><span class="s">&quot;true&quot;</span>
<span class="na">tools:text=</span><span class="s">&quot;Label&quot;</span>
<span class="nt">/&gt;</span>
<span class="nt">&lt;/RelativeLayout&gt;</span>
</pre></div>
<p>So very simple, one icon on top, one label underneath, a bit of padding and <a href="https://github.com/theyann/oneclickonemail/blob/master/app/src/main/res/drawable/bg_widget.xml">an awesome background</a> that allows for rounded corners ... super classy!</p>
<h3 id="step-2-the-provider-configuration">Step 2: the provider configuration</h3>
<p>The provider will be the key to interact with the widget: it will manage its creation, update and deletion. It will be up to you to figure out a way to make it do that right.</p>
<p>First you must define the provider creating the <a href="http://developer.android.com/reference/android/appwidget/AppWidgetProviderInfo.html"><code>AppWidgetProviderInfo</code></a> with an XML file located in the <code>res/xml</code> folder that will be called <code>widget_info.xml</code> (for lack of more originality), and it&#39;ll look <a href="https://github.com/theyann/oneclickonemail/blob/master/app/src/main/res/xml-v17/widget_info.xml">like this</a>:</p>
<div class="highlight"><pre><span class="cp">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;</span>
<span class="nt">&lt;appwidget-provider</span> <span class="na">xmlns:android=</span><span class="s">&quot;http://schemas.android.com/apk/res/android&quot;</span>
<span class="na">android:minWidth=</span><span class="s">&quot;40dp&quot;</span>
<span class="na">android:minHeight=</span><span class="s">&quot;40dp&quot;</span>
<span class="na">android:updatePeriodMillis=</span><span class="s">&quot;0&quot;</span>
<span class="na">android:resizeMode=</span><span class="s">&quot;none&quot;</span>
<span class="na">android:previewImage=</span><span class="s">&quot;@drawable/ic_widget&quot;</span>
<span class="na">android:initialLayout=</span><span class="s">&quot;@layout/widget_layout&quot;</span>
<span class="na">android:configure=</span><span class="s">&quot;com.techyos.oneclickonemail.ui.activities.WidgetConfigActivity&quot;</span>
<span class="na">android:widgetCategory=</span><span class="s">&quot;home_screen&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;/appwidget-provider&gt;</span>
</pre></div>
<p><strong>Explanation of the parameters</strong> (because I&#39;m a nice guy, and you may deserve it!)<br>
As per <a href="http://developer.android.com/guide/practices/ui_guidelines/widget_design.html#anatomy_determining_size">the documentation</a>, the <code>minWidth</code> and <code>minHeight</code> in this case will represent a widget that is 1x1 columns on the screen, and it&#39;s not resizable (yes I know, I&#39;m lazy), which is why <code>resizeMode</code> is set to &quot;none&quot;.<br>
Next, the <code>updatePeriodMillis</code>. It is not important in this case as it will manually be triggered for every change by the user, and the data cannot change on its own, so it is set to 0 to avoid useless system overhead and CPU churning.</p>
<p>The <code>previewImage</code>is the image that will be displayed in the widget picker area.<br>
The <code>initialLayout</code> is the one we made earlier.<br>
The <code>configure</code> points to the configuration activity, which is an activity like any other activity, and that will allow you to get whatever configuration you need from the user for that widget. You&#39;ll see later that you can re-use this activity in the regular app.<br>
And finally <code>widgetCategory</code> (which is only available since api level 17 by the way, so take appropriate precautions) defines this widget to be on the <em>home screen only</em> and <em>not the lock screen</em> (which makes no more sense since api level 21 by the way).</p>
<p>Ok now that we have defined our awesome widget ... well we need to put together the stuff that will make it actually work. Which means --&gt; <strong>CODE!</strong> (woohoo!)</p>
<h3 id="step-3-provider-implementation">Step 3: provider implementation</h3>
<p>It&#39;s time for a little of real fun, enough with <em>XML</em>, let&#39;s do some <em>Java</em> (sorry <em><a href="https://kotlinlang.org/">Kotlin</a></em> will be for a later post).</p>
<p>So in order to understand what the provider is, and how it works, you have to understand how a widget works.<br>
A widget is an entity that works independently from an app. You cannot programmatically create or delete it from an app: that is up to the system, and to the end user, to decide to add a widget on the home screen, or remove it for that matter.<br>
And if you want to interact with it from an app or a service, you need some kind of a communication channel, and this channel is the <a href="http://developer.android.com/reference/android/appwidget/AppWidgetProvider.html"><code>AppWidgetProvider</code></a>.<br>
In the previous step, we have created an <em>XML</em> file describing the behavior of the widget, the system will figure things out based on that. Now we have to let the system know what instance of the provider to use in order for the widget to live.</p>
<p>First, we need to ad a few definitions in the <code>AndroidManifest.xml</code>, starting with the provider declaration which actually is a <a href="http://developer.android.com/reference/android/content/BroadcastReceiver.html"><code>BroadcastReceiver</code></a>:</p>
<div class="highlight"><pre><span class="nt">&lt;receiver</span> <span class="na">android:name=</span><span class="s">&quot;.ui.widgets.WidgetProvider&quot;</span> <span class="nt">&gt;</span>
<span class="nt">&lt;intent-filter&gt;</span>
<span class="nt">&lt;action</span> <span class="na">android:name=</span><span class="s">&quot;android.appwidget.action.APPWIDGET_UPDATE&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;action</span> <span class="na">android:name=</span><span class="s">&quot;android.appwidget.action.APPWIDGET_DELETED&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/intent-filter&gt;</span>
<span class="nt">&lt;meta-data</span> <span class="na">android:name=</span><span class="s">&quot;android.appwidget.provider&quot;</span>
<span class="na">android:resource=</span><span class="s">&quot;@xml/widget_info&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/receiver&gt;</span>
</pre></div>
<p>Notice the <em>intent filters</em>, which basically tells the system to wake this instance up when a widget is updated (= also created) or deleted. Then, there is that line (meta-data) that says &quot;and by the way, the configuration is in the xml file mentioned here&quot;.</p>
<p>Next thing, while we&#39;re in the manifest anyway, let&#39;s declare the configuration activity as well:</p>
<div class="highlight"><pre><span class="nt">&lt;activity</span> <span class="na">android:name=</span><span class="s">&quot;.ui.activities.WidgetConfigActivity&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;intent-filter&gt;</span>
<span class="nt">&lt;action</span> <span class="na">android:name=</span><span class="s">&quot;android.appwidget.action.APPWIDGET_CONFIGURE&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/intent-filter&gt;</span>
<span class="nt">&lt;/activity&gt;</span>
</pre></div>
<p>Again, note the intent filter specifying that the activity will react to a widget configuration intent.</p>
<p><strong>Enough with XML (finally)</strong><br>
So far, everything we have done have been &quot;by the book&quot;. All of that can be found pretty much exactly as is in the <a href="http://developer.android.com/guide/topics/appwidgets/index.html">official documentation</a>. What is not defined in the said documentation is what comes afterwards.</p>
<p>The point of this article is to show how to make a configurable widget, which means you have an activity that allows the user to set some values that will provide a specific behavior for the widget. <br>
We have declared this activity previously in the <code>AndroidManifest.xml</code>, as well as in the <code>appwidget-provider</code> XML, and the implementation of that activity is not very important as, I hope, you have already done tons of them. In this example, it is a simple form like activity that will write the data in the database using the received appwidget id as the key. </p>
<p>Now what is tricky is not the activity, it is the implementation of the provider, which we also have declared in the manifest earlier. And here is its implementation. <br>
There are (at least) 2 methods to override in order for everything to work smoothly:</p>
<h4 id="first-the-onupdate-method">First, the <a href="https://gist.github.com/theyann/be403ddf3b94ce32db87"><code>onUpdate</code> method</a>:</h4>
<div class="highlight"><pre><span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onUpdate</span><span class="o">(</span><span class="n">Context</span> <span class="n">context</span><span class="o">,</span> <span class="n">AppWidgetManager</span> <span class="n">appWidgetManager</span><span class="o">,</span> <span class="kt">int</span><span class="o">[]</span> <span class="n">appWidgetIds</span><span class="o">)</span> <span class="o">{</span>
<span class="n">WidgetEntryDao</span> <span class="n">dao</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">WidgetEntryDao</span><span class="o">(</span><span class="k">new</span> <span class="nf">DbHelper</span><span class="o">(</span><span class="n">context</span><span class="o">));</span>
<span class="kd">final</span> <span class="kt">int</span> <span class="n">N</span> <span class="o">=</span> <span class="n">appWidgetIds</span><span class="o">.</span><span class="na">length</span><span class="o">;</span>
<span class="c1">// Perform this loop procedure for each App Widget that belongs to this provider</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">N</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">appWidgetId</span> <span class="o">=</span> <span class="n">appWidgetIds</span><span class="o">[</span><span class="n">i</span><span class="o">];</span>
<span class="c1">// Finding the widget entry for the app widget id</span>
<span class="n">WidgetEntry</span> <span class="n">entry</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">findByWidgetId</span><span class="o">(</span><span class="n">appWidgetId</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">entry</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// creating the intent with all the information we want to pre-fill</span>
<span class="n">Intent</span> <span class="n">intent</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">Intent</span><span class="o">(</span><span class="n">Intent</span><span class="o">.</span><span class="na">ACTION_SEND</span><span class="o">);</span>
<span class="c1">// array of destination email addresses</span>
<span class="n">intent</span><span class="o">.</span><span class="na">putExtra</span><span class="o">(</span><span class="n">Intent</span><span class="o">.</span><span class="na">EXTRA_EMAIL</span><span class="o">,</span> <span class="n">entry</span><span class="o">.</span><span class="na">getTo</span><span class="o">());</span>
<span class="c1">// subject (optional)</span>
<span class="n">intent</span><span class="o">.</span><span class="na">putExtra</span><span class="o">(</span><span class="n">Intent</span><span class="o">.</span><span class="na">EXTRA_SUBJECT</span><span class="o">,</span> <span class="n">entry</span><span class="o">.</span><span class="na">getSubjectPrefix</span><span class="o">());</span>
<span class="c1">// little bonus, we&#39;re adding some kind of signature after the (optional) message</span>
<span class="n">intent</span><span class="o">.</span><span class="na">putExtra</span><span class="o">(</span><span class="n">Intent</span><span class="o">.</span><span class="na">EXTRA_TEXT</span><span class="o">,</span> <span class="n">entry</span><span class="o">.</span><span class="na">getMessagePrefix</span><span class="o">()</span> <span class="o">+</span> <span class="s">&quot;\n\n\n&quot;</span> <span class="o">+</span> <span class="n">context</span><span class="o">.</span><span class="na">getString</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">string</span><span class="o">.</span><span class="na">signature</span><span class="o">));</span>
<span class="c1">// and setting a type that will narrow the choice of apps that handle email related stuff</span>
<span class="n">intent</span><span class="o">.</span><span class="na">setType</span><span class="o">(</span><span class="s">&quot;message/rfc822&quot;</span><span class="o">);</span>
<span class="c1">// creating pending intent, the flag is REALLY important, and so is the appWidgetId</span>
<span class="n">PendingIntent</span> <span class="n">pendingIntent</span> <span class="o">=</span> <span class="n">PendingIntent</span><span class="o">.</span><span class="na">getActivity</span><span class="o">(</span><span class="n">context</span><span class="o">,</span> <span class="n">appWidgetId</span><span class="o">,</span> <span class="n">intent</span><span class="o">,</span> <span class="n">PendingIntent</span><span class="o">.</span><span class="na">FLAG_UPDATE_CURRENT</span><span class="o">);</span>
<span class="n">RemoteViews</span> <span class="n">views</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">RemoteViews</span><span class="o">(</span><span class="n">context</span><span class="o">.</span><span class="na">getPackageName</span><span class="o">(),</span> <span class="n">R</span><span class="o">.</span><span class="na">layout</span><span class="o">.</span><span class="na">widget_layout</span><span class="o">);</span>
<span class="c1">// using main layout to handle the click, so the whole widget is a button</span>
<span class="n">views</span><span class="o">.</span><span class="na">setOnClickPendingIntent</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">layoutWidget</span><span class="o">,</span> <span class="n">pendingIntent</span><span class="o">);</span>
<span class="c1">// setting the label</span>
<span class="n">views</span><span class="o">.</span><span class="na">setTextViewText</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">textLabel</span><span class="o">,</span> <span class="n">entry</span><span class="o">.</span><span class="na">getLabel</span><span class="o">());</span>
<span class="c1">// updating the widget because</span>
<span class="n">appWidgetManager</span><span class="o">.</span><span class="na">updateAppWidget</span><span class="o">(</span><span class="n">appWidgetId</span><span class="o">,</span> <span class="n">views</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p><strong>Few details</strong></p>
<ul>
<li>I won&#39;t get into details with the DAO, it is just my way of dealing with data on Android, I like the <a href="https://en.wikipedia.org/wiki/Separation_of_concerns"><strong>separation of concerns</strong></a>. Check out <a href="https://github.com/theyann/oneclickonemail/blob/master/app/src/main/java/com/techyos/oneclickonemail/db/dao/WidgetEntryDao.java">this file</a> for more information.</li>
<li>This method is called when a <code>APPWIDGET_UPDATE</code> intent is broadcasted. In our case it&#39;s when the widget is created, and when modification is made from the main app. Remember that we have set a <code>updatePeriodMillis</code> to 0, but had you set this value to some other number greater than 0, the intent would have been triggered by the system every that much milliseconds automatically.</li>
<li>About the way to open a pre-filled email app on Android, there are several ways of doing it, <a href="https://gist.github.com/theyann/33818d2159507c41c3bd"><strong>I know of 2</strong></a>. The solution displayed may not be the best as it may show some apps that do not send emails in the app selection dialog. But it works, and I can set multiple recipients :).</li>
<li>The biggest problem I faced was that if I had several widgets with a different configuration, they would all open with the configuration of the first widget. I finally found out about the <code>PendingIntent.FLAG_UPDATE_CURRENT</code> flag that is set during the construction of the <code>PendingIntent</code> instance, which saved my life. Also, the <code>appWidgetId</code> in there is not mandatory but will help to focus this particular <code>PendingIntent</code> instance with that particular widget and avoid weird behaviors. This is my version of a winning combination!</li>
</ul>
<h4 id="second-the-ondelete-method">Second, the <a href="https://gist.github.com/theyann/210f0d1b92802abc1aaa"><code>onDelete</code> method</a>:</h4>
<div class="highlight"><pre><span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onDeleted</span><span class="o">(</span><span class="n">Context</span> <span class="n">context</span><span class="o">,</span> <span class="kt">int</span><span class="o">[]</span> <span class="n">appWidgetIds</span><span class="o">)</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">.</span><span class="na">onDeleted</span><span class="o">(</span><span class="n">context</span><span class="o">,</span> <span class="n">appWidgetIds</span><span class="o">);</span>
<span class="n">WidgetEntryDao</span> <span class="n">dao</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">WidgetEntryDao</span><span class="o">(</span><span class="k">new</span> <span class="nf">DbHelper</span><span class="o">(</span><span class="n">context</span><span class="o">));</span>
<span class="kd">final</span> <span class="kt">int</span> <span class="n">N</span> <span class="o">=</span> <span class="n">appWidgetIds</span><span class="o">.</span><span class="na">length</span><span class="o">;</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">N</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
<span class="n">dao</span><span class="o">.</span><span class="na">deleteByWidgetId</span><span class="o">(</span><span class="n">appWidgetIds</span><span class="o">[</span><span class="n">i</span><span class="o">]);</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>Not much to explain here, other than the fact that the method is called when a <code>APPWIDGET_DELETED</code> intent is broadcasted by the system, meaning when the user is removing the widget from his/her home screen. <br>
Basically here, I&#39;m back again with my DAO object and I delete the widget corresponding to the received id from the database, that&#39;s it.<br>
Note: if you try to broadcast this yourself in the app, the system will throw a very nice <code>java.lang.SecurityException: Permission Denial</code> exception because as <a href="http://developer.android.com/reference/android/appwidget/AppWidgetManager.html#ACTION_APPWIDGET_DELETED">stated in the documentation</a>, this intent can only be broadcasted by the system.</p>
<h3 id="step4-what-39-s-left">Step4: What&#39;s left?</h3>
<p>So now we have the widget&#39;s layout, the configuration, the provider ... what&#39;s left?<br>
In our example, the widget is a button, and the button opens up an (email) app installed on the device. But a widget could do all sorts of stuff like displaying information, or sending data to a server, etc.</p>
<p>In this example, I decided that the main app could let the user change the configuration at will, and thus I have a list of all the widget configurations that have been written in the database, and with a tap on one of the list item, the configuration activity is launched again and fills the form entries the data corresponding data, save that data in the database once the changes are made, and then broadcast a <code>APPWIDGET_UPDATE</code> intent afterwards so that the whole update process will occur as the platform intended it to.</p>
<p>In another app that I have made, I didn&#39;t need any UI on click, I needed to send some information to a server through some <a href="https://en.wikipedia.org/wiki/Representational_state_transfer">REST API</a>. In that case the provider was very similar, but instead of calling an activity, I was calling an <a href="http://developer.android.com/reference/android/app/IntentService.html"><code>IntentService</code></a> instead. The <code>PendingIntent</code> construction code looked more like this:</p>
<div class="highlight"><pre><span class="n">PendingIntent</span> <span class="n">pendingIntent</span> <span class="o">=</span> <span class="n">PendingIntent</span><span class="o">.</span><span class="na">getService</span><span class="o">(</span><span class="n">context</span><span class="o">,</span> <span class="n">appWidgetId</span><span class="o">,</span> <span class="n">intent</span><span class="o">,</span> <span class="n">PendingIntent</span><span class="o">.</span><span class="na">FLAG_UPDATE_CURRENT</span><span class="o">);</span>
</pre></div>
<p>Notice the <code>PendingIntent.getService</code> instead of <code>PendingIntent.getActivity</code> as we have used earlier. The difference is pretty self explanatory, but the flags and parameters are exactly the same.</p>
<p>So basically now it&#39;s up to you to decide what&#39;s next. Depending on your requirements, hopes and dreams, figure out what is the best course of action for you, I think you have all the pieces here.</p>
<h1 id="conclusion">Conclusion</h1>
<p>Developing a widget is not complicated, it&#39;s just a lot of stuff and steps to do. <br>
I find that the official documentation is lacking a bunch of details, such as the little tips that I&#39;ve been giving throughout this post: the flags for the <code>PendingIntent</code>, how to communicate the configuration, how to call a service, etc.</p>
<p>Also, it is nice to have a proper understanding of how things are working ... it tends to remove a lot of frustrations :) So for instance, understanding the principle of broadcast receivers help with understanding the provider. Knowing about the intent mechanism also helps with the way we can communicate data across.</p>
<p>The full app is open source and completely available <a href="https://github.com/theyann/oneclickonemail"><strong>on github</strong></a>. Don&#39;t hesitate to clone it, fork it, do whatever you want with it.<br>
Feel free to get back to me if I wasn&#39;t clear enough, if I made a mistake, if you found better ways of doing things, or to let me know that this was useful to you. <br>
Thanks a bunch for reading, see you next time!</p>
Yannick Lemintag:www.yannicklemin.com,2005:Article/189962015-10-25T03:13:00-05:002018-11-16T05:43:57-06:00Initial Commit<p>I have wanted to write a blog for a while, but never took the time. So now here it is.</p>
<p>I&#39;ve been working on Android development for a while now, I think I started tinkering in 2008 I didn&#39;t even own a compatible phone at the time. <br>
I worked on a bunch of mobile project, mostly native Android, but also some with PhoneGap, and Titanium but really it&#39;s native Android that I liked the best.</p>
<p>So it&#39;s been 7 years, and lately for the first time, I actually have put my very app on the store. It was actually my first encounter with making widgets ... I figured why not put some ads in it and try to become rich? </p>
<p>So here it is: <a href="https://play.google.com/store/apps/details?id=com.techyos.fitdrinkup">Fit DrinkUp!</a>.<br>
If you are a fitbit user like me, and you were annoyed at tracking your water consumption like me (that makes about 1 of us ... yes I know ... I should have researched the demand a little bit more), this app allows you to add pre-configured widgets on your home screen which will log the configured amount of water onto your account.</p>
<h2 id="so-i-have-learned-about">So I have learned about:</h2>
<ul>
<li>configurable widgets</li>
<li>how poor the widget documentation is</li>
<li>how to put ads on a view (which is actually quite simple)</li>
<li>that I might not have made the most profitable app for my first official!</li>
</ul>
<p>This was indeed fun, and I will certainly make an entry in the near future with some more insights about widget making, and the difficulties that I have encountered.<br>
In the meantime, go and try <a href="https://play.google.com/store/apps/details?id=com.techyos.fitdrinkup">the app</a>, let me know how you like it, send me <strong>feedbacks</strong>.</p>
<p>Over and out!</p>
Yannick Lemin