반응형

Google Cloud 사이트 접속

https://console.cloud.google.com/

 

1번 클릭하여 프로젝트 선택

 

 

2번 IAM 및 관리자 클릭

 

 

3번 서비스 계정 클릭4번 서비스 계정 클릭

 

 

4번 서비스 계정 클릭

 

 

5번 키 클릭6번 키 추가 / 새 키 만들기 클릭

 

 

6번 키 추가 / 새 키 만들기 클릭

 

 

7번과 같이 키 생성 되고 ‘service-account.json’ 파일이 다운로드 됨.

주의사항 : 해당 파일은 다시 다운로드가 불가능하다.

반응형
블로그 이미지

SKY STORY

,
반응형
 

알림 메시지, 데이터 메시지 차이점을 알아보자.


구분 알림 메시지 (Notification Message) 데이터 메시지 (Data Message)
목적 시스템이 자동으로 알림 표시 앱이 직접 알림을 처리해야 함
앱 상태 백그라운드/완전 종료에서도 알림 표시 가능 포그라운드 상태에서만 앱이 직접 처리 가능
구성 제목, 본문, 이미지 등 알림 내용 포함 데이터 키-값 쌍으로 구성
사용 예 간단한 알림 전송에 유용 앱에서 특정 작업 수행에 유용
배너 알림 표시 자동으로 베너 알림 표시 앱이 포그라운드일 때 코드로 구현 가능
예시 코드 { "notification": { "title": "알림 제목", "body": "알림 내용" } } { "data": { "key1": "value1", "key2": "value2" } }

 

요약 

알림 메시지 : 시스템이 자동으로 베너 형태의 알림을 관리해주며, 앱의 상태와 무관하게 표시된다.

데이터 메시지 : 앱이 실행 중일 때만 앱 내 코드로 처리할 수 있다. 베너 알림을 표시하려면 직접 구현해야 한다.

 

반응형
블로그 이미지

SKY STORY

,
반응형
 

<application>  <activity> 태그의 속성과 하위 요소, 적용 가능 API, 필수여부 등을 정리해 보았다.

 

<application> 태그 속성

앱의 전체적인 설정을 제어하며, 여러 속성  하위 요소를 통해 앱의 동작, 권한, 리소스 등을 정의할  있다.

속성 적용 가능 API 버전
(Android 버전)
필수 여부 설명
android:icon API 1 (Android 1.0) 필수 앱의 기본 아이콘을 설정합니다.
android:label API 1 (Android 1.0) 선택 앱의 기본 이름(라벨)을 설정합니다.
android:theme API 1 (Android 1.0) 선택 애플리케이션의 기본 테마를 설정합니다.
android:permission API 1 (Android 1.0) 선택 앱에서 선언된 모든 컴포넌트에 적용되는 권한을 정의합니다.
android:debuggable API 1 (Android 1.0) 선택 디버깅 모드를 활성화할지 여부를 지정합니다.
android:enabled API 1 (Android 1.0) 선택 애플리케이션이 활성화 상태인지 여부를 지정합니다.
android:hasCode API 1 (Android 1.0) 선택 애플리케이션이 자체적으로 컴파일된 코드(DEX 파일)를 포함하는지 여부를 지정합니다.
android:persistent API 1 (Android 1.0) 선택 시스템 메모리에서 앱이 항상 실행 중인지 여부를 정의합니다.
android:taskAffinity API 1 (Android 1.0) 선택 애플리케이션의 태스크 친화도를 정의합니다.
android:process API 1 (Android 1.0) 선택 앱이 실행될 프로세스를 지정합니다.
android:allowTaskReparenting API 1 (Android 1.0) 선택 태스크 변경 시 액티비티가 재배치될 수 있는지 여부를 지정합니다.
android:killAfterRestore API 1 (Android 1.0) 선택 백업 후 애플리케이션을 종료할지 여부를 설정합니다.
android:restoreAnyVersion API 1 (Android 1.0) 선택 앱이 다른 버전의 백업 데이터를 복원할 수 있는지 여부를 설정합니다.
android:resizeableActivity API 1 (Android 1.0) 선택 애플리케이션의 액티비티가 크기 조정 가능한지 여부를 지정합니다.
android:usesCleartextTraffic API 1 (Android 1.0) 선택 앱에서 암호화되지 않은 트래픽을 허용할지 여부를 정의합니다.
android:installLocation API 8 (Android 2.2) 선택 앱이 설치될 위치를 지정합니다. (auto, internalOnly, preferExternal)
android:backupAgent API 8 (Android 2.2) 선택 백업 및 복원을 담당하는 백업 에이전트를 정의합니다.
android:allowBackup API 8 (Android 2.2) 선택 앱 데이터의 백업을 허용할지 여부를 정의합니다.
android:hardwareAccelerated API 11 (Android 3.0) 선택 애플리케이션에서 하드웨어 가속을 사용할지 여부를 설정합니다.
android:largeHeap API 11 (Android 3.0) 선택 애플리케이션이 더 큰 힙 메모리를 사용할 수 있는지 여부를 지정합니다.
android:vmSafeMode API 11 (Android 3.0) 선택 앱이 VM에서 안전 모드로 실행될지 여부를 지정합니다.
android:isGame API 19 (Android 4.4) 선택 앱이 게임인지 여부를 정의합니다.
android:banner API 20 (Android 4.4W) 선택 Android TV에서 사용할 배너 이미지를 지정합니다.
android:restrictedAccountType API 22 (Android 5.1) 선택 제한된 계정의 유형을 설정합니다.
android:fullBackupContent API 23 (Android 6.0) 선택 백업 내용과 제외 항목을 정의하는 XML 파일을 지정합니다.
android:roundIcon API 25 (Android 7.1) 선택 원형 아이콘을 지정합니다.
android:category API 26 (Android 8.0) 선택 애플리케이션의 카테고리를 정의합니다. (game, productivity, social 등)
android:appComponentFactory API 28 (Android 9.0) 선택 애플리케이션의 컴포넌트 생성을 처리하는 클래스를 지정합니다.
android:profileable API 29 (Android 10.0) 선택 애플리케이션이 성능 프로파일링이 가능한지 여부를 정의합니다.
android:dataExtractionRules API 31 (Android 12.0) 선택 앱의 데이터 추출 규칙을 정의하는 XML 파일 경로를 지정합니다.

<application> 태그 하위 요소

하위요소 적용 가능 API 버전
(Android 버전)
필수 여부 설명
<activity> API 1 (Android 1.0) 필수 앱의 액티비티를 선언합니다.
<service> API 1 (Android 1.0) 선택 백그라운드 작업을 수행하는 서비스 컴포넌트를 선언합니다.
<receiver> API 1 (Android 1.0) 선택 브로드캐스트 수신기를 선언합니다.
<provider> API 1 (Android 1.0) 선택 앱에서 데이터를 공유할 수 있는 콘텐츠 제공자를 선언합니다.
<uses-library> API 1 (Android 1.0) 선택 앱에서 사용할 추가 라이브러리를 선언합니다.
<meta-data> API 1 (Android 1.0) 선택 추가적인 메타데이터 정보를 설정합니다.
<activity-alias> API 1 (Android 1.0) 선택 기존 액티비티의 별칭을 정의하여 다른 이름으로 사용할 수 있도록 합니다.
<permission> API 1 (Android 1.0) 선택 앱에서 정의하는 권한을 선언합니다.
<permission-group> API 1 (Android 1.0) 선택 권한을 그룹화하여 선언합니다.
<permission-tree> API 1 (Android 1.0) 선택 권한의 계층 구조를 선언합니다.
<uses-permission> API 1 (Android 1.0) 선택 앱이 필요로 하는 권한을 정의합니다. 특정 기능을 사용하려면 권한 요청이 필요할 때 추가합니다.
<profileable> API 29 (Android 10.0) 선택 앱의 성능을 프로파일링할 수 있는지 여부를 정의합니다.

 


 

