Preference


프리퍼런스를 관리하는 클래스는 SharedPreferences이다.

  • SharedPreferences getSharedPreferences (String name, int mode)

    • 첫 번째 인수는 프레퍼런스를 저장할 XML 파일의 이름
    • mode 인수는 이 파일의 공유 모드로 0이면 읽기 쓰기가 가능 하다.
  • SharedPreferences getPreferences (int mode)

    • 파일 인수가 생략되어 있는데 이 경우 액티비티의 이름과 같은 xml 파일이 생성된다.
  • int getInt (String key, int defValue)

  • String getString (String key, String defValue)

  • boolean getBoolean (String key, boolean defValue)

값을 기록하는 메서드는 내부 클래스인 SharedPreferences.Editor가 제공된다.

  • SharedPreferences.Editor putInt(String key, int value)
  • SharedPreferences.Editor putBoolean(String key, boolean value)
  • SharedPreferences.Editor putstring(String key, String value)
  • SharedPreferences.Editor remove(String key)
  • boolean commit()
  • SharedPreferences.Editor clear()

문자열과 정수를 저장하는 간단한 예제

public class PrefTest extends Activity {
	TextView textName;
	TextView textStNum;
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.preftest);

		textName = (TextView)findViewById(R.id.name);
		textStNum = (TextView)findViewById(R.id.stnum);

		SharedPreferences pref = getSharedPreferences("PrefTest",0);
		String Name = pref.getString("Name", "이름없음");
		textName.setText(Name);

		int StNum = pref.getInt("StNum",20101234);
		textStNum.setText("" + StNum);
	}

	public void onPause() {
		super.onPause();

		SharedPreferences pref = getSharedPreferences("PrefTest",0);
		SharedPreferences.Editor edit = pref.edit();

		String Name = textName.getText().toString();
		int StNum = 0;
		try {
			StNum = Integer.parseInt(textStNum.getText().toString());
		}
		catch (Exception e) {}

		edit.putString("Name", Name);
		edit.putInt("StNum", StNum);

		edit.commit();
	}
}
  • getSharedPreferences메서드로 프레퍼런스 객체를 얻는다.
  • onPause에서 edit메서드로 기록할 데이터를 프레퍼런스에 기록 한다.
  • onCreate에서 객체를 읽어온다.

PreferenceActivity

사용자가 설정값을 입력하고 불러 올 수 있는 UI를 미리 만들어서 제공하는 자동화된 방법이다.
xml만 잘 작성하고 Activity에서 PreferenceActivity만 잘 상속해서 사용하면 된다.

<PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android">
<EditTextPreference
	android:key="age"
	android:title="나이"
	android:summary="너 도대체 몇 살이니?"
	android:defaultValue="19" 
/>
<CheckBoxPreference
	android:key="male"
	android:title="성별"
	android:summary="남자면 체크"
	android:defaultValue="true" 
/>
</PreferenceScreen>
public class PrefActivity extends PreferenceActivity {
	@SuppressWarnings("deprecation")
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		addPreferencesFromResource(R.layout.prefactivity);
	}
}

TextPref

xml을 이용한 방법은 parser를 이용해야 하기 때문에 속도가 느리다.
빈번하게 onPause에서 현재 상태를 저장해야 한다면 문제가 발생 한다.

그래서 그냥 단순히 text에 기록하고 불러오는 방법을 사용한다.

테스트 코드

public class TextLogTest extends Activity {
	LinearLayout mLinear;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.textlogtest);

		// onCreate에서 로그 유틸리티 초기화
		TextLog.init(this);
		TextLog.mAppendTime = true;
		TextLog.mReverseReport = true;

		mLinear = (LinearLayout)findViewById(R.id.linear);
		mLinear.setOnTouchListener(new View.OnTouchListener() {
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					// 필요할 때 로그 기록
					lg.o("down. x = " + (int)event.getX() + 
							", y = " + (int)event.getY());
					return true;
				case MotionEvent.ACTION_MOVE:
					lg.o("move. x = " + (int)event.getX() + 
							", y = " + (int)event.getY());
					return true;
				}
				return false;
			}
		});
	}

	// 다음 두 메서드를 디버깅 프로젝트의 엑티비티에 추가한다.
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		TextLog.addMenu(menu);
		return true;
	}

	public boolean onOptionsItemSelected(MenuItem item) {
		if (TextLog.execMenu(item) == true) {
			return true;
		}
		return false;
	}
}
//텍스트 파일에 설정 정보를 저장하는 클래스. 안드로이드의 프레프런스가 너무 느려 새로 만듬
//Ready()를 호출하여 입출력 준비하고 기록할 때는 CommitWrite, 읽기만 했을 때는 EndReady를 호출한다.
class TextPref {
	String mPath;
	StringBuilder mBuf;
	static final String HEADER = "__Text Preference File__\n"; 

	// 생성자로 프레퍼런스의 완전 경로를 전달한다. 
	public TextPref(String Path) throws Exception {
		mPath = Path;
		File file = new File(mPath);
		if (file.exists() == false) {
			FileOutputStream fos = new FileOutputStream(file);
			fos.write(HEADER.getBytes());
			fos.close();
		}
	}

