Android 動態更改應用程式圖標 App Icon

一、問題描述 最近使用 Todoist 做任務管理時發現,App 內有提供自選圖標的功能,也就是動態更換 App 的 Launcher Icon。 Step 0 Step 1 Step 2 Step 3 按下按鈕啟用自選圖標功能。 原本 App 預設是紅色的 App Icon。 在 App 內設定指定的 Icon 後。 Launcher 上的 Todoist Icon 就真的換剛才所選的 App Icon 了! 另外一個 App DuckDuckGo 也有一樣的功能。不過操作流程上不太一樣。DuckDuckGo 不需要特別啟用自選圖標,但在每次更換 Icon 時,App 都會在設定完成後自動關閉,使用者必須自動重啟 App 才能繼續使用。 🚩 兩者使用體驗差異整理: Todoist: 首次使用必須啟用功能。 啟用功能後 App 會自行關閉,需要使用者自行重開 App。 重開後就可以使用自選圖標的功能,而且往後的更換行為 App 都不會再自動關閉。 DuckDuckGo: 不須特別啟用功能。 每次更換圖標都會自動關閉 App,使用者要自己重開。 ==如果想直接看怎麼做,可以跳到 三、解決方案。== 二、研究歷程 2-1 問題釐清 搜尋幾個關鍵字其實滿快就找到相關的解法了,基本上分成使用 AndroidManifest.xml 的 activity-alias 更換 App 進入點的參數,或是使用 App Shortcuts。 ...

November 23, 2023 · 7 min · 1349 words · Daniel Huang

Android UI 日期時間選擇 DatePicker

簡介 Android 原生提供的日期時間選擇 UI。 官方推薦使用 Material Design 的 API MaterialDatePicker (Dialog) 日期區間選擇 DateRangePicker Kotlin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import com.google.android.material.datepicker.MaterialDatePicker val datePicker = MaterialDatePicker.Builder.dateRangePicker() .setTitleText("選擇調查日期區間") .setSelection(Pair(startPeriod, endPeriod)) .build() datePicker.show(childFragmentManager, TAG_DATE_RANGE_PICKER) datePicker.addOnPositiveButtonClickListener { startPeriod = it.first endPeriod = it.second setTvStartAndEnd() } Java 1 2 3 4 5 6 7 8 9 10 11 12 import androidx.core.util.Pair; import com.google.android.material.datepicker.MaterialDatePicker; MaterialDatePicker<Pair<Long, Long>> dateRangePicker = MaterialDatePicker.Builder.dateRangePicker() .setTitleText(R.string.date_filter) .setSelection(Pair.create(startTime, endTime)) .build(); dateRangePicker.addOnPositiveButtonClickListener(selection -> mMainViewModel.setFilterPeriod(selection)); dateRangePicker.show(getChildFragmentManager(), TAG_DATE_PICKER); 使用 MaterialDatePicker.Builder.dateRangePicker 建立,可設定 UI 上的標題 (setTitleText()) 與預選的日期區間 (setSelection)。 dateRangePicker 是泛型 Pair<Long, Long>,Pair 中儲存的是開始日期與結束日期的 UNIX時間(milliseconds)。 ...

October 31, 2023 · 2 min · 425 words · Daniel Huang

Android BuildConfig 消失了?

問題 最近開新專案的時候,發現寫 BuildConfig 都沒有出現 prompt,後來才發現是新的專案要另外開設定。 什麼是 BuildConfig BuildConfig 是 Gradle 在編譯時期自動建立的類別,裡面包含目前建製版本的相關資訊,開發者也可以自行加入客製化的欄位資料。 為什麼會有這個問題? 根據 解決 Android Studio 中的 BuildConfig 找不到問題 與 Fixing the “Build Type contains custom BuildConfig fields, but the feature is disabled” error w/ buildConfigField的資訊,可以知道 Gradle 8.0.0 後的版本,預設 BuildConfig 是關閉的。 解法 在 module 的 build.gradle 中新增以下程式碼,在重新 build project 即可。 1 2 3 4 5 6 7 8 9 10 // (app) build.gradle android { // 略... buildFeatures { // 開啟 buildConfig true } }

June 30, 2023 · 1 min · 75 words · Daniel Huang

Android 定位結果的 `Location.getTime()` 不一定是衛星時間

Photo by SpaceX on Unsplash 前言 最近的專案需要取定位的時間,並用該時間判斷使用者是否有在指定時間完成任務,而業主就提出希望以定位所取得的時間做為判斷依據。 然後,就發現事情沒有想像中的那麼單純。 原來目前在 Android 的定位結果中所取得的時間,只有在定位來源為純 GPS 的情況下才會是衛星所回傳的時間。 來看看究竟是怎麼一回事吧… 先認識 Location 型別 不論是使用 Android 官方推薦的 Fused Location Provider 或是 LocationManager ,定位結果所回傳的型別都是 Location。這個型別除了基本的經緯度與海拔等資訊,其中也包含定位的時間。 通常開發上指的定位時間,我們會使用 Location.getTime() 取得 Unix epoch time,再將這串數字轉成人類可閱讀的時間格式。 Unix epoch time:從 UTC 1970 年 1 月 1 日 0 時 0 分 0 秒起至現在的總秒數,不考慮閏秒。 – Wikipedia Location.getTime() 會跟定位來源有關 從 Android Doc: Location.getTime() 的說明會發現,不同的定位結果所取得的時間來源不見得相同。 ...

May 27, 2023 · 2 min · 257 words · Daniel Huang

比 Android 原生更方便的 Log 工具: Timber

本文同步發表在 HackMD & Medium Timber 是什麼 Timber 是一個以 Android Log 為基底所開發的 Logger Library,由 Jake Wharton 大神所開發。 Timber 為了解決什麼問題 1. 開發時可以留著,但發佈版本需要移除 Log 1 2 3 4 // 你可能很常看到類似這樣的寫法... if (BuildConfig.DEBUG) { Log.d(TAG, "Hello World!") } 一般來說在開發上,我們習慣使用 Android 的 Log class 來印出所需的資訊。但是當今天開發到一定的階段,程式必須發布上線時,為了資訊安全等需求,需要將這些 Log 給全部註解或移除,又或是加上 buildFlavor 或 buildType 判斷,這一切實在是太麻煩了… 2. 每次在新的類別中使用 Log 就要建一個該類別的 TAG String 1 2 3 4 5 val TAG: String = Hello::class.java.simple if (BuildConfig.DEBUG) { Log.d(TAG, "Hello World!") } 同步發表在 HackMD & Medium Timber 怎麼使用 1. Dependency 在 build.gradle 中加入以下的 Dependency。 ...

May 27, 2023 · 1 min · 170 words · Daniel Huang