<activity> 태그 속성

액티비티의 동작과 속성을 정의한다. 앱의 개별 화면을 구성하며, 앱의 주요 동작 방식을 정의할 있다.

속성 적용 가능 API 버전
(Android 버전)
필수 여부 설명
android:name API 1 (Android 1.0) 필수 액티비티의 클래스 이름을 정의합니다.
android:label API 1 (Android 1.0) 선택 액티비티의 이름을 정의합니다.
android:theme API 1 (Android 1.0) 선택 액티비티에서 사용할 테마를 설정합니다.
android:icon API 1 (Android 1.0) 선택 액티비티에 사용할 아이콘을 설정합니다.
android:permission API 1 (Android 1.0) 선택 액티비티에 접근하기 위해 필요한 권한을 설정합니다.
android:configChanges API 1 (Android 1.0) 선택 액티비티가 처리할 구성 변경 사항을 설정합니다.
android:launchMode API 1 (Android 1.0) 선택 액티비티의 실행 모드를 지정합니다.
android:taskAffinity API 1 (Android 1.0) 선택 태스크의 친화도를 지정합니다.
android:windowSoftInputMode API 3 (Android 1.5) 선택 소프트 입력 모드의 동작을 설정합니다. (adjustResize, adjustPan 등)
android:hardwareAccelerated API 11 (Android 3.0) 선택 하드웨어 가속을 사용할지 여부를 설정합니다.
android:clearTaskOnLaunch API 1 (Android 1.0) 선택 태스크가 시작될 때 다른 액티비티를 모두 종료할지 여부를 설정합니다.
android:alwaysRetainTaskState API 1 (Android 1.0) 선택 태스크의 상태를 항상 유지할지 여부를 설정합니다.
android:autoRemoveFromRecents API 21 (Android 5.0) 선택 액티비티가 종료되면 최근 작업 목록에서 자동으로 제거될지 여부를 설정합니다.
android:allowEmbedded API 30 (Android 11.0) 선택 액티비티가 다른 액티비티 내에 임베드될 수 있는지 여부를 설정합니다.
android:exported API 31 (Android 12.0) 필수 외부에서 액티비티를 호출할 수 있는지 여부를 정의합니다.

<activity> 태그 하위 요소

하위요소 적용 가능 API 버전
(Android 버전)
필수 여부 설명
<intent-filter> API 1 (Android 1.0) 선택 액티비티가 처리할 수 있는 인텐트를 정의합니다.
<meta-data> API 1 (Android 1.0) 선택 액티비티에 대한 추가 메타데이터를 제공하여 앱 실행 시 필요한 정보를 설정할 수 있습니다.
<layout> API 1 (Android 1.0) 선택 액티비티가 사용할 레이아웃을 정의합니다. 보통 XML 파일로 참조됩니다.

 

<intent-filter> 태그 하위 요소

하위요소 적용 가능 API 버전
(Android 버전)
필수 여부 설명
<action> API 1 (Android 1.0) 필수 인텐트 필터에서 처리할 수 있는 인텐트 액션을 정의합니다. 예: android.intent.action.MAIN
<category> API 1 (Android 1.0) 선택 인텐트 필터에서 처리할 수 있는 인텐트 카테고리를 정의합니다. 예: android.intent.category.LAUNCHER
<data> API 1 (Android 1.0) 선택 인텐트 필터가 처리할 수 있는 데이터(URI, MIME 타입 등)를 정의합니다.

 

 

반응형
블로그 이미지

SKY STORY

,
반응형

Toast가 여러 줄로 출력되지 않는 경우는 디바이스의 화면 크기텍스트의 길이 때문이다. 그래서 여러 줄을 출력하기위해 TextView를 사용하는 MultiLine Toast를 만들어 보았다.

 

1. res/layout/multiline_toast.xml 파일 생성:

<!-- res/layout/multiline_toast.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/black"
    android:padding="10dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/multiline_toast_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white"
        android:textSize="16sp"/>
</LinearLayout>

 

2. showMultiLineToast 함수 작성:

private fun showMultiLineToast(message: String) {
    // 1. LayoutInflater를 사용해 multiline_toast 레이아웃을 불러옴
    val inflater = layoutInflater
    val layout = inflater.inflate(R.layout.multiline_toast, findViewById(R.id.multiline_toast_text))

    // 2. multiline_toast 레이아웃의 TextView에 메시지를 설정
    val textView: TextView = layout.findViewById(R.id.multiline_toast_text)
    textView.text = message

    // 3. Toast에 multi-line layout을 설정
    with(Toast(applicationContext)) {
        duration = Toast.LENGTH_LONG
        view = layout
        show()
    }
}

 

3. 사용 예시:

val message = """
    BLE 스캔 성공:
    deviceName: ${result.deviceName}
    RSSI: ${result.rssi}
    data: ${result.data}
""".trimIndent()

showMultiLineToast(message)  // Multi-line Toast로 출력

 

 

반응형
블로그 이미지

SKY STORY

,

NFC 권한설정

개발/Android 2024. 10. 21. 11:50
반응형

NFC 태그 사용을 위한 권한설정에 대해 알아보겠다.

NFC 태그가 앱에 의해 감지될 때 android.nfc.action.TAG_DISCOVERED는 NFC 태그가 감지될 때 인텐트를 전달하는 데 필요하다. 이를 위해 AndroidManifest.xml에 설정을 추가해야 한다. 이 설정은 TAG_DISCOVERED, TECH_DISCOVERED, NDEF_DISCOVERED와 같은 액션을 통해 NFC 태그 감지 시 앱으로 인텐트를 전달하는 역할을 한다.

 

권한 설명

  1. android.nfc.action.NDEF_DISCOVERED:
    NDEF 메시지를 포함한 NFC 태그가 감지되었을 때 작동하는 액션이다. 주로 특정 애플리케이션 데이터 또는 MIME 타입이 있는 태그에서 사용된다.
  2. android.nfc.action.TAG_DISCOVERED:
    NFC 태그가 감지되었을 때 작동하는 기본 액션으로, NDEF 메시지가 포함되지 않은 모든 NFC 태그를 처리할 수 있다.
  3. android.nfc.action.TECH_DISCOVERED:
    태그가 특정 기술(예: NfcA, MifareUltralight 등)을 지원할 때 작동한다. 이를 통해 특정 기술 스택을 가진 태그를 처리할 수 있다. 예를 들어 nfc_tech_filter.xml에서 정의된 기술과 일치하는 태그가 감지되었을 때 인텐트를 처리한다.

추가 설명

  • MIME 타입은 NDEF 태그의 데이터를 처리할 때 필수입니다. 예를 들어, "text/plain"은 특정 애플리케이션 데이터 타입을 지정한 것입니다.
  • NDEF_DISCOVERED는 NDEF 메시지가 포함된 태그만 처리할 수 있으므로, 태그의 내용이 특정 유형(MIME 타입)일 때만 작동하게끔 설정됩니다.
  • TECH_DISCOVERED는 기술 스택을 기반으로 태그를 처리하며, nfc_tech_filter.xml에서 정의한 기술과 일치하는 태그가 감지되면 작동합니다.

