전체 글 (24)

Android Platform 은 사용자에게 좀 더 안전한 환경을 제공하고자 단문 통신인 http 를 지양(!)하고자했습니다.

그래서, Android 6.0(M) 에서부터 AndroidManifest.xml 파일에 android:useClearTextTraffic 이란 attribute 를 제공하기 시작,

이 attribute 를 false 로 선택할 경우, App 내부에서 http 단문 통신을 하고자 할 경우, Platform 에서 트래픽을 막았습니다.

물론, 이 속성은 Api level = 28 (Android 8.0(P)) 까지 기본적으로 false 입니다.

<application android:usesCleartextTraffic="true"/>

 

이 값으로는 약간 부족하다고 생각했었는지, Android 7.0(N, 24) 에서는 android:networkSecurityConfig 라는 attribute 를 추가했습니다. 이 속성 값에는 cleartextTrafficPermitted 를 기술한 xml 파일(아래 코드 참조)을 값으로 추가할 수 있습니다. 이 xml 파일에는 이전보다는 좀 더 자세한 사항들을 기술할 수 있습니다. 예를 들어, 아래 예제처럼 도메인 단위의 http 트래픽을 허용할 것인지 아닌지를 기술할 수 있습니다.

<application
	android:networkSecurityConfig="@xml/network_security_config"/>
<?xml version="1.0" encoding="utf-8"?> 
<network-security-config> 
	<base-config cleartextTrafficPermitted="false"/> 
	<domain-config cleartextTrafficPermitted="true">         
		<domain includeSubdomains="true">develop-branch.tistory.com</domain>        
	</domain-config> 
</network-security-config>

 

 

여기서 주의할 점은 <base-config> 를 설정하지 않을 경우 기본 값을 따르며, android:useClearTextTraffic 보다 android:networkSecurityConfig 를 더 우선한다는 점입니다. 쉽게 얘기하면, android:useClearTextTraffic=false 로 지정하더라도 android:networkSecurityConfig xml 값이 지정되어 있다면, xml 에 기술된 값을 우선시 한다는 것입니다.

 

아래 표는 AndroidManifest.xml 에서 android:useClearTextTraffic=[값없음,true,false] 일 때, android:networkSecurityConfig 파일에서 cleartextTrafficPermitted=[값없음,true,false] 값에 대해 각각 NetworkSecurityPolicy.getInstance().isCleartextTrafficPermitted() 값을 보여주고 있다.

 

networkSecurityConfig :

xml 파일 지정하지 않음

networkSecurityConfig :

xml 파일 지정함

   

cleartextTrafficPermitted = 값없음

cleartextTrafficPermitted = true

cleartextTrafficPermitted = false

useClearTextTraffic = 값없음

true (Default)

true (Default)

true

false

useClearTextTraffic = true

true

true (Default)

true

false

useClearTextTraffic = false

false

true (Default)

true

false

물론, 이 값은 AndroidManifest.xml 파일에서 targetSdkVersion < 28 로 설정한 경우입니다.

targetSdkVersion >= 28 이라면, true (Default) 가 false (Default) 로 바뀝니다.

 

* 코드 상에서 이 값을 확인하는 방법은 크게 두 가지입니다.

A)

context.packageManager.getApplicationInfo("com.example").flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC

B)

NetworkSecurityPolicy.getInstance().isCleartextTrafficPermitted()

 

A) 안은 일반적으로 AndroidManifest 에 기술된 값을 얻을 때 사용하는 방법이며, B) 안은 Api Level 23 에서 정의된 클래스를 이용한 것입니다.

B) 는 A) 를 포함하고 있고, 코드도 간결하기 때문에, B) 를 사용하는 것이 좋습니다.

추가로 A) 안은 API Level 23 이하에서도 사용가능한 방법이기 때문에, Build.VERSION.SDK_INT 로 제한하지 않을 경우, 오동작할 수 있습니다. 물론, 위의 내용은 일반적인 HTTP 통신인 경우(URL, UrlConnection 같은 객체를 사용하는 경우)입니다.

 

WebView 에서는 위와 조금 다르게 동작합니다. https://developer.android.com/reference/android/security/NetworkSecurityPolicy 을 참고하면, 아래와 같은 노트를 확인할 수 있습니다.

