코딩 (독학)/★ Kotlin

[Ch.1] JDTALK 어플 시작 화면 구성-Splash Screen (카K오톡 클론코딩) - Android studio(with.Kotlin)

짱득이 2021. 12. 22. 19:04
300x250
반응형

* 시작에 앞서

개인 프로젝트, 코딩 과정을 상세하게 기록하고 리뷰하기 위해 작성된 블로그입니다.
공부와 함께 진행되는 스파르타식 프로젝트이므로, 부족한 부분이 많을 수 있습니다.
Feedback은 언제나 환영입니다.

 


[Ch1.] 앱 시작 화면 구성

Configuration ?
  • Project Name : JDTalk_Clone
  • Language : Kotlin (Android Studio)

첫 포스트이니 만큼 왜 굳이 K카오톡을 클론코딩 하기로 하였는지 초심을 잃지 않기 위해 작성하자면, 그냥 만들게 없어서였다. 만들어보고 싶은 앱은 많지만, 어떻게 만들어야 잘 만들었다는 말이 나올지, 효율적일지 등등 많은 이유에서 그냥 차라리 유명하고 안정적이고 잘 짜여진 앱을 따라 만들어보면서 차근차근 하나씩 배워가고, 실력을 증진시키기 위해서였다. 앱 개발 실력은 볼 품 없지만, 다른 언어를 많이 접해봤다는 장점 하나만 살려서 열심히 구글링으로 독학하고 부딪히려고 한다.

 

요즘은 구글링 시대니까! 

 

심지어 다양한 서적들의 내용을 그대로 실습 삼아 베껴서 자신의 블로그에 포스트한 글도 넘쳐나서 그냥 굳이 책 사서 안보고 그런거나 보련다. 맞는 방법인지는 모르겠지만 세상은 변하는 것 처럼 공부 방법도 바뀌는거고, 빨리 적응하고 때에 맞춰서 유연하게 공부하면 되겠다는 생각이었다.

그럼 코이팅!


New Project 상태에서 시작 화면을 구성하기 위해 "SplashScreen_Activity" 액티비티를 하나 더 생성 해 주었다.

 

* MainActivity은 그대로 놔둔 이유? (별도의 화면을 굳이 Main에서 구성하지 않은 이유?)
 - 본인은 프로그래밍 실무 경험이 없고, 실무에서 각각의 화면, 페이지들을 어떻게 관리 하는지 모른다.
 - 다만, 많지는 않지만 적다고 하기는 애매한 개인 프로젝트 경험을 통해 페이지 관리를 편하게 하기 위해서는 별도의 페이지
   들을 다 만들어두고, Main이 되는 부분에서는 작성된 페이지를 불러오거나, 종료 하는것이 가장 편리했었기 때문에 이것이
   가장 좋은 방법이라는 판단 아래 이렇게 만들게 되어버렸다.

 

그래서 작성된 MainActivity.kt 와 SplashScreen_Activity의 코드는 아래와 같다.

 

MainActivity.kt

 

package com.jjangdeuk.jdtalk_clone

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlin.concurrent.timer

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash_screen)
    }
}
  • MainActivity.kt 에서는 setContentView(R.layout.activity_splash_screen) 을 통해 SplashScreen_Activity에 연결된 .xml을 가져온다.
  • setContentView 사용 형식 == setContentView(R.layout.".xml_name")

 

SplashScreen_Activity

 

package com.jjangdeuk.jdtalk_clone

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.ImageView

class SplashScreen_Activity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash_screen)
    }
}

 

 

Splash Screen (초기 앱 실행 스플래쉬 화면)

 

이제, activity_splash_screen.xml 파일을 열고, splash 효과를 줄 Image를 Import 해 주어야 한다.

Image는 아래와 같은 두가지 이미지를 사용하였다.

 

카카오톡의 이미지를 인용하여 제작했음을 알려드립니다.
* 카카오톡의 이미지를 인용하여 제작했음을 알려드립니다.

 

  • .xml의 Design 탭에서 ImageView 를 Drag&Drop 해 주면, Pick a Resource 창이 생긴다.
  • + 버튼 -> Vector Asset 을 추가하고, Asset Type을 Local file (SVG,PSD)에서 생성한 파일을 추가 해 주면 된다.
  • 본인은 다행히 psd 로 수정한 파일이 있어서 호환성 좋게 해결했다. 이미지로 불러오려면 Image Asset에서 하면 되는 듯 하다.

 

두개의 Image PSD를 추가 해 주게 되면 이와 같은 경로에 Image.png 가 추가된다.

res/drawable/[Image.png]
// png name : jdtalk_logo, jdtalk_madeby_text

 

 

만약 그냥 복붙을 하고싶으면 이미지를 복사하고, Android Studio 자체의

drawable 폴더를 누른 상태로 붙여넣기 하면 편리하다.

 

단, 붙여넣기 하는 폴더는 drawable-v24가 아닌, drawable 폴더여야 한다.

단순히 복붙 하는 방법

 

복붙을 하고 나서 ImageView를 xml에 Drag & Drop 하면 추가한 이미지를 선택할 수 있게 된다.

 

activity_splash_screen.xml

 

 

 

 

 

두개의 ImageView (JDTALK, Made by ....)를 이와 같이 정리 해 주었다.

Layout의 Constraints를 세팅 해 주고, 배경 색은 모두 yellow로 채우기 해 주었다.

 

* background color 설정은 아래에 있음.

 

 

 

 

 

 

 

* 배경색도 노란색인 전체 이미지를 넣지 않은 이유? (굳이 ImageView를 두개 사용한 이유?)
 - 처음에는 이미지를 통째로 노란 배경으로 채워서 만들어 보았지만, 너비나 높이가 호환되는 기기가 달라질 때 마다 제대로 채워지지 않는 오류가 있어서 핵심 이미지만 잘라낸 뒤, 배경색은 채우기 해 주었다.
* 주의 해야할 점 *
Image로 사용되는 친구들의 Naming 은 대문자가 아닌, 소문자로 해 주는게 꼬일 일이 없겠다..
그래서 파일명을 각각 jdtalk_logo.png / madeby_text.png 로 바꿔 주었다.

 

Background Color 설정 (=노란색으로)

 

  • app/res/values/colors.xml

