'3. Implementation/Android'에 해당되는 글 51건

  1. 2014.07.24 The process of the hierarchy dump in android
  2. 2014.07.24 How to search android source using google
  3. 2014.07.24 Android Source Search Site
  4. 2012.05.14 Android App (Apk) Source Reverse Engineering
  5. 2012.05.10 [펌] 항상 최상위에 나오는 뷰 만들기
  6. 2012.05.08 Classpath problem using Eclipse for Android platform development
  7. 2012.05.08 [펌] 안드로이드 - LockScreen 만들기
  8. 2012.02.16 emma 와 ant 를 이용하여 코드 커버리지 측정하기 1
  9. 2011.11.24 안드로이드 터치 이벤트 처리 관련
  10. 2011.11.06 Context 메모리 릭 관련
  11. 2011.11.01 이클립스에서 안드로이드 소스 보기 1
  12. 2011.09.10 How to Sign Android APK or Zip Files
  13. 2011.08.17 Understanding security on Android
  14. 2011.08.17 [펌] 이클립스에서 네이티브 애플리케이션을 디버그 모드로 서명하기
  15. 2011.08.17 Eclipse IDE를 이용한 Android Platform Development (CDT install)
  16. 2011.08.17 Android에서 Home Key 와 Power(Endcall) Key 를 onKeyDown, onKeyUp 으로 인식할 수 없는 이유
  17. 2011.07.28 Controlling the Embedded VM
  18. 2011.07.28 Stack Dumps
  19. 2011.07.28 [펌] Dalvik VM java assert 켜기
  20. 2011.07.28 [번역] Log 읽고 쓰기
2014. 7. 24. 07:29

The process of the hierarchy dump in android

The simple overview of ui dump process in android is like the following figure:

(2 years ago, I was involved in the project that developed the android test automation tool.)





The related source code is as below:


-----------------------------------------------------------------------------------

ViewServer.java

-----------------------------------------------------------------------------------

https://android.googlesource.com/platform/frameworks/base/+/master/services/java/com/android/server/wm/ViewServer.java



class ViewServer implements Runnable {


    private final WindowManagerService mWindowManager;


    class ViewServerWorker implements Runnable, WindowManagerService.WindowChangeListener {

        private Socket mClient;

        private boolean mNeedWindowListUpdate;

        private boolean mNeedFocusedWindowUpdate;

        public ViewServerWorker(Socket client) {

            mClient = client;

            mNeedWindowListUpdate = false;

            mNeedFocusedWindowUpdate = false;

        }

        public void run() {

            BufferedReader in = null;

            try {

                in = new BufferedReader(new InputStreamReader(mClient.getInputStream()), 1024);

                final String request = in.readLine();

                String command;

                String parameters;

                int index = request.indexOf(' ');

                if (index == -1) {

                    command = request;

                    parameters = "";

                } else {

                    command = request.substring(0, index);

                    parameters = request.substring(index + 1);

                }

                boolean result;

                if (COMMAND_PROTOCOL_VERSION.equalsIgnoreCase(command)) {

                    result = writeValue(mClient, VALUE_PROTOCOL_VERSION);

                } else if (COMMAND_SERVER_VERSION.equalsIgnoreCase(command)) {

                    result = writeValue(mClient, VALUE_SERVER_VERSION);

                } else if (COMMAND_WINDOW_MANAGER_LIST.equalsIgnoreCase(command)) {

                    result = mWindowManager.viewServerListWindows(mClient);

                } else if (COMMAND_WINDOW_MANAGER_GET_FOCUS.equalsIgnoreCase(command)) {

                    result = mWindowManager.viewServerGetFocusedWindow(mClient);

                } else if (COMMAND_WINDOW_MANAGER_AUTOLIST.equalsIgnoreCase(command)) {

                    result = windowManagerAutolistLoop();

                } else {

                    result = mWindowManager.viewServerWindowCommand(mClient,command, parameters);

                }

   // ...

}

    }

}


-----------------------------------------------------------------------------------

WindowManagerService.java

-----------------------------------------------------------------------------------

https://android.googlesource.com/platform/frameworks/base/+/master/services/java/com/android/server/wm/WindowManagerService.java



public class WindowManagerService extends IWindowManager.Stub

        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs,

                DisplayManagerService.WindowManagerFuncs, DisplayManager.DisplayListener {


    boolean viewServerWindowCommand(Socket client, String command, String parameters) {


        // Any uncaught exception will crash the system process

        try {

            // Find the hashcode of the window

            int index = parameters.indexOf(' ');

            if (index == -1) {

                index = parameters.length();

            }

            final String code = parameters.substring(0, index);

            int hashCode = (int) Long.parseLong(code, 16);

            // Extract the command's parameter after the window description

            if (index < parameters.length()) {

                parameters = parameters.substring(index + 1);

            } else {

                parameters = "";

            }

            final WindowState window = findWindow(hashCode);

            if (window == null) {

                return false;

            }

            data = Parcel.obtain();

            data.writeInterfaceToken("android.view.IWindow");

            data.writeString(command);

            data.writeString(parameters);

            data.writeInt(1);

            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);

            reply = Parcel.obtain();

            final IBinder binder = window.mClient.asBinder();

            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER

            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);


}

}


-----------------------------------------------------------------------------------

WindowState.java

-----------------------------------------------------------------------------------

https://android.googlesource.com/platform/frameworks/base/+/master/services/java/com/android/server/wm/WindowState.java


import android.view.IWindow;


final class WindowState implements WindowManagerPolicy.WindowState {


    final IWindow mClient;


}


-----------------------------------------------------------------------------------

IWindow.aidl

-----------------------------------------------------------------------------------

https://android.googlesource.com/platform/frameworks/base/+/master/core/java/com/android/internal/view/BaseIWindow.java


oneway interface IWindow {

    void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor);

}


-----------------------------------------------------------------------------------

ViewRootImpl.java

-----------------------------------------------------------------------------------

https://android.googlesource.com/platform/frameworks/base/+/17d28ca/core/java/android/view/ViewRootImpl.java


