2013년 1월 14일 월요일

What is reflection of Java?

The Java reflection API allows you to do exactly that by giving you a window into the fundamental features of the language -- classes and fields and methods -- via an ordinary Java API.


Refer to this below link
  in English. Reflections on Java Reflection
  in Korean. Java 리플렉션에 대한 재고

Using reflection with Android

Use reflection to find such below symbol.

  • class and its information
  • inner class and its information
  • member field and its information
  • member method and its information

Sample Code


import java.lang.reflect.Field;


/**
 * Helper class for Java reflection
 *
 * @author tnkim
 *
 */
public class ReflectHelper {

    /**
     * Return flag that expresses existing a field or not
     *
     * @param clsName class name that is included package name
     * @param fldName field name
     * @return
     */
    public static boolean hasField(String clsName, String fldName) {
        Class<?> cls = ReflectHelper.getClass(clsName);
        if (cls == null)
            return false;

        Field fieldlist[] = cls.getDeclaredFields();
        for (Field fld : fieldlist) {
            if (fld.getName().equals(fldName))
                return true;
        }

        return false;
    }

    /**
     * Return flag that expresses existing the specific field
     * or not in the specific inner class
     *
     * @param clsName class name that is included package name
     * @param fldName field name
     * @return
     */
    public static boolean hasFieldInInnerClass(String clsName, String innerClsName, String fldName) {
        Class<?> cls = ReflectHelper.getInnerClass(clsName, innerClsName);
        if (cls == null)
            return false;

        Field fieldlist[] = cls.getDeclaredFields();
        for (Field fld : fieldlist) {
            if (fld.getName().equals(fldName))
                return true;
        }

        return false;
    }

    /**
     * Return flag that expresses existing the specific inner class
     * or not in the specific class
     *
     * @param clsName class name that is included package name
     * @param fldName field name
     * @return
     */
    public static boolean hasInnerClass(String clsName, String innerClsName) {
        Class<?> innerCls = getInnerClass(clsName, innerClsName);
        if (innerCls == null)
            return false;

        return true;
    }

    /**
     * Return a Class for the specific clsName.
     *
     * @param clsName
     * @return
     */
    public static Class<?> getClass(String clsName) {
        Class<?> cls = null;
        try {
            cls = Class.forName(clsName);
        } catch (ClassNotFoundException e) {
            cls = null;
        }
        return cls;
    }


    /**
     * Return an inner class for the specific clsName
     * and the specific innerClsName.
     *
     * @param clsName
     * @param innerClsName
     * @return
     */
    public static Class<?> getInnerClass(String clsName, String innerClsName) {
        Class<?> cls = ReflectHelper.getClass(clsName);
        if (cls == null)
            return null;

        StringBuilder builder = new StringBuilder(clsName);
        builder.append('$').append(innerClsName);
        String clsNInnerClsName = builder.toString();
        Class<?>[] classList = cls.getClasses();
        for (Class<?> tmpCls: classList) {
            if (tmpCls.getName().equals(clsNInnerClsName)) {
                return tmpCls;
            }
        }

        return null;
    }
}

2012년 12월 28일 금요일

System popup이 떠 있을 때 Activity가 volume설정 시점을 확인하는 방법

볼륨관련 UI를 가지는 activity인 경우라면 system popup이 떠있는 경우라도 hardware volume key에 의한 볼륨값을 해당 activity의 볼륨UI에 업데이트 해야하는 요구가 있을 수 있다.

이러한 경우에는 다음과 같은 방식을 사용한다.

1. BroadcastReceiver클래스 추가

class MediaVolumeChangeReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            boolean hasWindowFocus = %특정_Activity%.this.hasWindowFocus();

            // 현재 activity의 window에게 focus가 없는 경우의 처리
              //
            // 참고로, 키입력에 의해 이동하는 focus가 아니라 window들 중 f/g에 있는 window가
            // 어떤 것인지를 구분하기위한 focus이다.
            // 즉, 안드로이드 플랫폼에서 띄우는 전원종료와 같은 Dialog가 f/g에 있는 경우에 해당 값은
            // false이고, 해당 activity의 window가 f/g에 있다면 true이다.
            if (hasWindowFocus == false) {
                // TODO: 종료팝업이 떠 있는 경우에 volume UI 업데이트 처리
            }
        }
    }
2. MediaVolumeChangeReceiver mMediaVolChgReceiver;
3. BroadcastReceiver 등록
    getApplicationContext().registerReceiver(mMediaVolChgReceiver, new  IntentFilter("android.media.VOLUME_CHANGED_ACTION"));

4. BroadcastReceiver 등록 해제
    getApplicationContext().unregisterReceiver(mMediaVolChgReceiver);

Activity가 System popup이 떠 있는지 여부를 확인하는 방법

Sub title: How to know there's a showing system popup on an activity?

간단하다.

Activity 클래스의 public boolean hasWindowFocus()를 사용하면 된다.

참고로, 해당 플랫폼 코드는 아래와 같다.


    /**
     * Returns true if this activity's <em>main</em> window currently has window focus.
     * Note that this is not the same as the view itself having focus.
     *
     * @return True if this activity's main window currently has window focus.
     *
     * @see #onWindowAttributesChanged(android.view.WindowManager.LayoutParams)
     */
    public boolean hasWindowFocus() {
        Window w = getWindow();
        if (w != null) {
            View d = w.getDecorView();
            if (d != null) {
                return d.hasWindowFocus();
            }
        }
        return false;
    }


