【问题标题】:Storing new data in settings在设置中存储新数据
【发布时间】:2013-02-02 16:49:34
【问题描述】:

在我的应用程序中,用户可以保存程序将连接到的服务器配置文件。 由于我不知道用户将添加的连接配置文件的数量,我不能简单地将其放入SettingsActivity

由于我不想再打扰 XML 文件,我想我可以像这样保存 SharedPreferences:

server1hostname
server1username
server1password
server2hostname
server2username
server2password
server3hostname
server3username
server3password

第一个问题:如果我想将所有内容都保存在标准首选项文件中(与在某处创建自己的文件相反),是否有更好的方法?

第二个问题:我已经或多或少地实现了这一点。奇怪的是:它适用于现有设置(最初是通过 SettingsActivity 创建的),但不适用于新条目。

这是源代码(Powerline 是服务器配置文件的类名):

@Override
public void onBackPressed() {
    super.onBackPressed();

    // Save powerline item
    Powerline newPowerline = new Powerline();
    newPowerline.setAddress(etAddress.getText().toString());
    newPowerline.setSendPort(Integer.parseInt(etSendPort.getText().toString()));

    newPowerline.setReceivePort(Integer.parseInt(etReceivePort.getText().toString()));
    newPowerline.setUsername(etUsername.getText().toString());
    newPowerline.setPassword(etPassword.getText().toString());

    int powerlinePositionInSettings = getIntent().getIntExtra("powerlinePositionInSettings", -1);

    if (option.equals("create"))    {
        if (newPowerline.create(this, powerlinePositionInSettings))
            finish();
    } else {
        if (powerlinePositionInSettings >= 0)
            if (newPowerline.change(this, powerlinePositionInSettings))
                finish();
    }
}

这里是Powerline类的创建函数:

public boolean create(Context context, int powerlinePositionInSettings) {
    String positionString = String.valueOf(powerlinePositionInSettings);        
    Log.i("Powerline", "Saving new powerline to settings to position " + positionString + ".");

    try {
        SharedPreferences.Editor prefsEditor = PreferenceManager.getDefaultSharedPreferences(context).edit();
        prefsEditor.putString("powerline" + positionString + "Address", this.getAddress());
        prefsEditor.putString("powerline" + positionString + "SendPort", String.valueOf(this.getSendPort()));
        prefsEditor.putString("powerline" + positionString + "ReceivePort", String.valueOf(this.getReceivePort()));
        prefsEditor.putString("powerline" + positionString + "Username", this.getUsername());
        prefsEditor.putString("powerline" + positionString + "Password", getPassword());

        Log.i("Prefs", "Saving \"" + "powerline" + positionString + "Address" + "\" to be \"" + this.getAddress() + "\"");

        return prefsEditor.commit();
    } catch(Exception e) {
        e.printStackTrace();
        return false;
    }
}

这里是Powerline类的变化函数:

public boolean change(Context context, int powerlinePositionInSettings) {
    String positionString = String.valueOf(powerlinePositionInSettings);
    Log.i("Powerline", "Saving powerline to settings to position " + positionString + ".");

    try {
        SharedPreferences.Editor prefsEditor = PreferenceManager.getDefaultSharedPreferences(context).edit();
        prefsEditor.putString("powerline" + positionString + "Address", this.getAddress());
        prefsEditor.putString("powerline" + positionString + "SendPort", String.valueOf(this.getSendPort()));
        prefsEditor.putString("powerline" + positionString + "ReceivePort", String.valueOf(this.getReceivePort()));
        prefsEditor.putString("powerline" + positionString + "Username", this.getUsername());
        prefsEditor.putString("powerline" + positionString + "Password", getPassword());

        Log.i("Prefs", "Saving \"" + "powerline" + positionString + "Address" + "\" to be \"" + this.getAddress() + "\"");

        return prefsEditor.commit();
    } catch(Exception e) {
        e.printStackTrace();
        return false;
    }
}

更改函数存储的值确实被保存了。 create 函数保存的新值不是。

有人有想法吗?我看不出这两个函数有什么显着差异。

【问题讨论】:

  • 我可能是错的,但你不是在设备被root的情况下暴露用户密码吗?
  • 是的,你是对的。在一般存储过程正常工作后,我会为其添加一些加密。
  • 你有任何 logcat 错误吗?
  • 至少没有错误。选项变量是“create”。
    将新的电力线保存到位置 3。
    将“powerline3Address”保存为“test”
    然后当我读取设置时,新条目不存在。