public final class ViewRootImpl implements ViewParent,

        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {


    static class W extends IWindow.Stub {

        @Override

        public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {

            final ViewRootImpl viewAncestor = mViewAncestor.get();

            if (viewAncestor != null) {

                final View view = viewAncestor.mView;

                if (view != null) {

                    if (checkCallingPermission(Manifest.permission.DUMP) !=

                            PackageManager.PERMISSION_GRANTED) {

                        throw new SecurityException("Insufficient permissions to invoke"

                                + " executeCommand() from pid=" + Binder.getCallingPid()

                                + ", uid=" + Binder.getCallingUid());

                    }

                    OutputStream clientStream = null;

                    try {

                        clientStream = new ParcelFileDescriptor.AutoCloseOutputStream(out);

                        ViewDebug.dispatchCommand(view, command, parameters, clientStream);

                    } catch (IOException e) {

                        e.printStackTrace();

                    } finally {

                        if (clientStream != null) {

                            try {

                                clientStream.close();

                            } catch (IOException e) {

                                e.printStackTrace();

                            }

                        }

                    }

                }

            }

        }

    }


}



-----------------------------------------------------------------------------------

ViewDebug.java

-----------------------------------------------------------------------------------

https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/ViewDebug.java


/**

 * Various debugging/tracing tools related to {@link View} and the view hierarchy.

 */

class ViewDebug

{

void dispatchCommand(View view, String command, String parameters,

            OutputStream clientStream) throws IOException {

        if (REMOTE_COMMAND_DUMP.equalsIgnoreCase(command)) {

            dump(view, false, true, clientStream);

}




    /**

     * Dumps the view hierarchy starting from the given view.

     * @hide

     */

    public static void dump(View root, boolean skipChildren, boolean includeProperties,

            OutputStream clientStream) throws IOException {

        BufferedWriter out = null;

        try {

            out = new BufferedWriter(new OutputStreamWriter(clientStream, "utf-8"), 32 * 1024);

            View view = root.getRootView();

            if (view instanceof ViewGroup) {

                ViewGroup group = (ViewGroup) view;

                dumpViewHierarchy(group.getContext(), group, out, 0,

                        skipChildren, includeProperties);

            }

            out.write("DONE.");

            out.newLine();

        } catch (Exception e) {

            android.util.Log.w("View", "Problem dumping the view:", e);

        } finally {

            if (out != null) {

                out.close();

            }

        }

    }


    private static void dumpViewHierarchy(Context context, ViewGroup group,

            BufferedWriter out, int level, boolean skipChildren, boolean includeProperties) {

        if (!dumpView(context, group, out, level, includeProperties)) {

            return;

        }

        if (skipChildren) {

            return;

        }

        final int count = group.getChildCount();

        for (int i = 0; i < count; i++) {

            final View view = group.getChildAt(i);

            if (view instanceof ViewGroup) {

                dumpViewHierarchy(context, (ViewGroup) view, out, level + 1, skipChildren,

                        includeProperties);

            } else {

                dumpView(context, view, out, level + 1, includeProperties);

            }

            if (view.mOverlay != null) {

                ViewOverlay overlay = view.getOverlay();

                ViewGroup overlayContainer = overlay.mOverlayViewGroup;

                dumpViewHierarchy(context, overlayContainer, out, level + 2, skipChildren,

                        includeProperties);

            }

        }

        if (group instanceof HierarchyHandler) {

            ((HierarchyHandler)group).dumpViewHierarchyWithProperties(out, level + 1);

        }

    } 


}





2014. 7. 24. 07:21

How to search android source using google


Use site option as below:


windowmanageservice site:android.googlesource.com/platform/frameworks/base/


Without cpp file


windowmanageservice site:android.googlesource.com/platform/frameworks/base/ -cpp


This search doesn't catch the contents of the source, so just use to reach latest or specific version of android source file.

2014. 7. 24. 07:17

Android Source Search Site

The following site is really helpful to find something inside android  and kernel source!

This site uses OpenGrok internally. 2 years ago I also used this. 


http://androidxref.com/




Additional References : Set Opengrok Up

2012. 5. 14. 23:41

Android App (Apk) Source Reverse Engineering

안드로이드 apk 파일에서 소스를 추출하는 방법을 설명해 드리겠습니다. 여기서 소스는 원본소스가 아닌 disassembly 를 이용하여 생성된 byte code (dex format)로부터 생성된 Java 소스를 말합니다. 좀더 정확하게 말하면 .class 포맷으로 변경해서 이 포맷을 볼 수 있는 Viewer 를 통해서 소스를 보는 것입니다. 아무래도 원본 소스랑은 좀 다르겠지만 로직이나 어떤 API 를 사용했느냐를 분석할 수 있어서 큰 도움이 될 수 있습니다.


(자료 자체가 공개할만한개 아니라 비공개로 작성합니다.)



Swype.apk


유명한 SwypePad 의 apk 파일입니다. 엔지니어링 빌드 폰의 System/App 위치에서 복사했습니다.


1. http://code.google.com/p/dex2jar/ 에서 다운로드



dex2jar-0.0.9.8.zip



2. d2j-dex2jar 명령을 실행합니다.


D:\Android\apps>d2j-dex2jar -f Swype.apk

dex2jar Swype.apk -> Swype-dex2jar.jar


3. 새로 생성된 Swype-dex2jar.jar 파일을 JD-GUI (Java Decompiler) 툴로 열면 아래처럼 소스가 보입니다.



jd-gui-0.3.3.windows.zip



http://java.decompiler.free.fr/?q=jdgui






2012. 5. 10. 00:11

[펌] 항상 최상위에 나오는 뷰 만들기

출처: http://blog.daum.net/_blog/BlogTypeView.do?blogid=0NADc#ajax_history_1


위 링크에는 최상위 윈도우를 만드는 방법에 대해서 소개하고 있습니다. 간단한 내용만 소개하므로 자세한 내용을 원하면 위 링크를 참고하세요. 


1. 뷰 생성 및 최상위 윈도우에 추가


//최상위 윈도우에 넣기 위한 설정
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,   //항상 최 상위에 있게
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,       //터치 인식
PixelFormat.TRANSLUCENT);                                                          //투명
        
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); //윈도 
wm.addView(tv, params);  //최상위 윈도우에 뷰 넣기. permission필요.


2. 퍼미션 설정


<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>


3. 뷰 제거


((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(tv);


다음은 like miller 님이 작성한 소스입니다.



AlwaysOnTop.zip



원본 글 댓글에 보면 waa 님께서 SwipePad 에 대해서 소개하는 내용이 있습니다. 이 app 이 이와 유사한 기능을 이용하여 구현하고 있습니다. 아래는 SwipePad 캡처 화면입니다. 네 귀퉁이에 빨간색으로 표현된 부분이 모든 app 에서 인식되는 hotspot 영역입니다. 나름 재밌는 app 이더군요. 분석을 떠나서 한번 사용해 보심도 괜찮을듯 합니다.





웹서핑하다가 StackOverflow 에서 다음 링크를 발견하였습니다. 비슷한 내용이군요.


http://stackoverflow.com/questions/4481226/creating-a-system-overlay-always-on-top-button-in-android






2012. 5. 8. 23:30

Classpath problem using Eclipse for Android platform development

Android 프레임워크 소스를 Eclipse 에 로딩시 Classpath 문제에 대한 해결책을 제공하는 글입니다. 


에러 메시지


Project 'Generic-Android' is missing required library: 'out/target/
common/obj/JAVA_LIBRARIES/google-common_intermediates/javalib.jar'
Project 'Generic-Android' is missing required library: 'out/target/
common/obj/JAVA_LIBRARIES/gsf-client_intermediates/javalib.jar'  


출처: https://groups.google.com/forum/#!topic/android-contrib/wEpciQkEUlA/discussion


It seems like the sample .classpath file from development/ide/eclipse 
is outdated. Eclipse complains about some missing JAR libraries (out/ 
target/common/obj/JAVA_LIBRARIES/google-common_intermediates/ 
javalib.jar and out/target/common/obj/JAVA_LIBRARIES/gsf- 
client_intermediates/javalib.jar). Searching on the groups, I found 
that google-common_intermediates has been moved to android- 
common_intermediates, and gsf-client_intermediates is not used 
anymore. 


After this, the build path errors were gone, but I got 197 errors 
referring to missing types. Ouch! Since running make was hassle free, 
this could only be another classpath problem for Eclipse. So I hunted 
down the missing types, and after adding them to the .classpath file, 
building was a success. Here are the extra libraries, that we have to 
add to the .classpath file: 


<classpathentry kind="lib" path="out/target/common/obj/JAVA_LIBRARIES/ 
android-support-v13_intermediates/javalib.jar"/> 
<classpathentry kind="lib" path="out/target/common/obj/JAVA_LIBRARIES/ 
filterfw_intermediates/classes-jarjar.jar"/> 


Don't forget to refresh your project :) 




2012. 5. 8. 23:12

[펌] 안드로이드 - LockScreen 만들기

출처: http://blog.naver.com/PostView.nhn?blogId=multikth&logNo=150109761153


 FC 포르테님이 작성한 글을 퍼왔습니다. 이렇게 복사해 오는 이유는 블로그 내에서 검색이 되도록 하기 위함입니다.


안드로이드폰에서 hold키를 누르면 순정 lockscreen으로 화면이 잠긴다.

이 락스크린을 개발자가 직접 건드릴수는 없으므로 가짜(?) 락스크린을 만들어 넣는 방법을 생각해 볼 수 있다.

 

LockScreen.java에서 Activity를 상속 받고,

onCreate메소드에서

WindowManager를 통해 플래그를 주었다...

 

 - onCreate()

getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED|

                              WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

 

setContentView(R.layout. .....);

 

위 플래그를 통해 홀드키를 누르면 안드로이드 순정 락스크린이 걸린상태에서 그 위에

LockScreen.java 액티비티를 띄우게 된다.

 

나는 서비스를 돌리고, 서비스에서 브로드캐스트 리시버를 통해 "Intent.ACTION_SCREEN_OFF" 브로드캐스트가 수신됐을때

(즉, 화면이 꺼졌을때) startActivity(new Intent(new, LockScreen.class)); 와 같은 형식으로 락스크린 액티비티를 호출해줬다.

그러면 화면이 꺼지고 안드로이드 순정 락스크린이 걸린 상태에서 그 위에 LockScreen.java 액티비티가 호출되어 있을 것이다.

 

이상태에서 다시 홀드키를 눌러 화면을 켜게되면 원래는 순정 락스크린이 떠 있어야 하지만, onCreate에서 추가해준 플래그에 의해

순정 락스크린이 떠있는 상태에서 그 위에 LockScreen.java 액티비티가 떠있게 되므로, 사용자 입장에서는

그것이 락스크린이 된다. 거기서 락을 해제할수있는 버튼을 하나 만들어서 그 버튼을 눌렀을때

LockScreen.java 액티비티는 onPause쯤에서 finish() 호출해서 액티비티를 종료 시키고,

아래 코드를 추가하면,

 

KeyguardManager km = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);

KeyguardManager.KeyguardLock keyLock = km.newKeyguardLock(KEYGUARD_SERVICE);

keyLock.disableKeyguard(); //순정 락스크린 해제

 

이렇게 해주면 순정 LockScreen이 종료 되면서 순정 락스크린도 함께 해제되어

모르는사람은 그게 진짜 락스크린처럼 보일 것이다..

 

위에서 사용한 코드(KeyguardManager를 사용하려면 AndroidManifest.xml에서 퍼미션을 추가해줘야 사용 가능하다.

<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>

 

반대로 락을 다시 걸어주는 방법은

keyLock.reenableKeyguard();를 호출해주면 순정락화면으로 잠긴다.

이때도 마찬가지, reenableKeyguard를 호출해 순정락화면으로 잠궈버리고,

다시 startActivity로 LockScreen.java액티비티를 호출하면 자연스럽게

onCreate에서 추가해준 플래그에 의해 락스크린위에 LockScreen.java 액티비티가 위로 올라가기 때문에

락스크린으로써의 기능(?)을 다 할수가 있다.

 

좀더 유연하게 쓰려면 여러가지 살을 좀 붙여야겠지만. 이정도만해도 충분히 락스크린을 만들 수 있다.

 

어떤 블로그나 자료를 보면 onCreate에서 추가한 플래그들이 락스크린을 해제 해주는 코드라고 하는데..

정확하게 말해서 락스크린을 해제 해주게 아니라, 락스크린이 안풀린 상태에서 그 위에 또다른 액티비티가 올라가기 때문에

락이 해제된 것 처럼 보일 뿐이다.

 

 

-혼자 공부하려고 쓴 포스트이니... 태클은 정중히 사양하겠습니다...

2012. 2. 16. 00:42

emma 와 ant 를 이용하여 코드 커버리지 측정하기

아주 급하게 정리하였습니다. 좀더 정리가 필요한 것 같지만 일단은 여기서 마무리 하겠습니다.

D:\Android\Workspace>android create test-project --help
Error: Flag '--help' is not valid for 'create test-project'.

       Usage:
       android [global options] create test-project [action options]
       Global options:
  -h --help    : Help on a specific command.
  -v --verbose : Verbose mode, shows errors, warnings and all messages.
  -s --silent  : Silent mode, shows errors only.

                              Action "create test-project":
  Creates a new Android project for a test package.
Options:
  -p --path    : The new project's directory. [required]
  -n --name    : Project name.
  -m --main    : Path to directory of the app under test, relative to the test
                 project directory. [required]


D:\Android\Workspace>android create test-project -p HelloActivity_test -m ../HelloActivity

ant 설치

ant coverage 하면 에러가 발생했음
sdk/tools/ant 밑에 build.xml 을 살펴보면 emma 빌드가 있어서 시도해봄

ant emma 

성공

테스트 대상 프로젝트(원본프로젝트)에 테스트 프로젝트에 생성된 build.xml 과 local.properties 파일을 복사함

그리고 

ant debug

성공

그리고 test project 가서

ant emma debug install test

했는데 마지막에 실패함.

D:\Android\Workspace\HelloActivity_test>adb shell am instrument -w -e coverage true com.example.android.helloactivity.tests/android.test.InstrumentationTestRunner

com.example.android.helloactivity.HelloActivityTest:.
Error: Failed to generate emma coverage. Is emma jar on classpath?

다시 시도해 봄

원본 프로젝트로 가서

android update project -p HelloActivity

를 입력

ant debug

성공 후, test project 로 가서

ant emma debug install test

해서 모두 성공했으나 

     [exec] remote object '/data/data/com.example.android.helloactivity/coverage
.ec' does not exist

라는 메시지와 함께 마지막에 안타깝게 실패

아래 명령 실행으로 성공함.

D:\Android\Workspace\HelloActivity_test>adb shell am instrument -w -e emma true
com.example.android.helloactivity.tests/android.test.InstrumentationTestRunner

위에 것은 성공이 아닌듯 함.

ant emma debug install test

를 성공시켜야 하는데

test 프로젝트에 있는 coverage.em 파일을

adb push coverage.em /sdcard/coverage.ec

로 강제로 밀어 넣고,

android-sdk\tools\ant\build.xml 을

       <!--<property name="emma.dump.file"
                value="/data/data/${tested.manifest.package}/coverage.ec" />-->
        <property name="emma.dump.file"
                value="/sdcard/coverage.ec" />
                
이렇게 수정하고 난 후

D:\Android\Workspace\HelloActivity_test>D:\Android\tools\apache-ant-1.8.2\bin\an
t emma debug install test

이렇게 했더니 성공함.

참고
2011. 11. 24. 02:02

안드로이드 터치 이벤트 처리 관련

참고: http://ecogeo.tistory.com/251
 

ViewRoot.java 에 보면 deliverPointerEvent 라는 함수가 있습니다. (비슷한 종류로 deliverKeyEvent, deliverKeyEventToViewHierarchy, deliverTrackballEvent 등이 더 있습니다.)

주의! 이 글에서 인용된 코드는 안드로이드 최신 소스가 아닐 수 있습니다.

 
    private void deliverPointerEvent(MotionEvent event) {
        if (mTranslator != null) {
            mTranslator.translateEventInScreenToAppWindow(event);
        }

        boolean handled;
        if (mView != null && mAdded) {

            // enter touch mode on the down
            boolean isDown = event.getAction() == MotionEvent.ACTION_DOWN;
            if (isDown) {
                ensureTouchMode(true);
            }
            if(Config.LOGV) {
                captureMotionLog("captureDispatchPointer", event);
            }
            if (mCurScrollY != 0) {
                event.offsetLocation(0, mCurScrollY);
            }
            if (MEASURE_LATENCY) {
                lt.sample("A Dispatching TouchEvents", System.nanoTime() - event.getEventTimeNano());
            }
            handled = mView.dispatchTouchEvent(event);
            if (MEASURE_LATENCY) {
                lt.sample("B Dispatched TouchEvents ", System.nanoTime() - event.getEventTimeNano());
            }
            if (!handled && isDown) {
                int edgeSlop = mViewConfiguration.getScaledEdgeSlop();

                final int edgeFlags = event.getEdgeFlags();
                int direction = View.FOCUS_UP;
                int x = (int)event.getX();
                int y = (int)event.getY();
                final int[] deltas = new int[2];

                if ((edgeFlags & MotionEvent.EDGE_TOP) != 0) {
                    direction = View.FOCUS_DOWN;
                    if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
                        deltas[0] = edgeSlop;
                        x += edgeSlop;
                    } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
                        deltas[0] = -edgeSlop;
                        x -= edgeSlop;
                    }
                } else if ((edgeFlags & MotionEvent.EDGE_BOTTOM) != 0) {
                    direction = View.FOCUS_UP;
                    if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
                        deltas[0] = edgeSlop;
                        x += edgeSlop;
                    } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
                        deltas[0] = -edgeSlop;
                        x -= edgeSlop;
                    }
                } else if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
                    direction = View.FOCUS_RIGHT;
                } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
                    direction = View.FOCUS_LEFT;
                }

                if (edgeFlags != 0 && mView instanceof ViewGroup) {
                    View nearest = FocusFinder.getInstance().findNearestTouchable(
                            ((ViewGroup) mView), x, y, direction, deltas);
                    if (nearest != null) {
                        event.offsetLocation(deltas[0], deltas[1]);
                        event.setEdgeFlags(0);
                        mView.dispatchTouchEvent(event);
                    }
                }
            }
        }
    }

View nearest = FocusFinder.getInstance().findNearestTouchable 에 보면 적절한 view 를 선택하고 있습니다. 해당 코드는 아래와 같습니다. (FocusFinder.java) 

    public View findNearestTouchable(ViewGroup root, int x, int y, int direction, int[] deltas) {
        ArrayList<View> touchables = root.getTouchables();
        int minDistance = Integer.MAX_VALUE;
        View closest = null;

        int numTouchables = touchables.size();

        int edgeSlop = ViewConfiguration.get(root.mContext).getScaledEdgeSlop();

        Rect closestBounds = new Rect();
        Rect touchableBounds = mOtherRect;

        for (int i = 0; i < numTouchables; i++) {
            View touchable = touchables.get(i);

            // get visible bounds of other view in same coordinate system
            touchable.getDrawingRect(touchableBounds);

            root.offsetRectBetweenParentAndChild(touchable, touchableBounds, true, true);

            if (!isTouchCandidate(x, y, touchableBounds, direction)) {
                continue;
            }

            int distance = Integer.MAX_VALUE;

            switch (direction) {
            case View.FOCUS_LEFT:
                distance = x - touchableBounds.right + 1;
                break;
            case View.FOCUS_RIGHT:
                distance = touchableBounds.left;
                break;
            case View.FOCUS_UP:
                distance = y - touchableBounds.bottom + 1;
                break;
            case View.FOCUS_DOWN:
                distance = touchableBounds.top;
                break;
            }

            if (distance < edgeSlop) {
                // Give preference to innermost views
                if (closest == null ||
                        closestBounds.contains(touchableBounds) ||
                        (!touchableBounds.contains(closestBounds) && distance < minDistance)) {
                    minDistance = distance;
                    closest = touchable;
                    closestBounds.set(touchableBounds);
                    switch (direction) {
                    case View.FOCUS_LEFT:
                        deltas[0] = -distance;
                        break;
                    case View.FOCUS_RIGHT:
                        deltas[0] = distance;
                        break;
                    case View.FOCUS_UP:
                        deltas[1] = -distance;
                        break;
                    case View.FOCUS_DOWN:
                        deltas[1] = distance;
                        break;
                    }
                }
            }
        }
        return closest;
    }

