블로그 이미지
인간은 자신이 이해하지 못하는 것을 경멸하는 버릇이 있다. 셜병장

카테고리

분류 전체보기 (37)
주절주절 (1)
누리다 (1)
생활의 발견 (0)
Memory (1)
내 몸의 물 (8)
Developments (14)
Android (8)
Java (5)
JavaScript/Html (1)
Window (0)
Tool (0)
Attraction (9)
Father Time (2)
Play Ground (1)
Total
Today
Yesterday

얼마전 개발 App중에 Call을 Answer 해야하는 기능의 App이 있는데..

이게 kikat에서는 잘 돌아갔는데..Lollipop에서는 안돌아 가는가는 문제가 생겼다..


열심히 구글링 구글링했지만...

http://stackoverflow.com/questions/26924618/how-can-incoming-calls-be-answered-programmatically-in-android-5-0-lollipop

아직까지 성공한 사람은 없는듯.

이 ㅁ이 전에 사용하던 방법...

new Thread(new Runnable() {

    @Override
    public void run() {
        try {
            Runtime.getRuntime().exec("input keyevent " +
                    Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));
        } catch (IOException e) {
            // Runtime.exec(String) had an I/O problem, try to fall back
            String enforcedPerm = "android.permission.CALL_PRIVILEGED";
            Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                    Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
                            KeyEvent.KEYCODE_HEADSETHOOK));
            Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                    Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
                            KeyEvent.KEYCODE_HEADSETHOOK));

            mContext.sendOrderedBroadcast(btnDown, enforcedPerm);
            mContext.sendOrderedBroadcast(btnUp, enforcedPerm);
        }
    }

}).start();

이건 안통한다..


WHY??

구글신께서는 아직 해답을 알아내지 못한걸까?아니면 나를 시험에 들게하기위해 못찾게 숨겨놓으신건가?

할수 없이 직접 안되는 원인을 해결하기 위해

reference Lollipop Full source를 뒤졌다..그리고 Kikat과 비교를 해봤다.

그리고 드디어 Lollipop 에서 위의 내용이 안먹는 이유를 찾았다.


기존에는 CallApp에서 저 BR( Intent.ACTION_MEDIA_BUTTON )을 받는 Receiver가 있었다..

그리고 KEYCODE_HEADSETHOOK을  확인 후 자체적으로 Call Answer를 했는데..

아뿔사 Lollipop에서는 이 부분이 사라졌다...

그럼?? Headset hook으로 전화를 못받는건가? 그래서 이어폰 장착후 전화 수신을 해보니 잘되더라..;;

그럼 어디로 간걸까?? 

GB때 이후로 Phoneapp을 오랜만에 봐서 그런지 소스 위치가 많이 바뀌어서 찾는데 애먹었다.

Telecomm이라는 service로 이동되어있는데..

전처럼 Receiver로 받는게 아니었다.

Lollipop에서 MedaiSession이라는 Service가 생겨났고, 여기서 CallBack을 받아서 처리하고 있었다.

난감... Callback을 훔쳐올수도 없고..ㅡ.ㅡ


그래서 생각해낸 방법은

MediaSession service에서 Key 동작 method를 빌려서 호출하는 방법이다.

Reciever의 응용편이라고 하는게 적당할듯...

그렇게 몇시간 삽질하니 결국은 잘 동작되었다.


관련 소스는 회사에 있으니...추후 업데이트 해야겠다..


늦은 업데이트....아래와 같다.

private MediaSessionManager mSessionManager;


    @TargetApi(Build.VERSION_CODES.LOLLIPOP)