AndroidManifest.xml 에 추가된 설정 예 :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mwkg.testwebview">


    <!-- NFC 권한 설정 -->
    <uses-permission android:name="android.permission.NFC"/>

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.TestWebView">

        <!-- FCM 푸시 알림 서비스 등록 -->
        <service
            android:name=".MyFirebaseMessagingService"
            android:exported="true"
            android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>

        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.TestWebView">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <!-- NFC NDEF 태그 인텐트 필터 -->
            <intent-filter>
                <!-- NDEF 메시지를 포함한 NFC 태그가 감지될 때 앱으로 인텐트를 전달 -->
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />
                <category android:name="android.intent.category.DEFAULT" />

                <!-- NDEF 메시지에서 처리할 MIME 유형 지정 (예: 특정 애플리케이션 또는 텍스트 MIME 유형) -->
                <data android:mimeType="text/plain" />  <!-- ex: "text/plain" 또는 "application/vnd.*" -->
            </intent-filter>

            <!-- NFC 태그 인텐트 필터 -->
            <intent-filter>
                <!-- 모든 NFC 태그가 감지될 때 앱으로 인텐트를 전달 (NDEF 메시지가 없을 때도 작동) -->
                <action android:name="android.nfc.action.TAG_DISCOVERED" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

            <!-- NFC 기술 인텐트 필터 -->
            <intent-filter>
                <!-- NFC 태그에 기술 스택이 감지되면 앱으로 인텐트를 전달 (특정 기술 유형을 지원하는 태그를 처리) -->
                <action android:name="android.nfc.action.TECH_DISCOVERED" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

            <!-- NFC 기술 필터 설정 (nfc_tech_filter.xml 파일을 참조하여 특정 기술을 처리) -->
            <meta-data
                android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfc_tech_filter" />
        </activity>
    </application>

</manifest>

 

nfc_tech_filter.xml 사용 예 :

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <!-- Ndef 태그 (NFC Data Exchange Format) -->
    <tech-list>
        <tech>android.nfc.tech.Ndef</tech>
    </tech-list>

    <!-- NdefFormatable 태그 (NFC 태그를 NDEF 형식으로 포맷할 수 있는 경우) -->
    <tech-list>
        <tech>android.nfc.tech.NdefFormatable</tech>
    </tech-list>

    <!-- NfcA 태그 (ISO 14443-3A) -->
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
    </tech-list>

    <!-- NfcB 태그 (ISO 14443-3B) -->
    <tech-list>
        <tech>android.nfc.tech.NfcB</tech>
    </tech-list>

    <!-- NfcF 태그 (Felica, JIS 6319-4) -->
    <tech-list>
        <tech>android.nfc.tech.NfcF</tech>
    </tech-list>

    <!-- NfcV 태그 (ISO 15693) -->
    <tech-list>
        <tech>android.nfc.tech.NfcV</tech>
    </tech-list>

    <!-- IsoDep 태그 (ISO 14443-4) -->
    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
    </tech-list>

    <!-- MifareClassic 태그 -->
    <tech-list>
        <tech>android.nfc.tech.MifareClassic</tech>
    </tech-list>

    <!-- MifareUltralight 태그 -->
    <tech-list>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>



    <!-- 기술 조합이 필요한 경우 -->
    <!-- NfcA와 Ndef, MifareUltralight를 동시에 지원하는 태그 -->
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
</resources>

 

 

반응형
블로그 이미지

SKY STORY

,
반응형

NdefFormatable은 NFC 태그를 NDEF 형식으로 포맷할 수 있을 때 사용하는 인터페이스이다. 만약 NFC 태그가 NDEF 형식으로 포맷되지 않은 경우, NDEF 포맷팅 작업을 수행할 수 있다. 이 기능은 주로 NFC 태그가 기본적으로 NDEF 메시지를 지원하지 않는 경우에 사용된다. NDEF 포맷팅은 태그에 데이터를 기록할 수 있는 형태로 변환하는 과정을 말한다.

NdefFormatable 사용 시점:

  • NFC 태그가 아직 NDEF 포맷으로 되어 있지 않은 경우 NdefFormatable을 사용하여 태그를 포맷하고 NDEF 메시지를 기록할 수 있다.
  • 한 번만 포맷할 수 있는 태그, 비어 있는 상태에서만 포맷할 수 있는 태그에 유용하다.

일반적으로 NFC 태그를 처음 사용하거나 비어 있는 상태에서 NDEF 메시지를 기록하려는 경우 NdefFormatable은 포맷할 수 있는 태그에 대해 connect(), format()  writeNdefMessage()와 같은 작업을 제공한다.

다음은 NdefFormatable을 사용하여 NFC 태그를 NDEF 형식으로 포맷하고 데이터를 기록하는 예이다.

fun formatTagWithNdefMessage(tag: Tag, ndefMessage: NdefMessage): Boolean {
    val ndefFormatable = NdefFormatable.get(tag)

    if (ndefFormatable != null) {
        try {
            // NDEF 포맷팅을 위해 태그 연결
            ndefFormatable.connect()

            // NDEF 메시지로 태그 포맷 및 데이터 기록
            ndefFormatable.format(ndefMessage)

            Log.d("NFC", "태그를 NDEF 형식으로 포맷하고 메시지를 기록했습니다.")
            return true
        } catch (e: IOException) {
            Log.e("NFC", "태그 포맷팅 실패: ${e.message}")
        } finally {
            try {
                ndefFormatable.close()
            } catch (e: IOException) {
                Log.e("NFC", "태그 닫기 실패: ${e.message}")
            }
        }
    } else {
        Log.e("NFC", "이 태그는 NDEF 포맷이 지원되지 않습니다.")
    }

    return false
}
 

 

주요 메서드 설명:

  • NdefFormatable.get(tag): Tag 객체에서 NdefFormatable 인스턴스를 얻는다. NDEF 포맷 미지원 시 null을 반환 한다.
  • connect(): NFC 태그와 연결을 시도한다.
  • format(NdefMessage): 태그를 NDEF 형식으로 포맷하고, 제공된 NDEF 메시지를 기록한다.
  • close(): 태그와의 연결 종료한다.

주의사항:

  • NDEF 형식으로 포맷하면 원래 상태로 되돌릴 수 없다.
  • 일부 태그는 포맷 후에도 더 이상 기록할 수 없는 경우가 있다. (읽기 전용 태그로 변환).
  • 모든 태그가 NDEF 포맷을 지원하지 않는다.

 

반응형

'개발 > Android' 카테고리의 다른 글

멀티라인 Toast 메시지 출력  (0) 2024.10.24
NFC 권한설정  (1) 2024.10.21
NFC Tag 상세정보 출력  (2) 2024.10.18
안드로이드 각 버전별 추가된 주요 기능  (0) 2024.10.15
JIT, AOT 컴파일 비교  (1) 2024.10.15
블로그 이미지

SKY STORY

,
반응형

NFC Tag에서 얻을 수 있는 정보를 json 문자열 포맷으로 반환하는 함수를 만들어보았다.

테그 정보 :

  1. UID (고유 ID): tag.id에서 추출한 고유 식별자.
  2. Tech List: 태그가 지원하는 모든 기술 목록 (tag.techList).
  3. NfcA (ISO 14443-3A): ATQA, SAK, 최대 전송 길이, 타임아웃 정보.
  4. IsoDep (ISO 14443-4): 역사적 바이트(historicalBytes), 고층 응답(hiLayerResponse), 최대 전송 길이, 타임아웃 정보.
  5. NfcB (ISO 14443-3B): 응용 데이터, 프로토콜 정보, 최대 전송 길이.
  6. NfcF (Felica): 제조사 정보, 시스템 코드, 최대 전송 길이, 타임아웃.
  7. NfcV (ISO 15693): 응답 플래그, DSFID, 최대 전송 길이.
  8. MifareClassic: 타입, 크기, 섹터 블록 .
  9. MifareUltralight: 타입 정보 (Ultralight, Ultralight C).

 

구현 함수는 다음과 같다.

