What is the best way and how to set up a config file for a application?
I want the application to be able to look into a text file on the sd card and pick out certain information that it requires ?
If your application is going to be released to the public and if you have sensitive data in your config such as API keys or passwords I would suggest to use secure-preferences instead of SharedPreferences since ultimately SharedPreferences are stored in an XML in clear text and on a rooted phone it is very easy for an application to access another's shared preferences.
By default it's not bullet proof security (in fact it's more like obfuscation of the preferences) but it's a quick win for incrementally making your android app more secure. For instance it'll stop users on rooted devices easily modifying your app's shared prefs. (link)
I would suggest a few of other methods:
Method 1: Use a *.properties file with Properties
Pros:
Cons:
First, create a config file: res/raw/config.properties
and add some values:
api_url=http://url.to.api/v1/
api_key=123456
You can then easily access the values with something like this:
package some.package.name.app;
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public final class Helper {
private static final String TAG = "Helper";
public static String getConfigValue(Context context, String name) {
Resources resources = context.getResources();
try {
InputStream rawResource = resources.openRawResource(R.raw.config);
Properties properties = new Properties();
properties.load(rawResource);
return properties.getProperty(name);
} catch (Resources.NotFoundException e) {
Log.e(TAG, "Unable to find the config file: " + e.getMessage());
} catch (IOException e) {
Log.e(TAG, "Failed to open config file.");
}
return null;
}
}
Usage:
String apiUrl = Helper.getConfigValue(this, "api_url");
String apiKey = Helper.getConfigValue(this, "api_key");
Of course this could be optimized to read the config file once and get all values.
Method 2: Use AndroidManifest.xml meta-data element:
Personally I've never used this method because it doesn't seem very flexible.
In your AndroidManifest.xml
add something like:
...
<application ...>
...
<meta-data android:name="api_url" android:value="http://url.to.api/v1/"/>
<meta-data android:name="api_key" android:value="123456"/>
</application>
Now a function to retrieve the values:
public static String getMetaData(Context context, String name) {
try {
ApplicationInfo ai = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
Bundle bundle = ai.metaData;
return bundle.getString(name);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Unable to load meta-data: " + e.getMessage());
}
return null;
}
Usage:
String apiUrl = Helper.getMetaData(this, "api_url");
String apiKey = Helper.getMetaData(this, "api_key");
Method 3: Use buildConfigField
in your Flavor:
I didn't find this in the official Android documentation/training but this blog article is very useful.
Basically setting up a project Flavor (for example prod
) and then in your app's build.gradle
have something like:
productFlavors {
prod {
buildConfigField 'String', 'API_URL', '"http://url.to.api/v1/"'
buildConfigField 'String', 'API_KEY', '"123456"'
}
}
Usage:
String apiUrl = BuildConfig.API_URL;
String apiKey = BuildConfig.API_KEY;