It feels like Google is seriously promoting the use of CoordinatorLayouts these days. They even released (unfortunately, I can’t seem to locate the link for it) an entire blog/website dedicated to teach little tips and tricks to properly using the CoordinatorLayout.
CoordinatorLayouts are great. I like them. When you start a new Android project and create a new empty Activity, Android Studio will even autogenerate a new XML layout file with a CoordinatorLayout. They make implementing certain Material design easy to implement and given that you actually know how to use the layout properly, makes laying out elements on your screen very easy.
However, I’ve seen some developers (which includes the past me) use CoordinatorLayout as container of some sort, kind of like a FrameLayout. While this “works”, it isn’t optimal.
CoordinatorLayout is computationally more expensive than any other layout in Android, thus including it in your layouts when you’re not using its specific features will unnecessarily increase CPU load in return for no benefit. Thus, if you’re not using any of CoordinatorLayout‘s features, it’s always better to replace with a FrameLayout or a RelativeLayout to lessen the CPU load.
This is a relatively short blog post, but an important one for me as I’ve been unnecessarily using CoordinatorLayouts when using other layouts would have been a better choice.
Many apps that have a user authentication component sends a user’s access token to have access to the API and that user’s information.
Many posts on StackOverflow suggest storing the user’s access token in SharedPreferences to have easy access to it. In fact, this is what I’ve been doing too as it is easy and convenient. Also, based on what I’ve been reading on how to store tokens on the client side, this seems to be the de-facto way most people approach storing tokens on client side.
One recent code review I’ve gotten suggested that I use a third party Secure SharedPreferences library to encrypt the user’s access token. This is because a user who may have root access to their phone will be able to view the values stored in SharedPreferences. Is this being a bit too paranoid? I think so. I mean, the last time I rooted my phone was back in the original Droid days (500 mhz phone…) so that I can overclock it and install custom ROMs. These days, phones are so fast that I’m too lazy to root it. But is Secured SharedPreferences easy enough to implement to warrant not doing it? Nope, it’s super easy that it makes no sense not to use it to encrypt potentially sensitive user data when saving data to SharedPreferences.
There are numerous libraries available to do this. I decided to go with this one since it was the one suggested by the code reviewer.
Code reviews like this made me wonder whether I should get a proper job where I can work on Android development on a team with more people who are more experienced in Android development than I am. It should speed up my learning process (as it did with web development a few years ago). Also, I do miss working on a proper software development team.
In this blog post, we’ll go over how to build out custom Info Windows in Android.
What are Info Windows? In applications that display a list of locations in a map with pins, you can often tap on the pins to display information about that specific location. One example is the maps feature in the Yelp app where the app will display a map with various pins of locations of interest on the map. You can click on the pins and it’ll display a little pop up with the various data about that location. Sample screenshot is below.
That little pop up that displays with the label “El Gran Pollo”, rating table, and etc is the Info Window. The Android SDK comes with a standard InfoWindow that allows you to display a title and description. If that’s enough and the design of the standard InfoWindow meets your requirements, then you can stop here. If you need to customize your InfoWindow, continue reading.
This tutorial is going to assume that you know how to integrate Google Maps into your Android application and that you know how to obtain location information using the LocationListener and GoogleApiClient.
Set those up first and prepare a list of data that you would like to display.
Sample data that we’ll be working with
We’ll be displaying different restaurants on the map. The model will look like
The name and description fields are straightforward. photoUrl field will return a url with an image file. We’ll be using Picasso to insert photos into the ImageView‘s.
Pin the markers
Assuming that your Google Map on your Activity (or Fragment) is set up and ready to go, we’ll start pinning the markers. We’ll have a list of Restaurants in an ArrayList and go from there.
// This is a bit of a hack to get custom images loading. If you
// don't have images in your custom info windows, you do not need
// the following two lines
The code above is simple but there are two non-obvious things. The first is the mRestaurantMap where we keep reference to the restaurants themselves with the markers as keys and the second is the last two lines of code where I call showInfoWindow and hideInfoWindow methods on the markers.
In the RestaurantInfoAdapter that we’ll be coding up next, we’ll need to be able to retrieve the correct restaurants that belong to a specific marker that the user taps on the screen. the mRestaurantMap HashMap is an easy way for us to store and retrieve the correct restaurants.
As for the showInfoWindow and hideInfoWindow methods, this is a workaround in order to display any images that you want to show on your Info Windows. As noted in the comments in the code snippet above, you do not need these two lines of code if you do not have any images in your custom info windows.
Write the InfoAdapter
Let’s write our Custom Info Adapter and the accompanying XML layout file.
First create your custom layout file. I’ll be naming the file info_window_restaurant. The code for the layout is below.
In this layout, I’m using a CardView in order to easily provide rounding border radius. If that’s not a requirement for you, then you can use whatever layout (RelativeLayout, LinearLayout, etc.) that you want. I also have an ImageView in there to display the photo of the restaurants that will come in later.
Next up, let’s build our Info Adapter. Back in your Activity or Fragment file where you had that pinMarker method, add this class.
Here, you can see the mRestaurantMap coming into play, where we take the marker that is passed in to retrieve the correct Restaurant from mRestaurantMap. Then we grab that and set the texts and images for the TextView‘s and the ImageView.
If you are observant, you may have noticed the new MarkerCallback(marker) line in the Picasso part of the getInfoWindow method. This is a workaround that we have to do specifically when trying to load images in custom info windows due to the race condition that occur between Picasso and Google Maps. This StackOverflow post’s accepted answer explains it pretty well.
Basically, you’ll need to build a custom callback into Picasso or your image loading in your custom info windows will be inconsistent at best and non-functional at worst. Also, I found the code solution in that StackOverflow post to not work for me, so without further ado, below is the solution that have worked for me.
And yep, the solution is pretty much the same, except that I call hideInfoWindow before showInfoWindow. I found that just calling showInfoWindow doesn’t help reload the page.
Also, remember the two lines of code in the pinMarkers method where I call hideInfoWindow and showInfoWindow during the pin marking process? The reason I do that is because if I don’t, the image in the first pin that the user taps on, the image will never load. I’m not sure why, but hiding and showing the info windows quickly (so that the user doesn’t notice) when you’re pinning the markers initially is a workaround that I found to work well.
You can also further optimize this solution by adding a boolean variable in your RestaurantInfoAdapter to determine whether Picasso has already loaded and displayed the image or not. Since Picasso automatically caches images for you, if the marker has been tapped and image already loaded and displayed, we do not have to add the MarkerCallback into our Picasso calls. This is simple to do so I won’t display that here.
I hope this post helps anyone who needs to build custom info windows in their Android apps.
Sometimes, you’ll need to get one or a list of nearby addresses using latitude and longitude. Unfortunately, the standard way of implementing this feature has a bug within Google’s Android ecosystem, making the implementation unreliable. I’ll go over an alternative implementation that is more reliable.
Let’s say that you want to retrieve an address using the latitude and longitude that you get from your phone’s GPS system. The standard documented way of going about this is using the Geocoder library, pass in your latitude and longitude data, and ask for a maximum number of suggested addresses. The code usually looks something like this.
This is the ideal and clean way to retrieve addresses using geolocation data, but the results you get will be inconsistent. More often than not, you won’t get any addresses back and you’ll get an error in your console that goes something like Geocoder throwing exception: IOException: Service not Available.
If you look at the Geocoderdocs, it has a line that says
The Geocoder query methods will return an empty list if there no backend service in the platform. Use the isPresent() method to determine whether a Geocoder implementation exists.
The question is… what the heck is a “backend service” mean? Just like many of Google’s lovely documentation, it fails to mention what this backend service is. Is it something provided by Google or is it something you have to implement on your server side code? At the time of this writing, I still don’t know the answer.
Many of the solutions to this problem found on StackOverflow suggests that you simply reboot your device. This seems to work for some people (it never worked for me), but this is an unreasonable request to ask of to your users. Thus, I came up with something way more roundabout to get the addresses but way more reliable at the same time. Rather than using the Geocoder library, I make http requests directly to Google Maps API with the latitude and longitude interpolated in the web url. I get a JSON object back from this request and I parse through that JSON object to get the address information that I need.
The code sample below assumes that you’re using OkHttp version 3 to make your HTTP requests and Google’s gson library to parse the JSON, but you can use whatever you want.
As you can see, the code is straightforward. I build a url string that has my latitude and longitude information in it, and I make a HTTP request to that url, and then I parse through the JSON object that I get back appropriately to get the address that I want. The nice part of the JSON object that we do get back is that it comes with a field with the address already properly formatted for us 🙂
There are other “workarounds” that utilizes Geocoder floating around the internets (some of which include trying to make requests with Geocoder in an endless while loop) and using Geocoder ends up in cleaner code, I think that the brittleness of that library makes it a suboptimal solution. My workaround makes you write a bit more custom code to get the address data that you need, but it’s reliable and will work consistently.
A lot of apps have a landing screen with images and logos where you can slide through various screens. There are various third party libraries in the open source world that makes this easy, but none of them are highly customizable. In this post, I’ll go over how to build one of these slideshows from scratch.
Just so that we’re on the same page, an example library that lets you easily build an Intro Slider is https://github.com/apl-devs/AppIntro. In one of the apps I’m working on, I had to build out something similar, but with two static buttons in the bottom of the page that the user can interact with. Needless to say, none of the libraries I could find was able to accommodate this. So, I had to build my own.
And here’s the video of the intro slider that we’ll be building
1 – Define the slider position dots and various colors
Open your colors.xml and define two colors for our slider dots, one for an inactive state and one for an active state. Also, go ahead and define a color for the white color and colors for the three background images that we’ll have. These colors will come into play later.
<!--Bunch of other color definitions up here-->
<!--Slider dot colors-->
<!--Slider Background Images-->
You can change those color definitions to however you want them.
2 – Remove the Toolbar and then hide the notification bar in MainActivity
We want to remove the Toolbar that comes with the standard MainActivity and then hide the notification bar to give more prominence to our intro slider.
For removing the Toolbar, we need to add two style definitions to our AppTheme. So open up styles.xml and then add these two lines into your main app theme.
Adding those two lines with the windowActionBar and windowNoTitle will set an application wide theme where the Toolbar (or ActionBar for those of you who want to proper naming) will be hidden by default.
Now, we want to hide the notification bar. This has to be done in code and isn’t available in all versions of Android. Open up your MainActivity file (or whatever activity you are displaying your intro sliders) and add this code.
Make sure you add those two lines before you call setContentView. We want it to take effect before we set the view of the activity. What this will do is hide the notification bar if the feature is available on the device running the app (SDK version of the device is higher than 21).
3 – Creating the slides
We want to create the 3 slides that the user will be able to swipe through (you can create more if the app you’re building requires more slides). Under your res/layouts folder, create three layout files named landing_slide_1.xml, landing_slide_2.xml, and landing_slide_3.xml respectively.
All of the slides are practically the same with the exception of the texts and the background colors that we’re displaying. This is to distinguish the slides from each other so that you will be able to see that different slides are displaying as you are swiping through the ViewPager that we’ll be building. You can also replace the texts with ImageViews and other components as you see fit.
4 – Build the MainActivity XML layout
We want the above landing slide layout files to display in our activity_main layout file. We also want them to be displayed inside a ViewPager. Finally, we want to have two static buttons at the bottom that stay in place as the user swipes through. Open up your activity_main.xml file and copy/paste this in.
I’ll go over the important parts of this code step by step.
First important parts are the mLayouts array containing various layout ids and the addBottomDots method. The mLayouts integer array holds all of the layout files that you’ll be displaying in your intro app slider. In our case, we have three: landing_slide_1, landing_slide_2, and landing_slide_3. We then have our addBottomDots method that will programmatically add the slider dots to our layout file. These dots will help indicate to the user exactly which slide he/she is in.
When we are defining these in our onCreate method, we want to pass in “0” into our addBottomDots method so that when the user first opens the app, the first dot will be highlighted. In our addBottomDots method, you can see at the bottom of the method that we retrieve the current dot with the currentPage integer passed in to set the text color of that dot to R.color.dot_slider_active that we defined in our color definitions at the beginning of this tutorial.
The sole reason for us to even have this OnPageChangeListener is to call the addBottomDots method with our current position so that the correct dot is highlighted as the user swipes through the various slides. As you can see, we call our addBottomDots method in the overridden onPageSelected method, passing in the current position of the ViewPager page. This will dynamically activate the correct dot and inactivate the rest of the dots with appropriate colors as the user swipes through the various landing screens.
Second piece of code that we need to write is our ViewPagerAdapter. We define it as SliderViewPagerAdapter in our sample app and it extends itself from the PagerAdapter class. This part of the code is pretty simple. The adapter determines which view to inflate using the mLayouts array we defined above (the one that contains the various layout ids).
After all this, we finish setting up our MainActivity by setting an instance of our SliderViewPagerAdapter to our ViewPager and then setting our viewPagerPageChangeListener as our ViewPager’s OnPageChangeListener.
This post will show how to filter through a list of data that’s set in a RecyclerView.
A lot of apps have a search feature where you have a list in a RecyclerView and a Search menu bar where as the user types, the list filters automatically. I wrote a whole post on how to build a custom search view in one of my posts. Thankfully, this guide will be more brief and straightforward.
The main library that we’ll be utilizing is the same SearchView library that we used in my Custom SearchView post, MaterialSearchView.
If you’re observant, you’ll see that we call two methods sequentially, getFilter and filter on my RecyclerView.Adapter (variable named mAdapter). We have a method on my adapter called setData and we use that to set our data. I’ll go over the getFilter and filter methods first.
getFilter && filter
First thing we want to do is to implement Filterable on our RecyclerView.Adapter
// More typical RecyclerView stuff below, like ViewHolder pattern and stuff
There are a few things going on here. First, we implement Filterable to our adapter and implement the necessary methods getFilter and getFilteredResults. What these two basically do is take in a string (which is passed in from our activity which is bound to the user inputs in our SearchView), and filters through the data list. It scopes down the data based on the filtering conditions we give it, and returns the result. This implements the actual filtering feature that works with the filter method we have in our mAdapter.getFilter().filter(newText) method chain.
One important thing that we do in our activity though is when the user input is empty. If you look at the listeners that I set on our SearchView, you’ll see that I constantly set the dataset in our RecyclerView back with the full data set. The reason for this is because the data set in our adapter will be reduced as the user searches through. Thus, we want to “reset” our list of data back up to full when the user either deletes some of his/her input to search for something else or clears the input in the SearchView entirely.
SVGs (Scalable Vector Graphics) are awesome. They resize themselves perfectly to any size without quality loss and thus allowing us to skip the tedious process of scale the image files for different density buckets.
In web development, we can use SVGs directly for improved front end performance. Unfortunately in Android development, we cannot use SVGs directly and need to convert them to their corresponding XML files. Doing this is used to be a tedious process (I think I remember doing this in web development, cobbling together various tools on the web), but Android Studio includes a tool called Vector Asset Studio to make this process easier.
Here are the steps to integrate your own SVGs into your Android app using Android Studio.
Right click on your drawable folder in Android Studio and then drill down to New -> and then select “Vector Asset”.
Do note that Android Studio comes with all of the SVG Material Design icons that you can export into appropriate XML formats. But in our case, we want to use our own SVG files, so select “Local file (SVG, PSD)” under Asset Type and choose the appropriate file under the Path section. Once you have selected your file, click “Finish”.
And that’s pretty much it. Clicking on that “Finish” button will create a new XML file that will be a representation of your SVG file under your drawable folder.
There’s a method called onBackPressed that you can override in Activity classes. This is a pretty easy way implement any custom action you might want to take if and when the user presses the back button. However, this onBackPressed override option is unavailable in fragments. We can make this feature available in fragments however. And that’s what I’ll be going over in this post.
Our activity and fragment that we’ll be referring to as examples will be called MainActivity and MainFragment (creative names, I know). MainActivity will be displaying MainFragment and for whatever reason, we want to be able to listen to onBackPressed in our fragment instead of our activity. Just as a note, I had come across this problem where one activity had a ViewPager displaying content from two different fragments and I had to listen to the back pressed action in the fragments instead of the Activity due to the requirement of passing some data from individual fragments instead of the Activity.
To implement this, we need to utilize interfaces in our Activity which we will implement in our Fragment. So, in your MainActivity, add an interface called OnBackPressedListener like this and override both the onDestroy and onBackPressed method as shown.
Here, we are defining an interface called onBackPressedListener which defines a method called doBack. We will be implementing this interface in our fragment. We also have a method called setOnBackPressedListener which we will be calling in our fragment.
We are also overriding both the onDestroy methods and the onBackPressed methods. In the onDestroy method, we are nullifying the instantiated onBackPressedListener so that it doesn’t interfere with any new future activities that are instantiated. In the overriden onBackPressed method, we call the doBack method on the onBackPressedListener if it is not null, or just call the normal onBackPressed method of the Activity if it is null. We’ll be utilizing this altogether in our fragment.
Now, implement our fragment like this. The main thing you’ll see is that we’ll be implementing the MainActivity’s OnBackPressedListener in our fragment.
// Whatever you need to do here when the user presses back
The most important part in our MainFragment is that we implement the OnBackPressedListener interface of our MainActivity and then in our onViewCreated method that we override, call the setOnBackPressedListener method while passing in the MainFragment. This will allow us to utilize MainActivity’s onBackPressed method in the doBack method of our MainFragment.
And that’s how you can listen for the back pressed action within your fragments. Sometimes I do wish that Google would just provide default APIs for these types of things.
In this short blog post, I’ll write about a pattern I like to use when starting new activities in Android development.
To start a new activity in Android development, we need to instantiate an intent, specify in that intent the current activity’s name and the new activity’s name. The code usually looks something like this.
This is pretty common and straightforward. The one thing I never really liked about this though, especially if the ToActivity is an activity that’s called often from different places, is how I always have to manually instantiate a new intent and then specify which activity I am trying to open.
Instead of manually instantiating a new intent in an Activity file every time I want to open a new intent, I like to set a static method on the Activity class that needs to be opened. For example, in our example, in our ToActivity class file, I would have a static method called startActivity that looks like this.
I find this to be much cleaner compared to our previous version. Also, if we need to start up ToActivity from more than one place, this pattern allows us to reuse the startActivity method, thus reducing duplication.
API endpoints that return a list of data often have pagination parameters that you can pass in to get different pages of lists back. Often, they have something like page and per_page parameters that you can pass in.
Let’s say that there’s an API endpoint that returns a list of books. In the database of the API, there are 100,000 books. It would be impractical to fetch all 100,000 books from the API all in one request. In fact, we would probably get an OutOfMemory exception. To avoid this, we want to paginate through our list of books when making requests to our API. Just as a note, the code samples below for making the API calls are using Retrofit with GSON.
Setting up Retrofit for pagination
Here’s our Retrofit interface with a definition that will get a list of books with pagination
Here, the page is referring to the page number that you want and limit is referring to the number of books you would like to fetch per page.
I generally like to have an interface where I define variables that will be constants throughout my application. Page limit for pagination purposes when making a API request is one of those things that I like to keep consistent throughout my apps, unless it’s a requirement that they be different throughout the app. So let’s make a Constants interface.
Here’s I have set up a Constants interface that I can implement throughout my activities and fragments. I also defined a URL_DOMAIN that would be consistent throughout the app.
Now, let’s write our class that will generate our RetrofitService.
This ServiceGenerator just has a factory method that will generate our service whenever we need it.
Making the API call
We’ll be making the API requests in our MainActivity. Let’s also say that we have already defined our activity_main.xml with a RecyclerView and that we have our layout for our row adapters for our RecyclerView all set and ready to go.
// Your typical average RecyclerView code with ViewHolder
Building the pagination
We’ll be using a library for this portion. There are two main reasons for this.
It makes for shorter, more readable, and concise code
It comes with Material Design loader all ready and set to go
Most guides that shows you how to do this manually don’t work very well
The biggest reason is number 3. If you do a quick Google search on how to paginate through a RecyclerView, you’ll quickly realize that there isn’t really a consensus on how to do this properly. Also, there isn’t really a clean API on the RecyclerView that allows you to detect the exact position of the user in your RecyclerView. Just to figure out where your user is, you have to do all sorts of positioning math wizardry, which can take time to figure out and can be easy to get wrong. Thus, to make our lives easier, we use a library.
The one that I found to be the simplest and straightforward to use is the Paginate library by MarkoMilos (https://github.com/MarkoMilos/Paginate). So add that to your app/build.gradle file and also add the SmoothProgressBar (https://github.com/castorflex/SmoothProgressBar) to it too. The SmoothProgressBar is actually already a dependency of the Paginate library, but in case you want to customize your loader spinner that the user sees when he/she reaches the bottom of the page, you’ll need that SmoothProgressBar library added separately to your app/build.gradle file.
// Your typical average RecyclerView code with ViewHolder
A few things have been added and changed in this final version.
First major thing is that we have added the overriding callbacks that are required by the Paginate library. As for the instance variables, we have added three:
Boolean variable mLoading which is initialized to false and
Integer variable mCurrentPage which is initialized to 1
BookLibraryServiceAPI mService so that we can initialize it just once and reuse throughout the MainActivity class
There is a new variable mPaginate that will initialize the pagination feature.
The mLoading variable is set to true when we’re making the API call, but is set back to false when the API call has finished. We then use this variable in the overridden isLoading() method to tell our Paginate library whether new list is being loaded into our RecyclerView or not.
The mCurrentPage variable is incremented by 1 in the onLoadMore() method so that whenever we are loading a new set of books, we are retrieving the next page.
When we piece all of this together, you’ll see the beautiful pagination working whenever the user scrolls down.
A couple of notes on the mPaginate build method and its chained methods and parameters (the important parts).
In the Paginate.with(), you pass in the RecyclerView that you are paginating by
The setLoadingTriggerThreshold is the number of items that are left in the RecyclerView from the bottom of the list while the user is scrolling that should trigger the next API request. In my example, I have set this to 10. So, as the user scrolls, as soon as there are 10 items left in the RecyclerView, the next API request (if there are any more pages left) will be made.
And that’s it! This should allow you to build in smooth pagination features in your apps.