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

카테고리

분류 전체보기 (37)
주절주절 (1)
누리다 (1)
생활의 발견 (0)
Memory (1)
내 몸의 물 (8)
Developments (14)
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 셜병장
, |

-. abstract class (추상 클래스)

abstract class MethodName{

...

}


  • 일반 클래스와 동일하나 추상 클래스로는 instance를 만들 수 없다.
  • 추상클래스는 하나 이상의 추상메서드를 포함하고 있다.
  • 생성자, 멤버변수, 메서드등을 가질수 있다.
  • 상속을 통해 서브 클래스에 의해서만 완성된다.

(오버라이딩으로 조상의 메서드를 구현해주어야 하며, 사용하지 않을시에는 동일하게 abstract를 붙여 추상메서드를 지정해야한다 이 자체도 abstract class 가 된다.)



2. abstract class를 사용하는 이유는? (추론)

추가적인 부모 클래스의 instance를 생성하지 않고 만들고자 하는 객체의 개념만 정의 해놓았다.

객체에서 필요로 하는 메서드에 대해 미리 부모가 지정할수 있다.

조상 클래스가 반드시 필요로 하는 부분에 대해 상속 받으려는 클래스에게 구현하도록 미리 설계하는것이 주 목적으로 보인다.

부모(parent)가 자식(child)이 태어나면 손가락(finger) 개수부터 확인한다는 옛말을 인용하면 부모가 자식에게 꼭 있었으면 하는 부분(finger)에 대해 미리 abstract(추상)해 놓고 태어날때 필수 조건으로 놓고 태어나길 원하는 심정이라고 보면 되겠다

이는 프로그래밍적으로 설계도의 역할을 하는 것으로 만들고자하는 객체의 설계를 미리함으로써 실질적인 청사진을 그려볼수 있다.


-.Interface(인터페이스)

1. 인터페이스란?

  • 일종의 추상클래스이다.
  • 추상 클래스와는 달리 일반 메서드와 멤버변수를 구성원으로 가질 수 없다.

오직 추상 메서드 (abstract method)와 상수(constant)만을 멤버변수로 가질 수 있다.

  • 멤버변수는 모두 public static final이어야 하며 메서드는 모두 public abstract이어야 한다. (constant)

생략가능하며 생략시에는 컴파일러가 자동으로 추가한다.



2. 인터페이스의 장점?

  • 다중 상속

Java는 기본적으로 다중 상속이 불가능하다. 이는 다중상속의 장점보다 단점이 더 크다고 판단하기 때문에 기본적으로 허용하지 않도록 설계되어있다.

허나 Interface를 이용하면 다중 상속이 가능하다.

정확히 표현하자면 interface는 상속의 개념이 아니라 implements (구현)으로 표현하는 것이 맞으므로 다중 상속보다 다중 구현이 맞지 않나 싶지만...;;

  1. 구현 방법

A와 B의 클래스를 상속받아서 사용하는 C 클래스가 있다면 이때 비중이 더 높은쪽 (A클래스라 가정한다.)를 상속받아서 사용하고 B 클래스의 interface를 만들어 implements하여 C를 사용한다.

public class C extends A implements B{

....

}

이때 다형성의 장점을 얻을 수 있다.

  1. 다형성
public class AClass implements BInterface{

...

}

=>

Binterface B = new AClass();

  • 개발 시간이 단축된다.

interface가 작성되면 선언부만으로 각각의 class를 구현할 수 있으므로 코딩 작업을 분할할수 있다.

  • 표준화가 가능하다. 

특정 프로젝트를 수행한다고 했을시 interface로 표준화시켜 놓으면 보다 정형화된 프로그램 작성이 가능하다.

  • 서로 관계없는 class들끼리 관계를 맺을 수 있다.

다중 interface를 이용하므로 서로 상관없는 class들이 하나로 관계가 맺는것이 가능하다.

  • 독립적인 프로그래밍이 가능하다.

class의 선언부와 구현부의 분리가 가능하므로 실제구현시 독립적인 구현이 가능하다.


3. Interface의 이해

A -> B

A는 B.method()호출

기존 A에서 B 메서드 호출시 B의 선언부를 호출

A->I->B

A는 I.method()를 호출

A는 B를 직접 호출할것 없이 I(인터페이스)를 호출함으로써 I를 implement한 B의 호출이 가능하다.

이때 I는 다형성에 의해 동일한 구현부를 가진 C나 D도 호출이 가능하다.

B의 클래스가 추가되거나 변경되어도 A가 사용하는데는 영향을 받지 않으며 선언부 자체가 이미 interface를 사용하였기 때문에

B,C,D등은 그것에 맞추어 구현만 하면 되고 A는 이를 부르기만 하면된다.






Posted by 셜병장
, |

1. Constructor 와 Member Method의 차이점


 -. Constructor (생성자)란?

  •  객체 생성시 최초 생성되는  Method (인스턴스 초기화) - New 연산자로 최초 생성된다.
  •  Return 값이 없다. (메서드 자체에서 Return 되는 값이 없다.)
  •  Class와 동일한 이름을 사용해야 한다. 
	public class test {

		test(){ ...

		}

	}

  • 별도의 Constructor를 만들어 주지 않아도 Default로 생성된다. (이때 매개변수도 안에 내용도 없는 빈 생성자를 생성한다.)

      이는 컴파일러가 자동으로 추가하는 것으로 클래스내에 생성자가 하나도 없을때만 성립한다.

      매개변수가 존재하는 생성자가 해당 Class에 존재할시 컴파일 에러가 발생한다. 


 -. Constructor를 사용하는 이유?

생성자를 공부하면서 Java에서 생성자가 존재하는 이유에 대해 생각을 해보았다.

우선 첫번째로 Java는 객체지향의 언어이다. 이는 객체를 중심으로 프로그래밍한다는 말로 존재하는 객체에 대해 정확한 정보가 중요하다.

Instance로 객체를 생성할때 객체 안에 존재하는 정보가 정확하지 않다면 그 객체를 참조 또는 사용하는 많은 부분에서 정확한 데이터가 전달되지 않을것이다.

결론은 Java의 Constructor는 이런 객체의 정확한 정보 전달을 위한 Initialization (초기화)를 기반으로 두고 있는것으로 생각된다.

생성자는 정확한 데이터를 가진 정보를 초기화하는 책임이 있는 것이다.

예로 "Dog"라는 객체를 생성할때 쌩뚱맞게 "Wing"(날개)라는 정보가 객체안에 포함되어있다면 "Dog"를 사용하는 모든 클래스에서는 "날개를 단 강아지"라는 정보로 운용되는 일이 발생할것이다. 


 -. Constructor와 Method의 차이점은?

  • Constructor는 반환값이 없다. (type은 기본적으로 void이지만 생량되어서 표기된다.)
  • Class가 생성되기 전에 미리 초기화하여 먼저 생성된다.
  • New가 호출될때 인스턴스당 단 한번씩만 호출된다.


-. Constructor에 static을 선언?

  •  생성자 선언시 초기화 Block으로 static type 생성 가능하다.
	public class staticTest{

		static{

			...

		}

	}

  • 이외에도 static factory method를 생성자 대신 사용 가능하다.



-. static factory method란?

  • 일반적인 Constructor
	public class constructorTest{

		constructorTest(){

			...

		}

	}
  • static factory method로 변경시
	public class constructorTest{

		private static final constructorTest INS = new constructorTest();



		constructorTest(){

			...

		}

		public static constructorTest getInstance(){

			return INS;

		}

	}


  • 대표적인 예 - Calendar

Calendar는 Calendar ca = Calendar.getInstance();로 호출

이는 호출할때마다 매번 생성자를 호출하지 않고 static으로 이미 생성된 Instance를 사용할수 있다는 장점이 있다.


해당 static Instance는 Class가 Load될때 JVM 의 Method 영역에 미리 저장된다. 

일반적으로 Heap에 저장되는 Instance와는 다르며 Instance를 생성할때 (New사용) 생성자보다 더 먼저 호출된다.

단 , 해당 Class가 상속받은 Class일시 Parent의 생성자가 먼저 호출된다.




Posted by 셜병장
, |

기본적으로 Java 컴파일러는 클래스를 생성할때 생성자가 없으면 첫줄에서 자동으로 생성해준다.

