Android Development Elliott Chenger Android Development Elliott Chenger

Kotlin Platform Types, Nullable Annotations and AOSP: A Cautionary Tale

I think it is fair to say that most of us are super happy with how nullability is handled in Kotlin. The overall code that we are writing with nullability in mind is mostly cleaner looking and helps us avoid the pitfalls we saw in Java. Having said that *Platform Types* are a place in particular that I ran into where I feel like the developer experience and the impact to the user is worse. If you are not aware, *[Platform Types][1]* are types that were created when Kotlin cannot infer the nullability of a type from Java.

I think it is fair to say that most of us are super happy with how nullability is handled in Kotlin. The overall code that we are writing with nullability in mind is mostly cleaner looking and helps us avoid the pitfalls we saw in Java. Having said that Platform Types are a place in particular that I ran into where I feel like the developer experience and the impact to the user is worse. If you are not aware, Platform Types are types that were created when Kotlin cannot infer the nullability of a type from Java. Let’s look at the URI class in Android as an example, and specifically let’s look at the getQueryParameter method:

public String getQueryParameter(String key) {
  return null;
}

If you will notice the return type in Java is String which can inherently return null as a valid response but Kotlin will not attempt to infer that and instead will mark this type as a Platform Type or String!. Because String! is able to be null we need to immediately treat it accordingly, which means using the safe call operator, ?. .

Now there is another way for us to solve the problem if you have access to source Java code that is returning here. You can add one of six approved annotations that denote nullability, which will tell the compiler how other code should expect to handle the nullability of the return types. The six types used here are the following:

• JetBrains (@Nullable and @NotNull from the org.jetbrains.annotations package)

• Android (com.android.annotations and android.support.annotations)

• JSR-305 (javax.annotation, more details below)

• FindBugs (edu.umd.cs.findbugs.annotations)

• Eclipse (org.eclipse.jdt.annotation)

• Lombok (lombok.NonNull).

My assumption is that this list is just widely popular and/or used annotations in Java. So to fix our problem we could do the following:

@Nullable//If the return type can be null
public String getQueryParameter(String key)

Or

@NonNull//If the return type can NEVER be null
public String getQueryParameter(String key)

Cool... so we’re done here, right? Nope, not at all. We don’t have access to the source code because this is an Android class, so what have they done to tell us the return type's nullability? It turns out that Google has its own internal Annotation to handle nullability which is not on the supported list. And the example class URI that we are using actually uses that Annotation as of Pie.

So, what’s the problem with that? Well, let’s expand the scope of our example. Still using uri.getQueryParameter(...) let’s create our own method that takes the result of that method and consumes it:

fun handleParam(param: String)

As you can see, in this case I am saying that the String type of param should not be null. And let’s now pass it the result of our URI param:

val param = uri.getQueryParameter(“id”) // Get the ID query Param
handleParam(param)

If the result of parsing the query param is null, when we call handleParam(...) with the null value an IllegalStateException is thrown and your app crashes. So basically we have swapped out an NPE for this new exception. What’s worse is that none of this fails at compile time. As far as the compiler is concerned, even though Platform Types are technically nullable, it will not proactively tell us that a possible error exists.

The result is that we need to be very careful about the return types of the Java libraries that we consume. The first and best solution is to find Kotlin based equivalent libraries where Platform Types do not exist. Though this is not a problem I suspect will be around for a long time it is something to keep in mind now and be wary of when interacting with Java code.

https://imnotyourson.com/which-nullness-annotation-you-should-use-on-android/

Read More
Android Development Elliott Chenger Android Development Elliott Chenger

Android Studio Tip #004: Finding concrete methods of Interfaces

Have you ever found yourself navigating through code and ending up at an Interface, instead of the concrete implementation you were hoping for? During Yun Cheng's talk - MVP The Life-Changing Magic of Tidying Up Your Presentation Layer (at 360 AndDev), her and her team uncovered that exact command.

Have you ever found yourself navigating through code and ending up at an Interface, instead of the concrete implementation you were hoping for? During Yun Cheng's talk - MVP The Life-Changing Magic of Tidying Up Your Presentation Layer (at 360 AnDev), her and her team uncovered that exact command.

What is it?

The Go To Implementation(s) action, which will take you to the concrete instance of and Interface. If more than one concrete class exists, a picker will be displayed that will let you choose which instance to go to.

How do I use it?

Position your cursor on an Interface method and press ⌘+⌥+B. Note: you can do this from the Interface class itself or you can do this from a invocation of the method.

Links:

Read More
Android Development Elliott Chenger Android Development Elliott Chenger

Gradle 4.1 Task Dependencies

While migrating to Gradle 4.1 an Android Gradle Plugin we discovered and issue that wasn’t documented. I would love to share this issue with you and explain how we fixed the problem.

While migrating to Gradle 4.1 and Android Gradle Plugin 3.0 we discovered an issue that wasn’t documented. I would love to share this issue with you and explain how we fixed the problem.

The Problem

My team develops libraries that get integrated into the apps we have at Under Armour and, because of that, most of the time we are working on AARs that are consumed by those apps. In our deploy script we run a series of tasks which, up until Gradle 4.1, all ran sequentially (even though you could enable parallel tasks prior to 4). So here is a rough idea of what our CI server runs when we merge code in:

./gradlew clean assemble artifactoryPublish

The problem we found after upgrading to 4.1 is that our tasks were now being run in parallel and our artifactoryPublish task would run before the end of the assemble task. This as you can imagine adds some complication, unless you can get the finished AARs from an alternative reality where the build is already done.

This is now parallelized due to the Worker API which was introduced in Gradle 4.1. I won't delve too deeply, but this new API was made with Android in mind and allows work from a task and build level to be parallelized with minimal effort (from the app developers side). The effort is mostly on the plugin developer, which I am not so I am going to refrain from saying more. Although I will note there is a great talk given by Paul Merlin and Gary Hale on this topic I would suggest watching.

