A Conservative Guide to ProGuard for Android

Android’s documentation for ProGuard describes it like so:-

“The ProGuard tool shrinks, optimizes, and obfuscates your code by removing unused code and renaming classes, fields, and methods with semantically obscure names. The result is a smaller sized. apk file that is more difficult to reverse engineer…. Having ProGuard run is completely optional, but highly recommended.”

But this documentation for ProGuard is minimal in its recommendations, and ProGuard advice on Stack Overflow is inconsistent. Some developers find that ProGuard can introduce bugs when delivering push notifications, making in-app purchases, and using third-party libraries. This post is a conservative guide to ProGuard that minimizes the chance of these bugs by stressing safety over aggressive optimizations. When developing Burner for Android, this approach still led to ProGuard reducing the size of its. apk file by almost 25%, from ~1.7 MB to ~1.3 MB.

Basic configuration

First, open your project’s project.properties file and find the line specifying proguard.config. Append to it a colon as a delimiter, followed by proguard-appname.txt, substituting your own application name for appname. In its entirety the line should look like:

proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-appname.txt

So for Burner, it looks like:

proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-burner.txt

If no such line for proguard.config exists in your project.properties file, add one.

If you navigate to the directory {sdk.dir}/tools/proguard/, you’ll find that in addition to proguard-android.txt there is another file named proguard-android-optimize.txt. By using the former, your code will be shrunk and obfuscated. By using the latter, your code will also be optimized. But as Donald Knuth famously said, premature optimization is the root of all evil. The preamble to proguard-android-optimize.txt warns us so:

“Adding optimization introduces certain risks, since for example not all optimizations performed by ProGuard works on all versions of Dalvik. The following flags turn off various optimizations known to have issues, but the list may not be complete or up to date.”

We’re erring on the side of safety and referring to proguard-android.txt instead of proguard-android-optimize.txt. If your application is running slowly, it may be best to explore other space-time tradeoffs in your code before switching to proguard-android-optimize.txt. If using proguard-android-optimize.txtintroduces a bug on an esoteric or new version of Dalvik, that bug may be impossible or costly to fix.

Next, create that file proguard-appname.txt in your project. It should be a sibling of the project.properties file. Again, for Burner, this filename is proguard-burner.txt.