이때 매개변수가 없는 생성자는 별문제없으나 매개변수가 있는 생성자만 존재한다면

하위 클래스 ..즉, 서브클래스에서 상속받을시 문제가 발생할 수 있다.


EX) 

에러메시지는 아래와 같다..

Error Msg : Implicit super constructor test06.Machine() is undefined. Must explicitly invoke another constructor


그에 상응하는 예제..

public class test06 {

	class Machine{

		String name = "machine";

		public Machine(String nm){

			name = nm;

		}

	}

	

	public class Tank extends Machine{

		String model = "0000";		

		public Tank(String id){

			model = id;

		}

	}

	

	public void main(String[] args){

		Tank t = new Tank("4231");

		System.out.println(t.model);

	}

}


컴파일시 생성자의 첫번째 명령문이 super 클래스의 생성자 호출문이 아니면 자동으로 해당 위치에 매개변수가 없는 호출문을 추가한다. 위에서는 super 클래스에 매개변수가 없는 생성자가 없기때문에 컴파일 에러가 발생하는 것이다.


해결 방법)

1. Super 클래스에 매개변수가 없는 생성자를 추가

	class Machine{

		String name = "machine";

		public Machine(){}	⁄⁄첫번째 해결 방법

		public Machine(String nm){

			name = nm;

		}

	}


2. 서브 클래스의 생성자 안에 슈퍼 클래스의 생성자를 호출

	public class Tank extends Machine{

		String model = "0000";		

		public Tank(String id){

			super("Tank");	⁄⁄두번째 해결 방법

			model = id;

		}

	}


자바 컴파일러는 서브클래스의 생성자 안에 슈퍼클래스의 생성자 호출문이 있으면 매개변수가 없는 생성자를 추가로 호출하지 않는다.

이때 super 호출문은 생성자 제일 위애 존재하여야 한다!!!


Posted by 셜병장
, |

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

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



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

ex)

interface name {

	public static final int number = 12;

	public abstract doIt(String str);

}


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

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

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

Posted by 셜병장
, |

argument에 가변적으로 변할수 있는 일종의 list를 받아올수 있도록 할수 있다.

예로 String뒤에 "..." "점점점" 세개를 붙이면 argument로 가변적적인 string 갯수를 가져올수 있다.


public void test(String... str){

	for(int i=0;i<str.length;i++){

		System.out.print(str[i]+" ");

	}	

}


주의 할점 : 

1. 해당 Method를 오버라이딩시 정상적으로 동작하지 않을수 있다.

가변적인 인자에 대한 값이 오버라이딩시 문제 발생

2. 인자 값을 "String... str"외에 "int x"등을 추가할시 반드시 가변인자 값을 맨 뒤에 써야한다.


아래와 같은 상황은 Error 발생 int와 String 위치를 바꿔줘야함

public void test(String... y, int x){

	⁄* source code*⁄

}



Posted by 셜병장
, |

[Java] synchronized

Developments/Java / 2013. 7. 13. 11:47

멀티스레드에서 여러 스레드가 객체의 상태에 손상을 줄수 있으므로 해당 객체에 대한 접근을 제한하는...동시에 실행되어서는 안되는 critical section에 보호하기 위해 synchronized 를 사용한다.

A 쓰레드에서 작업하던 도중 B 쓰레드에게 제어권이 넘어갔을 때, A쓰레드가 작업중이던 공유데이터를 B쓰레드가 임의로 변경한다면 A쓰레드에게 제어권이 넘어갔을때 해당 공유데이터의 작업시 다른 결과가 나오는 문제가 발생할수 있다. 

이를 방지하기 위한 일정의 Lock ... 즉, 접근 방지이다.!!


하나의 스레드만이 데이터 구조에 접근하는 방식이라면 굳이 해당 방식을 사용하지 않아도 된다.


//객체에 Lock을 걸때

synchronized(객체의 참조변수){
	//Source Code...
}


//메서드에 Lock을 걸때

public synchronized void lockTest(){
	//Source Code...
}


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 셜병장
, |

최근에 달린 댓글

최근에 받은 트랙백

글 보관함