After looking a bit more into the Worker API, I found that not only will this allow in-task parallel work, but it will also allow tasks with no relationship or dependencies to run in parallel as well:

(From the Writing Custom Tasks Guide): Of course, any tasks that are dependent on this task (and any subsequent task actions of this task) will not begin executing until all of the asynchronous work completes. However, other independent tasks that have no relationship to this task can begin executing immediately.

I was unaware of this initially, so after about two hours of experimentation we found that even though there is no way to turn the feature off there are two options for getting around the issue.

The Solution

Solution 1: Run tasks one at a time

Instead of running:

./gradlew clean assemble artifactoryPublish

We could do the following:

./gradlew clean 
./gradlew assemble 
./gradlew artifactoryPublish

Though I think this looks ugly, it gets the job done. Many people will scoff at this, there are times when the quick-and-dirty helps us get through a gauntlet unscathed. Most of the time I disregard these types of solutions, but in a time of need it is still valid.

Now, the reason that I say Solution 1 is viable is that I suspect many people in the Android community are not Gradle experts. I have spent 10-15% of my work time over the last year learning more about Gradle and I feel confident in my knowledge.. I suspect however, that I have still probably only touched 10 to 20% of Gradle.

Solution 2: Create task dependencies in your build gradle files

If you get into a situation where tasks are running out of order due to the parallelization of tasks in 4.1., think about adding task specific dependencies. In order to enforce the dependency between the assemble task and the artifactoryPublish task you can put the following line in your build.grade:

artifactoryPublish.dependsOn assemble

Note: If you have multiple modules in your gradle project you can cascade this to each of them using the subprojects configuration block in your project build.gradle.

The dependsOn method is part of the Task API and allows us to tell our artifactoryPublish that we depend on the assemble task to finish before it can run. Creating this dependency will now stop the assemble task from running before it should and causing build issues.

There have been many things that have changed with the Android plugin and the team at Google have done a great job documenting almost all of these changes. However, there are always things that are overlooked or may be under documented. I hope if you ran into task parallelization issues that this helped you get through the issue and I look forward to hearing other people's experiences.

Read More
Android Development Elliott Chenger Android Development Elliott Chenger

Android Studio Tip #003: Swap Intention Action

Today’s tip is going to be short and sweet. I was testing an internal library that I had little experience with a few days ago, when I noticed that for one method invocation I had reversed the inputs. This was partially to do with the lack of documentation and the fact that this legacy library lacked human readable parameter names, but I digress. The problem I had was that this method invocation was used enough that I didn’t want to swap all of the values by hand. 

Today’s tip is going to be short and sweet. I was testing an internal library that I had little experience with a few days ago, when I noticed that for one method invocation I had reversed the inputs. This was partially to do with the lack of documentation and the fact that this legacy library lacked human readable parameter names, but I digress. The problem I had was that this method invocation was used enough that I didn’t want to swap all of the values by hand.

After searching Android Studio for all its actions (⌘+⇧+A) it turns out that what I was looking for does exist. For methods with two parameters only, you can swap the parameters. This action is aptly named swap and though it doesn’t have a direct hot key, you are normally only a couple of keystrokes away from using it.

What is it?

The swap action is what the people at JetBrains consider an Intention Actions. You may be familiar with actions that show up as a light bulb icon next to your cursor, which happens under situations like missing imports, possible refactoring and potential bugs.

How do I use it?

Simply position your cursor anywhere inside your method invocation’s parentheses. And press (⌥+⏎), the Intention Actions drop down will appear and last on the list of the drop down should be swap ‘x’ and ‘y’ where x and y are the parameters you wish to swap.

I am not always swapping parameters so I can’t say this was a monumental find for me but as always knowing of its existence may save me more time in the future and hopefully it does you as well. What’s more important, or interesting, to note is that if you ever want to see what Intention Actions are available for your code you can always press (⌥+⏎) and find out.

P.S.

If you press (⌥+⏎) on string literals you can extract those strings directly to your Strings.xml. Which is great for refactoring legacy code with hardcoded strings.

Read More
Android Development Elliott Chenger Android Development Elliott Chenger

Android Studio Tip #002: Re-enable Test Artifact Switching

It's no doubt that Android Studio gets better with every version. Who doesn't love Instant Run? There is one thing I am sad to see change without mention. Test Artifacts are merged together by default now. 

It's no doubt that Android Studio gets better with every version. Who doesn't love Instant Run? There is one thing I am sad to see change without mention. Test Artifacts are merged together by default now.

If you aren't familiar with testing or test artifacts in Android, Google themselves have created a really nice starting point answering most of your questions. Also I love to note that I am a huge fan of the Arrange-Act-Assert pattern and TDD. I would definitely check them out if you are new to testing or programming in general.

I usually run my tests at the command line via the same build task that will be run on the server. This validate that what I am working on will in fact pass on the server. However, if I want to debug through my tests in IDE I usually like to isolate which test artifact I am running. The reason being is that tests run on the regular JVM are usually faster and it means I don’t have to have a device connected to run them.

So if you are like me chances are that you would like to not have your tests ran together out of the box. In order to get back the old Android Studio behavior navigate to the Experimental tab in Preferences.

Preferences>Build, Execution, Deployment>Build Tools>Gradle>Experimental

And simply toggle off the Enable all tests… box and apply. Voila! You now can switch between your Unit Tests and Android Instrumentation Tests.

TL;DR:

Read More
Android Development Elliott Chenger Android Development Elliott Chenger

Dex Redux

In October of 2014 a friend and past colleague of mine, Mustafa Ali, wrote a great Medium article to help solve a problem that many Android developers have encountered at one point in their career. The Dex method issue in short is a limit to the amount of executable methods allowed in Android's Dalvik Executable file (the one used to execute Android code). Shortly after writing his guide Google did the unthinkable... they released a support library. The library creates multiple dex files to help apps that are large get around the single dex file limit issue. Though this is a great solution for large apps Google suggests to use Proguard to strip your app of unused code or to reduce your dependency on libraries as a whole. The former is much easier than the latter. 