fun readTagDetailsAsJson(tag: Tag): String {
    val tagInfo = mutableMapOf<String, Any>()

    // UID 정보 (태그 고유 ID)
    tagInfo["uid"] = tag.id.joinToString("") { String.format("%02X", it) }

    // 기술 스택 나열 (태그가 지원하는 모든 기술들)
    tagInfo["techList"] = tag.techList.joinToString()

    // NfcA (ISO 14443-3A) 정보
    val nfcA = NfcA.get(tag)
    if (nfcA != null) {
        tagInfo["NfcA"] = mapOf(
            // ATQA: Answer to Request Type A. 태그가 리더기에 응답할 때 사용하는 정보
            "atqa" to nfcA.atqa.joinToString("") { String.format("%02X", it) },
            // SAK: Select Acknowledge. 태그가 리더기에 제공하는 지원 기능 정보
            "sak" to String.format("%02X", nfcA.sak),
            // 한 번에 보낼 수 있는 최대 전송 길이 (바이트 단위)
            "maxTransceiveLength" to nfcA.maxTransceiveLength,
            // 통신 타임아웃 시간 (밀리초 단위)
            "timeout" to nfcA.timeout
        )
    }

    // IsoDep (ISO 14443-4) 정보
    val isoDep = IsoDep.get(tag)
    if (isoDep != null) {
        tagInfo["IsoDep"] = mapOf(
            // Historical Bytes: 태그가 초기 통신 설정 시 리더기에 제공하는 추가 정보
            "historicalBytes" to (isoDep.historicalBytes?.joinToString("") { String.format("%02X", it) } ?: "N/A"),
            // Higher Layer Response: 고급 프로토콜에 대한 응답 정보
            "hiLayerResponse" to (isoDep.hiLayerResponse?.joinToString("") { String.format("%02X", it) } ?: "N/A"),
            // 한 번에 전송할 수 있는 최대 데이터 길이 (바이트 단위)
            "maxTransceiveLength" to (isoDep.maxTransceiveLength.toString() ?: "N/A"),
            // 통신 타임아웃 시간 (밀리초 단위)
            "timeout" to isoDep.timeout
        )
    }

    // NfcB (ISO 14443-3B) 정보
    val nfcB = NfcB.get(tag)
    if (nfcB != null) {
        tagInfo["NfcB"] = mapOf(
            // Application Data: 태그의 애플리케이션과 관련된 데이터
            "applicationData" to (nfcB.applicationData?.joinToString("") { String.format("%02X", it) } ?: "N/A"),
            // Protocol Info: 태그가 제공하는 프로토콜 정보
            "protocolInfo" to (nfcB.protocolInfo?.joinToString("") { String.format("%02X", it) } ?: "N/A")
        )
    }

    // NfcF (Felica, JIS 6319-4) 정보
    val nfcF = NfcF.get(tag)
    if (nfcF != null) {
        tagInfo["NfcF"] = mapOf(
            // 제조사 코드
            "manufacturer" to (nfcF.manufacturer?.joinToString("") { String.format("%02X", it) } ?: "N/A"),
            // 시스템 코드
            "systemCode" to (nfcF.systemCode?.joinToString("") { String.format("%02X", it) } ?: "N/A"),
            // 한 번에 전송할 수 있는 최대 데이터 길이 (바이트 단위)
            "maxTransceiveLength" to nfcF.maxTransceiveLength.toString(),
            // 통신 타임아웃 시간 (밀리초 단위)
            "timeout" to nfcF.timeout.toString()
        )
    }

    // NfcV (ISO 15693) 정보
    val nfcV = NfcV.get(tag)
    if (nfcV != null) {
        tagInfo["NfcV"] = mapOf(
            // 응답 플래그
            "responseFlags" to String.format("%02X", nfcV.responseFlags),
            // DSFID (Data Storage Format Identifier)
            "dsfId" to String.format("%02X", nfcV.dsfId),
            // 한 번에 전송할 수 있는 최대 데이터 길이 (바이트 단위)
            "maxTransceiveLength" to nfcV.maxTransceiveLength
        )
    }

    // NfcBarcode (Type V or JIS 6319-4) 정보 - maxTransceiveLength 지원 없음
    val nfcBarcode = NfcBarcode.get(tag)
    if (nfcBarcode != null) {
        tagInfo["NfcBarcode"] = mapOf(
            // 바코드 타입 정보 (Type V or JIS 6319-4)
            "type" to nfcBarcode.type
        )
    }

    // MifareClassic 정보
    val mifareClassic = MifareClassic.get(tag)
    if (mifareClassic != null) {
        tagInfo["MifareClassic"] = mapOf(
            // MifareClassic 타입 (Classic, Plus, Pro)
            "type" to when (mifareClassic.type) {
                MifareClassic.TYPE_CLASSIC -> "Classic"
                MifareClassic.TYPE_PLUS -> "Plus"
                MifareClassic.TYPE_PRO -> "Pro"
                else -> "Unknown"
            },
            // MifareClassic 메모리 크기
            "size" to mifareClassic.size,
            // 섹터 개수
            "sectorCount" to mifareClassic.sectorCount,
            // 블록 개수
            "blockCount" to mifareClassic.blockCount
        )
    }

    // MifareUltralight 정보
    val mifareUltralight = MifareUltralight.get(tag)
    if (mifareUltralight != null) {
        tagInfo["MifareUltralight"] = mapOf(
            // MifareUltralight 타입 (Ultralight, Ultralight C)
            "type" to when (mifareUltralight.type) {
                MifareUltralight.TYPE_ULTRALIGHT -> "Ultralight"
                MifareUltralight.TYPE_ULTRALIGHT_C -> "Ultralight C"
                else -> "Unknown"
            }
        )
    }

    // JSON 형태로 변환하여 반환
    return JSONObject(tagInfo as Map<*, *>).toString()
}

 

결과값 로그 출력 값은 아래와 같다.

로그 출력 값 예 :
{
  "uid": "641B27A2B67881",  // 시리얼 번호
  "techList": "android.nfc.tech.IsoDep, android.nfc.tech.NfcA", // 태그에서 지원하는 NFC 기술 목록
  "NfcA": {		// NfcA (ISO/IEC 14443-3A) 기술에 대한 정보
    "atqa": "4800",		// Answer to Request, Type A (ATQA) 값
    "sak": "20",		// Select Acknowledge (SAK) 값
    "maxTransceiveLength": 253,	// NFC 통신에서 한 번에 전송할 수 있는 최대 데이터 길이(바이트)
    "timeout": 618		// 통신 타임아웃 시간(밀리초)
  },
  "IsoDep": {	// IsoDep (ISO/IEC 14443-4) 기술에 대한 정보
    "historicalBytes": "",	// NFC 태그가 최초로 통신을 시작할 때 제공하는 부가적인 정보를 포함
    "hiLayerResponse": "N\/A",	// 태그가 고급 프로토콜을 지원하는 경우 제공
    "maxTransceiveLength": "65279",// IsoDep에서 한 번에 전송할 수 있는 최대 데이터 길이
    "timeout": 618		// 통신 타임아웃 시간(밀리초)
  }
}

 

 

반응형

'개발 > Android' 카테고리의 다른 글

NFC 권한설정  (1) 2024.10.21
NdefFormatable 태그  (0) 2024.10.21
안드로이드 각 버전별 추가된 주요 기능  (0) 2024.10.15
JIT, AOT 컴파일 비교  (1) 2024.10.15
FCM 푸시설정  (0) 2024.10.14
블로그 이미지

SKY STORY

,
반응형