이제 Background Color로 사용 할 Yellow 색상을 지정 해 준다. (#000000 등으로 불러와도 되지만, 편리성을 위해서 ^^)

<color name="talk_yellow">#FAE301</color>

 

 

  • colors.xml 전체 코드

 

 

12번 line과 같이 talk_yellow 만 추가 해 준 것이다.

 

이제는 에디터도 발전해서 왼쪽에 색깔이 같이 나와주더라..

멋지다..ㅋㅋㅋㅋㅋㅋ

(yellow 는 여기에서 예약어가 따로 있는건지 모르겠지만, yellow로 하면 인식을 안하더라.. 그래서 talk_yellow 로 해 주었다.)

 

 

 

 

  • app/res/layout/activity_splash_screen.xml
android:background="@color/yellow"

눈에 보여지는 xml에 background 를 yellow 로 설정 해 준다.

 

 

 

  • activity_splash_screen.xml 전체 코드

background를 위해 7번 line만 추가 되었다.

 


 !! Warning !! 

MainActivity.kt 에서는 아래와 같은 코드로 인해 main 코드에 등록된 Hello World 만 출력된다.

setContentView(R.layout.activity_main)

그러나, 위 코드를 아래와 같이 바꾸게 된다면 ?

setContentView(R.layout.activity_splash_screen)

메인 화면은 스킵되어 버리면서, 관리가 어렵고 코드가 줄줄이 꼬여버리기 때문에..

이럴때는 Kotlin의 Intent 기능을 사용하면 좋다.

 

  • Intent : 의도한 (?) 이라는 의미라고 한다.
  • 기본적으로 Intent는 안드로이드에서 데이터를 Activity <---> Activity 간에 서로 이동할 때 사용한다고 한다.

지식이 부족한 탓에, Intent 기능을 사용하기 위해 열심히 구글링 하였고 필요한 부분만 열심히 떼다 붙였다.

어찌되었든 코드는 내가 원하는 대로 작동하면 장땡이니까!

 

 

activity_splash_screen.xml 에서 추가 된 부분

 

private val SPLASH_CHANGE:Long = 4500 // 1.5sec
// SPLASH 이후 CHANGE 될 시간을 정의한 val 변수

 

import android.os.Bundle
import android.os.Handler

// override fun onCreate.... 내부에 추가
Handler().postDelayed({
            startActivity(Intent(this, MainActivity::class.java))
            finish()
        }, SPLASH_CHANGE)

 

 

Meanning of the Command?

 

  • Handler   &   postDelayed

Handler = 작업을 처리한다

기본적으로는 안드로이드의 기본적인 이벤트를 처리하는 시스템이다.

비동기적(Asynchronous)으로 어떠한 작업을 처리하게 되는데, UI에 접근하는 방식 = Handler라고 생각하면 될 듯 하다.

(물론, 구글링 하였다.)

post = 발송 / delay = 지연, 지체, 연기하다

postDelayed는 handler를 지연하여 사용하게 하는 친절한 메소드임이 분명하다.

 

기본적인 문법, 구조는 아래와 같다.

Handler().postDelayed({
	// 명령을 적는 부분
}, 2000) // 지연시간을 적는 부분. 2000을 주었다.

 

 

 

  • Bundle ?

기본적으로 Bundle의 의미=여러가지 Type의 값을 저장하는 Map 클래스

예를 들면 String 값을 Bundle 클래스에 Mapping(대응, 변환)하는 것이다.

 

기본 타입인 Int,  Double, Long, String 부터 FloatArray, StringArrayList, Serializable, Parcelabe 까지 구현한다.

(Serializable(객체직렬화)는 객체를 Byte로 저장하는 Java의 인터페이스이고,

Parcelable은 안드로이드에서 만든거라는데 뭔지는 잘 모르겠다.)

 

Bundle의 다른 용도는 지금 보고있는 글들처럼 Activity를 생성할 때 Bundle savedInstanceState 객체를 가지고 와서 Activity를 중단할 때 savedInstanceState Method를 호출하여 임시적으로 데이터를 저장한다. 즉, 이전에 저장된 데이터가 있었으면 그 데이터를 가지고 Activity를 다시 생성한다고 한다.

 

     => Bundle은 무엇이든 포장할 수 있는 상자이고, 이 상자를 이용해 Intent도 오고갈 수 있고 다양한 데이터 통신에 이용할 수 있는 것이라고 한다.

              ==>> 결국 말이 너무 어렵다.

 

 

 

  • startActivity ?

아직 짧은 지식이기 때문에, 잘 생각 해 보면 우리가 New Empty Activity 를 생성하는 것 처럼

Intent를 사용할 때 메소드를 통해 Activity를 start 하는 것으로 생각하면 될 듯 하다.

 

다만, 본 포스트에서 의도 한 코드는 메인 스플래쉬가 일정 시간동안 지연 된 뒤에 다른 Activity로 Change 되어야 하기 때문에, 초기 화면에서 필요한 Data는 이 과정에서 Bundle savedInstanceState를 통해 데이터를 주고받는다고 생각하면 될 듯 하다.

      => Intent와 합이 좋은 녀석인 것 같다.

 

 

 

  • 그래서 튀어나온 Intent ?

앞서 간단히 말 했듯, Activity 간에 데이터도 주고받고, 화면도 전환하고자 할 때 안드로이드에서 주로 사용하는것이 Handler에서 이뤄지는 Intent 기능인 것 처럼 보이는데, 열심히 구글링 한 결과 드디어 역할을 제대로 알았다. (본인은 사실 제대로 개념을 알지 못하면 잘 못 넘어가는 성격이기에..ㅎㅎ)

 

일단 Android Application 을 구성하는 4가지 기본 요소Activity, Service, Broadcast Receiver, Content Provider 가 있는데, Intent라는 녀석으로 이러한 구성요소 (컴포넌트) 간에 작업 수행을 위한 정보를 전달하는 역할을 한다.

Intent를 가장 활용성 좋게 사용한 예로는 Activity 간의 화면 전환을 예로 들 수 있다. 

(워후;; 속이 그냥 시원하다.)

(출처 : HyoGeun's Android Tistory Blog

https://hyogeun-android.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EA%B0%95%EC%9D%98-5-Inte)

 

안드로이드 강의 5. Intent와 Activity 이동

안녕하세요~ 심효근입니다! 뭔가 나른....해지는 시간이네요! 이번 차시에는 Intent와 Activity이동에 대해 배워볼건데요! 일단 항상 하던대로 안드로이드 스튜디오를 실행해봅시다! 이 activity_main에

hyogeun-android.tistory.com

 


Activity 간 Intent 하기

 

역할은 알았으니 사용법좀 쪼개보자.

import android.content.Intent

Handler().postDelayed({
            startActivity(Intent(this, MainActivity::class.java))
            finish()
        }, SPLASH_CHANGE)
  • startActivity로 Intent를 시작한다.
  • Intent(this, MainActivity::class.java)   = this는 자기 자신 클래스의 정보 (코드상에서 보이지는 않지만, 본 코드에서 this의 의미는 결국 this@SplashScreen_Activity와 같다.) = MainActivity는 띄워줄 화면의 정보를 적어준다.

==> Intent(자기 자신, 띄울 화면::참조)

  • ::class.javaReflection 기능 (클래스 참조)으로, 내가 참조하려는 값을 찾기 위해 사용한다.

  • Reflection (참조) 구분
* Java Reflection (Class)
reflectionClass.class -> 클래스 자체를 리플렉션 (참조)

reflectionInstance.getClass() -> 인스턴스에서 클래스를 리플렉션

* Kotlin Reflection (KClass) => ::(더블콜론) 을 이용하여 참조
reflectionClass::class

reflectionInstance::class

그런데, 작성한 SplashScreen_Activity에서는 class 뒤에 .java가 붙어 class.java의 형식으로 작성 하였는데, 그 이유는 Java에서 쓰는 Class와 Kotlin에서 쓰는 Class가 다르기 때문에 ::class를 하게 되면 KClass를 리턴하여 다시 Class로 바꿔줘야 하는데 이 상황에서 차라리 .java를 붙여 자바 클래스로 리턴받는다.

 

멍 게소리야..?

 

 

멍게소리야?

 

 

 

 


여기서 심각한 의문점이 발생했더랬다.

 

우리는 Kotlin으로 작성중인데 왜 KClass인  ::class로 리턴 하는것이 아닌, ::class.java(JAVA Class)로 리턴 해야하는가? 왜?!

 

이것만 2시간째 열심히 각종 커뮤니티와 구글링을 통해 탐구 했는데.. 겨우 찾은 답은 아래와 같았다.

 

이게 확실한 답이 맞는지는 모르겠지만.. 

 

잘 모르겠고, 그냥 열심히 삽질만 했다.
android studio에서 kotlin 으로 작성된 intent 코드를 찾아 보았는데 이게 구글링에서 나오는 android studio intent docs랑 같은 내용이었을 줄이야.. ㅎㅎ.... 어찌되었든!

인텐트 기능이 자바로 작성되어있고, class.java로 리턴하여 JAVA Class Instance 로 리턴 받아야한다는 결론을 내렸다.

이게 사실 그렇게 중요하진 않은 것 같지만.. 잘 모를 때에는 삽질도 커가는 과정이라고 생각해서 열심히 삽질 했지만....
파지지 않는 구덩이였던 것 같다.. ㅎ

 

 

  • 결론 : reflection 최종 정리
1. ::class              =>  Kotlin Class의 Instance로 Return
                              (속성, 데이터 클래스 등과 같은 Kotlin 기능을 처리할 수 있는 Kotlin Reflection API)

2. ::class.java        =>  Java Class Instance로 Return
                              (모든 JAVA Reflection 코드와 상호 운용되지만 일부 Kotlin 기능에서는 작동하지 않을 수 있음.)

(출처 :https://korean-otter.tistory.com/entry/android-studio-kotlin-intent-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

https://juahnpop.tistory.com/222)


 

finish() ?

 

현재 활성화된 Activity 를 종료한다. 중요하지 않은 듯 중요 해 보이는듯 한 본 코드 finish()는 로그인 액티비티 등과 같이

한번 사용하고 다시는 사용 안할 Activity에 대하여 작성 해 주면 좋은 코드이다.

 

현재 SplashScreen_Activity에서 스플래쉬 과정에서 특별한 기능이 없이, 단순 스플래쉬만 작동하기 때문에 finish() 코드가 있든 없든 Handler Intent 덕분에 코드 자체는 정상작동하지만, 앱의 안정성을 위하여 finish()도 함께 작성 해 주었다.

 

 

  • activity_splash_screen.xml 전체 코드

R이 빨간 이유는 잠시 다른거 테스트하느라 그렇다.

현재 이 코드를 그대로 Run App 하면 스플래쉬 되지 않고, MainActivity만 화면에 나타나게 된다.

정상적으로 스플래쉬 시키려면 AndroidManifest.xml에 SplashScreen_Activity를 선언 해 주어야 한다.

(현재는 MainActivity만 Manifest에 선언 되어있는 상태)

 

 

AndroidManifest.xml 의 역할
  • Android Application에 대한 각종 정보를 기술한 Application 명세서
  • 모든 App Project에서 가장 상위 폴더에 필수적으로 존재해야 하며, 앱이 실행되기 전 시스템이 알아야 할 내용을 정의
  • 앱 구성요소들이 실행될 수 있는 조건을 기술하고, 실행하며 상호작용하기 위한 필요한 권한을 설정
  • 앱이 연결되어야 하는 라이브러리를 기술
AndroidManifest.xml에 특히 선언되어야 하는 정보
  • Application Package Name
  • App에서 사용되는 Component (Activity, Service, BroadCast Receiver, Content Provider)
  • 권한 (Permission)
  • 앱에서 요구하는 H/W & S/W 특징

 

=> 너무 사전적이니까 굳이 외우지 않고, 그냥 그렇구나 하고 넘어가자.

 

 

React의 router.js와 연관지어 생각 해 보면, 일단 실행되어야 하는 레이아웃은 manifest에 표기 해 줘야할 것 같은 느낌이다.

 

 

 

AndroidManifest.xml 에도 Intent 관련 Set Up 해주기

 

  • Project - Android - App - manifests - AndroidManifest.xml
	<activity android:name=".MainActivity"/>
        
        <activity
            android:name=".SplashScreen_Activity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

처음 앱 구동시에는 Splash 화면이 먼저 나타나야하고, 그 뒤에 MainActivity도 인식하는 과정.

(AndroidManifest.xml에 Splash해 줄 Activity를 추가로 삽입 해 준다.)

 

이렇게 SetUp 해 주면 manifest에서 MainActivity와 SplashScreen_Activity를 모두 인식하기는 한다.

SplashScreen_Activity를 먼저 MAIN으로 호출하고, Intent에 의해 그 다음으로 MainActivity가 실행되는 구조가 된다.

 

얼추 생긴형식으로 봤을 때에는 React.js 를 공부 했을때 router.js와 비슷하게 생긴 듯 해서 조금은 익숙 해 보인다.

 

AndroidManifest.xml 분해하기

<intent-filter> ?

인텐트 필터 전에, 인텐트에 대해 조금 더 깊숙히 그리고 간단히 알고 넘어가면 좋을듯 한 내용을 먼저 말하자면..

인텐트에도 유형이 있다는 것인데, 명시적 인텐트이냐 암시적 인텐트이냐로 나뉜다는 것이다.

<명시적 인텐트>

 - 호출할 액티비티를 알고있는 경우, 그것을 콕 찝어 명시 해 주는 것.

 

<암시적 인텐트>

호출 할 액티비티를 정확히 알고있지 않고, 인텐트 객체 내 호출 액티비티를 찾을 수 있는 정보들만 들어있는 경우 사용

 

* 그런데 여기서 Intent-Filter가 필요한 이유에 대해서 등장한다.

  • 암시적인 인텐트를 통해 사용자로 하여금 어느 액티비티를 사용할지 선택하도록 하고자 할 때 Intent-Filter가 필요
  • Android System 내부에서 수많은 App에 의해 수많은 Intent들이 발생, 이 중 자신에게 필요한 Intent만 받기 위해 필요

Intent-Filter가 없다고 해서 Intent를 받을 수 없는 것은 아님. (명시적인 Intent는 Intent-Filter 가 없어도 Intent 가능)

 

 

 

* 그럼에도 불구하고, Intent-Filter가 필요한 이유?

  • Self-Made Activity 라면 Activity Name을 정확하게 알 수 있지만, 다른 사람이 만든 Activit인 경우, 이름을 알기가 어렵기 때문에 명시적 인텐트를 사용하여 호출하기 힘들다.
  •  
  • Manifest 파일에 들어갈 수 있는 태그 요소들의 종류 및 의미
태그 네임 설명


<application />


애플리케이션을 선언한다.
Title, Icon, Theme 등 앱 자체의 정보를 속성으로 지정할 수 있다.
이때, <application /> 태그는 Manifest에 단일로 하나만 존재해야 한다.
<manifest /> 및 <application /> 태그는 유일해야만 한다.



<activity />



액티비티 구성 요소를 선언한다.
4대 구성요소 중 하나중 Activity를 정의 한 것으로, 사용자에게 보여주는 UI 화면이다.
1개의 App에는 최소 1개 이상의 Activity가 존재해야 하고, manifest File에 선언되지 않은 Activity는 시스템이 표시하지 않고, 실행도 되지 않는다.
해당 태그 안에는 <intent-filter />가 존재한다.



<intent-filter />



액티비티, 서비스 또는 Broadcast Receiver가 응답할 수 있는인텐트 유형을 지정한다. <manifest>:AndroidManifest.xml 파일의 루트 요소이다.
해당 태그 안에는 <action />, <category /> 등의 태그가 존재하여 첫 화면을 결정하게 된다.

<action /> 태그의 경우 MAIN이 되어야 하고, <category /> 태그의 경우 LAUNCHER가 되어야 한다.

<action />
intent를 통해 수행 할 행동을 지정 (단, 리터럴 문자열 값이어야 함)
(android.intent.action.MAIN = 메인이니까 첫번째로 나와)

<data />

intent 필터에 Data 사양을 추가

<category />

action과 함께 activity의 특징을 나타냄 (단, 리터럴 문자열 값이어야 함)
(android.intent.category.LAUNCHER : 넌 첫번째야 ㅇㅋ?)
<permission>

이 애플리케이션 또는 다른 애플리케이션의 각 구성 요소나 기능에 대한 액세스를 제한하는 데 사용하는 보안 권한을 선언한다.

Android App은 민감한 User 정보나 Camera, Internet 등 특정 시스템 기능을 사용할 때 반드시 권한을 요청해야 한다.

ex) SMS 전송에 대한 권한을 요청하기 위해 Manifest 파일에 다음과 같이 설정한다.
<manifest ...>
              <uses-permission android:name="android.permission.SEND_SNS"/>
                                                                                                                                              </manifest>








<provider />








콘텐츠 제공자 구성 요소를 선언한다.
App 내에서 사용할 수 있는 Data의 Share를 위한 구성 요소로, App은 Content Provider에만 접근하며, 필요한 Data를 얻어올 수 있다.

일반적으로 App에서 자료를 저장할 때 주로 DB를 사용하는데, 한 App 내의 DB에는 해당 앱을 제외한 다른 App이 접근 해 오는것이 불가능하다.

그렇다면 다른 App이 해당 DB에 접근할 수 있는 방법은 없는것인가? 그렇지 않다.

외부 App이 마음대로 내 DB에 접근하지 못하게 하면서, 동시에 내가 가진 DB중 원하는 것들만 Share할 수 있도록 해 주는 역할을 하는 것이 바로 Contents Provider이다.

ex) 전화번호부에 등록된 전화번호 데이터가 자동으로 연동되어 카카오톡에 친구가 추가된다.
이것이 가능한 이유는 전화번호부에 Contents Provider가 전화번호부에 접근할 수 있게 해 주는 것이고, 카카오톡의 Contents Resolver가 번호를 요청하여 친구 추가에 이용하는 것이다.





<receiver />





Broadcast Receiver 구성 요소를 선언한다.
System 전반적인 특정 이벤트에 대해 응답하는 Receiver 역할을 한다. 배터리 부족, 스크린 캡쳐, 파일 다운로드 완료 등의 행위는 broadcast receiver를 통해 응답 받을 수 있다.
다만, 이벤트를 확인하는 기능만 담당할 뿐, 사용자에게 Event를 Alert 하지 않는다.
개발자가 이를 알리려 할 때에는 notification, Toast 를 사용하여 알림을 전달해야 한다.

ex) AirPods 연결이 해제 된 경우, 서비스에서 실행되고 있는 음악을 일시정지 시키려면, BroadCast Receiver를 통해 이어폰 연결이 해제 되었다는 정보를 수신하고 서비스를 종료해야 한다.