In October of 2014 a friend and past colleague of mine, Mustafa Ali, wrote a great Medium article to help solve a problem that many Android developers have encountered at one point in their career. The Dex method issue in short is a limit to the amount of executable methods allowed in Android's Dalvik Executable file (the one used to execute Android code). Shortly after writing his guide Google did the unthinkable... they released a support library. The library creates multiple dex files to help apps that are large get around the single dex file limit issue. Though this is a great solution for large apps Google suggests to use Proguard to strip your app of unused code or to reduce your dependency on libraries as a whole. The former is much easier than the latter.

I have to be totally transparent and say that I am not as familiar with the depth of the dexing process. I had initially planned on learning more about this and then writing up a large post however due to a family emergency I have not really had the time I wanted to devote to this. I am writing this in hopes to bring more exposure to the problem and maybe get some people who have a great understanding to help contribute to this post.

Finally The problem

So the other day while integrating two feature branches into our development branch. The following error occurred on our build server:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':application:transformClassesWithDexForNormalDebug'.
com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexException: Too many classes in --main-dex-list, main dex capacity exceeded

As I am not 100% familiar with what was going on I googled to see if this was something that others have been seeing. To my surprise there was only one result and that was a Google Issue Ticket. There isn't a ton of info in there, some people are suggesting that Google has broken a filter they have that creates the main-dex-list, which is a file that seems to be used to know which classes that should be included in the dex (I could be totally wrong about this).

Google acknowledged the issue, suggested a work around (which I have tried but haven't seen work) and opened another ticket to account for the actual solution. Because I couldn't get their solution to work I decided to test out a solution suggested by Alex Lipov, who was the one who created the Google Issue. Alex has a blog that talks through what he has found while working on this issue. Oddly enough he wrote this blog December of 2014 but didn't create the Google Tracker ticket till April 7th of 2016.

His updated solution is to access the CreateManifestKeepList class which is responsible for what gets kept for the dex. Then he modifies the accessibility of the class so it won't throw any exceptions while being modified. He basically makes the ImmutableMap mutable. It is a drastic approach but it works.

This is where the real fun starts. After utilizing his fix, I removed it so I could prove to myself that the fix is in fact real. When I removed his code from my Gradle build file...it still compiled without any issues. So I am interested in answering the following:

  1. What is the purpose of the main-dex-list?
  2. Why after removing the workaround am I not seeing the bug anymore?

Once I get back to real life I will pick back up and continue understanding the issue but I figured I would put this out and see if the community had any ideas what was going on. I would love to hear if you have had the same issue and how you solved it or if you have any extra info!

Read More
Android Development Elliott Chenger Android Development Elliott Chenger

Re: Chathead Basics

In Pierre-Yves Ricau's blog from 2013 he walks you through how to make a very basic version of Facebook's Chatheads, which if you haven't read is a great read and is yet another reason why I love Android. At the end of his blog he asked the question:

"Does this imply that Facebook Chatheads (or any application with SYSTEM_ALERT_WINDOW permission) is able to conduct keylogging and take screenshots at arbitrary time?"

It was a great question but after trying to explore more with adding views directly to the window I think I found another concern.

In Pierre-Yves Ricau's blog from 2013 he walks you through how to make a very basic version of Facebook's Chatheads, which if you haven't read is a great place to start and highlights yet another reason why I love Android. At the end of his blog he asked the question:

"Does this imply that Facebook Chatheads (or any application with SYSTEM_ALERT_WINDOW permission) is able to conduct keylogging and take screenshots at arbitrary time?"

It was a great question but after trying to explore more with adding views directly to the window I think I found another concern.

What was I trying to do:

In the advent of mobile phones I would have never thought that phones larger than 5 inches would be a market leading trend. However, here it is 2016 and I have a 6 inch Nexus 6p, which has been an amazing device despite it's size. So I set out to see if I could record any touch on the screen to see if I could start to build a heat map from my device. In doing so I made my phone un-usable. My solution was just a dirty proof of concept but I think what I proved is to be very careful adding things directly to the window.

My implementation:

As I said before right now my approach to this problem has been very basic. I took just a plain old View, made it the size of the screen and attached a touch listener to it. I let the touch listener return false, which by definition should have allowed other views to receive the touch. Most of the code is covered in Pierre-Yves' post so I won't go into much detail. What I found in practice was that I was now no longer able to interact with my screen at all.

touchView = new View(this);
WindowManager.LayoutParams params = new
         WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);

WindowManager windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
windowManager.addView(touchView,params);
touchView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return false;
    }
});

So it is apparent that any app with the SYSTEM_ALERT_WINDOW could render a user's phone useless or potentially could hijack the user's screen in a ransomware style attack. I am curious if anyone has found a way around this or has taken a different approach than me to do something similar. I don't want my idea to die off because though I love the Nexus 6P the one hand UX is absolutely horrible and I am trying to experiment with some different paradigms to see how they could make the experience better.

Note:

Since his post there is one slight change in how you ask for permssion to draw on the window, which I have covered in the following gist.

Read More
Android Development Elliott Chenger Android Development Elliott Chenger

Android Studio Tip #001: Bookmarks and Favorites

Chances are if you are an Android developer there are a bunch of really amazing features hiding in Android Studio that you have probably yet to discover. I am definitely not the exception to that and yesterday I stumbled upon (/took the time to understand) a few features that have so far made my life much easier. These features are Bookmarks and Favorites.

Chances are if you are an Android developer there are a bunch of really amazing features hiding in Android Studio that you have probably yet to discover. I am definitely not the exception to that and yesterday I stumbled upon (/took the time to understand) a few features that have so far made my life much easier. These features are Bookmarks and Favorites.