2012년 12월 9일 일요일

adb procrank command

Android에서 가장 정확한 memory usage infomation을 제공한다.

tnkim@tnkim-N53SV:~/git/drawingmemo$ adb shell procrank -h
Usage: procrank [ -W ] [ -v | -r | -p | -u | -h ]
    -v  Sort by VSS.
    -r  Sort by RSS.
    -p  Sort by PSS.
    -u  Sort by USS.
        (Default sort order is PSS.)
    -R  Reverse sort order (default is descending).
    -w  Display statistics for working set only.
    -W  Reset working set of all processes.
    -h  Display this help screen.

중요한 정보는 아래와 같다.
  • USS(Unique Set Size)
    • 프로세스만의 고유한 페이지 수. 즉, 공유되지 않은 프로세스의 private한 메모리 크기이다.
  • PSS(Proportional Set Size)
    • USS + (공유 페이지 / 공유하는 프로세스 수)
    • 즉, 프로세스 고유 메모리 사용량 + 하나의 프로세스가 차지하는 공유 메모리 비율
    • 예. 만약 A프로세스가 6MB 메모리를 사용하고 그 중 2MB가 그 프로세스의 고유 영역(USS)이라면, 나머지 4MB는 공유 메모리이다. 4MB의 공유메모리를 4개의 프로세스가 공유하고 있다면 PSS는 2MB + (4MB/4) = 3MB가 된다.
    • 프로세스별 PSS 수치는 adb shell dumpsys meminfo <processname> 을 통해서도 볼 수 있다.
### start of procrank command example ###
tnkim@tnkim-N53SV:~/git/drawingmemo$ adb shell procrank
  PID      Vss            Rss         Pss          Uss        cmdline
 1296   49828K   47396K   18075K   15048K  system_server
 1357   46140K   39876K   11308K    9244K  com.android.systemui
 2951   41388K   38260K    9937K    7892K  com.android.gallery3d
 4174   34972K   34880K    8019K    6400K  android.process.acore
 1186   36564K   36440K    6267K    3468K  zygote
 1525   32160K   32108K    5957K    4676K  com.android.phone
 1492   31620K   31532K    5460K    4248K  android.process.media
 4246   29156K   29060K    3758K    2536K  com.android.quicksearchbox
 4191   29152K   29080K    3600K    2476K  com.android.keychain
 4158   28684K   28616K    3442K    2372K  com.android.defcontainer
 1188    6896K    6896K    2756K    2400K  /system/bin/mediaserver
...
 4991     116K     116K      67K      64K  /sbin/adbd
 8279     124K     124K      63K      56K  /sbin/adbd
 8006     120K     120K      63K      56K  /sbin/adbd
                          ------   ------  ------
                         280030K  239196K  TOTAL

RAM: 868796K total, 275900K free, 27536K buffers, 194924K cached, 1136K shmem, 14140K slab
### end of procrank command example ###

* 참고 사이트

2012년 12월 5일 수요일

비트맵(Bitmap) 사용 시에 OutOfMemoryError가 발생한다.


체크포인트는 아래와 같다.
  1. 사용하지 않는 Bitmap객체에 대한 recycle() 처리
    1. Activity의 onPause() 또는 onDestroy()에서 member field로 사용 중인 Bitmap객체를 recycle
  2. 대용량 이미지 파일을 Bitmap객체로 decode하고자 한다면 아래와 같이 BitmapFactory의 Options을 활용하여 sampling한다.
    1. 메모리 사용량을 줄이기 위해 decode시에 Bitmap을 1/2크기로 sampling하기      위한 방법이다.
      1. BitmapFactory.Options options = new BitmapFactory.Options();
      2. options.inSampleSize = 2;
      3. bitmap = BitmapFactory.decodeFile(filepath, options);
    2. 자세한 방식은 구글링하자~^_^
  3. 특정 플랫폼 메서드 중에서는 내부적으로 OutOfMemoryError를 소비하는 경우가 있다. 그러한 경우에는 해당 method의 실패여부를 알려주는 return값을 받아서 적절히 처리한다.
    1. 내부적으로 OutOfMemoryError를 소비하는 예제 메서드. android.graphics.Bitmap.compress(Bitmap.java:729)

2012년 11월 19일 월요일

하드웨어 리셋 이후에 저장된 파일이 날아간다.


  • 증상하드웨어 리셋 이후에 저장된 파일이 날아간다.
    • 상세 내용: FileOutputStream을 write후 close해서 DDMS의 File Explorer에 해당 파일이 나타났는데도 하드웨어 리셋을 하면 파일 크기가 0이 되거나 파일이 없어진다.
  • 원인: 파일시스템은 버퍼를 활용하고 있다. 버퍼링된 내용이 물리 파일에 씌여지기 전에 하드웨어 리셋이 되기 때문이다.
  • 해결책: FileOutputStream객체의 getFD()를 통해 전달받는 FileDescriptor객체를 이용하여 sync() 를 호출하여, 물리파일에 씌여지는 시기를 강제화 한다.
  • sync()사용 시의 문제점
    • 전화 중과 같은 상황에 sync가 호출 되면 속도가 느려질 수 있다.
  • 참고 링크