<service />



서비스 구성 요소를 선언한다.
UI 없이 Background 작업을 수행하는 구성요소로, Activity가 종료되어 있는 상태에서도 동작하기 위해 만들어진 구성 요소이다.
ex) 전화 앱을 켜 놓지 않은 상태에서 전화를 받을 수 있는 것은 Background에서 <Service />가 동자하고 있어야 하는 것이다.

* 리터럴 문자열 값? (Literal)

상수와 리터럴로 구분하면 좋다. 다만, 구분하기 전에 둘 다 의미는 변하지 않는 값(데이터)라는 전제가 있는것은 동일하다.

 

다만, IT적으로 이야기 하자면 둘의 차이는 아래와 같다.

 

상수(Constant) = 변하지 않는 변수

메모리 공간의 주소값이며 변경되지 않음.(객체가 할당 된 경우엔 값의 변경이 가능)

 

참조변수가 상수라는 의미이고, 해당 주소가 가리키는 데이터들까지 상수라는 의미는 아니기 때문에 아래 예시로 이해하면 좋다.

 

* JAVA로 든 예시

final Test t1 = new Test();

t1 = new Test();

위 코드는 불가능 하지만,

t1.num = 10;

이렇게 Class 안의 Data를 변경하는것은 상관 없는것이 상수라는 의미이다.

 