isCleartextTrafficPermitted
...
NOTE: WebView honors this flag for applications targeting API level 26 and up.

말인 즉슨,  WebView 에서는  targetSdkVersion이 26 보다 같거나 큰 경우에만, 동작한다는 것이다.

위에서 언급한 useClearTextTraffic 이나 networkSecurityConfig 값을 false 로 설정하더라도 targetSdkVersion 이 26 보다 낮을 경우, WebView 에서는 HTTP 단문 통신이 가능하다는 것이다.

 

엄밀히 말하면, 이는 Android 7.0, 24 에서 기본 적용된 Chrome WebKit 53.0 이상 버전에서 적용되는 사항입니다.

Android 6.0, 23 에서 적용된 Chrome WebKit 44.0 버전에서는 적용되지 않습니다.

즉, Android 6.0, 23, 의 기본 Chrome WebKit 44.0 을 업데이트 하지 않은 상황이라면, 어떤 설정을 적용하더라도 WebView 에서 HTTP 통신이 가능합니다.

 

종합하면 WebView 의 경우, targetSdkVersion>=26 으로 설정하고, Chrome WebKit 53.0 이상 버전을 사용한다면, (일반적으로 Android 7.0 24 이상의 단말), isCleartextTrafficPermitted 설정이 적용될 수 있습니다.

'Android' 카테고리의 다른 글

Android targetSdkVersion=30, queryIntentActivities() 문제  (0) 2022.01.10
Gson - Android Proguard 문제  (0) 2020.11.12
Android Studio - Database Inspector  (0) 2020.11.04
Android AlertDialog Style 변경  (0) 2020.08.05
Android Custom Lint  (0) 2020.07.28

 

잡담처럼 코로나 라는 단어를 등록정보에 추가했다가 플레이스토어에서 정지되었습니다.

악의적인 경우들을 방지하기 위해 이런 정책들이 최근에 추가된 것 같습니다.

 

 

 

이 상황이 매우 당황스러웠는데, 이 상태가 되면, 구글 플레이스토어 내에서 이 앱에 대해 어떤 수정도 허용되지 않습니다.

무슨 말인고 하면, '코로나' 라는 단어를 썼다는 것 때문에, 정지된 것인데, '코로나' 라는 단어를 지울 수 없는 상황이 되어버립니다.

불행 중 다행으로, 플레이 스토어에 실수로 단어를 언급한 것이니 계정 상태를 풀어달라고 (메일 내용 중 이의제기 링크를 통해) 정책지원팀에 메일을 보내면, 확인 뒤, 상태가 변경됩니다.

그리고, 등록정보 변경이 되더라도 플레이 스토어에 게시되지 않는 경우가 있는데, 이 때에는 새 버전(apk or abb)을 업데이트 해주어야 합니다.

'Chat' 카테고리의 다른 글

구글 플레이 스토어 - 부적절한 광고 정책  (0) 2020.09.23

Software Develop

Code Kata

2020. 4. 23. 16:46

 

클린 코더(The Clean Coder, 단순기술자에서 진정한 소프트웨어 장인이 되기까지) - 6장 연습 을 읽다가...

Kata - 품새, 형 - 이라는 말이 나와서 간단한 글을 남겨 둡니다.

 

이를 테면, 카타는 준비 운동 같은 것입니다.

태권도에서도 품새같은 걸 연습하듯이, ('클린 코더'에서 역자는 Kata 를 품새로 번역을 했습니다.)

뭔가 코딩을 하기 전에 잠시 연습삼아 해보는 코딩을 말하는 것입니다.

저자는 매일 정해진 코딩을 하는 듯 한데, 찾아보니 https://www.codewars.com/ 에 적당한 연습 문제들이 꽤 있는 것 같습니다.

 

첫 Kotlin Kata 는 아래였습니다.

fun multiply(x: double, y: double) => x * y

잘 실행되도록 고치라는 것인데, 생각보다 대단치 않은 함정들이 있습니다.

(컴파일 후 나오는 어떤 에러메시지를 참조하지 않고, 단순히 에디터로 풀어보는 것도 괜찮습니다. ㅋㅋ)

 

저자는 마치 운동을 하기전, 준비 운동도 하고, 운동을 마친 후, 몸 풀기? 마무리 운동을 하는 것처럼 Kata 를 한 번씩 해보라는 정도입니다.

어떤 운동을 하기 전에 이런 준비/마무리 운동을 하는 것은 부상을 예방하거나 근육에 무리를 덜 가게 한다던가 하는 연구 결과들이 있을 듯 하지만, 코드 카타는 솔직히 그런 연구 결과들이 나오기는 어려운 녀석임에는 틀림없습니다.

코딩을 하기 전에 연습문제 하나 풀었다고 버그의 갯수가 줄어든다던가 혹은 만드는 시간이 줄어들었다던가 하는 것들은 측정하기 어려운 일일 것입니다. (S/W 개발 분야가 대부분 측정하기 힘든 것들 투성이이긴 합니다. ㅋ)

 

하지만, 간혹 Best Practice 나 남들이 풀어놓은 것들을 보다 보면, 평소에 내가 잘 모르던 api 들을 알게 될 수도 있고, 이런 식으로 코딩을 할 수도 있구나 하고 얻게 되는 것들도 있습니다.

그리고, 비록, 코딩하는데 도움이 될지/아닐지, 좋아/나빠 를 똑 부러지게 이야기하기는 어렵지만, 좋은것 같다? 나쁘지는 않다 정도

며칠 혹은 몇주간 매일 연습삼아 하나씩 해본 뒤, 괜찮다고 생각되면 습관처럼 계속 해보는 것이 좋을 것 같습니다.

 

P.S. 카타는 알고리즘 문제처럼 빠르거나 최적의 해결안을 내놓는 것을 목적으로 한다기 보다는 단순한 코드를 지향(?)한다고 볼 수 있습니다. 그래서, 몸 풀기용 문제로 어려운 문제보다는 쉽게 풀 수 있는 문제들이 많습니다.

 

이전 글 : Color Tool

 

이전 글은 칼라 값의 설정이었다면, 이번 글은 아이콘에 관한 글입니다.

 

안드로이드 스튜디오의 Image Asset 툴은 나 홀로 앱 개발을 할 때 필요한 강력한 툴 중 하나입니다.

 

물론, 요즘 무료 아이콘을 사용할 수 있는 사이트들도 많이 있지만, 전문적인 디자이너의 도움이 없이 간단한 아이콘들을 추가하는 것은 Image Asset 으로 충분합니다.

 

 

사용 방법은 위 두 장의 그림으로 갈음합니다.

한 두 번 클릭 해보시다 보면, 초보자라도 쉽게 사용법을 익힐 수 있습니다.

 

덧붙임 1.

안드로이드 개발자 사이트의 문서, 역시 충분히 친절하게(?) 설명되어 있어서 참고하시면 좋습니다.

 

2020/03/09 - [Android/Widget] - 안드로이드 위젯 개발하기 (1)

2020/03/10 - [Android/Widget] - 안드로이드 위젯 개발하기 (2)

 

이전 글에서는 WidgetProvider 를 BroadcastReceiver 를 통해 구현한 것이었습니다.

class WidgetProvider : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
    }
}

 

BroadcastReceiver 를 사용한 것은 Widget 을 개발하는데 있어 기본적인 동작을 확인하기 위함이었습니다.

개발자 문서에도 기술되어 있지만, WidgetProvider 는 BroadcastReceiver 보다는 AppWidgetProvider 로 구현하는 것이 좋습니다.

이유는 AppWidgetProvider 소스 코드에 다 나와있지만, 간단히 설명드리면,

위젯 설치 전후 받을 수 있는 모든 Intent Action 과 extra 에 대해 BroadcastReceiver 를 잘 풀어놓은 것이기 때문입니다.

이를 테면, ACTION_APPWIDGET_UPDATE action 은 onUpdate 함수에, ACTION_APPWIDGET_DELETED action 은  onDeleted 함수를 호출 하도록 되어 있습니다. 자세한 것은 AppWidgetProvder.java 소스 코드를 참조하세요.

 

class WidgetProvider : AppWidgetProvider() {
    override fun onUpdate(context: Context?, manager: AppWidgetManager?, widgetIds: IntArray?) {
        val remoteViews = RemoteViews(
            "com.tistory.develop_branch.widget",
            R.layout.widget_layout
        )
        widgetIds?.forEach {
            manager?.updateAppWidget(it, remoteViews)
        }
    }
	override fun onAppWidgetOptionsChanged(
		context: Context?, appWidgetManager: AppWidgetManager?,
		appWidgetId: Int, newOptions: Bundle?
	) {
	}

	override fun onDeleted(context: Context?, appWidgetIds: IntArray?) {}

	override fun onEnabled(context: Context?) {}

	override fun onDisabled(context: Context?) {}

	override fun onRestored(
		context: Context?,
		oldWidgetIds: IntArray?,
		newWidgetIds: IntArray?
	) {
	}    
}

 

여기서 잠시 맨 처음 글에서 언급하였던 <receiver> 태그에 대해서 다시 이야기해 보죠.

<receiver android:name=".WidgetProvider" >
	<intent-filter>
	<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
	</intent-filter>
	<meta-data 
    	android:name="android.appwidget.provider"
    	android:resource="@xml/widget_info"/>
</receiver>

 

AndroidManifest.xml 파일에 기술해 놓았던 <intent-filter> 는 "android.appwidget.action.APPWIDGET_UPDATE" action 뿐이었습니다.

하지만, 알고보면 AppWidgetProvider 는 APPWIDGET_UPDATE 뿐만아니라, APPWIDGET_DELETED, APPWIDGET_ENABLED, APPWIDGET_DISABLED, APPWIDGET_OPTION_CHANGED, APPWIDGET_RESTORED action 도 받아서 처리하고 있습니다.

이는 시스템에서 두 가지 값 APPWIDGET_UPDATE action intent filter 와 "android.appwidget.provider" meta-data 를 가지고 있는 경우에 대해서 명시적인  Intent 를 보내주고 있다는 의미입니다.

다시 말하면, APPWIDGET_DELETED 를 intent-filter 로 추가하지 않아도, 해당 이벤트를 수신할 수 있고, 설령 추가하지 않는다하더라도 항상 이벤트를 수신하는데는 문제가 없다는 얘기입니다.

 

덧붙임 1.

AndroidManifest.xml 파일에서 android:exported=false 를 추가해놓을 경우, Intent 를 받지 못한다는 경우가 종종 있는 것 같습니다.

물론, 저는 겪어 보지 않았습니다만, 스택오버플로우에서 종종 볼 수 있는 질문입니다.

 

 

 

'Android Widget' 카테고리의 다른 글

안드로이드 위젯 개발하기 (4)  (0) 2020.07.27
안드로이드 위젯 개발하기 (2)  (0) 2020.03.10
안드로이드 위젯 개발하기 (1)  (0) 2020.03.09

 

몇 년전만 해도 나 홀로 앱 개발을 하고 있을 때, 가장 어려웠던 것은 앱 디자인이었습니다.

어떤 색을 선택해야 할지 어떤 아이콘을 써야 할지,  좀 처럼 만만한 일이 없었습니다.

제 아무리 포토샵을 잘 한다고 해도, 아이콘을 직접 그리는 것도 만만치 않은 일이었고,

무료 사이트를 뒤져서 나온 괜찮은 아이콘을 썩 마음에 들지 않더라도 사용하는 것이 다반사였습니다.

 

구글이 이런 저의 마음을 어찌나 잘 알아주었는지 시간이 흐르면서 적당한 기능들을 만들어주고 있습니다.

 

그 첫 번째가 기본이 되는 색을 지정해 놓는 것 입니다.

아래 링크를 확인해 보면, 어떤 색을 지정할 경우, 이 색보다 약간 밝은 색과 약간 어두운 색을 알려줍니다.

https://material.io/resources/color/#!/?view.left=0&view.right=0

 

Color Tool - Material Design

Create and share color palettes for your UI, and measure the accessibility of any color combination.

material.io

 

예를 들어, 아래 그림과 같이 붉은 색을 선택했다면,...

 

 

