AndroidからReact Nativeアプリ呼び出し(Java)
やりたいこと
既にあるReact NativeアプリをJavaかKotlinで呼び出して組み込みたいという需要があったときに、 どんな感じでやればいいかを試してみます。 (Java)
実現したいこと
Java製の画面にボタンがあって、ボタンを押すとReact Nativeの画面に遷移するのをやりたいです。
React Nativeをbundle化
React Nativeアプリを作成 teisyoku-tabetai.hatenablog.com
React Nativeをbundle化
assetsフォルダがない場合は作成します。
mkdir android/app/src/main/assets
bundle化
npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res
index.android.bundleができていれば完了です。
React Native関連のモジュールの用意
ここのところの方法は、いろいろ試した挙句できなかったので、以下の参考文献の内容を記述させていただいています。
mkdir integratedReactNativeProject
cd integratedReactNativeProject && touch package.json
package.jsonの中身
{ "name": "sampleReactApp", "version": "0.0.1", "private": true, "scripts": { "start": "yarn react-native start" } }
npm i yarn
yarn add react-native
Androidプロジェクト作成 & React Nativeの依存関係を記述
Android StudioでAndroidプロジェクトを作成
node_modulesと同階層に移動させる。
Androidプロジェクトに依存関係を記述
プロジェクト配下のbuild.gradle(appディレクトリと同階層)に以下を追記
allprojects { repositories { maven { // All of React Native (JS, Android binaries) is installed from npm url ("$rootDir/../node_modules/react-native/android") } maven { // Android JSC is installed from npm url("$rootDir/../node_modules/jsc-android/dist") } google() jcenter() } }
- app配下のbuild.gradleに以下を追記(※1)
dependencies { ... implementation "com.facebook.react:react-native:+" // From node_modules implementation "org.webkit:android-jsc:+" } apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
(※1)
implementation "com.facebook.react:react-native:+" について
わざわざnpmでReact Nativeを入れてnode_modulesから引っ張ってきてるのはmavenから取ってこれなかったため。(2023年3月現在)
Gradleあまり詳しくないので、もっと良い方法がありそう...
central.sonatype.com
- gradle.propertiesに以下を追加
android.enableJetifier=true
- settings.gradleに以下を追記(※2)
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
(※2) プロジェクト配下のbuild.gradleにrepositoriesを追記したので、settings.gradleにもある場合はコメントアウト(二重で記述するとエラー)
3 起動用のActivityを追加
package com.example.myapplication; // プロジェクト名に応じて変更 import android.app.Activity; import android.os.Bundle; import android.view.KeyEvent; import com.facebook.react.PackageList; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactPackage; import com.facebook.react.ReactRootView; import com.facebook.react.common.LifecycleState; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.soloader.SoLoader; import java.util.List; public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler { private ReactRootView mReactRootView; private ReactInstanceManager mReactInstanceManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SoLoader.init(this, false); mReactRootView = new ReactRootView(this); List<ReactPackage> packages = new PackageList(getApplication()).getPackages(); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setCurrentActivity(this) .setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") .addPackages(packages) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); mReactRootView.startReactApplication(mReactInstanceManager, "sampleReactApp", null); // (※3) setContentView(mReactRootView); } @Override public void invokeDefaultOnBackPressed() { super.onBackPressed(); } }
(※3) 元のReact Nativeプロジェクトのプロジェクト名に合わせる必要がある。プロジェクト名が分からなかったらindex.android.bundleから探せば行けるかもです。
4 Android Studioで実行
Android StudioからReact Nativeアプリを呼び出すことができました。
サンプル画面のロゴ画像が表示できていませんが、あまり気にしないこととします。
画面遷移を作る
- 先に表示させるAndroid画面用のアクティビティを作成
MainActivity.java
package com.example.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.button); textView = findViewById(R.id.text_view); button.setOnClickListener( v -> { this.onClick(); }); } public void onClick() { Intent intent = new Intent(); intent.setClassName(getApplicationContext(), "com.example.myapplication.MyReactActivity"); startActivity(intent); } }
2 MainActivity用のActivityを追加
<activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".MyReactActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
3 app/src/main/res/layoutのactivity_main.xmlを編集
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Androidアプリ" android:textSize="34sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0.497" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.281" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#42CC47" android:backgroundTint="#4CAF50" android:text="React Nativeアプリへ遷移" android:textColorHint="#FFFFFF" android:textColorLink="#FFFFFF" android:textSize="16sp" app:iconTint="#4CAF50" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0.496" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.6" app:rippleColor="#4CAF50" /> </androidx.constraintlayout.widget.ConstraintLayout>
以上の手順で、冒頭に示したような、AndroidからReact Nativeへの画面遷移を実現できました。