다시 말해, Data Type 에 관계없이 변화하지 않는 변수들을 상수라고 부르는 것이다.

 


리터럴(Literal) = 변수에 넣는 변하지 않는 데이터 값

(메모리 공간에 할당된 변수 안의 값이며 변경되지 않음)

 

final int a = 1;

위와 같이 int 앞에 final을 붙이게 되면, a는 상수가 된다. 여기서의 리터럴은 1인 것이다.

즉, 1과 같이 변하지 않는 데이터(boolean, char, double, long, int, etc....)를 리터럴(literal)이라고 부른다.

 

그렇기 때문에 인스턴스(Class Data)는 리터럴이 될 수 없다.

 

만약 인스턴스 안에 있는 값들을 변경하지 않는다면 되겠지만, 일반적으로 사용되는 인스턴스 값이란 동적으로 사용하기 위해 작성되어왔기 때문에 리터럴이 될 수가 없다. 즉, 값이 언제 변할지 모른다는 점 때문인 것이다.

 

또한, 변수 안에 들어가는 변하지 않는 값을 의미하는 단어이기 때문에 변수는 리터럴이라고 부를 수 없다.

 

 

< 변수, 상수, 리터럴 한줄 요약 >

  • 변수 (Variable) : 변할 수 있는 값 (Value) 를 저장하기 위한 공간
  • 상수 (Constant) : 변할 수 없는 값 (Value) 를 저장할 수 있는 공간
  • 리터럴 (Literal) : 그 자체만으로 값을 표기하는 것. 즉, Value의 표기 방법 = 값 또는 데이터 자체

 

  • 이 외의 Manifest 태그 요소 및 의미
