startActivity가 안돼요

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

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

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

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

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

그 밖에

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

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

참고

댓글 남기기

이메일은 공개되지 않습니다.

This site uses Akismet to reduce spam. Learn how your comment data is processed.