独学書

Text Date Status
Spring解体新書(バッチ編) 2022/08/08 finished ->コード
Kotlinプログラミング 2019/11/13 finished ->コード
はじめてのAndroidプログラミング 2019/10/12 finished ->コード

環境

  1. Windows 11

    Machine Env / FW Last Updated
    Windows Insider IntelliJ IDEA 2025.2.2 RC 2025/09/14
      - Kotlin 2.2.20 2025/09/13
      - PostgreSQL JDBC Driver 42.7.5 2025/03/08
      Amazon Coretto 22.0.2 2024/11/16
      Android Studio Narwhal 4 2025.1.4 Canary 5 2025/09/12
      - Kotlin 2.2.20 2025/09/13
      - Android SDK Command-line Tools v.19 2025/03/14
      - Android Emulator v.36.2.8 2025/09/12
  2. macOS Sequoia 15.6.1

    Machine Env / FW Last Updated
    macOS Android Studio Narwhal 3 2025.1.3 2025/09/03

ノウハウ

IntelliJ IDEA

  • Latest Version
    • IntelliJ IDEA 2025.2.2 RC (Ultimate Edition)
      Build #IU-252.26199.74, built on September 10, 2025
      Source revision: 64ef3c3fe7d7a
      Runtime version: 21.0.8+1-b1038.71 amd64 (JCEF 122.1.9)
      VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
      Toolkit: sun.awt.windows.WToolkit
      Windows 11.0
      GC: G1 Young Generation, G1 Concurrent GC, G1 Old Generation
      Memory: 2048M
      Cores: 8
      Registry:
        ide.experimental.ui=true
      Non-Bundled Plugins:
        org.jetbrains.completion.full.line (252.26199.74)
        com.intellij.notebooks.core (252.26199.83)
        org.toml.lang (252.26199.83)
        Dart (252.25557.23)
        com.intellij.properties (252.26199.83)
        com.jetbrains.restClient (252.26199.74)
        intellij.jupyter (252.26199.83)
        org.jetbrains.plugins.kotlin.jupyter (252.26199.74)
        Docker (252.26199.84)
        com.intellij.ml.llm (252.26199.74)
        org.jetbrains.android (252.26199.74)
        org.jetbrains.security.package-checker (252.26199.84)
      Kotlin: 252.26199.74-IJ
      
  • History
    • IntelliJ IDEA 2024.3.4.1
      • Update PostgreSQL JDBC Driver
        dependencies {
          ...
          runtimeOnly("org.postgresql:postgresql:42.7.5")
          ...
        }
        
    • IntelliJ IDEA 2024.3.2.2
      • Mockito as agent over jdk 21
        • Support configuring Mockito java agent in java 21+
          var mockitoAgent = configurations.create("mockitoAgent")
          
          dependencies {
            ...
            testImplementation("org.mockito.kotlin:mockito-kotlin:5.4.0")
            mockitoAgent("org.mockito:mockito-core") { isTransitive = false }
          }
          
          tasks {
            test {
              jvmArgs("-javaagent:${mockitoAgent.asPath}")
            }
          }
          
    • IntelliJ IDEA 2024.3
      • Kotlin 2.1.0
        plugins {
          ...
          kotlin("jvm") version "2.1.0"
          ...
        }
        
    • IntelliJ IDEA 2024.2.3
      • Kotlin 2.0.20
        • kotlinOptions Deprecated - https://kotlinlang.org/docs/gradle-compiler-options.html#target-the-jvm
          tasks.named("compileKotlin", org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask::class.java) {
            compilerOptions {
              freeCompilerArgs.add("-Xjsr305=strict")
              apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0)
            }
          }
          
    • IntelliJ IDEA 2024.2.0.2
      • PostgreSQL 16.4
      • Gradle 8.8
    • Kotlin 2.0.0
      • Compose Multiplatform Compose for Desktop
    • Intellij IDEA 2024.1.1
      • Kotlin 1.9.24
    • Intellij IDEA 2023.3.6
      • Kotlin 1.9.23
        plugins {
          ...
          kotlin("jvm") version "1.9.23"
          ...
        }
        
    • Intellij IDEA 2023.3.4
      • Kotlin 1.9.22 Kotlinコンパイラ デバッグ
        • kotlinc.xml
          <?xml version="1.0" encoding="UTF-8"?>
          <project version="4">
            <component name="Kotlin2JvmCompilerArguments">
              <option name="jvmTarget" value="21" />
            </component>
            <component name="KotlinJpsPluginSettings">
              <option name="version" value="1.9.22-release-704" />
            </component>
          </project>
          
    • 履歴

