2011년 12월 27일 화요일

Android - 현재 설정 언어 조회하기


Locale locale = getResources().getConfiguration().locale;
String displayCountry =  locale.getDisplayCountry();
String country =  locale.getCountry();
String language =  locale.getLanguage();
 
Log.e(" DisplayCountry", displayCountry  );
Log.e(" Country", country  );
Log.e(" Language", language  );

테스트는 알아서...

한국일경우 CAULY
그외 지역일 경우 ADMOB을 표시하기 위함

2011년 11월 22일 화요일

Android - ProgressDialog 표시


private ProgressDialog progressDialog = ProgressDialog.show(context, "", "Please wait...", true, false);


new Thread() {
    public void run() {
    //시간이 오래걸리는 작업

     //Intent i = new Intent(context,ActivitySubject.class);
//context.startActivity(i);

        handler.sendEmptyMessage(0);
    }
}.start();




private Handler handler = new Handler() {
    public void handleMessage(Message msg) {
        loagindDialog.dismiss();
        // View갱신
    }
};


화면(View) 와 관련된 코딩(다이얼로그의 호출과 같은)은 Hanlder를 이용해야 한다.

그렇지 않으면

Can't create handler inside thread that has not called Looper.prepare()

에러가 발생된다.

2011년 11월 4일 금요일

Android - 단체 SMS 전송하기

매우간단함


Intent intent = new Intent(Intent.ACTION_SENDTO,Uri.parse("smsto:" + "수신인번호1;수신인번호2");
intent.putExtra("sms_body", "SMS TEXT");
context.startActivity(intent);

수신인과 수신인 사이 세미콜론 ";" 삽입

Android - eMail 전송하기


Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" + "수신1@gmail.com, 수신2@gmail.com"));
intent.putExtra(Intent.EXTRA_CC, new String[]{"참조1@gmail.com", "참조2@gmail.com"}); //참조
intent.putExtra(Intent.EXTRA_SUBJECT, "TITLE"); //제목
intent.putExtra(Intent.EXTRA_TEXT, "Body"); //본문
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///sdcard/파일")); //첨부파일

context.startActivity(intent);

2011년 9월 27일 화요일

Android - Color를 XML로 정의하여 사용하기

XML에 정의
/res/values/colors.xml


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="color01">#ffff0000</color>
    <color name="color02">#ff00ff00</color>
    <color name="color03">#ff0000ff</color>
    <color name="color04">#ff000000</color>
</resources>





사용하기

<TextView android:id="@+id/textView4" android:text="TextView" android:layout_height="wrap_content" android:layout_width="wrap_content" android:textColor="@color/color01"></TextView>

2011년 9월 21일 수요일

2011년 9월 16일 금요일

Android - onDraw() 가 안먹을때

View 에서는 기본적으로 onDraw가 동작한다.

하지만 View를 RelativeLayout으로 바꿨더니 갑자기 동작하지 않았다.

해결방법은

this.setWillNotDraw(false);

위 코드를 onCreate 에 작성해주면 된다.

2011년 9월 8일 목요일

Android - XML에 배열 정의하여 사용하기

보통의 문자열은

/res/values/strings.xml 파일에 아래와 같이 정의하여 사용한다.


 <string name="app_name">WHOMLI</string>


XML에서 쓸때
@string/app_name


JAVA에서 쓸때
getString(R.string.app_name)



하지만 문자열 배열은??




/res/values/strings.xml 파일에 아래와 같이 정의하여 사용한다.

    <string-array name="planets_array">
        <item>Mercury</item>
        <item>Venus</item>
        <item>Earth</item>
        <item>Mars</item>
    </string-array>



JAVA에서 쓸때
String[] planets = getResources().getStringArray(R.array.planets_array);

Android - view, layout의 사이즈 구하기

바탕화면의 상대좌표를 이용하여 그림을 그리거나, 콤포넌트를 배치하려고 할때 화면, view, layout 의 사이즈를 알아야 하는 경우가 있다.

아래와 같이 코딩해 보지만 원하는 결과값을 얻을 수 없다.



@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main_layout);

        View layoutMainView = (View)this.findViewById(R.id.mainLayout);

        Log.w("Layout Width - ", String.valueOf(layoutMaintView.getWidht()));
        Log.w("Layout Height - ", String.valueOf(layoutMaintView.getHeight()));

    }


=========  Result =========
Layout Width - 0
Layout Height - 0




