mewais
mewais

Reputation: 1337

How to configure Android library from an app that imports it?

I'm kinda new to Android development so my question might be weird or not even possible. I wouldn't know!

Anyway, I'm building multiple apps that will have a lot of shared elements, so I decided to build a library with those components and use it in all of the apps, rather than stupid copying and pasting code. For example, the library handles the welcome screen and login/signup flow activities, among other things. So here are the problems this approach might cause:

  1. While the behavior is the same across the apps, but the logo that I show at the welcome screen is different. Right now I populate it with an image resource from the library resources (R class) which will be the same for all apps and is obviously not correct.
  2. The login/signup process is based on Firebase, which will require the app to have a key to be able to use them. Right now I also populate it with a dummy string resource from the library resources.

So my question really boils down to 3 parts:

  1. Is there anyway I could pass this info from the app to the library? can I somehow modify the R class of the library? Or can I use the app's R class from the library? I can also call this part of the library as a function passing the parameters I need. But the first solution looks maybe more clean to me?
  2. Whatever the answer to Q1 is. Where would I do this and how? The library has the welcome activity itself which is supposed to be the first activity in the app. How and where do I do this once the app starts and before the first activity starts?
  3. If what I'm doing is wrong or impossible, is there any other way to achieve it?

Upvotes: 4

Views: 225

Answers (2)

mewais
mewais

Reputation: 1337

Apart from the solution above, I also found another way to achieve this whole thing without having to initialize libraries and whatnot. I think the correct way to do this is to use productFlavors in the library. This allows the library to share the one main set of source code, one main set of resources, then an extra set of resource per app/flavors. This is very sufficient for my purposes.

For more info about build variants and flavors: https://developer.android.com/studio/build/build-variants

Upvotes: 0

ישו אוהב אותך
ישו אוהב אותך

Reputation: 29783

  1. Is there anyway I could pass this info from the app to the library? can I somehow modify the R class of the library? Or can I use the app's R class from the library? I can also call this part of the library as a function passing the parameters I need. But the first solution looks maybe more clean to me?

You don't need to modify the R class because you can override the resource file by creating a file with the same name. But it's not a clean solution because you constantly need to ensure your project and library resources name are the same.

  1. Whatever the answer to Q1 is. Where would I do this and how? The library has the welcome activity itself which is supposed to be the first activity in the app. How and where do I do this once the app starts and before the first activity starts?

Instead of overriding the resources name, you're better to modify your library to receive a configuration as a contract to use the library. Here the sample:

First, create the class for holding the configuration:

public class Configuration {
  private int welcomeImageDrawableId;
  private int logoDrawableId;

  // constructor
  public Configuration(int welcomeImageDrawableId, int logoDrawableId) {
    this.welcomeImageDrawableId = welcomeImageDrawableId;
    this.logoDrawableId = logoDrawableId;
  }

  // setter and getter.
  public int getLogoDrawableId() {
    return logoDrawableId;
  }
}

Second, use the configuration class for the library by creating a Singleton class which will be used internally by the library:

public class MyLibrary {
    private static MyLibrary myLibrary;
    private Configuration configuration;

    private MyLibrary(){}
    private MyLibrary(Configuration configuration) {
      this.configuration = configuration;
    }

    public static MyLibrary getInstance() {
        if(myLibrary == null) {
            throw new RuntimeException("Need call createInstanceWith method first!!");
        }
        return myLibrary;
    }

    public static MyLibrary createInstanceWith(Configuration configuration) {
        if(myLibrary == null) {
            synchronized(MyLibrary.class) {
                if (myLibrary == null) {
                  myLibrary = new MyLibrary(configuration);
                }
            }
        }
        return test;
    }

    public Configuration getConfiguration() {
      return configuration;
    }
}

Third, use the configuration class in your library via the singleton class. something like this:

// assume imvLogo is an existing ImageView
Configuration configuration = MyLibrary.getInstance().getConfiguration();
imvLogo.setImageResource(configuration.getLogoDrawableId());

Last, register the contract when the library is used with:

Configuration configuration = new Configuration(R.drawable.welcome, R.drawable.logo);
MyLibrary.createInstanceWith(configuration);

Note: all the code isn't tested yet, error is to be expected.

Upvotes: 2

Related Questions