Android 5.0 (API 21 - Lollipop)

  1. Material Design 도입: 새로운 디자인 언어로, 더 직관적이고 일관된 UI 제공.
    • Elevation: 뷰에 그림자와 깊이를 추가하여 더 입체적인 UI 구현.
    • Ripple Effect: 버튼 등에서 터치 반응 효과 추가.
  2. RecyclerView: ListView보다 효율적인 데이터 표시를 위한 컴포넌트.
    • 더 나은 성능과 애니메이션 지원.
    • ViewHolder 패턴을 강제하여 성능 최적화.
  3. JobScheduler API: 작업을 백그라운드에서 실행하는 API로 배터리 효율성을 높임.
    • 네트워크 상태, 충전 중 여부 등을 기반으로 작업 실행 제어 가능.
  4. **ART(Android Runtime)**로 전환: JIT(Just-In-Time) 컴파일 대신 AOT(Ahead-Of-Time) 컴파일을 도입하여 앱 성능 향상.
  5. Notifications: 알림의 스타일을 개선하고, 사용자가 바로 상호작용할 수 있는 Heads-up 알림 추가.

Android 5.1 (API 22 - Lollipop)

  1. HD Voice: 고화질 음성 통화 지원.
  2. Dual-SIM Support: 두 개의 SIM 카드를 사용하는 기능 지원.
  3. Device Protection: 기기가 초기화되었을 때도 Google 계정을 통해 잠금을 유지할 수 있는 기능.
  4. Wi-Fi Calling: Wi-Fi를 이용해 통화할 수 있는 기능 도입.

Android 6.0 (API 23 - Marshmallow)

  1. App Permissions: 런타임 권한 시스템 도입, 사용자가 앱 실행 중 개별적으로 권한을 승인할 수 있음.
  2. Doze Mode: 배터리 절약을 위해 기기가 오랫동안 사용되지 않으면 백그라운드 활동을 제한.
  3. Fingerprint API: 지문 인식 기능을 이용해 앱에서 인증할 수 있는 기능 제공.
  4. App Links: HTTP 링크를 앱과 직접 연결하여 앱 내에서 URL을 처리 가능.
  5. Adoptable Storage: SD 카드나 USB 저장소를 내부 저장소로 포맷하여 앱 데이터를 저장할 수 있도록 지원.

Android 7.0 (API 24 - Nougat)

  1. Multi-Window Support: 화면을 분할하여 두 개의 앱을 동시에 실행할 수 있는 기능 도입.
    • Split-Screen(화면 분할) 및 Picture-in-Picture(PiP) 모드 지원.
  2. Direct Reply Notifications: 알림에서 바로 메시지나 답장을 할 수 있는 기능 제공.
  3. Doze on the Go: 기기가 이동 중일 때도 배터리 절약 기능을 활성화.
  4. Vulkan API: 고성능 3D 그래픽 렌더링을 위한 API 도입.
  5. Java 8 Support: 새로운 언어 기능을 포함한 Java 8의 일부 기능 지원.

Android 7.1 (API 25 - Nougat)

  1. App Shortcuts: 홈 화면에서 앱 아이콘을 길게 눌러 자주 사용하는 기능으로 바로 이동할 수 있는 기능.
  2. Image Keyboard: 키보드를 통해 직접 이미지를 전송할 수 있는 기능 도입.
  3. Circular App Icons: 아이콘을 원형으로 표시할 수 있는 기능 추가.

Android 8.0 (API 26 - Oreo)

  1. Adaptive Icons: 아이콘의 모양이 런처에 따라 동적으로 변할 수 있는 기능. 여러 모양(정사각형, 원형, 물방울 등)을 지원.
    • 아이콘을 전경(foreground)과 배경(background)으로 분리하여 다이내믹한 효과를 줄 수 있음.
  2. Notification Channels: 알림을 카테고리별로 그룹화하고, 사용자에게 더 세밀한 알림 제어권 제공.
    • 사용자가 각 채널별로 알림의 중요도, 사운드 등을 설정할 수 있음.
  3. Picture-in-Picture (PiP): 사용자가 비디오를 작은 창으로 띄워 다른 앱을 사용할 수 있는 기능.
  4. Background Execution Limits: 앱의 백그라운드 활동에 제한을 두어 배터리 절약.
  5. Autofill Framework: 사용자 정보를 자동으로 입력할 수 있는 기능.

Android 8.1 (API 27 - Oreo)

  1. Neural Networks API: 머신 러닝을 위한 하드웨어 가속 API 제공.
  2. Autofill Enhancements: 자동 완성 기능이 향상되어 더 많은 앱에서 지원 가능.
  3. Shared Memory API: 프로세스 간 공유 메모리를 안전하게 사용할 수 있는 기능.

Android 9 (API 28 - Pie)

  1. Adaptive Battery: 앱의 사용 패턴을 학습하여 자주 사용하는 앱에 우선순위를 부여해 배터리 효율을 향상.
  2. App Actions: 사용자의 행동을 예측하고 적절한 기능을 앱에서 바로 실행할 수 있는 기능 제공.
  3. Slices API: 앱의 주요 기능을 검색 결과나 Google Assistant에서 사용할 수 있게 함.
  4. Gesture Navigation: 홈 버튼 대신 제스처를 통해 내비게이션하는 새로운 방식 도입.
  5. Background App Privacy Restrictions: 백그라운드 앱의 카메라, 마이크, 센서 접근을 제한하여 보안 강화.

Android 10 (API 29 - Q)

  1. Dark Theme: 시스템 전반에서 다크 모드 제공.
  2. Gesture Navigation: 더 직관적이고 개선된 제스처 내비게이션 도입.
  3. Privacy Enhancements: 위치 권한을 앱이 포그라운드일 때만 사용하도록 설정 가능.
  4. Scoped Storage: 각 앱이 자신의 영역에만 파일을 저장할 수 있도록 제한.
  5. Foldable Device Support: 폴더블 기기를 지원하기 위한 새로운 화면 전환 및 상태 관리 API.

Android 11 (API 30)

  1. Bubbles API: 메시지 앱에서 대화형 버블을 통해 멀티태스킹 가능.
  2. One-time Permissions: 위치, 카메라, 마이크에 대한 1회성 권한 부여 가능.
  3. Scoped Storage 개선: 앱의 저장소 접근 방식을 개선하여 데이터 보안 강화.
  4. Conversations in Notifications: 대화형 알림이 더 직관적이고 우선적으로 처리되도록 개선.

Android 12 (API 31)

  1. Material You: 사용자 맞춤형 색상 테마를 설정할 수 있는 기능으로 UI 개인화 가능.
  2. Privacy Dashboard: 사용자가 앱이 접근한 위치, 카메라, 마이크 정보에 대해 더 명확하게 볼 수 있는 대시보드 제공.
  3. Approximate Location: 앱이 대략적인 위치 정보만 요청할 수 있도록 지원.
  4. Mic/Camera Indicators: 상태 표시줄에 마이크와 카메라 사용 여부를 표시하는 기능 추가.
  5. Haptic Feedback Enhancements: 진동 패턴을 더 세밀하게 제어할 수 있는 기능 제공.

Android 12L (API 32)

  1. Large Screen Enhancements: 태블릿 및 폴더블 기기와 같은 큰 화면을 위한 UI 개선.
  2. Taskbar: 대형 화면에서 더 쉬운 멀티태스킹을 위한 태스크바 추가.

Android 13 (API 33)

  1. Per-App Language Preferences: 앱마다 다른 언어 설정이 가능.
  2. Photo Picker: 특정 사진만 앱에 제공할 수 있도록 새로운 사진 선택기 도입.
  3. Notification Permission: 앱에서 알림을 보내기 위해 사용자의 동의를 받아야 함.
  4. Bluetooth LE Audio: 저전력 오디오 전송을 위한 Bluetooth LE Audio 지원.