From the collective wisdom of Stack Overflow, I always begin this file with the following entries:

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.billing.IInAppBillingService
-keep public class * extends android.view.View {
    public (android.content.Context);
    public (android.content.Context, android.util.AttributeSet);
    public (android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {
    public (android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
    public (android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.content.Context {
    public void *(android.view.View);
    public void *(android.view.MenuItem);
}

This excludes shrinking and obfuscating parts of classes that extend select classes from the Android API. The line including BroadcastReceiver is especially important if your application reacts to notifications, while the line including IInAppBillingService is especially important if your application offers in-app purchases. Again, some of these exclusionary rules could probably be removed, but we’re erring on the side of safety.

Third-party libraries

Many problems with ProGuard stem from the inclusion of third-party libraries in your project. For example, the following line of code from the greenDAO ORM throws a NoSuchFieldException because ProGuard obfuscates the field name TABLENAME:

this.tablename = (String) daoClass.getField("TABLENAME").get(null);

The first step in avoiding such errors is to consult the documentation of each third-party library and follow any instructions for deployment with ProGuard. For example, the Urban Airship documentation instructs adding the following lines to your configuration:

# Suppress warnings if you are NOT using IAP:
-dontwarn com.urbanairship.iap.**
# Required if you are using Autopilot
-keep public class * extends com.urbanairship.Autopilot

# Required if you ARE using IAP:
#-keep class com.android.vending.billing.**

# Required if you are using the airshipconfig.properties file
-keepclasseswithmembers public class * extends com.urbanairship.Options {
public *;
}

If the documentation mentions nothing about ProGuard, but the library is open source, then there is no point to obfuscating its code from a security standpoint anyway. Find the source code for the library, or temporarily rename the JAR file so that it has a .zip extension and extract its contents. Then find the ancestor packages for its code. For example, the ancestor package for all greenDAO ORM code is de.greenrobot.dao, which includes subpackages async, identityscope, internal, query, and test. With the following two lines in our ProGuard configuration, we exclude shrinking and obfuscating any code in package de.greenrobot.dao or a subpackage like de.greenrobot.dao.async:

-libraryjars libs

-keep class de.greenrobot.dao.** { *; }
-keep interface de.greenrobot.dao.** { *; }

In addition to the JAR file for greenDAO ORM, your libs folder may contain JAR files for third-party libraries like Joda Time and the Android Asynchronous Http Client. Your project may also depend on Android library projects like ActionBarSherlock and ViewPagerIndicator. Applying the approach above to each of these libraries, proguard-android.txt looks like:

-libraryjars libs

# The official support library.
-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }

# Library JARs.
-keep class de.greenrobot.dao.** { *; }
-keep interface de.greenrobot.dao.** { *; }
-keep class org.joda.** { *; }
-keep interface org.joda.** { *; }
-keep class com.loopj.android.http.** { *; }
-keep interface com.loopj.android.http.** { *; }

# Library projects.
-keep class com.actionbarsherlock.** { *; }
-keep interface com.actionbarsherlock.** { *; }
-keep class com.viewpagerindicator.** { *; }
-keep interface com.viewpagerindicator.** { *; }

This immediately follows the block of entries shown under Basic configuration. Change its content according to what libraries your project depends on.

Output

ProGuard runs when you build your application in release mode. After it has run, you should find a proguard directory in your project directory. The Android’s documentation for ProGuard contains complete information on the files it contains, but two are especially important:

  • seeds.txt contains classes and members excluded from obfuscation. Here you should find those belonging to the library packages that you explicitly excluded; if missing, then they were obfuscated and bugs may appear.
  • mapping.txt maps between the original and obfuscated class, method, and field names. If you are using a crash-reporting tool like Crittercism to automatically collect the stacktraces from crashes, then you will need this file to translate their obfuscated names back to their original names. Many crash-reporting tools will automatically perform this translation given this file; for example, see the Crittercism documentation. Because mapping.txt is so important to debugging, commit it to Git, add it to Dropbox, or copy it to a location that grants it longevity.

Further optimization:-

While this is a conservative guide to ProGuard, you can use it as a starting point for aggressive optimization with fewer exclusionary rules. Refer to its official documentation for more information.

How hating code made me a better designer.

Product Design through a technical looking glass

Four months ago, I left my cushy San Francisco gig at LinkedIn to learn to code.

As an aspiring designer, I didn’t have a clue about how web products were built. Coding was the next logical step to pursuing this goal.

I started my intensive coding bootcamp not knowing the difference between programming logic and markup, and I most certainly couldn’t tell you the difference between client side and server side code (or even what those terms meant).

Needless to say, the learning curve was painful.

Source: Akoallana

Now, as I interview for Product Design roles, I realize that learning to code was undoubtedly the right decision for me. As I tackle design challenges, I consistently recognize my “coding hat” in full motion as I dissect problems. Here are a few key lessons that have come out of my experience:

Keep things simple

Coding is about writing clean, legible and functional programs that can execute a series of micro-tasks. Overall, the problems you’re trying to solve are big.

In the past, upon starting a design project, I felt overwhelmed by the ambiguity of what I was designing. Coding taught me to break up every problem into small micro-bites that are executable as individual functions.

Now, as I approach a design problem, I start by looking at the collective whole with the confidence that the pieces can be chipped away, bit by bit.

Pro-tip: As you wireframe, think of each element as a component. I’ve started to design from the perspective of a developer by thinking about each component as the building blocks of my application.

Responsive website redesign concept for Kiva. My partner and I broke down the design through developers eye, as we were making design decisions.

Learning how to learn

In the past, when tasked with a problem I was unsure the answer, or asked to use a technology I had yet to touch, I would immediately go into panic mode.

Coding taught me that a human brain can’t possibly store all the information one needs to write in dozens of languages or on multiple operating systems. Programming teaches you the fundamentals of how to think. And for everything else, there’s Google.

Want to program in iOS? Learn PHP? Or design a chatbot? Chances are someone has written about their experience or published their solution to a component of code, or design element you can reference. Break down the pieces of what needs to be done and start your research from there.

Heightened empathy

If you aren’t coming from a computer science or technical field of study like engineering or mathematics, learning a baseline amount of code can bridge so many gaps. It can heighten your understanding of what’s important so you can think from the perspective of a developer as you design your product.

“The most important thing is for designers to develop empathy for how engineers work, and vice versa, so both sides can understand the other’s process and work together efficiently.” — Ryan Scott, Senior Designer, DoorDash

Designing for the technology you are using

Rarely will you wonder: is this possible? Learning the properties of various languages and web frameworks will help you understand the possibilities and limitations within your scope.

Even if you’re still unsure about whether an interaction is achievable, your coding sensibilities will help you figure it out. The first time I saw advanced CSS and JavaScript, a wave of inspiration hit me as I discovered an entire library of interactions at my disposal.

“Understanding engineering constraints allows me to look for effective design solutions.” — Elliot Dahl, Product Designer, Pivotal Labs

Pro-tip: Do your homework. Every language has official documentation. Between that, Stack Overflow, and Google searches, you should be able to find what’s in the realm of possibilities before you present your designs to the development team.

Better communication

Learning to code sequentially teaches you to think like an engineer. Thinking like an engineer builds bridges to form solid communication.

Coding gives you the ability to form a more holistic user experience and articulate your ideas in a way that a technically driven mind will respect.

Countless hackathons and teams later, I’ve learned that a creative is only as a good as their ability to get others to share their vision through the effective articulation of their ideas. Coding has helped me step into this space.

Coding can be infuriating. Until you get over the hump. Then it’s empowering.

I don’t hate coding anymore. I really enjoy it. But the scars from countless battles involving hair-pulling, head-banging frustration have marked me so profoundly that I will forever have the strongest empathy for developers working alongside me.

Through this experience I’ve learned that I don’t have to be a developer to think like one. If you can specialize in kick-ass designs, but have the communication skills to work with your technical partners, you can take your designs to the next level and become a great digital product designer.

Things I wish I knew when I started building Android Libraries

It all starts when some android developer tries to figure out a solution to a problem he/she is having while building their “Awesome Android App”. During the process, most developers would encounter a couple of issues and in tandem, to those, they would come up with possible solutions.

Now here is a thing, if you are like me, who believes that if the problem was big enough for me to spend some time on it and there wasn’t an existing solution out there, I would abstract the whole solution in a modular manner, which eventually turns out to be an android library. Just so that whenever in future I encounter this problem again, I can reuse this solution easily.

So far, so good. So you have built the library and probably started using it completely privately or if you think someone else could make use of the same solution you release the code as an android library i.e.you open source the code. I believe (..or rather that is what it looks like..) at this point everyone thinks they are done.

WRONG! This very point is where most people usually miss out that this android library code is going to be used by other developers that do not sit next to you and that to them this is just some android library they wish to use to solve a similar problem. The better your approach of designing the API the better the chances of making sure that the library will be used as it is intended to be and whoever is using it isn’t confused. It should be clear from the very start what needs to be done to start using the library.

Why does this happen?
The devs that write these android libraries are usually the ones who don’t care about the API design when building one. At least the majority of them don’t. Not because they are indifferent but I think most of them are just beginners and there is no set rules that they can look up to be better at designing the API. I was in the same boat sometime back, so I can understand the frustration of not having a lot of information in this field.

So I have had my experiences and I happen to release some of the code as android libraries (which you can check out here). I have come up with a quick list of points which each and every developer who designs an API in the form of Android Library should keep in mind (some of them may apply to designing API in general too).

Point to note here, my list isn’t exhaustive and I may not be covering everything. It covers things I have encountered and wished I knew it when I started and thus I will keep on updating this post as and when I learn with more experience in the future.

Before we dive into anything let’s first answer the most basic questions that everyone would have regarding building Android SDK/Library. So here goes

Why would you create an android SDK/Library?

Sure it is…

Well, you do not have to create an SDK/library in all cases. It makes more sense to decide on building one based on the understanding of what value you bring to the table. Ask yourself the below

Is there some existing solution that would solve the problem?
If your answer is Yes, then possible try and use that existing solution.
Say that does not solve your specific problem, even in that scenario it is better to start by forking the code, modifying it to solve the problem and then using it versus starting from scratch.

Bonus Points to you if you go ahead and submit a Pull Request to get the fix you made pushed into the existing library code so that the community can benefit from it.

If your answer is No, then go ahead and build the android sdk/library. Share it with the world later on so that others can make use of it in their projects.

What are the packaging options for your artifacts?

Even before you start building your library you need to decide on how do you want to deliver your artifacts to developers.
Let me start here by describing some terms which we might use in the post here. To begin with let me describe what is an artifact first,

In general software terms, an “artifact” is something produced by the software development process, whether it be software related documentation or an executable file.
In Maven terminology, the artifact is the resulting output of the maven build, generally a jar , war , aar or other executable files.

Let’s look at the options you have

  • Library Project: Code that you have to checkout and link into your project. It is the most flexible one as you can modify the code once you have it in your code, but also introduces issues such as being in sync with upstream changes.
  • JAR: Java ARchive is a package file format typically used to aggregate many Java class files and associated metadata into one file for distribution.
  • AAR: Android ARchive is similar to JAR with added functionality. Unlike JAR files, AAR files can contain Android resources and a manifest file, which allows you to bundle in shared resources like layouts and drawable in addition to Java classes and methods.

We have the artifact, Now what? Where does one host these artifacts?

Not really…

Turns out you have a couple of options here too, each having its own pros and cons. Let’s take a look at each

Local AAR

If you happen to be very specific about not wanting to put your android library artifact into any repository, you can generate your local aar file and use that directly. Read this stackoverflow answer to understand how to do that.

In a gist is you need to put the aar file in the libs directory (create it if needed), then, add the following code in your build.gradle :

dependencies {
   compile(name:'nameOfYourAARFileWithoutExtension', ext:'aar')
 }
repositories{
      flatDir{
              dirs 'libs'
       }
 }

..what comes with this is that now whenever you want to share your android library you are passing around your aar file(…which is not the best way to share your android library).

Avoid doing this as much as you can, since it is prone to a lot of problems the biggest one being manageability and maintainability of the code base.
Another issue with this approach is you cannot make sure that the users of this artifact are in sync with the latest code.
Not to mention the whole process is lengthy and prone to human error, just to integrate the library in an android project.

Local/Remote Maven Repositories

What if you wanted to use the android library privately?
The solution for that is to deploy your own instance of artifactory (read about how to do that here) or using Github or Bitbucket repository as your own maven repository (read about how to do that here).

Again this is specific to you using your android library privately. If you want to share this with others its not the approach you wanna stick to.

First issue that this approach has is that your artifact is in an private repository, to give access to this library you have to give access to the private repository which could be a security issue.
Second issue is that to use your android library one would need to include an extra line in their rootbuild.gradle file

allprojects {
	repositories {
		...
		maven { url 'http://url.to_your_hosted_artifactory_instance.maven_repository' }
	}
}

..which to be fair is an extra step and we are all here to make the process simpler. It is easier on the creator part to push the android library out quickly but adds an extra step for the users to use the library code.

Maven Central, Jcenter or JitPack

Now the easiest way to push it out immediately is via JitPack. So you would want to do that. JitPack takes your code from a public git repository, checks out the latest release code, builds it to generate the artifacts and later publishes to their self hosted maven repository.

However the issue at hand is same as the one for local/remote maven repositories that users of your android library would need to include an extra line in their rootbuild.gradle file

allprojects {
	repositories {
		...
		maven { url 'https://www.jitpack.io' }
	}
}

You can read about how to publish your android library to JitPack here.

The other option you have is of Maven Central or Jcenter.
Personally I would suggest you to stick to Jcenter as it well documented and better managed. It is also the default repository that is looked up for dependencies in Android projects (…unless someone changed it).
If you publish to Jcenter, bintray the company behind it gives you the option to sync with Maven Central from within their publishing platform. Once published its as simple as adding the below line to your build.gradle file to use the library in any android project

dependencies {
      compile 'com.github.nisrulz:awesomelib:1.0'
  }

You can read about how to publish your android library to Jcenter here.


With all those basic questions out of the way, let us look at things one should take care of while building an Android SDK/Library

Avoid multiple arguments

Every android library has to be usually initialized with some arguments and to do that you would usually be passing a set of arguments to either a constructor or have an init function to setup your library. Whenever doing that consider the below

Passing more than 2–3 arguments to your init() function is bound to cause more headaches than provide ease of use.
Just because its hard to remember the exact mapping of these arguments and the order in which they are declared in the library code.It also is prone to more mistakes as anyone can make a mistake of passing int value in a String field or vice versa.

// DONOT DO THIS
void init(String apikey, int refresh, long interval, String type);
// DO this
void init(ApiSecret apisecret);

where ApiSecret is an Entity Class, declared as below

public class ApiSecret{
    String apikey;
    int refresh;
    long interval;
    String type;
    // constructor
    /* you can define proper checks(such as type safety) and
     * conditions to validate data before it gets set
     */
   
    // setter and getters
}

Or you can also use Builder Pattern as an alternative approach to the above.
You can read more about Builder Pattern here. JOSE LUIS ORDIALES talks in depth about how to implement it in your code, take a look here.

Ease of use

When building your android library, keep in mind the usability of the library and the methods you expose. It should be

  • Intuitive
    For everything thats happening in the android library code , there should be some feedback either in the logs or in the view. Depends on what kind of an android library is being built. If it does something that cannot be comprehended easily, the android library basically “does not work” in the language of devs. It should do what the user of android library expects it to do without having to look up the documentation.
  • Consistent
    The code for the android library should be well thought and should not change drastically between versions. Follow semantic versioning.
  • Easy to use, Hard to misuse
    It should be easily understandable in terms of implementation and its usage in the first sight itself. The exposed public methods should have enough validation checks to make sure people cannot misuse its functionality other than what it was coded and intended for.Provide sane defaults and handle scenarios when dependencies are not present.

In short…

simple.

Minimize Permissions

In the current times, when everyone just wants to jump the road and ask as many permissions, you should pause and think about do you really need that extra permission. Take care of these points especially

  • Minimize your permissions as much as you can.
  • Use Intents to let dedicated apps do the work for you and return the processed result.
  • Enable and disable your features based off if you have the permission for it. Do not let your code crash just because you do not have the said permission. If at all , you must educate the user well before requesting the permission and that why its required. If possible have a fallback functionality if the permission isn’t approved.
    This is how you check if you have a said permission granted or not:
public boolean hasPermission(Context context, String permission) {
  int result = context.checkCallingOrSelfPermission(permission);
  return result == PackageManager.PERMISSION_GRANTED;
}

Some of the devs would say that they really need that specific permission, what to do in that case. Well, your library code should be generic for all types of apps that need the specific functionality. If you can provide hooks such as functions to let users of your android library pass the data you need the dangerous permission for. In that way, you do not force the devs to require a permission they do not want to. In absence of the permission provide a fallback implementation. Simple.

/* Requiring GET_ACCOUNTS permission (as a requisite to use the 
 * library) is avoided here by providing a function which lets the 
 * devs to get it on their own and feed it to a function in the 
 * library.
 */
MyAwesomeLibrary.getEmail("username@emailprovider.com");

Minimize Requisites

We have all been there. We have a specific functionality that requires that the device has a certain feature. The usual way you would approach this is by defining the below in your manifest file

<uses-feature android:name="android.hardware.bluetooth" />

..the problem with this is that when this is defined in the android library code, this would get merged into the app manifest file during the manifest-merger phase of build and thus hide the app in Play Store for devices that do not have the bluetooth unit (this is something the Play Store does as filtering). So basically an app that was earlier visible to a larger audience would now be visible to a smaller audience, just cause you added that to your library code.

Well, that’s not we want, do we? Nope. So how do we solve this.
Well what you need to do is not include that uses-feature in your manifest file for the android library but rather check for the feature during runtime in your code as below

String feature = PackageManager.FEATURE_BLUETOOTH;
public boolean isFeatureAvailable(Context context, String feature) {
 return context.getPackageManager().hasSystemFeature(feature);
}

.. this way there is no entry in the manifest and once it merges into the app, it won’t let the app get filtered in the Play Store.
As an added feature though if the feature is not available you can just disable the functionality in your library code and have some fallback functionality in place. It is a Win- Win for both the android dev who built the library and the dev who integrates the lib in their app.

Support different versions

How many are out there exact
ly?

If you have

a feature that’s available in a certain version of android, you should do the check for that in code and disable the feature if the version is lower than supported.

As a rule of thumb support the full spectrum of versions via defining in minSdkVersion and targetSdkVersion. What you should do internally to your library code is check for the android version at runtime and enable/disable the feature or use a fallback.

// Method to check if the Android Version on device is greater than or equal to Marshmallow.
public boolean isMarshmallow(){
    return Build.VERSION.SDK_INT>= Build.VERSION_CODES.M;
}

Do not log in production

Just DO NOT.

Almost every time I am asked to test an app or an android library project the first thing that I have seen is that they log everything up in the open, in their release code.

As a rule of thumb, never log in production. You should use build-variantswith timber to help you in the process to separate logging info in production vs debug builds. A simple solution can be to provide a debuggable flag that the devs can flip to enable/disable logging from your android library

// In code     
boolean debuggable = false;
MyAwesomeLibrary.init(apisecret,debuggable);
// In build.gradle  
   debuggable = true

Do not crash silently and fail fast

I have seen this a lot of times now. Some of the devs would not log their errors and exception in logcat! Which basically adds a headache to the users of the android library when they are trying to debug the code. In tandem to the last tip about not logging in production, you must understand that exceptions and errors need to be logged irrespective of being in debug or production. If you do not want to log in production, at least provide a functionality of enabling logs via passing some flag when you initialize your library

. i.e

void
 init(ApiSecret apisecret,boolean debugga
ble){      ...
      try{
        ...
      }catch(Exception ex){
        if(debuggable){
          // This is printed only when debuggable is true
          ex.printStackTrace();
        }
    
  }      ....
}

It is important that your android library fails immediately and shows an exception to the user of your android library instead of being hung up on doing something. Avoid writing code which would block the Main Thread.

Degrade gracefully in an event of error

What I mean by this is that when say your android library code fails, try to have a check so that the code would not crash the app instead only the functionality provided by your library code is disabled.

Catch specific exceptions

Continuing with the last tip, you might notice that in my last code snippet I am using a try-catch statement. Catch statement specificallyEx catches all ception as its a base class. There is no specific distinction between one exception vs the other one. So what one must do is define specific types of Exception as per the requirement at hand. i.e NUllPointerException, SocketTimeoutException, IOException, etc.

Handle poor network conditions

…this gets on my nerves, seriously!

If the android library you wrote deals with making network calls, a very simple thing that usually goes unnoticed is that you should always consider a case of what happens if the network is slow or non-responsive.

What I have observed is that library code developers assume that the network calls being made will always go through. A good example will be if your android library fetches some config file from the server to initialize itself. Now when developing the library the devs assume that the config file will always get downloaded. What they forget is that on a flaky network, the library code will not be able to download the config file and hence would crash the whole codebase. If simple checks and a strategy to handle such situations are built right into the android library code, it saves quite a number of people the headaches they would have otherwise.

Whenever possible batch your network calls and avoid multiple calls. This also saves a lot of battery, read here

Reduce the amount of data you transfer over the network by moving away from JSON and XML to Flatbuffers.

Read more about managing network here

Reluctance to include large libraries as dependencies

This one goes without much explanation. As most of fellow Android Devs would be knowing, there is a method count limit of 65K methods for android app code. Now say if you have a transitive dependency on a large library, you would introduce two undesirable effects to the android app your library is being included

  1. You will considerably increase the method count of the android app, even though your own library codebase has a low method count footprint since you would transitively download the larger library and thus it will contribute to the method count too.
  2. If the method count hits the 65K limit, just because of your library code that transitively downloaded the larger library, the app developer will be forced to get into the lands of multi-dexing. Trust me on this, no one wants to get into the multi-dexing world.
    In such a scenario, your library has introduced a bigger problem than solving the initial problem. So most probably your library will be replaced by some other library that does not add to the method count or basically that takes care everything in a better way.

Do not require dependencies unless you very much have to

Now this rule is something that I think everyone knows, right? Do not bloat your android libraries with dependencies you do not need. But the point to note here is that even if you need dependencies you do not have to make the users of the library download it transitively. i.e the dependency does not not need to be bundled with your android library.

Well, then the question arises as to how do we use it if it is not bundled with our library?

Well the simple answer is you ask your users to provide that dependency to you during compile time. What this means is that not every user might need the functionality which requires the dependency. And for those users, if you cannot find the dependency as provided to you, you just disable the functionality in your code. But for those who need it, they will provide you the dependency, by including it in their build.gradle .

How to achieve this ? Check in classpath

private boolean hasOKHttpOnClasspath() {
   try {
       Class.forName("com.squareup.okhttp3.OkHttpClient");
       return true;
   } catch (ClassNotFoundException ex) {
       ex.printStackTrace();
   }
   return false;
}

Next, you can use provided(Gradle v2.12 and below) or compileOnly(Gradle v2.12+)(Read here for complete information), so as to be able to get hold of the classes defined by the dependency during compile time.

dependencies {
   // for gradle version 2.12 and below
   provided 'com.squareup.okhttp3:okhttp:3.6.0'
   // or for gradle version 2.12+
   compileOnly 'com.squareup.okhttp3:okhttp:3.6.0'
}

A word of caution here, you can only use this functionality of requiring a dependency if its a complete java dependency. i.e if its an android library you want to include at compile time, you can not reference its transitive libs as well as resources which need to be present before compilation. A pure java dependency, on the other hand, has only java classes and they are the only ones that would be added to classpath during the compilation process.

Try not to hog the startup

no k
idding…

What

I mean by this is that, as soon as the app starts up try not to initialize your android library greedily. What that would tend to do is that it will increase the startup time for the App itself, even though the app does simply nothing at startup except off course initialize your android library.

The solution to such a problem is to do all work of initializing off the main thread i.e in a new thread, async. Better if you use Executors.newSingleThreadExecutor() and keep the number of thread to just one.

Another solution would be to initialize components of your android library on demand i.e Load them up/initialize them only when they are needed.

Remove functionality and features gracefully

Do not remove your public functions between versions as that would lead the builds of many users of your android library break and they would be clueless as to why did that even happen.

Solution: Deprecate the functions by marking them @Deprecated and then define a roadmap of their removal in future versions.

Make your code Testable

Making sure you have tests in your code isn’t actually a rule to follow. You should be doing this everywhere and for every project app or library without saying.

Test your library code by making use of Mocks, avoiding final classes, not having static methods, etc.

Writing code with interfaces around your public API also makes your android library capable of swapping implementations easily and in turn makes the code more testable.i.e you can provide mock implementations easily when testing.

Document Everything!

Being the creator of the android library you would know about your code, but the people who are going to use it won’t know about it unless you expect them to figure out by reading your source code (you should never need that).

Document your library well including every detail about how to use it and detailing every feature you have implemented.

  1. Create a Readme.md file and place it at the root of your repository.
  2. Have javadoc comments in your code, covering all public functions. They should cover and explain
    – Purpose of the public method
    – The arguments passed
    – Return type
  3. Bundle a sample app which demonstrates a working example of how the library and its features are used.
  4. Make sure you keep a detailed change log for your changes. A good place to do that would be to add the information right in your release section for the specific version tag.
Screenshot of Github Releases section for Sensey android library

…and here is the link to releases section for Sensey

Provide a most minimalistic Sample App

This goes without saying. Always provide the most minimalistic Sample app with your library code, as that is the first thing other devs will checkout to understand a working example of using your android library. The simpler it is the easier it is to understand. Making the sample app look fancy and code complex would only undermine the actual goal of the sample app, that is to provide a working example of using your android library.

Consider putting up a License

Most of the time developers forget about the Licensing piece. This is one factor that decides the adoption of your android library.
Say you decided to license your android library in a restrictive manner i.e Using GPL license, would mean that whoever uses your library and makes modification will have to contribute back to your codebase in order to keep using the android library. Putting such restrictions hampers the adoption of android libraries and developers tend to avoid such codebases.

The solution to this is that you stick to more open licenses such as MIT or Apache 2.
Read about licensing at this simple site and about need of copyright in your code here

Last but not the least, get feedback

Yeah, you heard that right!

Your android library was built to cater to your needs initially. Once you put it out for others to use, you will come to know a lot of issues in it. Hear out your fellow devs and gather feedback. Act on it considering and weighing on the functionality to introduce or fix while maintaining the goals of the android library intact.

Summary

In short, you need to take care of the below points while building

  • Avoid multiple arguments
  • Ease of use
  • Minimize permissions
  • Minimize requisites
  • Support different versions
  • Do not log in production
  • Do not crash silently and fail fast
  • Degrade gracefully in an event of error
  • Catch specific exceptions
  • Handle poor network conditions
  • Reluctance to include large libraries as dependencies
  • Do not require dependencies unless you very much have to
  • Try not to hog the startup
  • Remove features and functionalities gracefully
  • Make your code testable
  • Document everything
  • Provide a most minimalistic sample app
  • Consider putting up a license
  • Get feedback, lots of them

As a rule of thumb follow the rule of SPOIL-ing your Library

Simple — Briefly and Clearly expressed

Purposeful — Having or showing resolve

OpenSource — Universal Access, Free license

Idiomatic — Natural to the native environment

Logical — Clear, Sound Reasoning

I read this sometime back in a presentation by some author I cannot recall. I took note of it as it makes a lot of sense and provides a clear picture in a very concise manner. If you know who the author is, please comment it and I will add his link and give due credit.

Ending Thoughts

I hope this post helps fellow android devs in building better android libraries. Android Community benefits extensively from using android libraries published daily by fellow android devs and if everyone starts to take care of their API design process keeping in mind the end user (other android developers) we would all be a step closer to an even better ecosystem as a whole.

These guidelines are compiled on my experience of developing android libraries. I would love to know your views on the pointers mentioned above. Please leave a comment, and let me know!

If you have suggestions or maybe would like me to add something to the content here, please let me know.

Till then keep crushing code 🤓

Dagger 2 and MVP Architecture

Aditya Ladwa

What we will be Learning?

  • Use dagger2 with RetrofitOkHttpGson andRxJavaandRxAndroid
  • Use Model View Presenter(MVP) Architecture to decouple the Business logic and the underlying implementation of the logic to produce more cleaner code
  • Use RxJava to make request to our REST API
  • Use Retrofit to make call to a API and display the result
  • Learn about dependent components in dagger and creating custom scope for dependent components
  • We will be using Android studio and the code will be hosted on github

Lets get started

Step 1: Create a project with a Blank Activity

Step 2: Add the necessary dependency

Android Studio by default will not recognize a lot of generated Dagger 2 code as legitimate classes, but adding the android-apt plugin will add these files into the IDE class path and enable you to have more visibility. Add this line to your root

View original post 1,997 more words

Android Tips & Tricks

Android Tips & Tricks

This is a simple set of tips and tricks regarding Android Development which I have gathered from various sources. It helps me direct other android devs in my community regarding stuff each android dev should know about. Its also there for me to keep track of anything I either learn on my own or from other sources now and then when browsing the internet.

Contributions are always welcome, hoping people will help me in growing this. To contribute, simply open up a PR with the changes.

Know Your Tools

Android Studio

  • Code faster by using keyboard shortcuts
    Description Mac Linux/Win
    Lookup IDE commands Cmd+Shift+A Ctrl+Shift+A
    Open Class Cmd+O Ctrl+O
    Open File Cmd+Shift+O Ctrl+Shift+N
    Open recently edited file Cmd+Shift+E Ctrl+Shift+E
    Lookup Actions Cmd+Shift+A Ctrl+Shift+A
    Open Symbol Cmd+Opt+O Alt+Shift+N
    Open recently used file Cmd+E Ctrl+E
    Last Edited Location Cmd+Shift+Backspace Ctrl+Shift+Backspace
    Find Usage in persistent window Opt+F7 Alt+F7
    Find Usage in floating window Cmd+Opt+F7 Ctrl+Alt+F7
    Format the code with proper Indentation Cmd+Opt+L Ctrl+Alt+L
    Surround With Opt+Cmd+T Alt+Ctrl+T
    Open Terminal Opt+F12 Alt+F12
    Generate Setter/Getters Cmd+N Alt+Ins
    Find Class CMD+O Ctrl+N
    Refactor/Rename Shift+F6 Shift+F6
    Quick Fix Opt+Enter Alt+Enter
    Goto Definition Cmd+B Ctrl+B
    Show parameters for selected method Cmd+P Ctrl+P
    Refactor This Ctrl+T Ctrl+Alt+Shift+T
    Stop Process Cmd+F2 Ctrl+F2
    Search Everywhere Shift+Shift Shift+Shift
    Select Methods to Override Ctrl+O Ctrl+O
    Delete Line Cmd+Backspace Ctrl+Y
    Duplicate Line Cmd+D Ctrl+D
    Grow/Shrink selection from cursor Opt+Up/Down Arrow key Shift+Ctrl+W
    Multicursor Selection Ctrl+G Alt+J

    Complete Keymap Guide : MacOSX | Linux/Win

  • Use plugins to become more efficient
    1. KeyPromoter

      The plugin basically will annoy the hell out of you by showing you a big screen overlay with the key combination you should have used , if you used your mouse to execute some command to a level when you basically would start using the key combination just to avoid KeyPromoter annoying you all the time. Its also is useful features, like it will prompt you to create a key binding for a command which does not have a key binding and you have used it 3 times.

    2. String Manipulation

      Provides actions for text manipulation such as Toggle case, encode/decode, sorting,

    3. Lines Sorter

      Add Sort Lines action in Edit menu to sort selected lines or whole file if selection is empty.

    4. Findbugs

      Provides static byte code analysis to look for bugs in Java code from within Android Studio

    5. Sonar Lint

      Plugin that provides on-the-fly feedback to developers on new bugs and quality issues injected into Java, JavaScript and PHP code.

    6. Checkstyles

      Plugin provides both real-time and on-demand scanning of Java files from within Android Studio.

    7. ADB Idea

      Plugin that adds ADB commands to Android Studio and Intellij such as ADB Uninstall App, ADB Kill App, ADB Restart App, etc

    8. Exynap

      Plugin which helps you find and implement the code you require in an instant.

    9. Dagger IntelliJ Plugin

      The Dagger IntelliJ plugin creates visual connections between a @Inject object and the @Provides method that creates it.

    10. JVM Debugger Memory View

      This plugin extends the built-in JVM debugger with capabilities to explore objects in the JVM heap during a debug session.

  • Use Live Templates in Android Studio
    • newInstance – Generates the static newInstance function inside a Fragment
    • Toast – Generates Toast.makeText(context, "", Toast.LENGTH_SHORT).show();
    • fbc – findViewById with cast
    • const – Define a android style int constant
    • logd – Generates Log.d(TAG, "");
    • logm – Log current method name and its arguments.
    • logr – Log result of the current method
    • logt – static logtaf with current classname
    • psf – public static final
    • sout – Prints a string to System.out
    • soutm – Prints current class and method names to System.out
    • soutp – Prints method parameter names and values to System.out
    • visible – Set view visibility to VISIBLE
    • gone – Set view visibility to GONE
    • noInstance – private empty constructor to prohibit instance creation

    Comprehensive list of all Live Templates in Android Studio

  • Postfix code completion in Android Studio

    Android Studio/IntelliJ havea special kind of code completion which allows you to write code specific to a field

    • <expr>.null will auto complete to if(<expr> == null)
    • <expr>.nootnull will auto complete to if(<expr> != null)
    • <expr>.var will auto complete to T name = <expr>
    • <expr>.field will auto complete to create a global field variable field = <expr>
    • <ArrayExpr>.for will auto complete to for(T item : <Arrayexpr>)
    • <ArrayExpr>.fori will auto complete to for(int i = 0; i < <Arrayexpr>.length; i++)
    • <ArrayExpr>.forr will auto complete to for(int i = <Arrayexpr>.length - 1; i > 0 ; i--)

    Complete list of available postfix code completion can be found at Settings → Editor → Postfix Templates

  • Use the Darcula Theme in Android Studio

    Ok, I know its more like a preference , but trust me using that keeps your eyes less strained as they would be if you used the Default Light theme.

  • Don’t use a small font

    Preferably use a font in Android Studio thats easy to read and is at a font size which doesnot forces you to strain your eyes. I use Menlo font.

  • Use a code style

    You should use a standard codestyle, so possible contenders can be

  • Use the Embedded Terminal inside Android Studio
  • Use the Memory/Network/CPU Monitor inside Android Studio to profile your code/app
  • Configure Android Studio

Emulator

Apart from using physical devices , one should use emulators as they are as of now easy to manage and equivalently powerful.

Vysor

This one needs special mention due to how useful it is. It basically is a window to your device i.e it streams and allows you to interact with your physical device on your laptop. Very useful when you are demo-ing your app during a presentation. You can interact with your physical device and it will be shown right in your laptop screen. It has a paid/free version , paid version is totally worth buying.

DeskDock

Yes, vysor was great, but if you want to share your keyboard and mouse directly to your Android device, then this app is for you. It enables you to control your Android device as if it was part of your desktop computer. The FREE version includes use of computer mouse, while the PRO version includes features such as use of keyboard. This is useful where you can test your app without your hands ever leaving your keyboard.

Make better choices while coding

  • Use OkHttp over HttpUrlConnect

    HttpUrlConnect suffers from quite some bugs. Okhttp solves them in a more elegant manner. [Reference Link]

  • Reference local aar files as below [Stackoverflow Ref]
      dependencies {
         compile(name:'nameOfYourAARFileWithoutExtension', ext:'aar')
       }
      repositories{
            flatDir{
                    dirs 'libs'
             }
       }
    
  • Use Pidcat for a better log reading experience
  • Use some Version Control System(VCS) like Git
  • Use ClassyShark

    Its a standalone tool for Android Devs used to browse any Android executable and show important info such as class interfaces and members, dex counts and dependencies

  • Use Stetho

    Debug your android apps using Chrome Dev Tools. Includes tools like Network Monitor, Shared Preference explorer etc.

  • Use Battery Historian

    A tool to analyze battery consumers using Android “bugreport” files.

  • Always use a constant version value like “24.2.0”

    Avoid using + when specifying the version of dependencies.

    • Keeps one secured from unexpected API changes in the dependency.
    • Avoids doing an extra network call for the checking latest version of each dependency on every build.
  • Use Handler instead of a TimerTask
  • Do not use your own personal email for Google Play Developer Account
  • Use Vectors instead of PNG

    If you do have to use png, compress them. Take a look at TinyPNG.

  • Use proguard
    android {
      ...
      buildTypes {
          release {
              minifyEnabled true
              proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
          }
      }
    }
  • Use shrinkResources
    android {
      ...
      buildTypes {
          release {
              shrinkResources true
              minifyEnabled true
              ...
          }
      }
    }
  • Simulating Android killing your app in the background, run in terminal adb shell am kill
  • Follow the below rule to have faster gradle builds
    Gradle memory >= Dex memory + 1Gb
  • Split your apk using gradle when using Native code, do not bundle all of em together and ship!.. coz that will make you evil
    defaultConfig {
        ...
    
        ndk {
          abiFilters "armeabi", "armeabi-v7a", "mips", "x86"
        }
      }
    
    //Split into platform dependent APK
      splits {
        abi {
          enable true
          reset()
          include 'armeabi', 'armeabi-v7a', 'mips', 'x86' //select ABIs to build APKs for
          universalApk false //generate an additional APK that contains all the ABIs
        }
      }
    
      // map for the version code
      project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'mips': 5, 'x86': 8]
    
      // Rename with proper versioning
      android.applicationVariants.all { variant ->
        // assign different version code for each output
        variant.outputs.each { output ->
          output.versionCodeOverride =
              project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) *
                  1000000 +
                  android.defaultConfig.versionCode
        }
      }
  • Learn about some architecture such as MVP or Clean
  • Try to understand and follow TDD (Test Driven Development)
  • To force re-download of dependencies
    ./gradlew --refresh-dependencies
  • To exclude a certain task from being run by gradle

    Suppose you want to exclude the task javaDoc then use -x option followed by the task name, i.e javaDoc in this case.

    ./gradlew clean build -x javaDoc
  • To have the each subproject script name match that of the project name

    Then add this line in settings.gradle

    rootProject.children.each{
      it.buildFileName = it.name + '.gradle'
    }

    Checkout more gradle tips here

  • Follow the DRY principle DRY = Do not Repeat Yourself
  • Package by Feature, not layers
  • Learn about Dependency Resolution

    With the speed android dependencies update, sooner or later you are going to encounter some sort of dependency conflict. Solution is making use of Dependency Resoultion. Official Reference

  • Use different package name for non-release builds
      android {
          buildTypes {
              debug {
                  applicationIdSuffix '.debug'
                  versionNameSuffix '-DEBUG'
              }
    
              release {
                  // ...
              }
          }
      }
  • Find and STOP leaking memory in your android app
  • If you’re creating a gradient in xml with a part being completely transparent, be really careful when using @android:color/transparent
  • Follow a standard naming convention for your resources
  • Make use of custom gradle tasks in your build.gradle files

    Android uses Gradle as its build system, which actually allows one to make a lot of things easy by creating tasks to automate things. This reddit post enlists a lot of such useful gradle scripts

  • Use a proper .gitignore in your Android Projects, Check it here
  • Use LeakCanary to detect memory leaks in your app – Its a memory leak detection library for Android and Java.
  • Speed up your gradle builds in Android Studio 2.3+
    • Switch to gradle 3.3

      Run this inside your project folder to update your gradle wrapper

      ./gradlew wrapper --gradle-version 3.3 --distribution-type all
    • Set the below property in your global gradle.properties file
      android.enableBuildCache=true
      
  • Stop a running gradle build process
    ./gradlew -stop
  • Enable gradle to automatically download missing platforms in android sdk

    Set the below property in your global gradle.properties file

      android.builder.sdkDownload=true
    

    This is an experimental option and it only downloads build tools and platforms, but doesn’t actually update Google or Support repository [Bug Ref]

  • Donot include both jcenter() & mavenCentral() in your build.gradle file

    JCenter is a superset of MavenCentral. [Ref tweet]

  • Clear your gradle cache if you think that bundled support and google play services lib in android sdk are inconsistent
    • Goto ~/.gradle/caches/ and delete everything inside the cache folder.
    • Open SDK Manager and resync all support libs and google play services
    • Next re-sync your project
    • Everything should become consistent and functional.
  • Setup handy adb aliases for your terminal [Ref Link]

    Append the below Aliases to your ~/.bashrc or ~/.zshrc file, save and restart the terminal. Once saved , use them as show in Usage column

    Alias Usage
    alias screenshot="adb exec-out screencap -p > screen-$(date -j "+%s").png" screenshot
    alias startintent="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X shell am start $1" startintent https://twitter.com/nisrulz
    alias apkinstall="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X install -r $1" apkinstall ~/Desktop/DemoApp.apk
    alias rmapp="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X uninstall $1" rmapp com.example.demoapp
    alias clearapp="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X shell pm clear $1" clearapp com.example.demoapp
  • Setup Android Studio to fail build if code contains //STOPSHIP [Ref Link]

    To enable the //STOPSHIP lint check, in your build.gradle

    android {
    ...
        lintOptions {
            abortOnError true
            fatal 'StopShip'
        }
    }

    If you have a //STOPSHIP comment in your code, this will cause an error to be thrown when a release apk is generated.

    You can turn on //STOPSHIP highlighting in Android Studio (isn’t enabled by default) in

    Preferences > Editor > Code Style > Inspections.

    Search for STOPSHIP to find the correct setting.

  • Use adb install -g to grant all permissions listed in the manifest [More Info]
  • Use alfi to find the gradle dependency statement for a library

    Its basically the commandline version of Gradle, Please which is a web hosted.

    • Run
      alfi name_of_library
    • Copy the desired library
    • Paste in your build.gradle
  • Use dryrun to test a library directly
    • Just Run
      dryrun REMOTE_GIT_URL
  • Output unit tests directly to the console [Ref Link]

    A small neat trick to see Android unit tests logging results as they happen in the terminal.

    android {
        ...
        testOptions.unitTests.all {
          testLogging {
            events 'passed', 'skipped', 'failed', 'standardOut', 'standardError'
            outputs.upToDateWhen { false }
            showStandardStreams = true
          }
        }
      }
  • Make your builds faster by building offline [Ref Link]

    The --offline flag tells gradle to always use dependency modules from the cache, regardless if they are due to be checked again. When running offline, gradle will never attempt to access the network to perform dependency resolution. If required modules are not present in the dependency cache, build execution will fail.

    • Assembling develop debug at full speed:
      ./gradlew assembleDevelopDebug --offline
    • Running your unit tests at full speed:
      ./gradlew test --offline
  • Use an abtracted Logger class
  • If you want to automatically initialize your library, use a Content Provider [Read how Firebase does it – Ref Link]
  • Reduce installed app size with "android:extractNativeLibs:false" in <application> [Ref Link]

    This will essentially prevent the system from creating a second copy of the .so files and fix the System.loadLibrary call so it’s able to find and open native libs straight from the APK, no code changes on your part required.

  • Selectivily execute a specific method in Android Studio [Ref Link]

    Image

  • Did you get one of these Google Play Developer Policy Violation Emails? Worry not, generate a Privacy Policy for your android app [Ref ink]

Tips regarding UI/UX

  • Motion
    • Material Design uses real-world metaphors as its foundation. Objects in the real world don’t move linearly, they move in curved paths and accelerate and decelerate according to the motion’s properties.
    • As such, motion should also use such properties and animate objects so that the motion feels natural rather than forced
    • For example, a car leaving the screen in a movie starts off slowly, then accelerates till it’s out of the frame. Similarly, views should be interpolated using classes like AccelerateInterpolator, FastOutSlowInInterpolator, etc. [[More Info]](https://developer.android.com/reference/android/animation/TimeInterpolator.html
  • Typography
    • While custom typefaces can be used for branding, it is essential to stick to Roboto and Noto if possible, especially for body text, due to their clarity and optimistic nature.
    • Roboto covers Latin, Greek and Cyrillic extended scripts, with Noto filling in for other language scripts [More Info]
    • Weight balancing is an important aspect of typography, the fundamental concept of which is that the larger a typeface is, the less its weight should be so that it doesn’t appear too thick and balances its weight with smaller typefaces of higher weights
    • Typography should align to a 4dp baseline grid, and maintain a minimum contrast ratio of 4.5:1 based on luminance values, with a recomemended ratio being 7:1.
    • The ideal reading length for large blocks of text is 40 to 60 characters per line. Anything less is too narrow and anything more is too wide.
  • Icons
    • Icons should be designed at 48dp, with 1dp edges, which equates to
      • 48px by 48px at mdpi
      • 72px by 72px at hdpi
      • 96px by 96px at xhdpi
      • 144px by 144px at xxhdpi
      • 192px by 192px at xxxhdpi
    • An additional icon of 512px by 512px should be designed for use on Google Play
    • Material icons, in addition to the base icon, should contain the following important elements
      • 1dp tinted edge at the top
      • 1dp shaded edge at the bottom
      • Contact shadow – a soft shadow around all edges of raised elements
      • Finish – a soft tint to provide surface lighting, fading from upper life to lower right [More Info]
  • Ripples
    • When implementing Ripple Effect use ?attr/selectableItemBackground instead of ?android:attr (Ref)
    • When implementing Ripples contained within the view like Button, use (Ref)
      android:background="?attr/selectableItemBackground"
    • When implementing Ripples that extend beyond the view’s bounds like ImageView: (Ref)
      ?attr/selectableItemBackgroundBorderless
  • Other Points to Note
    • Views should be aligned to Material Design’s 8dp baseline grid and the keylines when possible. This gives the UI a sense of structure and hierarchy. [More Info]
    • If you plan on keeping a reference to any ViewGroup (LinearLayout, FrameLayout, RelativeLayout, etc.), and you don’t want to use any methods specific to this particular type of Layout, keep it as a ViewGroup object. [More Info]
    • While picking an accent color (if the brand already has one), pick a color complementary to the primary color so that the contrast is high enough

Tips if you use Kotlin

  • Checkout From Java to Kotlin

    Cheatsheet when you come from Java to Kotlin. Very nice resource to compare the two languages.

Other Resources

Extra : Android Libraries built by me

  • EasyDeviceInfo – Enabling device information to be at android developers hand like a piece of cake!
  • Sensey – Android library to make detecting gestures easy
  • PackageHunter – Android library to hunt down package information
  • Zentone – Easily generate audio tone in android
  • RecyclerViewHelper – RecyclerViewHelper provides the most common functions around recycler view like Swipe to dismiss, Drag and Drop, Divider in the ui, events for when item selected and when not selected, on-click listener for items.
  • StackedHorizontalProgressbar – Android Library to implement stacked horizontal progressbar
  • QREader – A library that uses google’s mobile vision api and simplify the QR code reading process
  • ScreenShott – Simple library to take a screenshot of the device screen , programmatically!
  • EvTrack – Android library to make event and exception tracking easy
  • OptimusHTTP – Android library that simplifys networking in android via an async http client
  • ShoutOut – Android library for logging information in android

Credits

This curated cheatsheet includes tips and tricks that I have been following in my workflow as well as those being suggested/followed by other android devs worldwide.I have tried to add direct links wherever I could remember, giving people due credit who have explained the concepts. If you think I have missed any , then either send a PR or open an issue and I will fix it asap.

If you found this cheatsheet helpful or you learned something today and want to thank me, consider buying me a cup of :coffee: