いつの間にか色々変わっていて大分面倒臭くなっている
一番の変更はローカルビルドが出来なくなって
ビルドにものすごい時間がかかるようになっている
ローカルビルド出来るっぽい
共通
npx create-expo-app@latest [option]
option部分にアプリ名を入れると対話形式での作成が不要になる
ちなみにnpx react-native init [アプリ名]
は動かなくなっている
cd [アプリ名]
npx expo prebuild
これを行わないとandroidディレクトリは作成されない
ちなみにiosディレクトリはMacOS環境で無いと作成されない
ソースコード
ルートにあるApp.tsx
が無くなっていて、react-navigation
もうまく動作しない
app
ディレクトリ内の_layout.tsx
が開始位置と思われる
react-navigation
の代わりにはexpo-router
を使う
expo-router
例)
_layout.tsx
がこんな感じにあったとしたら
<ThemeProvider value={DefaultTheme}>
<Stack>
<Stack.Screen name="index" />
<Stack.Screen name="device" options={{title: 'Unknown Device Name'}} />
</Stack>
</ThemeProvider>
indexからdeviceへは
Link
のhref
にこんな感じで記載する
<Link style={styles.line} onPress={() => { startScan(false) }} href={"./device?address=" + item.address + "&name=" + item.name}>
...
</Link>
android
実行方法は変化なし
npm run android
Native Module
以前のNativeModuleは動作しない
以前の例)
import { NativeModules } from "react-native";
const native = NativeModules.BLEModule
export const ble = {
register: async (keyno, uuid, input, cb) => {
native.register(keyno, uuid, input, cb)
},
open: async (cb) => {
const { key_no, uuid, key } = await getKeyInfo()
native.open(key_no, uuid, key, cb)
},
...
TurboModuleというのを使う必要がある
詳細はリンク先の通りだが
specファイルを適切に記載する必要がある
例) app/specs/NativeBLE.ts
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
start_scan(): void
stop_scan(): void
connect(address: string): void
disconnect(): void
send_data(val: string): void
}
export default TurboModuleRegistry.getEnforcing<Spec>(
'BLEModule',
);
getEnforcing内のモジュール名はNativeModuleの名前に依存する
以下のgetName部分
class BLEModule(reactContext: ReactApplicationContext?) : NativeBLESpec(reactContext),
BLEInterface {
private var mManager: BLEManager? = null
private val foundedDevices: HashMap<String, BluetoothDevice> = HashMap()
private var lastConnected: String? = null
init {
ContextHolder.init(reactContext)
}
override fun getName() = NAME
...
package.jsonには以下のように記載する
"codegenConfig": {
"name": "NativeBLESpec",
"type": "modules",
"jsSrcsDir": "app/specs",
"android": {
"javaPackageName": "com.yano.interplan.imble3_app"
}
},
package.jsonの"name"欄にはspecファイルのファイル名に依存するので注意
ファイル名(除くsuffix)+'Spec'
EventEmitteer
EventEmitterは以前と同じ様に使用出来る
android側の例
private fun sendEvent(data: String) {
val params = Arguments.createMap()
params.putString("json", data)
val context = ContextHolder.context
val module = context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
if (module == null) {
dlog("")
return
}
module.emit(EVENT_NAME, params)
}
受け側の例
useEffect(() => {
const eventEmitter = new NativeEventEmitter(NativeModules.DeviceFound)
let eventListener = eventEmitter.addListener(EVENT_NAME, event => {
if (event && event.json) {
...
}
})
return () => {
eventListener.remove()
}
})
アイコンの変更
assets/images/icon.png
とassets/images/splash-icon.png
を変更して
npx expo prebuild
するだけ
サイズ別のファイルを用意する必要も無くなって
すごい楽になった
なお、以前と同じ方法をするとprebuild
で上書きされるので注意
以前の方法
android/app/src/main/res/mipmap-xxx内の
ic_launcher.webp
ic_launcher_foreground.webp
ic_launcher_round.webp
をそれぞれ
ic_launcher.png
ic_launcher_foreground.png
ic_launcher_round.png
に置き換える
apkファイルの作成
コード更新後に必ずこれを実行する
npx expo prebuild
androidディレクトリに移動してbuild
ディレクトリを削除
cd android
rm -rf build
NativeModuleを使用している場合は以下も実行する
./gradlew generateCodegenArtifactsFromSchema
ルートに戻って
cd ..
eas.jsonを作成して
{
"build": {
"preview": {
"android": {
"buildType": "apk"
}
},
"preview2": {
"android": {
"gradleCommand": ":app:assembleRelease"
}
},
"preview3": {
"developmentClient": true
},
"preview4": {
"distribution": "internal"
},
"production": {}
}
}
expo-cliは必須
npm install -g expo-cli
expoにアカウントを作る
メールとパスワードだけなので簡単だと思う
アカウントを作成してメール認証したらログインする
eas login
対話形式なのでメールアドレスとパスワードでログインする
easでローカルビルド
eas build --local -p android --profile preview --clear-cache
こんな感じで結果が表示されるので
Build successful
You can find the build artifacts in /home/tyano/workspace/react_native/sample_app/build-1738129212397.apk
普通にインストール
adb install /home/tyano/workspace/react_native/sample_app/build-1738129212397.apk

old
ローカルでのビルドは出来ないらしい
ビルド(普通に数10分かかる)
eas build --platform android
ios
expo
MacOS以外で作ったプロジェクトなら
expoをインストールする
npm install expo
iosディレクトリを作成してもらう
npx expo prebuild
Gemfile
なぜかGemfileは存在しないので自分で作る
cd ios
bundle init
vim Gemfile
gem "cocoapods"
を追記
cocoapodのインストール
bundle install
bundle exec pod install
NativeModule
iosのNativeModuleはあんまり変わっていない
以下の部分が変更になったくらい
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params {
return std::make_shared<facebook::react::NativeLocalStorageSpecJSI>(params);
}
詳細は公式の通り