Android2012. 1. 9. 13:43
[목표]
Activity 에 ImageView를 추가하고, ImageView를 클릭했을 때, onTouch 이벤트를 받는다.
이벤트는  ACTION_DOWN, ACTION_UP, ACTION_MOVE를 받아야 한다.

ImageButton이 아닌, ImageView 를 하나 만든다.

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    android:orientation="vertical" >

    <imageview
        android:id="@+id/iv_facebook"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@drawable/img_facebook"
        android:contentdescription="@string/todo" >
    </imageview>

</linearlayout>


화면에 보여줄 이미지뷰에 onTouch 리스너를 등록하고 각각의 메시지를 받으면 로그를 찍어본다.
public class OnTouchDemoActivity extends Activity implements OnTouchListener {
    @Override
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		ImageView ivFacebook = (ImageView) findViewById(R.id.iv_facebook);
		ivFacebook.setOnTouchListener(this);
	}
    
	@Override
	public boolean onTouch(View v, MotionEvent event) {
		
		int action = event.getAction();
		int id = v.getId();
		
		if(action==MotionEvent.ACTION_DOWN) {
			if(id == R.id.iv_facebook) {
				Log.d("TAG", "OnTouch : ACTION_DOWN");
			}
        }
        else if(action==MotionEvent.ACTION_UP){
        	if(id == R.id.iv_facebook) {
        		Log.d("TAG", "OnTouch : ACTION_UP");
    		}
        }
        else if(action==MotionEvent.ACTION_MOVE){
        	if(id == R.id.iv_facebook) {
        		Log.d("TAG", "OnTouch : ACTION_MOVE");
    		}
        }
		return false;
	}
}



[문제점]
이미지 버튼을 아무리 클릭해도, 위와 같이 ACTION_DOWN 메시지만 불려지고, UP, MOVE 메시지는 발생하지 않는다.

[해결책]
ImageView의 속성 중 "clickable"속성을 켠다(On).

ImageView ivFacebook = (ImageView) findViewById(R.id.iv_facebook);
ivFacebook.setOnTouchListener(this);
ivFacebook.setClickable(true);  // If you set this, you can get all the touch-actions
 또는,
<imageview
    android:id="@+id/iv_facebook"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="@drawable/img_facebook"
    android:clickable="true"
    android:contentdescription="@string/todo" >
</imageview>


이후에는 DOWN, MOVE, UP 순서로 메시지들이 전달되는 것을 알 수 있다.



[전체소스]
    다운로드 


Posted by 데브로망스
Android2011. 9. 22. 23:28

Activity를 이것 저것 띄우고 닫고 하다보면, 과연 내가 잘 하고 있나? 불안할 때가 있다.
더구나, 인텐트에 액티비티 관련 플래그를 사용하기 시작하면 그 불안감은 고조된다.

실제로 단 3개의 Activity가  destroy()되지 않은 채, 19개가 되는 현상을 겪었다. -0-a
물론, Activity의 생명주기를 로그로 찍어서 확인하는 것도 좋겠지만,
그래도 딱! Activity Stack의 모습을 볼 수 있으면 좋겠다는 생각에 방법을 찾아봤다.


* 방법 : 커멘드 창에서 "adb shell dumpsys activity" 실행

매우 긴 영문들이 뒤섞여 보인다.
처음에는 매우 난감했지만, Activity를 이래저래 띄우면서 테스트 한 결과에 의하면,
"Activity Stack"과 "Running Activities" 부분을 보면 된다.

"Activity Stack"에는 스택 순서대로 Hist #2, Hist #1, Hist #0 순으로 표기되어 있다.
즉, 단말기의 [이전]버튼을 누르면 ActivityA가 닫히고, 한 번 더 누르면 MainActivity가 닫힌다.

작업하는 중간중간에 다시 실행시켜보면, 정확히 화면에 보이는 Activity가 "Activity Stack" 로그의 최상위에 보여지게 된다.

Hist #0는 보통 안드로이드 런처(홈) Activity이다.



