AndroidターゲットAPIレベル34への移行時のアプリクラッシュ問題の解決
問題の説明
AndroidアプリをターゲットAPI 33から34(Android 14)にアップグレードした際、以下のようなエラーが発生しアプリがクラッシュする現象が発生します:
java.lang.RuntimeException: Unable to create application com.testreactnative.MainApplication:
Caused by: java.lang.SecurityException: com.testreactnative:
One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified
when a receiver isn't being registered exclusively for system broadcasts
主な症状:
- API 33エミュレータでは動作するがAPI 34ではクラッシュ
- ビルド自体は成功するが起動直後に終了
- Logcatに上記のセキュリティ例外が出力される
BridgeDevSupportManager
関連のエラーが併記される場合がある
根本的な原因
Android 14(APIレベル34)から導入されたブロードキャストレシーバーのエクスポート制限が主要因です:
- 新セキュリティポリシー: システムブロードキャスト以外のレシーバー登録では
RECEIVER_EXPORTED
またはRECEIVER_NOT_EXPORTED
の明示必須 - 非互換ライブラリ: React Native関連モジュール(
react-native-orientation
等)が新APIに未対応 - Gradle/依存関係: 古いビルドツールや互換性のないライブラリバージョンで発生する二次的エラー
解決策
以下に効果的な解決方法を優先度順に紹介します。
🛠️ 方法1: ブロードキャストレシーバーの明示的エクスポート設定(推奨)
MainApplication.java にオーバーライドメソッドを追加:
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import org.jetbrains.annotations.Nullable;
public class MainApplication extends Application {
// ...
@Override
public Intent registerReceiver(
@Nullable BroadcastReceiver receiver,
IntentFilter filter
) {
if (Build.VERSION.SDK_INT >= 34 &&
getApplicationInfo().targetSdkVersion >= 34) {
// Android 14以上でRECEIVER_EXPORTEDを明示
return super.registerReceiver(
receiver,
filter,
Context.RECEIVER_EXPORTED
);
} else {
return super.registerReceiver(receiver, filter);
}
}
}
必要な依存関係を追加 (app/build.gradle):
dependencies {
implementation 'org.jetbrains:annotations:16.0.2'
}
📦 方法2: サードパーティライブラリのパッチ適用
react-native-orientation 等のライブラリで発生する場合の修正手順:
- ライブラリのビルド設定を修正 (
node_modules/react-native-orientation/android/build.gradle
):
android {
compileSdkVersion getExtOrDefault('compileSdkVersion', 33)
buildToolsVersion getExtOrDefault('buildToolsVersion', "33.0.0")
defaultConfig {
minSdkVersion getExtOrDefault('minSdkVersion', 21)
targetSdkVersion getExtOrDefault('targetSdkVersion', 34)
}
}
- ソースコードを修正 (
OrientationModule.java
):
import android.os.Build;
// ...
if (Build.VERSION.SDK_INT >= 34 &&
activity.getApplicationInfo().targetSdkVersion >= 34) {
activity.registerReceiver(
receiver,
new IntentFilter("onConfigurationChanged"),
Context.RECEIVER_EXPORTED // 明示的エクスポート
);
} else {
activity.registerReceiver(
receiver,
new IntentFilter("onConfigurationChanged")
);
}
- 修正を永続化:
yarn add patch-package --dev
yarn patch-package react-native-orientation
⚙️ 方法3: compileSdkVersionとtargetSdkVersionの調整
一時的な回避策として build.gradle を調整:
ext {
compileSdkVersion = 33 // 現状維持
targetSdkVersion = 34 // Android 14をターゲット
buildToolsVersion = "34.0.0"
}
注意点
これは一時的な回避策です。長期的にはcompileSdkVersion
も34に上げる必要があります
🔧 方法4: 依存関係とビルドツールの更新
安定ビルドのための環境アップグレード:
- gradle-wrapper.properties:
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
- トップレベルのbuild.gradle:
dependencies {
classpath 'com.android.tools.build:gradle:7.2.2'
classpath "com.google.firebase:perf-plugin:1.4.1"
}
- React Nativeライブラリの更新例 (package.json):
{
"dependencies": {
"react-native": "0.66.5",
"react-native-screens": "3.22.1",
"react-native-webview": "11.22.7"
},
"resolutions": {
"@react-native-community/cli**": "^7.0.0"
}
}
Android 14対応のベストプラクティス
テストサイクルの確立:
- エミュレータ/実機両方での検証
targetSdkVersion
変更後は必ずフルリグレッションテスト
権限設定の見直し:
- ストレージ権限の
maxSdkVersion
を確認
xml<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
- ストレージ権限の
モジュラリティの活用:
gradle// build.gradleに追加 android { useLibrary 'android.test.runner' useLibrary 'android.test.base' }
公式ドキュメントの参照:
推奨アップデートフロー
compileSdkVersion
とtargetSdkVersion
を段階的に更新- 各ライブラリの互換性バージョンを確認
- パッチ適用が必要なモジュールを抽出
- Android 14エミュレータで動作検証
- 実機テストで最終確認
まとめ
Android 14対応ではブロードキャストレシーバーの新しいセキュリティ制約が主要課題となりますが:
RECEIVER_EXPORTED
/RECEIVER_NOT_EXPORTED
の明示的指定- 影響を受けるサードパーティライブラリの修正パッチ適用
- Gradle/React Nativeライブラリの適切なバージョン管理
これらを適切に実施することで安定動作が可能です。APIレベル34への移行は必須要件のため、本ガイドを参考に安全にアップグレードを実施してください。