원인으로는 onCreate 함수는 화면이 그려지기 전에 호출 되는 관계로 onCreate 시 객체의 사이즈를 구할 수 없다.


따라서 onCreate가 아닌 다른 함수에 해당 코드를 작성해야 한다.
그 코드는 바로....

onWindowFocusChanged(boolean hasFocus)



@Override
public void onWindowFocusChanged(boolean hasFocus) {

        View layoutMainView = (View)this.findViewById(R.id.mainLayout);

        Log.w("Layout Width - ", String.valueOf(layoutMaintView.getWidht()));
        Log.w("Layout Height - ", String.valueOf(layoutMaintView.getHeight()));
}


위와 같이 작성하면 올바르게 사이즈를 리턴하는 것을 확인 할 수 있다.

2011년 8월 31일 수요일

Android - Spinner 예제


Spinner - Android 에서 사용하는 콤보 박스

사용 예는 아래와 같다.


gradeList = new ArrayList<String>();

gradeList.add("");
gradeList.add("SUN");
gradeList.add("MON");
gradeList.add("TUE");
gradeList.add("WED");
gradeList.add("THU");
gradeList.add("FRI");
gradeList.add("SAT");

ArrayAdapter<String> arrayAdapterGrade = new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item, gradeList);


arrayAdapterGrade.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);


spnrGrade.setPromptId(R.string.grade);


spnrGrade.setAdapter(arrayAdapterGrade);

(spnrGrade : Spinner)



현재 요일을 자동으로 선택하고 싶다면 아래 코드를 추가 하면 된다.

Calendar c = Calendar.getInstance();
position = c.get(Calendar.DAY_OF_WEEK) // 일요일 - 1, 월요일 - 2, 화요일 - 3 ...
spnrGrade.setSelection(position)

위와같이 setSelection(int position)  함수를 이용하면 된다.




현재 선택된 item 을 알고 싶으면

String todayIs = gradeList.get(getSelectedItemPosition());

와 같이 getSelectedItemPosition() 함수를 이용하면 된다.



2011년 8월 26일 금요일

Android - EditText 값 입력 제어 (TextWatcher 사용)

TextWatcher

사용 목적
 - EditText에 값이 입력되는 경우 입력 값의 유효성을 검증하여 입력할지 말지를 결정 한다거나.
  값이 입력될때 무언가를 해주고 싶을때 사용한다.

기타 자세한 설명은...
http://developer.android.com/reference/android/text/TextWatcher.html
를 참고


설명을 보면 알겠지만 TextWatcher 는 interface로 아래 3개의 method를 가지고 있다.

public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}


@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// TODO Auto-generated method stub
}


@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}



사용 예는 아래와 같다

EditText et = new EditText();
et.addTextChangedListener(new TextWatcher() {

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
Log.w("onTextChanged", s.toString());
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
Log.w("onTextChanged", s.toString());
}

@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
Log.w("onTextChanged", s.toString());
}
});

위와 같이 하면 et 에 값을 입력할때마다 log가 찍힌다.


본인 같은 경우에는 월(month)를 입력받는 EditText를 만들때 사용했다.
1~12월 사이의 숫자만 입력되야 하기 때문에 아래와같이 코딩했다.

TextWatcher를 상속받은 MonthTextWatcher 를 정의하여 제어 함.

//editTextBeginMonth 는 EditText


MonthTextWatcher endWatcher = new MonthTextWatcher(editTextEndMonth);
editTextBeginMonth.addTextChangedListener(beginWatcher);






//month EditText에 12를 초과하는 값이 못들어가게 제어
private class MonthTextWatcher implements TextWatcher{
EditText et;
String beforeText;

public MonthTextWatcher(EditText et){
this.et = et;
}

@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
if(s.toString().length() > 0){
if(Integer.parseInt(s.toString()) > 12){
et.setText(beforeText);
}
}
}


@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// TODO Auto-generated method stub
beforeText = s.toString();
}


@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}

}





2011년 8월 22일 월요일

SQLite - ... has more than one primary key

DB Table ("T_TIMETABLE ") 생성시 에러 발생

table "T_TIMETABLE" has more than one primary key


CREATE TABLE 구문은...


CREATE TABLE IF NOT EXISTS T_TIMETABLE ( subject_id text primary key, day text primary key, begin_tm text primary key, end_tm text primary key )


SQLite 에서 1개 이상의 칼럼을 기본 키로 설정 하고 싶다면

CREATE TABLE 문을 아래와 같이 사용해야 한다.


CREATE TABLE IF NOT EXISTS T_TIMETABLE ( subject_id text, day text, begin_tm text, end_tm text, PRIMARY KEY ( subject_id, day, begin_tm, end_tm) )

Android - Can't upgrade read-only database from version...

아무 문제가 없을거라고 생각했던 프로그램에서 에러가 났다

내가 한거라고는 그냥 DB Table 생성하는 부분만 코딩했을 뿐인데...

에러 내용은

android.database.sqlite.SQLiteException: Can't upgrade read-only database from version 0 to 1: /data/data/....




원인은...

잘못된 CREATE 문 때문이었다.

CREATE TABLE IF NOT EXISTS T_CONFIG ( config_id text primary key, values text, description text, opt1 text, opt2 text, opt3 text )


SQLite에서 values 라는 칼럼명은 허용이 안된다는걸 알게 되었다.



ps .
아래와 같이 수정하니 에러가 사라졌다.

CREATE TABLE IF NOT EXISTS T_CONFIG ( config_id text primary key, vals text, description text, opt1 text, opt2 text, opt3 text )


2011년 8월 10일 수요일

Java - Singleton (Design Pattern)

어떤 시스템에 단 한개의 인스턴스만 존재하는경우 사용

음.... 어떤 시스템의 테마나 설정값 같은경우 서로다른 화면마다 공통된 값을 적용해야 한다.

이럴때 사용하면 좋은게 싱글톤(Singleton) 패턴 이다.

기본적인 구조는...


public class Theme{
   private static Theme theme = new Theme();

   public static Theme getInstance(){
      return theme;
   }
}

이렇게 설정 클래스 정의하고 아래와 같이 사용하면 된다.

public class Main{
   public static void main(String[] args){
      Theme t1 = Theme.getInstance();
      Theme t2 = Theme.getInstance();
   }
}

위에서의 t1, t2는 서로 동일한 객체 이다.

이와같이 Singleton을 사용하여 동일한 객체를 아무데서나 사용 할 수 있다.

불필요한 작업없이 공통적으로 사용될 설정값, 데이터set 등을 싱글톤으로 정의하고 사용하면 편할듯 하다...

2011년 8월 1일 월요일

Android - Custom View 에 xml 로 속성 부여하기, CUSTOM BUTTON

목적
사용자가 정의한 cutom view를 layout xml에서 정의해서 사용할 경우
사용자가 정의한 custom view의 속성에 값을 layout xml 파일에서 설정 할 수 있다.
(음.. 설명이 어렵군..)

예)
ImageButton이 맘에 들지 않아 ImageView를 상속받은 custom button을 만들려고 한다.


다른부분은 별다른 수정없이 사용 가능하지만


ACTION_DOWN, ACTION_UP 시 이미지를 변화시키는 로직을 custom button 안에 구현하고 싶다.


그러기 위해서 custom view 클래스는 평상시 icon과 눌려졌을때(ACTION_DOWN) icon 에 대한 속성값을 가지고 있어야 하고


이 속성들을 이용해서 onTouchListener를 구성해주면 된다.


위에서 언급한 icon들을 class 파일에서 설정해 줄 수 있지만


왠지 코드가 지저분해지는거 같아 layout xml파일에서 해당 속성을 입력해주고싶다.


뭐 이런 상황에서 사용하는 방법이다.

간단하게 설명하면,

추가할 속성값들을 새로운 xml 파일로 정의하고, 정의된 xml 파일을 layout의 namespace에 추가해서 사용하는 형태인데

이것도 말로 하면 복잡하니까 예를 들어 설명하면


1. res/values/attr.xml - 신규작성 : 신규 속성을 정의할 xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomImageButton">
    <attr name="icon" format="integer" />
        <attr name="icon_selected" format="integer" />
    </declare-styleable>
</resources>



2. CustomImageButton.java - custom button 클래스


package jh;

import jh.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

public class CustomImageButton extends ImageView{

private Drawable icon;
private Drawable iconSelected;

public CustomImageButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setTouchEvent();
setIcons(context, attrs);
// TODO Auto-generated constructor stub
}

public CustomImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
setTouchEvent();
setIcons(context, attrs);
// TODO Auto-generated constructor stub
}

public CustomImageButton(Context context) {
super(context);
setTouchEvent();

// TODO Auto-generated constructor stub
}


private void setIcons(Context context, AttributeSet attrs){
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomImageButton);


icon = a.getDrawable(R.styleable.CustomImageButton_icon);
iconSelected = a.getDrawable(R.styleable.CustomImageButton_icon_selected);
}

private void setIconNormal(){
if (icon != null) {
this.setImageDrawable(icon);
}
}

private void setIconSelected(){
if (iconSelected != null) {
this.setImageDrawable(iconSelected);
}
}

private void setTouchEvent(){
this.setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() == MotionEvent.ACTION_DOWN){
setIconSelected();
}else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_OUTSIDE){
setIconNormal();
}

return false;
}
});
}

}




3. res/layout/subject.xml - layout 파일

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/jh"
android:layout_width="fill_parent"
    android:layout_height="fill_parent" android:background="#fffbfbfb">
 
    <LinearLayout
    android:id="@+id/contentLayout"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
     >
     
        <LinearLayout android:layout_height="wrap_content" android:id="@+id/linearLayout2" android:layout_width="match_parent">
            <Spinner android:layout_height="wrap_content" android:id="@+id/spinner1" android:layout_weight="1" android:layout_width="wrap_content"></Spinner>
         
            <jh.project.whomli.school.custom.CustomImageButton app:icon="@drawable/utilicon_add" app:icon_selected="@drawable/utilicon_add_selected" android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="@+id/subjectBtnAdd" android:src="@drawable/utilicon_add" android:layout_weight="0" android:clickable="true"></jh.project.whomli.school.custom.CustomImageButton>
        </LinearLayout>

    </LinearLayout>

</RelativeLayout>




뭐 이런식으로 사용하면 된다.

뭔가 단순하면서도 유용할듯하다.

2011년 7월 31일 일요일

Android - DDMS 인식 오류, Devices 인식 못함

증상

안드로이드 스마트폰을 PC와 연결하였으나 기기 인식을 못한다.

1. 안드로이드 폰의 "설정 > 애플리케이션 > 개발 > USB디버깅"은 당연히 체크 상태이다.
2. USB 케이블에는 아무 이상이 없다.


해결방법

1. USB 드라이버가 제대로 설치되어 있는지 확인한다.
 - 제어판 에 있는 장치관리자로 이동하여 Android Phone 가 제대로 인식되어 있는지 확인한다.
 - 제대로 인식되지 않고 느낌표(!)가 떠 있다면 드라이버를 설치해줘야 한다.
 - 드라이버는 android-sdk 폴더 > extras > google > usb_driver 폴더에 있다.

2. 드라이버도 제대로 설치되어 있는데 안되면, adb 프로세스를 재 시작 한다.
 - adb kill-server 로 프로세스를 종료시키고
 - adb devices 로 프로세스를 재 시작한다.

3. 드라이버도 설치되어있고 adb 프로세스 재 시작 해도 안되면 리부팅한다.


2011년 7월 28일 목요일

Android - 이벤트시 icon 변경 (Selector 이용)

사용자 정의 버튼이나 이미지 버튼을 만드는 경우

버튼이 눌러지거나, 포커스를 받는경우

아이콘 모양을 변경시켜 이벤트가 발생함을 표시할 필요가 있다



예) 평소 왼쪽과 같은 상태이지만 터치나, 포커스를 받는 이벤트가 발생할 경우 오른쪽 모양처럼 변한다.

  -터치, 포커스->
                                        menuiconsubject.png                           menuiconsubjectselected.png
                                 


이럴경우 Selector 라는 놈을 사용한다.


기본적인 파일 위치와 정의는 아래와 같이 한다.

res/drawable/menu_item_subject.xml

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

<selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:dither="true">

    <item android:state_pressed="true" android:drawable="@drawable/menuiconsubjectselected" />
    <item android:state_focused="true" android:drawable="@drawable/menuiconsubjectselected" />
    <item android:drawable="@drawable/menuiconsubject" />

</selector>



정의된 selector를 사용하는 방법은 아래와 같다.

<ImageView
android:id="@+id/icon" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content"  android:clickable="true" android:src="@drawable/menuiconsubject"/>


2011년 7월 26일 화요일

Android - 화면회전시 layout 설정, 다국어 설정

가로 화면방향에 대응하는 Layout은 layout-land 폴더(기본은 layout 폴더)에 작성한다고 알고있다.

