Skip to content

アプリ再起動時にFLPサブスクリプションの蓄積を防止してAndroid 16のバックグラウンド位置更新を改善#5423

Merged
TinyKitten merged 2 commits intodevfrom
claude/fix-android-location-updates-65U9y
Feb 22, 2026
Merged

アプリ再起動時にFLPサブスクリプションの蓄積を防止してAndroid 16のバックグラウンド位置更新を改善#5423
TinyKitten merged 2 commits intodevfrom
claude/fix-android-location-updates-65U9y

Conversation

@TinyKitten
Copy link
Member

@TinyKitten TinyKitten commented Feb 22, 2026

https://claude.ai/code/session_01Kg2KPdwZq34z3uo8L8vmdX

Summary by CodeRabbit

  • バグ修正

    • バックグラウンド位置情報更新開始前に既存の位置情報更新を検出して停止する事前クリーンアップを追加。古いタスクの干渉を抑え、追跡の信頼性を向上。クリーンアップ失敗時は警告を記録して起動を継続します。
  • テスト

    • 古いタスクの停止・未検出時の挙動、クリーンアップ失敗時の警告、及び非同期順序(開始前チェックの待機)を検証するテストを追加・強化しました。

@github-actions github-actions bot added the react label Feb 22, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 22, 2026

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Walkthrough

背景での位置情報更新を開始する前に、同名の既存タスクが起動していないか Location.hasStartedLocationUpdatesAsync を確認し、存在すれば Location.stopLocationUpdatesAsync で停止するプリクリーンアップを追加。クリーンアップ失敗時は警告を出して起動は継続。関連テストを追加/拡張。

Changes

Cohort / File(s) Summary
背景位置情報クリーンアップロジック
src/hooks/useStartBackgroundLocationUpdates.ts
開始処理の先頭で Location.hasStartedLocationUpdatesAsync(LOCATION_TASK_NAME) を呼び、既存タスクがあれば Location.stopLocationUpdatesAsync(LOCATION_TASK_NAME) で停止するプリクリーンアップを追加。停止失敗は console.warn で記録し、起動処理は継続。
クリーンアップ動作の検証テスト
src/hooks/useStartBackgroundLocationUpdates.test.tsx
mockHasStartedLocationUpdatesAsync を導入して既存タスク有無・停止失敗・順序保証・キャンセル経路を検証するテストを追加/拡張。process.nextTick 等で非同期経路の同期を強化し、hasStartedLocationUpdatesAsync の解決を待つよう修正。

Sequence Diagram(s)

sequenceDiagram
    participant Hook as useStartBackgroundLocationUpdates
    participant LocationAPI as Location API
    participant Logger as Logger

    Hook->>LocationAPI: hasStartedLocationUpdatesAsync(LOCATION_TASK_NAME)
    alt ステールタスクあり
        LocationAPI-->>Hook: true
        Hook->>LocationAPI: stopLocationUpdatesAsync(LOCATION_TASK_NAME)
        LocationAPI-->>Hook: success
    else ステールタスクなし
        LocationAPI-->>Hook: false
    else クリーンアップ失敗
        LocationAPI-->>Hook: error
        Hook->>Logger: warn("stale cleanup failed")
    end

    Hook->>LocationAPI: startLocationUpdatesAsync(LOCATION_TASK_NAME, options)
    LocationAPI-->>Hook: success
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

android

Poem

🐰 古い足跡を確かめて、前を掃くよ。
小さな警告が鳴れば、また跳ねてゆく。
新しい風をうけて、背景を駆ける。
ビートは軽やか、コードは丁寧。
ぴょんと始めよう、位置の旅路へ。

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed プルリクエストのタイトルは、アプリ再起動時のFLPサブスクリプションの蓄積防止とAndroid 16のバックグラウンド位置更新の改善という、変更セットの主要な目的を明確に説明しています。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/fix-android-location-updates-65U9y

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/hooks/useStartBackgroundLocationUpdates.test.tsx (2)

112-128: 呼び出し順序の検証を追加することを検討してください。

このテストはstopLocationUpdatesAsyncstartLocationUpdatesAsyncの両方が呼び出されることを検証していますが、「stopがstartの前に呼ばれる」という順序の検証がありません。

♻️ 呼び出し順序を検証する例
+      const callOrder: string[] = [];
+      mockStopLocationUpdatesAsync.mockImplementation(() => {
+        callOrder.push('stop');
+        return Promise.resolve();
+      });
+      mockStartLocationUpdatesAsync.mockImplementation(() => {
+        callOrder.push('start');
+        return Promise.resolve();
+      });
+
       renderHook(() => useStartBackgroundLocationUpdates());

       await new Promise(process.nextTick);

       expect(mockHasStartedLocationUpdatesAsync).toHaveBeenCalledWith(
         LOCATION_TASK_NAME
       );
       expect(mockStopLocationUpdatesAsync).toHaveBeenCalledWith(
         LOCATION_TASK_NAME
       );
       expect(mockStartLocationUpdatesAsync).toHaveBeenCalled();
+      expect(callOrder).toEqual(['stop', 'start']);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useStartBackgroundLocationUpdates.test.tsx` around lines 112 - 128,
Add an assertion that verifies stopLocationUpdatesAsync was invoked before
startLocationUpdatesAsync in the test for useStartBackgroundLocationUpdates:
after rendering and awaiting the tick (where you already assert both calls
occurred), read the mock invocation order values from
mockStopLocationUpdatesAsync.mock.invocationCallOrder and
mockStartLocationUpdatesAsync.mock.invocationCallOrder and assert the stop
invocation order is less than the start invocation order so the test confirms
stop happens before start; reference the existing mocks
mockStopLocationUpdatesAsync and mockStartLocationUpdatesAsync and the hook
useStartBackgroundLocationUpdates.

130-144: stopLocationUpdatesAsyncが呼ばれないことの明示的なアサーションが不足しています。

コメントには「stopはクリーンアップ用のstartの前には呼ばれない」と記載されていますが、実際のアサーションがありません。unmount時のクリーンアップでもstopLocationUpdatesAsyncが呼ばれるため、このテストではstartLocationUpdatesAsync呼び出し時点でstopLocationUpdatesAsyncが呼ばれていないことを検証すべきです。

♻️ アサーションを追加する例
       expect(mockHasStartedLocationUpdatesAsync).toHaveBeenCalledWith(
         LOCATION_TASK_NAME
       );
-      // stopはクリーンアップ用のstartの前には呼ばれない
+      // プリクリーンアップのstopは呼ばれない(startの前にstopが呼ばれていないことを確認)
+      expect(mockStopLocationUpdatesAsync).not.toHaveBeenCalled();
       expect(mockStartLocationUpdatesAsync).toHaveBeenCalled();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useStartBackgroundLocationUpdates.test.tsx` around lines 130 - 144,