标签: android settings store android-preferences


【解决方案1】:

首先:不要创建文件来存储用户数据。而不是这个,创建一个数据库。因此,您可以读取、写入或更改数据。为此有一些 tuts: http://thenewboston.org/list.php?cat=6 在此页面中,您可以观看从 #111 到 #124 的 tuts。他们会教你的。

【讨论】:

    【解决方案2】:

    我将使用这种方法。

    用法:

    //创建电力线

    new Powerline("hostname", "username", "password", 8080, 9090).create(this);

    //更新所有电力线

    List<Powerline> powerlines = Powerline.getAll(this);
        for (Powerline p : powerlines) {
            p.hostname = p.hostname + " updated";
            p.update(this);
        }
    

    PS:测试过的代码,根据你的要求修改:

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    import android.content.Context;
    import android.content.SharedPreferences;
    import android.preference.PreferenceManager;
    
    public class Powerline {
    private int _id;
    public String hostname;
    public String username;
    public String password;
    public int inPort;
    public int outPort;
    
    public Powerline(String hostname, String username, String password,
            int inPort, int outPort) {
        super();
        this.hostname = hostname;
        this.username = username;
        this.password = password;
        this.inPort = inPort;
        this.outPort = outPort;
    }
    
    public Powerline(String powerlineString) {
        String[] vars = powerlineString.split(":");
        _id = Integer.parseInt(vars[0]);
        hostname = vars[1];
        inPort = Integer.parseInt(vars[2]);
        outPort = Integer.parseInt(vars[3]);
        password = vars[4];
        username = vars[5];
    }
    
    public void create(Context context) {
        save(context, increamentKey(context));
    }
    
    public void update(Context context) {
        save(context, _id);
    }
    
    private void save(Context context, int id) {
        SharedPreferences.Editor ed = PreferenceManager
                .getDefaultSharedPreferences(context).edit();
        ed.putString("powerline:" + id, toString());
        ed.commit();
    }
    
    @Override
    public String toString() {
        return _id + ":" + hostname + ":" + inPort + ":" + outPort + ":"
                + password + ":" + username;
    }
    
    public static List<Powerline> getAll(Context context) {
        SharedPreferences p = PreferenceManager
                .getDefaultSharedPreferences(context);
        List<Powerline> powerlines = new ArrayList<Powerline>();
        Map<String, ?> all = p.getAll();
        for (String key : all.keySet()) {
            if (key.startsWith("powerline:")) {
                powerlines.add(new Powerline(p.getString(key, null)));
            }
        }
        return powerlines;
    }
    
    private int increamentKey(Context context) {
        int key = PreferenceManager.getDefaultSharedPreferences(context)
                .getInt("_id", -1);
        PreferenceManager.getDefaultSharedPreferences(context).edit()
                .putInt("_id", ++key).commit();
        // also assign it to current object
        _id = key;
        return key;
    }
    }
    

    【讨论】:

    • 我非常感谢您的代码。但是你能在我的身上看到什么似乎是错误的吗?
    • 我在回答“有更好的方法吗?”将一台服务器数据存储在一个地方而不是 server1hostname、server1username 等。您的提交代码似乎很好。我建议不要在覆盖的方法中调用super.onBackPressed(),如果你坚持调用它,那么将这一行移到onBackPressed() 方法的末尾。还要确保你的阅读代码没有错误,你的提交代码看起来很好。
    • 您也不能使用相同的键存储数据。我想你已经知道了,但只是确定一下。如果您已经存储了一次“server3hostname”,再次使用相同的键存储将替换旧值。
    • 我通过在 SettingsActivity 中添加预期的键来检查我的阅读代码。那里也是空的。无论如何,我现在选择了数据库解决方案。对于我要存储的少数数据,它似乎有点过大。但它比设置的东西好得多。非常感谢您的建议。我会记住它们以备后用。顺便说一句:我删除了 super.onBackPressed()。
    猜你喜欢
    • 2023-04-09
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    • 2016-09-04
    • 1970-01-01
    • 2019-05-16
    • 2015-02-23
    相关资源
    最近更新 更多