2014년 9월 22일 월요일

[JH Project] 쉽고 편리하게 여행검색을 하자 투어투비 (TourToBee)

여행 상품을 검색할때 다양한 상품을 검색 하기 위해 수 많은 여행사 사이트를 돌아 다니면서 하나씩 검색하는 일은 힘들고 시간이 많이걸린다.

하지만 투어투비 사이트를 이용하면 다양한 여행사 (하나, 모두, 온라인 투어, 노랑풍선)의 여행 상품을 한 화면에서 다 검색 해 볼 수 있다.

사용방법도 간단하고 결과도 매우 정확한 편인듯 하여, 여행, 관광, 허니문 상품을 조회하기에 정말 유용할 것으로 생각 된다.


요기서 검색하면

아래와 같이 결과가 나온다.
다양한 조건으로 조회 할 수 있어 유용하게 사용 할 수 있을 것 같다.

2012년 2월 9일 목요일

Android - [PROJECT] WHOLI School


바쁜 학교생활 유용하게 사용할 수 있는 어플


=== Update ===
ver. 1.10

시간표 위젯!! - 시간표를 편하게 확인하세요


현재 요일 현재 시간이 표시되어 확인하기 편리합니다.








=== 핵심 기능 ===
학기, 과목 관리 - 한눈에 전체 학기 정보를 확인 가능. 학기별 과목관리가 쉽고 편리함.
시간표 - 과목별 색을 지정하여 한눈에 확인 가능.
학점관리 - 손쉽게 전체 과목에 대한 학점관리 가능.
메모 - 간단한 내용을 쉽게 메모.
그룹 관리 - 조별활동을 위한 그룹을 설정, 전체 SMS, eMail 송신 가능.




Useful application for busy school life



=== Update ===
ver. 1.10
Timetable Widget - Convenient and easy to check timetable



=== Key features ===
Semester, course management - You can check entire semester information easily. Convenient and easy to manage semester courses.
Timetable - Subjects can be easily identified by specifying a color.
Grade management - Grade for the entire course can be managed easily.
MEMO - Memo simple content easily
Group management - You can set groups for group activity and send SMS, eMail to group members.

=== Keywords ===
school, college, study, student, semester, course, grade, grade calculator, group, timetable, memo, 학교, 대학교, 학기, 학점, 학점계산기, 그룹관리, 그룹, 메모, 시간표


https://play.google.com/store/apps/details?id=jh.project.whomli.school 







     


     

     

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 프로세스 재 시작 해도 안되면 리부팅한다.