<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Ivan Shafran on Medium]]></title>
        <description><![CDATA[Stories by Ivan Shafran on Medium]]></description>
        <link>https://medium.com/@shafran?source=rss-9899144a13c8------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*bWE2ngbDa_vzWwINHwk_cQ.jpeg</url>
            <title>Stories by Ivan Shafran on Medium</title>
            <link>https://medium.com/@shafran?source=rss-9899144a13c8------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 23 Jun 2026 13:40:03 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@shafran/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Let’s make a game with a smile control]]></title>
            <link>https://proandroiddev.com/lets-make-a-game-with-a-smile-control-256981c38e62?source=rss-9899144a13c8------2</link>
            <guid isPermaLink="false">https://medium.com/p/256981c38e62</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[game-development]]></category>
            <category><![CDATA[ml-kit]]></category>
            <category><![CDATA[hackathons]]></category>
            <dc:creator><![CDATA[Ivan Shafran]]></dc:creator>
            <pubDate>Mon, 03 Jan 2022 19:07:59 GMT</pubDate>
            <atom:updated>2022-01-03T19:07:59.574Z</atom:updated>
            <content:encoded><![CDATA[<p>Sometimes I visit hackathons where I can implement any crazy ideas. Today I will tell you how to make a mobile game prototype with unusual controls in just a couple of hours: a character will react to a smile and a wink.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*eXNt311NtnZ7mUiY" /><figcaption>Photo by <a href="https://unsplash.com/@erictang2769?utm_source=medium&amp;utm_medium=referral">Erick Tang</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>How we got this idea</h3><p>The idea to create such a game came to me during a hackathon several years ago. The format assumed that I had one working day to develop, that is, 8 hours. I chose the Android SDK to get the prototype done in time. Perhaps game engines would be better suited, but I don’t know any of them good enough.</p><p>Another game suggested to me the concept of control with the help of emotions: there you could set the character’s movements by changing the volume of your voice. Maybe already someone has also used emotions in the game control. But I knew few such examples, so I settled on this format.</p><p>Watch out! It is a loud video!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fu7Mk75m8-Ic%3Fstart%3D81%26feature%3Doembed%26start%3D81&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Du7Mk75m8-Ic&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fu7Mk75m8-Ic%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/1af8ee33351a8ce7ed6f1af638987452/href">https://medium.com/media/1af8ee33351a8ce7ed6f1af638987452/href</a></iframe><h3>Setting up the development environment</h3><p>We only need <a href="https://developer.android.com/studio/install">Android Studio</a> on the computer. If you don’t have <a href="https://developer.android.com/training/basics/firstapp/running-app#RealDevice">a real Android device</a> to run, you can use <a href="https://developer.android.com/training/basics/firstapp/running-app#Emulator">an emulator</a> with <a href="https://stackoverflow.com/a/30792615/7958563">a webcam enabled</a>.</p><h4>Creating a project with ML Kit</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/856/0*vSVVIk1YO2t-25Sq.png" /></figure><p><a href="https://developers.google.com/ml-kit">ML Kit</a> is a great tool to impress the hackathon jury as you use AI in your prototype! It also helps you embed machine learning solutions into projects, such as functionality for defining objects in a frame, as well as translation and OCR.</p><p>It is suitable for us that ML Kit has a free offline API for recognizing smiles and open or closed eyes.</p><p>Previously, we had to first register in the Firebase console in order to create any project with ML Kit. Now we can skip this step for offline functionality.</p><h3>Android app</h3><h4>Removing unnecessary</h4><p>Let’s take the official sample and remove what we don’t need so as not to write the logic for working with the camera from scratch.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/0*zwRYrTMy-o_fjf9X.gif" /></figure><p>First, download <a href="https://github.com/googlesamples/mlkit/tree/c92758e7b268030766091b4557bfabda4c222303/android/vision-quickstart">the example</a> and try running it. Explore the Face detection mode: it will look like the article preview.</p><blockquote>Note that the link goes to the specific commit in the past. The tutorial uses this particular version of the sample as its base. You surely can use <a href="https://github.com/googlesamples/mlkit/tree/master/android/vision-quickstart">the latest version of the sample</a>, but you’ll have to match the diffs and adapt the ideas to the new version.</blockquote><h4>Manifest</h4><p>Let’s start editing AndroidManifest.xml. We will remove all activity tags except the first one. And we will put the CameraXLivePreviewActivity in its place so that we can start from the camera right away. We leave only face in the android:value attribute to exclude unnecessary resources from the APK.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c84e8ece2d2b2c6394daca87163fb07b/href">https://medium.com/media/c84e8ece2d2b2c6394daca87163fb07b/href</a></iframe><p><a href="https://github.com/IvanShafran/emotion-control-game-prototype/commit/308329405d6c9669a2fa8246580c0bcb925c7a9f">Full diff.</a></p><h4>Camera</h4><p>We will save time and won’t delete unnecessary files, and instead, we will focus on the elements of the CameraXLivePreviewActivity screen.</p><p>On line 117, we will set the face detection mode:</p><pre><strong>private</strong> String selectedModel = FACE_DETECTION;</pre><p>On line 118, we will turn on the front camera:</p><pre><strong>private</strong> <strong>int</strong> lensFacing = CameraSelector.LENS_FACING_FRONT;</pre><p>At the end of the onCreate method we will hide the settings on lines 198–199:</p><pre>findViewById(R.id.settings_button).setVisibility(View.GONE); findViewById(R.id.control).setVisibility(View.GONE);</pre><p>We can stop at this point. But if the FPS rendering and face grid are visually distracting, then you can turn them off in the following way:</p><p>In the VisionProcessorBase.java file, we remove lines 213–215 to hide the FPS:</p><pre>graphicOverlay.add(<br>       new InferenceInfoGraphic(<br>          graphicOverlay, currentLatencyMs, shouldShowFps ? framesPerSecond : null));</pre><p>In the FaceDetectorProcessor.java file, we remove lines 75–78 to hide the face grid:</p><pre>for (Face face : faces) {<br>    graphicOverlay.add(new FaceGraphic(graphicOverlay, face));<br>    logExtrasForTesting(face);<br>}</pre><p><a href="https://github.com/IvanShafran/emotion-control-game-prototype/commit/dc76cb50ce67e41f61aec8d047421620666e3a5b">Full diff.</a></p><h4>Emotion recognition</h4><p>Smile detection is turned off by default, but it’s straightforward to get started. It’s not for nothing that we took the example code as a basis! We will allocate the parameters we need into a separate class and declare the listener interface:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4178d7d5a598a475f8b43e2bc7926104/href">https://medium.com/media/4178d7d5a598a475f8b43e2bc7926104/href</a></iframe><p>We will set up the FaceDetectorProcessor in the CameraXLivePreviewActivity class and subscribe to receive the emotion state to enable emotion classification. Then we convert the probabilities to boolean flags. For testing, we will add a TextView to the layout, in which we will show emotions through emoticons.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*bFAqx69JEj2TTnZ3.png" /></figure><p><a href="https://github.com/IvanShafran/emotion-control-game-prototype/commit/7cadcdede6a4bb67a32d78ffd23e0d44f25d0eec">Full diff.</a></p><h4>Divide and conquer</h4><p>We are making a game, so we need a place to draw the elements. We will assume that it runs in portrait mode on the phone. Let’s split the screen into two parts: the camera on top and the game on the bottom.</p><p>Controlling a character with a smile is a difficult task, and the hackathon has little time to implement advanced mechanics. Therefore, our character will collect cool things along the way, being either at the top of the playing field or at the bottom. We will add actions with closed or open eyes as a complication of the game: we caught cool things with closed eyes, which means the points are doubled.</p><p>If you want to implement different gameplay, then I can suggest you some other options:</p><ul><li>Guitar Hero/Just Dance — analog, where you need to show a certain emotion to the music;</li><li>a race with overcoming obstacles, where you need to reach the finish line in a specific time or without crashing;</li><li>shooter, where the player shoots the enemy with a wink.</li></ul><p>We will display the game in a custom Android View. In the onDraw method, we will draw the character to Canvas. In the first prototype, we will restrict ourselves to geometric primitives.</p><h4>Player</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/793/0*R_SEc38WSZeyNvKd.png" /></figure><p>Our character is a square. We’ll size it and position it to the left on initialization since it will be fixed to the same place. The Y-axis position will depend on the player’s smile. We will calculate all absolute values ​​relative to the size of the game area. It’s easier than choosing specific sizes, and we will also get a good look on other devices.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/765fe4c1fa2f5c9c11b7153be12048b9/href">https://medium.com/media/765fe4c1fa2f5c9c11b7153be12048b9/href</a></iframe><h4>Cake</h4><p>Our character “runs” and tries to catch cakes to score as many points as possible. We use the standard technique with the transition to the reference system relative to the player: he will stand still, and the cakes will fly towards him. If the cake square intersects with the player’s square, we count the point. And if at the same time at least one of the user’s eyes is closed, we count two points. ¯ \ _ (ツ) _ / ¯</p><p>Also there will be only one cake in our universe. When a character eats it, it moves off the screen to a random line with a random coordinate.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0050419e82afa32cb873f8420f1549f6/href">https://medium.com/media/0050419e82afa32cb873f8420f1549f6/href</a></iframe><h3>Intermediate results</h3><p>We will make the display of points very simple. We will display the number in the screen center. We only need to consider the text height and indent the top for beauty.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a3c877fcd8d54de2d5b49669351c4c99/href">https://medium.com/media/a3c877fcd8d54de2d5b49669351c4c99/href</a></iframe><p>Let’s see what game we made:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FDtMwDzEYl1Q%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DDtMwDzEYl1Q&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FDtMwDzEYl1Q%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/9a8674899e2f7cad68eeb31dc1e37ec8/href">https://medium.com/media/9a8674899e2f7cad68eeb31dc1e37ec8/href</a></iframe><h3>Graphics</h3><p>We’ll add some graphics so we won’t be ashamed to show the game at the hackathon presentation!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*uoz70tN5_BIJ2qLO.png" /></figure><h4>Images</h4><p>We don’t know how to draw impressive graphics. Fortunately, there are websites with free game assets. I liked <a href="https://web.archive.org/web/20191004010332/https://www.gameart2d.com/freebies.html">this website</a>, although it is currently not available directly for a reason unknown to me.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/542/0*rU-bQpcaC-bSEqYZ.png" /></figure><h4>Animation</h4><p>We draw on Canvas, which means we need to implement the animation ourselves. If there are pictures with animation, it will be easy to program them. We introduce a class for an object with images that alternate with each other.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/593e776a7611fdc626e3eb02193fe394/href">https://medium.com/media/593e776a7611fdc626e3eb02193fe394/href</a></iframe><p>The background also needs to be animated to get the motion effect. Having a series of background frames in memory is expensive. Therefore, we will do a trickier thing: draw one image with a time shift. Idea outline:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*bExXByChD1kumZrY.png" /></figure><p><a href="https://github.com/IvanShafran/emotion-control-game-prototype/commit/0e22be63149d2ee62d9b1f92eab24d42487fd5a2">Full diff.</a></p><h3>Final result</h3><p>It’s hardly a masterpiece, but it’s okay for a prototype overnight. You can find the code <a href="https://github.com/IvanShafran/emotion-control-game-prototype">here</a>. It runs locally without any additional steps.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F4eW7JAhXRP8%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D4eW7JAhXRP8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F4eW7JAhXRP8%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/46dfadaca8ab5b5aa9ca8614925b6cf7/href">https://medium.com/media/46dfadaca8ab5b5aa9ca8614925b6cf7/href</a></iframe><p>Finally, I will add that ML Kit Face Detection can be useful for other scenarios.</p><p>For example, you can analyze all the people in the frame and make sure everyone smiles and opens their eyes to take perfect selfies with friends. Detecting multiple faces in a video stream works out of the box, so the task is not difficult.</p><p>Using face contour recognition from the Face Detection module helps to replicate the masks that are now popular in almost all camera apps. And if we add interactivity through the definition of a smile and a wink, they will be doubly fun to use.</p><p>This functionality — face contour recognition — can be used for more than just entertainment. Those who have tried to cut out a photo for documents themselves will appreciate this feature. We take the face contour and automatically crop out the photo with the desired aspect ratio and the correct head position. The gyroscope sensor will help determine the proper shooting angle.</p><p><strong>Let’s become friends on </strong><a href="https://twitter.com/NotShafran"><strong>Twitter</strong></a><strong>, </strong><a href="https://github.com/IvanShafran"><strong>Github, </strong></a><strong>and </strong><a href="https://www.facebook.com/not.shafran"><strong>Facebook</strong></a><strong>!</strong></p><pre><strong>Clap, share and follow me if you like it🐱‍💻</strong></pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=256981c38e62" width="1" height="1" alt=""><hr><p><a href="https://proandroiddev.com/lets-make-a-game-with-a-smile-control-256981c38e62">Let’s make a game with a smile control</a> was originally published in <a href="https://proandroiddev.com">ProAndroidDev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Note Keeper with ML —  A Pet Project Idea in Details]]></title>
            <link>https://proandroiddev.com/note-keeper-with-ml-a-pet-project-idea-in-details-f91dd4fa8f02?source=rss-9899144a13c8------2</link>
            <guid isPermaLink="false">https://medium.com/p/f91dd4fa8f02</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[android-development]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[androiddev]]></category>
            <category><![CDATA[kotlin]]></category>
            <dc:creator><![CDATA[Ivan Shafran]]></dc:creator>
            <pubDate>Tue, 19 May 2020 19:04:50 GMT</pubDate>
            <atom:updated>2020-05-19T19:54:22.672Z</atom:updated>
            <content:encoded><![CDATA[<h3>Note Keeper with ML — A Pet Project Idea</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oBKAtentlDRcNbZE" /><figcaption>Photo by <a href="https://unsplash.com/@kylejglenn?utm_source=medium&amp;utm_medium=referral">Kyle Glenn</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>The article presents a pet project idea for Android developers. It includes design in Figma, useful links, and other tips.</p><p>Initially, I’ve created the materials for an Android course for beginners. Most students were able to implement a project from scratch, so I believe this pet project is a good start point in Android development. Experienced developers may use it as a code sample for job applications.</p><h3>An empty project</h3><p>A good start is essential. Let’s create an empty project in Android Studio. Almost all default preferences are okay. Check several instructions below:</p><ul><li>Set 21 min API. It simplifies API usage a lot.</li><li>Add .idea folder to root .gitignore . It contains files from .idea by default, but there is usually no need to keep any of .idea files.</li><li>If you are familiar with Kotlin, enable it in the empty project wizard. Kotlin is the preferred language for Android development.</li><li>Add project under git, for example, on GitHub. Try to give a meaningful name for every commit. Moreover, commit code piece by piece. It is a positive sign for those who will discover your repository.</li></ul><p>Links: <a href="https://developer.android.com/studio">install Android Studio</a>, <a href="https://developer.android.com/studio/run/emulator">run an app on an emulator</a>, <a href="https://developer.android.com/studio/run/device">on the device</a>.</p><h3>First screen</h3><p>The first screen contains an image and text. Content is static for now. The task is to create this in an Activity.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.figma.com%2Fembed%3Fembed_host%3Doembed%26url%3Dhttps%3A%2F%2Fwww.figma.com%2Ffile%2FgVJdhLJR54Odhw8hRwYpkq%2FFirst%3Fnode-id%3D0%253A1&amp;display_name=Figma&amp;url=https%3A%2F%2Fwww.figma.com%2Ffile%2FgVJdhLJR54Odhw8hRwYpkq%2FFirst%3Fnode-id%3D0%253A1&amp;image=https%3A%2F%2Fapi-cdn.figma.com%2Fresize%2Fthumbnails%2F800c6de3-ef46-416c-bd96-a8770c3b9380%3Fheight%3D450%26bucket%3Dfigma-alpha&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=figma" width="800" height="450" frameborder="0" scrolling="no"><a href="https://medium.com/media/58a5abca5982dab03b82e5c723e41169/href">https://medium.com/media/58a5abca5982dab03b82e5c723e41169/href</a></iframe><p>Please sign in to Figma to get full information about the design. Pay attention to the distance between elements on the screen.</p><p>It looks easy to implement but try to see it in landscape mode. Also, try different image shapes and text that doesn’t fit in the screen.</p><h3>Landscape</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/664/1*kKtqwPxBT2pwK0St3OV8Hg.png" /></figure><p>Okay, let’s lay down for a second and rest after the hard work. Oh no, our app looks strange in landscape mode. The image is small, and it is hard to read the text. Therefore we need to study <a href="https://developer.android.com/guide/topics/resources/providing-resources">resource directory qualifiers</a>.</p><p>I propose to implement a landscape layout as displayed below. The screen is divided into two parts horizontally.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.figma.com%2Fembed%3Fembed_host%3Doembed%26url%3Dhttps%3A%2F%2Fwww.figma.com%2Ffile%2FiUCtNT4yrZ2ChKIVso7J69%2FFirst-landscape%3Fnode-id%3D0%253A1&amp;display_name=Figma&amp;url=https%3A%2F%2Fwww.figma.com%2Ffile%2FiUCtNT4yrZ2ChKIVso7J69%2FFirst-landscape%3Fnode-id%3D0%253A1&amp;image=https%3A%2F%2Fapi-cdn.figma.com%2Fresize%2Fthumbnails%2Fa708c200-a51c-4c47-8de6-7851301e7439%3Fheight%3D223%26bucket%3Dfigma-alpha&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=figma" width="800" height="450" frameborder="0" scrolling="no"><a href="https://medium.com/media/6a8dde69255b1ef23a496feff03fd443/href">https://medium.com/media/6a8dde69255b1ef23a496feff03fd443/href</a></iframe><h3>List</h3><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.figma.com%2Fembed%3Fembed_host%3Doembed%26url%3Dhttps%3A%2F%2Fwww.figma.com%2Ffile%2Fj8kMewWQ7ARTMsRlFsGVNO%2FList&amp;display_name=Figma&amp;url=https%3A%2F%2Fwww.figma.com%2Ffile%2Fj8kMewWQ7ARTMsRlFsGVNO%2FList&amp;image=https%3A%2F%2Fapi-cdn.figma.com%2Fresize%2Fthumbnails%2Ff73dca47-968e-4c5e-bd6b-cc7e52b4a9a1%3Fheight%3D450%26bucket%3Dfigma-alpha&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=figma" width="800" height="450" frameborder="0" scrolling="no"><a href="https://medium.com/media/096f3e87e1b7b1b24c29c1a45f14482b/href">https://medium.com/media/096f3e87e1b7b1b24c29c1a45f14482b/href</a></iframe><p>Now move on to more complicated exercises. Take a look at the list design above. In Android, it is usually implemented via <a href="https://developer.android.com/guide/topics/ui/layout/recyclerview">RecyclerView</a>. An element of the list has a rounded border. The easiest way to achieve it is a <a href="https://developer.android.com/guide/topics/ui/layout/cardview">CardView</a>.</p><p>At this point, you could still use stub data. We will connect to a database later.</p><h3>Pad</h3><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.figma.com%2Fembed%3Fembed_host%3Doembed%26url%3Dhttps%3A%2F%2Fwww.figma.com%2Ffile%2Fdayv3QCVVVJk7ohZibEiHU%2FPad%3Fnode-id%3D0%253A1&amp;display_name=Figma&amp;url=https%3A%2F%2Fwww.figma.com%2Ffile%2Fdayv3QCVVVJk7ohZibEiHU%2FPad%3Fnode-id%3D0%253A1&amp;image=https%3A%2F%2Fapi-cdn.figma.com%2Fresize%2Fthumbnails%2Fab3c338d-439e-4137-a125-aa142a1d66a1%3Fheight%3D450%26bucket%3Dfigma-alpha&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=figma" width="800" height="450" frameborder="0" scrolling="no"><a href="https://medium.com/media/48f189336f1ae4012ffbcb9822b5f3cb/href">https://medium.com/media/48f189336f1ae4012ffbcb9822b5f3cb/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xT4Szh0D7XXiJs6h.jpg" /></figure><p>Sorry, but I’ll blow your mind with multiple-device configuration. As you can see we should show the double-row list in the portrait mode and one-row list in the landscape mode. Moreover, the detail screen should be placed alongside the list screen.</p><p>If you can’t beat that task, take a look at <a href="https://github.com/IvanShafran/ml-note-keeper-pieces/tree/master/PadSample">this sample</a>. There are several ways to implement it, so it’s okay if your solution differs from the sample.</p><h4>Pad testing</h4><p>Without a tablet device, you could use an Android emulator to test different configurations. The more implicit way is to change the “smallest width” in the developer settings.</p><h3>Camera</h3><p>Our camera screen should be able to take and save a photo.</p><p>Implementing a camera from scratch on Android has been painful for many years. Because of this camera libraries exist to simplify our code:</p><ul><li><a href="https://github.com/natario1/CameraView">https://github.com/natario1/CameraView</a></li><li><a href="https://github.com/CameraKit/camerakit-android">https://github.com/CameraKit/camerakit-android</a></li><li><a href="https://github.com/RedApparat/Fotoapparat">https://github.com/RedApparat/Fotoapparat</a></li></ul><p>You could use them if you’d like. However, I’d suggest checking the new <a href="https://developer.android.com/training/camerax">CameraX library</a> from the Android team. At the point of writing this article, it is still in the beta version. Despite this, I hope CameraX is the future, so I prepared a <a href="https://github.com/IvanShafran/ml-note-keeper-pieces/tree/master/CameraX">sample</a> in case you struggle with implementation details.</p><p>I left behind the scenes the easiest implementation. You could just <a href="https://developer.android.com/training/camera/photobasics">ask Android</a> to take a photo for you. But it is boring, isn’t it?</p><p>One last tip about the camera. You should learn about <a href="https://developer.android.com/guide/topics/permissions/overview">permissions</a> and ask the camera permission before starting the preview.</p><h4>CameraX troubleshooting</h4><p>In the case of <strong>Caused by: java.lang.BootstrapMethodError: Exception from call site #0 bootstrap method </strong>or similar during CameraView inflating, enable Java 1.8 compatibility:</p><pre>compileOptions <strong>{<br>    </strong>sourceCompatibility JavaVersion.<em>VERSION_1_8<br>    </em>targetCompatibility JavaVersion.<em>VERSION_1_8<br></em><strong>}<br><br></strong>kotlinOptions <strong>{<br>    </strong>jvmTarget = &quot;1.8&quot;<br><strong>}</strong></pre><h3>ML Kit</h3><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.figma.com%2Fembed%3Fembed_host%3Doembed%26url%3Dhttps%3A%2F%2Fwww.figma.com%2Ffile%2FXEiOlUEDSz1CVPlNUzHL1o%2FCamera%3Fnode-id%3D0%253A1&amp;display_name=Figma&amp;url=https%3A%2F%2Fwww.figma.com%2Ffile%2FXEiOlUEDSz1CVPlNUzHL1o%2FCamera%3Fnode-id%3D0%253A1&amp;image=https%3A%2F%2Fapi-cdn.figma.com%2Fresize%2Fthumbnails%2F4d83b190-0c08-4e47-aae0-54ac617a0a7a%3Fheight%3D450%26bucket%3Dfigma-alpha&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=figma" width="800" height="450" frameborder="0" scrolling="no"><a href="https://medium.com/media/acbbbc305d95b9d5eefc1250fef59e85/href">https://medium.com/media/acbbbc305d95b9d5eefc1250fef59e85/href</a></iframe><p>The most magical part of our application will be done by ML Kit from Google. It has free offline support for Latin-based languages. Just follow steps in <a href="https://firebase.google.com/docs/ml-kit/android/recognize-text">this tutorial</a>. There are several ways to recognize text on the image using the ML Kit API. I assume, that in the previous part we saved a photo to the disk, so we will use code like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b81b1a61766b3cc4d4118dedb042b60e/href">https://medium.com/media/b81b1a61766b3cc4d4118dedb042b60e/href</a></iframe><h3>Database</h3><p>Now it is a good time to implement a database. You could use this <a href="https://developer.android.com/training/data-storage/sqlite">tutorial</a> to implement it. Additionally, I implemented <a href="https://github.com/IvanShafran/ml-note-keeper-pieces/tree/master/DatabaseSample">the sample</a>. But we’ll notice the warning:</p><blockquote><strong>Caution:</strong> Although these APIs are powerful, they are fairly low-level and require a great deal of time and effort to use.</blockquote><p><a href="https://developer.android.com/training/data-storage/room">This article</a> describes the Room library good enough, so check it out. Generally, the implementation is easy, the only unobvious thing is using a background thread for all operations. Even DAO creation takes a noticeable amount of time, which may cause UI lags.</p><h3>Test</h3><p>In my opinion, testing an Android application is hard, but it worth it. As you know, there are unit tests, functional tests, and so on. However, on Android, I would divide tests into three main categories:</p><ul><li>Local tests that could be run on the JVM.</li><li>Instrumented tests which should be run on device or emulator. Tests check classes.</li><li>UI tests which should be run on device or emulator. Tests check application UI.</li></ul><p>You should write as many local tests as you can because they are fast, easy to run. Unfortunately, they are hard to write. Therefore I wrote an article about them.</p><p><a href="https://proandroiddev.com/evolution-of-unit-tests-in-android-daa3c76b0494">Evolution of unit tests in Android</a></p><h3>The end</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*XPO2svdFuAGGnBE77ZBoKw.png" /></figure><p>I understand that following this tutorial may be hard if you are new to Android development. You could check my implementation version below:</p><p><a href="https://github.com/IvanShafran/note-app">IvanShafran/note-app</a></p><p>Note that the recognition will not work without package.json file. I can’t post it due to security reasons. You could generate this file in Firebase and use it.</p><p><strong>Let’s become friends on </strong><a href="https://twitter.com/NotShafran"><strong>Twitter</strong></a><strong>, </strong><a href="https://github.com/IvanShafran"><strong>Github, </strong></a><strong>and </strong><a href="https://www.facebook.com/not.shafran"><strong>Facebook</strong></a><strong>!</strong></p><pre><strong>Clap, share and follow me if you like it🐱‍💻</strong></pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f91dd4fa8f02" width="1" height="1" alt=""><hr><p><a href="https://proandroiddev.com/note-keeper-with-ml-a-pet-project-idea-in-details-f91dd4fa8f02">Note Keeper with ML —  A Pet Project Idea in Details</a> was originally published in <a href="https://proandroiddev.com">ProAndroidDev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Evolution of unit tests in Android]]></title>
            <link>https://proandroiddev.com/evolution-of-unit-tests-in-android-daa3c76b0494?source=rss-9899144a13c8------2</link>
            <guid isPermaLink="false">https://medium.com/p/daa3c76b0494</guid>
            <category><![CDATA[unit-testing]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[android-app-development]]></category>
            <dc:creator><![CDATA[Ivan Shafran]]></dc:creator>
            <pubDate>Thu, 22 Aug 2019 13:41:21 GMT</pubDate>
            <atom:updated>2019-08-22T13:41:21.739Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*nZC0T9pA9BNetxtP" /><figcaption>Photo by <a href="https://unsplash.com/@tateisimikito?utm_source=medium&amp;utm_medium=referral">Jukan Tateisi</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>In the article we take a look at the unit test evolution from beginner to pro-level. “Rate us” dialog is a popular feature, and it will be a good example. Typical “rate us” dialog has requirements like:</p><ul><li>Should be shown after some condition or user action</li><li>Has “rate us” button that leads to Google Play</li><li>Has “remind me later” button that schedules dialog to show after some time(2 months in our case)</li><li>Has “never show again” button that hides the dialog forever</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/379/1*FO-i17Sc89KakyUOD47pUw.png" /><figcaption>Android “rate us” implemented via AlertDialog</figcaption></figure><h3>Zero version: no unit tests</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*m4Xf74GU-uP9xkif.jpg" /><figcaption><a href="https://imgflip.com/i/383h35">https://imgflip.com/i/383h35</a></figcaption></figure><p>At the beginning of the Android community, unit tests were not so popular. There are several arguments behind this:</p><ul><li>Tests require time to be implemented and maintained</li><li>Apps were mostly simple</li><li>The framework itself isn’t friendly for writing unit tests</li></ul><h3>First version: my first unit test</h3><p>But unfortunately, “rate us” dialog is a too vital feature to ignore unit tests. The more users leave reviews, the more new users your app gets. Also, it should not be annoying. Otherwise, people will leave 1-star reviews.</p><p>I’ve implemented a sample app that follows the logic described in the introduction. To trigger dialog, a user should click button two times. <a href="https://github.com/IvanShafran/android-unit-tests-evolution-rate-us-dialog">Check code in the repository</a>.</p><p>To code first unit test, I had to do several things.</p><h4>Learn a little about <a href="https://junit.org/junit5/">JUnit Framework</a></h4><pre><strong>Feel free to skip this chapter if you are familiar with JUnit.</strong></pre><p>JUnit is the most popular testing framework for Java. It’s included in dependencies by default to all new Android projects:</p><pre>dependencies {<br>    testImplementation &#39;junit:junit:4.12&#39;<br>}</pre><p>To write a test, you should create a class in test folder which is created by default and contains ExampleUnitTest.java. Usually, if devs test SomeClass , devs will name class with tests SomeClassTest . Moreover, most times, it belongs to the same Java package.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/601/1*2Fz51wbyrLu0TIzhS1xhQA.png" /><figcaption>Simple unit test on JUnit</figcaption></figure><p>Let’s see a simple test. You should annotate all test methods with org.junit.Test . Android Studio will automatically show the run test button. assertEquals will throw an exception if arguments are not equal. JUnit marks test as passed if it ends without any exception.</p><h4>Abstract an Android from business logic</h4><p>In Android, you can’t write unit tests for a class that uses the Android framework. But wait… <strong>WHAT???!</strong></p><p>Yes, the framework requires a specific environment and you can’t run it on any JVM. In unit tests, all Android classes are mocked to throw an exception. The best that we can do is to force it to return default values instead of throwing an exception.</p><pre>// In application module build.gradle<br>android.testOptions {<br>    unitTests.returnDefaultValues = true<br>}</pre><p>Back to the dialog, we certainly use Android classes like Activity/Fragment, View, Dialog, and others for “rate us” feature. Therefore we can’t write unit tests without a bit of effort.</p><p>First, I created an interface for every Android dependency which I use for “rate us” showing logic.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/84bd125fa61ff85afac940795c47bc48/href">https://medium.com/media/84bd125fa61ff85afac940795c47bc48/href</a></iframe><p>Second, I created an interface for every Java dependency that can’t be used directly in tests. More specifically, it is System.currentTimeMillis() .</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e821b594885623aa0e1ce38143be4d3b/href">https://medium.com/media/e821b594885623aa0e1ce38143be4d3b/href</a></iframe><p>Last, I applied the dependency inversion principle toShowRateUsLogic.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e4064c3f29b4a3528e50dfc86359a9a1/href">https://medium.com/media/e4064c3f29b4a3528e50dfc86359a9a1/href</a></iframe><h4>Mocks</h4><p>Now we should write mock classes for unit tests. I’ll show one mock below. You can check all the mocks <a href="https://github.com/IvanShafran/android-unit-tests-evolution-rate-us-dialog/tree/master/app/src/test/java/com/github/ivanshafran/unit_tests_evolution/v1">here</a>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/634df18922111dd9546a2370951bbed8/href">https://medium.com/media/634df18922111dd9546a2370951bbed8/href</a></iframe><h4>First unit test</h4><p>After hardworking, it is a pleasure to code the first unit test :)</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b1f300572ca3768f319df38368b13571/href">https://medium.com/media/b1f300572ca3768f319df38368b13571/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*hadLWWKRbSN69e9h" /><figcaption><a href="https://mmorpg.org.pl/system/posts/posters/000/030/808/medium/beauty.jpg?1521034537">https://mmorpg.org.pl/system/posts/posters/000/030/808/medium/beauty.jpg?1521034537</a></figcaption></figure><p>To be honest, it is not. But I wrote it in the “my first unit test” style. And I’ll fix it in the next chapters.</p><h3>Second version: code cleaning</h3><p>The first unit test is cool but if no one can understand it, then it is useless. Therefore I’ve refactored test class:</p><ol><li>setUp is marked with @Before annotation. It makes the method to be invoked before every unit test. We’ll move the common test code to setUp method.</li><li>A good test method has a meaningful name. It’s better for reading and also it appears in test reports. We’ll rename test1 to onFirstCheckAndOneClickItShouldNotShow .</li><li>I’ve added a more complicated test. The test name is too short to express all the information. That’s why we’ll add comments to the method body.</li><li>For the last step, we’ll delete unnecessary and wrong time set.</li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a88b3745ba0da32ee56402ec093b6659/href">https://medium.com/media/a88b3745ba0da32ee56402ec093b6659/href</a></iframe><h3>Third version: mocking libraries</h3><p>As mentioned, we can <strong>not</strong> use Android classes in unit tests. But almost all our classes do it. And it’s quite boring to create an interface, an implementation and a mock for every class.</p><p>Fortunately, there is an alternative way. We can use mocking libraries.</p><h4><a href="https://site.mockito.org/">Mockito</a></h4><p>Directly to the most frequently used API:</p><ul><li>Use Mockito.mock(Class) to mock any interface or class</li><li>Use Mockito.when(instance.method()).thenReturn(value) to mock method call</li><li>Use Mockito.verify(instance).method() to check if method was called</li></ul><h4><a href="https://github.com/IvanShafran/shared-preferences-mock">Shared preferences mock</a></h4><p>In my practice, shared preferences class is the most used Android dependency in business logic. Therefore I’ve implemented shared preferences mock library which mimics Android implementation. Now you can use shared preferences in unit tests with one additional line of code ;)</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4a1e0fa42fc9628fac75c3d72b933377/href">https://medium.com/media/4a1e0fa42fc9628fac75c3d72b933377/href</a></iframe><h3>Fourth version: Kotlin</h3><p>Kotlin is a good language for Android development. And also, it can bring improvements to unit tests code.</p><ol><li>We’ll rename the test method name using spaces enclosed in backticks</li><li>We’ll move the common preparation code to function with default arguments</li><li>We’ll delete unnecessary comments because we can use named arguments</li><li>We’ll use <a href="https://github.com/nhaarman/mockito-kotlin">mockito-kotlin</a> cause it has a more idiomatic and compact syntax</li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3df2f5972a8958c6ce19973874ced79c/href">https://medium.com/media/3df2f5972a8958c6ce19973874ced79c/href</a></iframe><h3>Fifth version: Spek</h3><p><a href="https://github.com/spekframework/spek">Spek </a>is a unit testing framework for Kotlin which supports Specification and Gherkin style.</p><p>Personally, the crucial features of Spek are:</p><ul><li>Ability to structure test due to condition</li><li>Ability to construct tests on the go(cause test code is a lambda, not a method)</li></ul><p>I intentionally will not describe syntax because it is easy to understand. And if you are interested in Spek then check out this <a href="https://spekframework.org/core-concepts/">link</a>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2354325268adcccc588ecc6f92912498/href">https://medium.com/media/2354325268adcccc588ecc6f92912498/href</a></iframe><p>Moreover, Spek generates a structured test report in Android Studio.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/670/1*M0FxRi-DpkOuP8lgz12KAw.png" /></figure><h3>Bonus part</h3><p>The article about unit tests in Android will not be full without several mentions. If you have more links to mention, please share them in comments and I’ll add them to the article.</p><h4><a href="http://robolectric.org/">Robolectric</a></h4><blockquote><a href="http://robolectric.org/">Robolectric</a> is a framework that brings fast and reliable unit tests to Android. Tests run inside the JVM on your workstation in seconds.</blockquote><p>It is not a pure unit testing but allows us to test Android APIs without launching a device or emulator. On the other hand, it has a bigger test run time.</p><h4>Assertion frameworks</h4><p>‘Rate us’ dialog logic has boolean return value, therefore we used simple assertTrue or assertFalse. But for more complicated tests, there’s not enough flexibility in default assertions.</p><blockquote><a href="http://hamcrest.org/JavaHamcrest/tutorial">Hamcrest</a> is a framework for writing matcher objects allowing ‘match’ rules to be defined declaratively.</blockquote><pre>assertThat(Math.sqrt(-1), is(notANumber()))</pre><blockquote><a href="https://assertj.github.io/doc/">AssertJ</a> — fluent assertions java library.</blockquote><pre>assertThat(frodo.getName()).isEqualTo(&quot;Frodo&quot;)</pre><blockquote><a href="https://github.com/google/truth">Truth</a> makes your <a href="https://truth.dev/benefits#readable-assertions">test assertions</a> and <a href="https://truth.dev/benefits#readable-messages">failure messages</a> more readable. <a href="https://truth.dev/comparison">Similar</a> to <a href="http://joel-costigliola.github.io/assertj/">AssertJ</a>, it <a href="https://truth.dev/known_types">natively supports</a> many JDK and <a href="https://github.com/google/guava">Guava</a> types, and it is <a href="https://truth.dev/extension">extensible</a> to others.</blockquote><pre>assertThat<strong>(</strong>notificationText<strong>).</strong>contains<strong>(</strong>&quot;testuser@google.com&quot;<strong>)</strong></pre><p>Check the full sample code here:</p><p><a href="https://github.com/IvanShafran/android-unit-tests-evolution-rate-us-dialog">IvanShafran/android-unit-tests-evolution-rate-us-dialog</a></p><p>You can star shared preferences mock library here:</p><p><a href="https://github.com/IvanShafran/shared-preferences-mock">IvanShafran/shared-preferences-mock</a></p><p><strong>Let’s become friends on </strong><a href="https://twitter.com/NotShafran"><strong>Twitter</strong></a><strong>, </strong><a href="https://github.com/IvanShafran"><strong>Github</strong></a><strong>, and </strong><a href="https://www.facebook.com/not.shafran"><strong>Facebook</strong></a><strong>!</strong></p><pre><strong>Clap, share and follow me if you like it🐱‍💻</strong></pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=daa3c76b0494" width="1" height="1" alt=""><hr><p><a href="https://proandroiddev.com/evolution-of-unit-tests-in-android-daa3c76b0494">Evolution of unit tests in Android</a> was originally published in <a href="https://proandroiddev.com">ProAndroidDev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Improve Android unit tests with shared preferences mock library]]></title>
            <link>https://proandroiddev.com/improve-android-unit-tests-with-shared-preferences-mock-library-959173a70fb4?source=rss-9899144a13c8------2</link>
            <guid isPermaLink="false">https://medium.com/p/959173a70fb4</guid>
            <category><![CDATA[testing]]></category>
            <category><![CDATA[unit-testing]]></category>
            <category><![CDATA[androiddev]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[android-app-development]]></category>
            <dc:creator><![CDATA[Ivan Shafran]]></dc:creator>
            <pubDate>Wed, 03 Jul 2019 15:06:01 GMT</pubDate>
            <atom:updated>2022-02-25T10:55:53.310Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*f6x-3xm2kicDGwP0" /><figcaption>Photo by <a href="https://unsplash.com/@rimakruciene?utm_source=medium&amp;utm_medium=referral">Rima Kruciene</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p><strong>TL;DR:</strong> <a href="https://github.com/IvanShafran/shared-preferences-mock">Shared preferences mock</a> is the lightweight library let you increase coverage of unit tests and simplify code for them with one line of code.</p><h3>The problem</h3><p>Unit test on Android uses a framework mock where every method throws UnsupportedOperationException or does nothing depending on your settings in Gradle testOptions.</p><p>In unit tests, we mostly test business logic, which often depends on preferences. Therefore you should mock all classes which use SharedPreferences inside. It is a lot of boilerplate in tests. Moreover, because of this limitation, we never test preferences class code. However, it also may have bugs.</p><h3>The solution</h3><p>The library implements SharedPreferences, Context.getSharedPreferences and Context.deleteSharedPreferences in memory using only Java API.</p><p>It allows you to use classes with shared preferences in unit tests as is and also to write tests for them.</p><h3>Usage</h3><p>Update 2022: moved to maven central.</p><p>Add it in your root build.gradle at the end of repositories:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/eb6fefb9ccb78dbf82061df7f21f36ad/href">https://medium.com/media/eb6fefb9ccb78dbf82061df7f21f36ad/href</a></iframe><p>Add the dependency to module build.gradle:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/67315aa8dd1bf4129936d52d81c73beb/href">https://medium.com/media/67315aa8dd1bf4129936d52d81c73beb/href</a></iframe><p>In most cases, preference class or preference utils depends on Context. In unit test instead of real Context pass Contextcreated by new SPMockBuilder().createContext().</p><p>If you already have Context with some mocked methods, you can use new SPMockBuilder().wrapContext(preconfiguredContext).</p><p>If you need raw SharedPreferences use new SPMockBuilder().createSharedPreferences().</p><p>If thread safety is necessary for your test, then configure SPMockBuilder.setThreadSafe(true) . It is false by default.</p><h3>Sample</h3><p>The sample below describes common code where logic uses preference class to check condition. In line 29 SPMockBuilder creates a context for the preference unit tests. Simple, isn’t it?</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0caf812bb2975c72e0501e80c25f8924/href">https://medium.com/media/0caf812bb2975c72e0501e80c25f8924/href</a></iframe><h3>Alternatives</h3><p>Create CounterPreferences interface and implement Java version for a test by yourself:</p><ul><li>Doesn’t test CounterPreferences implementation</li><li>Requires boilerplate code in tests</li></ul><p>Use <a href="https://github.com/mockito/mockito">Mockito</a>:</p><ul><li>Doesn’t test CounterPreferences implementation</li></ul><p>Use <a href="https://github.com/robolectric/robolectric">Robolectric</a>:</p><ul><li>Has test startup delay for a few seconds</li></ul><p>Use instrumented test(not a unit test!):</p><ul><li>Requires device for testing</li></ul><h3>The library and sample code</h3><p>You can star the library and learn more info at:</p><p><a href="https://github.com/IvanShafran/shared-preferences-mock">IvanShafran/shared-preferences-mock</a></p><p><strong>Let’s become friends on </strong><a href="https://twitter.com/NotShafran"><strong>Twitter</strong></a><strong>, </strong><a href="https://github.com/IvanShafran"><strong>Github </strong></a><strong>and </strong><a href="https://www.facebook.com/not.shafran"><strong>Facebook</strong></a><strong>!</strong></p><pre><strong>Clap, share and follow me if you like it🐱‍💻</strong></pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=959173a70fb4" width="1" height="1" alt=""><hr><p><a href="https://proandroiddev.com/improve-android-unit-tests-with-shared-preferences-mock-library-959173a70fb4">Improve Android unit tests with shared preferences mock library</a> was originally published in <a href="https://proandroiddev.com">ProAndroidDev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Android open source app secure build]]></title>
            <link>https://proandroiddev.com/android-open-source-app-secure-build-c3d3df8bcc16?source=rss-9899144a13c8------2</link>
            <guid isPermaLink="false">https://medium.com/p/c3d3df8bcc16</guid>
            <category><![CDATA[android-app-development]]></category>
            <category><![CDATA[gradle]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[androiddev]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <dc:creator><![CDATA[Ivan Shafran]]></dc:creator>
            <pubDate>Thu, 23 May 2019 11:36:01 GMT</pubDate>
            <atom:updated>2019-05-23T11:36:01.068Z</atom:updated>
            <content:encoded><![CDATA[<h3>Android open source app secure build config</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GokUBniUDrdysuAE" /><figcaption>Photo by <a href="https://unsplash.com/@jamessutton_photography?utm_source=medium&amp;utm_medium=referral">James Sutton</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p><strong>TL;DR repository: </strong><a href="https://github.com/IvanShafran/android-open-source-app-signing"><strong>https://github.com/IvanShafran/android-open-source-app-signing</strong></a></p><p>By default Android app has debug build in which APK is signed automatically with debug keystore. But for a release build, you have to sign with a manually created keystore.</p><p>If you develop an open source app, you can’t keep a keystore together with code due to security reasons. You can easily exclude it in the .gitignore file, but in this case, your contributors won’t build an app in a release variant. It complicates open source development because some bugs can only be discovered in a release build. Moreover, you can’t run UI tests for release builds directly from a repository. Let’s solve the problem!</p><h4>First step. Create two keystores</h4><p>Create one keystore for production build with strong passwords. And create another for contributors with any password. Place them both in the main app module folder. For default created project folder is “app.”</p><p><a href="https://developer.android.com/studio/publish/app-signing#generate-key">How to generate keystore</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/590/1*HuVpvI7832cxKuai3AgAtA.png" /></figure><p><strong>At this point add </strong><strong>production.jks to </strong><strong>.gitignore .</strong></p><h4>Second step. Create two properties files</h4><p>Create two properties files in the same folder as described below.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f877184acaa4590a337478e6c12ddb20/href">https://medium.com/media/f877184acaa4590a337478e6c12ddb20/href</a></iframe><p>Also, create production.properties with production key and passwords.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/575/1*wJZqUq4ZhUQBA8XSbbROdw.png" /></figure><p><strong>At this point add </strong><strong>production.properties to </strong><strong>.gitignore .</strong></p><h4>Third step. Add script</h4><p>Add script listed below to the same folder and apply it in build.gradle. Script checks if production properties file exists in the folder and if it exists script uses production keystore otherwise contributors. That’s all magic :)</p><p><strong>Don’t forget to add </strong><strong>production.jks and </strong><strong>production.properties to </strong><strong>.gitignore .</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/26fe488d7966aa222c070959682db5bc/href">https://medium.com/media/26fe488d7966aa222c070959682db5bc/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/de0e2bf8a68c765081b28cdf7eacd3b1/href">https://medium.com/media/de0e2bf8a68c765081b28cdf7eacd3b1/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/584/1*gqotFy4FSLClQfZQ1lzEPA.png" /></figure><p><strong>Full sample here: </strong><a href="https://github.com/IvanShafran/android-open-source-app-signing"><strong>https://github.com/IvanShafran/android-open-source-app-signing</strong></a></p><p><strong>Let’s become friends on </strong><a href="https://twitter.com/NotShafran"><strong>Twitter</strong></a><strong>, </strong><a href="https://github.com/IvanShafran"><strong>Github </strong></a><strong>and </strong><a href="https://www.facebook.com/not.shafran"><strong>Facebook</strong></a><strong>!</strong></p><pre><strong>Clap, share and follow me if you like it🐱‍💻</strong></pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c3d3df8bcc16" width="1" height="1" alt=""><hr><p><a href="https://proandroiddev.com/android-open-source-app-secure-build-c3d3df8bcc16">Android open source app secure build</a> was originally published in <a href="https://proandroiddev.com">ProAndroidDev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kotlin library development for Android/Java hints]]></title>
            <link>https://proandroiddev.com/kotlin-library-development-for-android-java-hints-29365017516d?source=rss-9899144a13c8------2</link>
            <guid isPermaLink="false">https://medium.com/p/29365017516d</guid>
            <category><![CDATA[java]]></category>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[android-app-development]]></category>
            <dc:creator><![CDATA[Ivan Shafran]]></dc:creator>
            <pubDate>Sun, 12 May 2019 06:09:01 GMT</pubDate>
            <atom:updated>2019-05-12T06:09:01.153Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*44Tk4bqGW0R8va3_" /><figcaption>Photo by <a href="https://unsplash.com/@inakihxz?utm_source=medium&amp;utm_medium=referral">Iñaki del Olmo</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>Kotlin versions support</h3><p>When we develop a regular app for Android we can choose any Kotlin version. Some teams prefer to use the latest version in order to try new features and tooling improvements. Some teams wait some time before switching to a new version. It can be linked to a release cycle or waiting for community feedback on the last version.</p><p>But when we develop a library on Kotlin we have to support both versions. Luckily Kotlin has good forward and backward compatibility.</p><h4>Backward compatibility</h4><p>It’s simple:</p><blockquote>All binaries are backwards compatible, i.e. a newer compiler can read older binaries (e.g. 1.3 understands 1.0 through 1.2) [1]</blockquote><p>But it only applies to fully stable APIs: std-lib, coroutines. Check [2] for the full list.</p><h4>Forward compatibility</h4><p>There is such statement:</p><blockquote>Preferably (but we can’t guarantee it), the binary format is mostly forwards compatible with the next feature release, but not later ones (in the cases when new features are not used, e.g. 1.3 can understand most binaries from 1.4, but not 1.5). [1]</blockquote><p>Not very specific but in practice, my library which targets 1.3 works fine with 1.2 and even 1.1 std-lib without any changes. And it’s not working with 1.0 due to function reference feature which I used in the library code.</p><p>But if we want more strict guarantees Kotlin compiler provides two useful flags: apiVersion and languageVersion.[3]</p><blockquote><em>-language-version X.Y</em> - compatibility mode for Kotlin language version X.Y, reports errors for all language features that came out later.[4]</blockquote><blockquote><em>-api-version X.Y</em> - compatibility mode for Kotlin API version X.Y, reports errors for all code using newer APIs from the Kotlin Standard Library (including the code generated by the compiler).[4]</blockquote><p>In Gradle I’ve configured it as following:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6989a82e32e16350d8b0e16f0d4876f9/href">https://medium.com/media/6989a82e32e16350d8b0e16f0d4876f9/href</a></iframe><p>After that, you will probably see some compilation errors. In order to fix them, you should exclude new features usages and write useful extension/function/classes from 1.3 by yourself.</p><h4>Library development version</h4><p>You can use the latest Kotlin version in your development. Except for new language features(which we can’t use due to apiVersion and languageVersion) it also brings compiler and tooling improvements.</p><h4>Dropping support of old versions</h4><p>In my opinion, it is not healthy to support old versions too long. I would recommend maintaining stability only one version back. Also, you could check release dates in artifacts repository to decide which versions to support [5].</p><h3>Kotlin std-lib, std-lib-jdk7 or std-lib-jdk8?</h3><p>Mainly you should choose between them in the following order:</p><ol><li>std-lib (for Java 6)</li><li>std-lib-jdk7 (for Java 7)</li><li>std-lib-jdk8 (for Java 8)</li></ol><p>If your code uses some features from jdk7(for example AutoCloseable useextension) and developer who uses your library provides std-lib, not std-lib-jdk7 or std-lib-jdk8 then his app will throw NoClassDefFoundError .</p><p>In Android, there is no need to support std-lib if you minSdk 19 at least. And there is no need to support std-lib-jdk7 if you source and target compatibility JavaVersion.VERSION_1_8.[6][7] But Android Studio doesn’t warning about that so try to support std-lib with fewer restrictions.</p><h3>Package structure and visibility</h3><p>A good library should hide all unnecessary classes, functions and properties from library users. Mostly you should prefer using private and internal modifiers for these situations.</p><p>In addition, it is recommended to move all your not public code in the package with name “internal”:</p><blockquote>Also, by convention, packages named “internal” are not considered public API. [8]</blockquote><h3>Java compatibility</h3><p>In most cases, Kotlin does all work for you. It creates get/setfor properties for example.</p><p>Currently, I’ve faced only one problem. If you declare a public property in companion from Java it is accessible via Sample.Companion.INSTANCE . To fix that use @JvmField annotation.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7a4fc6963bbf7774ece29b629c6a0c59/href">https://medium.com/media/7a4fc6963bbf7774ece29b629c6a0c59/href</a></iframe><h3>Kotlin dependency in pure Java project</h3><p>An Android library which is distributed as aar doesn’t include its dependency. Therefore in pure Java project library users will get NoClassDefFoundError because your library depends on Kotlin std-lib. Thus you should write notices about that in the README file or docs.</p><p>But people don’t like to read docs a lot. I would suggest one trick below. Please share in comments your opinion is it a good practice or not?</p><p>Declare dependency checker:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/541d622f8f35d0bc15237a912488f577/href">https://medium.com/media/541d622f8f35d0bc15237a912488f577/href</a></iframe><p>Check dependency in the static initializer block:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fc410a38b44821625dabdb48de6abf4c/href">https://medium.com/media/fc410a38b44821625dabdb48de6abf4c/href</a></iframe><p>And if someone forgets to include Kotlin std-lib dependency he will get the solution in a crash log not just error.</p><p><strong>Let’s become friends on </strong><a href="https://twitter.com/NotShafran"><strong>Twitter</strong></a><strong>, </strong><a href="https://github.com/IvanShafran"><strong>Github </strong></a><strong>and </strong><a href="https://www.facebook.com/not.shafran"><strong>Facebook</strong></a><strong>!</strong></p><pre><strong>Clap, share and follow me if you like it🐱‍💻</strong></pre><h3>Links</h3><ol><li><a href="https://kotlinlang.org/docs/reference/evolution/kotlin-evolution.html#evolving-the-binary-format">https://kotlinlang.org/docs/reference/evolution/kotlin-evolution.html#evolving-the-binary-format</a></li><li><a href="https://kotlinlang.org/docs/reference/evolution/kotlin-evolution.html#evolving-the-binary-format">https://kotlinlang.org/docs/reference/evolution/kotlin-evolution.html#evolving-the-binary-format</a></li><li><a href="https://kotlinlang.org/docs/reference/using-gradle.html#attributes-common-for-jvm-and-js">https://kotlinlang.org/docs/reference/using-gradle.html#attributes-common-for-jvm-and-js</a></li><li><a href="https://kotlinlang.org/docs/reference/evolution/compatibility-modes.html">https://kotlinlang.org/docs/reference/evolution/compatibility-modes.html</a></li><li><a href="https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib">https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib</a></li><li><a href="https://developer.android.com/studio/write/java8-support">https://developer.android.com/studio/write/java8-support</a></li><li><a href="https://stackoverflow.com/a/13550632/7958563">https://stackoverflow.com/a/13550632/7958563</a></li><li><a href="https://kotlinlang.org/docs/reference/evolution/kotlin-evolution.html#libraries">https://kotlinlang.org/docs/reference/evolution/kotlin-evolution.html#libraries</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=29365017516d" width="1" height="1" alt=""><hr><p><a href="https://proandroiddev.com/kotlin-library-development-for-android-java-hints-29365017516d">Kotlin library development for Android/Java hints</a> was originally published in <a href="https://proandroiddev.com">ProAndroidDev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Fragment: getContext vs requireContext]]></title>
            <link>https://medium.com/@shafran/fragment-getcontext-vs-requirecontext-ffc9157d6bbe?source=rss-9899144a13c8------2</link>
            <guid isPermaLink="false">https://medium.com/p/ffc9157d6bbe</guid>
            <category><![CDATA[android-support-library]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[android-app-development]]></category>
            <category><![CDATA[kotlin]]></category>
            <dc:creator><![CDATA[Ivan Shafran]]></dc:creator>
            <pubDate>Sun, 26 Aug 2018 15:04:06 GMT</pubDate>
            <atom:updated>2018-08-26T15:04:06.805Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jq0saHt6r5xE3kTaGtNPVA.png" /><figcaption>Warning in Java and error in Kotlin after updating to support lib 27.1.0</figcaption></figure><p><strong>TLDR: use requireContext only when you are sure fragment is attached to its host(onResume, onViewCreated, etc).</strong></p><p>Android team annotated some sdk methods with NonNull and Nullable in support library in 27.1.0. That change leads to warnings and errors like on the picture above.</p><h3>Why did they do this?</h3><p>At first sight it looks like adding more and more pain to android apps development. But actually this annotations help us to decrease crash rate.</p><p>getContext can return null when fragment isn’t attached to its host. Let’s take a look at two examples.</p><pre>@Override<br>public void onResume() {<br>    super.onResume();<br>    Resources resources = getContext().getResources();<br>}</pre><p>First sample shows us that as long as fragment is attached to its host(in onResume for example) it’s safe to use getContext without nullability checking.</p><pre>@Override<br>public void onResume() {<br>    super.onResume();<br>    new Handler().postDelayed(new Runnable() {<br>        @Override<br>        public void run() {<br>            final Resources resources = getContext().getResources();<br>        }<br>    }, TimeUnit.<em>SECONDS</em>.toMillis(5));<br>}</pre><p>The second one reveals potential NullPointerException. If after 5 seconds fragment isn’t attached to host, app is crashed.</p><p>So getContext Nullable annotation can prevent bugs like in the second sample. But it causes a useless warning in the first sample in Java and an error in Kotlin.</p><h3>How should we fix that?</h3><p>Firstly we should fix potentials bugs.</p><ol><li>Find all places where fragment can be detached at some point of time</li><li>Change code like in the sample below</li></ol><p>In Java:</p><pre>Context context = getContext();<br>if (context == null) {<br>    // Handle null context scenario<br>} else {<br>    // Old code with context<br>}</pre><p>In Kotlin:</p><pre>val context: Context = this.context ?: return // or if block</pre><p>Finally replace the rest with requireContext() which returns NonNull Context instead of getContext(). <strong>But keep in mind that requireContext() will throw an exception if fragment isn’t attached to its host. So you should use requireContext() with respect to fragment lifecycle.</strong></p><h3>Wrong fixes</h3><p>In Java:</p><pre>1.<br>// requireContext() does the same<br>Context context = getContext();<br>if (context == null) {<br>    throw new IllegalStateException(&quot;&quot;);<br>}<br>2.<br>// Warning supressing only hides the real problem<br>private void doSomething(@NonNull final Context context) {<br>}<br><br>@Override<br>public void onResume() {<br>    super.onResume();<br><br>    //noinspection ConstantConditions<br>    doSomething(getContext());<br>}</pre><p>In Kotlin:</p><pre>// It is similar to requireContext() but with NullPointerException<br>val context: Context = <em>context</em>!!</pre><h3>Other similar methods</h3><ol><li>getActivity vs requireActivity</li><li>getHost vs requireHost</li><li>getFragmentManager vs requireFragmentManager</li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ffc9157d6bbe" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>