Android 14 (API 34)

  1. Predictive Back Gesture: 뒤로 가기 제스처를 미리 볼 수 있는 기능 도입.
  2. Regional Preferences: 사용자 지역에 따라 온도 단위, 시작 요일 등을 커스터마이징할 수 있음.
  3. App Cloning: 같은 앱을 여러 계정으로 실행할 수 있는 기능 지원.
  4. Credential Manager API: 패스워드 및 패스키 기반 인증을 통합 관리할 수 있는 새로운 API.
반응형

'개발 > Android' 카테고리의 다른 글

NdefFormatable 태그  (0) 2024.10.21
NFC Tag 상세정보 출력  (2) 2024.10.18
JIT, AOT 컴파일 비교  (1) 2024.10.15
FCM 푸시설정  (0) 2024.10.14
디버그 서명 인증서와 릴리즈 서명 인증서 차이  (0) 2024.10.14
블로그 이미지

SKY STORY

,
반응형

JIT(Just-In-Time) 컴파일과 AOT(Ahead-Of-Time) 컴파일의 차이점을 표로 정리하면 다음과 같다.

항목JIT(Just-In-Time) 컴파일AOT(Ahead-Of-Time) 컴파일
컴파일 시점 프로그램 실행 중 (런타임) 프로그램 실행 전에 (빌드 또는 배포 시)
초기 실행 속도 초기 실행 시간이 느림 (실시간 컴파일) 초기 실행 시간이 빠름 (미리 컴파일된 상태)
최적화 방식 동적 최적화 (실행 중 분석 후 최적화 가능) 정적 최적화 (컴파일 시 최적화, 실행 중 추가 최적화 불가)
메모리 사용 필요할 때만 컴파일하여 상대적으로 메모리 사용이 적음 모든 코드를 미리 컴파일하므로 더 많은 메모리 사용 가능
코드 분석 실행 중 코드 패턴을 분석해 최적화 가능 실행 중 코드 패턴 분석 불가
배포 파일 크기 컴파일러와 일부 런타임 데이터를 포함하여 다소 큼 컴파일된 바이너리만 포함하여 비교적 작음
플랫폼 의존성 플랫폼에 따라 다르게 컴파일할 수 있어 유연함 플랫폼에 맞게 미리 컴파일되므로 다소 제한적일 수 있음
사용 예시 Java (JVM), .NET, Android iOS (Swift), 일부 C++ 컴파일러, Angular (Ivy)
장점 런타임 최적화로 반복 실행 시 성능 향상 가능 빠른 실행 시간, 미리 컴파일된 바이너리로 보안성이 높음
단점 초기 로딩이 느릴 수 있으며, 컴파일로 인한 런타임 오버헤드 발생 가능 런타임 최적화 불가, 모든 코드를 미리 컴파일하므로 비효율 가능

장단점 요약

  • JIT: 동적 최적화를 통해 실행 중 성능을 개선할 수 있지만, 초기 실행 시간이 느릴 수 있다.
  • AOT: 빠른 시작 시간이 장점이지만, JIT처럼 동적인 최적화를 할 수 없고, 모든 코드를 미리 컴파일하므로 메모리 사용량이 많아질 수 있다.

사용 사례

  • JIT: 일반적으로 자바나 .NET 같은 플랫폼에서 많이 사용되며, 코드가 여러 번 실행되고 최적화가 중요한 경우 유리하다.
  • AOT: iOS의 Swift와 같은 환경에서는 AOT를 많이 사용하며, 프로그램의 빠른 시작 시간이 중요한 경우 적합하다.
반응형
블로그 이미지

SKY STORY

,

FCM 푸시설정

개발/Android 2024. 10. 14. 15:21
반응형

다음은 FCM 푸시 설정관련 내용을 알아보겠다.

Firebase 앱등록은 이미 완료됬다고 가정하겠다.

 

만약 아래 그림과 같이 'Product Flavors' 설정을 하지 않았다면 1번 위치에

설정을 하였다면 2번과 같이 'google-services.json'파일 복사한다.

 

프로젝트 수준 build.gradle :

 

모듈 수준 build.gradle :

 

AndroidManifest.xml에 알림 권한 추가:

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

 

권한 요청 코드 (MainActivity 등에서):

안드로이드 13(API 33) 이상에서는 알림 권한이 필요하다. 

import android.Manifest
import android.content.pm.PackageManager
import androidx.core.content.ContextCompat
import androidx.core.app.ActivityCompat
import android.os.Build

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 푸시 알림 권한 요청
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (ContextCompat.checkSelfPermission(
                    this,
                    Manifest.permission.POST_NOTIFICATIONS
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                // 알림 권한 요청
                ActivityCompat.requestPermissions(
                    this,
                    arrayOf(Manifest.permission.POST_NOTIFICATIONS),
                    1000
                )
            }
        }

        // 그 외 FCM 설정
    }
}

 

FCM 토큰 생성 및 토큰 로그 확인

Firebase에서 푸시 메시지를 보내기 위해서는 FCM 토큰이 필요하다. 이 토큰은 앱 설치 시 자동으로 생성되며, 이를 통해 Firebase는 해당 기기에 푸시 메시지를 전송할 수 있다.

FCM 서비스 초기화 (FirebaseMessagingService 상속):

아래 코드와 같이 FirebaseMessagingService를 상속받아 FCM 토큰을 얻을 수 있다.

import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.messaging.RemoteMessage
import android.util.Log

class MyFirebaseMessagingService : FirebaseMessagingService() {
	
    override fun onNewToken(token: String) {
        super.onNewToken(token)
        Log.d("FCM", "FCM 토큰 생성: $token")
        // 서버로 토큰 전송
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
        Log.d("FCM", "푸시 메시지 수신: ${remoteMessage.notification?.body}")
        // 알림을 처리하거나 사용자에게 알림을 표시
    }
}

 

Firebase 토큰을 가져오는 코드 (선택적, 로그 확인용):

이미 생성된 토큰을 얻는다.

FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
    if (task.isSuccessful) {
        val token = task.result
        Log.d("FCM", "FCM 토큰: $token")
    } else {
        Log.w("FCM", "FCM 토큰 생성 실패", task.exception)
    }
}

 

푸시 수신 처리

푸시 알림이 수신되면, onMessageReceived 메서드에서 이를 처리한다. FCM 서버에서 전송된 메시지의 내용을 바탕으로 푸시 알림을 처리하고, 알림을 기기에 표시할 수 있다.

알림 표시 예제 (푸시 수신 시):

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    super.onMessageReceived(remoteMessage)

    // 메시지의 제목과 본문을 가져옴
    val title = remoteMessage.notification?.title ?: "푸시 알림"
    val message = remoteMessage.notification?.body ?: "새로운 메시지가 있습니다."

    // Android 8.0 이상에서는 알림 채널이 필요
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channelId = "default_channel"
        val channelName = "기본 알림 채널"
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val notificationChannel = NotificationChannel(channelId, channelName, importance)
        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(notificationChannel)
    }

    // 알림 생성
    val notificationBuilder = NotificationCompat.Builder(this, "default_channel")
        .setSmallIcon(android.R.drawable.ic_dialog_info)  // 알림 아이콘 설정
        .setContentTitle(title)
        .setContentText(message)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)

    // 알림 표시
    with(NotificationManagerCompat.from(this)) {
        notify(0, notificationBuilder.build())
    }
}

 

 

반응형
블로그 이미지

SKY STORY

,
반응형

디버그 서명 인증서 Android 앱을 개발하고 테스트할 때 사용됩니다. Android 앱은 개발 중일 때와 실제 배포 시에 서명되어야 하는데, 이 두 경우에 각각 다른 인증서를 사용합니다. 디버그 서명 인증서는 앱이 아직 개발 중일 때, 주로 디버깅 테스트를 위해 사용된다.

 

디버그 서명 인증서와 릴리스 서명 인증서의 차이