아래 그림처럼 동일한 이름의 xml로 서로 다른(가로방향, 세로방향) Layout을 구성하면

보통상태일때 main.xml Layout을 사용하다가 화면을 회전시키면 layout-land 폴더에 있는 main.xml Layout을 사용하게 된다.





이와 같은 방법으로 여러가지 언어로 작성하여 다국어 지원이 가능한 어플을 만들 수도 있다.

방법은 values 폴더의 string.xml  파일을 이용하는것으로 가능하다. 

기본 언어는 values 폴더, 기타 지정된 언어는 values-"언어코드" 폴더를 만들어서 작업을 해주면된다. (예. 한글 - values-ko,  영어- values-en,  일어 - values-ja,  중국어 - values-cn)

아래와 같이 구성하면 기본적으로 영어로 나오고, 시스템 언어가 한글로 설정된 기기에서는 한글로 표시된다.






2011년 7월 24일 일요일

Android - 개발환경 세팅

Android 세팅은 크게


  1) JAVA 설치
  2) ECLIPSE 설치
  3) 안드로이드 SDK설치
  4) ADT Plugin for Eclipse 설치


순으로 실시 한다.


※ JAVA 와 ECLIPSE가 설치되어 있다면 패스해도 무관하다.



1) JAVA 설치
1. http://www.oracle.com/index.html -> Downloads -> Java SE 이동
   그냥 http://www.oracle.com/technetwork/java/javase/downloads/index.html 로 이동하여 JDK 를 다운로드 한다.


2. 다운로드된 실행파일 설치

3. 제어판 > 시스템 및 보안 > 시스템 > 고급 시스템 설정 > 환경변수

4. JAVA_HOME 설정 - 설치 java 폴더 (ie. C:\Program Files\Java\jdk1.6.0_26)
   시스템 변수 밑에 "새로만들기"버튼 > 변수 이름 "JAVA_HOME", 변수 값 설치폴더"C:\Program Files\Java\jdk1.6.0_26"

5. path설정 ";%JAVA_HOME%\bin" 추가

6. CLASSPATH 설정 ";%JAVA_HOME%\lib\tools.jar" 추가



2) eclipse org
1. www.eclipse.org 이동

2. download



3. 설치가 필요없이 압축만 풀면 끝, 원하는 폴더로 압축파일 이동 후 압축 풀기



3) 안드로이드 SDK설치
1. http://developer.android.com/sdk/index.html 이동 > os에 맞는버전 다운로드


2. 설치하고 싶은 폴더로 이동 후 압축 풀기



4) ADT Plugin for Eclipse 설치
1. eclipse 실행 > Help > Install New Software 이동

2. Add 버튼 > Name : "android ADT", Location : "https://dl-ssl.google.com/android/eclipse/"




3. eclipse 재 시작 후 에러 발생 (에러는 발생하지 않을 가능성이 더 큼)


4. Window > Preferences > Android 선택 > SDK Location 설정(에러는 발생하지 않을 가능성이 더 큼)


5. Help > Check for Updates

6. Window > Android SDK and AVD Manager

7. Available packages > 원하는 버전 선택 후 Install Selected > Eclipse 재시작

8. Virtual devices 는 입맛에 맞게 (os버전, 화면크기) 알아서 생성


2011년 7월 20일 수요일

etc - 무료 Icon

서핑중 좋은 Free Icon 사이트를 발견했다.

http://www.iconfinder.com/

자기가 원하는 아이콘을 검색할 수 도 있고 디자이너나 그룹별로 아이콘을 구경할 수도 있다.

png, ico 두가지 형식을 제공하며

매우 다양한 사이즈를 제공하지만 아이콘마다 제공하는 사이즈는 조금씩 다르다.

무엇보다 가장 좋은점은 License에 대해 명확히 기술하였다.

사실 무료 아이콘들은 많으나 상용 목적으로 사용해도 되는지 애매한적이 많아서 처음부터 쳐다도 안본 경우가 많았는데 그런 문제점이 없다.

Free for commercial use 또는 GPL 이라고 명시된 icon 들은 모두 무료로 마음껏 사용해도 된다. (..라고 알고있다.)

어플을 개발할때 더 이상 아이콘 그린다고 낑낑대지 않아도 훨씬 멋있고 깔끔한 icon들을 사용 할 수 있게 되었다.

깔끔하고 멋진 icon들이 한가득~

2011년 7월 7일 목요일