private Method getMethodDispatchMediaKey(){

        mSessionManager = (MediaSessionManager) mCtx

                .getSystemService(Context.MEDIA_SESSION_SERVICE);

        Method m = null;

        try {

        m = Class.forName(mSessionManager.getClass().getName()).getDeclaredMethod("dispatchMediaKeyEvent", KeyEvent.class);

      m.setAccessible(true);

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (NoSuchMethodException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

        return m;

    }


    @TargetApi(Build.VERSION_CODES.LOLLIPOP)

    public void acceptCall(){

    try {

    getMethodDispatchMediaKey().invoke(mSessionManager, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));

getMethodDispatchMediaKey().invoke(mSessionManager, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

    }




'Developments > Android' 카테고리의 다른 글

주요 ADB 명령어 모음  (0) 2014.05.17
[Android/Tip] Interface  (0) 2013.07.13
[Android/Exception] - java.lang.IllegalStateException  (0) 2013.07.13
[Android] Parcel  (0) 2013.07.13
[Android/Tip] ListView getView 중복 호출  (0) 2013.05.06
Posted by 셜병장
, |

-. adb 명령어

adb kill-server

adb start-server


파일 밀어넣기 

System app에 강제로 apk 밀어 넣을때 종종 사용 ( Install과 비슷하지만 다른 개념)

adb push xxx.apk /system/app/


push 시 Read-only file system

adb remount  /또는/ adb shell mount -o remount,rw -t rfs /dev/stl12 /system


dump.txt 파일로 덤프 파일 저장하기

adb shell dumpstate >> dump.txt 


system의 메모리 정보 mem 파일로 저장

adb shell dumpsys meminfo >> mem.txt


process 의 메모리 사용량 

adb shell procrank >> proc.txt


system의 properties 내용 prop파일에 저장

adb shell getprop >>prop.txt


-. adb shell 

# am  (activity manager)

am start -a [intent] -d [data] -t [minetype] -c [category] -n [component] -f [flags]

ex) call 발신

am start -a android.intent.action.CALL -d tel:01012345678 


broadcast도 가능

am broadcast


단말의 사이즈 강제로 조정하기 > 1280x800으로 변경

am display-size 1280x800


단말의 Density값 강제로 조정하기 >480으로 변경

am display-density 480 


단말의 상태 모니터링 (ANR등을 확인)

am monitor 


# pm (package manager)

pm list package [option]

package 모두 보여준다.

-d (disable 되어있는 package 목록)

-e (enable 되어있는 package 목록)

-s (system package 목록)

-3 (thrid party package 목록)


해당 패키지 삭제

pm uninstall [pacakgename]


해당 패키지의 데이터 삭제

pm clear [package]


disable 되어있는 package를 enable 로 변경

pm enable [package]

<-> pm disable : 반대로 enable 되어있는 package를 disable 시킨다.



Android 4.4(level 19) 이상의 버전에서만 지원되는 기능 

mp4로 촬영

adb shell screenrecord /sdcard/xxx.mp4

단말의 동작을 촬영하여 xxx.mp4 파일로 저장

option : --size --rotate 등 옵션 가능

(ctrl-c 시 촬영 중지) 



Posted by 셜병장
, |

Interface - 알고는 있지만 막상 깊게는 알지 못하는 부분이 속속들이 보인다.

아래는 미처 놓치고 있던 부분을 요약한것으로 추후 업데이트



인터페이스안의 요소는 추상메서드와 상수만을 멤버로 가질수 있으며, 그외의 다른 어떠한 요소도 허용되지 않는다.

ex)

interface name {

	public static final int number = 12;

	public abstract doIt(String str);

}


interface안의 abstract는 생략가능하다.

abstract를 붙인 추상메서드는 추후 상속받은 메서드에서 해당 메서드를 반드시 구현해야하므로 

abstract를 붙여 "추상메서드임"이라고 알리기 위함이다.

Posted by 셜병장
, |

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. 


[in ListView(-1, class android.widget.ListPopupWindow$DropDownListView) with Adapter(class android.widget.Spinner$DropDownAdapter)] 


IllegalStateException : 불법적인 상태에 대한 예외 / state 이동이 잘못된 상태에 발생한 에러


The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread

: Listview의 adapter가 변경된 상태를 알리지 않은 상태에서 재참조한 상황. 

결국 adapter를 쓰려면 Background thread로 돌지 말고 UI thread로 돌려라라는 의미


구조적인 문제로 100% 발생할수 있지만 타이밍적으로 발생가능성이 있음


동작 listview로 setAdapter한 상황에서 add된 상황에 대해 반환하지 않고 다시 setAdapter를 다시 호출할 경우 발생 (물론 경우의 수임) 결국 동기화 문제인가? ㅡ.,ㅡ

타이밍적인 문제라면 Adapter add 후에 notifyDataSetChanged() 호출하여 갱신하면 해결가능



'Developments > Android' 카테고리의 다른 글

주요 ADB 명령어 모음  (0) 2014.05.17
[Android/Tip] Interface  (0) 2013.07.13
[Android] Parcel  (0) 2013.07.13
[Android/Tip] ListView getView 중복 호출  (0) 2013.05.06
[Android/Tip] - adjustResize in Fullscreen  (1) 2013.04.17
Posted by 셜병장
, |

[Android] Parcel

Developments/Android / 2013. 7. 13. 11:29

Parcel은 내부의 데이터는 모두 직렬화 되어야한다.

parcel로 저장된 데이터는 Serializable되었으므로 Read시 순서대로 읽어야 한다.

(setDataPosition을 통해 특정 위치로 이동할수 있다.)


Parcel parcel = parcel.obtain();

// write -->

parcel.writeInt(intData);

parcel.writeString(stringData);

parcel.writeFloat(floatData);


parcel.setDataPosition(0);


//read -->

parcel.readInt();

parcel.readString();

parcel.readFloat();


Serializeable을 상속받은 객체


String

ArrayList

LinkedList

HashMap

TreeMap


implements된 Parcelable에 상속받는 method

describeContents() 


writeToParcel(Parcel out, int flags)  //객체 분해 송신시 사용

해당 객체 전송하면 frameworks 내부의 IPC 전송담당에서 자동으로 호출한다.


//객체 조립 수신시

    public static final Parcelable.Creator<SearchRequest> CREATOR

            = new Parcelable.Creator<SearchRequest>() {

        public testPacel createFromParcel(Parcel in) {

            return new SearchRequestImpl(in);

        }



        public testPacel[] newArray(int size) {

            return new testPacel[size];

        }

    };


Posted by 셜병장
, |

-. getView가 중복 호출되는 문제

Listview를 감싸는 parent view의 layout_height가 wrap_content일때 중복 호출 발생

fill_parentmatch_parent로 변경하면 중복 현상 없이 정상동작한다.


참고 site : http://www.androidpub.com/41674

'Developments > Android' 카테고리의 다른 글

[Android/Tip] Interface  (0) 2013.07.13
[Android/Exception] - java.lang.IllegalStateException  (0) 2013.07.13
[Android] Parcel  (0) 2013.07.13
[Android/Tip] - adjustResize in Fullscreen  (1) 2013.04.17
[Android] Resource Density and Screen  (0) 2013.04.10
Posted by 셜병장
, |

  • adjustResize

android:windowSoftInputMode="adjustResize" 또는

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);