위의 코드를 살펴 보면 ArrayList<View> touchables = root.getTouchables();
라는 부분이 있습니다. 다시 getTouchables 의 소스를 살펴보겠습니다.
아래는View.java 에서 발췌하였습니다.

    /**
     * Find and return all touchable views that are descendants of this view,
     * possibly including this view if it is touchable itself.
     *
     * @return A list of touchable views
     */
    public ArrayList<View> getTouchables() {
        ArrayList<View> result = new ArrayList<View>();
        addTouchables(result);
        return result;
    }

    /**
     * Add any touchable views that are descendants of this view (possibly
     * including this view if it is touchable itself) to views.
     *
     * @param views Touchable views found so far
     */
    public void addTouchables(ArrayList<View> views) {
        final int viewFlags = mViewFlags;

        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
                && (viewFlags & ENABLED_MASK) == ENABLED) {
            views.add(this);
        }
    }

addTouchables 는 ViewGroup.java 에서 다음과 같이 재정의되어 있습니다.

    @Override
    public void addTouchables(ArrayList<View> views) {
        super.addTouchables(views);

        final int count = mChildrenCount;
        final View[] children = mChildren;

        for (int i = 0; i < count; i++) {
            final View child = children[i];
            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
                child.addTouchables(views);
            }
        }
    }


위 내용에서 터치 대상이 되는 Target View 를 찾는 과정은 지금 진행하고 있는 일에서 꽤 중요한 정보가 될 것 같습니다.
2011. 11. 6. 17:06

Context 메모리 릭 관련

Context 에는 두가지 종류가 있습니다. 하나는 Application 이고 하나는 Activity 입니다.

Activity 의 경우 Orientation 이 바뀌는 경우에도 소멸되고, 다시 생성됩니다. 이때 이전의 Activity Context 를 static 변수가 만일 참조하고 있다면 Activity 가 GC에 의해 소멸되지 않을 것입니다.

이렇게 Context 관련해서 참조를 해야 하는 경우는 Activity 보다는 Application Context 를 참조해야 합니다.

컨텍스트 관련 메모리 릭을 피하는 방법은 다음과 같습니다.

 * Activity Context 를 참조하는 경우, Activity 라이프 사이클과 동일해야 합니다. 
 * context-activity 대신 context-application 을 사용하세요
 * 중첩클래스(inner class)의 라이프 사이클을 제어하지 않는다면, activity 내에 비정적 중첩 클래스(non-static inner class)를 사용하지 마세요. 정적 중첩 클래스를 사용하고 내부적으로 activity 에 대한 약한 참조(weak reference)를 사용하세요. 이 이슈에 대한 해결책은 외부 클래스(outer class)에 대한 약한참조를 가지는 정적 중첩 클래스를 사용하는 것입니다, 이에 대한 예로 ViewRoot 안에 W 중첩 클래스가 그렇게 구현되어 있습니다.
 * Garbage Collector 가 메모리 릭 방지를 보장해 주지는 않습니다.
출처: http://developer.android.com/resources/articles/avoiding-memory-leaks.html
2011. 11. 1. 23:58

이클립스에서 안드로이드 소스 보기