etc - Canvas Rider


CANVAS RIDER

can play GOOGLE CHROME BROWSER (APP)


draw and upload your own track

enjoy BMX !!!!



2011년 7월 2일 토요일

Android - 소스상태에서 에러가 없던 어플이 apk파일로 Export후 에러가 날때

에러 : nullpointerexception

원인 : aidl을 사용할 경우 proguard를 이용하면 발생할 수 있다.

해결 방법
 progaurd.cfg 파일을 열어 해당 aidl 파일에 대한 옵션을 걸어줘야 한다.



-keep public interface [interface]

예)
-keep public interface jh.project.widget.digital.biorhythm.service.IBiorhythmClockService





keep 옵션 외에도
keepclassmembers
keepclasswithmembers
등과 같은 옵션들이 많이 있다.


자세한 내용은 http://proguard.sourceforge.net/ 에 가서 확인을...

2011년 6월 29일 수요일

Java - 날짜 검증법

날짜를 String 값으로 받아서 Date 형식으로 변환했을때 exception 이 발생하지 않으면 정상 발생하면 비정상

SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
sdf.setLenient(false); //정확한 해석을 위해

try{
  //형식 맞음
}catch(Exception e){
 //형식 틀림
}

2011년 6월 24일 금요일

Android - Custom Font 적용

폰트파일위치 - assets/fonts

소스
Typefact tf = Typeface.createFromAsset(getAssets(), "fonts/폰트파일명");
TextView tv = (Textview) findViewById(R.id.CustomFont);
tv.setTypeface(tf);


이렇게 해주면 해당 폰트가 적용이 된다~

2011년 6월 20일 월요일

Android - Activity에서 Service 호출하기

상황
어느 Activity 에서 특정 이벤트를 발생 시켰을때 자신이 생성한 Service를 호출 하고 싶은경우

예) 위젯 설정 Activity에서 위젯의 바탕화면 이나, 폰트 등을 설정하였을경우 이게 바로 위젯으로 적용되었으면 하는 경우


Activity와 Service와 호출 하기 위해 aidl 이란걸 사용한다.

1. aidl 정의 (jh/project/widget/digital/biorhythm/IBiorhythmClockService.aidl)


package jh.project.widget.digital.biorhythm;

interface IBiorhythmClockService {
void updateWidgetIF();
}



2. Service에서 aidl Interface 구현, onBind 구현

package jh.project.widget.digital.biorhythm;

public class BiorhythmClockService extends Service{
    ...
    ...
    ...
    public class BiorhythmClockServiceImple extends IBiorhythmClockService.Stub {
@Override
        public void updateWidgetIF() throws RemoteException {
readAgain = true;
updateWidget();
        }
    }

    public IBinder onBind(Intent intent) {
    return new BiorhythmClockServiceImple();
    }

    private void updateWidget() {
       //Do Something
    }
    ...
    ...
    ...
}



3. Activity에서 해당 Interface 호출

package jh.project.widget.digital.biorhythm;

public class Configuration extends{

//Interface, ServiceConnection 정의
private IBiorhythmClockService biorhythmClockService = null;
private ServiceConnection biorhythmClockConn = new ServiceConnection() {
public void onServiceDisconnected(ComponentName p_name) {
biorhythmClockService = null;
}

public void onServiceConnected(ComponentName name, IBinder service) {
biorhythmClockService = IBiorhythmClockService.Stub.asInterface(service);
//callService();
}
};
      
        //binding 시작
protected void onStart() {
super.onStart();
bindService(new Intent(IBiorhythmClockService.class.getName()), biorhythmClockConn, Context.BIND_AUTO_CREATE);
}

        //binding 종료
protected void onStop() {
super.onStop();
unbindService(biorhythmClockConn);
}

//Interface 함수 호출하는 함수
private void callService() {
try {
biorhythmClockService.updateWidgetIF();
} catch(RemoteException e) {
Toast toast = Toast.makeText(this, "ERROR - " + e.getMessage(), Toast.LENGTH_SHORT);
toast.show();
}
}

// 뭔가 이벤트가 발생하면 위에서 만든 함수를 실행해서 Service에 함수를 호출한다.
//(Configuration.onClick() -> Configuration.callService() -> IBiorhythmClockService.updateWidgetIF() -> BiorhythmClockService.updateWidget() 순으로 실행된다.)

public void onClick(View v) {
...
...
...
callService();
...
...
...
}

}