Conceptually these are about the most basic features that we could possibly ask for and are pretty self-explanatory. Besides the fact that it is painfully obvious what the features do, I was also frustratingly upset with myself because of where these features are located, which is in the Tool Buttons bar on the left side of Android Studio. These features weren't even hiding from me but staring me right in the face.

Favorites

So as I said before the Bookmarks and Favorites features are embarrassingly easy to understand. Favorites can be made of any file, from Java classes to XML resources and everything in between. To add the current file you are on to Favorites you can simply press (⌥⇧f) or you can right click on any tab and then click on Add to Favorites. You will probably need to create a new Favorite list or if you have any other lists already created you can easily add to them. I have found that it is helpful to name Favorite lists after tickets I have worked on or keywords so that I can easily find them.

Speaking of finding Favorites there are numerous ways you can get to the Favorites menu. The easiest way by pressing (⌘2) otherwise you can look on the Tool buttons bar (on the left hand side of the screen) and find the vertical Favorites tab. Note: If you are in Distraction Free mode you can easily show the side bars by pressing (⌘) two times. Also this view is searchable so if you start typing while you have something selected in that view it will start searching all of your Favorites and Bookmarks.

Bookmarks

Bookmarks are a bit more specific than Favorites. Bookmarks are done per line and can be created by pressing (fn F3) which will visually put a check next to the line, similarly to debug break points. You can as well have mnemonic bookmarks, by pressing (fn ⌥ F3) which in essence allows you to swap the checkmark out for number 0-9 or character A-Z. It's important to note that you can't reuse mnemonics. As well another difference from Favorites is the ability to give Bookmarks descriptions. Simply navigate to the Favorites tab on the Tool Buttons bar and right click on any Bookmark and select Edit Description.

There you have it a great way to create and organize Favorites and Bookmarks without cluttering up your IDE with tabs.

TL;DR

Favorites and Bookmarks are possible in AS and amazing!

Favorites

  • Add (⌥⇧f) or right click on tab
  • View/Edit/Remove Favorites (⌘2)

Bookmarks

  • Add/Remove Bookmark (fnF3)
  • Add/Remove mnemonic Bookmark (fn⌥F3)
  • View/Edit/Remove Bookmarks (⌘2)
Read More
Android Development Elliott Chenger Android Development Elliott Chenger

Being an Advocate for Android

“We can just port this from iOS to Android”  If you are an Android engineer then chances are you have heard this phrase many times in the past few years. It may even be because of this phrase that you are here today. I am no exception to this quandary, numerous times in my career I have found myself responding to this question or others like it. The first time I heard this I became irritated because certainly any designer working in the mobile industry already knew everything about Android. I quickly realized that this wasn’t one person neglecting the beloved Android platform. The problem is a lack of day to day experience with the platform. From that day forward I decided I will not contribute to the growing divide between the Android organization and the rest of my company. That was the day I became an advocate for Android.

“We can just port this from iOS to Android” If you are an Android engineer then chances are you have heard this phrase many times in the past few years. It may even be because of this phrase that you are here today. I am no exception to this quandary, numerous times in my career I have found myself responding to this question or others like it. The first time I heard this I became irritated because certainly any designer working in the mobile industry already knew everything about Android. I quickly realized that this wasn’t one person neglecting the beloved Android platform. The problem is a lack of day to day experience with the platform. From that day forward I decided I will not contribute to the growing divide between the Android organization and the rest of my company. That was the day I became an advocate for Android.

What an advocate isn’t

Many of you may cringe at the thought of calling yourself an Advocate. You’ll conjure up visions of linkedin profiles of people who have words like “ninja” or “guru” in their job title. Don’t worry I am not suggesting you update your profile and CV to reflect your new role. I am not even suggesting you go ask your boss to have your job title changed. What I am suggesting is to go above and beyond to make something truly amazing. Really this is only for the people who fall into one very specific category… people who give a damn about android UI and UX.

More important than any of this you don’t want to be the person that makes dividing lines between organizations. Many people in your company maybe be Apple users or have some very personal draw towards the Apple platform. It’s not your job to win them over to Android. It’s also not your job to shun those who don’t care to learn. We are quickly moving away from an iOS first or iOS only landscape but despite this there are still people who are going to think that Android is a second class citizen.

What does it mean to be an Advocate?

So what the hell is an advocate anyways? Great question! The dictionary definition says it is some who “publicly supports or recommends a particular cause or policy”, I would suggest we modify that a bit to be more actionable, with all due respect to Merriam-Webster, I would say it be something like: “A person who supports a cause through education and continuous engagement.”

Education

As an advocate we need to help bridge the gap between Android and the rest of our company. This may seem like a big task especially when you are in a larger organization however the more you educate the more experts you create in Android and now dissemination of information becomes much easier. To accomplish this we need to do a few things and make sure that they are ingrained in our company culture regarding android.

Don’t wait for others to start a discussion. Put together lunch meetings where you focus on talking through material design or just have an open ended discussion about design on Android in general. It’s important to test the waters and see what gets people in your company engaged in the discussion. Remember as you start to pull in more people of varying backgrounds there is more of a chance that people don’t understand what the hell you or someone else is talking about so encourage questions and dialogue. Education isn’t a one way street.

The Android platform gives us great domain specific language to speak with which helps us communicate with eachother. Educating people on this is a great natural place to start your education process. You will quickly find out what level of knowledge people possess in your company as well as help clear up any questions that they may have been too scared to ask. It’s been my experience that doing this not only helps others learn more about the platform but sometimes also help deepen or even unearth questions you have had and for whatever reason have never thought to ask out loud.

Part of what you are doing when you educate others is also creating future advocates. People who hopefully will go out after you are done talking and use this information to help others learn about Android. Your ultimate goal should be to take yourself or your team out of the equation as being the source of truth. Getting others to speak more frequently about this will hopefully go a long way to dispel the trend of always thinking iOS first and Android second.