Visual Studio Code

  • 環境は、Android Studioをインストールし、同時にインストールしたkotlinを利用する
    1. PATH環境変数にJDKおよびkotlinのパスを設定する
      • E200HA
        • F:\ProgramData\jdk-12.0.1\bin
        • F:\Program Files\Android\Android Studio\plugins\Kotlin\kotlinc\bin
      • E230MA
        • C:\Users\taish\AppData\Local\Programs\AdoptOpenJDK\bin
        • C:\Program Files\Android\Android Studio\plugins\Kotlin\kotlinc\bin
    2. VSCodeにcode-runnerをインストールし、code-runnerにkotlinの呼び出しを記述する
       "kotlin": "cd $dir && kotlinc-jvm.bat $fileName -include-runtime -d $fileNameWithoutExt.jar && java -jar $fileNameWithoutExt.jar"
      

Spring Boot

  • Spring Boot 3.5.0/Spring Batch 5.2.2/Spring Framework 6.2.7 2025/05/27 updated from 3.4.0
  • History
    • Spring Boot 3.4.0 2024/12/14 updated from 3.3.4
      • Deprecated AssertFile
        他の検証同様、AssertJを使用するように修正
        • 修正前
          AssertFile.assertFileEquals(
            FileSystemResource(_expectedFilePath),
            FileSystemResource(property.outputPath()))
          
        • 修正後
          val actualContent = Files.readAllBytes(File(property.outputPath()).toPath())
          val expectedContent = Files.readAllBytes(File(_expectedFilePath).toPath())
          assertThat(actualContent).isEqualTo(expectedContent)
          
    • Spring Boot 3.2.0/Spring Batch 5.1/Spring Framework 6.1
    • throttleLimitの非推奨
      • TaskExecutor::setThrottleLimit -> TaskExecutor::setConcurrencyLimit
        • 修正前
          @Bean
          fun asyncTaskExecutor(): TaskExecutor {
            return SimpleAsyncTaskExecutor("parallel_")
          }
          
          StepBuilder(...)
            .taskExecutor(asyncTaskExecutor())      // executor
            .throttleLimit(3)                       // 同時実行数
            ...
          
        • 修正後
          @Bean
          fun asyncTaskExecutor(): TaskExecutor {
            val executor = SimpleAsyncTaskExecutor("parallel_")
            executor.concurrencyLimit = 3
            return executor
          }
          
          StepBuilder(...)
            .taskExecutor(asyncTaskExecutor())      // executor
            ...
          
    • Kotlin 2.2.0
      • AnnotationのターゲットをParameterに限定する
        • 修正前
          @Value("\${retry.num}")
          
        • 修正後
          @param:Value($$"${retry.num}")
          

Kotlinプログラミング

Kotlin Multiplatform Mobile

Gemini

  • Gemini 2.5 Gemini 2.5 Pro
  • Gemini 2.0 Vertex AI Studio
  • Gemini 1.5
    • 実行時に制限抵触に関する警告メッセージが出て、結果を取得できない Gemini Warning
  • Gemini 1.0 Pro Gemini API Starter Create API Key Pixel 8 Emulator

Android / Android Studio

  • Windows
    • Android Studio Narwhal 4 Feature Drop | 2025.1.4 Canary 5
      Build #AI-251.27812.49.2514.14085407, built on September 11, 2025
      Runtime version: 21.0.8+-14018985-b1038.68 amd64
      VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
      Toolkit: sun.awt.windows.WToolkit
      Windows 11.0
      Kotlin plugin: K2 mode
      GC: G1 Young Generation, G1 Concurrent GC, G1 Old Generation
      Memory: 2048M
      Cores: 8
      Registry:
        ide.experimental.ui=true
        gradle.phased.sync.enabled=true
        com.android.studio.ml.activeModel=com.android.studio.ml.AidaModel
      Non-Bundled Plugins:
        Dart (251.27812.12)
        io.flutter (87.1)
      
  • macOS
    • Android Studio Narwhal 3 Feature Drop | 2025.1.3
      Build #AI-251.26094.121.2513.14007798, built on August 28, 2025
      Runtime version: 21.0.7+-13880790-b1038.58 aarch64
      VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
      Toolkit: sun.lwawt.macosx.LWCToolkit
      macOS 15.6.1
      Kotlin plugin: K2 mode
      GC: G1 Young Generation, G1 Concurrent GC, G1 Old Generation
      Memory: 2048M
      Cores: 8
      Metal Rendering is ON
      Registry:
        ide.experimental.ui=true
      

      Android Studio Narwhal 2025.1.2

  • 共通
    • HyperVisor利用には、機能の有効化が必要 HyperVisor
    • 開発者向けオプション
    • Android Studioの日本語化
    • Android VersionとAPIの対応
    • Gradle設定
      • Gradleに関する設定は、環境変数GRADLE_USER_HOMEで設定したディレクトリを参照するため、変更したい場合、格納先のディレクトリを設定する
    • Android SDK設定 SDK設定
    • エミュレータのイメージ退避
      1. エミュレータのイメージは、ユーザの.androidディレクトリに格納されるため、移動する
      2. 以下のように、イメージの管理ファイル(.ini)にある格納先を変更する
        path=F:\Program\.android\avd\Nexus_5X_API_28.avd
        
    • Kotlin 2.2.0
      • AnnotationのターゲットをParameterに限定する
        • 修正前
          @Value("\${retry.num}")
          
        • 修正後
          @param:Value($$"${retry.num}")
          
    • Junit 5
  • 対応履歴
    • Android Canary
      • API 36 Canary API Canary Preview
    • Android 16 QPR2 Beta 1(Android Baklava Preview)
      • Android Studio Narwhal Feature Drop 2025.1.4 Canary 2 MyApplication
    • Android 15 (API 35)
    • Narwhal
      • Feature Drop 2025.1.4
        • Canary 5
          • Android Gradle Plugin 9.0.0-alpha04 -> 9.0.0-alpha05
          • Android Emulator 36.2.8
          • Kotlin Plugin Issue
        • Canary 4
          • Android Gradle Plugin 9.0.0-alpha03 -> 9.0.0-alpha04
          • Android Emulator 36.2.7
        • Canary 3
          • Android Gradle Plugin 9.0.0-alpha02 -> 9.0.0-alpha03
          • Kotlin Pluginの記述が不要になった模様(MySchedulerがビルドできないので、以後変更される可能性あり)
            plugins {
              id 'com.android.application'
              // id 'kotlin-android'
            }
            
        • Canary 2
          • Android Emulator 36.2.5
          • Android Gradle Plugin 9.0.0-alpha01 -> 9.0.0-alpha02
        • Canary 1
          • Kotlin 2.2.0 -> 2.2.10
          • Android Emulator 36.2.4
          • Gradle 8.13 -> 9.0
          • Android Gradle Plugin 8.13.0-alpha04 -> 9.0.0-alpha01
      • Feature Drop 2025.1.3
        • Android Gradle Plugin 8.12.2 -> 8.13.0
        • Canary 4
          • Android Gradle Plugin 8.13.0-alpha03 -> 8.13.0-alpha04
        • Canary 3
          • Android Gradle Plugin 8.13.0-alpha02 -> 8.13.0-alpha03
          • Android Emulator 36.2.2 / 36.2.3
        • Canary 2
          • Android Gradle Plugin 8.12.0-alpha09 -> 8.13.0-alpha02
          • Android Emulator 36.2.1
      • Feature Drop 2025.1.2
        • Canary 9
          • Android Gradle Plugin 8.12.0-alpha08 -> 8.12.0-alpha09
        • Canary 8
          • Android Gradle Plugin 8.12.0-alpha07 -> 8.12.0-alpha08
        • Canary 7
          • Android Gradle Plugin 8.12.0-alpha06 -> 8.12.0-alpha07
        • Canary 6
        • Canary 4
          • Android Gradle Plugin 8.12.0-alpha03 -> 8.12.0-alpha04
        • Canary 3
          • Android Gradle Plugin 8.12.0-alpha02 -> 8.12.0-alpha03
        • Canary 2
          • Android Gradle Plugin 8.11.0-alpha10 -> 8.12.0-alpha02
          • Android Emulator 36.1.1
          • Android Emulator HyperVisor Driver 2.2.0
      • 2025.1.1
        • Canary 10
          • Android Gradle Plugin 8.11.0-alpha09 -> 8.11.0-alpha10
        • Canary 9
          • Android Gradle Plugin 8.11.0-alpha08 -> 8.11.0-alpha09
        • Canary 8
          • Android Gradle Plugin 8.11.0-alpha07 -> 8.11.0-alpha08
        • Canary 7 Upgrade_Suggested
          • Gradle 8.11.1 -> 8.13
          • Android Gradle Plugin 8.10.0-rc02 -> 8.11.0-alpha07
    • Meerkat
      • Meerkat Feature Drop RC 2
        • Android Gradle Plugin 8.10.0-rc01 -> 8.10.0-rc02
      • Meerkat Feature Drop RC 1
        • Android Gradle Plugin 8.9.0 -> 8.9.1 -> 8.10.0-rc01
        • Upgrade Suggested Beta 1からRC 1に更新したにもかかわらず、Beta 1へのアップグレードを提案される! Upgrade Suggested
      • Meerkat Feature Drop Canary 8
        • Android Gradle Plugin 8.8.2 -> 8.9.0
      • Meerkat Feature Drop Canary 7
        • Android Gradle Plugin 8.8.1 -> 8.8.2
      • Meerkat Feature Drop Canary 5
        • Android Gradle Plugin 8.8.0 -> 8.8.1
      • Meerkat Feature Drop Canary 2
        • Kotlin 2.1.0 -> 2.1.10
        • Update SDK SDKUpdate
      • Meerkat Canary 9 対応
        • Android Gradle Plugin 8.7.3 -> 8.8.0
      • Meerkat Canary 4 対応
        • Kotlin 2.1.0
        • Gradle 8.10 -> 8.11.1
        • Android Gradle Plugin 8.7.2 -> 8.7.3
        • Android Emulator v35.4.3
      • Meerkat Canary 3 対応
        • Android Baklava (=Android 16) Preview
        • Android Emulator v35.4.2
    • Ladybug 対応
      • 2024.2.1 Patch 2 対応
        • Android Gradle Plugin 8.7.1 -> 8.7.2
        • CompileSdk 34 -> 35
          • core-ktx および core 1.15.0 は、バージョン35以上のSDKでビルドする必要あり
      • 2024.2.1 Patch 1 対応
        • Android Gradle Plugin 8.7.0 -> 8.7.1
        • Kotlin Gradle Plugin 2.0.20 -> 2.0.21
      • 2024.2.1 対応
        • Android Gradle Plugin 8.6.1 -> 8.7.0
        • Gradle 8.8 -> 8.9 -> 8.10
    • Koala 対応
      • Feature Drop 2024.1.2 Patch 1 対応
        • Android Gradle Plugin 8.6.0 -> 8.6.1
      • Feature Drop 2024.1.2 対応
        • Android Gradle Plugin 8.5.2 -> 8.6.0
        • Kotlin Gradle Plugin 2.0.10 -> 2.0.20
          • Plugin更新には、Gradle 8.8 以上への更新必須
      • 2024.1.1 Patch 2 対応
        • Android Gradle Plugin 8.5.1 -> 8.5.2
        • Kotlin Gradle Plugin 2.0 -> 2.0.10
      • Gradle ビルドエラー
        • Gradle 8.8
          • Gradle 8.7 で metadata.binが見つからないエラーでビルドできないケースがあり、V8.8に更新することで解消
      • 2024.1.1 Patch 1 対応
        • Android Gradle Plugin 8.5.0 -> 8.5.1
      • 2024.1.1 対応
        • Android Gradle Plugin 8.4.1 -> 8.5.0
          • Gradle 8.7
        • Android Gradle Plugin 8.5.0 rc01 -> 8.5.0
        • Android API 35
        • Android SDK Built-Tools 35.0.0
      • RC 1 対応
      • Beta 2 対応
        • Android Gradle Plugin 8.5.0 beta01 -> 8.5.0 beta02
      • Beta 1 対応
        • Android Gradle Plugin 8.5.0 alpha05 -> 8.5.0 beta01
        • Gradle 8.6 -> 8.7
          Update Assistant
      • Canary 5 対応
        • Android Gradle Plugin 8.5.0 alpha04 -> 8.5.0 alpha05
    • Jellyfish 対応
      Android Studio Jellyfish
      • Android Gradle Plugin 8.3.2 -> 8.4.0
        • Gradle 8.6
    • Iguana Patch 2 対応
      • Android Gradle Plugin 8.3.1 -> 8.3.2
      • junit4が廃要素になったための変更(junit-ktx)
        dependencies {
            ...
            implementation 'androidx.test.ext:junit-ktx:1.1.5'
            testImplementation 'junit:junit:4.13.2'
            ...
        }
        
    • Iguana Patch 1 対応
      • Android Gradle Plugin 8.3.0 -> 8.3.1
    • Iguana 対応
      • Android Gradle Plugin 8.2.2 -> 8.3.0
    • Hedgehog Patch 1 対応
      • Android Gradle Plugin 8.2 -> 8.2.1
        • Gradle 8.4
      • Kotlin Gradle Plugin 1.9.21 -> 1.9.22
        • Java 21 設定/ターゲットJVMバージョン
    • Hedgehog 対応
      • Android Gradle Plugin 8.2
        • Gradle 8.4
    • Giraffe 対応
      • Android Gradle Plugin 8.1
    • Flamingo 対応
      • Gradle 8.0 and Android Gradle Plugin 8.0
        • AGPが使用するJVMバージョンが17になるため、プロジェクトのJVMバージョンを変更する必要あり プロジェクトのJVMバージョンは、Project Structureで設定する Project Structure 設定によって出力される build.gradle は、下記の通り
          compileOptions {
              sourceCompatibility JavaVersion.VERSION_17
              targetCompatibility JavaVersion.VERSION_17
          }
          
        • MySchedulerのみGradle 7.xで据え置き
          • Realm-AndroidがGradle 8.0で廃止になるTransform APIを使用しているため
      • Kotlin 1.8.20
    • Electric Eel 対応
      • Gradle 7.5 and Android Gradle Plugin 7.4.0
      • Kotlin 1.8
    • Dolphin 対応
      • Gradle 7.4.2 and Android Gradle Plugin 7.3.0
      • アップデート対応 @2022/09/25
        • 起動時例外発生 ``` 内部エラーが発生しました。Please refer to https://code.google.com/p/android/issues

          com.intellij.ide.plugins.StartupAbortedException: UI initialization failed at com.intellij.idea.StartupUtil.lambda$start$15(StartupUtil.java:268) at java.base/java.util.concurrent.CompletableFuture.uniExceptionally(CompletableFuture.java:986) at java.base/java.util.concurrent.CompletableFuture$UniExceptionally.tryFire(CompletableFuture.java:970) at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506) at java.base/java.util.concurrent.CompletableFuture.postFire(CompletableFuture.java:610) at java.base/java.util.concurrent.CompletableFuture$UniRun.tryFire(CompletableFuture.java:791) at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478) at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:776) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:727) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721) at java.base/java.security.AccessController.doPrivileged(Native Method) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85) at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:746) at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203) at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124) at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90) Caused by: java.util.concurrent.CompletionException: java.lang.VerifyError: Expecting a stack map frame Exception Details: Location: com/intellij/openapi/util/text/StringUtil.pluralize(Ljava/lang/String;I)Ljava/lang/String; @7: nop Reason: Expected stackmap frame at this location. Bytecode: 0000000: 2ab0 0000 a7ff fe00 bf00 00a7 fffe
          Stackmap Table: same_frame(@2) same_frame(@9)

          at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
          at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
          at java.base/java.util.concurrent.CompletableFuture$UniRun.tryFire(CompletableFuture.java:787)
          ... 14 more Caused by: java.lang.VerifyError: Expecting a stack map frame Exception Details: Location:
          com/intellij/openapi/util/text/StringUtil.pluralize(Ljava/lang/String;I)Ljava/lang/String; @7: nop Reason:
          Expected stackmap frame at this location. Bytecode:
          0000000: 2ab0 0000 a7ff fe00 bf00 00a7 fffe      Stackmap Table:
          same_frame(@2)
          same_frame(@9)
          
          at com.intellij.openapi.util.SystemInfo.isOsVersionAtLeast(SystemInfo.java:51)
          at com.intellij.openapi.util.SystemInfo.<clinit>(SystemInfo.java:54)
          at com.intellij.ui.JreHiDpiUtil.isJreHiDPIEnabled(JreHiDpiUtil.java:58)
          at com.intellij.ui.scale.JBUIScale.getOrComputeUserScaleFactor(JBUIScale.java:190)
          at com.intellij.ui.scale.JBUIScale.scale(JBUIScale.java:314)
          at com.intellij.ui.scale.UserScaleContext.<init>(UserScaleContext.java:26)
          at com.intellij.util.ui.JBUI$BaseScaleContext.<init>(JBUI.java:1408)
          at com.intellij.ui.scale.ScaleContext.<init>(ScaleContext.java:32)
          at com.intellij.ui.scale.ScaleContext.create(ScaleContext.java:108)
          at com.intellij.ui.scale.ScaleContextSupport.<init>(ScaleContextSupport.java:11)
          at com.intellij.openapi.util.IconLoader$CachedImageIcon.<init>(IconLoader.java:702)
          at com.intellij.ui.CoreIconManager$IconWithToolTipImpl.<init>(CoreIconManager.java:91)
          at com.intellij.ui.CoreIconManager.loadRasterizedIcon(CoreIconManager.java:61)
          at com.intellij.icons.AllIcons.load(AllIcons.java:17)
          at com.intellij.icons.AllIcons.<clinit>(AllIcons.java:670)
          at com.intellij.icons.AllIcons$Nodes.<clinit>(AllIcons.java:719)
          at com.intellij.ide.ui.laf.IdeaLaf.initIdeaDefaults(IdeaLaf.java:74)
          at com.intellij.ide.ui.laf.IdeaLaf.initComponentDefaults(IdeaLaf.java:35)
          at java.desktop/javax.swing.plaf.basic.BasicLookAndFeel.getDefaults(BasicLookAndFeel.java:150)
          at java.desktop/javax.swing.plaf.metal.MetalLookAndFeel.getDefaults(MetalLookAndFeel.java:1560)
          at com.intellij.idea.StartupUtil.lambda$scheduleInitUi$21(StartupUtil.java:476)
          at com.intellij.ui.scale.JBUIScale.computeSystemFontData(JBUIScale.java:69)
          at com.intellij.ui.scale.JBUIScale.getSystemFontData(JBUIScale.java:360)
          at com.intellij.idea.StartupUtil.lambda$scheduleInitUi$22(StartupUtil.java:474)
          at java.base/java.util.concurrent.CompletableFuture$UniRun.tryFire(CompletableFuture.java:783)
          ... 14 more
          

        Your JRE: 11.0.13+0-b1751.21-8125866 amd64 (JetBrains s.r.o.) D:\Program Files\Android\Android Studio\jre ```

    • Chipmunk 対応
      • Gradle 7.3.3 and Android Gradle Plugin 7.2.0
    • Arctic Fox 対応として吸収すべき課題 @2021/11/23 updated!
      • Android Studio Arctic Fox 2020.3.1 (based IntelliJ 2020.3) Wrote first at 2021.8.20
        • 環境刷新
          • Kotlin 1.6.0 Update at 2021.11.23
            Build.gradleでKotlinバージョンを変更
          • Gradle V7.0
            Project Referenceで使用するGradleのバージョンを変更
            • Android Gradle Plugin Version: 7.0.3 Update at 2021.11.23
            • Gradle Version: 7.0.2
          • JDK 11
            Android Studioに含まれるJDKがJDK11に変更になり、同じJDKをGradle実行にも使用するため、Gradle SettingでAndroid Studioに含まれるJDKを使用するように変更する

          build.gradle(project) Update at 2021.8.20

          buildscript {
              ext.kotlin_version = '1.5.21'
              repositories {
                  google()
                  mavenCentral()
              }
              dependencies {
                  classpath "com.android.tools.build:gradle:7.0.1"
                  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
              }
          }
          
    • Android 12 / 非互換として吸収すべき課題
      • SDKバージョン範囲の見直し Update at 2021.8.20
        • ビルド時に下記メッセージが出るため、SDKバージョンを26以上にする
          • “Invoke-customs are only supported starting with Android O (–min-api 26)”
          • “Default interface methods are only supported starting with Android N (–min-api 24)
          • “Static interface methods are only supported starting with Android N (–min-api 24)
      • マニフェスト Update at 2021.8.20
        • アクティビティのエクスポート
          • manifestでintent-filterを使っている場合、android:exportedをtrueにする必要あり
            <activity android:name=".MainActivity" android:exported="true">
                <intent-filter>
                ...
                </intent-filter>
            </activity>
            
      • ビューバインディング
        • Android 3.5までの実装を変更する
        • ビューバインディングの使用を宣言する
          • build.gradle(app)
            android {
                viewBinding {
                    enabled = true
                }
            }
            
        • ビューバインディング使用により、不要になるkotlin-android-extensionsプラグインを削除する(削除すると、下記のようになる)
          plugins {
              id 'com.android.application'
              id 'kotlin-android'
          }
          
        • 要素に応じた修正を行う
          1. アクティビティの場合
            • アクティビティにバインディングクラスのインスタンス変数を追加する
              class MainActivity : AppCompatActivity() {
                  private lateinit var binding: ActivityMainBinding
                  ...
              }
              
            • インポートする名前空間を変更する(上記の変数を追加するとIDEからメッセージが出る)
              import kotlinx.android.synthetic.main.activity_main.*
              
              import com.example.helloandroid.databinding.ActivityMainBinding
              
            • 初期化時にバインディングクラスのインスタンス変数を初期化し、ルートビューへの参照を取得する
              override fun onCreate(savedInstanceState: Bundle?) {
                  super.onCreate(savedInstanceState)
                  binding = ActivityMainBinding.inflate(layoutInflater)
                  val view = binding.root
                  setContentView(view)
                  ...
              }
              
            • アクティビティ内の項目へのアクセスを変更する
              override fun onCreate(savedInstanceState: Bundle?) {
                  ...
                  tapHere.setOnClickListener {
                      textView.text = "ボタンがタップされました"
                  }
              }
              

              override fun onCreate(savedInstanceState: Bundle?) {
                  ...
                  binding.tapHere.setOnClickListener {
                      binding.textView.text = "ボタンがタップされました"
                  }
              }
              
          2. フラグメントの場合
            • フラグメントにバインディングクラスのインスタンス変数を追加する
              private var _binding: ResultProfileBinding? = null
              // This property is only valid between onCreateView and
              // onDestroyView.
              private val binding get() = _binding!!
              
            • フラグメントの初期化時にバインディングクラスのインスタンス変数を初期化し、ルートビューへの参照を取得する
              override fun onCreateView(
                  inflater: LayoutInflater,
                  container: ViewGroup?,
                  savedInstanceState: Bundle?
              ): View {
                  _binding = ResultProfileBinding.inflate(inflater, container, false)
                  val view = binding.root
                  return view
              }
              
            • フラグメントの破棄時にバインディングクラスのインスタンス変数を解放する
              override fun onDestroyView() {
                  super.onDestroyView()
                  _binding = null
              }
              
            • フラグメント内の項目への参照を変更する
              name.text = viewModel.name
              button.setOnClickListener { viewModel.userClicked() }
              

              binding.name.text = viewModel.name
              binding.button.setOnClickListener { viewModel.userClicked() }
              
            • フラグメントをアクティビティ内で機能させる Update at 2021.8.21
              • フラグメント生成
                val fragment = TitleFragment()
                fragment.setTitle("フラグメント動物図鑑")
                
              • フラグメントマネージャーの取得
                val fragmentManeger = this.supportFragmentManager
                
              • トランザクション実行
                • 下記例では、トランザクション開始~フラグメント追加~トランザクション終了(コミット)を一連のブロック(commitブロック)で実行する
                  supportFragmentManager.commit {
                      replace(R.id.fragmentContainerView, fragment)
                      addToBackStack("name") // name can be null
                  }
                  
      • 共有プリファレンス
        • build.gradle(app)に以下を追加する
          dependencies {
              ...
              implemetation 'androidx.preference:preference-ktx:1.1.0'
              ...
          }
          
        • FragmentStatePagerAdapterの置換 Update at 2021.8.22
          • アダプタの継承クラスのコンストラクタの継承元をFragmentStateAdapterに置き換える
            • https://developer.android.com/reference/androidx/fragment/app/FragmentStatePagerAdapter
              class MyAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm){
                  ...
                  override fun getCount(): Int {
                      ...
                  }
              }
              
            • https://developer.android.com/reference/androidx/viewpager2/adapter/FragmentStateAdapter
              class MyAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa){
                  ...
                  override fun getItemCount(): Int {
                      ...
                  }
              }
              
          • アクティビティでのアダプタへのアクセスを変更する
            binding.pager.adapter = MyAdapter(supportFragmentManager)
            

            binding.pager.adapter = MyAdapter(this)
            
        • タイマ処理におけるハンドラ周りを見直す Update at 2021.8.22
          • ハンドラ生成の見直し
            var handler = Handler()
            

            Looper.prepare()
            val handler = Looper.myLooper()?.let { Handler(it, null) }
            
          • ハンドラ利用の見直し(セーフアクセス修飾子)
            timer(period = 5000){
                handler.post {
                    ...
                }
            }
            

            timer(period = 5000){
                handler?.post {
                    ...
                }
            }
            
        • フラグメント作成後の処理手続きの変更 Update at 2021.8.22
          • onActivityCreatedメソッドでの実行は非推奨となったため、フラグメントのビューをタッチするコードは、onActivityCreatedメソッドの実行直前に呼び出されるonViewCreatedメソッドでの実行に変更。その他の初期化コードは onCreate() 内での実行に変更。
            override fun onActivityCreated(...){
                ...
            }
            

            override fun onViewCreated(...){
                ...
            }
            
        • SoundPool(Lollipopで非推奨) Update at 2021.8.25
          soundPool = SoundPool.Builder()
                      .setMaxStreams(1)
                      .setAudioAttributes(audioAttributes)
                      .build()
          
        • PendingIntent.getBroadcast Update at 2021.8.25
          • lintでMuttable Flagを指定されていないと指摘されるため、指定するように変更
        • SimpleDateFormat Update at 2021.8.25
          • lintでロケールを指定するよう指摘されるため、ロケールを指定するように変更
        • Realm 環境の更新 Update at 2021.8.28
          • build.gradle(project)
            buildscript {
              repositories {
                google()
                mavenCentral()
                jcenter()
              }
              dependencies {
                classpath "com.android.tools.build:gradle:7.0.1"
                classpath "io.realm:realm-gradle-plugin:10.7.0"
              }
            }
            allprojects {
              repositories {
                google()
                mavenCentral()
                jcenter()
              }
              dependencies {
              }
            }
            task clean(type: Delete) {
              delete rootProject.buildDir
            }
            
          • build.gradle(app)
            plugins {
              id 'kotlin-kapt'
              id 'realm-android'
            }
            ...
            realm {
              syncEnabled = true
            }
            

Androidプログラミング

  • プロジェクト残課題状況

    AP Status Issue
    AnimalBook Fixed 起動時にNullPointerExceptionが発生し、起動できない
    MyCountdownTimer No Problem リセット時に3:00に表示が戻らない
    リセット後、すぐにカウントダウンするため、2:59になることで問題なし
    MyScheduler Fixed 入力したスケジュールが保存できない
    MySlideshow Fixed 起動時にNotImplementedErrorで起動できない
    -> Arctic Fox対応でビューバインディングを導入した際のコード移行漏れ
  • 入力したスケジュールが保存できないの主な修正内容:

    1. 古いライブラリへの依存の解消

      • 問題点:

        ビルドエラーの根本的な原因は、現在は利用できなくなった古いRealmデータベースのアダプターライブラリ (RealmRecyclerViewAdapter) を使おうとしていたことでした。

      • 解決策:

        この古いライブラリの使用をやめ、現在のAndroid開発で標準的に使われる ListAdapter という仕組みに置き換えました。

    2. ScheduleAdapterの近代化

      ListAdapter を使うように変更しました。これにより、リストの項目が追加・変更・削除された際に、効率的かつスムーズに画面を更新できるようになります。 各スケジュール項目が一意のIDを持つことをRecyclerViewに伝え(setHasStableIds(true))、動作を安定させました。

    3. ScheduleListFragment.kt の安定化

      • 問題点:

        修正の過程で、データベースの変更通知と画面のライフサイクルのタイミングが競合し、クラッシュが発生していました。

      • 解決策:

        データベースの変更を監視する RealmChangeListener の実装方法を修正しました。具体的には、特定のデータセット(スケジュール一覧)のみを監視し、さらに画面が存在するときだけUIを更新するようにチェック処理を追加して、クラッシュを防ぎました。

    4. MainActivity.kt のクラッシュ修正

      • 問題点:

        アプリ起動時に、画面遷移を管理する NavController を不適切なタイミングで取得しようとしていたため、クラッシュが発生していました。

      • 解決策:

        Androidが推奨する安全な方法で NavController を取得するように修正し、起動時のクラッシュを解消しました。