안드로이드 프로젝트를 생성한 후, Activity 와 같은 안드로이드에서 제공하는 클래스에서 F3 를 누를 경우 소스를 찾을 수 없다는 메시지가 나옵니다. jad(http://www.varaneckas.com/jad ,  Java Decompiler) 플러그인(http://sourceforge.net/projects/jadclipse/)을 설치하여 dummy 코드를 얻어서 멤버와 메소드 정도는 확인할 수 있지만 왠지 성에 차지 않습니다.

안드로이드 자체가 Open Source 인 만큼, 소스를 볼 수 있으면 더 좋겠지요. 다음과 같이 하면 됩니다.

우선 안드로이드 소스를 가지고 있다고 가정하겠습니다. 그리고 물론 빌드도 하였구요.

해당 버전의 소스를 하기 링크에서 원하는 버전의 Framework 소스를 다운받으시면 됩니다. 용량이 크지 않습니다. lol
http://grepcode.com/snapshot/repository.grepcode.com/java/ext/com.google.android/android/2.3.3_r1/


OS 버전과  API Number 는 Android 공식 사이트에 나와 있습니다. (http://source.android.com/source/build-numbers.html)

Code nameVersionAPI level
(no code name) 1.0 API level 1
(no code name) 1.1 API level 2
Cupcake 1.5 API level 3, NDK 1
Donut 1.6 API level 4, NDK 2
Eclair 2.0 API level 5
Eclair 2.0.1 API level 6
Eclair 2.1 (incl. 2.1-update 1) API level 7, NDK 3
Froyo 2.2.x API level 8, NDK 4
Gingerbread 2.3 - 2.3.2 API level 9, NDK 5
Gingerbread 2.3.3 - 2.3.7 API level 10
Honeycomb 3.0 API level 11
Honeycomb 3.1 API level 12
Honeycomb 3.2 - 3.2.2 API level 13

android.jar 의 경우,

android.jar 는 소스 링크를 변경하지 못하게 되어 있습니다. 그래서 빌드 당시의 위치에 소스가 존재하도록 해주어야 합니다.

ANDROID-SDK/platforms/ 폴더 밑에 버전별로 sources 폴더를 만들어 복사해 주면 됩니다. (복사한 후 이클립스를 한번 죽였다가 다시 뛰워주는 센스를 발휘하세요.)

만약 android-7 에 해당하는 소스를 복사한다면,

안드로이드 소스의 framework 폴더를 
ANDROID-SDK/platforms/android-7/sources 하위에다가 복사해 주면 됩니다.

복사후에는,
ANDROID-SDK/platforms/android-7/sources/framework/...

와 같이 되겠지요.

 

혹, ddmlib.jar 와 같은 라이브러리를 이용하는 경우,

ddmlib.jar 는 소스 위치만 지정해 주면 됩니다. 소스의 위치를 external folder 로 하여,

소스위치/sdk/ddms/libs/libs/ddmlib/src

로 지정해주기만 하면 이클립스에서 안드로이드 소스를 바로 확인할 수 가 있습니다.


2011. 9. 10. 21:27

How to Sign Android APK or Zip Files

(안드로이드 애플리케이션 사이닝하기)

How to create private/public key pair using openssl (windows version)

- openssl genrsa -out key.pem 1024
- openssl req -new -key key.pem -out request.pem
- openssl x509 -req -days 9999 -in request.pem -signkey key.pem -out certificate.pem
- openssl pkcs8 -topk8 -outform DER -in key.pem -inform PEM -out key.pk8 -nocrypt

How to sign apk or zip files using SignApk.jar:

java -jar signapk.jar certificate.pem key.pk8 your-app.apk  your-signed-app.apk
OR
- java -jar signapk.jar certificate.pem key.pk8 your-update.zip your-signed-update.zip



참고
http://www.londatiga.net/how-to-sign-apk-zip-files/
http://android-dls.com/wiki/index.php?title=Generating_Keys
http://forum.xda-developers.com/showthread.php?t=442480&page=83
2011. 8. 17. 05:22

Understanding security on Android

아래 링크에 대해 정독하면 좋을 것 같습니다.

참고: http://www.ibm.com/developerworks/opensource/library/x-androidsecurity/?ca=drs-
2011. 8. 17. 04:57

[펌] 이클립스에서 네이티브 애플리케이션을 디버그 모드로 서명하기

원본: http://ecogeo.tistory.com/264

드로이드 소스에 SRC/build/target/product/security 에 가면 eng 빌드에서 동작하는 테스트 키들이 있습니다. 이 테스트 키들은 user build 로 가면 각 제조사별로 다르게 Signing 되기 때문에 동작하지 않습니다.

- media.pk8, media.x509.pem 
- platform.pk8, platform.x509.pem 
- shared.pk8, shared.x509.pem 
- testkey.pk8, testkey.x509.pem  

4가지 키에 대한 간략한 설명은 다음과 같습니다.

* testkey - a generic key for packages that do not otherwise specify a key
* platform - a test key for packages that are part of the core platform
* shared - a test key for things that are shared in the home/contacts process
* media - a test key for packages that are part of the media/download system

jks 파일을 만드는 방법을 다음과 같습니다. (jks 파일은 이클립스에서 지정하여 자동으로 app 이 해당 키로 사이닝 되게 할 수 있습니다.)

1 PK8 유형의 키 파일을 PEM 유형 키로 변환

$ openssl pkcs8 -inform DER -nocrypt -in testkey.pk8 -out testkey.pem


2. 키와 인증서를 포함하는 PKCS#12 포맷의 저장소 생성

$ openssl pkcs12 -export -in testkey.x509.pem 
    -inkey testkey.pem -out testkey.p12 
    -password pass:android -name androiddebugkey


3. PKCS#12 포맷 저장소 파일을 자바 키저장소 포맷으로 변환

(1) JDK 1.5 인 경우 jetty 라이브러리에 포함된 PKCS12Import 클래스를 이용

$ java -classpath jetty-core-6.1.14.jar 
    org.mortbay.jetty.security.PKCS12Import testkey.p12 testkey.jks


(2) JDK 1.6 인 경우 JDK에서 제공하는 keytool 을 이용

$ keytool -importkeystore -deststorepass android 
    -destkeystore testkey.jks 
    -srckeystore testkey.p12 -srcstoretype PKCS12 -srcstorepass android
☞ 윈도우즈에서도 key 를 생성할 수 있습니다.

☞ 이클립스 Preferences > Android > Build 메뉴 Custom debug keystore 에 jks 파일을 지정하면 해당 키를 이용하여 사이닝 되게 됩니다.

☞ 만약 platform 키로 사이닝된 System 권한의 App 을 만들려면 메니페스트에 sharedUserId 를 선언해 주어야 합니다.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.sskk.sample"
  android:sharedUserId="android.uid.system"
>
 
2011. 8. 17. 04:42

Eclipse IDE를 이용한 Android Platform Development (CDT install)

2011. 8. 17. 04:40

Android에서 Home Key 와 Power(Endcall) Key 를 onKeyDown, onKeyUp 으로 인식할 수 없는 이유

2011. 7. 28. 05:57

Controlling the Embedded VM

원본: http://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=docs/embedded-vm-control.html;hb=HEAD

위 링크 원본 중 일부만 발췌하였습니다. 눈여겨 볼 것은 adb shell stop; adb shell start; 를 이용하는 것, /data/local.prop 파일의 존재, 그리고 아래 명령어 입력 방식.

adb shell "echo name = value >> /data/local.prop"

( 따옴표를 빠뜨리지 않아야 합니다!)

asb shell stop; adb shell start; 는 stdio, strerr 설정에서도 나옵니다.
$ adb shell stop
$ adb shell setprop log.redirect-stdio true
$ adb shell start

Introduction (read this first!)
 
The Dalvik VM supports a variety of command-line arguments (use adb shell dalvikvm -help to get a summary), but it's not possible to pass arbitrary arguments through the Android application runtime. It is, however, possible to affect the VM behavior through certain system properties. 

For all of the features described below, you would set the system property with setprop, issuing a shell command on the device like this: 

adb shell setprop <name> <value>

 
The Android runtime must be restarted before the changes will take effect (adb shell stop; adb shell start). This is because the settings are processed in the "zygote" process, which starts early and stays around "forever". 

You may not be able to set dalvik.* properties or restart the system as an unprivileged user. You can use adb root or run the su command from the device shell on "userdebug" builds to become root first. When in doubt, 

adb shell getprop <name>

 
will tell you if the setprop took. 
If you don't want the property to evaporate when the device reboots, add a line to /data/local.prop that looks like: 

<name> = <value>

 
Such changes will survive reboots, but will be lost if the data partition is wiped.

(Hint: create a local.prop on your workstation, then adb push local.prop /data. Or, use one-liners like adb shell "echo name = value >> /data/local.prop" -- note the quotes are important.




2011. 7. 28. 05:38

Stack Dumps

간단한 내용이라 번역하지 않겠습니다.

Like other desktop VMs, when the Dalvik VM receives a SIGQUIT (Ctrl-\ or kill -3), it dumps stack traces for all threads. By default this goes to the Android log, but it can also be written to a file.

The dalvik.vm.stack-trace-file property allows you to specify the name of the file where the thread stack traces will be written. The file will be created (world writable) if it doesn't exist, and the new information will be appended to the end of the file. The filename is passed into the VM via the -Xstacktracefile argument.

For example:

adb shell setprop dalvik.vm.stack-trace-file /tmp/stack-traces.txt

If the property is not defined, the VM will write the stack traces to the Android log when the signal arrives.


출처:  http://www.netmite.com/android/mydroid/dalvik/docs/embedded-vm-control.html#assertions
2011. 7. 28. 05:37

[펌] Dalvik VM java assert 켜기

원본: http://blog.naver.com/PostView.nhn?blogId=treebystream&logNo=130087206849

 
##android device or emulator에서 java assert 켜기
 

모듈 통합에 있어서 어려운 점은 모듈에 버그가 있을 때 어떤 모듈에 있는지 찾는데 시간이 너무 많이 걸린다는 것이다. 버그가 발생했을때 빠르게 원인을 추적할 수 있는 방법 중에 하나는 assert를 효과적으로 사용하는 것이다. unit test의 testcase를 작성하여서 실행하는것도 중요한데 따로 케이스 작성할 여유가 없는 경우에는 java의 native assert를 이용할것을 적극 추천한다.


이방법은 에뮬레이터에서는 잘작동한다 그러나 실제 device에서는 root권한이 필요하므로 사용하지 못할 수 있다. (/data 경로에 파일을 생성해야한다.)

 

android의 Dalvik VM도 java native assert 기능을 제공한다. 다음은 assert를 켜는 방법이다.

1.file local.prop을 만들고  아래의 내용을 입력한다.
dalvik.vm.enableassertions=all

 

2.커맨드 창에서 다음을 실행한다.
adb push local.prop /data 
제대로 전송 되었는지 확인한다. 
adb shell ls -l /data/local.prop

 

3.device or emulator를 재부팅한다.

 

4. java 코드에서 assert(false);를 사용하여 잘 작동하는지 확인한다.

그 외 dalvik VM 속성 설정
dalvik.vm.enableassertions=all
dalvik.vm.stack-trace-file=/tmp/stack-traces.txt
dalvik.vm.deadlock-predict=err
dalvik.vm.checkjni=true

 
 

끄는 방법은 /data/local.prop파일을 삭제한 후 device를 재부팅하면 된다.

adb shell rm /data/local.prop

 

그외 Dalvik VM command line argument

adb shell dalvikvm -help


참고 문서

http://www.netmite.com/android/mydroid/dalvik/docs/embedded-vm-control.html#assertions

2011. 7. 28. 04:32

[번역] Log 읽고 쓰기

안드로이드 로깅 시스템은 시스템 디버그 출력을 수집하고 보기 위한 매커니즘을 제공합니다. Logcat 은 시스템 메시지 로그를 덤프하고, 이것은 스택 트레이스와 같은 것들을 포함하고 있습니다. ADB 또는 DDMS 를 이용하여 LogCat 를 실행할 수 있습니다.

Log 클래스

Log 는 LogCat 에다가 메시지를 출력하기 위해 코드 내에 이용할 수 있는 로깅 클래스입니다. 일반적인 로깅 메소드는 다음과 같습니다.


예를 들어,

Log.i("MyActivity", "MyClass.getView() — get item number " + position);

LogCat 은 아래처럼 출력될 것입니다.

I/MyActivity( 1557): MyClass.getView() — get item number 1

LogCat 사용하기


DDMS 에서 또는 ADB 셀에서 LogCat 을 사용할 수 있습니다. DDMS 내에서 LogCat 을 사용하는 방법에 대해서는 
 Using DDMS 를 참고하세요. ADB 셀에서 LogCat 을 실행하기 위한 일반적인 사용법은 다음과 같습니다.


[adb] logcat [<option>] ... [<filter-spec>] ...

개발용 컴퓨터에서 또는 에뮬레이터/장치 인스턴스의 원격 adb 셀에서 logcat 명령을 사용할 수 있습니다. 개발용 컴퓨터에서 로그 출력을 보기 위해서는 다음과 같이 합니다.

$ adb logcat

그리고 원격 adb 셀에서는 다음과 같이 합니다.

# logcat

아래 표는 logcat 명령어 라인 옵션을 나타냅니다.

-c Clears (flushes) the entire log and exits.
-d Dumps the log to the screen and exits.
-f <filename> Writes log message output to <filename>. The default is stdout.
-g Prints the size of the specified log buffer and exits.
-n <count> Sets the maximum number of rotated logs to <count>. The default value is 4. Requires the -r option.
-r <kbytes> Rotates the log file every <kbytes> of output. The default value is 16. Requires the -f option.
-s Sets the default filter spec to silent.
-v <format> Sets the output format for log messages. The default is brief format. For a list of supported formats, see Controlling Log Output Format.

로그 출력 필터링

모든 안드로이드 로그 메시지는 태그와 우선순위를 가지고 있습니다.

  • 태그는 메시지가 어디에서 기원하는 지를 나타내는 짧은 문자열입니다. (예를 들면, "View" 는 view 시스템)
  • 우선순위는 아래 문자 값들 중의 하나이며, 우선순위가 낮은 것에서부터 높은것 으로 정렬하였습니다.
  • V — Verbose (lowest priority)
  • D — Debug
  • I — Info
  • W — Warning
  • E — Error
  • F — Fatal
  • S — Silent (highest priority, on which nothing is ever printed)

LogCat 을 실행한 후 각 메시지의 처음 두 칼럼을 살펴봄으로써 시스템에 사용된 우선순위/태그의 리스트를 얻을 수 있습니다.

아래는 우선순위 레벨이 "I" 이고 태그가 "ActivityManager" 인 메시지를 출력하는 logcat 출력의 예입니다.

I/ActivityManager(  585): Starting activity: Intent { action=android.intent.action...}


로그 출력을 좀더 다루기 쉽도록 하기 위해서, 필터 표현식을 사용하여 로그 출력을 제한할 수 있습니다. 필터 표현식은 시스템에게 당신이 관심있는 태그-우선순위 조합만을 출력하도록 지정할 수 있습니다.

필터 표현식은 tag:priority ...와 같은 포맷을 따르며, tag 는 관심있는 태그를 가리키며, priority 는 그 태그에 대한 최소 레벨의 우선순위를 가리킵니다. 지정된 우선순위에 해당되는 또는 그 이상의 메시지만이 로그에 출력됩니다. 하나의 필터 표현식 내에 임의 개수의 tag:priority 명세를 제공할 수 있습니다. 일련의 명세는 공백으로 구분됩니다.

ActivityManager 태그와 "info" 우선순위, MyApp 태그와 "Debug" 우선순위를 지정하는 예는 다음과 같습니다.

adb logcat ActivityManager:I MyApp:D *:S

위 표현식의 마지막 엘리먼트인 *:S 는 모든 태그에 대한 우선 순위를 "silent" 로 설정하여, "View" 와 "MyApp" 을 가지는 로그 메시지만이 표시되도록 합니다. *:S 를 사용하는 것은 명시적으로 나열한 필터만 출력하도록 하는 훌륭한 방법입니다.

아래 필터 표현식은 "warning" 우선순위 또는 그 이상의 모든 메시지를 출력합니다.

만약 개발용 컴퓨터(이와 다른 방법은 원격 adb 셀에서 실행되는 것) 에서 LogCat 을 실행하고 있다면, 환경 변수 ANDROID_LOG_TAGS 에 값을 설정함으로써 디폴터 필터를 설정할 수 있습니다.

export ANDROID_LOG_TAGS="ActivityManager:I MyApp:D *:S"


만일 원격 셀 또는 adb shell logcat 을 사용하여 LogCat을 실행중이라면, 에뮬레이터/디바이스 인스턴스에는 ANDROID_LOG_TAGS 필터가 적용되지 않는다는 것을 기억하세요.

로그 출력 포맷 제어하기

로그 메시지는 태그와 우선순위 외에도 많은 메타데이터 필드를 포함하고 있습니다. 출력 포맷을 수정함으로써 특정 메타데이터 필드를 표시하도록 할 수 있습니다. 그렇게 하기 위해서는, -v 옵션을 사용하며 아래에 나열된 출력 양식중 하나를 지정하면 됩니다.

  • brief — Display priority/tag and PID of originating process (the default format).
  • process — Display PID only.
  • tag — Display the priority/tag only.
  • thread — Display process:thread and priority/tag only.
  • raw — Display the raw log message, with no other metadata fields.
  • time — Display the date, invocation time, priority/tag, and PID of the originating process.
  • long — Display all metadata fields and separate messages with blank lines.

LogCat 을 시작할 때, -v 옵션 을 사용하여 출력 포맷을 지정할 수 잇습니다.

[adb] logcat [-v <format>]


아래는 thread 출력 포맷을 표시하기 위한 방법을 보여줍니다.

adb logcat -v thread

-v 옵션은 오직 하나만 지정할 수 있다는 것을 기억하세요.

선택적인 로그 버퍼 보기 (Viewing Alternative Log Buffers)

안드로이드 로깅 시스템은 로그 메시지를 위해 다수의 원형 버퍼(multiple circular bufers)를 유지합니다, 그리고 모든 로그 메시지가 디폴트 원형 버퍼에 전달되는 것은 아닙니다. 추가적인 로그 메시지를 보기 위해서는, 다른 원형 버퍼 보기를 요청하기 위해, -b 옵션을 이용할 수 있습니다. 아래는 사용가능한 버퍼 목록입니다.

  • radio — View the buffer that contains radio/telephony related messages.
  • events — View the buffer containing events-related messages.
  • main — View the main log buffer (default)

-b 옵션의 사용법은 다음과 같습니다.

[adb] logcat [-b <buffer>]

radio 와 telephony 메시지를 포함하는 로그 버퍼를 보기위한 예제는 다음과 같습니다.

adb logcat -b radio

stdout 과 stderr 보기

디폴트로, 안드로이 시스템은 stdout (표준 입력) 과 stderr (표준 에러) 를 /dev/null 로 보냅니다. Dalvik VM 을 실행하는 프로세스에 대해서는 시스템이 출력의 사본을 로그 파일에다가 작성하도록 할 수 있습니다. 이 경우, 시스템은 stdout 과 stderr 태그, 그리고 우선순위 I 를 가지는 메시지를 출력합니다.

이런식으로 출력을 재지정하기 위해서는, 실행중인 에뮬레이터/장치 인스턴스를 멈춥니다 그리고 출력 재지정을 활성화하기 위해 setprop 셀 명령을 사용합니다.

$ adb shell stop
$ adb shell setprop log
.redirect-stdio true

$ adb shell start

시스템은 에뮬레이터/장치 인스턴스가 종료될 때까지 이 설정을 유지합니다. 에뮬레이터/장치 인스턴스에서 이 설정을 디폴트로 사용하기 위해서는,  /data/local.prop 에다가 값을 추가해 주면 됩니다.

Web 애플리케이션 디버깅

안드로이드를 위한 웹 애플리케이션을 개발하고 있다면, 콘솔 JavaScript API 를 사용하여 JavaScript 를 디버그할 수 있습니다, 그리고 이것은 메시지를 LogCat 에 출력합니다. 상세한 정보는  Debugging Web Apps 를 보시기 바랍니다. 

원본: http://developer.android.com/guide/developing/debugging/debugging-log.html