froger_mcs dev blog Coding with love {❤️} http://frogermcs.github.io Time to move on <p>After a couple years of publishing posts here I have decided to move on to the more flexible blogging platform. frogermcs.github.io was originally created as a content-first project. The idea behind it was to setup website as fast as possible, with almost zero configuration - no HTML/CSS, no server nor domain setup. And Jekyll + Github Pages combination was the best option for it - the platform was ready to publish literally in an hour. Now I’m moving on to something a bit more complex but with much bigger flexibility. Also something even more personal. My new website will still be mostly focused on coding. But over the time I have developed a couple more areas of interest (AI, leadership, self-development) which in sum with coding will lead to something much bigger. Let’s call it “building solutions with love {❤️}”. At the end, the things we code are designed to serve people - to unlock possibilities, inspire, make something better. I hope, the experience I share will help with that.</p> <p>I invite you to my new home: <a href="https://mirekstanek.online">https://mirekstanek.online</a>. I hope you’ll find there something interesting for you!</p> <h3 id="author">Author</h3> <p><a href="http://about.me/froger_mcs">Miroslaw Stanek</a><br /> <em>Head of Mobile Development</em> @ <a href="https://azimo.com">Azimo Money Transfer</a></p> Tue, 02 Jan 2018 00:00:00 +0000 http://frogermcs.github.io/Time-to-move-on/ http://frogermcs.github.io/Time-to-move-on/ Basic Android app analytics in <60min <p>Every big tech company today is <strong>data-driven</strong>. Products are more often built based on collected data rather than internal opinions. It’s very likely that in this moment some of apps on your device are serving you A/B test variants, checking how: new layout, text or even functionality affect your activity and engagement.<br /> The biggest companies have dedicated Business Intelligence teams, their own data warehouses, custom analytics tools and big flat screens in conference rooms showing realtime charts.<br /> And the most important — endless audience waiting to be analysed by pie charts or bars 📊.</p> <p>So if you are member of small mobile-dev team, your app just touched the market or even won’t go out of Android Studio, you may think that data analysis isn’t your problem yet.</p> <p>You can’t be more wrong. 🙂</p> <p>There won’t be any analytics people in the future who will join your team just to add some data loggers here and there. Because as usual — everything starts with developers - it depends only on you how quickly you’ll make your app <strong>data-driven</strong>. Believe me, there won’t be easier than now to start collecting the data and in case you are not doing it yet, I have prepared shortlist of propositions how in less than 60 minutes make your app more friendly for data analyst in the future.</p> <h2 id="proper-abstraction-basic-events">Proper abstraction, basic events</h2> <p>Most of mobile analytics tools are able to track basic data almost automatically. In a few lines of code you will be able to capture installation, app launch events, screen views, crashes and probably even more. Whole implementation usually takes no more than 15 minutes so most of us choose this way as a first step. But in long term perspective it has some flaws:</p> <ul> <li>It’s not easy to migrate this solution. And there will be many reasons to do this in the future: too big costs of current service, too limited list of features, new data wizard in company has his own toolset and many more.</li> <li>Automatically tracked data is not enough. Sooner or later you will need to log more details what in most cases means explicit implementation.</li> <li>External SDK is not testable. At some point in the future you will need to guarantee that key metrics are logged properly after every app release.</li> </ul> <p>So how we could make it better?</p> <h3 id="base-implementation">Base implementation</h3> <p>At the beginning just make sure that your analytics tools are available “everywhere”. At the beginning you can simply inject them into your <code class="highlighter-rouge">BaseActivity</code> class:</p> <script src="https://gist.github.com/frogermcs/f23d071438e98b2383ed44f759505607.js?file=BaseActivity.java"> </script> <p>Now every subclass will always require screen name (<code class="highlighter-rouge">getScreenNameForAnalytics()</code> method implementation). But in return you are sure that launch event for every new screen will be always logged, no matter of used tools.</p> <script src="https://gist.github.com/frogermcs/56b5c8a40bdb07661710d1fcba9def53.js?file=MainActivity.java"> </script> <p>And the basic implementation of <code class="highlighter-rouge">AnalyticsTools</code>. Do you really need to use automatic tracking when this code is so simple?</p> <script src="https://gist.github.com/frogermcs/a302df15f632019dbecc94243ed9b526.js?file=AnalyticsTools.java"> </script> <p>And that’s it. With just 100 lines of code in two files you are able to log: <strong>screen launches</strong> (automatically), <strong>button clicks</strong> and <strong>custom events</strong> (on demand).<br /> Now when you decide to replace Mixpanel with Flurry or Google Analytics with your custom BigQuery implementation, you will just need a few amendments in source code. Logged data will remain the same. Oh, and If you know <strong>Dependency Injection</strong> concept you probably noticed that <code class="highlighter-rouge">AnalyticsTools</code> is fully testable with unit tests (you can inject fake GoogleAnalytics and make sure that tracked events are passed to there properly).</p> <h3 id="next-steps">Next steps</h3> <p>It completely depends on you but I would recommend those:</p> <ul> <li> <p><strong>DRY_RUN mode</strong> — even as simple boolean flag which makes sure that your data isn’t logged in analytics services (keep logging them in LogCat) when you build your app or test it.</p> </li> <li> <p><strong>Async tracking</strong> — most of analytics services are pretty good in using background threads but some of them still have problems with blocking initialisation. Even 200–500ms can be critical when tools are loaded during app launch. So instead of <code class="highlighter-rouge">CustomAnalyticsSDK</code> you can inject <code class="highlighter-rouge">Observable&lt;CustomAnalyticsSDK&gt;</code>. Why and what for? <a href="https://medium.com/@froger_mcs/async-injection-in-dagger-2-with-rxjava-e7df503343c0">Check my blog post</a>.</p> </li> </ul> <h2 id="buttons">Buttons</h2> <p>Logging every button click manually isn’t the most convince way. Even with our implementation you always have to look for <code class="highlighter-rouge">AnalyticsTools</code> reference in your code. If you build your apps in MVP pattern you will probably end with call chain: presenter —- <em>calls</em> -—&gt; activity —- <em>calls</em> -—&gt; analytics tools.<br /> Of course only if you won’t forget to add logging to each newly added button.</p> <p>Can we automate it somehow? Maybe it’s not the most elegant way but you can always build your <code class="highlighter-rouge">CustomButton</code>:</p> <script src="https://gist.github.com/frogermcs/1647cd3cd4430afded8a5388b59ba7c7.js?file=CustomButton.java"> </script> <p>It’s not as simple as <code class="highlighter-rouge">BaseActivity</code>, but it’s still less than 100 lines of code. Let’s see:</p> <ul> <li> <p><code class="highlighter-rouge">AnalyticsTools</code> are injected to every instance of <code class="highlighter-rouge">CustomButton</code> (you can use Dagger 2 for this — check posts on this blog for more articles about it).</p> </li> <li> <p>In this implementation there are two attributes which will be used in button click event: <code class="highlighter-rouge">CustomButton_analyticsLabel</code> and <code class="highlighter-rouge">CustomButton_analyticsScreenName</code>. First one is mandatory and if it’s not set, Line 33 will make sure that app will crash when you open it for the first time. The second one is overridden by current Activity screen name (our <code class="highlighter-rouge">getScreenNameForAnalytics()</code> method).</p> </li> <li> <p>Event is logged whenever user clicks on button. Current implementation logs label and screen name so it’s easy to distinguish “OK” button on main screen and the one on user settings.</p> </li> </ul> <p>To use custom attributes we need to declare them in <strong>res/values/attrs.xml</strong>:</p> <script src="https://gist.github.com/frogermcs/1647cd3cd4430afded8a5388b59ba7c7.js?file=attrs.xml"> </script> <p>Now all you have to do is to add your CustomButton into <strong>activity.xml</strong> file:</p> <script src="https://gist.github.com/frogermcs/cf44a491df2c0241ea15c4057fae468e.js?file=activity.xml"> </script> <p>Property <code class="highlighter-rouge">app:analyticsLabel</code> can be both: String or String reference (good practice is to create another file: <strong>res/values/analytics_labels.xml</strong> to not mix labels with real texts in our app).</p> <h2 id="less-logic-more-data">Less logic, more data</h2> <p>Soon or later you will need to track custom events in your app (e.g. conversions like sign-up, buy, invite a friend). There is no single way to do this, so let me give you small advice. Stick to one rule: <strong>always try to log as simple events as possible without any logic behind</strong>. Instead of building custom rules around tracked events try to log a bit more data — logic will be added later, during analysis.</p> <p>So whenever some comes to you asking for: <code class="highlighter-rouge">custom_event_user_signed_up_from_usa</code> just send: <code class="highlighter-rouge">custom_event_user_signed_up</code> with additional parameter: <code class="highlighter-rouge">country=”usa”</code> instead. Otherwise you will end up explaining what are exact conditions for every custom event which is sent from app. Almost every analytics tool is really good in filtering and segmentation so let’s move some responsibility out of you. 🙂</p> <h2 id="privacy">Privacy</h2> <p>The last hint is for your conscience. Data-driven development is really great approach because the goal is to make user more happy with your app. But keep in mind that there is thin border between analysing and spying. Also please remember that whenever you use external analytics services, you send users data to other companies. So please, make sure that you are not sharing too much of it and respect your customers privacy.<br /> And yes, you can always analyse anonymised data. Apple calls it <a href="https://www.wired.com/2016/06/apples-differential-privacy-collecting-data/">Differential Privacy</a>.</p> <p>Thanks for reading! 😊</p> <h3 id="author">Author</h3> <p><a href="http://about.me/froger_mcs">Miroslaw Stanek</a><br /> <em>Head of Mobile Development</em> @ <a href="https://azimo.com">Azimo Money Transfer</a></p> Thu, 27 Jul 2017 00:00:00 +0000 http://frogermcs.github.io/Basic-Android-app-analytics/ http://frogermcs.github.io/Basic-Android-app-analytics/ Hello world Google Home <h2 id="github-actionsbuilding-first-agent-for-google-assistant-injava">Github Actions — building first agent for Google Assistant in Java</h2> <p>Some time ago I <a href="https://medium.com/@froger_mcs/building-google-actions-with-java-696cffedbd01">published</a> unofficial Google Actions SDK written in Java. Source code and documentation can be found on Github: <a href="https://github.com/frogermcs/Google-Actions-Java-SDK">Google-Actions-Java-SDK</a>. Library can be also downloaded from Bintray jCenter:</p> <script src="https://gist.github.com/frogermcs/5dd507e968d30d89e4090d6297520b81.js?file=gactions.gradle"> </script> <p>The goal for this project is to give Android/Java developers possibility to build solutions for Google Home without learning new language (official Actions SDK is written in Node.js).</p> <h2 id="google-assistant-action-from-scratch">Google Assistant Action from scratch</h2> <p>In this post we’ll go through Google Assistant agent implementation. We’ll build simple Github client which will tell us what is the one of the hottest repositories from last days.</p> <p>Source code for final project can be found here: <a href="https://github.com/frogermcs/Github-Google-Actions">Github Google Actions</a></p> <h3 id="environment-configuration">Environment configuration</h3> <p>Our Github Actions agent will be built in Java and hosted on App Engine.<br /> At the beginning we need to create new project in <a href="https://console.cloud.google.com/home/dashboard">Google Cloud Platform dashboard</a>.<br /> When it’s done remember your project ID, it will be needed during configuration. <em>In example described in this post id is: *githubactions*</em>.</p> <p>Then we need to install CLIs for Google Cloud and Google Actions:</p> <ul> <li> <p><a href="https://cloud.google.com/sdk/docs/">Instruction for Google Cloud SDK</a></p> </li> <li> <p><a href="https://developers.google.com/actions/tools/gactions-cli">Instruction for gactions</a></p> </li> </ul> <h3 id="project-init">Project init</h3> <p>Now let’s create our Java/gradle project (I use <strong><a href="https://medium.com/r/?url=https%3A%2F%2Fwww.jetbrains.com%2Fidea%2F">IntelliJ IDEA</a></strong>, free community edition). For better code structure, I also created module app. Final structure looks like this (some files/tries aren’t show for better readability):</p> <script src="https://gist.github.com/frogermcs/816d0d05d0058fe236b5e2eb75bed2fc.js?file=structure1"> </script> <p>When it’s done, run <code class="highlighter-rouge">$ gactions init</code> from <code class="highlighter-rouge">/app</code> directory. It should create example config file: <code class="highlighter-rouge">app/actions.json</code>:</p> <script src="https://gist.github.com/frogermcs/b4ad8dc0d89c11d77c5289a642be9572.js?file=example.json"> </script> <p>This config file defines our agent’s Actions. It’s mostly self-describing but in case you would like to know better what is happening here, please visit official <a href="https://developers.google.com/actions/develop/sdk/actions">documentation</a>.</p> <p>Now let’s update it with our configuration. We would like to have an agent which is able to handle two actions/intents:</p> <ul> <li> <p><strong>assistant.intent.action.MAIN</strong> (defined in Google Actions SDK)<br /> Action is launched when user starts talking, but without clear intention e.g.: “Ok Google, talk to Github”. In most cases this should be used as an agent introduction.</p> </li> <li> <p><strong>com.frogermcs.githubactions.intent.TRENDING</strong> (defined by us)<br /> In response to this request, our agent will find one of the hottest repositories from last days. There are a couple utterances which should fire this intent:<br /> “Ok Google, ask Github what are the hottest repositories”<br /> “…trending repositories”<br /> “…hot projects”<br /> …<br /> and others. List of queries is defined in <strong>actions.json</strong>. Here is final configuration for our agent:</p> </li> </ul> <script src="https://gist.github.com/frogermcs/ada1f417c83ff08dbbc36a92f165dabd.js?file=githubactions.json"> </script> <p>###The code</p> <p>Now let’s build service to handle requests from Google Assistant. We will build simple REST server, which handles POST requests (based on configuration above, both intent requests will be sent to https://githubactions.appspot.com/).</p> <h4 id="project-configuration">Project configuration</h4> <p>Our app requires a couple dependencies defined in <code class="highlighter-rouge">app/build.gradle</code> file:</p> <ul> <li> <p>App Engine SDK</p> </li> <li> <p><a href="https://github.com/frogermcs/Google-Actions-Java-SDK/">Google Actions Java SDK</a> (my unofficial library)</p> </li> <li> <p><a href="https://github.com/google/google-http-java-client">Google HTTP Client Library for Java</a> — to make calls to Github API. Not a good news for Android devs familiar with Okhttp and Retrofit — because of App Engine restrictions in threading, it’s really hard to make it working here.</p> </li> <li> <p><a href="https://google.github.io/dagger/">Dagger 2</a> — Dependency injection framework to make our code a bit cleaner and easy to extend.</p> </li> </ul> <p>Final gradle files (able to build, run and deploy our GAE code) can be found here:</p> <ul> <li> <p><a href="https://github.com/frogermcs/Github-Google-Actions/blob/master/app/build.gradle">app/build.gradle</a></p> </li> <li> <p><a href="https://github.com/frogermcs/Github-Google-Actions/blob/master/build.gradle">build.gradle</a></p> </li> <li> <p><a href="https://github.com/frogermcs/Github-Google-Actions/blob/master/settings.gradle">settings.gradle</a></p> </li> </ul> <h4 id="servlet">Servlet</h4> <p>Now let’s build code for processing requests from Google Assistant. At this level, it’s nothing more than just proper configuration of <a href="https://github.com/frogermcs/Google-Actions-Java-SDK/">Google Actions Java SDK</a>:</p> <ul> <li> <p>Build response handler. This object will be used to pass final responses to Google Assistant. Nothing really interesting, it just meets communication requirements (headers, format) Final code: <a href="https://github.com/frogermcs/Github-Google-Actions/blob/master/app/src/main/java/com/frogermcs/githubactions/assistant/AppEngineResponseHandler.java">AppEngineResponseHandler</a>.</p> </li> <li> <p>Build request handlers. Those are responsible for handling particular requests (our <strong>MAIN</strong> and <strong>TRENDING</strong> intents). Request handlers should process incoming request and generate tell/ask/permission response. In our app we’ll have only tell responses: greeting (MAIN) and randomly picked hot repository (TRENDING). In the future we’ll build more complex solutions on top of ask and permission responses. Final code for <a href="https://github.com/frogermcs/Github-Google-Actions/blob/master/app/src/main/java/com/frogermcs/githubactions/assistant/requestHandlers/MainRequestHandler.java">MainRequestHandler</a> and <a href="https://github.com/frogermcs/Github-Google-Actions/blob/master/app/src/main/java/com/frogermcs/githubactions/assistant/requestHandlers/TrendingRequestHandler.java">TrendingRequestHandler</a> (take a look at returned variable from getResponse() methods — in both cases we use <code class="highlighter-rouge">ResponseBuilder.tellResponse(…)</code>.</p> </li> <li> <p>Intents mapped to proper request handlers:</p> </li> </ul> <script src="https://gist.github.com/frogermcs/f0c54881471ffe99295244639ac3ad9e.js?file=AssistantModule.java"> </script> <p>All dependencies for Assistant Actions can be found in <a href="https://github.com/frogermcs/Github-Google-Actions/blob/master/app/src/main/java/com/frogermcs/githubactions/assistant/AssistantModule.java">AssistantModule</a> class.</p> <p>Final servlet code should be similar to this:</p> <script src="https://gist.github.com/frogermcs/7355dcde7ccd51f9a2db6d1869f8dd2b.js?file=GithubActionsServlet.java"> </script> <p>Line 15 is the place where all magic happens:</p> <p>1) POST request comes from Google Assistant. It is parsed to <code class="highlighter-rouge">RootRequest</code> object (lines: 18–20) and passed to <code class="highlighter-rouge">assistantActions</code>.</p> <p>2) Based on defined intents map, <code class="highlighter-rouge">assistantAction</code> passes <code class="highlighter-rouge">RootRequest</code> object to <code class="highlighter-rouge">MainRequestHandler</code> or <code class="highlighter-rouge">TrendingRequestHandler</code>.</p> <p>3) Picked request handler generates tell response: <code class="highlighter-rouge">RootResponse</code>.</p> <p>4) Response is passed to <code class="highlighter-rouge">AppEngineResponseHandler</code> which sends it back to <strong>Google Assistant</strong>.</p> <h4 id="servlet-configuration">Servlet Configuration</h4> <p>At the end you need to add App Engine servlet configuration to your project (files: <strong>web.xml</strong> and <strong>appengine-web.xml</strong>):</p> <script src="https://gist.github.com/frogermcs/81114876931412d66b723185f475acda.js?file=structure2"> </script> <p>Their content should be self-explaining:</p> <script src="https://gist.github.com/frogermcs/acdb87f4516e81b396b2048ecc88c09f.js?file=web.xml"> </script> <script src="https://gist.github.com/frogermcs/7136f0a9f306a7ddd36248ae3007440a.js?file=appengine-web.xml"> </script> <p>Now our app is ready to deploy. If the configuration is correct, all you have to do is:</p> <p><code class="highlighter-rouge">$ ./gradlew app:appengineDeploy</code></p> <h3 id="testing-assistant-actions">Testing Assistant Actions</h3> <p><img src="/images/31/web_simulator.png" alt="Web Simulator" title="Web Simulator" /></p> <p>Even if you don’t have Google Home device, it’s still possible to simulate you newly created Assistant Actions. To do this you can use <strong>Google Home Web Simulator</strong>. All you need to do is:</p> <p>1) <code class="highlighter-rouge">$ gactions preview -action_package=app/action.json -invocation_name=Github</code> called from project’s root directory.</p> <p>2) Sign-in and start: <a href="https://developers.google.com/actions/tools/web-simulator">Web Simulator</a></p> <p>More details can be found in <a href="https://developers.google.com/actions/tools/testing">official guide</a>.</p> <p>And that’s all! We’ve just built our very first preview version of Actions for Google Assistant. In future publications we’ll see how to extend its functionality.</p> <p>Thanks for reading! 😊</p> <h2 id="source-code">Source code</h2> <p>Final source code of described project can be found on <a href="https://github.com/frogermcs/Github-Google-Actions">Github</a>.</p> <h3 id="author">Author</h3> <p><a href="http://about.me/froger_mcs">Miroslaw Stanek</a><br /> <em>Head of Mobile Development</em> @ <a href="https://azimo.com">Azimo Money Transfer</a></p> Fri, 12 May 2017 00:00:00 +0000 http://frogermcs.github.io/Hello-world-Google-Home/ http://frogermcs.github.io/Hello-world-Google-Home/ Building Google Actions with Java <p>Voice interfaces are definitely the future of interaction between people and the technology. Even if they won’t replace mobile apps (at least in next years), for sure they extend their possibilities. It means that for many mobile programmers, assistants like <a href="https://developers.google.com/actions/">Actions on Google</a> or <a href="https://developer.amazon.com/alexa">Amazon Alexa</a> will be next platforms to build their solutions.</p> <h1 id="google-actionssdk">Google Actions SDK</h1> <p>Currently if we want to build app for Google Home or Google Assistant we have to use Node.js <a href="https://developers.google.com/actions/develop/sdk/">library</a>. But under the hood, Assistant Platform uses JSON-formatted HTTP requests as a communication standard. It means that it’s relatively easy to build SDK in any other language. </p> <p>And so I started building unofficial <a href="https://github.com/frogermcs/Google-Actions-Java-SDK">Google Actions Java SDK</a>. If you are like me — an old-fashioned Android developer who builds in Java, there is a big chance that you have a lot of great code powering your apps which can be reused in Assistant Actions. And this was the main reason for this SDK — to enable as much developers as possible to write code for Assistant Platform.</p> <h2 id="about-project">About project</h2> <p>Since Google Actions Java SDK is on the proof-of-concept stage and still there is a lot of work to do (including documentation and tests), working implementation is all about:</p> <ul> <li> <p>Handling <a href="https://github.com/frogermcs/Google-Actions-Java-SDK/blob/master/google-actions-java-sdk/src/main/java/com/frogermcs/gactions/api/request/RootRequest.java">RootRequest</a> objects (incoming requests from Google Assistant)</p> </li> <li> <p>Preparing proper <a href="https://github.com/frogermcs/Google-Actions-Java-SDK/blob/master/google-actions-java-sdk/src/main/java/com/frogermcs/gactions/api/response/RootResponse.java">RootResponse</a> objects and sending them back to Assistant.</p> </li> </ul> <p>The rest are just better code architecture/scalability and utils (e.g. <a href="https://github.com/frogermcs/Google-Actions-Java-SDK/blob/master/google-actions-java-sdk/src/main/java/com/frogermcs/gactions/ResponseBuilder.java">ResponseBuilder</a> and all others not yet written).</p> <h3 id="appengine-actionsservlet">AppEngine ActionsServlet</h3> <p>As a working example we have simple AppEngine app written in Java which can be used as a replacement for Node.js server, and be easily deployed on Google Cloud. I won’t describe Servlet deployment process - it’s just a mix of these tutorials:</p> <ul> <li> <p><a href="https://developers.google.com/actions/develop/sdk/#set_up_your_environment">https://developers.google.com/actions/develop/sdk/#set_up_your_environment</a> — GActions CLI</p> </li> <li> <p><a href="https://cloud.google.com/sdk/downloads">https://cloud.google.com/sdk/downloads</a> — Google Cloud SDK</p> </li> <li> <p><a href="https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/appengine/helloworld-new-plugins">https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/appengine/helloworld-new-plugins</a> — Example Gradle config for AppEngine</p> </li> </ul> <p>Our servlet is pretty simple — when user starts interaction (app receives <code class="highlighter-rouge">assistant.intent.action.MAIN</code> intent after interpreting “Talk to hello action” utterance), Assistant should ask him/her to tell something. Then next utterance (intent: <code class="highlighter-rouge">assistant.intent.action.TEXT</code>) is echoed by Assistant. And conversation is over.</p> <p>From code perspective here is the whole flow:</p> <p>1) <a href="https://github.com/frogermcs/Google-Actions-Java-SDK/blob/master/google-actions-java-sample/src/main/java/com/frogermcs/gactions/sample/ActionsServlet.java">ActionsServlet</a> receives POST JSON-formatted request, which is parsed to RootRequest object.</p> <p>2) Thanks to intents mapping, <code class="highlighter-rouge">RequestHandler</code> passes <code class="highlighter-rouge">RootRequest</code> to <code class="highlighter-rouge">MainRequestHandler</code>.</p> <script src="https://gist.github.com/frogermcs/d6f04f2e62ab617a788665a7d6110d08.js?file=AssistantActions_mapping.java"> </script> <p>3) <em>Ask</em> response is generated and passed to <code class="highlighter-rouge">ResponseHandler</code> which sends response to Assistant.</p> <script src="https://gist.github.com/frogermcs/c376dff4c05b09e593b3fa594c55a314.js?file=MainRequestHandler.java"> </script> <script src="https://gist.github.com/frogermcs/a1f6e8ec608a1f4078a241d54c1b7812.js?file=AppEngineResponseHandler.java"> </script> <p>4) 1–3 steps are repeated for next utterance which then is echoed to user.</p> <script src="https://gist.github.com/frogermcs/91031b932cc84fb694ed67e8c67be888.js?file=TextRequestHandler.java"> </script> <p>Here you can see output from <a href="https://developers.google.com/actions/tools/web-simulator">Web Simulator</a> which additionally can shows the whole debug output for communication between Assistant and our Servlet.</p> <p><img src="/images/30/web_simulator.png" alt="Web Simulator" title="Web Simulator" /></p> <h2 id="next-steps">Next steps</h2> <p>Presented example is very simple yet powerful. If you already have any rest client implemented in your Android app (e.g. <a href="https://developer.github.com/v3/">Github API</a> client) you can put this code to our example Servlet and give user possibility to access this informations via voice interface. As mentioned at the beginning — all you have to do is proper handling for <code class="highlighter-rouge">RootResponse</code> and <code class="highlighter-rouge">RootRequest</code>.  </p> <p>At the end I highly encourage you to contribute in <a href="https://github.com/frogermcs/Google-Actions-Java-SDK">Google Actions Java SDK</a> development. Let’s enable as many developers as possible to build their brilliant ideas for Google Assistant and Home!</p> <p>Thanks for reading!</p> <h3 id="author">Author</h3> <p><a href="http://about.me/froger_mcs">Miroslaw Stanek</a><br /> <em>Head of Mobile Development</em> @ <a href="https://azimo.com">Azimo Money Transfer</a></p> Wed, 25 Jan 2017 00:00:00 +0000 http://frogermcs.github.io/Building-Google-Actions-with-Java/ http://frogermcs.github.io/Building-Google-Actions-with-Java/ FrameMetrics — realtime app smoothness tracking <p>A couple months ago, when Android Nougat was announced, among new features like Multi-window, enhanced notifications, VR support, 72 new emojis 👍 and others, there was a new addition to monitoring tools: <a href="https://developer.android.com/about/versions/nougat/android-7.0.html#framemetrics_api">Frame Metrics API</a>.</p> <p>On older Android versions when we would like to see graphic performance metrics we had to get them via adb shell, by calling:</p> <p><strong>$ adb shell dumpsys gfxinfo com.frogermcs.framemetrics</strong></p> <p>As a result we get:</p> <script src="https://gist.github.com/frogermcs/56b49ee97b50d26a5f4cfd5ad6d6461c.js?file=gistfile1.txt"> </script> <p>These statistics are generated for last 120 frames for given application package (<em>hint: this is not always last 2 seconds - frames are drawn only when Android is requested to do this e.g. when layout is changed or animated</em>).</p> <p>While this data can give us a lot of information about UI performance, accessing it from console isn’t the most convenient way, especially when we would like to use it during automatic app testing. Of course it isn’t impossible, and great example how it can be done is described in <a href="https://codelabs.developers.google.com/codelabs/android-perf-testing/index.html?index=..%2F..%2Findex#0">Automated Performance Testing Codelab</a> (it’s implemented as a MonkeyRunner script).</p> <h1 id="framemetrics">FrameMetrics</h1> <p>Starting from Android SDK 24, we can have access to these informations directly from application code. There is no limit to the past 120 frames, because frame timing info for current app window is captured in realtime. Having direct access to this data means also that we are able to measure production app to know how it works on users’ devices.</p> <p>FrameMetrics API <a href="https://developer.android.com/reference/android/view/FrameMetrics.html">documentation</a> is pretty clear about what can be measured (chronologic order):</p> <ul> <li> <p><a href="https://developer.android.com/reference/android/view/FrameMetrics.html#UNKNOWN_DELAY_DURATION">UNKNOWN_DELAY_DURATION</a></p> </li> <li> <p><a href="https://developer.android.com/reference/android/view/FrameMetrics.html#INPUT_HANDLING_DURATION">INPUT_HANDLING_DURATION</a></p> </li> <li> <p><a href="https://developer.android.com/reference/android/view/FrameMetrics.html#ANIMATION_DURATION">ANIMATION_DURATION</a></p> </li> <li> <p><a href="https://developer.android.com/reference/android/view/FrameMetrics.html#LAYOUT_MEASURE_DURATION">LAYOUT_MEASURE_DURATION</a></p> </li> <li> <p><a href="https://developer.android.com/reference/android/view/FrameMetrics.html#DRAW_DURATION">DRAW_DURATION</a></p> </li> <li> <p><a href="https://developer.android.com/reference/android/view/FrameMetrics.html#SYNC_DURATION">SYNC_DURATION</a></p> </li> <li> <p><a href="https://developer.android.com/reference/android/view/FrameMetrics.html#COMMAND_ISSUE_DURATION">COMMAND_ISSUE_DURATION</a></p> </li> <li> <p><a href="https://developer.android.com/reference/android/view/FrameMetrics.html#SWAP_BUFFERS_DURATION">SWAP_BUFFERS_DURATION</a></p> </li> <li> <p><a href="https://developer.android.com/reference/android/view/FrameMetrics.html#TOTAL_DURATION">TOTAL_DURATION</a></p> </li> </ul> <p>Metrics names are mostly self explaining but if this list looks not complete to you, take a look at <a href="https://github.com/android/platform_frameworks_base/blob/4b1a8f46d6ec55796bf77fd8921a5a242a219278/core/java/android/view/FrameMetrics.java">FrameMetrics sources</a> to see how each metric is calculated:</p> <script src="https://gist.github.com/frogermcs/b88e189ea01d83c3c91646f76897b5c7.js?file=FrameMetrics.java"> </script> <p>There are also great videos where <strong>Colt McAnlis</strong> explains among the others what VSYNC is or how layout is transformed to GPU commands (<code class="highlighter-rouge">FrameMetrics.COMMAND_ISSUE_DURATION</code>). So they also can shed some light on FrameMetrics fields:</p> <blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Some FrameMetrics fields can be demystified by <a href="https://twitter.com/duhroach">@duhroach</a> videos: Rendering Performance on <a href="https://twitter.com/hashtag/AndroidDev?src=hash">#AndroidDev</a> <a href="https://t.co/LG3BUDK4Fs">https://t.co/LG3BUDK4Fs</a> <a href="https://twitter.com/hashtag/PerfMatters?src=hash">#PerfMatters</a></p>&mdash; Miroslaw Stanek (@froger_mcs) <a href="https://twitter.com/froger_mcs/status/797912470828548096">November 13, 2016</a></blockquote> <script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <h1 id="activityframemetrics">ActivityFrameMetrics</h1> <p>To make FrameMetrics even easier to use I created simple library called <strong>ActivityFrameMetrics</strong>. It is small 1-class library which prints janky frames warnings to Logcat:</p> <p><img src="/images/29/logcat.png" alt="Logcat" title="Logcat" /></p> <p>Installation is pretty simple — you can copy <a href="https://github.com/frogermcs/ActivityFrameMetrics/blob/master/activityframemetrics/src/main/java/com/frogermcs/activityframemetrics/ActivityFrameMetrics.java">ActivityFrameMetrics.java</a> class to your project or use gradle dependency:</p> <script src="https://gist.github.com/frogermcs/41f69bffff535b33eaca9a88e0c831e2.js?file=ActivityFrameMetrics.gradle"> </script> <p>To use it, just register <code class="highlighter-rouge">ActivityFrameMetrics</code> as an ActivityLifecycleCallback in your <code class="highlighter-rouge">Application</code> class:</p> <script src="https://gist.github.com/frogermcs/0429206107879fdb23237cdcb7397dae.js?file=MyApplication.java"> </script> <p>By default library prints Logcat warning for every frame which rendering took more than 17ms, and error for more than 34ms.</p> <p>Default values can be changed with <code class="highlighter-rouge">ActivityFrameMetrics.Builder</code> params:</p> <script src="https://gist.github.com/frogermcs/db346227c17676b5e0ee09b11bc2b4ee.js?file=ActivityFrameMetricsBuilder.java"> </script> <p>Repo for ActivityFrameMetrics library can be found on <a href="https://github.com/frogermcs/ActivityFrameMetrics">Github</a>.</p> <h1 id="digging-deeper-into-framemetrics">Digging deeper into FrameMetrics</h1> <p>If it’s still not enough and you are still curious how FrameMetrics works under the hood here are a couple hints where you could start searching.</p> <p>First of all FrameMetrics is just a simple data container written in java but nothing really is measured in it. Instead this data comes as a notification from C++ code which is responsible for view rendering. Good starting point could be <a href="https://github.com/android/platform_frameworks_base/blob/4b1a8f46d6ec55796bf77fd8921a5a242a219278/core/java/android/view/ThreadedRenderer.java">ThreadedRenderer</a> class which proxies rendering to render thread. If you explore C++ code a bit more, at the end probably you’ll find <a href="https://github.com/android/platform_frameworks_base/blob/4b1a8f46d6ec55796bf77fd8921a5a242a219278/libs/hwui/JankTracker.cpp">JankTracker</a> class which is responsible for filling up FrameMetrics data (and you will realise that this is exactly the same data which is presented in <strong>dumpsys gfxinfo</strong>) and <a href="https://github.com/android/platform_frameworks_base/blob/4b1a8f46d6ec55796bf77fd8921a5a242a219278/libs/hwui/FrameInfo.h">FrameInfo</a> class which is C++ data container which is in sync with FrameMetrics.java.</p> <p>What else you can find there is only up to you. <strong>Just never stop searching and always be curious</strong>. </p> <p>Thanks for reading!</p> <h3 id="author">Author</h3> <p><a href="http://about.me/froger_mcs">Miroslaw Stanek</a><br /> <em>Head of Mobile Development</em> @ <a href="https://azimo.com">Azimo Money Transfer</a></p> Sat, 19 Nov 2016 00:00:00 +0000 http://frogermcs.github.io/FrameMetrics-realtime-app-smoothness-tracking/ http://frogermcs.github.io/FrameMetrics-realtime-app-smoothness-tracking/ Activities Subcomponents Multibinding in Dagger 2 <p>A couple months ago, during <a href="http://2016.mceconf.com/">MCE³</a> conference, Gregory Kick in his <a href="https://www.youtube.com/watch?v=iwjXqRlEevg">presentation</a> showed a new concept of providing Subcomponents (e.g. to Activities). New approach should give us a way to create ActivitySubcomponent without having AppComponent object reference (which used to be a factory for Activities Subcomponents). To make it real we had to wait for a new release of Dagger: <a href="https://github.com/google/dagger/releases/tag/dagger-2.7">version 2.7</a>.</p> <h2 id="the-problem">The problem</h2> <p>Before Dagger 2.7, to create Subcomponent (e.g. <code class="highlighter-rouge">MainActivityComponent</code> which is Subcomponent of <code class="highlighter-rouge">AppComponent</code>) we had to declare its factory in parent Component:</p> <script src="https://gist.github.com/frogermcs/e33c129125c98931bfeea32c6a6efee7.js?file=AppComponent.java"> </script> <p>Thanks to this declaration Dagger knows that <code class="highlighter-rouge">MainActivityComponent</code> has access to dependencies from <code class="highlighter-rouge">AppComponent</code>.</p> <p>Having this, injection in <code class="highlighter-rouge">MainActivity</code> looks similar to:</p> <script src="https://gist.github.com/frogermcs/f1f303ca47cce6d5c6deece22d39ae49.js?file=ActivityComponent.java"> </script> <p>The problems with this code are:</p> <ul> <li> <p>Activity depends on <code class="highlighter-rouge">AppComponent</code> (returned by <code class="highlighter-rouge">((MyApplication) getApplication()).getComponent())</code> — whenever we want to create Subcomponent, we need to have access to parent Component object.</p> </li> <li> <p><code class="highlighter-rouge">AppComponent</code> has to have declared factories for all Subcomponents (or their builders), e.g.: <code class="highlighter-rouge">MainActivityComponent plus(MainActivityComponent.ModuleImpl module);</code>.</p> </li> </ul> <h3 id="modulessubcomponents">Modules.subcomponents</h3> <p>Starting from Dagger 2.7 we have new way to declare parents of Subcomponents. <code class="highlighter-rouge">@Module</code> annotation has optional <a href="http://google.github.io/dagger/api/2.7/dagger/Module.html#subcomponents--">subcomponents</a> field which gets list of Subcomponents classes, which should be children of the Component in which this module is installed.</p> <p><strong>Example</strong>:</p> <script src="https://gist.github.com/frogermcs/ebc20e703efef051cbb34cbca77a0d91.js?file=ActivityBindingModule.java"> </script> <p><code class="highlighter-rouge">ActivityBindingModule</code> is installed in <code class="highlighter-rouge">AppComponent</code>. It means that both: <code class="highlighter-rouge">MainActivityComponent</code> and <code class="highlighter-rouge">SecondActivityComponent</code> are Subcomponents of <code class="highlighter-rouge">AppComponent</code>.<br /> Subcomponents declared in this way don’t have to be declared explicitly in <code class="highlighter-rouge">AppComponent</code> (like was done in first code listing in this post).</p> <h2 id="activities-multibinding">Activities Multibinding</h2> <p>Let’s see how we could use <code class="highlighter-rouge">Modules.subcomponents</code> to build Activities Multibinding and get rid of AppComponent object passed to Activity (it’s also explained at the end of this <a href="https://www.youtube.com/watch?v=iwjXqRlEevg&amp;feature=youtu.be&amp;t=1693">presentation</a>). I’ll go only through the most important pieces in code. Whole implementation is available on Github: <a href="https://github.com/frogermcs/Dagger2Recipes-ActivitiesMultibinding">Dagger2Recipes-ActivitiesMultibinding</a>.</p> <p>Our app contains two simple screens: <code class="highlighter-rouge">MainActivity</code> and <code class="highlighter-rouge">SecondActivity</code>. We want to be able to provide Subcomponents to both of them without passing <code class="highlighter-rouge">AppComponent</code> object.</p> <p>Let’s start from building a base interface for all Activity Components builders:</p> <script src="https://gist.github.com/frogermcs/6aacee420032d4d4bd868eac9021a988.js?file=ActivityComponentBuilder.java"> </script> <p>Example Subcomponent: <code class="highlighter-rouge">MainActivityComponent</code> could look like this:</p> <script src="https://gist.github.com/frogermcs/17155715cb88f84064969e7752261f20.js?file=MainActivityComponent.java"> </script> <p>Now we would like to have <code class="highlighter-rouge">Map</code> of Subcomponents builders to be able to get intended builder for each Activity class. Let’s use <code class="highlighter-rouge">Multibinding</code> feature for this:</p> <script src="https://gist.github.com/frogermcs/cd3117b2afce35d71026305e0e3bd2bb.js?file=ActivityBindingModule.java"> </script> <p><code class="highlighter-rouge">ActivityBindingModule</code> is installed in <code class="highlighter-rouge">AppComponent</code>. Like it was explained, thanks to this <code class="highlighter-rouge">MainActivityComponent</code> and <code class="highlighter-rouge">SecondActivityComponent</code> will be Subcomponent of <code class="highlighter-rouge">AppComponent</code>.</p> <script src="https://gist.github.com/frogermcs/05ad5b0e0c21322ae85d285bfc0bc091.js?file=ActivityBindingModule.java"> </script> <p>Now we can inject Map of <code class="highlighter-rouge">Subcomponents</code> builder (e.g. to <code class="highlighter-rouge">MyApplication</code> class):</p> <script src="https://gist.github.com/frogermcs/8fbb97357819e6a276593bd30909fc48.js?file=MyApplication.java"> </script> <p>To have additional abstraction we created <code class="highlighter-rouge">HasActivitySubcomponentBuilders</code> interface (because <code class="highlighter-rouge">Map</code> of builders doesn’t have to be injected into <code class="highlighter-rouge">Application</code> class):</p> <script src="https://gist.github.com/frogermcs/4025e0bd9ff5110bcb8a1e244bba7bfb.js?file=HasActivitySubcomponentBuilders.java"> </script> <p>And the final implementation of injection in Activity class:</p> <script src="https://gist.github.com/frogermcs/3c926bba2353d8835dd64e7f2d421b4c.js?file=MainActivity.java"> </script> <p>It’s pretty similar to our very first implementation, but as mentioned, the most important thing is that we don’t pass <code class="highlighter-rouge">ActivityComponent</code> object to our Activities anymore.</p> <h2 id="example-of-use-caseinstrumentation-tests-mocking">Example of use case — instrumentation tests mocking</h2> <p>Besides loose coupling and fixed circular dependency (Activity &lt;-&gt; Application) which not always is a big issue, especially in smaller projects/teams, let’s consider the real use case where our implementation could be helpful — mocking dependencies in instrumentation testing.</p> <p>Currently one of the most known way of mocking dependencies in Android Instrumentation Tests is by using <a href="https://medium.com/@fabioCollini/android-testing-using-dagger-2-mockito-and-a-custom-junit-rule-c8487ed01b56#.eh5zfyou5">DaggerMock</a> (Github <a href="https://github.com/fabioCollini/DaggerMock">project link</a>). While DaggerMock is powerful tool, it’s pretty hard to understand how it works under the hood. Among the others there is some reflection code which isn’t easy to trace.</p> <p>Building Subcomponent directly in Activity, without accessing AppComponent class gives us a way to test every single Activity decoupled from the rest of our app.<br /> Sounds cool, now take a look at code.</p> <p>Application class used in our instrumentation tests:</p> <script src="https://gist.github.com/frogermcs/5232f6fb0775c929a4924cdb66c32d0c.js?file=ApplicationMock.java"> </script> <p>Method <code class="highlighter-rouge">putActivityComponentBuilder()</code> gives us a way to replace implementation of ActivityComponentBuilder for given Activity class.</p> <p>Now take a look at our example Espresso Instrumentation Test:</p> <script src="https://gist.github.com/frogermcs/1d8d067e0610d2bace0c73933d6e62ad.js?file=MainActivityUITest.java"> </script> <p>Step by step:</p> <ul> <li> <p>We provide Mock of <code class="highlighter-rouge">MainActivityComponent.Builder</code> and all dependencies which have to be mocked (just <code class="highlighter-rouge">Utils</code> in this case). Our mocked <code class="highlighter-rouge">Builder</code> returns custom implementation of <code class="highlighter-rouge">MainActivityComponent</code> which injects <code class="highlighter-rouge">MainActivityPresenter</code> (with mocked <code class="highlighter-rouge">Utils</code> object in it).</p> </li> <li>Then our <code class="highlighter-rouge">MainActivityComponent.Builder</code> replaces the original Builder injected in <code class="highlighter-rouge">MyApplication</code> (line 28): <code class="highlighter-rouge">app.putActivityComponentBuilder(builder, MainActivity.class);</code></li> <li>Finally test — we mock <code class="highlighter-rouge">Utils.getHardcodedText()</code> method. Injection process happens when Activity is created (line 36): <code class="highlighter-rouge">activityRule.launchActivity(new Intent());</code> and at the and we’re just checking the results with Espresso.</li> </ul> <p>And that’s all. As you can see almost everything happens in MainActivityUITest class and the code is pretty simple and understandable.</p> <h2 id="source-code">Source code</h2> <p>If you would like to test the implementation on your own, source code with working example showing how to create <strong>Activities Multibinding</strong> and mock dependencies in Instrumentation Tests is available on Github: <a href="https://github.com/frogermcs/Dagger2Recipes-ActivitiesMultibinding">Dagger2Recipes-ActivitiesMultibinding</a>.</p> <p>Thanks for reading!</p> <h3 id="author">Author</h3> <p><a href="http://about.me/froger_mcs">Miroslaw Stanek</a><br /> <em>Head of Mobile Development</em> @ <a href="https://azimo.com">Azimo Money Transfer</a></p> Tue, 18 Oct 2016 00:00:00 +0000 http://frogermcs.github.io/activities-multibinding-in-dagger-2/ http://frogermcs.github.io/activities-multibinding-in-dagger-2/ Building UserScope with Dagger2 <p>Custom scopes in Dagger 2 can give better control on dependencies which should live unusual amount of time (different than application and screen lifetime). But to implement it properly in Android app we need to keep in mind a couple things like: scope cannot live longer than application process, process can be killed by system and restored in the middle of user flow with new objects instances and more. Today we’ll go through all of them and try to implement production ready UserScope.</p> <p>-</p> <p>In one of my blog posts about Dagger 2 I <a href="http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/">wrote</a> about building <strong>custom scopes</strong> and <strong>Subcomponents</strong>. As an example I used <code class="highlighter-rouge">UserScope</code> which should live as long as user is logged in.  Example of scopes lifetime:</p> <p><img src="/images/15/scopes-lifecycle.png" alt="Scopes lifecycle" title="Scopes lifecycle" /></p> <p>While it looks pretty simple, its implementation showed in that post was far away from code which can be production ready. That’s why I’d like to go through this subject again — but more in implementation context.</p> <h1 id="example-app">Example app</h1> <p>We’ll build 3-screens application which will be able to get user details from <a href="https://developer.github.com/v3/">Github API</a> (let’s assume that this would be authentication event in production app).</p> <p>App will have 3 scopes:</p> <p>Application scope</p> <ul> <li> <p>(<strong>@Singleton</strong>) — dependencies which live as long as application.</p> </li> <li> <p><strong>@UserScope</strong> — dependencies which live as long as user session is active (during single application launch).  <strong>Important</strong>: this scope won’t live longer than application itself. Each new app instance will create new @UserScope (even if user session was not finished between app launches).</p> </li> <li> <p><strong>@ActivityScope</strong> — dependencies which live as long as Activity screen.</p> </li> </ul> <h2 id="how-it-works">How it works? </h2> <p>When app gets data from Github API for given username, new screen is opened (UserDetails). Under the hood <code class="highlighter-rouge">LoginActivityPresenter</code> asks <code class="highlighter-rouge">UserManager</code> to start session (get data from Github API). When operation succeeds, user is saved to <code class="highlighter-rouge">UserDataStore</code> and <code class="highlighter-rouge">UserManager</code> creates <code class="highlighter-rouge">UserComponent</code>.</p> <script src="https://gist.github.com/frogermcs/95a06693ef1710ada28f28df9cd274cf.js?file=UserManager.java"> </script> <p><strong>UserManager</strong> is a singleton object so it lives as long as Application and is responsible for <code class="highlighter-rouge">UserComponent</code> which reference is kept as long as user session exists.  When user decides to close session, component is removed so all objects which are <code class="highlighter-rouge">@UserScope</code> annotated should be ready for GC.</p> <script src="https://gist.github.com/frogermcs/e593714bd539b5a1763b24dce8abe985.js?file=UserManager_closeSession.java"> </script> <h2 id="components-hierarchy">Components hierarchy</h2> <p>In our app all subcomponents use <code class="highlighter-rouge">AppComponent</code> as a root component. Subcomponents for screens which show user related content use <code class="highlighter-rouge">UserComponent</code> which keeps <code class="highlighter-rouge">@UserScope</code> annotated objects (one instance per user session).</p> <p><img src="/images/28/scopes.png" alt="Scopes" title="Scopes" /></p> <p>Example component hierarchy for <code class="highlighter-rouge">UserDetailsActivityComponent</code> can look like this:</p> <script src="https://gist.github.com/frogermcs/19a8c125b2b9fe54934a97035bf3f57c.js?file=AppComponent.java"> </script> <p>For <code class="highlighter-rouge">UserComponent</code> we use <a href="http://google.github.io/dagger/subcomponents.html#subcomponent-builders">Subcomponent builder</a> pattern to make our code cleaner and have possibility to inject this builder to <code class="highlighter-rouge">UserModule</code> (<code class="highlighter-rouge">UserComponent.Builder</code> is used to create component <code class="highlighter-rouge">UserModule.startUserSession</code> method showed above).</p> <h2 id="restoring-userscope-between-app-launches">Restoring UserScope between app launches </h2> <p>As I mentioned earlier UserScope cannot live longer that application process. So if we assume that user session can be stored between app launches, we need to handle state restoring operation for our <code class="highlighter-rouge">UserScope</code>. And there are two scenarios which we need to keep in mind:</p> <h3 id="user-launches-app-from-scratch">User launches app from scratch</h3> <p>This is the most common case which should be pretty straightforward to handle. User launches app from scratch (e.g. by clicking on app icon). <code class="highlighter-rouge">Application</code> object is created and then first <code class="highlighter-rouge">Activity</code> (<strong>LAUNCHER</strong>) is started. We need to provide simple logic checking if we have any saved user in our data store. If yes user is forwarded to proper screen (<code class="highlighter-rouge">UserDetailsActivity</code> in our case) where UserComponent is automatically created.</p> <h3 id="application-process-was-killed-by-the-system">Application process was killed by the system</h3> <p>But there is also a case which we very often forget about. Application process can be killed by the system (e.g. because of low memory). It means that all application data is destroyed (application, activities, static fields). Unfortunately this cannot be handled nicely — we don’t have any callbacks in Application lifecycle. To complicate it even more, Android saves activities stack. What means that when user decides to launch app which was killed somewhere in the middle of flow, system will try to bring user back to this screen. </p> <p>For us it means that we need to be ready to restore <code class="highlighter-rouge">UserComponent</code> from any screen in which it’s used.</p> <p>Let’s consider this example:</p> <ol> <li>User minimised app on <code class="highlighter-rouge">UserDetailsActivity</code> screen</li> <li>Whole app is killed by the system (later I will show how to simulate it)</li> <li>User opens Task Switcher, clicks on our app screen.</li> <li>System creates new instance of <code class="highlighter-rouge">Application</code>. What means that also new <code class="highlighter-rouge">AppComponent</code> is created. And then instead of opening <code class="highlighter-rouge">LoginActivity</code> (which is our launcher activity) system opens <code class="highlighter-rouge">UserDetailsActivity</code> immediately.</li> </ol> <p>For us it means that <code class="highlighter-rouge">UserComponent</code> has to be brought back (new instance has to be created). And this is our responsibility. Example solution to do this can look like this:</p> <script src="https://gist.github.com/frogermcs/c22f41b80db816623fd0795d520cd683.js?file=BaseUserActivity.java"> </script> <p>Each Activity which use UserComponent has to extend our <code class="highlighter-rouge">BaseUserActivity</code> class (<code class="highlighter-rouge">setupActivityComponent()</code> method is called in <code class="highlighter-rouge">onCreate()</code> method in <code class="highlighter-rouge">BaseActivity</code>).</p> <p><code class="highlighter-rouge">UserManager</code> is injected from <code class="highlighter-rouge">AppComponent</code> which was created with Application. Session is started in this way:</p> <script src="https://gist.github.com/frogermcs/ae6fdc70a4192810aa36f0143df23b23.js?file=isUserSessionStartedOrStartSessionIfPossible.java"> </script> <h3 id="what-if-user-doesnt-exist-anymore">What if user doesn’t exist anymore?</h3> <p>So there is another case to handle — what if user was logged out (e.g. by <code class="highlighter-rouge">SyncAdapter</code>) and <code class="highlighter-rouge">UserComponent</code> cannot be created? That’s why we have those lines in our <code class="highlighter-rouge">BaseUserActivity</code>:</p> <script src="https://gist.github.com/frogermcs/a98f2da2bade8c74bef650ccd56e2f2b.js?file=setupUserComponent.java"> </script> <p>But if there is a chance that UserComponent cannot be created we have to remember that dependency injection won’t happen. That’s why we need to check it every time in <code class="highlighter-rouge">onCreate()</code> method to prevent from NullPointerExceptions on injected dependencies.</p> <script src="https://gist.github.com/frogermcs/b5a54d5089a9dcd5cbfaa9b7175b53cd.js?file=UserDetailsActivity.java"> </script> <h2 id="how-to-simulate-application-process-kill-by-system">How to simulate application process kill by system</h2> <ol> <li>Open app on screen which you would like to test</li> <li>Minimize app with system Home button.</li> <li>In Android Studio, Android Monitor select your application and click Terminate</li> <li>Now on your device open Task Switcher, find your app (you still should see preview of last visible screen).</li> <li>Your app was launched, new Application instance was created and Activity was restored.</li> </ol> <h2 id="source-code">Source code</h2> <p>Source code with working example showing how to create and use <code class="highlighter-rouge">UserComponent</code> is available on Github: <a href="https://github.com/frogermcs/Dagger2Recipes-UserScope">Dagger2 recipes — UserScope</a>.</p> <p>Thanks for reading!</p> <h3 id="author">Author</h3> <p><a href="http://about.me/froger_mcs">Miroslaw Stanek</a><br /> <em>Head of Mobile Development</em> @ <a href="https://azimo.com">Azimo Money Transfer</a></p> Sun, 14 Aug 2016 00:00:00 +0000 http://frogermcs.github.io/building-userscope-with-dagger2/ http://frogermcs.github.io/building-userscope-with-dagger2/ Inject everything - ViewHolder and Dagger 2 (with Multibinding and AutoFactory example) <p>The main purpose of Dependency Injection pattern which is implemented by Dagger 2 is that DI separates the creation of a client’s dependencies from the client’s behavior. In practice it means that all calls of <code class="highlighter-rouge">new</code> operator, <code class="highlighter-rouge">newInstance()</code> and others shouldn’t be invoked in places other than Dagger’s Modules.</p> <h3 id="the-price-of-dagger-everything"><em>The price of Dagger-everything</em></h3> <p><em>The purpose of this post is to show what we can do, not what we should do. That’s why it’s important to know what we give in return for separating creation from behavior.</em> <em>If you want to use Dagger 2 for almost everything in your project you will quickly see that big piece of 64k methods count limit is used by generated code for injections.</em></p> <h1 id="inject-everything-example">Inject everything example</h1> <p>Probably the best known code example of Dagger 2 shows how to inject simple object (e.g. Presenter) to Activity and looks similar to this:</p> <script src="https://gist.github.com/frogermcs/397c3aae28921a86eee1318c2276f6b5.js"> </script> <p>When we start extending this code (let’s say we work on Activity which shows list of items) sometimes we take a shortcuts. It means that we don’t always @Inject new objects (like adapter in this case):</p> <script src="https://gist.github.com/frogermcs/a421ff40c8ad3b030e95696b46455ecf.js"> </script> <p>And with this approach we act against DI and profits given by it. Calling Adapter constructor inside Activity class means that every time when we need to change something in its implementation (new constructor argument, maybe completely new implementation which shows grid instead of list), we have to update Activity code.</p> <p>Sometimes taking a shortcut like this is intended (we know that this code won’t be extended more in the future). But today we’ll try to make all adapter related code a part of dependency injection approach. As an example we’ll extend our <a href="https://github.com/frogermcs/GithubClient">GithubClient</a> app - its screen which shows list of repositories for given username.</p> <p><img src="/images/27/repositories_list.png" alt="Repositories list" title="Repositories list" /></p> <p>To make it more complex and closer to real apps our Adapter will have three different view types: normal, extended and featured.</p> <h2 id="the-beginning">The beginning</h2> <p>Here you can see starting code base for our example. For me this is how the first iteration of implemented Adapter looks like in most cases.</p> <p><strong>RepositoriesListActivity</strong></p> <script src="https://gist.github.com/frogermcs/c1137169de22d237ad667f047e7b06df.js"> </script> <p><strong>RepositoriesListAdapter</strong></p> <script src="https://gist.github.com/frogermcs/c4954681c0803523f781e7b80e192e3b.js"> </script> <h2 id="adapter-injection">Adapter injection</h2> <p>At the beginning we’ll inject our adapter object instead of calling its constructor in Activity class:</p> <p><strong>RepositoriesListActivity</strong></p> <script src="https://gist.github.com/frogermcs/398409987d2a07be31a6e1ba1dd445df.js"> </script> <p>To make this possible we have to initialize <code class="highlighter-rouge">RepositoriesListAdapter</code> object in our Activity Module:</p> <script src="https://gist.github.com/frogermcs/d40499eb8689e1895b5b3eef493fa4da.js"> </script> <p>Pretty straightforward. Now let’s do some refactoring of our <code class="highlighter-rouge">RepositoriesListAdapter</code> class. Inner static classes for ViewHolders should be moved out of Adapter code:</p> <script src="https://gist.github.com/frogermcs/13e713582fefcd87a9a90a055b2a9768.js"> </script> <p>To do it fast in Android Studio just put cursor on class name and click F6 (<em>Move Inner to Upper Level</em>)</p> <p><img src="/images/27/refactoring.png" alt="Refactoring" title="Refactoring" /></p> <h2 id="assisted-injection-auto-factory">Assisted injection, Auto-factory</h2> <p>In the next step of our refactoring process we would like to move out construction process from <code class="highlighter-rouge">onCreateViewHolder()</code> method:</p> <script src="https://gist.github.com/frogermcs/d8b9a95d114e78a6f17be62b9d82f9a4.js"> </script> <p>It’s not as straightforward as in previous example. As you can see our ViewHolders have mandatory argument which is View object (<code class="highlighter-rouge">RecyclerView.ViewHolder</code> class has only one constructor: <code class="highlighter-rouge">public ViewHolder(View itemView)</code>). It means that every time when we want to create new object, we need to provide view (which is created during runtime so we cannot configure this in advance in Module classes).</p> <p>This problem is known as an <strong>Assisted Injection</strong> and was wider described on <a href="http://stackoverflow.com/questions/16040125/using-dagger-for-dependency-injection-on-constructors">StackOverflow</a> and <a href="https://groups.google.com/forum/#!topic/dagger-discuss/QgnvmZ-dH9c">Dagger Discuss group</a>.</p> <p>Final solution (until there is no official way of doing this in Dagger 2 framework) is to inject Factory object which takes those dependencies as an arguments and creates intended object. In mentioned StackOverflow thread you can see how to do this by hand, but also Google provides us a solution to generate those factories automatically.<br /> <a href="https://github.com/google/auto/tree/master/factory">AutoFactory</a> generates factories that can be used on their own or with JSR-330-compatible dependency injectors from a simple annotation. To use it in our project we have to add new dependency in <strong>build.gradle</strong> file:</p> <script src="https://gist.github.com/frogermcs/d5b7c56da46cd3b636aad6744c0c0ad4.js"> </script> <p>Now all we have to do is to annotate classes for which we would like to create factories:</p> <script src="https://gist.github.com/frogermcs/eadb4a653bde0430abdd023a135326e5.js"> </script> <p>Arguments of <code class="highlighter-rouge">@AutoFactory</code> annotation can make our Factory class extending given class or implementing given interface. In our case it will be:</p> <script src="https://gist.github.com/frogermcs/246f13498fdaba4ec98ea73074978e49.js"> </script> <p>After this update Adapter’s <code class="highlighter-rouge">onCreateViewHolder()</code> method looks like this:</p> <script src="https://gist.github.com/frogermcs/41f110d2110eef0376aac915f5828c19.js"> </script> <p>Now our code is a bit cleaner but still we call constructors inside it.</p> <h2 id="multibinding">Multibinding</h2> <p>Final step in our refactoring is to initialize our Factory objects in Module class to get rid of constructors calls in Adapter class. We can simply inject them as a <code class="highlighter-rouge">RepositoriesListAdapter</code> constructor parameters. But it would mean that every time when we decide to add/remove new type of ViewHolder we still would need to update Adapter code by hand.</p> <p>Instead we can make use from <a href="http://google.github.io/dagger/multibindings.html">Multibinding</a>. Thanks to this feature Dagger allows us to bind several objects into a collection (even when the objects are bound in different modules).<br /> Our ViewHolder factories have one thing in common: interface <code class="highlighter-rouge">RepositoriesListViewHolderFactory</code>. It means that we can inject map of Integers (type of Repository object is represented as a <code class="highlighter-rouge">static final int</code>) and RepositoriesListViewHolderFactory:</p> <script src="https://gist.github.com/frogermcs/d66e990d059199797bed17e293fcbeaf.js"> </script> <p>And here you can see how our map is created:</p> <script src="https://gist.github.com/frogermcs/dee5923bb9facedacb738ff503a44c4c.js"> </script> <p><code class="highlighter-rouge">@IntoMap</code> annotation makes those objects a part of map and puts them under keys given in <code class="highlighter-rouge">@IntKey</code> (<a href="https://google.github.io/dagger/api/latest/dagger/multibindings/package-summary.html">here</a> you can find more annotations for different types of keys):</p> <p>Finally, after all of those code improvements <code class="highlighter-rouge">onCreateViewHolder()</code> method is as simple as possible:</p> <script src="https://gist.github.com/frogermcs/01e558603e94b4da79798b39e2016acc.js"> </script> <p>No constructors, no if-else statements. Everything is done by proper Dagger graph configuration.</p> <p>And that’s all - our adapter and its ViewHolders are now a part of Dagger 2 graph. We are another step closer to <strong>inject everything</strong> in our code. With <strong>AutoFactory</strong> and <strong>Multibinding</strong> it will be much simpler.</p> <p>Thank you for reading! 🙂</p> <h2 id="complete-source-code">Complete source code</h2> <p>Here you can find source code of described classes after refactoring:</p> <ul> <li><a href="https://github.com/frogermcs/GithubClient/blob/4ee4a68bf2170295823020c6354976722b1a632a/app/src/main/java/frogermcs/io/githubclient/ui/activity/RepositoriesListActivity.java">RepositoriesListActivity</a></li> <li><a href="https://github.com/frogermcs/GithubClient/blob/4ee4a68bf2170295823020c6354976722b1a632a/app/src/main/java/frogermcs/io/githubclient/ui/adapter/RepositoriesListAdapter.java">RepositoriesListActivityAdapter</a></li> <li><a href="https://github.com/frogermcs/GithubClient/blob/4ee4a68bf2170295823020c6354976722b1a632a/app/src/main/java/frogermcs/io/githubclient/ui/activity/module/RepositoriesListActivityModule.java">RepositoriesListActivityModule</a></li> </ul> <p>Full source code of described project GithubClient is available on Github <a href="https://github.com/frogermcs/GithubClient">repository</a>.</p> <h3 id="author">Author</h3> <p><a href="http://about.me/froger_mcs">Miroslaw Stanek</a><br /> <em>Head of Mobile Development</em> @ <a href="https://azimo.com">Azimo Money Transfer</a></p> Sun, 12 Jun 2016 00:00:00 +0000 http://frogermcs.github.io/inject-everything-viewholder-and-dagger-2-example/ http://frogermcs.github.io/inject-everything-viewholder-and-dagger-2-example/ Async Injection in Dagger 2 with RxJava <p>A couple weeks ago I <a href="https://medium.com/@froger_mcs/dependency-injection-with-dagger-2-producers-c424ddc60ba3">wrote a post</a> about asynchronous dependency injection in Dagger 2 with <strong>Producers</strong>. Objects initialization execution on background thread(s) has one great advantage - it doesn’t block main thread which is responsible for drawing UI in real-time (<a href="https://www.youtube.com/watch?v=CaMTIgxCSqU">60 frames per second</a> for keeping smooth interface).</p> <p>It’s worth pointing out, that slow initialization in not everyone’s issue. But even if you really care about it in your code there is always a chance that any external library does disc/network operations in constructor or any <code class="highlighter-rouge">init()</code> method. If you are not sure about it I suggest you to give a try <a href="https://github.com/frogermcs/AndroidDevMetrics">AndroidDevMetrics</a> - my performance metrics library for Android. It can tell you how much time was needed to show particular screens in app and (if you use Dagger 2) how much time was consumed to provide each object in you dependencies graph.</p> <p>Unfortunately Producers are not designed for Android and have a couple flaws:</p> <ul> <li>Use Guava as a dependency (can cause 64k methods issue and increase build time)</li> <li>Aren’t extremely fast (injection mechanisms can block main thread for a few to dozens of milliseconds depending on device)</li> <li>Don’t use @Inject annotation (a little more mess in code)</li> </ul> <p>While we cannot do much with last two, the first one can compromise Producers in Android projects.</p> <h2 id="async-injection-with-rxjava">Async injection with RxJava</h2> <p>Fortunately a lot of Android devs use RxJava (and <a href="https://github.com/ReactiveX/RxAndroid">RxAndroid</a>) for creating asynchronous code in our apps. Let’s try to use it in Dagger 2 asynchronous injection.</p> <h3 id="async-singleton-injection">Async @Singleton injection</h3> <p>Here is our heavy object:</p> <script src="https://gist.github.com/frogermcs/e88824181b15477403bb26bb9d0af419.js"> </script> <p>Now let’s create additional <code class="highlighter-rouge">provide...()</code> method which returns <code class="highlighter-rouge">Observable&lt;HeavyExternalLibrary&gt;</code> object, which will call this code asynchronously:</p> <script src="https://gist.github.com/frogermcs/49e0039d249c040a8e3a64301519678d.js"> </script> <p>Let’s analyze it line by line:</p> <ul> <li><code class="highlighter-rouge">@Singleton</code> - it’s important to keep in mind that it will be single instance of <code class="highlighter-rouge">Observable</code> object, not <code class="highlighter-rouge">HeavyExternalLibrary</code>. Singleton also prevents from creating additional Observable object.</li> <li><code class="highlighter-rouge">@Provides</code> - because this method is also a part of <code class="highlighter-rouge">@Module</code> annotated class. Do you remember <a href="http://frogermcs.github.io/dependency-injection-with-dagger-2-the-api/">Dagger 2 API</a> 😉?</li> <li><code class="highlighter-rouge">Lazy&lt;HeavyExternalLibrary&gt; heavyExternalLibraryLazy</code> object prevents from initializing HeavyExternalLibrary object internally by Dagger (otherwise in a moment of calling <code class="highlighter-rouge">provideHeavyExternalLibraryObservable()</code> object would be already created).</li> <li><code class="highlighter-rouge">Observable.create(...)</code> code - it will return <code class="highlighter-rouge">heavyExternalLibrary</code> object by calling <code class="highlighter-rouge">heavyExternalLibraryLazy.get()</code> everytime when this Observable will be subscribed.</li> <li><code class="highlighter-rouge">.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());</code> - by default RxJava code is executed on a thread in which Observable is created. That’s why we should move execution to background thread (<code class="highlighter-rouge">Schedulers.io()</code> in this case) and just watch for the results on main thread (<code class="highlighter-rouge">AndroidSchedulers.mainThread()</code>).</li> </ul> <p>Our Observable is injected like any other object in graph. But object <code class="highlighter-rouge">heavyExternalLibrary</code> itself will be available a bit later:</p> <script src="https://gist.github.com/frogermcs/ce55b336b86b1a497ac951a1393a88b3.js"> </script> <h3 id="async-new-instance-injection">Async new instance injection</h3> <p>Code above presented how to inject singleton objects. What if we want to inject asynchronously new instances?</p> <p>Make sure that our object is not @Singleton annotated anymore:</p> <script src="https://gist.github.com/frogermcs/877e358790c8b21b043e0935db2125b0.js"> </script> <p>Also our <code class="highlighter-rouge">Observable&lt;HeavyExternalLibrary&gt;</code> provider method should be changed a bit. We cannot use <code class="highlighter-rouge">Lazy&lt;HeavyExternalLibrary&gt;</code> because it creates new instance only for the first time when <code class="highlighter-rouge">get()</code> method is called (see <a href="http://google.github.io/dagger/api/latest/dagger/Lazy.html">Lazy documentation</a> for more details).</p> <p>Here is the updated code:</p> <script src="https://gist.github.com/frogermcs/94a92cc9894db97bfbd6221b344ee627.js"> </script> <p>Our <code class="highlighter-rouge">Observable&lt;HeavyExternalLibrary&gt;</code> can be a singleton but everytime when we call subscribe() on it, we will get new instance of <code class="highlighter-rouge">HeavyExternalLibrary</code>in onNext() call:</p> <script src="https://gist.github.com/frogermcs/162044b19463fbca3431f52a91ad42c9.js"> </script> <h4 id="complete-async-injection">Complete async injection</h4> <p>There is another way to do asynchronous injection in Dagger 2 with RxJava. We can just simply wrap whole injection process with <code class="highlighter-rouge">Observable</code>.</p> <p>Let’s say our injection is performed in this way (code is taken from <a href="https://github.com/frogermcs/GithubClient/">GithubClient</a> example project):</p> <script src="https://gist.github.com/frogermcs/83d9f38a57826d637eaff3353c716ca2.js"> </script> <p>To make it asynchronous we just need to wrap <code class="highlighter-rouge">setupActivityComponent()</code> method with Observable:</p> <script src="https://gist.github.com/frogermcs/f32faa96c4d97610ad0ac2f46cbc18c1.js"> </script> <p>As it’s explained, all <code class="highlighter-rouge">@Inject</code> annotated objects will be injected in some time in the future. In return injection process will be asynchronous and won’t have big impact on main thread.</p> <p>Of course creating <code class="highlighter-rouge">Observable</code> objects and additional threads for <code class="highlighter-rouge">subscribeOn()</code> is not completely free - it will also take some time. It’s pretty similar to impact generated by <strong>Producers</strong> code.</p> <p><img src="/images/26/splash_metrics.png" alt="Splash metrics" title="Splash metrics" /></p> <p>Thanks for reading!</p> <h3 id="author">Author</h3> <p><a href="http://about.me/froger_mcs">Miroslaw Stanek</a><br /> <em>Head of Mobile Development</em> @ <a href="https://azimo.com">Azimo Money Transfer</a></p> Sat, 16 Apr 2016 00:00:00 +0000 http://frogermcs.github.io/async-injection-in-dagger-2-with-rxjava/ http://frogermcs.github.io/async-injection-in-dagger-2-with-rxjava/ AndroidDevMetrics - Activity lifecycle methods tracing <p><a href="https://github.com/frogermcs/AndroidDevMetrics">AndroidDevMetrics</a> is a performance metrics library which will help you find potential performance issues in your Android app. Thanks to it we are able to measure objects graph initialization in Dagger 2, Activities lifecycle methods timings and frame drops for each screen in app.</p> <p>Since today another new feature comes to light. Without any additions in app’s source code AndroidDevMetrics lets us profile Activity lifecycle calls (<code class="highlighter-rouge">onCreate()</code>, <code class="highlighter-rouge">onStart()</code>, <code class="highlighter-rouge">onResume()</code>) with method tracing.</p> <h1 id="methods-tracing">Methods tracing</h1> <p>Android itself gives us possibility to trace methods execution stack. Thanks to this we are able to get know how much time was needed to run each method (exclusively and inclusively - with all methods called inside this particular method).</p> <p>We have two ways to start profiling:</p> <ul> <li>Easier, less accurate directly form Android Studio. Accessed via <strong>Android Monitor tab -&gt; CPU -&gt; Start/Stop Method Tracing</strong> can be started and stopped by hand. Immediately after that Traceview debugger is opened with collected data. While this way is probably the easiest, in most cases it’s hard to hit start/stop in a moment which we want to measure.</li> <li>A bit more complex but extremely accurate - profiling directly from source code. Android SDK provides us <a href="developer.android.com/reference/android/os/Debug.html">Debug</a> class which has two methods: <code class="highlighter-rouge">startMethodTracing()</code> and <code class="highlighter-rouge">stopMethodTracing()</code>. Wrapping our code with them will give us very clear results. Trace file is saved in device’s storage so we can get it by calling <code class="highlighter-rouge">$ adb pull {file_path}.trace</code>. To see this file you have to just drag it to Android Studio. If you have used this method before, probably you know that there is one big disadvantage of <code class="highlighter-rouge">Debug.startMethodTracing()</code> - our code has to be recompiled and pushed to our device every time when we want to debug something new. So in more complex projects it takes ages (tens of seconds or minutes…)</li> </ul> <p>With a newest version of AndroidDevMetrics (v0.4) you can schedule method tracing for Activity lifecycle methods: <code class="highlighter-rouge">onCreate()</code>, <code class="highlighter-rouge">onStart()</code>, <code class="highlighter-rouge">onStop()</code>.</p> <p><img src="/images/25/adm_tracing.png" alt="AndroidDevMetrics" title="AndroidDevMetrics" /></p> <p>Profilling will take a place in the next Activity launch. You can even kill your app and open it again. In this case you will make sure that profiled Activities are created from a scratch.</p> <p>What next ? If everything will be ok you should see Dialog telling you how to grab generated <strong>.trace</strong>f files from your device. And then all you have to do is just to drag those files to Android Studio to see them.</p> <p><img src="/images/25/trace_finished.png" alt="Trace finished" title="Trace finished" /></p> <h2 id="traceview">TraceView</h2> <p>How it works in practice? Let’s assume that in our Activity we have this piece of code:</p> <script src="https://gist.github.com/frogermcs/05073ef65dd2582c1d8f.js"> </script> <p>As you can see, in <code class="highlighter-rouge">onResume()</code> app calls two methods. The 2nd one simulate any heavy operation which takes 500ms. Let’s profile it with AndroidDevMetrics:</p> <p><img src="/images/25/steps.png" alt="Steps" title="Steps" /></p> <p>Here you can see how TraceView looks like for capture file: <code class="highlighter-rouge">SplashActivityonResume.trace</code></p> <p><img src="/images/25/trace.png" alt="Trace" title="Trace" /></p> <p>We can see clearly that most of the time is taken by <code class="highlighter-rouge">SplashActivity.callHeavyMethod()</code>. It takes about 500ms inclusive time (why only 32µs of exclusive time? Because most of it is taken by <code class="highlighter-rouge">Thread.sleep()</code> called inside this method).</p> <p>Simple, right? I hope that thanks to this update we will save a lot of time which we would spend on recompiling the app code. 🙂 Now it’s your turn - let’s give a chance to <strong>AndroidDevMetrics</strong>. I would really appreciate your feedback!</p> <p>Thank you for reading.</p> <h2 id="source-code">Source code</h2> <p>Full source code of AndroidDevMetrics project is available on Github <a href="https://github.com/frogermcs/AndroidDevMetrics">repository</a>.</p> <h2 id="getting-started-with-androiddevmetrics">Getting started with AndroidDevMetrics</h2> <p>Script below shows how to enable all available metrics.</p> <p>In your <code class="highlighter-rouge">build.gradle</code>:</p> <script src="https://gist.github.com/frogermcs/9fca7b8758bab8fe850f.js"> </script> <p>In your <code class="highlighter-rouge">Application</code> class:</p> <script src="https://gist.github.com/frogermcs/de55ee04e25f670a2aa8.js"> </script> <h3 id="author">Author</h3> <p><a href="http://about.me/froger_mcs">Miroslaw Stanek</a><br /> <em>Head of Mobile Development</em> @ <a href="https://azimo.com">Azimo Money Transfer</a></p> Tue, 22 Mar 2016 00:00:00 +0000 http://frogermcs.github.io/androiddevmetrics-activity-lifecycle-methods-tracing/ http://frogermcs.github.io/androiddevmetrics-activity-lifecycle-methods-tracing/