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 리플렉션에 대한 재고
2013년 1월 14일 월요일
Using reflection with Android
Use reflection to find such below symbol.
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;
}
}
- 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);
이러한 경우에는 다음과 같은 방식을 사용한다.
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;
}
간단하다.
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.
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가 발생한다.
체크포인트는 아래와 같다.
- 사용하지 않는 Bitmap객체에 대한 recycle() 처리
- Activity의 onPause() 또는 onDestroy()에서 member field로 사용 중인 Bitmap객체를 recycle
- 대용량 이미지 파일을 Bitmap객체로 decode하고자 한다면 아래와 같이 BitmapFactory의 Options을 활용하여 sampling한다.
- 메모리 사용량을 줄이기 위해 decode시에 Bitmap을 1/2크기로 sampling하기 위한 방법이다.
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inSampleSize = 2;
- bitmap = BitmapFactory.decodeFile(filepath, options);
- 자세한 방식은 구글링하자~^_^
- 특정 플랫폼 메서드 중에서는 내부적으로 OutOfMemoryError를 소비하는 경우가 있다. 그러한 경우에는 해당 method의 실패여부를 알려주는 return값을 받아서 적절히 처리한다.
- 내부적으로 OutOfMemoryError를 소비하는 예제 메서드. android.graphics.Bitmap.compress(Bitmap.java:729)
2012년 11월 19일 월요일
하드웨어 리셋 이후에 저장된 파일이 날아간다.
- 증상하드웨어 리셋 이후에 저장된 파일이 날아간다.
- 상세 내용: FileOutputStream을 write후 close해서 DDMS의 File Explorer에 해당 파일이 나타났는데도 하드웨어 리셋을 하면 파일 크기가 0이 되거나 파일이 없어진다.
- 원인: 파일시스템은 버퍼를 활용하고 있다. 버퍼링된 내용이 물리 파일에 씌여지기 전에 하드웨어 리셋이 되기 때문이다.
- 해결책: FileOutputStream객체의 getFD()를 통해 전달받는 FileDescriptor객체를 이용하여 sync() 를 호출하여, 물리파일에 씌여지는 시기를 강제화 한다.
- sync()사용 시의 문제점
- 전화 중과 같은 상황에 sync가 호출 되면 속도가 느려질 수 있다.
- 참고 링크
- Saving Data Safely
피드 구독하기:
글 (Atom)