아래와 같이 style.xml 과 color.xml 값을 지정해 놓고 시작하면 좋습니다.

<resources>    
        <!-- style.xml -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/primaryColor</item>
        <item name="colorPrimaryDark">@color/primaryDarkColor</item>
    </style>
</resources>
<resources>
	<!-- colors.xml -->
    <color name="primaryColor">#b71c1c</color>
    <color name="primaryDarkColor">#7f0000</color>
</resources>

'Lonely Developer' 카테고리의 다른 글

Github Actions 에서 cron 설정  (0) 2023.08.15
Google Firebase : TestLab  (0) 2021.06.02
Android Playstore Library Core - Update Apk  (0) 2020.09.04
Android Studio - Image Asset Tool  (0) 2020.03.13

이전 글 :  2020/03/09 - [Android/Widget] - 안드로이드 위젯 개발하기 (1)

 

이전 글에서는 가장 기초적인 내용에 대해서만 기술했습니다.
이 글에서는 위젯 개발에서 WidgetInfo 에 대해서만, 좀 더 깊숙히 들어가 보도록 하겠습니다.

이전 글에서 WidgetInfo 가 가지는 속성 값 중 가장 중요한 값은 minWidth 와 minHeight 였습니다.
안드로이드는 이 값을 기준으로 위젯의 크기가 1x1 사이즈인지 2x2 사이즈인지를 구별합니다.
기준이 되는 값은 아래와 같습니다. (출처 : 앱 위젯 디자인 가이드 라인)

셀 개수(열 또는 행) 사용 가능한 크기(dp)(minWidth 또는 minHeight)
1 40dp
2 110dp
3 180dp
4 250dp
n 70 × n − 30

이런 식으로 min 값만을 제공하는 이유는 단말마다 홈 크린에서 제공할 수 있는 1x1 위젯의 공간 크기가 제각각 다르기 때문입니다.
그래서, 시스템이 보장해줄 수 있는 최소 값을 제공하고, 그에 따라 위젯 레이아웃을 구성하도록 하는 것입니다.
1x1 위젯의 최소값은 40dp-40dp 이지만, 실제로 대부분의 안드로이드 단말들은 1개의 셀당 크기가 이보다 큰 것이 일반적입니다.

홈 화면에서 셀당 크기를 변경할 수도 있습니다.

 

그럼, 이제 각각의 속성 값에 대해서 좀 더 자세히 알아보도록 하겠습니다.

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
	android:minWidth="40dp"
	android:minHeight="40dp"
	android:updatePeriodMillis="86400000"
	android:previewImage="@drawable/preview"
	android:initialLayout="@layout/example_appwidget"
	android:configure="com.example.android.ExampleAppWidgetConfigure"
	android:resizeMode="horizontal|vertical"
	/>

updatePeriodMillis
: 위젯은 매우 수동적인 녀석입니다. 시스템에서 어쩌다 한 번씩 '업데이트 하라구!!!' 라는 메시지를 주어야 그제서야 위젯을 업데이트 합니다. 이 값은 '업데이트 하라구!!!' 라는 메시지를 얼마나 자주 보내주는지에 대한 것입니다. 예제에도 있지만, 보통 24시간(=86400초) 정도로 업데이트 할 것을 예상하고 만든 것으로 보입니다. (아마도 구글 형님들은 그런 의도로 만들었을 거라는 제 추측입니다. )
위젯 업데이트가 배터리 소모에 상당한 영향을 준다는 얘기도 있었고, 개발자 문서에서는 30분내에는 두 번이상 메시지를 보내지 않는다고 기술되어 있습니다. 즉, 최소값이 30분이라는 것으로 판단됩니다만, 위젯 업데이트 시간에 대해 구현을 진행하다 보면 보통 이런 업데이트 주기에 상관없이 앱에서 위젯을 업데이트하기 때문에 값을 별로 신경쓰지 않게 됩니다.

initialLayout
: 초기 레이아웃 값입니다. 보통 AppWidgetManger 로 RemoteView 를 업데이트 해주면 별 상관없는 값이긴 합니다만, 부팅 직후 처럼 아직 업데이트가 진행되지 않은 상황에서 위젯에 "Problem loading widget" 와 같은 메시지가 표시되는 것을 방지해줍니다.
보통 실제 데이터와 거의 유사한 화면을 추가해 놓는데, (그렇게 해 놓는 것이 예쁘긴 합니다.) 이 초기 화면을 너무 실제와 비슷하면, 간혹 개발 중에 오류가 발생하더라도 실수로 지나치는 경우가 종종 발생합니다.

previewImage
: 설정하지 않을 경우, 이전 글에 포함되어 있는 그림 처럼 기본 런처 아이콘이 사용됩니다.

configure
: 위젯 설정 Activity 를 지정(?) 할 수 있습니다. 보통 위젯을 홈 화면에 설치하기 직전에 나오는 설정 화면입니다.
이 설정 Activity 에 대해서는 후속 글에서 더 이야기 할 것들이 있습니다.

resizeMode
: 위젯을 상하좌우로 늘릴 수 있는지 옵션을 설정해 주는 속성입니다.
위에서 기술했다 시피 최소값을 기준으로 위젯을 만들기는 하지만, 대부분 이 최소값보다는 큰 사이즈를 감안해서 위젯을 만들게 됩니다.
그런 관점에서 2x2 위젯을 4x4 로 늘린다고 크게 문제 없도록 상대적인 값으로 잘 디자인한다면, 사용자 입장에서 꽤나 괜찮은 옵션일 것입니다.

 

덧붙임 1.

WidgetInfo 의 minWidth, minHeight 값만으로는 부족함을 많이 느낄 때가 많습니다.

상대적인 레이아웃의 배치를 고려한다고 하더라도, 위젯의 크기가 실제로 어느 정도 되는것인지 가늠이 되지 않기 때문입니다.

fun getWidgetSize(context : Context, appWidgetId : Int){
	val manager = AppWidgetManager.getInstance(context)
	val options = manager.getAppWidgetOptions(appWidgetId)
	val minWidth = options.getInt("appWidgetMinWidth") // dp
	val minHeight = options.getInt("appWidgetMinHeight") // dp
	val maxWidth = options.getInt("appWidgetMaxWidth") // dp
	val maxHeight = options.getInt("appWidgetMaxHeight") // dp
}

코드상에서는 Context 와 appWidgetId(Int) 값만 있으면, 아래 코드를 통해 위젯의 실제 사이즈를 가늠해 볼 수 있습니다.

비록 실제적인 값은 아니지만, min/max 값으로 Preview 화면을 미리 가늠해 볼 수 있기 때문입니다.

위젯 개발 혹은 디자인이 까다로운 이유는 이런 레이아웃의 width, height 값을 가늠하기만 할 뿐, 특정하기가 어렵기 때문입니다.

 

덧붙임 2.

WidgetInfo 파일에서 minWidth/minHeight = 40dp 혹은 110dp 가 아니라 70dp 로 설정하면 어떻게 될까요?

어떤 단말에서는 1x1 으로 나올 수도 있지만, 어떤 단말에서는 2x2 으로 또 어떤 단말에서는 1x2 로 나올 수도 있습니다.

그렇기 때문에, 위 개발자 문서에서 가이드한 40/110/.../70xN-30 의 값은 NxM 위젯이라는 것을 정의하는 수준일 뿐,

실제 위젯 뷰의 사이즈를 확정하기도 어렵습니다.

'Android Widget' 카테고리의 다른 글

안드로이드 위젯 개발하기 (4)  (0) 2020.07.27
안드로이드 위젯 개발하기 (3)  (0) 2020.03.13
안드로이드 위젯 개발하기 (1)  (0) 2020.03.09

안드로이드 위젯 개발은 생각만큼 개발하기 쉬운 것은 아닙니다.

감히 안드로이드 개발을 하면서 가장 지저분한(?) 아이템 중 하나라 감히 말씀드리고 싶네요.

언뜻 보기에는 그렇게 대단해 보이지 않는 녀석같지만, 기능을 하나하나 추가하다 보면, 의외로 난관에 부딪히는 경우가 많습니다.

 

일단, 그런 예외적인 상황들에 앞서, 개발자 사이트에서 제공해 주는 문서를 한 번 읽어보겠습니다.