Remember that talk is cheap and there are concepts that are hard to grasp without examples. So make sure you have plenty examples of what you are trying to discuss. You can do this through many ways: find apps in the play store that people can download and play with, draw things out on a whiteboard, my personal favorite is to create an app around what we are talking about. This takes extra time but acts as a way for you to refresh yourself on the topic as well as can give you a great starting point if you want to prototype new ideas.

Engagement

So you got the education thing down but the problem now is engagment. Don’t think of your new found role as a one and done type of thing. Overtime hopefully others will help participate but we need to keep the ball moving so that we keep people talking about Android. Make yourself available for more one on one discussions. If you just held a meeting talking about RecyclerView it may be a good idea to keep some time after for chatting with people who may have follow up questions. Be proactive and reach out to the people who came to the talk on an individual basis. This communication is great to get feedback about the meeting as well as continues the discussion and keeps that person engaged in the Android discussion.

Google and Material design isn’t The Word

Don’t pontificate purely because Matais and the design team at Google has said so in the material design guidelines. The general goal of all apps is for the UX and UI to be so seamless that they disappear into the background. Don’t like FABs because they obscure UI and context, that’s fine not all apps need these things. One of the most important things I have ever heard about UI and UX design is to “get out of the way of the user” I can’t remember where I heard this but this couldn’t be any more true. Material design is a great place to get the common ground for UI and UX on Android but when you feel your app starts to be prohibitive and not inhibitive it’s completely ok to start thinking of how to reduce friction.

So there you have it, you now have some tools and hopefully the courage to go and advocate in your department, organization or company. Remember that advocacy does not make you better or relieve you of any of your development duties. This is above and beyond the call of duty to help educate and engage others to increase knowledge and awareness of Android and it's amazing UI and UX.

--

Read More
Android Development Elliott Chenger Android Development Elliott Chenger

Fragments and the Toolbar

I am not one to generally praise Fragments, its mostly the navigational stack that always seem to give me a plethora of issues. Having said that, its comforting to find something that works the way you would expect. A few days ago I found that at the intersection of the Fragment and the Toolbar (formerly known as the Actionbar).

I am not one to generally praise Fragments, its mostly the navigational stack that always seem to give me a plethora of issues. Having said that, its comforting to find something that works the way you would expect. A few days ago I found that at the intersection of the Fragment and the Toolbar (formerly known as the Actionbar). I have been working on a side project which I have found to be the exact instance you would want to use Fragments. A flat top level where the Fragment container is switched out to provide small UI blocks that are not related. There is also a limited amount of options for this top level and very little to worry about with state.

I did however come across one thing that I had never run into before, the ability to have the Fragment update or change items in the Toolbar based on which Fragment is displayed. In my pessimistic state I figured, I was going to need some callback to reach my Activity to invalidate options or get the Activity and cast it and then have some public method on the Activity. Before I went down this path, I did a little bit of reading in the docs and low and behold I found setHasOptionsMenu. It turns out that setHasOptionsMenu is just the API that I was hoping existed, thats a great feeling when that happens. Here is what the doc says for setHasOptionsMenu:

Report that this Fragment would like to participate in populating the options menu by receiving a call to onCreateOptionsMenu(Menu, MenuInflater) and related methods.

Parameters
hasMenu    If true, the Fragment has menu items to contribute.

Beautiful! This makes total sense and is super easy to use, call this method from your Fragment's onCreate or onCreateView (I don't think that either makes a difference):

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        setHasOptionsMenu(true);
}

and now your Fragment is informed of any "related" menu callbacks. Ok so that was way to easy, now lets see how you listen to those callbacks. Again to my surprise all I have to do is override the onCreateOptionsMenu that I am used to from Activities and I am ready to go.

If you are reading this hopefully you understand why this is exciting to me, its not that Android is fraught with problems or that Fragments are really that hard, but for a long time things that held true for most situations in a Activity seemed to not be the case for Fragments. As well Fragments always seemed to be just different enough to where it was noticeable when you were working with one versus an Activity. I digress though, so the last and one of my favorite parts of this entire interaction is what happens to the menu when you create the menu from your Fragment. I assumed, once again pessimistically, that the call to onCreateOptionsMenu would completely override anything that was in my Activity and would mean that I would now have to handle each of the Activity's cases in my Fragment which meant the possibility of duplicate code or the creation of some utility to handle all of the menu logic in one place. I was once again wrong, the minute I inflated the menu and ran the app I noticed that all of my menu options from my Activity stayed and the ones from my Fragment were added to the current list. Not only that but both the menu and the Activity could receive callbacks when they were clicked, which could allow for different functionality per multiple Fragments without the underlying Activity having to hold and maintain that code.

So there it is if you haven't explored this option with your Toolbar I would highly suggest it, not only does this make me feel better about using Fragments (in very limited situations) but as always its nice to see where the architectural design of Android comes together to provide a great experience for developer and user.

Read More
Android Development Elliott Chenger Android Development Elliott Chenger

Mockito Verify Inconsistency

When I initially set out to blog about Mockito I wanted to write a post where I explained the Verify API. Though there wasn't much in the realm of posts around this topic, I think that the javadocs have ample examples. Maybe the only topic that would be worth covering for a second post would be good places to use Verify. I recently have been working a lot with the Verify API and found some inconsistencies that I wanted to share so that if you are using Mockito you can avoid the pain I had. So here it is two weeks later and here is my post about some caveats while using the Verify API.

When I initially set out to blog about Mockito I wanted to write a post where I explained the Verify API. Though there wasn't much in the realm of posts around this topic, I think that the javadocs have ample examples. Maybe the only topic that would be worth covering for a second post would be good places to use Verify. I recently have been working a lot with the Verify API and found some inconsistencies that I wanted to share so that if you are using Mockito you can avoid the pain I had. So here it is two weeks later and here is my post about some caveats while using the Verify API.