C:\Users\Juno>adb shell dumpsys activity


   ... 중략 ...

  

  Activity stack:

  * TaskRecord{461e6d10 #42 A com.juno.activitytest}

    clearOnBackground=false numActivities=2 rootWasReset=false

    affinity=com.juno.activitytest

    intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.juno.activitytest/.MainActivity}

    realActivity=com.juno.activitytest/.MainActivity

    lastActiveTime=6762895 (inactive for 6s)

    * Hist #2: HistoryRecord{46096400 com.juno.activitytest/.ActivityA}

        packageName=com.juno.activitytest processName=com.juno.activitytest

        launchedFromUid=10026 app=ProcessRecord{461537b0 1050:com.juno.adpd.activitytest/10026}

        Intent { flg=0x20000000 cmp=com.juno.activitytest/.ActivityA (has extras) }

        frontOfTask=false task=TaskRecord{461e6d10 #42 A com.juno.livepoint}

        taskAffinity=com.juno.activitytest

        realActivity=com.juno.activitytest/.ActivityA

        base=/data/app/com.juno.activitytest-1.apk/data/app/com.juno.activitytest-1.apk data=/data/data/com.juno.activitytest

        labelRes=0x7f080000 icon=0x7f02000e theme=0x1030006

        stateNotNeeded=false componentSpecified=true isHomeActivity=false

        configuration={ scale=1.0 imsi=0/0 loc=ko_KR touch=3 keys=1/1/2 nav=2/1orien=2 layout=34 uiMode=17 seq=2}

        launchFailed=false haveState=false icicle=null

        state=RESUMED stopped=false delayedResume=false finishing=false

        keysPaused=false inHistory=true persistent=false launchMode=0

        fullscreen=true visible=true frozenBeforeDestroy=false thumbnailNeeded=false idle=true

    * Hist #1: HistoryRecord{46130618 com.juno.activitytest/.MainActivity}

        packageName=com.juno.activitytest processName=com.juno.activitytest

        launchedFromUid=2000 app=ProcessRecord{461537b0 1050:com.juno.activitytest/10026}

        Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.juno.activitytest/.MainActivity }

        frontOfTask=true task=TaskRecord{461e6d10 #42 A com.juno.activitytest}

        taskAffinity=com.juno.activitytest

        realActivity=com.juno.activitytest/.MainActivity

        base=/data/app/com.juno.activitytest-1.apk/data/app/com.juno.activitytest-1.apk data=/data/data/com.juno.activitytest

        labelRes=0x7f080000 icon=0x7f02000e theme=0x1030006

        stateNotNeeded=false componentSpecified=true isHomeActivity=false

        configuration={ scale=1.0 imsi=0/0 loc=ko_KR touch=3 keys=1/1/2 nav=2/1orien=2 layout=34 uiMode=17 seq=2}

        launchFailed=false haveState=true icicle=Bundle[mParcelledData.dataSize=812]

        state=STOPPED stopped=true delayedResume=false finishing=false

        keysPaused=false inHistory=true persistent=false launchMode=0

        fullscreen=true visible=false frozenBeforeDestroy=false thumbnailNeeded=false idle=true

  * TaskRecord{461626c0 #2 A com.android.launcher}

    clearOnBackground=true numActivities=1 rootWasReset=true

    affinity=com.android.launcher

    intent={act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.android.launcher/com.android.launcher2.Launcher}

    realActivity=com.android.launcher/com.android.launcher2.Launcher

    lastActiveTime=6749602 (inactive for 19s)

    * Hist #0: HistoryRecord{4615d870 com.android.launcher/com.android.launcher2.Launcher}

        packageName=com.android.launcher processName=com.android.launcher

        launchedFromUid=0 app=ProcessRecord{46162bb0 2292:com.android.launcher/10012}

        Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.android.launcher/com.android.launcher2.Launcher }

        frontOfTask=true task=TaskRecord{461626c0 #2 A com.android.launcher}

        taskAffinity=com.android.launcher

        realActivity=com.android.launcher/com.android.launcher2.Launcher

        base=/system/app/Launcher2.apk/system/app/Launcher2.apk data=/data/data/com.android.launcher

        labelRes=0x7f0c0002 icon=0x7f02005a theme=0x7f0d0000

        stateNotNeeded=true componentSpecified=false isHomeActivity=true

        configuration={ scale=1.0 imsi=0/0 loc=ko_KR touch=3 keys=1/1/2 nav=2/1orien=2 layout=34 uiMode=17 seq=2}

        launchFailed=false haveState=true icicle=Bundle[mParcelledData.dataSize=4480]

        state=STOPPED stopped=true delayedResume=false finishing=false

        keysPaused=false inHistory=true persistent=false launchMode=2

        fullscreen=true visible=false frozenBeforeDestroy=false thumbnailNeeded=false idle=true



  Running activities (most recent first):

    TaskRecord{461e6d10 #42 A com.juno.activitytest}

      Run #2: HistoryRecord{46096400 com.juno.activitytest/.ActivityA}

      Run #1: HistoryRecord{46130618 com.juno.activitytest/.MainActivity}

    TaskRecord{461626c0 #2 A com.android.launcher}

      Run #0: HistoryRecord{4615d870 com.android.launcher/com.android.launcher2.Launcher}


  mPausingActivity: null

  mResumedActivity: HistoryRecord{46096400 com.juno.activitytest/.ActivityA}

  mFocusedActivity: HistoryRecord{46096400 com.juno.activitytest/.ActivityA}

  mLastPausedActivity: HistoryRecord{4614cb90 com.juno.activitytest/.DetailActivity}


  mCurTask: 42


   ... 중략 ...


C:\Users\Juno>



그림으로 그리면, 요런 모습이겠다.



[여담]
이런 로그 메시지를 분석하는 부분은 꽤 자신없는 부분이네요.
혹시나, 잘못된 내용은 가감없이 지적바랍니다.


Update #1

누군가 고맙게도 stack만 추려서 볼 수 있게, 만들어줬네요.

sed 명령어를 사용하려면 GnuWin32를 설치해야합니다.

http://sourceforge.net/projects/getgnuwin32/files/getgnuwin32/


  adb shell dumpsys activity activities | sed -En -e "/Stack #/p " -e "/Running activities/,/Run #0/p"

출처 : http://stackoverflow.com/a/31107447/536078



Posted by 데브로망스
Android2011. 1. 27. 14:44

여기서 거론되는 "구글 날씨 API"는 사실 iGoogle 가젯을 위한 API이다. 하지만, 필요한 건 결과물만 있으면 되니까...^^ 

[Base URL]

가장 간단한 방법은 도시 명칭을 입력하는 것인데, 아래와 같이 seoul, new york 등 지역명칭을 넣으면 된다.
그런데, 이러한 방법은 지역을 설정하는 UI를 만들거나, 현재 위치가 어느 지역인지 알아내는 등의 방법이 필요하다.

http://www.google.com/ig/api?weather=[seoul , pusan ...]

위의 방법은 구현하는 사람이나 사용하는 사람이나 "귀찮다!!"
현재 위치로 바로 찾는 방법을 찾아보니 훌륭한 외국인(?)들이 이런저런 댓글을 달아놨다.

현재 위치를 입력해서 그 지역의 날씨를 얻어 오는 방법은 아래와 같다.

http://www.google.com/ig/api?weather=,,,36497695,127481491

콤마(,) 3개 ",,," 입력한 뒤, 위도-경도 순으로 입력을 한다. 위경도 사이에는 역시 콤마(,)를 입력한다. 
여기서 한 가지 중요한 점은 위도와 경도에 각각 1,000,000을 곱한 후 입력해야 하는 것이다.

(IE나 파이어폭스에서 주소를 넣어보면 XML 내용을 볼 수 있다.)

[언어 및 단위 설정하기]

ISO 코드를 설정하면, 언어 및 단위 등, 원하는 값을 얻을 수 있는데, 예를 들면, "&hl=en"을 설정하면 영어, mph, 화씨(Fahrenheit) 단위로 변하고, "&hl=ko"는 한국어, kph, 섭씨(Centigrade) 단위로 변한다.

[&hl=en를 설정한 결과]

[&hl=ko를 설정한 결과]


* 지원하는 주요 ISO 언어코드
"en", "da", "de", "es", "fi", "fr", "it", "ja", "ko", "nl", "no", "pt-BR", "ru", "sv", "zh-CN", "zh-TW"

Default는 "en"이기 때문에, 지원하지 않는 코드를 입력할 경우 결과는 영어로 전달된다.

[날씨의 종류]
* 아이콘 업데이트(날씨 아이콘 파일명이 모조리 변경되었다. 기존 개발자들이 곤혹을 겪는 중..)
정확한 날씨 리스트는 찾기 힘들다. 이번에는 친절한 외국인(?)이 노가다로 찾은 결과를 올려줬는데 이는 "아이콘 리스트"이다. 이 리스트가 99% 정확할 것이라고 하니 믿어봄직 하다. ^^ 뭐, 아이콘 명칭으로 대략 어떤 날씨인지 알 수 있을 것이다. 

/NEW 아이콘 리스트/
http://g0.gstatic.com/images/icons/onebox/weather_scatteredshowers-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_sunny-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_partlycloudy-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_mostlycloudy-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_rain-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_cloudy-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_drizzle-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_heavyrain-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_thunderstorms-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_scatteredthunderstorms-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_sleet-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_snow-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_icy-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_dust-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_fog-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_smoke-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_haze-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_snowflurries-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_overcast-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_rainsnow-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_windy-40.gif
http://g0.gstatic.com/images/icons/onebox/weather_heavysnow-40.gif
 
/OLD 아이콘 리스트/
http://www.google.com/images/weather/chance_of_rain.gif
http://www.google.com/images/weather/sunny.gif
http://www.google.com/images/weather/mostly_sunny.gif
http://www.google.com/images/weather/partly_cloudy.gif
http://www.google.com/images/weather/mostly_cloudy.gif
http://www.google.com/images/weather/chance_of_storm.gif
http://www.google.com/images/weather/rain.gif
http://www.google.com/images/weather/chance_of_rain.gif
http://www.google.com/images/weather/chance_of_snow.gif
http://www.google.com/images/weather/cloudy.gif
http://www.google.com/images/weather/mist.gif
http://www.google.com/images/weather/storm.gif
http://www.google.com/images/weather/thunderstorm.gif
http://www.google.com/images/weather/chance_of_tstorm.gif
http://www.google.com/images/weather/sleet.gif
http://www.google.com/images/weather/snow.gif
http://www.google.com/images/weather/icy.gif
http://www.google.com/images/weather/dust.gif
http://www.google.com/images/weather/fog.gif
http://www.google.com/images/weather/smoke.gif
http://www.google.com/images/weather/haze.gif
http://www.google.com/images/weather/flurries.gif

*아래 페이지에서 검색한 결과인데, 구글 아이콘의 퀄리티가 높지 않다고 생각했는지, 자신이 만든 아이콘을 나열해 놓았다. 무료인 것 같으니 사용해도 좋겠다. ^^ (이 아이콘 또한 예전 파일명이다. 새로운 날씨명칭에 대한 아이콘이 필요해졌다. ㅠ.ㅠ)
*한글로 된 날씨 명칭을 알면 좋겠는데, 진짜 노가다가 필요할 것 같다. 

[결과 사용하기]

구글 날씨 API는 결과값을 XML형태로 제공한다. XML만 분석하면 이런저런 기능으로 활용이 가능하다.
구글 날씨는 현재날씨, 오늘의 예상날씨, 이후 3일의 예상날씨를 제공한다.
제공되는 정보는 매우 적다.


[기타 다른 API]


[참고사항]

C#에서 구글 날씨 API 사용한 예

날씨 API에 대한 리뷰

iGoogle Dev Forum


Posted by 데브로망스