※ 알고있는것을 말, 글로 표현한다는건 엄청 어려운일.
혹시 추가 코멘트나, 잘못된 정보 지적등 댓글 받습니다.

2011년 6월 14일 화요일

Item - 학교종이 땡땡땡

학교 생활에 필요한것들

시간표 (위젯)
과목관리(시험일정, 과제, 기타사항)
조원 관리(단체문자)
중요 메모(위젯)

또 뭐가 있을까...

Android - 어느 Widget에서 Configuration (Activity)를 호출하였나?

위젯을 생성할때 설정 화면(activity) 로 넘어가서 필요 한 데이터들을 설정한 다음에 위젯을 생성하는 경우가 있다.

manifast에

<activity android:name=".Configuration" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


그리고 앱 위젯 프로바이더에

<appwidget-provider
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="294dip"
    android:minHeight="146dip"
    android:initialLayout="@layout/biorhythm_clock_widget"
    android:configure="jh.project.widget.digital.biorhythm.Configuration"/>

이렇게 설정 해주면 된다.

하지만 다양한 종류의 위젯에서 하나의 설정 화면을 호출하는경우, 필요에 따라서 어느 앱 위젯 프로바이더에서 설정 화면을 호출하였는가가 중요할 때도 있다.

이런 경우에는

설정 화면(activity)의 onCreate(Bundle savedInstanceState) 함수 안에


Intent intent = getIntent();
Bundle extras = intent.getExtras();
   if (extras != null) {
    widgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,AppWidgetManager.INVALID_APPWIDGET_ID);


      AppWidgetManager manager = AppWidgetManager.getInstance(this);
      String className = manager.getAppWidgetInfo(widgetId).provider.getClassName();
    }
해주면 어느 프로바이더를 통해서 해당 activity가 호출 되었는지 알 수 있다.

2011년 6월 8일 수요일

Java - 1000 단위마다 콤마(,) 삽입하는 펑션

public static String insertComma(String arg){
int j = 0;
String rtnValue = new String();

for (int i = arg.length() - 1 ; i >= 0; i--){
j++;

rtnValue = arg.charAt(i) + rtnValue;
if(i > 0){
if(j == 3){
rtnValue = "," + rtnValue;
j = 0;
}
}
}

return rtnValue;
}

2011년 6월 7일 화요일

SQLite - Date, Time Functions

Functions
date( timestring, modifier, modifier, ...)
time( timestring, modifier, modifier, ...)
datetime( timestring, modifier, modifier, ...)
julianday( timestring, modifier, modifier, ...)
strftime( format, timestring, modifier, modifier, ...)


timestring

YYYY-MM-DD
YYYY-MM-DD HH:MM
YYYY-MM-DD HH:MM:SS
YYYY-MM-DD HH:MM:SS.SSS
YYYY-MM-DDTHH:MM
YYYY-MM-DDTHH:MM:SS
YYYY-MM-DDTHH:MM:SS.SSS
HH:MM
HH:MM:SS
HH:MM:SS.SSS
now
DDDD.DDDD

modifier