태그 네임 설명
<activity-alias /> 액티비티의 별명을 선언한다.
<compatiable-screens /> 애플리케이션과 호환되는 각 화면 구성을 지정한다.
<supports-gl-texture /> 앱이 지원하는 단일 GL 텍스처 압축을 선언한다.
<grant-uri-permission /> 상위 콘텐츠 제공자가 액세스할 권한이 있는 앱 데이터의 하위 집합을 지정한다.
<instrumentation /> 애플리케이션과 시스템의 상호작용을 모니터링할 수 있는Instrumentation 클래스를 선언한다.
<meta-data /> 상위 구성 요소에 제공할 수 있는 추가적인 임의의 데이터 항목에 대한 이름-값 쌍이다.
<path-permission /> 콘텐츠 제공자 내에서 특정 데이터 하위 집합에 대한 경로와 필수 권한을 정의한다.
<permission-group /> 관련 권한의 논리적 집합에 대한 이름을 선언한다.
<permission-tree /> 권한 트리의 기본 이름을 선언한다.
<supports-screens /> 앱이 지원하는 화면 크기를 선언하고 앱이 지원하는 것보다 큰 화면에 대해서는 화면 호환성 모드를
활성화한다.
<uses-configuration /> 애플리케이션이 요구하는 특정 입력 기능을 나타낸다.
<uses-feature /> 애플리케이션이 사용하는 단일 하드웨어 또는 소프트웨어 기능을 선언한다.
<uses-library /> 애플리케이션과 링크되어야 하는 공유 라이브러리를 지정한다.
<uses-permission /> 앱이 올바르게 작동하기 위해 사용자가 반드시 부여해야 하는 시스템 권한이다.
<uses--sdk> 하나 이상의 Android 플랫폼 버전과의 애플리케이션 호환성을 API 레벨 정수로 표시할 수 있다.

 

