메인 액티비티 실행이 안돼요

일반적으로 앱은 아이콘이 있다. 아이콘을 누르면 진입점 역할의 액티비티가 실행된다. 이 액티비티를 편의상 메인 액티비티라고 부르자.

메인 액티비티를 만드는 법은 간단하다. AndroidManifest.xml에 선언된 액티비티 중 메인으로 만들고 싶은 것을 골라 아래와 같이 MAIN 액션LAUNCHER 카테고리가 포함된 인텐트 필터를 추가하면 된다.

<intent-filter>
     <action android:name="android.intent.action.MAIN" /> 
     <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

위와 같이 인텐트 필터를 선언하면, 런쳐는 메인 액티비티로 판단하여 앱 슬롯에 아이콘을 표시한다.

그럼, 코드로 메인 액티비티를 실행해보자. 내 앱이라면 패키지 이름과 컴포넌트 이름으로 명시적 호출도 가능하다. 여기서는 암시적 인텐트를 이용해 보자.

adb shell am start <패키지이름>

패키지 이름만 건네면 앱의 메인 액티비티를 찾아 실행하는 명령어다. 위 명령어로 앱들을 실행해보면 어떤 앱은 실행되고 어떤 앱은 실행되지 않는다. 왜 그럴까?

실행여부는 <intent-filter>에 android.intent.category.DEFAULT가 있어야 있느냐에 따라 달라진다. DEFAULT 카테고리가 있어야 패키지 이름만으로 실행할 수 있는 것이다.

숨겨진 액티비티도 아니고 아이콘이 노출된 앱인데 코드로 실행할 수는 없다니 이상하다. 게다가, 메인 액티비티는 공개된 액티비티이므로 android:exported=”true”도 강제라고 한다. 그럼 외부에서 실행하는 것을 보장하겠다는 뜻이 아닌가?

이런 앞뒤가 맞지 않는 상황 때문인지 안드로이드의 PackageManager 클래스는  API3부터 getLaunchIntentForPackage()라는 설명이 재미있는 API를 제공한다.

Returns a "good" intent to launch a front-door activity in a package. 
...(이하 생략)

메인 액티비티를 실행하는 “좋은” 인텐트를 만들어 반환한다고 API 설명이 되어 있다. 하지만, 이 API도 MAIN 액션, LAUNCHER 카테고리를 가진 액티비티를 찾아 반환하는 것이므로 여전히 인텐트 필터는 필요하다.

메인 액티지티를 만들 때 DEFAULT 카테고리도 잊지 말고 추가하도록 하자. 다른 앱이 내 앱을 한 번이라도 더 실행하도록 말이다.

그 밖에

  • 한 앱에서 MAIN, LAUNCHER 속성을 2개 이상의 액티비티에 동시에 선언할 수 있으며, 이 때 아이콘이 각각 생긴다.
  • 아이콘의 레이블은 액티비티의 레이블을 따라간다. 그러므로, 아이콘을 다르게 여러 개 만들 수도 있다.

참조

블루라이트 앱 예제

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

만드는 방법은 화면에 필터를 씌워 파란색 광원을 줄인다. 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/* 아래 경로에 위치하지만, 권한이 없어 목록을 직접 확인할 수 없습니다.
  • 프리로드 앱 등은 다른 경로에 있을  수 있습니다.

 

Cleartext HTTP traffic to not permitted

P OS부터 targetSdk를 28로 올리면 네트워크 통신 시 아래와 같은 에러를 만날 수 있다.

08-21 18:15:53.165 16809-16917/me.sunphiz.android.test W/System.err: java.io.IOException: Cleartext HTTP traffic to <your-domain> not permitted
        at com.android.okhttp.HttpHandler$CleartextURLFilter.checkURLPermitted(HttpHandler.java:115)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:458)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:127)
        ...

IOException가 발생한 원인은 P OS부터 앱이 서버와 통신 시 TLS 기반하도록 기본값이 변경되었기 때문이다. 이해를 돕기 위해 여기서는 가장 많이 쓰이는 HTTP에 대해서만 살펴보자면 https만을 쓰라는 뜻이다(물론, TLS 기반 통신을 하라는 말이 https를 쓰라는 뜻은 아니다).  안드로이드의 네트워크 통신 기본 설정이 바뀐 이유에 대해서는 이 글을, https와 SSL/TLS의 관계에 대해서는 이 글을 참고하자.

과거 https 통신 시 최초 핸드쉐이크(handshake) 절차가 비싸다(자원 소비가 크다)기 때문에 필요에 따라 http와 https를 적절히 사용하는 것을 옳다고 이야기 하기도 했다. 하지만, 최근 네트워크와 장비의 성능 향상과 더불어 개인 데이터 보호 측면에서 모든 통신을 https로 하는 것이 좋다는 의견이 많으며, 개인적으로도 옳다고 본다.

수정 방법은 크게 두 가지다. 하나는 시대에 흐름에 맞춰 모든 통신을 https 기반으로 고치는 것이다.  다른 하나는, http로 통신할 서버를 xml 파일에 열거하면 된다. 모든 통신을 갑자기 https로 바꾸는 것은 어려우니 여기서는 xml 파일을 통해 문제를 해결해보자.

<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">insecure.example.com</domain>
        <domain includeSubdomains="true">insecure.cdn.example.com</domain>
    </domain-config>
</network-security-config>

안드로이드 가이드에서는 위처럼, http를 이용해 통신할 서버의 도메인을 모두 열거하고 나머지는 https를 사용하도록 권장한다. 만약 통신하는 서버의 dns를 모두 열거할 수 없거나, 모든 통신을 http로 하는 경우라면 아래처럼 기본값을 바꿀 수도 있다.

<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

위와 같이 하면 모든 clearText 통신이 허가되므로, 기본값이 바뀐 셈이다. 하지만 장기적으로는 모두 https 통신을 하는 것이 좋을 것이다.

참조