2012년 11월 29일 목요일

홈 키(Home key)로 인한 콜백 메서드 호출 순서






홈 키(Home key)로 인한 콜백 메서드 호출 순서
HomeKey로 인한 호출의 경우 함수가 호출되는 순서가
onUserLeaveHint() ⇒ onPause() 의 순서가 된다.

따라서 홈키가 눌려졌는지를 확인할려면 onUserLeaveHint()에서 플래그 하나를 설정해 주고 onPause()에서 그 플래그를 확인하는 작업을 한다면 Home key가 눌려졌을 때를 알수가 있다.

HttpURLConnection에 대한 개괄적 개념






HttpURLConnection은 인터넷을 통해 원격의 서버에 연결하는 전문 클래스인데 연결 상태를 확인하게 해 주는 전문 클래스로 정리하면 되겠다. 
이때 연결 상태를 알수 있는 메소드는

getResponseCode()와 getResponseMessage()이다.

HttpURLConnection 객체를 얻는 방법은 URL의 메소드인 openConnection()으로 얻어낼 수 있다.

URL url = new URL("http://www.naver.com");
HttpURLConnection con = (HttpURLConnection)url.openConnection();

안드로이드 버전 3.0 이상에서 UI Thread에서 인터넷 연결시 runtime 에러 안 나게 하는 법





안드로이드 버전 3.0 이상에서 UI Thread에서 인터넷 연결시 runtime 에러 안 나게 하는 법

 if (android.os.Build.VERSION.SDK_INT > 9) {
      StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
      StrictMode.setThreadPolicy(policy);

안드로이드 버전 3.0 이상부터는 인터넷 연결은 쓰레드나 핸들러에서 처리하도록 정책이 바뀌었다. 그래서 UI 쓰레스에서 인터넷 연결을
시도하면(HttpURLConnection과 같은 것으로) 실행 타임에서 에러가 발생한다. 그런데 위와 같은 코드를 인터넷 연결을 시도하는 코드 앞에
표시해 두면 안드로이드 버전 3.0 이상에서도 정상적으로 잘 실행이 된다. 
그런데 위 코드를 인터넷을 연결하는 곳 앞에 하지 않고 onCreate()에 다음과 같이 해도 가능하다. 우와 놀랍다. 

    @Override
    public void onCreate(Bundle savedInstanceState) {
     if (Build.VERSION.SDK_INT > 9){
     StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
     StrictMode.setThreadPolicy(policy);
     }
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.get_signature_from_toodledo);
        
        txt = (TextView)findViewById(R.id.txt);
    }





xml의 layout_gravity에 대한 숨겨진 규칙






xml의 layout_gravity에 대한 숨겨진 규칙

안드로이드 앱 개발을 하다보면 xml 레이아웃 파일에서 조정하는 작업들이 생각처럼 잘 안 먹혀 들어갈 때가 있다.
특히 layout_gravity에 대해 작업할 때 그런 경험을 자주 하게 된다.

그 이유는 이런 개념 때문이다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <Button
           android:id="@+id/btnPlus"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:padding="10dip"
           android:text=" 테스트 "
           android:layout_gravity="center"
           android:textSize="25sp" />
</LinearLayout>

LinearLayout의 orientation이 vertical일 경우 
Button의 layout_gravity는 수평 관련 속성만 적용이 된다.
예를 들어 layout_gravity="left" 혹은 center_horizontal 혹은 right와 같이 수평 관련 속성만 적용이 된다.
수직 관련 속성은 적용이 안된다. 
예를 들어서 layout_gravity="bottom", 혹은 top...은 적용이 안된다.

만일 orientation이 horizontal이라면 
Button의 layout_gravity는 수직 관련 속성만 적용이 된다.
bottom, top, center_vertical

이 이야기의 핵심은 LinearLayout에서 첫 번째 방향을 설정했으면(만일 수평이면) 두 번째 방향 설정(layout_gravity)에서는 수평인 상태에서 그 수편 중 어느 위치로 움직일 것인지를 결정하는 것만 허용이 된다는 것이다. 
즉 수평이 첫 번째 설정 값이면(LinearLayout에서) 그 수평 중 top에 놓일지, bottom에 놓일지, center_vertical에 놓일지만 결정한다는 뜻이다.

2012년 11월 22일 목요일

Context에 대한 이해





Context를 이해하는 걸 다들 어려워 한다. 질문글에 답을 달다가 갑자기 정리가 깔끔하게 되서....

하나의 application이 실행되기 위해서는 그 밑바탕에 깔려져야 하는 많은 정보들과 환경들이 필요하다. 
그 정보들과 환경들을 안드로이드 시스템이 제공해 준다.
application 실행을 위해 밑바탕에 깔려져 있는 정보들과 환경들을 Context라 한다.
따라서 이 Context에는 안드로이 시스템이 제공해주는 유용한 많은 정보들이 있다.
따라서 이 Context를 통해서 안드로이드 시스템이 제공해주는 많은 유용한 정보들을 
꺼집어 낼수 있다(getSystemService() 메소드로).

근데 Context를 필요로하는 곳에 Activity 객체인 this를 념길수 있는 이유는  
Activity가  Context를 상속 받았기 때문에 Activity는 Context의 모든 정보를 가지고 있는 것이이다. 
그래서 Context를 필요로 하는 곳에서 Activity의 객체를 넘길수 있는 것이다.

Context를 얻을 수 있는 몇 가지 방법
-. Activity 객체를 통해서. Activity 객체 자체가 Context이기도 하기 때문에 Context를   
   필요로하는 곳에 Activity 객체인 this를 사용하면 된다.
-. View의 객체가 있으면 View의 getContext()를 통해서. View의 객체가 없는 상황이면 
   View v = new View(activity.this);로 만들면된다. 이때 View를 전역적으로 선언하면
   된다.
-. Context 클래스의 getApplicationContext()를 통해서
이정도면 Context를 못 구할 일이 별로 없을 것이다.

이클립스에서 변수명 한번에 모두 바꾸기





현재 자바 소스에 있는 특정 변수명을 변경할 경우 소스가 클 경우 다소 복잡한 작업이 된다. 이 문제를 한번에 해결하는 단축키가 이클립스에서 제공한다.


alt-shift-r : 변수명 변경(이 변수를 사용한 모든 곳의 변수를 모두 바꿈)

바꾸고자 하는 변수명에 커서를 둔 상태에서 alt-shift-r을 누른 후 변경하면 이 변수를 사용하는 모든 곳의 변수를 모두 바꾼다.
아주 유용한 팁이다.

이클립스에서 소스코드 앞에 라인넘버 숫자 붙이기





이클립스로 개발시 소스 코드에 라인 번호가 붙여지는 건 매우 필요하고 요긴하다.
근데 이클립스의 디폴트가 코드의 라인 번호가 안 붙여지는 것으로 되어 있다.
해법은, 

Window  ⇒  Pereference  ⇒  General  ⇒  Editors  ⇒  Text Editors 
  ⇒  Show line numbers를 체크 표시


지역변수에 final이 붙을 때의 의미에 대해(Cannot refer to a non-final variable 문제)





지역변수에 final이 붙을 때의 의미에 대해

만일 아래 코드에서 mText에 final이 붙지 않은 상태에서  
layout.setOnTouchListener()에서 mText를 사용하고자 하면
컴파일 단계에서 아래와 같은 에러가 발생한다.

Cannot refer to a non-final variable mText inside an inner class defined in a different method

이유가 뭘까? 같은 onCreate() 메소드 안에 있는 변수인데...?
그 이유는...

public class AAAActivity extends Activity  {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        final TextView mText = (TextView)findViewById(R.id.textV);
        
        LinearLayout layout = (LinearLayout)findViewById(R.id.linear);
        layout.setOnTouchListener(new View.OnTouchListener() {
          public boolean onTouch(View v, MotionEvent e) {
              mText.setText("Touched"); //에러 발생
                return true;
          }
        });
    }


  • mText는 전역변수도 아니고, onTouch()의 지역 변수도 아니며 onCreate()의 지역 변수로 선언되어 있다.
  • 리스너인 onTouch()는 onCreate()에 속한 지역 메서드가 아니라는 점을 주의해야 한다. onCreate()가 실행시에 onTouch()가 같이 실행되는 것이 아니라 터치 이벤트 발생시 실행할 메스드로 등록만 할 뿐이다.
  • 에러가 발생하는 이유는 mText 변수는 onCreate()가 리턴되면 사라지는 지역 변수이다.  반면 onTouch()는 터치 리스너로 등록되며 onCreate()가  리턴된 후에라도 이벤트가 발생하면 언제든지 호출될 수 있다. onTouch()가 호출되었을 때는 mText 변수가 존재하지 않으므로 mText의 실제값을 참조할 길이 없다. 미래에 호출될 리스너에게 현재의 지역 변수값을 전달하는 것은 불가능하다.
  • 그런데 여기서 지역 변수에 final을 붙이면 더 이상 변경할 수 없는 상수가 되므로 onTouch()를 등록하는 시점에 그 값을 분명히 전달할 수 있다. 

영어 발음기호와 같은 특수문자 나올수 있게 하는 arial.ttf 폰트 지정하는 법





        EditText engW = (EditText)findViewById(R.id.engWordUser);
      
        ... 중간 생략 ...
       
        //발음기호와 같은 특수문자가 EditText에 정상적으로 보이도록 하는 기능.
        //사전에 assets/fonts폴더를 만들어서 arial.ttf 폰트를 복사해 놓아야 함.
        Typeface face = Typeface.createFromAsset(getAssets(), "fonts/arial.ttf");
        engW.setTypeface(face);