テストで startLocationUpdatesAsync を呼んだ時点で stopLocationUpdatesAsync
がまだ呼ばれていないことを明示的に検証してください:useStartBackgroundLocationUpdates のテスト内で
process.nextTick 後に expect(mockStopLocationUpdatesAsync).not.toHaveBeenCalled()
を追加し、続けて expect(mockStartLocationUpdatesAsync).toHaveBeenCalled()
をアサートしてください(アンマウント時のクリーンアップで stopLocationUpdatesAsync
が呼ばれることを確認したい場合は、renderHook の返り値の unmount を呼んだ後に
expect(mockStopLocationUpdatesAsync).toHaveBeenCalled() を追加してください)。
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/hooks/useStartBackgroundLocationUpdates.test.tsx`:
- Around line 112-128: Add an assertion that verifies stopLocationUpdatesAsync
was invoked before startLocationUpdatesAsync in the test for
useStartBackgroundLocationUpdates: after rendering and awaiting the tick (where
you already assert both calls occurred), read the mock invocation order values
from mockStopLocationUpdatesAsync.mock.invocationCallOrder and
mockStartLocationUpdatesAsync.mock.invocationCallOrder and assert the stop
invocation order is less than the start invocation order so the test confirms
stop happens before start; reference the existing mocks
mockStopLocationUpdatesAsync and mockStartLocationUpdatesAsync and the hook
useStartBackgroundLocationUpdates.
- Around line 130-144: テストで startLocationUpdatesAsync を呼んだ時点で
stopLocationUpdatesAsync
がまだ呼ばれていないことを明示的に検証してください:useStartBackgroundLocationUpdates のテスト内で
process.nextTick 後に expect(mockStopLocationUpdatesAsync).not.toHaveBeenCalled()
を追加し、続けて expect(mockStartLocationUpdatesAsync).toHaveBeenCalled()
をアサートしてください(アンマウント時のクリーンアップで stopLocationUpdatesAsync
が呼ばれることを確認したい場合は、renderHook の返り値の unmount を呼んだ後に
expect(mockStopLocationUpdatesAsync).toHaveBeenCalled() を追加してください)。

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/hooks/useStartBackgroundLocationUpdates.test.tsx (1)

45-52: ⚠️ Potential issue | 🟡 Minor

afterEachjest.clearAllMocks() を実行してください。
失敗時にモックが残る可能性があるため、ガイドラインどおり afterEach に移してください。

修正案
   beforeEach(() => {
-    jest.clearAllMocks();
     mockAutoModeEnabled = false;
     mockStartLocationUpdatesAsync.mockResolvedValue(undefined);
     mockStopLocationUpdatesAsync.mockResolvedValue(undefined);
     mockHasStartedLocationUpdatesAsync.mockResolvedValue(false);
     mockWatchPositionAsync.mockResolvedValue({ remove: mockRemove });
   });
+
+  afterEach(() => {
+    jest.clearAllMocks();
+  });

As per coding guidelines, "Call jest.clearAllMocks() in afterEach blocks in all test files".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useStartBackgroundLocationUpdates.test.tsx` around lines 45 - 52,
The test currently calls jest.clearAllMocks() inside beforeEach; remove that
call from the beforeEach and add an afterEach block that calls
jest.clearAllMocks() instead (e.g., afterEach(() => jest.clearAllMocks())); keep
the existing mock setup for mockStartLocationUpdatesAsync,
mockStopLocationUpdatesAsync, mockHasStartedLocationUpdatesAsync,
mockWatchPositionAsync and mockRemove in the beforeEach, ensuring only
jest.clearAllMocks() is moved to afterEach to follow the guideline.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/hooks/useStartBackgroundLocationUpdates.test.tsx`:
- Around line 137-145: The file
src/hooks/useStartBackgroundLocationUpdates.test.tsx failed Biome formatting
around the test "should not stop when no stale task exists"; fix it by running
the Biome formatter (biome format) on that file (or the repo), verify the diff
is clean, and re-commit the formatted changes so
useStartBackgroundLocationUpdates.test.tsx and the test block around
renderHook(() => useStartBackgroundLocationUpdates()) match the project's Biome
formatting rules.

---

Outside diff comments:
In `@src/hooks/useStartBackgroundLocationUpdates.test.tsx`:
- Around line 45-52: The test currently calls jest.clearAllMocks() inside
beforeEach; remove that call from the beforeEach and add an afterEach block that
calls jest.clearAllMocks() instead (e.g., afterEach(() =>
jest.clearAllMocks())); keep the existing mock setup for
mockStartLocationUpdatesAsync, mockStopLocationUpdatesAsync,
mockHasStartedLocationUpdatesAsync, mockWatchPositionAsync and mockRemove in the
beforeEach, ensuring only jest.clearAllMocks() is moved to afterEach to follow
the guideline.

@TinyKitten TinyKitten force-pushed the claude/fix-android-location-updates-65U9y branch from 7e9dba0 to 6e6abf0 Compare February 22, 2026 09:46
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/hooks/useStartBackgroundLocationUpdates.test.tsx (1)

45-52: ⚠️ Potential issue | 🟡 Minor

jest.clearAllMocks()afterEach に移してください。
現状は beforeEach のみなのでガイドライン違反です。

修正案
 beforeEach(() => {
-  jest.clearAllMocks();
   mockAutoModeEnabled = false;
   mockStartLocationUpdatesAsync.mockResolvedValue(undefined);
   mockStopLocationUpdatesAsync.mockResolvedValue(undefined);
   mockHasStartedLocationUpdatesAsync.mockResolvedValue(false);
   mockWatchPositionAsync.mockResolvedValue({ remove: mockRemove });
 });
+
+afterEach(() => {
+  jest.clearAllMocks();
+});

As per coding guidelines, "Call jest.clearAllMocks() in afterEach blocks in all test files".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useStartBackgroundLocationUpdates.test.tsx` around lines 45 - 52,
Move the jest.clearAllMocks() call out of the beforeEach block and into an
afterEach block in this test file: keep the existing mock initializations
(mockAutoModeEnabled, mockStartLocationUpdatesAsync.mockResolvedValue,
mockStopLocationUpdatesAsync.mockResolvedValue,
mockHasStartedLocationUpdatesAsync.mockResolvedValue,
mockWatchPositionAsync.mockResolvedValue) inside beforeEach, and add an
afterEach that calls jest.clearAllMocks() so that mocks are cleared after each
test; reference the beforeEach/afterEach hooks and the jest.clearAllMocks() call
when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/hooks/useStartBackgroundLocationUpdates.test.tsx`:
- Around line 45-52: Move the jest.clearAllMocks() call out of the beforeEach
block and into an afterEach block in this test file: keep the existing mock
initializations (mockAutoModeEnabled,
mockStartLocationUpdatesAsync.mockResolvedValue,
mockStopLocationUpdatesAsync.mockResolvedValue,
mockHasStartedLocationUpdatesAsync.mockResolvedValue,
mockWatchPositionAsync.mockResolvedValue) inside beforeEach, and add an
afterEach that calls jest.clearAllMocks() so that mocks are cleared after each
test; reference the beforeEach/afterEach hooks and the jest.clearAllMocks() call
when making the change.

@TinyKitten TinyKitten force-pushed the claude/fix-android-location-updates-65U9y branch from 6e6abf0 to 2e4e7d2 Compare February 22, 2026 09:51
@TinyKitten
Copy link
Member Author

@coderabbitai ほかになければ承認してもろて

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 22, 2026

@TinyKitten はい、変更内容を確認しました。古い位置情報タスクのクリーンアップロジックとそのテストが適切に追加されています。承認いたします。


🧠 Learnings used
Learnt from: TinyKitten
Repo: TrainLCD/MobileApp PR: 0
File: :0-0
Timestamp: 2025-08-11T21:13:39.083Z
Learning: TinyKitten prefers concise code reviews for the TrainLCD/MobileApp repository. Keep review comments brief and to the point.

Learnt from: TinyKitten
Repo: TrainLCD/MobileApp PR: 4448
File: functions/src/funcs/tts.ts:214-232
Timestamp: 2025-08-11T20:23:23.071Z
Learning: PR `#4448` in TrainLCD/MobileApp is specifically about AI feedback summarization and labeling functionality, not about TTS (Text-to-Speech) improvements. The TTS code changes appear to be part of a modularization refactoring but are not the focus of this PR.
✅ Actions performed

Comments resolved and changes approved.

@TinyKitten TinyKitten merged commit baf1b1b into dev Feb 22, 2026
6 checks passed
@TinyKitten TinyKitten deleted the claude/fix-android-location-updates-65U9y branch February 22, 2026 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants