2012년 1월 31일 화요일

[안드로이드] String.xml 사용하기2 - Format 이용하기

스트링을 이용하다 보면 가끔 C에서의 printf가 너무 그립다.
물론 java도 그에 해당되는 녀석이 있다.
(Formatter는 요기 참고~)
http://developer.android.com/reference/java/util/Formatter.html#format(java.lang.String, java.lang.Object...)

이러한 포맷을 string.xml에도 지정 할 수 있는데,
UI의 고정된 메시지에 숫자만 바뀌거나 어떤 한 값만 바뀌는 경우 유용하게 사용 할 수 있다.

<?xml version="1.0" encoding="utf-8"?>

<resources>
    <string name="like_message">%1$d명의 사용자가 좋아 합니다.</string>
</resources>

1명의 사용자가 좋아 합니다.
27명의 사용자가 좋아 합니다.
같이 몇명인가의 값만 바뀐다면,
    String strLike = getString(R.string.like_message, 27);
이런식으로 뒤에 해당 값을 대입 시켜 주면 된다.


    <string name="like_message">%1$d명의 사용자가 좋아 합니다.</string>


를 좀더 자세히 살펴 보면 %1$d 가 있는데 여기서,
%1은 첫번째 항목을 뜻하고,
$d는 익숙한 정수형값임을 뜻한다.


따라서 
    홍길동27명의 사용자가 좋아 합니다.
와 같이 홍길동 과 27 이 변경 되는 값이라면,
    <string name="like_message">%1$s외 %2$d명의 사용자가 좋아 합니다.</string>
처럼 하면 된다.


java파일 에서는 


    String strHello = getString(R.string.like_message, "홍길동", 27);


처럼 사용 하면 된다.

2012년 1월 30일 월요일

[안드로이드] String.xml 사용하기

프로그래밍을 하다보면 문자열을 사용 하는 경우가 많다.
보통 귀찮아서 하드코딩 하지만;;;
수정이 빈번해 지던가 상사의 갈굼이 들어 오면 몰아서 상수로 정의 하기도 한다.
하지만 안드로이드 Context를 사용 할 수 있다면 string.xml을 사용 하는 것이 좋다.
string.xml의 경로는 기본적으로 
     ProjectName/res/values/string.xml
이다.

열어 보면 

<?xml version="1.0" encoding="utf-8"?>

<resources>
    <string name="hello">Hello string</string>
</resources>

처럼 되어 있는데, <resources> </Resources> 사이에 <string> </string> 으로 값을 넣어 주면 된다.

위 예와 같이
    <string name = "이름">내용</string>
하면 되는데,
[이름]에는 나중에 java코드나 다른 xml 파일에서 사용할 변수명을,
[내용]에는 실제로 대치될 스트링 값을 넣어 주는 것이다.
또한 주의 할점은 [이름]의 변수 명을 짓을 때는 자바 변수명명 규칙을 준수 해야 되며,
[내용]의 경우 xml의 string 형식을 준수 해야 한다.
xml의 string 형식을 보충 하자면 
    & : &amp; 
    < : &lt; 
    > : &gt; 
    ' : &apos; 
    " : &quot;
와 같은 문자는 xml 예약어 이므로 위의 표대로 써줘야 한다.

자 그럼 자바 코드에서 위의 스트링 값을 사용 하려면??

    String strHello = getString(R.string. hello);

이렇게 해주면 된다.

2012년 1월 25일 수요일

[Android] 알람이 동작중인지 확인 하는법

제목 그대로 알람이 동작중인지 확인하여 동작 중이라면
알람을 재등록 하지 않는 다던가의 처리가 필요한 경우가 있다.
그럴 경우 다음과 같이 하면 알람이 등록 되었는지 확인 할 수 있다.

private boolean isAlarmActivated() 
{
boolean result;
PendingIntent pIntent;

Intent intentToSend = new Intent();
intentToSend.setAction("SOME_ACTION");

pIntent = PendingIntent.getService(getContext(), 0, intentToSend, PendingIntent.FLAG_NO_CREATE);

result = pIntent != null;

Logging.d(TAG, "[isAlarmActivated] " + result + " - " + pIntent);
   return result;
}

단, 주의해야 할 점이 몇가지 있다.
(아래 항목을 간과 한다면 계속 false 를 보게됨.)

1. 호출메소드를 잘 선택 할것
  - 밑줄친 부분의 메소드 명인데 PendingIntent를 처리할 주체가 어떤녀석이냐에 따라
PendingIntent.getActivity(context, requestCode, intent, flags);
PendingIntent.getActivities(context, requestCode, intents, flags);
PendingIntent.getBroadcast(context, requestCode, intent, flags);
PendingIntent.getService(context, requestCode, intent, flags);
  중에 호출할 메소드를 잘 선택해 주어야 한다.