WindowManager.LayoutParams.FLAG_FULLSCREEN 일때 adjustResize 안먹힌다.


회피 방법

WindowManager.LayoutParams lp = getWindow().getAttributes();

            lp.flags &=  ~WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;

            getWindow().setAttributes(lp);


또는 

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);

Remove 시킨다.


이러면 Full Screen도 되고 adjustResize도 정상적으로 된다.

android bug인듯하네..



'Developments > Android' 카테고리의 다른 글

[Android/Tip] Interface  (0) 2013.07.13
[Android/Exception] - java.lang.IllegalStateException  (0) 2013.07.13
[Android] Parcel  (0) 2013.07.13
[Android/Tip] ListView getView 중복 호출  (0) 2013.05.06
[Android] Resource Density and Screen  (0) 2013.04.10
Posted by 셜병장
, |

  • 다중 지원 스크린

안드로이드는 다양한 화면의 크기와 pixcel을 제공하는 장치에서 실행된다.

이에 시스템은 다른 화면 구성을 위한 UI설계 최적화의 크기 밀도등에 대한 API를 제공한다.


  • Screen

-. Screen size

화면의 대각선으로 측정한 실제 물리적크기


-. Screen density

화면의 물리적인 영역에서 픽셀의 양. 일반적으로 dpi(dots per inch)라 한다.


-. Resolution

화면의 물리적인 pixel읠 총 개수이다. 


-. Density-independent pixel (dp)

UI layout을 정의할때 layout의 크기 및 위치를 표현하기 위해 사용해야 하는 단위이다.