https://developer.android.com/guide/topics/appwidgets?hl=ko

 

앱 위젯 빌드  |  Android 개발자  |  Android Developers

앱 위젯은 다른 애플리케이션(예: 홈 화면)에 삽입되어 주기적인 업데이트를 받을 수 있는 소형 애플리케이션 뷰입니다. 이러한 뷰는 사용자 인터페이스에서 위젯이라고 하며 앱 위젯 공급자를 사용하여 게시할 수 있습니다.

developer.android.com

문서에서는 AppWidgetProviderInfo, AppWidgetProvider, 그리고, 초기 레이아웃 세 가지가 필요하다고 기술되어 있습니다.
이 중에서 가장 먼저 선행되어야하는 것은 WidgetInfo xml 파일과 APPWIDGET_UPDATE action 을 받을 수 있는 BroadcastReceiver 입니다.

 

1. AppWidetProviderInfo(Widget Info) 는 res/xml 디렉토리에 추가해주어야 하는 xml 파일입니다.

개발자 사이트 문서에는 더 많은 속성 값들과 설명들이 나열되어 있습니다. 이 중 가장 중요한 값은 아래에 기술된 minWidth, minHeight 값입니다. 이 두 개의 속성 값이 없을 경우, 위젯 추가 화면에 표시되지 않습니다.

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider 
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:minWidth="40dp"
	android:minHeight="40dp">
</appwidget-provider>

 

2. 그리고, BroadcastReceiver 파일을 추가한 뒤, AndroidManifest.xml 파일에 정보를 추가해 줍니다.
여기까지 진행 하면 그림과 같이 기본 아이콘으로 설정된 1x1 위젯이 위젯 추가 화면에서 메뉴가 나오기 시작합니다.

class WidgetProvider : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
    }
}

 

 

<receiver android:name=".WidgetProvider" >
	<intent-filter>
	<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
	</intent-filter>
	<meta-data 
    	android:name="android.appwidget.provider"
    	android:resource="@xml/widget_info"/>
</receiver>
    

 

 

물론, 여기까지 추가할 경우, 실제 위젯을 홈 화면에 띄울 수 있는 것은 아닙니다.
코드만 놓고 보아도 표시할 기본 레이아웃이 지정되어 있지 않기 때문에, 위젯 추가 화면에 표시만 될 뿐, 추가할 수 있는 위젯은 없는 셈입니다.

개발자 문서와는 약간 다르게 구현한 이유는, 안드로이드라는 시스템이 위젯을 인식하기 위해서는 최소한 어떠한 값들이 있어야 하는가를 조금이나마 가늠해보기 위한 것입니다.
핵심은 AndroidManifest.xml 에 기술된 <receiver> 와 <meta-data> 태그 안의 resource 파일입니다.
또 이 resource 파일에서 가장 중요한 값은 minWidth 와 minHeight 라는 것입니다.

 

3. 마지막으로 BroadcastReceiver - onReceive() 에 AppWidgetManager 코드를 추가해 주시면, 홈스크린에 추가되는 위젯을 만들 수 있습니다.

class WidgetProvider : BroadcastReceiver() {
	override fun onReceive(context: Context?, intent: Intent?) {
		if(intent == null){
			return
		}

		val widgetManager = AppWidgetManager.getInstance(context)
		when (intent.action) {
			AppWidgetManager.ACTION_APPWIDGET_UPDATE -> {
				val remoteViews = RemoteViews(
					"com.tistory.develop_branch.widget",
					R.layout.widget_layout
				)
				intent.extras?.let {
					val appWidgetIds: IntArray? =
						intent.extras!!.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS)
					appWidgetIds?.forEach {
						widgetManager.updateAppWidget(it,remoteViews)
					}
				}
			}
		}
	}
}

 

여기까지 진행된 소스는 여기를 참고하세요.

 

2020/03/10 - [Android/Widget] - 안드로이드 위젯 개발하기 (2)

 

'Android Widget' 카테고리의 다른 글

안드로이드 위젯 개발하기 (4)  (0) 2020.07.27
안드로이드 위젯 개발하기 (3)  (0) 2020.03.13
안드로이드 위젯 개발하기 (2)  (0) 2020.03.10