2. 알람의 Intent는 동일하게 할 것
  - 밑줄친 메소드의 인자중 3번째 인자인 Intent 값의 경우 알람 생성시 지정한 값과 같아야(완전히 같아야 한다는게 아니고 동일한 인텐트로 인식 될 수 있으면 됨)  한다.

3. 알람 해제시 PendingIntent를 cancel() 해줄 것
 - 알람을 해제 할때는 PendingIntent.cancel() 을 호출해 주어야 한다. 그렇지 않으면 알람은 해제 되었는데 PendingIntent가 살아 있어 원하는 결과를 얻을 수 없게 된다. (알람 먼저 cancel하고 동일한 PendingIntent를 Cancel하면 된다)


2012년 1월 19일 목요일

[안드로이드] Logcat창에 logcat session filter 가 자꾸 떠서 디버깅을 방해할 경우

안드로이드 API 버젼 14가 나오면서 ADT 또한 1.6으로 업데이트 되었다.
이번 ADT의 Logcat은 전버전에 비해 필터 기능이 창 편해 졌는데...

어느날 인가?
Eclipse의 설정값이 초기화 되었다.
귀찮아 하면서 설정을 복원했는데...
다하고 나서 디버깅을 하려 하니

 Logcat창에 logcat session filter 라는 항목이 생기면서 포커스를 자꾸 뺐어 가는 것이었다.
자동스크롤마저 되어서 이건 뭐 USB 케이블을 빼기 전까진 디버깅이 불가능 하다.

어딜 감히 건방지게 지맘대로 스크롤을해 -ㅁ-;;
가뜩이나 버그나서 짬뽕나는데;;

아무튼 이런 열받는 상황을 개선할 방법이 있다.

Eclipse Menu -> Preferences -> Android -> Logcat 에 보면..
Display logcat view when there are messages from an application in the workspace

이 옵션을 체크 해제 하면 된다.

2012년 1월 17일 화요일

[Android] PendingIntent의 Extra값이 바뀌지 않는 경우...


Alarm 이나 Notification 에 Intent를 등록 하려면 PendingIntent를 이용하여 Intent를 전달 해야 한다.
하지만 아래와 같이 하게 되면 희안하게도 Intent에 집어 넣은 Extra값이 바뀌지 않는 경우가 있다.

Intent intentToSend = new Intent();
intentToSend.setAction("SOME_ACTION");
intentToSend.putExtra("SOME_EXTRA", 7777); 
                      /* 777이 않바뀜 ㅜ_ㅠ */

PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 0, intentToSend, 0);

문제는 getActivity 메소드의 마지만 인수인 flag 값에 있었다.
해당 플래그를 다음과 같이 바꿔줘야 매번 갱신된 값이 반영되게 된다.

PendingIntent pendingIntent =  PendingIntent.getActivity(getContext(), 0, intentToSend, PendingIntent.FLAG_UPDATE_CURRENT);



2012년 1월 12일 목요일

[Android] Emulator 4.0.2 자동 업데이트;;

4.0 에뮬레이터를 사용중에 어느날 갑자기부팅 중 낯선 화면이 떴다.
뭔가 업그레이드를 한다는듯 한데;;

부팅이 끝난뒤 Setting -> About phone 에 들어가 보니,
4.0.2 로 업데이트 되어 있다;;

구글링좀 해보니 Minor 버그를 해결한 버젼이라 한다.
AVD엔 여전히 4.0으로 나온다.
API레벨도 여전히 14...

암튼 에뮬에서 업데이트를 하니 좀 신기한 경험 이었다 ㅋ

2012년 1월 4일 수요일

[Android] Activity xxx has leaked window xxxxxxx that was originally added here.

Dialog를 사용하다가 제목과 같은 에러를 만났다.
다른 경우에도 발생 할 법한 에러이긴 한데 아직 접해 본적은 없다.

일단 원인은 엑티비티에서 생성한 다이얼로그가 떠있는데,
액티비티가 종료되어 메모리 누수가 발생 했기 때문이다.

해결 방법은...
물론 액티비티가 종료될때 떠있을지 모르는 다이얼로그를 닫아 주면 되는데,

액티비티의 onPause()에서 다이얼로그의 dismiss() 를 호출 하거나,
다른 방법으로 닫아 주면 된다.

나의 경우
서비스에서 투명 액티비티를 띄워 투명액티비티상에서
다시 다이얼로그를 띄웠고 다이얼로그에서 뭔가 작업을 한뒤
다이얼로그가 닫히면서 액티비티도 종료 되는 것을 개발 하려 했는데,
실수로 액티비티만 닫히고 다이얼로그는 종료되지 않았던 것이었다.

알면 쉽지만..
이것 때문에 4시간은 해맨듯 하다.
ㅠㅠ