Configuration file to scale iOS mobile apps

 Posted on Jun 16, 2014 by de_poon

In our team of mobile rockstar engineers, we often ask ourselves this question: How can we scale our ios mobile apps?

Lets take a hypothetical situation. Your CEO is very pleased with the first delivery of the company’s mobile app. The other country managers come along and want you to build the same app but adjusted for their individual countries. Assuming they want a separate downloadable app, the general requirements are

  1. I want some features taken from the main app
  2. I do not want some features from the main app
  3. I want some features to be modified from my custom app.

Sounds familiar?

The way to go about is to create a non-binary configuration file that allows us to specifcy what we want in the app.

The most important principle is that no recompilation is needed when we scale our apps. In our team we’ve chosen to go with PList file as it is easy for developers to create one out of the box in XCode. Here’s the steps

  1. Create a PList from XCode

  2. Set up your features in a .plist

  3. Add the plist file into your main bundle.

  4. Use the following codes to read the contents of the plist as a NSDictionary

  5. In your app features, read the contents off the NSDictionary to determine how your feature should behave. Eg.

    • Should this feature be turned on?
    • How should I order by menu items on the side menu?
    • Should I enable specific UI Animations at a particular screen?

To create additional scalable apps, simply create a new project

Considerations

  1. Adding your plist directly into your main app bundle is not a secure way to do (So you think you can start working on it? Gotcha…). It is possible for someone to extract the plist from your app and this exposes all sensitive information such as api end points, security tokens, etc. Dont worry, an upcoming post will address this issue.

  2. You might want to create your own configurations file manager to generate your plist on the fly.

  3. PList is probably not the best way to encapsulate application configuration. You may want to explore other formats.

Feel free to buzz us your thoughts on this

Using context in Android testing
Creating an interface for Android's Context to break direct dependency for unit testing

 Posted on Jun 02, 2014 by Ha Duy Trung

If you are keen on doing TDD with Android, you may have stumbled upon the dreaded java.lang.RuntimeException: Stub! when you try to test drive your code with different contexts as input. For us, most of the time we use context is to get some resources out of it, either string, bool, raw, you name it. These resources may change execution behavior, and thus we are required to test with different resources to cover all cases.

Soon you learn that it is not straightforward to get the default Android’s Context out of the way, even with MockContext. That is one of the reasons why we see test frameworks such as Robolectric (or mock framework such as Mockito, PowerMock) getting popular. While it is convenient to let Robolectric build an activity for you and use it as the context, or mock up your own context using Mockito, there is a more structured way of making Context work for you in testing.

The reason why you can’t get Context out of your way in the first place is because it is a class, and you need to construct a specific instance to use it in testing, and it is just impossible to construct a real one! But what if it’s an interface? Then you can pass the interface around, and have a mock implementation of that interface to be used in testing instead of the real one?

With that in mind, we come up with the solution of having a ContextWrapper, which serves exact same purpose as Android’s Context, delegating all tasks to Android’s Context, and implements an interface, says IContext, that we will pass around instead of Android’s Context object. This IContext at a glance will look very much like what Android’s Context offers, and you can add in more as you go along with your project.

Below is a simplified example of how we implement this pattern. Now at least you can test AppUtils’ method without worrying about how to construct a Context!

public interface IContext {
    boolean getBoolean(int resId) throws Resources.NotFoundException;
}

public final class ContextWrapper implements IContext {
    private Context mContext;

    public ContextWrapper(Context context) {
        mContext = context;
    }
    @Override
    public boolean getBoolean(int resId) throws NotFoundException {
        return mContext.getResources().getBoolean(resId);
    }
}

public MyActivity extends Activity {
    private IContext mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = new ContextWrapper(this);
    }

    ...

    private boolean checkIsEnabled() {
        return AppUtils.isFeatureEnabled(mContext);
    }
}

public AppUtils {
    public static boolean isFeatureEnabled(IContext context) {
        try {
            return context.getBoolean(R.bool.is_feature_enabled);
        } catch (NotFoundException e) {
            return false;
        }
    }
}