安卓配置文件

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 的端点。如果我正确理解您的问题,您可以使用SharedPreferencessecure-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 );

【讨论】:

以上是关于安卓配置文件的主要内容,如果未能解决你的问题,请参考以下文章

delphi 安卓程序如何读取外部配置文件

为啥安卓手机没有运营商配置文件更新 而IOS就要?

安卓混淆配置简要说明

给客户配置安卓工程的时候遇到的问题

IIS配置安卓下载.apk文件

Json解析两种方法以及U3d配置安卓环境