	// 설정 파일을 삭제한다.
	public void Reset() {
		File file = new File(mPath);
		file.delete();
	}

	// 버퍼를 준비하여 읽기 및 쓰기 준비를 한다.
	public boolean Ready() {
		try {
			FileInputStream fis = new FileInputStream(mPath);
			int avail = fis.available();
			byte[] data = new byte[avail];
			while (fis.read(data) != -1) {;}
			fis.close();
			mBuf = new StringBuilder(avail);
			mBuf.append(new String(data));
		}
		catch (Exception e) {
			return false;
		}
		return true;
	}

	// 버퍼의 내용을 파일로 기록한다.
	public boolean CommitWrite() {
		File file = new File(mPath);
		try {
			FileOutputStream fos = new FileOutputStream(file);
			fos.write(mBuf.toString().getBytes());
			fos.close();
		} 
		catch (Exception e) {
			return false;
		}
		mBuf = null;
		return true;
	}

	// 버퍼를 해제하고 읽기를 종료한다. 변경한 내용은 모두 취소된다.
	public void EndReady() {
		mBuf = null;
	}
	
	// name키의 위치를 검색하여 = 다음 위치를 리턴한다. 없으면 -1을 리턴한다.
	// 우연한 중복 방지를 위해 키 이름앞에 __를 붙인다.
	int FindIdx(String name) {
		String key = "__" + name + "=";
		int idx = mBuf.indexOf(key);
		if (idx == -1) {
			return -1;
		} else {
			return idx + key.length();
		}
	}

	// 문자열 키를 기록한다. 이미 있으면 대체한다.
	public void WriteString(String name, String value) {
		int idx = FindIdx(name);
		if (idx == -1) {
			mBuf.append("__");
			mBuf.append(name);
			mBuf.append("=");
			mBuf.append(value);
			mBuf.append("\n");
		} else {
			int end = mBuf.indexOf("\n", idx);
			mBuf.delete(idx, end);
			mBuf.insert(idx, value);
		}
	}

	// 문자열 키를 읽는다. 없으면 디폴트를 리턴한다.
	public String ReadString(String name, String def) {
		int idx = FindIdx(name);
		if (idx == -1) {
			return def;
		} else {
			int end = mBuf.indexOf("\n", idx);
			return mBuf.substring(idx, end);
		}
	}

	// 정수를 읽는다. 일단 문자열 형태로 읽은 후 변환한다.
	public void WriteInt(String name, int value) {
		WriteString(name, Integer.toString(value));
	}

	// 정수를 기록한다. 문자열 형태로 변환하여 기록한다.
	public int ReadInt(String name, int def) {
		String s = ReadString(name, "__none");
		if (s.equals("__none")) {
			return def;
		}
		try {
			return Integer.parseInt(s);
		}
		catch (Exception e) {
			return def;
		}
	}
	
	public void WriteLong(String name, long value) {
		WriteString(name, Long.toString(value));
	}
	
	public long ReadLong(String name, long def) {
		String s = ReadString(name, "__none");
		if (s.equals("__none")) {
			return def;
		}
		try {
			return Long.parseLong(s);
		}
		catch (Exception e) {
			return def;
		}
	}
	
	// 진위값은 true, false가 아닌 1, 0으로 기록한다.
	public void WriteBoolean(String name, boolean value) {
		WriteString(name, value ? "1":"0");
	}

	public boolean ReadBoolean(String name, boolean def) {
		String s = ReadString(name, "__none");
		if (s.equals("__none")) {
			return def;
		}
		try {
			return s.equals("1") ? true:false;
		}
		catch (Exception e) {
			return def;
		}
	}
	
	public void WriteFloat(String name, float value) {
		WriteString(name, Float.toString(value));
	}

	public float ReadFloat(String name, float def) {
		String s = ReadString(name, "__none");
		if (s.equals("__none")) {
			return def;
		}
		try {
			return Float.parseFloat(s);
		}
		catch (Exception e) {
			return def;
		}
	}
	
	// 한꺼번에 값을 삽입하기 위해 준비한다. 헤더 작성하고 충분한 버퍼를 할당한다.
	void BulkWriteReady(int length) {
		mBuf = new StringBuilder(length);
		mBuf.append(HEADER);
		mBuf.append("\n");
	}

	// 문자열 형태로 받은 값을 무조건 뒤에 덧붙인다.
	void BulkWrite(String name, String value) {
		mBuf.append("__");
		mBuf.append(name);
		mBuf.append("=");
		mBuf.append(value);
		mBuf.append("\n");
	}

	// 키를 삭제한다. 
	void DeleteKey(String name) {
		int idx = FindIdx(name);
		if (idx != -1) {
			int end = mBuf.indexOf("\n", idx);
			mBuf.delete(idx - (name.length() + 3), end + 1);
		}
	}
}

출처

[1] 안드로이드 정복 4판, 김상형


'Computer Science > Android Application' 카테고리의 다른 글

AIDL과 Remote Service  (1) 2017.08.22
NDK 사용  (0) 2017.08.20
Broadcast Receiver  (0) 2017.08.16
Service  (0) 2017.08.16
Activity  (0) 2017.08.16

+ Recent posts