安卓配置文件
Posted
技术标签:
【中文标题】安卓配置文件【英文标题】:Android configuration file 【发布时间】:2011-07-05 15:52:37 【问题描述】:最好的方法是什么?如何为应用程序设置配置文件?
我希望应用程序能够查看 SD 卡上的文本文件并挑选出它需要的某些信息。
【问题讨论】:
这个配置文件是干什么用的?您需要保存用户设置或类似设置吗?有很多很好的使用 SharedPreferences 和类似的指南。 现在将 pda 的名称加载到应用程序中,然后我希望将来能够更改此名称而无需更改应用程序中的代码 一定要检查链接的问题。 .properties 答案就是我想要的这个问题。它看起来也像 @Beginner 正在寻找的东西。 你的意思是/default.prop
?
【参考方案1】:
如果您的应用程序要向公众发布,并且您的配置中有敏感数据,例如 API 密钥或密码,我建议使用 secure-preferences 而不是 SharedPreferences,因为最终使用 SharedPreferences以明文形式存储在 XML 中,在有根手机上,应用程序很容易访问其他人的共享首选项。
默认情况下,它不是防弹安全(实际上它更像 偏好的混淆),但对于渐进式来说,这是一个快速的胜利 让你的安卓应用更安全。例如,它会阻止用户 植根设备可以轻松修改您应用的共享首选项。 (link)
我会建议其他一些方法:
*方法一:使用带有Properties的.properties文件
优点:
-
无论您使用什么 IDE,都可以轻松编辑
更安全:因为它是使用您的应用编译的
如果你使用Build variants/Flavors,可以很容易地被覆盖
你也可以写在config里
缺点:
-
您需要上下文
您也可以在配置中写入(是的,它也可以是一个骗局)
(还有别的吗?)
首先,创建一个配置文件:res/raw/config.properties
并添加一些值:
api_url=http://url.to.api/v1/
api_key=123456
然后您可以通过以下方式轻松访问这些值:
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;
用法:
String apiUrl = Helper.getConfigValue(this, "api_url");
String apiKey = Helper.getConfigValue(this, "api_key");
当然,这可以优化为读取配置文件一次并获取所有值。
方法二:使用AndroidManifest.xml meta-data元素:
就我个人而言,我从来没有使用过这种方法,因为它看起来不太灵活。
在您的 AndroidManifest.xml
中,添加如下内容:
...
<application ...>
...
<meta-data android:name="api_url" android:value="http://url.to.api/v1/"/>
<meta-data android:name="api_key" android:value="123456"/>
</application>
现在是一个检索值的函数:
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;
用法:
String apiUrl = Helper.getMetaData(this, "api_url");
String apiKey = Helper.getMetaData(this, "api_key");
方法3:在Flavor中使用buildConfigField
:
我在 Android 官方文档/培训中没有找到这个,但是this blog article 非常有用。
基本上设置一个项目的Flavor(例如prod
)然后在你的应用程序的build.gradle
有类似的东西:
productFlavors
prod
buildConfigField 'String', 'API_URL', '"http://url.to.api/v1/"'
buildConfigField 'String', 'API_KEY', '"123456"'
用法:
String apiUrl = BuildConfig.API_URL;
String apiKey = BuildConfig.API_KEY;
【讨论】:
很好的答案,包含所有必要的细节。在大多数情况下,风味将是合适的选择。感谢您花时间发布此答案 所以我正在关注解决方案 1 和 3,但我的用例(我确信这是一个常见的用例)是拥有一个动态 API 主机地址,但资源路径由所有人共享构建变体。本质上,我正在寻找的是一个文本文件,用于将键/值对(以任何格式)存储在默认/全局空间(即 main)中,然后是特定于构建变体的一个,然后将这些对象与构建一起压缩变体优先。这存在吗?我读过SharedPreferences
,但这似乎是在运行时用户输入,我读过关于人们使用类来保存......
常量,但这也不太合适,因为我没有从覆盖常见配置值的特定配置值中获得任何好处。
@Justin 我从未使用过动态 API 主机地址;在我的情况下,服务器的 IP 会改变(负载平衡),而不是 API 的端点。如果我正确理解您的问题,您可以使用SharedPreferences
、secure-preferences
、数据库(SQLite、Realm、...),或在设备上创建/保存文件(*.properties 或其他)来存储键/值对 - 虽然我认为保存文件需要权限。最终,您还必须实现键/值源之间的优先级。无论如何,我认为你应该发布一个问题,因为这超出了这个问题的范围。
非常好的答案和很好的解释。谢谢。【参考方案2】:
您可以使用shared preferences 实现此目的
Google Android 页面上有关于如何使用共享首选项的非常详细的指南 https://developer.android.com/guide/topics/data/data-storage.html#pref
【讨论】:
哦,我想到了共享首选项,比如全局变量而不是配置文件,你可以看到我来自 web 开发背景而不是移动 :) 共享首选项文本文件的任何示例,以及访问此文件的活动? 如何将共享首选项用作配置源?我将配置视为一些“硬编码”文件(json、xml 等),其中包含要在应用程序内部使用的开发人员设置数据。共享首选项可能包含您在应用程序中生成的数据,但它们如何与其中的预设数据一起提供? 共享首选项不能像配置文件一样。【参考方案3】:如果您想存储应用程序的首选项,Android 为此提供了SharedPreferences。Here is the link to official training resource.
【讨论】:
共享首选项文本文件的任何示例,以及访问此文件的活动? @Uzi:要读取SharedPreferences,可以使用以下方式;boolean showInfo = preferences.getBoolean( Constants.PREFERENCES_INFO_SHOWN, false);
如何访问我存储在 SD 卡上的首选项文件,我应该是什么样子谢谢?
是的,我需要一种方法来存储外部配置数据。我不希望它们存储在内部
如何保存键值数据来满足应用程序中预定义数据的需求?在我看来,共享首选项可以很好地保存您的数据,但不能预先加载开发人员希望从头开始包含在其应用程序中的静态“硬编码”数据。【参考方案4】:
我最近遇到了这样的要求,在这里记下我是如何做到的。
应用程序能够查看 sd 卡上的文本文件和 挑选出它需要的某些信息
要求:
-
配置值(score_threshold)必须在 sdcard 上可用。所以有人可以在发布 apk 后更改这些值。
配置文件必须在安卓硬件的“/sdcard/config.txt”中可用。
config.txt 文件内容是,
score_threshold=60
创建一个实用程序类 Config.java,用于读写文本文件。
import android.util.Log;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
public final class Config
private static final String TAG = Config.class.getSimpleName();
private static final String FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/config.txt";
private static Config sInstance = null;
/**
* Gets instance.
*
* @return the instance
*/
public static Config getInstance()
if (sInstance == null)
synchronized (Config.class)
if (sInstance == null)
sInstance = new Config();
return sInstance;
/**
* Write configurations values boolean.
*
* @return the boolean
*/
public boolean writeConfigurationsValues()
try (OutputStream output = new FileOutputStream(FILE_PATH))
Properties prop = new Properties();
// set the properties value
prop.setProperty("score_threshold", "60");
// save properties
prop.store(output, null);
Log.i(TAG, "Configuration stored properties: " + prop);
return true;
catch (IOException io)
io.printStackTrace();
return false;
/**
* Get configuration value string.
*
* @param key the key
* @return the string
*/
public String getConfigurationValue(String key)
String value = "";
try (InputStream input = new FileInputStream(FILE_PATH))
Properties prop = new Properties();
// load a properties file
prop.load(input);
value = prop.getProperty(key);
Log.i(TAG, "Configuration stored properties value: " + value);
catch (IOException ex)
ex.printStackTrace();
return value;
创建另一个实用程序类来编写应用程序第一次执行的配置文件, 注意:必须为应用设置SD卡读/写权限。
public class ApplicationUtils
/**
* Sets the boolean preference value
*
* @param context the current context
* @param key the preference key
* @param value the value to be set
*/
public static void setBooleanPreferenceValue(Context context, String key, boolean value)
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
sp.edit().putBoolean(key, value).commit();
/**
* Get the boolean preference value from the SharedPreference
*
* @param context the current context
* @param key the preference key
* @return the the preference value
*/
public static boolean getBooleanPreferenceValue(Context context, String key)
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
return sp.getBoolean(key, false);
在您的主要活动中,onCreate()
if(!ApplicationUtils.getBooleanPreferenceValue(this,"isFirstTimeExecution"))
Log.d(TAG, "First time Execution");
ApplicationUtils.setBooleanPreferenceValue(this,"isFirstTimeExecution",true);
Config.getInstance().writeConfigurationsValues();
// get the configuration value from the sdcard.
String thresholdScore = Config.getInstance().getConfigurationValue("score_threshold");
Log.d(TAG, "thresholdScore from config file is : "+thresholdScore );
【讨论】:
以上是关于安卓配置文件的主要内容,如果未能解决你的问题,请参考以下文章