System 앱의 퍼미션 획득

설명하기 번거롭고 아무도 궁금해하지 않는 System 앱의 permission 획득(granted)에 대해 알아보자. 미리 이야기 할 것은, 안드로이드의 permission 중 protectionLevel이 system인 것은 없다. 대신 signatureOrSystem이 있는데, 이 permission의 획득 방법 두 가지이며 그 중 system 앱으로서 획득하는 방법에 대해 설명하고자 한다.

설명을 하기 위해서는 먼저 앱을 단말 내장 여부에 따라 구분해야 한다. 앱을 내장 여부에 따라 구분하는 일이 적어서 용어가 정착되지 않았는데, 여기서는 스토어/프리로드 앱으로 표현하겠다.

  • 스토어(store) 앱 : 단말에 내장되어 있지 않고, 단말 제조사나 구글의 앱 스토어에서 받아 설치(or 업데이트)할 수 있다. 일반 앱이나 서드파티 앱이라고도 부른다.
  • 프리로드(preload) 앱 : 단말에 내장되어 있고, 단말 제조사나 구글의 앱 스토어에서 업데이트 할 수도 있다.

프리로드 앱 중에서 특히 /system/priv-app/ 에 설치된 앱을 system 앱이라 한다. 혹은 프리빌리지드(privileged) 앱이라고도 부른다. 이 앱이 protectionLevel가 signatureOrSystem인 permission을 획득(granted)할 수 있다.

system 앱으로서 permission을 획득하는 방법을 설명했으니, permission에 영향을 줄 수 있는 system 앱의 특성을 살펴보자.

이를 위해서는 먼저 두 앱 간 설치/업데이트/삭제 시 차이점을 설명해야 한다. 스토어 앱은 최초 설치 시 /data/app/에 자리를 잡고, 업데이트 시에도 같은 위치에 덮어 씌운다. 삭제 시 업데이트 여부에 관계없이 /data/app/에 설치되었던 앱과 데이터가 사라진다.

프리로드 앱은 최초 설치 시 /system/priv-app/에 자리 잡고, 업데이트 시 /data/app/에 자리 잡는다. 삭제는 업데이트 여부에 따라 다르다. 최초 버전은 삭제할 수 없고, 업데이트 버전만 삭제할 수 있다. 삭제 시 /data/app/에 설치되었던 업데이트 버전의 앱이 사라진다.

이를 설명한 이유는 system 앱은 최초/업데이트 버전 여부에 따라 설치위치가 달라지고, 이에 따라 permission 획득도 달라질 수 있기 때문이다. 업데이트 버전에 <user-permission/> 선언을 신규추가한 경우 protectionLevel이 signatureOrSystem인 permission을 획득할 수 없다. 위에 설명한 것 처럼 업데이트 버전은 /system/priv-app/이 아닌 /data/app/에 설치되기 때문이다.

다만, 내장된 버전이 AndroidManifest의 <use-permission> 선언을 통해 이미 획득한 permission은 업데이트 버전도 선언만 하면 상속받는 것처럼 획득할 수 있다. 꼭 새 permission을 system 앱으로서 획득하고 싶다면 바이너리에 포함해야 한다.

그 밖에

  • 안드로이드의 permission에 4가지 protectionLevel에 대한 소개는 이 글을 확인하자.
  • 프리로드 앱은 system 앱 외에 다른 종류도 있다. 최초 부팅 시에 설치 되어있지만, 삭제 가능하며 단말 초기화(factory reset) 시 다시 설치된다. 이들은 /data/app/에 설치되므로 단말에 내장된 점을 제외하고 일반 앱과 같다.
  • 처음에 system앱은 /system/이하에 설치되는 앱을 말하며 system앱 모두가 권한을 가졌다. 그러나, /system/priv-app/에 설치되는 앱에만 권한을 주도록 정책이 축소&변경된다.  (아마도) 이 때 system앱과 구별하기 위해 previleged 앱이라 부르다 현재는 특별한 권한을 가진 앱을 가리킨다는 점에서 혼용하는 것 같다.

참조

 

startActivity가 안돼요

startActivity 메소드(startActivityForResult 메소드 포함)는 파라미터로 전달된 인텐트(Intent) 정보로 액티비티를 실행한다. 안드로이드 책 처음마다 이 메소드 소개는 빠지지 않는다. 그렇게 많이 사용하는데, 왜 안될까?