The Setup

I can't exactly share the original problem classes I had, yet, so instead I have recreated my problem in a set of examples. First, let's assume we have an interface called CallbackB (original name, I know) and it takes SomeModel as a parameter that we will say is only made up of a String.

public interface CallbackB{
        public void someMethod(SomeModel model);
    }

    public class SomeModel{
        private String text;

        public SomeModel(String text){
            this.text = text;
        }
    }

This interface defines the signatures for any class implementing it with the method someMethod. Now let's say we have the following class that uses CallbackB and we will call it ClassA (again, super original):

public class ClassA {

        private CallbackB mCallbacks;

        public ClassA(CallbackB callbacks){
            mCallbacks = callbacks;
        }

        public void doSomething(String text){
            if(text.contains("Artoo")) {
                mCallbacks.someMethod(new SomeModel(text));
            }
        }
    }

You can see that ClassA expects CallbackB to be passed to it from the constructor, but I wouldn't be too focused on that, the important part is the usage of the method doSomething.

You will notice that doSomething takes a string and if the string contains the text Artoo (my dogs name... sorry, only thing that came to mind as an example string) then we will call someMethod on our callbacks which is CallbackB.

Ok, so that’s the setup. We have a class which will act as callbacks for us, as well as a class doing some business logic which triggers the callback.

Testing

So now let's say we want to test that our callback is called at the correct time and for the correct reasons. In our case, because we are writing an interface that we expect someone else to utilize to listen for things happening in our code we don't care as much about testing what happens when the concrete versions of the interface are called, but the fact that they are called. To do this we can utilize Mockito and a tool through it called verify. If you have never used it I would highly suggest it. I will link to the docs for it but I don't want to spend time talking too much about how to use it. I may save that for another post if people actually want that.

So to test our interface our test could look something like this:

@Test
    public void doSomethingIsCalledOnlyOnceAny(){

      CallbackB mockedCallbackB = mock(CallbackB.class);
      ClassA classA = new ClassA(mockedCallbackB);
      String testStringHappy = "Artoo rocks!";
      String testStringSad = "Rocks!";

      classA.doSomething(testStringHappy);
      classA.doSomething(testStringSad);

      verify(mockedCallbackB).someMethod(any(SomeModel.class));

    }

Hopefully, this test is straightforward, basically we want to verify that someMethod is called only once and we don't care what the parameter passed to it is. This test will pass because of the way we built ClassA, however if we take out:

if(text.contains("Artoo")) {
    }

From the mix the test will fail because Mockito expects that the number of calls for that specific method should only be one. Now comes the oddity. let's say we use a custom argument matcher and also let's assume SomeModel has a getter to get the string. Here is what our ArgumentMatcher could look like:

class IsValidSomeModel extends ArgumentMatcher<SomeModel> {
        private String mExpected;
        public IsValidSomeModel(String expected){
            mExpected = expected;
        }
        public boolean matches(Object object) {
            String actual = ((SomeModel) object).getText();
            return actual.contains(mExpected);
        }
    }

Now that we have created the ArgumentMatcher the new test should look like this:

