Lint > Correctness

This is my 1st post of Code Inspection series. In your Android Development career, you might have ignored many lint warnings. Being an ideal developer, we should not ignore the lint warnings unknowingly. If you have a known reason for it, then you may ignore some warnings. In this post, we will have a brief idea about lint warnings related to Correctness.

Below are the sub categories of Lint > Correctness warnings with examples.


Case 1: This should probably be a plural rather than a string

We might have faced many situation where you need to declare a dynamic string resource. For example: lets consider the below string, which contains a formatter %d for some integer value.

<string name="alert_message_winner">Congratulations!!! You won the game and earned %1$d Reward Points.</string>

Lets understand the above string with two different cases.

  1. When %d should be replaced with 1.
  2. When %d should be replaced with more than 1.

The 1st case will of course fail. Instead of showing the expected result 1 Reward Point, it will show 1 Reward Points (Which is grammatically wrong).


To avoid this kind of situation, Android has something called plurals for us. Let us try to understand more about plurals and how to use it with the above mentioned string resource.

<plurals name="alert_message_winner">
<item quantity="one">Congratulations!!! You won the game and earned %1$d Reward Point.</item>
<item quantity="other">Congratulations!!! You won the game and earned %1$d Reward Points.</item>
</plurals>

So we have declared two string resources, one for singular and another for plurals. But how to get the value in java? Lets see the below snippet.

int rewardPoints = getRewardPoints();
Resources res = getResources();
String message = res.getQuantityString(R.plurals.alert_message_winner, rewardPoints, rewardPoints);
// Use message to show in UI

We have below take aways from the above snippet:

  • R.plurals.alert_message_winner instead of R.string.alert_message_winner
  • res.getQuantityString() instead of res.getString()

Now lets consider, you have some similar kind of string resource but you don’t need to maintain multiple string resources for handling plurality. With below snippet, you can a bit more clarity:

<string name="alert_password_size">Password length should be more than %1$d characters.</string>

Your business requirement might tell that there is no possibility of having zero or one characters. But still, lint will throw a warning suggesting to use plurals. So to avoid that we can just suppress the lint warning using tools:ignore.

<string name="alert_password_size" tools:ignore="PluralsCandidate">Password length should be more than %1$d characters.</string>

Reference:

Case 2: Class is not registered in manifest

Let us consider an example:

public class MyActivity extends Activity { … }

Now, lets start this Activity:

Intent intent = new Intent(context, MyActivity.class);
startActivity(intent);

The above code will surely throw an exception:

android.content.ActivityNotFoundException:Unable to find explicit activity class

So, we have to register this Activity into AndroidManifest.xml

<activity android:name=".MyActivity />

The same rule applies to other two components (Services and Content Providers). So we can finally conclude that each Android components except BroadcastReceivers should be registered with Manifest file.


Now lets consider another case study where you want to create an Activity which is only meant for a parent class of all other real Activities.

public class BaseActivity extends Activity { ... }
public class MyActivity1 extends BaseActivity { ... }
public class MyActivity2 extends BaseActivity { ... }

In this case, even though BaseActivity is an Activity, it should not be registered with Manifest, since its not a real Activity. But still, the lint will give this warning. So to avoid this we should always make the BaseActivity as an abstract class.

public abstract class BaseActivity extends Activity { ... }

Conclusion

Out of four Android components, Activities, Services and Content Providers are the three which must be registered in AndroidManifest.xml file using <activity>, <service> and <provider> tags respectively.

If your activity is simply a parent class intended to be subclassed by real activities, make it an abstract class.

Case 3: Gradle Dynamic Version

Gradle build system gave us a flexibility of using Android libraries just by adding a single line of code in build.gradle file.

dependencies {
compile 'com.android.support:appcompat-v7:24.2.0'
}

It also gives us the flexibility of choosing the latest available library version instead of a specific version.

dependencies {
compile 'com.android.support:appcompat-v7:24.0.+'
}

Even though the later one gives us more flexibility, it is not recommended.

Why Not Recommended?

Lets say, we have developed and tested our app with a library version 1.0.0 and submitted to build server for releasing to Play Store. By the time, out build server builds our app, there may be a slightly higher version of dependent library is available (e.g. 1.0.1). Since we have not mentioned a specific version to be used, build server will choose the latest one, not the version which is used while testing. This might cause some functionality not work.

Conclusion

We should always use a specific version of any dependent library.