용도 개발 및 테스트용 실제 배포용
생성 방법 Android Studio에서 자동 생성 개발자가 직접 생성
키스토어 위치 ~/.android/debug.keystore 개발자가 지정한 경로 (예: my-release-key.jks)
비밀번호 기본값: android 개발자가 설정한 비밀번호
서명 목적 테스트 기기에서 설치 및 실행 Google Play 스토어 또는 외부 배포
유효 기간 30년 개발자가 설정한 기간 (일반적으로 25년 이상)
보안 수준 낮음 (자동 생성된 인증서) 높음 (개발자가 관리하는 인증서)
사용 시점 개발 중, Firebase와 같은 기능 테스트 시 앱 배포 시 (Google Play 스토어 또는 외부 배포)

 

 

반응형
블로그 이미지

SKY STORY

,
반응형

디버그 서명 인증서 Android 앱을 개발하고 테스트할 때 사용된다. Android 앱은 개발 중일 때와 실제 배포 시에 서명되어야 하는데, 이 두 경우에 각각 다른 인증서를 사용한다. 디버그 서명 인증서는 앱이 아직 개발 중일 때, 주로 디버깅 테스트를 위해 사용된다.

Firebase 설정에서 디버그 서명 인증서 사용은 Firebase Authentication 또는 Firebase Cloud Messaging(FCM)과 같은 기능을 테스트할 때, 디버그 서명 인증서의 SHA-1 해시 값이 필요하다. 이는 Firebase가 디버그 빌드에서도 Firebase 기능을 사용할 수 있도록 앱을 식별하기 위해 사용된다.

 

Android 앱에 Firebase를 추가할 때, 디버그 서명 인증서의 SHA-1 정보를 등록하는 방법을 알아보자.

https://console.firebase.google.com/

 

디버그 서명 인증서 SHA-1 정보 확인하기

Android Studio를 사용하여 SHA-1 해시 값을 확인할 수 있는 방법이 두 가지 있다.


방법 1: Android Studio를 통해 SHA-1 값 확인

  1. Android Studio에서 Gradle 창을 연다.
    • 화면 우측의 Gradle 탭을 클릭. (보이지 않으면 View > Tool Windows > Gradle)
  2. Gradle Tasks 실행:
    • 프로젝트 이름을 선택한 후, Tasks > android > signingReport를 더블 클릭.
  3. SHA-1 값 확인:
    • signingReport를 실행하면 디버그 및 릴리스 키의 SHA-1  SHA-256 해시 값이 Android Studio의 Run 창에 출력된다.
    • 아래와 같은 내용 출력:
      Variant: debug 
      Config: debug 
      Store: /Users/username/.android/debug.keystore 
      Alias: AndroidDebugKey 
      MD5: A1:B2:C3:... 
      SHA1: AA:BB:CC:DD:... 
      SHA-256: AB:CD:...
  4. SHA-1 값 복사:
    • 여기서 SHA-1 값을 복사하여 Firebase 콘솔에 입력한다.

 

방법 2: 명령어로 디버그 서명 인증서 SHA-1 확인 (keytool 사용)

  1. 명령어 실행:
    • 명령어를 통해 SHA-1 값을 확인 가능하다.
    • macOS 또는 Linux에서는 터미널, Windows에서는 명령 프롬프트 사용.
    keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
     
  2. SHA-1 값 출력 확인:
    • 위 명령어를 실행하면 SHA-1 해시 값이 표시.
    SHA1: AA:BB:CC:DD:...
  3. SHA-1 값 복사:
    • SHA-1 값을 복사하여 Firebase 콘솔에 입력.

 

2:45:52 PM: Executing 'signingReport'...

Executing tasks: [signingReport] in project /Users/netcanis/projects4/TestWebview


> Task :app:signingReport
Variant: debug
Config: debug
Store: /Users/netcanis/.android/debug.keystore
Alias: AndroidDebugKey
MD5: B7:BA:15:3A:B7:E3:20:0A:5D:FE:9A:8C:21:6B:46:79
SHA1: 5D:D7:6C:1E:55:2E:20:59:15:23:81:43:F2:4D:BF:86:C7:E7:DF:2D
SHA-256: B2:A0:3A:51:2E:79:58:00:7B:C3:5A:84:F3:3B:C9:C0:75:08:94:F2:73:7C:33:6D:C6:D2:74:16:15:42:B8:BE
Valid until: Friday, June 6, 2053
----------
Variant: release
Config: null
Store: null
Alias: null
----------
Variant: debugAndroidTest
Config: debug
Store: /Users/netcanis/.android/debug.keystore
Alias: AndroidDebugKey
MD5: B7:BA:15:3A:B7:E3:20:0A:5D:FE:9A:8C:21:6B:46:79
SHA1: 5D:D7:6C:1E:55:2E:20:59:15:23:81:43:F2:4D:BF:86:C7:E7:DF:2D
SHA-256: B2:A0:3A:51:2E:79:58:00:7B:C3:5A:84:F3:3B:C9:C0:75:08:94:F2:73:7C:33:6D:C6:D2:74:16:15:42:B8:BE
Valid until: Friday, June 6, 2053
----------

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

Build Analyzer results available
2:45:53 PM: Execution finished 'signingReport'.

 

 

 

 

반응형
블로그 이미지

SKY STORY

,
반응형

Android Studio 앱서명 설정

Android Studio 열기: 프로젝트를 열고, 메뉴 바에서 Build → Generate Signed Bundle / APK...를 클릭.

 

Signed Bundle or APK 선택:

  • Android App Bundle(권장) 또는 APK 중 하나를 선택한다. Google Play 배포 시에는 App Bundle을 선택하는 것이 좋다.
  • APK 수동으로 배포할 경우에는 APK 선택할 있다.

 

키스토어 설정 화면:

  • **Create new...**을 클릭하여 새 키스토어 파일을 생성.

 

키스토어 파일 경로 설정:

  • /app폴더 아래 keystore폴더 생성후 읽기/쓰기 권한 설정)
  • Key store path: 키스토어 파일을 저장할 위치 지정.
    ex) /Users/netcanis/projects4/TestWebview/app/keystore/testwebview-release-key.jks
  • Password : keystone 비번입력.
  • Alias :  alias별칭을 입력. ex) testwebview-release-key-alias
  • Password : alias 비번 입력.

사용자 정보 입력:

  • First and Last Name: 개발자 이름을 입력.
  • Organization Unit: 부서 또는 팀 이름을 입력. (예: Engineering)
  • Organization: 회사 이름을 입력.
  • City or Locality: 도시 이름을 입력.
  • State or Province: 주 또는 도 이름을 입력.
  • Country Code (XX):  자리 국가 코드를 입력. (예: KR)

 

Release 선택하고 Create 버튼 클릭

 

생성된 keystore 파일 확인

 

 


 

 

서명된 APK파일 생성

Android Studio 열기: 프로젝트를 열고, 메뉴 바에서 Build → Generate Signed Bundle / APK... 클릭

 

APK 선택

 

keystore 비밀번호 Key alias 비밀번호를 입력

 

‘Remember passwords’ 체크하고 ‘Next’버튼 클릭

 

Release 선택하고 Create 버튼 클릭

 

생성된 APK파일 확인

 

 

 

반응형
블로그 이미지

SKY STORY

,
반응형

Android Gradle Plugin (AGP) 8.0 이상에서는 여러 가지 변화와 최적화가 이루어졌다. 이를 통해 성능 개선과 더불어 최신 Android SDK 및 Gradle 기능들을 더 잘 지원하게 되었다. Target SDK 34와 호환되며, 최적화되어 있다. Jetpack 및 라이브러리 호환성이 뛰어나며, 최신 Gradle 버전과 통합을 통해 Build 성능이 최적화 되었다. 아래는 AGP 8.0 이상에서 주목해야 할 주요 변경 사항들을 정리해 보았다.

 