NNN days
NNN hours
NNN minutes
NNN.NNNN seconds
NNN months (see #551 and [1163] )
NNN years (see #551 and [1163] )
start of month
start of year
start of week (withdrawn -- will not be implemented)
start of day
weekday N (see #551 and [1163] )
unixepoch
localtime
utc



현재의 날짜를 알고 싶으면
select date('now');

현재 기준 20일 후의 날짜를 알고 싶으면
select date('now', '20 days');


현재 기준 20일 이전의 날짜를 알고 싶으면
select date('now', '-20 days');

이렇게 조회를 하면 'YYYY-MM-DD' 형태로 조회가 된다.

특정한 양식으로 조회 결과를 얻는다던가, 아니면 일자, 월, 년도만 따로 조회를 하고 싶다면, strftime을 사용하면 된다.

strftime 함수의 format 파라미터에 아래 파라 미터들을 조합해서 원하는 형태로 날짜, 시간을 조회 할 수 있다.

%d  day of month
%f  ** fractional seconds  SS.SSS
%H  hour 00-24
%j  day of year 001-366
%J  ** Julian day number
%m  month 01-12
%M  minute 00-59
%s  seconds since 1970-01-01
%S  seconds 00-59
%w  day of week 0-6  sunday==0
%W  week of year 00-53
%Y  year 0000-9999
%%  %

현재 일시를 'YYYY/MM/DD HH24:MI' 형태로 조회하고 싶다면
select strftime('%Y/%m/%d %H:%M', 'now');


2011년 6월 3일 금요일

Android - Custom ListView

use LayoutInflater


LayoutInflater


This class is used to instantiate layout XML file into its corresponding View objects. It is never be used directly -- usegetLayoutInflater() or getSystemService(String) to retrieve a standard LayoutInflater instance that is already hooked up to the current context and correctly configured for the device you are running on.
(http://developer.android.com/reference/android/view/LayoutInflater.html)



아래 구성 요소들이 필요하다
1. LIST를 구성하는 ROW의 LAYOUT FILE(layout 폴더에 위치, XML)
2. LIST의 내용이 되는 데이터 클래스
3. LIST에 VIEW를 제공하는 ArrayAdapter 상속 클래스



각각 파일 예제


1. ROW의 LAYOUT(layout/add_row.xml)


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:minHeight="60dp"
android:orientation="horizontal"
>
    <LinearLayout android:layout_marginRight="10dp"
          android:layout_height="wrap_content"
          android:id="@+id/linearLayout2"
          android:layout_marginBottom="10dp"
          android:layout_marginTop="10dp"
          android:layout_width="fill_parent"
          android:orientation="horizontal">
        <ImageView android:src="@drawable/icon"
                  android:id="@+id/list_view_row_add_row_icon"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_gravity="center_vertical"></ImageView>
        <TextView android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:id="@+id/list_view_row_add_row_name"
                  android:text="name"
                  android:layout_gravity="center_vertical"
                  android:textSize="25dp"
                  android:paddingLeft="5dp"></TextView>
    </LinearLayout>

</LinearLayout>

2. DATA 클래스(ActionDTO.java)

import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.view.View.OnClickListener;

public class ActionDTO {

private Drawable icon;
private String title;

public Drawable getIcon() {
return icon;
}
public void setIcon(Drawable icon) {
this.icon = icon;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}


3. ArrayAdapter(AddListViewAdapter.java)


import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class AddListViewAdapter extends ArrayAdapter<ActionDTO>{
private Context context;
private int layout;
private ArrayList<ActionDTO> actionList;
private LayoutInflater layoutInflater;


public AddListViewAdapter(Context context, int textViewResourceId, ArrayList<ActionDTO> objects) {
super(context, textViewResourceId, objects);
// TODO Auto-generated constructor stub
this.context = context;
this.layout = textViewResourceId;
this.actionList = objects;
                //LayoutInflater 생성
this.layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ActionDTO action = actionList.get(position);

if(convertView == null){
                        //xml 파일로 정의된 layout 을 View 클래스로 변환
convertView = layoutInflater.inflate(layout, null);
}

if(action != null){
                        //convertView 라는 View 오브젝트를 이용해서 각각의 콤포넌트를 컨트롤
TextView tvName = (TextView) convertView.findViewById(R.id.list_view_row_add_row_name);
ImageView imgIcon = (ImageView) convertView.findViewById(R.id.list_view_row_add_row_icon);

tvName.setText(action.getTitle());
imgIcon.setImageDrawable(action.getIcon());
}

return convertView;
}
}



4. 실제 사용 예제


//listview, arraylist, adapter 초기화
ListView lstActionList = (ListView)findViewById(R.id.list_add);
ArrayList<ActionDTO> arrActionList = new ArrayList<ActionDTO>();
AddListViewAdapter adptActionList = new AddListViewAdapter(this, R.layout.add_row, arrActionList);

//adapter 세팅
lstActionList.setAdapter(adptActionList);

//list의 내용을 채울 ArrayList 작성

res = this.getResources();
ActionDTO action = new ActionDTO();
action.setTitle("ADD");
action.setIcon(res.getDrawable(android.R.drawable.ic_input_add));
arrActionList.add(action);

//listview refresh(?)
adptActionList.notifyDataSetChanged();


Android - Icon Size



ldpi (120 dpi)
(Low density screen)
mdpi (160 dpi)
(Medium density screen)
hdpi (240 dpi)
(High density screen)
xhdpi (320 dpi)
(Extra-high density screen)
Launcher Icon Size36 x 36 px48 x 48 px72 x 72 px96 x 96 px



Download the Icon Templates Pack for Android 4.0

from http://developer.android.com/guide/practices/ui_guidelines/icon_design.html