기준 밀도는 160 dpi(medium) 이며 이는 1dp가 1px이기 때문이다.

이를 토대로 계산시 화면 pixel 단위의 변환은 pixel = dp*(dpi/160) 이다.

반대로 dp를 계산한다면 dp=pixel/(dpi/160)이 된다.


예를 들어 WVGA의 경우

1dpi에 대한 pixel 값을 구하려면 480*(1/160) 이므로 1dpi는 3 pixel이 된다.


-. Android 4.2 기준 (http://developer.android.com/tools/revisions/platforms.html)


 Nexus 7 (7.3", 800 x 1280, Large tvdpi screen)

Galaxy Nexus (4.7", 720 x 1280, Normal xhdpi screen)

Nexus S (4.0", 480 x 800, Normal hdpi screen)

Nexus One (3.7", 480 x 720, Normal hdpi screen)

10.1" WXGA Tablet (1280 x 800, X-Large mdpi screen)

7.0" WSVGA Tablet (1024 x 600, Large mdpi screen)

5.4" FWVGA (480 x 854, Large mdpi screen)

5.1" WVGA (480 x 800, Large mdpi screen)

4.7" WXGA (1280 x 720, Normal xhdpi screen)

4.65" 720p (720 x 1280, Normal xhdpi screen)

4.0" WVGA (480 x 800, Normal hdpi screen)

3.7" WVGA (480 x 800, Normal hdpi screen)

3.7" FWVGA slider (480 x 854, Normal hdpi screen)

3.4" WQVGA (240 x 432, Normal ldpi screen)

3.3" WQVGA (240 x 400, Normal ldpi screen)

3.2" QVGA ADP2 (320 x 480, Normal mdpi screen)

3.2" HVGA slider ADP1 (320 x 480, Normal mdpi screen)

2.7" QVGA slider (240 x 320, Small ldpi screen)

2.7" QVGA (240 x 320, Small ldpi screen)


  • Density

 ldpi

  low-density screens ~120dpi

 mdpi 

 medium-density screens ~160dpi (일반적으로 baseline이다)

 hdpi 

 high-density screens ~240dpi

 xhdpi 

 extra high-density sreens ~320dpi

 nodpi 

 독립적인 dpi로 device에 일치하고 싶지 않을때 사용한다.

 tvdpi 

 mdpi와 hdpi의 사이로 약 213dpi정도이다. tvdpi는 일반적인 dpi로 간주되지 않으며 이름 그대로 tv을 위해 만들어 놓은것으로 일반적인 app에서는 대체로 사용되지 않는다.

tvdpi를 사용할 경우 size는 1.33*mdpi로 생각해야한다. 예를 들면 mdpi화면에 대한 100px X100px 이미지의 경우 tvdpi는 133px X 133px로 해야한다.

 xxhdpi 

 extra high-density screes 에서 extra가 하나 더 붙은거로 ~480dpi


  • new size qualifiers

android 3.2부터 제공된 것으로 기존에는 device의 size 및 pixel만 알면 사용이 가능하였는데 개발측면에서 더 폭넓게 resource size를 사용하도록 만든 개념으로 이해된다. 

android developer 사이트에서 대략적인 설명이 되어있는데 잘이해가 가지 않는다...;;


-. smallestWidth

sw은 smallestWidth로 가로/세로중 좁은쪽을 말한다. 이는 고정화면크기 특성이며 화면의 방향에 따라 변경되진 않는다.

sw320dp-hdpi 와같이 resource를 지정시 사용된다.


예로 320dpi (1280 x 720, Normal xhdpi screen) 를 가진 device가 있다고 하면 320dpi에 1280 x 720이므로 

320dpi : 720 px = 160dpi : x 이므로 방정식으로 계산하면 x 값은 360dp 

즉, 해당 resource는 sw360dp-xhdpi의 폴더가 적용된다. 

여기서 주의할 점은 320dpi는 단말의 정확한 dpi가 아닌 build시 고정된 값으로 된다. 이 값은 [ro.sf.lcd_density]에 정의되어있다.


참조 : http://developer.android.com/guide/practices/screens_support.html


Posted by 셜병장
, |

최근에 달린 댓글

최근에 받은 트랙백

글 보관함