1. 아이콘, 앱 이름 등을 삭제하는 것이 좋다.
만약 라이브러리를 사용하는 앱의 아이콘 이름과 라이브러리에 있는 아이콘 파일의 이름이 같다면 앱 아이콘이 라이브러리의 것으로 덮여씌워질 수 있다. 앱 이름도 마찬가지다.
이는 매니페스트 병합 규칙 마커를 사용한다고 해도 마찬가지다.
마찬가지의 이유로 라이브러리에서 사용하는 컬러, 테마 같은 리소스 이름은 고유해야한다.
패키지 이름의 일부를 이름에 적어넣도록 하자.
2. 매니페스트 병합을 신경쓰자
라이브러리를 쓴다는 것은 앱이 하나 이상의 매니페스트파일을 가지게 됨을 의미한다. 따라서 매니페스트 병합에 관한 규칙을 숙지할 필요가 있다. 그렇지 않으면 라이브브러리의 매니페스트 속성이 앱의 매니페스트 속성을 덮어씌워버릴 수가 있다.
다중 manifest 파일 병합 | Android 개발자 | Android Developers
manifest 병합 및 manifest 병합 도구에 관해 자세히 알아보세요.
developer.android.com
이러한 버그들은 앱에 어떤 영향을 끼칠지 예측하기 쉽지 않고 문제가 생겼을때 조기에 발견하기 까다롭기 때문에 숙지해야한다.
3. FileProvider를 유의해서 쓰자
먼저 FileProvider란 무엇인가?
<paths>
<external-files-path name="externalStorage" path="."/>
<external-cache-path name="cache_files" path="." />
<files-path name="internalStorage" path="."/>
<cache-path name="cache" path="."/>
</paths>
요렇게 생긴 놈인데, 자세한 내용은 여기를 참고하자
간단히 말하면 저 xml 파일에서 특정 경로를 미리 선언해두고, 그 경로에 대한 임시적인 읽고쓰기 권한을 가진 content 스키마의 uri를 만들 수 있는 녀석이다.
이 content uri는 읽기,쓰기 권한을 가진 uri다.
예를들어 내 앱에서 만든 파일을 가리키는 content uri를 카메라에 앱에 넘겨줘서 카메라앱이 사진을 찍고, 아웃풋을 그 uri가 가리키는 파일에 저장한다는 식으로 사용한다.
내 앱이 만든 파일이 다른 앱에 마구잡이로 접근되면 보안상 문제가 있으니까 이런 제한된 방식으로 다른 앱에 content uri를 제공하나보다.
아무튼 이 fileProvider라는 녀석을 라이브러리에서 쓸때는 유의해야할 점이 있다.
기본적으로 앱은 고유의 fileProvider를 가져야한다. 핸드폰에 이미 같은 fileProvider를 가진 앱이 존재하면 앱이 설치되지 않는다.
만약 라이브러리에 A라는 파일프로바이더가 있는데, B와 C가 A라이브러리를 사용한다면 곧 같은 파일프로바이더를 사용하게 되니 B와 C는 같은 핸드폰에 설치될 수 없다.
이 문제를 해결하려면 파일 프로바이더 속성중에 android:authorities 를 주목해야한다.
<provider
android:name="com.moongchipicker.util.MoongchiFileProvider"
android:authorities="com.moongchipicker.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
파일 프로바이더는 authorities 를 통해 구분한다. 같은 authorities를 쓰는 파일프로바이더가 있는 앱을 동시에 설치할 수 없다.
따라서 저 android:authorities에 앱마다 고유한 값을 줘야한다.
android:authorities="${applicationId}.provider"
이런 식으로 주면 applicationId에 getContext().getApplicationContext().getPackageName() 으로 구한 패키지이름이 들어간다. 그러면 이 라이브러를 쓰는 앱마다 고유한 authorities가 지정된다.
이 applicationId는 빌트인 build variable이다.
사용시에는
val uri = FileProvider.getUriForFile(getContext(), getContext().getApplicationContext().getPackageName() + ".provider", mediaFile);
이런식으로 사용하면 된다.
* 사족
1. debug와 release 앱을 한 핸드폰에 설치할 수 없다.
Build.gradle 에서 applicationIdSuffix ".debug" 를 이용해서 build Varient마다 앱을 한 핸드폰에 설치하고 싶을 수 있다.
그러나
fileProvider는 앱마다 고유하지만, build Varient 마다 고유하지는 못하다. 따라서 debug앱과 release앱은 하나의 핸드폰에 설치할 수 없다.
Build Varient마다 다른 authorities를 주면 어떨까?
간혹 페이스북 같은 third party library 를 사용하다보면
<provider
android:name="com.facebook.FacebookContentProvider"
android:authorities="com.facebook.app.FacebookContentProvider${facebookKey}"
android:exported="true" /> <!-- kakao -->
이렇게 파일 프로바이더를 지정해줘야할때가 있다.
여기서 저 authorities를 함부로 바꾸면 안된다.
FileProvider.getUriForFile() 함수의 두번째 파라미터가 저 authorities 값이기 때문이다.
이럴때는 Build Varient마다 다른 authorities를 주는 방법도 못한다.
2. 라이브러리와 앱의 provider 충돌
라이브러리에서 provider name 속성에 androidx.core.content.FileProvider 를 가급적 사용하지 말고
com.moongchipicker.util.MoongchiFileProvider 처럼 커스텀 FileProvider를 만들어 사용하자.
provider의 name이 중복되면 앱쪽에서 빌드가 안되기 때문이다.
커스텀 fileProvider를 만드는 방법은 그냥 FileProvider를 상속받는 클래스를 하나 만들면 된다.
class MoongchiFileProvider : FileProvider() {
}
'안드로이드 앱개발' 카테고리의 다른 글
이미지 피커 라이브러리 <뭉치피커> 개발기 (0) | 2022.03.29 |
---|---|
딥링크, 앱링크, 디퍼드 딥링크, 다이나믹링크와 광고의 연결 (0) | 2022.03.28 |
사내 카페 주문앱 개발기(1): 클린아키텍쳐 (0) | 2021.11.27 |
레거시 코드 리팩토링과 코틀린 마이그레이션 (0) | 2021.09.15 |
Service (0) | 2021.09.04 |