@Test
    public void doSomethingIsCalledOnlyOnceSpecific(){

      CallbackB mockedCallbackB = mock(CallbackB.class);
      ClassA classA = new ClassA(mockedCallbackB);
      String testStringHappy = "Artoo rocks!";
      String testStringSad = "Rocks!";

      classA.doSomething(testStringHappy);
      classA.doSomething(testStringSad);

      verify(mockedCallbackB).someMethod(argThat(new IsValidSomeModel("Artoo"));

    }

False Positive

So now we re-run the test suite. The first test will fail with the following error:

org.mockito.exceptions.verification.TooManyActualInvocations:callbackB.someMethod(<any>);
    Wanted 1 time:-> at com.omitneedlesscode.mockitoverifyexample.VerifyTests.doSomethingIsCalledOnlyOnceAny(VerifyTests.java:26)
    But was 2 times. Undesired invocation:-> at com.omitneedlesscode.mockitoverifyexample.ClassA.doSomething(ClassA.java:14)

However, the new test, mysteriously passes. Queue Twilight Zone music. I am still unsure why it is passing. However, I have come up with a temporary solution to the problem.

First and foremost, I would suggest not using the ArgumentMatcher while using verify. Instead I would suggest using the ArgumentCaptor it allows you to do assertions directly on the parameters themselves and seems to not be ailed by the mysterious passing test issue.

So let's say we want to go down this route. Here is a test with the ArgumentCaptor that will now properly fail due to too many invocations:

@Test
    public void doSomethingIsCalledOnlyOnceSpecificCaptor() {
                ArgumentCaptor<SomeModel> argument = ArgumentCaptor.forClass(SomeModel.class);
                CallbackB mockedCallbackB = mock(CallbackB.class);
                ClassA classA = new ClassA(mockedCallbackB);
                String testStringHappy = "Artoo rocks!";
                String testStringSad = "Rocks!";
                String expected  = "Artoo";

                classA.doSomething(testStringHappy);
                classA.doSomething(testStringSad);

                verify(mockedCallbackB).someMethod(argument.capture());

                assertTrue(argument.getValue().getText().contains(expected));
        }

So hopefully if you are using Mockito, or thinking about using it, this helps make things clear. The Verify API is a great asset in your testing toolbox, but be weary of some inconsistencies. Use ArgumentCaptors instead of ArgumentMatchers and don’t give up on tests because you can’t get them to run. The work you put in will save you regressions to your code, new bugs and will always make your code better.

Read More
Android Development Elliott Chenger Android Development Elliott Chenger

What developers should care about at I/O this year

Every year for the past 7 years the tech industry, financial analysts and tech aficionados alike post numerous blogs with rumors about the years I/O. This year is no exception. To give a different perspective, and maybe an altogether different approach, I have decided to come up with a few major things that Android developers should care about this I/O.

Every year for the past 7 years the tech industry, financial analysts and tech aficionados alike post numerous blogs with rumors about the years I/O. This year is no exception. To give a different perspective, and maybe an altogether different approach, I have decided to come up with a few major things that Android developers should care about this I/O. It's not to take away from the others who have spent time on an "I/O Prediction" article in the slightest, as I still love seeing what the rumor mill has to say. Hopefully, if you are coming to I/O to get something more out of your experience than just the keynote this will help you guide your course selection.

Code Labs

If I remember correctly, last year’s I/O did not have these. In 2013, I attended my first I/O which actually had the code labs and I was amazed how helpful it was. It makes a huge difference having someone there to help walk you through new APIs, to ask questions directly to a human being who has spent a good deal of their time working to understand how to use these APIs. In short, the code labs add great value to your I/O experience because it gives you scheduled time to work directly with all the cool things you just heard about in a subsequent talk.

This could be helpful not only with announcements related to this I/O, but could provide an opportunity to gain knowledge about other parts of Android you may be struggling with. Last year the lack of Code Labs meant that when I got home from I/O is when I really got deep into trying out new APIs and at that point it was much harder to solicit feedback. For some it was months until they were able to work with any of the Lollipop offerings and even worse for Material whose general support in pre-lollipop was decent, but still left us spending time exploring and asking questions on StackOverflow.

Battery, Rendering, Memory and Network Performance Tooling

This is a no brainer for many Android developers, but I feel it needs to be mentioned because making performance changes can be hard once you have written the code and even more complicated if you are reacting to bad press due to lots of jank. Colt McAnlis is a Developer Advocate for Android and has a series of youtube videos called Perf Matters. If you haven't watched this series yet, you have the rest of the day to catch up on these and if not please check it out after I/O. These are really great resources and worth your time to take a look.

Whether you are trying to get your app off the battery hog list, trying to make your UI snappy, helping to be a better user of system resource or trying to shave off data usage these talks will be a great jumping off point to making your app more performant and hopefully result in happy users.

It's important to note that this is in fact 4 different sandbox talks and thankfully they do not overlap at all, so be sure to attend them all.

Testing

Last, but not least is testing. I am unsure if this topic has even been covered at Google I/O in years previous, but I feel that in the 2 years that I have been in attendance I have yet to see anything major on this front. Hopefully this will be a really great series as well. Google will focus on both Unit (White box) and System testing (Black box) which is monumental and well timed with the recent announcment of the Android Testing Support Library which helps unifiy all aspects of testing in Android. Testing like many things in computer science is not a silver bullet, but makes a considerable difference in reducing your tech debt and in turn giving you and your team more time to work on adding all the new features we get tomorrow. It's also important to note that Google has done a lot to make testing a first class citizen of Android Studio. There is no doubt that these talks will be heavy in talking about how to structure, write, integrate and run tests. Not to mention a few years ago Google created a framework for system testing called Espresso, and this will be the first I/O talk that they will give about it so expect to learn a lot!

I feel like after seeing this years I/O schedule we are going to have a lot of tough decisions ahead of us. Not to say that any of the other talks are not going to be informative or worth attending. These are all extremely important topics and while the new stuff may entice you away from these just remember, the new stuff is recorded and when you are deep in a heap trace or debugging visual jank in your UI, was missing these worth the extra hours you will spend now going to look this info up?

Read More
Continuous Improvement Elliott Chenger Continuous Improvement Elliott Chenger

Process on a Personal Level

Process can be a double edged sword for many developers. I know personally the first time I learned about the different processes for making software I had tons of questions and also thought, “Why the hell do I need this?” After I realized the power that process had in making development more efficient and effortless, I noticed this process wasn’t only helpful for teams building software, but also for helping one tackle day-to-day tasks. Speaking with some of my friends and co-workers I discovered that most people have unknowingly created the same type of personal process to handle their work, which isn’t heavily rehearsed or planned. For a long time this was how my process was, finish a task move on to the next and triage any larger issues as they arise. About a year ago that changed and my process not only started to fail me, but I started to drown because my process didn’t allow me to scale easily. That being said, I set out to improve my process to help scale with the new responsibilities that I have.

Origin

My personal process started out very lightweight, as a contributor to a project my day-to-day was taking task from Jira, developing them and then putting them up for code review. Outside of that I would normally have to triage handling code reviews for other members of our team. This was the extent of my day-to-day and because my team’s process limited the amount of work we could do per two weeks I never felt overwhelmed or stressed.

Scale

This worked until I started to take on more of a leadership role for the project. My day quickly became more involved with juggling the release of our app to the play store, working with our customer’s dev and server teams for services and tools updates and outages, all the way to helping guide our customer for product decisions and technologies to use. Not to mention my usual day-to-day development and now meetings…way too many meetings.

This didn’t leave time for me to explore new technologies, develop prototypes or expand my development chops. I had emails I had to respond to, Jira tasks to finish, Google docs I needed to respond to or review, Confluence pages to update, builds to fix and technologies to investigate for my customer. In many ways this problem could have been solved simply by having enough people to split all the tasks amongst. However, as these things usually go, we were down a developer, had a tight deadline and a new team that had less context of the project.

How did I transform my process

I realized that I didn’t have one place to aggregate all of my tasks and because of that I was juggling numerous software sometimes just to get minor updates for portions of my tasks. So one of the first things I did was try and group my tasks together so that I could tackle numerous things each time I went into that specific software. For instance, when I went into Jira not only did I respond to any comments left for me, but I checked on everyone elses tasks to see if there was anything blocking them. I also looked at any new bugs that came in and triaged those, as well as got a general overview of our Jira boards. When I checked my email I tried to respond to everything in my inbox and sift through any crap that was just sitting in there. I found that this helped, but only if I had enough time to devote to each of these tools to keep the proverbial inbox from becoming too full.

I knew I was on to something though so I took another step back after setting up this initial process and I saw something interesting when I did. I could easily group these tasks (generally through email) into groups and even sub groups which I could prioritize based on more contextual knowledge of what is important to get done for each day. So for instance, I could group all my Jira emails for my project and then sub group those based off things like tickets I have been mentioned in, new tickets that have been created, etc. This meant that I could easily see from these folders the areas that I needed to attack at that moment, versus things that I could wait until later in the day.

I finally settled on a process that was starting to work for me. All of these tools sent email to my work account which were then filtered out of my inbox into their specific folder leaving my inbox to one off emails or things that require more immediate response. I accomplished this through using search queries in Gmail to be the backbone of each of my folders. Thankfully Google has a list of advanced search operators you can use which proved helpful in creating these.

Automate

After a few weeks of tweaking these queries and finding my sweet spot, I still had a major issue. The issue was that there was still this unnatural flow that using Gmail caused which didn’t allow me to prioritize items for each day. I had to understand what from each label was created on that day or before and that required a mental mapping that seemed a bit unnecessary. So after searching high and low I found a task application that seemed promising. Before settling on Todoist I tried almost every other under the sun including: Gmail Tasks, Google Keep, Anydo and GTask. The reason Todoist became the frontrunner for me were a few simple things that most task software didn’t have.

Integration with IFTTT (If This Than That) which allowed for me to trigger task creation when a new message was added to a label in gmail Tracking tasks for projects and tagging There is a mac app, web app and android app

This meant that IFTTT could do all of the heavy lifting for getting my emails into tasks and I could use email for its original intention… to communicate with others. Now in a perfect world I wouldn’t need Gmail to be the bottleneck for all task creation. I could write plugins for all of these tools to achieve the same results. Besides the fact that this would mean creating, maintaining and integrating with IFTTT my own custom code, all of these tools I am using are my customer’s and they have a fairly strict policy as far as custom integrations on their tech stack. So for all intents and purposes email can act as the middleman for me and also demonstrates how easy it is to take your email account back from the all of these constant automated messages.

Examples

So rather than just tell the story of my journey, I figured I would also give some examples for developers like myself to help possibly make your day-to-day better.

Broken Build

The build system my project is currently using is Jenkins. Jenkins will send out emails to any person who breaks a build or when a build is back to normal. I set up a few IFTTT triggers for this because not only did I want to make sure I had a task, but I also wanted to make sure my team was aware of the break or when the build was back to normal.

Google Filter Query:

IFTTT Recipe:

Screen Shot 2015-04-04 at 3.28.12 PM.png

New Builds are Ready

As you could probably tell from my previous example our team uses Slack as our means of communication. We all really dislike email so we have explored every option possible and finally ended up on Slack. Thankfully Slack integrates well with IFTTT so I came up with our new build trigger which happens when a new build is ready via Hockey App.

Google Filter Query:

IFTTT Recipe:

Screen Shot 2015-04-04 at 3.29.21 PM.png

You are mentioned in Jira

This was a really important one for me. When you subscribe to a jira task you will generally get a notification or email for every single note added to the ticket. This is great if you care to get every notification, but if you don’t and only want one when you are mentioned this is the IFTTT for you.

Google Filter Query:

Screen Shot 2015-04-04 at 3.46.31 PM.png

IFTTT Recipe:

This is nowhere near an exhausted topic and I am sure I will do a follow up as time goes on and things change for me and my process. The important thing I learned from this whole experience is that having and constantly updating a personal process is key to be successful at handling information overload.

I would love to hear about your process and what you have done so leave a comment below or tweet me @Echenger.

Read More
Android Development Elliott Chenger Android Development Elliott Chenger

What I want from Google Maps SDK for Android

For the past two months Google Maps and mapping has consumed a large portion of my life. During this time I have come to love and hate Google Maps V2. Besides just writing up a couple of issue trackers, I figured I would share my findings in hopes that it saves another developer the stress.

Touch Listeners

User input is super critical to be able to build robust mobile applications. The maps SDK falls short at providing developers the ability to differentiate between user input and programmatic camera changes. Currently the only way to tell that the user has interacted with the map is through the onCameraChangeListnener which should be considered a hack more than anything else. The API docs even go as far to say:

During an animation, this listener may not be notified of intermediate camera positions.

The simple fact that it may or may not be notified is a bit irritating to me. I would rather the API draw a line in the sand and either give me all of the changes or just the beginning and the end. I would say for simplicity's sake it would make sense to just give us the update at the end of the animation, then create a new listener for map touch events. Even just the basic touch up and down events would be a huge win.

Markers

A large part of the reason for having a map in your application is to visualize data or information. One tool Google gives us to do this is the marker, in essence a bitmap that represents a location on the map. Though it is probably the most utilized component of the maps SDK it is one of the most underwhelming. Lets take for instance marker animations. If you have done Android development before you would assume that the marker could be animated the same way as any other View. Unfortunately Marker is not a subclass of View so all of the base property animations are off limits. Instead the only field that is worth animating, position, relegates you to simple translations of xy, through the LatLng.

There is also some weirdness when trying to change a markers bitmap after it has been instantiated. The weirdness manifests itself as an IllegalManifestArgumentException when using the setIcon() method. Now Google hasn't officially responded to the issue and the status is marked as needs more info. I am hoping that they will have an answer soon, but until they do I am including this in my wish list. As of the writing of this post, the best way to side step this issue is to remove the marker and re-create the marker with the new bitmap you would like. Not the best of solutions, but I have not seen anything more staright forward.

Overall, a large portion of professional Android development right now is working with 3rd party SDKs and when doing so there is an inherent risk that we as developers assume. For me, the risk of having these issues or deficiencies in Google Maps was not enough to warrant me to look elsewhere for mapping SDKs, but the feature set put before me didn't create that restriction. Though Google Maps is a completely adequate tool, I would love to see more granular control for developers as well as better methods of communicating changes from the user to the developer.

Read More