* 조금 더 알고싶다면? => Android Intent Guide (Docs)

https://developer.android.com/guide/components/intents-filters?hl=ko 

 

인텐트 및 인텐트 필터  |  Android 개발자  |  Android Developers

An Intent is a messaging object you can use to request an action from another app component . Although intents facilitate communication between components in several ways, there are three fundamental use cases: An Activity represents a single screen in…

developer.android.com


 

Intent Filter 예시

아래 예시는 인텐트 필터의 동작을 나타내는 SNS 앱의 Manifest 파일 예시이다. (출처 : Android Developer Intent Docs)

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

        <activity android:name=".Handles_Share_Text&Media"
            <intent-filter>
                <action android:name="android.intent.action.SEND"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="text/plain"/>
            </intent-filter>
            
            <intent-filter>
                <action android:name="android.intent.action.SEND"/>
                <action android:name="android.intent.action.SEND_MULTIPLE"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="application/vnd.google.panorama360+jpg"/>
                <data android:mimeType="image/*"/>
                <data android:mimeType="video/*"/>
            </intent-filter>
        </activity>

 

첫번째 Activity인 ".MainAppLauncher"는 앱의 주요 진입 지점으로, 사용자가 아이콘을 이용해 앱을 처음 시작할 때 열리는 Activity이다.

  • action.MAIN (ACTION_MAIN) 작업은 이것이 주요 진입 지점임과 동시에 어떠한 Intent Data도 기대하지 않는다는 것을 나타냄
  • category.LAUNCHER (CATEGORY_LAUNCHER) 작업은 Activity의 아이콘이 시스템의 앱 시작 관리자에 배치되어야 한다는 것을 나타내고, <activity> 요소가 아이콘을 icon으로 지정하지 않은 경우, 시스템은 <application>요소로부터 가져온 아이콘을 사용함.