확인이 쉬운 것부터 살펴보자. 액티비티 호출을 위해 만드는 인텐트 유형은 명시적 인텐트와 암시적 인텐트로 나뉜다. 인텐트를 잘 만들었는지 살펴보자.

  • 명시적 인텐트는 호출할 대상 패키지와 패키지 속 액티비티 정보를 넣어야 한다. 명시적 인텐트를 통해 호출을 시도했으나 에러가 난다면 패키지나 액티비티 이름이 틀린 것은 아닌지 확인해보자.
  • 암시적 인텐트는 액션(action)을 이용하므로, 액션이 틀렸는지 확인하자.

intent에 넣은 정보가 맞는데도 안되는 경우도 있다. 그럼, 다음 경우도 생각해 보자.

  • 암시적 인텐트를 사용할 때 액션과 함께 전달하는 추가정보가 잘못 되었는지 확인하자.  예를 들면, AndroidManifest.xml에 액티비티가 처리할 수 있는 URL 스키마를 선언할 수 있다. 이 설정과 전달하는 url 데이터가 맞지 않다면 실행되지 않는다.
  • 퍼미션이 필요한지 확인하자. 안드로이드의 컴포넌트는 자신을 호출하는 앱이 퍼미션을 갖고(granted)있어야 실행하도록 강제할 수 있다. 퍼미션이 없다면 Exception이 발생한다.
  • 액티비티가 앱 외부에서 공개되지 않게 설정되었을 수도 있다. AndroidManifest.xml 내의 액티비티 컴포넌트 선언부의 android:exported 어트리뷰트가 true인지 확인하자. 참고로, 기본값이 true다.
  • intent에 넣은 정보가 맞는데도 실행이 안된다면 앱이 설치되었는지 확인하자. 앱 슬롯이나 셋팅 내 어플이케이션 목록을 통해 확인할 수 있다.
  • 설치가 되었는데도 실행되지 않는다면 앱이 비활성화 됐을 수 있다. 셋팅 내 어플이케이션 목록에서 앱을 찾아, 사용하지 않기(비활성화)로 둔 것은 아닌지 확인해보자.
  • 혹시, MAIN 액션과 LAUNCHER 카테고리를 가지는 일명 메인 액티비티가 실행되지 않는다면 이 글을 읽어보자.

그 밖에

액티비티를 실행할 때는 가능하다면 암시적 인텐트를 이용하자.

  • 같은 액션을 활용하는 모든 앱이 사용자에게 표시되므로 사용자에게 선호하는 앱을 이용할 수 있게 선택권을 줄 수 있다.
  • 호출할 액티비티의 패키지 이름이 바뀌더라도 명시적으로 컴포넌트를 선언하지 않기 때문에, ActivityNotFoundException과 같은 문제가 발생하지 않는다.
  • 액티비티 정보는 쉽게 알 수 없으니 명시적 인텐트가 안전하다고 생각하는 경우가 있다. dumpstate의 설치된 앱 정보 등을 통해 액티비티를 알아낼 방법은 다양하므로, 호출은 모두 가능하다. 잘못된 값이 전달될 위험은 값을 validation하여 대응하고, 사용 자체를 막고자 한다면 퍼미션을 활용하자.

참고

블루라이트 앱 예제

시력에 나쁜 영향을 주는 블루라이트를 감소시키는 앱이 구글 플레이 스토어에 많이 올라와 있다. 블루라이트를 감소시키는 원리는 간단한데, 파란색 표현량을 줄여서 눈에 부정적인 영향을 줄이는 것이다.물론, 색표현이 왜곡되지만 사진이나 영상을 보는 경우를 제외하면 사용에 문제가 없기 때문에 사람들이 많이 사용한다.

만드는 방법은 화면에 필터를 씌워 파란색 광원을 줄인다. WindowsManager를 이용해 이에 대한 샘플을 만들어 보았다.

자세한 내용과 소스는 Github에 있어요.

device-2014-10-15-141315 device-2014-10-15-141335

참고

AdapterViewFlipper을 이용한 위젯 예제

AdapterViewFlipper를 이용한 appwidget이 가능하다고 android.com에 나와있지만, 돌아가는 샘플은 찾을수가 없어 만들게 되었습니다.

자세한 내용과 소스는 Github에 있어요.

device-2013-08-21-115836

이제 위의 viewflipper를 활용해 멋진 위젯을 만들 수도 있겠죠?

안드로이드에서 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/* 아래 경로에 위치하지만, 권한이 없어 목록을 직접 확인할 수 없습니다.
  • 프리로드 앱 등은 다른 경로에 있을  수 있습니다.