1. compileSdkVersion  targetSdkVersion 변경

  • 이전: compileSdkVersion과 targetSdkVersion을 사용하여 SDK 버전을 설정.
  • AGP 8.0 이상: compileSdk와 targetSdk로 변경되었다.
android {
    compileSdk = 34
    targetSdk = 34 
}

 

2. minSdkVersion 변경

  • 이전: minSdkVersion을 사용하여 최소 SDK 버전을 설정.
  • AGP 8.0 이상: minSdk로 변경되었다.
android {
    minSdk = 21
}

 

3. buildToolsVersion 자동 관리

  • 이전: buildToolsVersion을 명시적으로 설정.
  • AGP 8.0 이상: Gradle이 자동으로 적절한 buildTools 버전을 선택하므로 buildToolsVersion을 삭제해도 된다.

 

4. tasks.register 방식 사용 권장

  • 이전: 태스크를 정의할 때 task를 사용.
  • AGP 8.0 이상: 'tasks.register' 를 사용하는 것이 권장됨. 이는 Gradle의 lazy configuration 방식을 따르기 때문에 빌드 성능이 향상된다.
tasks.register('clean', Delete) {
    delete rootProject.buildDir
}

 

5. lintOptions에서 lint로 변경

  • 이전: lintOptions 블록을 사용하여 린트 관련 설정을 구성.
  • AGP 8.0 이상: lint 블록으로 변경되었다.
android {
    lint {
    	checkDependencies true
    }
}

 

6. Kotlin과 Java 플러그인 적용

  • 이전: apply plugin 방식으로 플러그인을 적용.
  • AGP 8.0 이상: plugins {} 블록을 사용하는 것이 권장됨. apply plugin 방식도 여전히 작동하지만, 최신 방식으로는 plugins {} 블록을 사용하는 것이 더 명확하고 관리하기 쉽다.
plugins {
    id 'com.android.application'
    id 'kotlin-android' 
}

 

7. annotationProcessor 대신 kapt 사용

  • 이전: annotationProcessor를 사용하여 Annotations 프로세싱.
  • AGP 8.0 이상: Kotlin 프로젝트에서는 kapt를 사용하는 것이 권장된다.
dependencies { 
    kapt 'androidx.lifecycle:lifecycle-compiler:2.3.1' 
}

 

8. compile 의존성 구성 제거

  • 이전: compile 키워드로 의존성을 선언.
  • AGP 7.0 이상: compile은 더 이상 사용되지 않고 implementation, api, 'compileOnly' 로 대체되었다.
dependencies { 
    implementation "androidx.core:core-ktx:1.6.0" 
}

 

9. Java 8+ 기능 사용 권장

  • 이전: 프로젝트에서 Java 8 이상의 기능을 사용할 때 명시적으로 설정해야 했다.
  • AGP 8.0 이상: Java 8 이상의 기능을 사용하는 것이 기본적으로 지원됨. 추가 설정 없이 최신 Java 기능을 사용할 수 있다.

 

10. Jetpack Compose가 기본적으로 지원됨

  • 이전: Jetpack Compose를 사용하기 위해 여러 설정이 필요했다.
  • AGP 8.0 이상: Jetpack Compose가 기본적으로 지원되며, 설정이 더 간단해졌다.
android { 
    composeOptions { 
        kotlinCompilerExtensionVersion '1.5.1' 
    }
}

 

11. sourceSets 블록의 경로 변경

  • 이전: sourceSets 블록에서 경로 설정이 달랐다.
  • AGP 8.0 이상: src/main/ 경로와 관련된 경로 변경이 있을 수 있으므로, 이에 맞추어 경로를 명확하게 설정해야 한다.

 

 

반응형
블로그 이미지

SKY STORY

,
반응형

안드로이드에서 targetSdkVersion 34로 설정할 때는 몇 가지 주요 변경 사항과 주의 사항이 있습니다. 주요 사항은 다음과 같다.

 

1. 권한 처리 강화

  • 미디어 파일 권한: Android 14에서는 사진, 동영상, 오디오 파일에 대한 권한 요청이 분리되었습니다. READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_AUDIO와 같은 구체적인 권한을 사용해야 합니다.
  • 알림 권한: Android 13(API 33)부터 알림 사용을 위한 권한(POST_NOTIFICATIONS)이 필수적입니다. 사용자가 명시적으로 알림을 허용해야 앱이 알림을 보낼 수 있습니다.
    • 예시:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 100)
}

 

2. 백그라운드 작업 제한 강화

  • 정책 변경: Android 14는 백그라운드 작업에 대한 제약을 더 강화했습니다. 배터리 소모를 줄이기 위해 백그라운드에서 실행되는 작업에 대한 제한이 있으며, 특히 앱이 백그라운드에서 실행 중일 때 작업 스케줄링이 더 어려워졌습니다. 이를 해결하기 위해 JobScheduler 또는 WorkManager를 사용하는 것이 권장됩니다.

 

3. 기본 보안 정책 강화

  • SAF(Storage Access Framework) 적용 강화: 외부 저장소 접근이 더 제한적이며, 앱이 명시적으로 저장소 접근을 요청하지 않으면 사용자가 이를 거부할 수 있습니다. Scoped Storage 적용을 준비해야 하며, 파일 관리는 앱 전용 저장소나 사용자 상호작용을 통해서만 접근해야 합니다.

 

4. 암호화 및 보안

  • 암호화된 네트워크 통신: 명시적 암호화가 더 중요해졌습니다. Android 14는 더 엄격한 네트워크 보안 구성을 요구하며, 특히 비암호화된 HTTP 요청을 차단하거나 이를 명시적으로 허용하지 않으면 기본적으로 차단됩니다. 앱의 network_security_config.xml에서 설정을 확인하고 HTTPS를 권장합니다.

 

5. 개발자 옵션 사용 제한

  • Android 14에서는 디버그 앱이 아닌 경우, 앱 설치 후 개발자 옵션을 통해 설정된 일부 기능이 자동으로 차단될 수 있습니다. 따라서 개발자 전용 빌드 배포 빌드에서 설정 차이를 명확히 하고, 배포 빌드에서는 사용자 경험에 영향을 주지 않도록 주의해야 합니다.

 

6. 백그라운드 위치 접근 제한

  • 위치 서비스 관련 변경 사항으로, 백그라운드에서 위치 정보를 사용하는 경우에 대해 더 엄격한 권한 요구가 추가되었습니다. Android 10(API 29)부터 백그라운드 위치 권한(ACCESS_BACKGROUND_LOCATION)이 따로 분리되었으며, 이를 명시적으로 요청해야 합니다. 이제 위치 권한을 필요로 하는 경우, Foreground 권한 Background 권한을 각각 별도로 요청해야 합니다.

 

7. 동적 코드 로딩 제한

  • Android 14에서는 동적 코드 로딩(dynamic code loading)과 관련된 보안 정책이 더 엄격해졌습니다. APK 내에서 동적으로 코드를 로드하는 방식(예: 외부에서 다운받은 Dex 파일 로딩)을 사용한다면, 보안상의 이유로 Google Play 정책 위반이 될 수 있으므로 주의해야 합니다.

 

8. Non-SDK 인터페이스 사용 제한

  • Android 14에서는 Non-SDK 인터페이스(비공개 API) 사용을 제한하는 정책이 강화되었습니다. 이제 비공개 API에 접근하는 것은 더욱 어렵고, 이에 대한 경고나 오류가 발생할 수 있으므로, 공식 SDK를 사용하는지 점검해야 합니다.

 

 

반응형
블로그 이미지

SKY STORY

,