두번째 Activity인 ".Handels_Share_Text&Media"는 Text와 Media Contents의 Share를 용이하게 할 목적으로 만들어졌다.

사용자가 Main에서 Share로 이동하여 진입 할 수도 있지만, 두가지 인텐트 필터 중 하나와 일치하는 암시적 인텐트를 발생시키는 다른 앱에서 .Handels_Share_Text&Media에 직접 진입할 수도 있다.

 

이 외의 더 많은 Intent 관련 정보가 궁금하다면 언제든지 출처를 확인하면 좋을 듯 하다.

 


현재 상태에서 App을 구동하고 나면 상단에 App의 정보가 담긴 Bar가 자꾸 생성되어 보기에도 예쁘지 않고 불편하다.

앱의 완성도를 높이고, 깔끔하게 되도록 상단바를 없애주자.

 

res/values/themes/themes.xml 초기 코드

res/values/themes/themes.xml 로 이동하고, <resources /> 태그 내에 새로운 <style /> 태그를 커스터마이징 해 준다.

Splash 라는 이름을 가진 새로운 style 태그를 생성 한 것으로, NoActionBar를 요구하는 코드이다.

해당 코드를 직접 앱에 적용시켜주기 위해 다시 AndroidManifest.xml 로 이동하고, 아래와 같이 theme를 추가한다.

기존의 코드에 android:theme만 추가 된 것

전체 프로젝트 자체에 theme를 적용 시키는 방법은 다음 포스트에서 다루도록 하겠다.

지금은 본인도 성장중..^^


이번 포스트는 앱의 시작과 Manifest에서 Intent 적용하기, 간단한 Theme 적용에 대해 포스트 하였다.

 

다음 포스트는 각종 View 기능을 이용하여 적절한 View를 선택하고, 각종 메뉴 탭에 대한 뼈대를 만들고, 그 이후에는 각종 기능들의 살을 붙여 나갈 계획이다.

 

* Splash 화면 최종 결과물 *

 

 


 

 

 

* 참고한 글

https://yunaaaas.tistory.com/17

https://yuuj.tistory.com/10

https://korean-otter.tistory.com/entry/android-studio-kotlin-intent-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

https://popcorn16.tistory.com/94

https://bada744.tistory.com/m/95

https://readystory.tistory.com/187

https://juahnpop.tistory.com/212

 

728x90
반응형