안드로이드에서 adb shell로 apk 추출하기

adb shell을 이용한 apk 추출 가이드는 그림과 함께 친절히 작성된 글이 인터넷에 이미 많이 있습니다. 개인적 기록 차원에서 적어둡니다.

설치된 패키지를 찾습니다.

>adb shell pm list packages | find "<패키지 이름이나 키워드>"

apk의 정확한 패키지 이름 확인 후, apk 설치 위치를 확인합니다.

>adb shell dumpsys package <패키지 이름> | find "path"

apk 설치 위치를 찾은 후 apk를 명령창이 실행되고 있는 현재 경로로 꺼냅니다.

>adb pull <apk 저장 경로>

 

그 밖에

  • P OS 단말에서 테스트 되었습니다.
  • 다운로드 받아 설치한 apk는 /data/app/* 아래 경로에 위치하지만, 권한이 없어 목록을 직접 확인할 수 없습니다.
  • 프리로드 앱 등은 다른 경로에 있을  수 있습니다.

 

adb shell로 대량의 apk 설치하기

많은 apk 파일을 한꺼번에 설치해야하는데 스크립트까지 만들기도 귀찮다면, adb shell을 이용해보자.

  1. 설치할 apk 파일들을 단말에 먼저 옮긴 후
  2. 루프문으로 설치하게 하면 된다.

각각의 명령어는 아래와 같다.

>adb push ./apk /sdcard/

>adb shell for apk in /sdcard/*.apk; do pm install -r $apk ; done

이 때 adb shell에서는 모든 파일 선택 특수문자가 없으니, 폴더를 지정하여 넣는 것에 주의하자.

끝나고 설치가 잘 되었는지 궁금하다면 pm 명령어를 이용하면 된다.

>adb shell pm list package

참조

인텔리 제이에서 시스템 정보 확인하기(adb shell dumpsys)

안드로이드는 리눅스를 기반으로 한 운영체제 이기때문에 쉘(shell)을 사용할 수 있고 다른 글에서 쓴바 있다. 그리고 그 쉘에서 dumpsys라는 툴을 이용하면 안드로이드의 관심있는 서비스(?) 정보를 매우 자세하게 뽑아낼 수 있다. 이에 대한 자세한 설명은 안드로이드 개발자 사이트에 잘 정리되어 있기도 하다.

하지만, 번거롭다. 명령창을 통해  실행해야 하는데, 대부분의 개발자가 있는 줄 알면서도 안쓰게 만드는 가장 큰 이유다.

인텔리 제이 IDE에서 adb shell dumpsys 를 통해 확인하던 시스템 정보(System Information)을 추출할 수 있는 방법을 제공한다. Android DDMS 패널의 좌측 메뉴 중에 돋보기 모양의 “System Information” 버튼을 이용하면 된다.

android_ddms

제공하는 기능은 Community version 기준으로 다음과 같다.

  • Activity Manager State
  • Package Information
  • Memory Usage
  • Memory Use Over Time
  • Graphics State

단말이 연결된 상태에서 프로세스를 하나 선택해 메뉴가 활성화된다. 각 명령은

adb shell dumpsys [서비스 이름] [프로세스 번호 | 패키지 이름]

과 매치된다.  예를 들면, Memory Usage를 adb shell dumpsys를 통해 보려면

adb shell dumpsys meminfo android.my.app

라고 치는 식이다.

adb shell dumpsys를 이용하면 더많은 정보를 볼 수 있지만, adb 실행이나 매번 바뀌는 프로세스 번호 같은 것을 기억하지 않아도 된다는 점을 생각하면 역시 편리하다. dumpsys 툴 이이야기가 나온 김에 어떤 서비스 정보를 추출할 수 있는지 잘 정리된 링크도 걸어둔다.

그리고, 가장 많이 쓰는 기능은 모두 모여 있으니 애용해보자.

안드로이드의 유용한 shell 커맨드

앱 메모리 정보 확인하기

안드로이드는 리눅스 기반 O/S로 쉘을 사용할 수 있다. 가장 기본은

adb shell

인데, 위의 명령어만 치면 shell로 진입한다. 그 후 안드로이드에서 지원하는 명령창 툴들을 사용할 수 있다. 하지만, shell로 진입하는게 부담스럽다면

adb shell dumpsys

와 같이 shell 다음에 바로 툴을 입력할 수도 있다. 위 명령어는 너무 많은 데이터를 한번 쳐보면 알겠지만, 너무 많은 데이터가 보인다. 그래서 어떤 서비스의 정보만 보고 싶은지 ‘meminfo’와 같이 추가적으로 서비스 이름을 바로 입력할 수 있다.

adb shell dumpsys meminfo

meminfo는 짧을 것 같지만 여전히 길다. 메모리의 모든 정보를 알고 싶은 경우는 별로 없다. 전체 메모리 사용 자료 중에서 원하는 앱만 찾기가 쉽지 않은데, Linux의 grep과 같이 동작하는  윈도우의 커맨드 중 find 같은 것을 사용하면 유용하다.

adb shell dumpsys meminfo | find "com.google.android"

예를 들어 위와같은 명령어를 입력하면, 아래와 같이 메모리 정보중에서 com.google.android라는 문자열을 가진 열만 데이터가 출력된다.

C:\Java\android-sdk\platform-tools>adb shell dumpsys meminfo | find "com.google.android"
    15078 kB: com.google.android.apps.plus (pid 15239)
    13311 kB: com.google.android.gms (pid 15272)
    11854 kB: com.google.android.googlequicksearchbox:search (pid 18999)
     9254 kB: com.google.android.music:main (pid 19964)
     9038 kB: com.google.android.talk (pid 18976)
     5213 kB: com.google.android.gsf.login (pid 19246)
     3542 kB: com.google.android.partnersetup (pid 19047)
               15078 kB: com.google.android.apps.plus (pid 15239)
               13311 kB: com.google.android.gms (pid 15272)
               11854 kB: com.google.android.googlequicksearchbox:search (pid 18999)
                9254 kB: com.google.android.music:main (pid 19964)
                9038 kB: com.google.android.talk (pid 18976)
                5213 kB: com.google.android.gsf.login (pid 19246)
                3542 kB: com.google.android.partnersetup (pid 19047)

혹은 아래와 같이 바로 프로세스 번호나 패키지 이름을 쳐도 된다.

adb shell dumpsys meminfo [프로세스 번호|패키지 이름]

Application manager에서 versionCode나 versionName을 확인할 수 있다. 만약 adb 명령어를 이용해 커맨드로 하고 싶다면 아래와 같이 할 수 있다.

adb shell dumpsys package [package name] | find [versionCode|versionName]

위와 같이 입력하면 패키지 정보 중에서 versionCode나 versionName이 표시되는 부분만 결과로 표시된다.

 설치된 어플리케이션 목록 보기

어플리케이션에 설치된 앱의 정보를 AndroidManifest.xml 안의 package name 기준으로 보고 싶다면 아래 명령어가 유용하다.

adb shell pm list packages

위 명령어는 전체 목록이 나오는데 한 어플리케이션이 설치되었는지 확인하고 싶다면 뒤에 패키지 정보를 붙이면 된다.

adb shell pm list packages [패키지 이름]

예를 들면,

com.samsung.android.emailsync

와 같다.

설치된 어플리케이션 강제 종료

강제종료는 Settings > Application manager 메뉴를 통해 할 수 있다. 만약 adb 명령어를 이용해 커맨드로 하고 싶다면 아래와 같이 할 수 있다.

adb shell am force-stop  [package name]

참고로, 안드로이드 스투디오나 DDMS 등에서는 앱을 죽이는 버튼(보통, 빨간색에 X 자 마크)도 제공한다.

설치된 어플리케이션 데이터 삭제/캐시 삭제

데이터 삭제/캐시 삭제는 Application manager에서 한다. 만약 adb 명령어를 이용해 커맨드로 하고 싶다면 아래와 같이 할 수 있다.

adb shell pm clear [package name]

참고로,  Application Manager에서 패키지 명에 해당하는 앱의 상세정보 창을 보는 상태에서 위 명령을 시도해보면, “success”라는 결과가 나와도 창의 정보는 업데이트 되지 않는다. 그래도 삭제는 제대로 된 것이니 신경쓰지말자. 잘 지워졌는지 추가적으로 확인하고 싶다면, 다른창으로 이동했다가 다시 오면 지워져있다.

Preference 보기

Preference는 데이터를 XML 형식으로 파일에 저장해두는 것이다. 그러므로, Preference 파일의 위치만 안다면 리눅스의 cat과 같이 파일을 읽는 명령어를 통해 파일의 내용을 들여다 볼 수 있다.

adb shell cat /data/data/[package name]/shared_prefs/[preference name].xml

예를 들면 아래와 같이 쓸 수 있겠다.

adb shell cat /data/data/me.sunphiz.android.test/shared_prefs/my_preference.xml

Intent가 바르게 전달되었는지 확인하기

다른 앱 간 intent를 통한  전달이 잘 되었는지 확인해야할 때가 있다. (아무래도 네탓 내탓 공방을 할때..) 이 때, 아래의 명령어를 사용하면 컴포넌트가 어떤 Intent를 받을 때 어떤 데이터를 받았는지 확인해 볼 수 있다.

adb shell dumpsys activity activities

위 명령어를 실행하면, 현재 단말의 테스크가 나오고 상세 정보에 받은 Intent 정보가 들어 있다. 예를 들면,

ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
  Stack #0:
    Task id #92
    * TaskRecord{1392a53e #92 A=com.sec.android.app.launcher U=0 sz=1}
      userId=0 effectiveUid=u0a2 mCallingUid=0 mCallingPackage=null
      affinity=com.sec.android.app.launcher
      intent={act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10800000 cmp=com.sec.android.app.launcher/com.android.launcher2.Launcher}
      realActivity=com.sec.android.app.launcher/com.android.launcher2.Launcher
      autoRemoveRecents=false isPersistable=false numFullscreen=1 taskType=1 mTaskToReturnTo=0
      rootWasReset=false mNeverRelinquishIdentity=true mReuseTask=false
      Activities=[ActivityRecord{d2a87de u0 com.sec.android.app.launcher/com.android.launcher2.Launcher t92}]
      askedCompatMode=false inRecents=true isAvailable=true
      lastThumbnail=null lastThumbnailFile=/data/system/recent_images/92_task_thumbnail.png
      hasBeenVisible=true firstActiveTime=1433815768381 lastActiveTime=1433815768381 (inactive for 3s)
      * Hist #0: ActivityRecord{d2a87de u0 com.sec.android.app.launcher/com.android.launcher2.Launcher t92}
          packageName=com.sec.android.app.launcher processName=com.sec.android.app.launcher
          launchedFromUid=0 launchedFromPackage=null userId=0
          app=ProcessRecord{356c1b02 1500:com.sec.android.app.launcher/u0a2}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10800000 cmp=com.sec.android.app.launcher/com.android.launcher2.Launcher }
          frontOfTask=true task=TaskRecord{1392a53e #92 A=com.sec.android.app.launcher U=0 sz=1}
          taskAffinity=com.sec.android.app.launcher
          realActivity=com.sec.android.app.launcher/com.android.launcher2.Launcher
          baseDir=/system/priv-app/TWLauncherESS/TWLauncherESS.apk
          dataDir=/data/user/0/com.sec.android.app.launcher
          stateNotNeeded=true componentSpecified=false mActivityType=1
          compat={320dpi} labelRes=0x7f0d002e icon=0x7f02006e theme=0x7f0e001f
          config={0 1.0 themeSeq=0 ?mcc?mnc ko_KR ?layoutDir sw360dp w360dp h616dp 320dpi nrml long port finger -keyb/v/h -nav/h s.5}
          taskDescription: iconFilename=null label="null" color=ff00a5c4
          launchFailed=false launchCount=0 lastLaunchTime=-1m3s494ms
          haveState=false icicle=null
          state=RESUMED stopped=false delayedResume=false finishing=false
          keysPaused=false inHistory=true visible=true sleeping=false idle=true
          fullscreen=true noDisplay=false immersive=false launchMode=2
          frozenBeforeDestroy=false forceNewConfig=false
          mActivityType=HOME_ACTIVITY_TYPE
          waitingVisible=false nowVisible=true lastVisibleTime=-1m1s817ms

처럼 Intent의 act(액션), cat(카테고리), flg(플래그), cmp(컴포넌트)를 볼 수 있고, 여기에는 없지만, dat(데이터)를 통해 전달된 데이터도 확인할 수 있다. 다만, extra는 확인할 수 없으니 주의하자.

와이파이 켜고 끄기

svc 명령어를 이용하면 와이파이(WiFi)를 켜거나 끌 수 있다.

>adb shell svc wifi enable
>adb shell svc wifi disable

 

참고