前言
随着互联网的遇冷,前端如果只局限于 web 端开发的话,路会越走越窄,应该多朝夸端开发的方向拓展一下。最近研究了下使用 React Native 开发 App,这里分享下从搭建到构建一个 apk 的完整过程,以供参考学习。由于本人的 Mac 电脑还是 2018 年款的 8G 内存,跑不了 iOS 开发所需的环境,所以以下内容是在 windows 电脑以 Android 开发的角度书写的。
提醒:windows 电脑的内存最好是 32G 以上,否则在运行模拟器时,如果再运行其他一些耗内存的程序,会提示 内存不足 卡出来;还有就是注意一定要 科学上网,否则寸步难行;依赖安装的过程可能耗时比较长,需要耐心等待。
版本:"react": "18.3.1","react-native": "0.77.0"
代理说明
在应用首次编译打包时需要下载大量的依赖包,这一过程相当耗时;代理一般只会对浏览器上网有效,如果在终端使用的话可能会失效,你需要给自己的终端设置下代理,保证是通过代理去下载的。如图1是我的代理配置,在 android/gradle.properties 文件中配置相应的代理如下:
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=10810
systemProp.https.proxyHost=127.0.0.1
systemProp.https.proxyPort=10810
图1
环境搭建
安装依赖
作为前端开发,Node 环境应该都有,这里不多说,注意 Node 的版本应大于等于 18。
- Java Development Kit [JDK] 17 - 不建议直接使用搜索引擎搜索下载,尝试过......有很多夹带私货的流氓软件;通过科学上网直接到 官网 下载,注意需要先注册登录才能下载,为了长远考虑发点时间注册下也是值得的;还有一点需要注意的是你的 React Native 版本,低于 0.73 版本的 React Native 需要 JDK 11 版本,而低于 0.67 的需要 JDK 8 版本;安装完成后执行 javac -version 输出版本号看是否安装成功,一般会自动设置环境变量的。
- Yarn - 包管理工具建议使用 Yarn,这也是官方推荐的;执行 npm i -g --verbose yarn 就行了。
- Android Studio - 直接从 官网 下载,安装界面中选择"Custom"选项,确保选中了以下几项 Android SDK, Android SDK Platform, Android Virtual Device ,如果选择框是灰的,可以先跳过,稍后再来安装这些组件,然后点击"Next"来安装选中的组件;Android Studio 默认会安装最新版本的 Android SDK,目前编译 React Native 应用需要的是Android 14 (UpsideDownCake)版本的 SDK,需要在 Android Studio 的 SDK Manager 中选择安装,SDK Manager 可以在欢迎界面的 More Actions 中找到,如果已经过了欢迎界面,也可以在菜单栏中找到,如图2,打开 SDK Manager 后,已安装的不用管,勾选如图3所示的 SDK,最后点击"Apply"来下载和安装这些组件;Android Studio 安装完成后需要设置环境变量,这里不赘述了,如图4所示。
图1
图2
图3
图4
创建项目
直接使用命令,安装最干净的模板:
npx @react-native-community/cli init AwesomeProject
注意:初始化的项目名称改成自己想要的,否则初始化好了再改有点小麻烦;使用 yarn 安装依赖,这里可以切换到 taobao 源安装,快多了。
模拟器和真机
开发的时候需要预览和调试,可以使用模拟器,也可以使用真机。
创建模拟器
Android Studio 安装好了后,默认是有一个模拟器的,这里根据 React Native 的需要创建一个 Tiramisu API Level 33 image 的模拟器。
真机连接
- 用数据线和电脑连接,电脑中出现手机设备才行,如下图;
- 打开usb调试,不细讲了,可以直接看 这里。
编译运行
运行之前可以执行以下命令查看是否有连接的模拟器或真机设备,只保留一个设备就行了,因为太耗内存了,内存怪兽的略过......
adb devices
# 出现以下信息表示有2个设备连接
List of devices attached
emulator-5554 # Google emulator
14ed2fcc device # Physical device
如果显示没有连接的设备也没关系,因为运行的时候会自动启动模拟器设备,直接在项目根目录执行:
yarn android
运行时自动启动的模拟器效果如下图:
生成 APK 包
Android 要求所有应用都有一个数字签名才会被允许安装在用户手机上,所以需要先生成一个签名密钥。这里我们直接使用keytool命令快速生成一个密钥。
- 找到 Java 安装的 bin 目录,如:C:\Program Files\Java\jdkx.x.x_x\bin,在该目录下创建一个终端,执行:
keytool -genkeypair -v -storetype PKCS12 -keystore reactapp-release-key.keystore -alias reactapp-key-alias -keyalg RSA -keysize 2048 -validity 10000
这条命令会要求你输入密钥库(keystore)和对应密钥的密码,这2个密码应该保持一致,最终会在当前目录创建一个叫reactapp-release-key.keystore的密钥库文件,有效期为 10000 天,将密钥库文件放到项目的 android/app 下(密钥库文件在提交时会自动忽略,不要将它提交到远程项目)。
- 找到 android/gradle.properties,添加如下代码
MYAPP_RELEASE_STORE_FILE=reactapp-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=reactapp-key-alias
MYAPP_RELEASE_STORE_PASSWORD=<这里输入自己设置的密码>
MYAPP_RELEASE_KEY_PASSWORD=<这里输入自己设置的密码>
3. 把签名配置加入到项目的 android/app/build.gradle 配置中。
...
android {
...
defaultConfig { ... }
signingConfigs {
release {
if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
storeFile file(MYAPP_RELEASE_STORE_FILE)
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias MYAPP_RELEASE_KEY_ALIAS
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
}
}
buildTypes {
release {
...
signingConfig signingConfigs.release
}
}
}
...
4. 在项目根目录执行以下命令,生成 APK 包,生成的包在 android/app/build/outputs/apk/release 中。
cd android
./gradlew assembleRelease
开发实践
入口文件修改
创建项目的 entry file index.js 默认在项目根目录,将它改成熟悉的 SPA 框架目录,创建 src 目录,将 index.js,App.tsx,app.json 移入 src 目录,android/app/build.gradle 配置需要做相应的修改,如下:
// The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
// entryFile = file("../js/MyApplication.android.js")
entryFile = file("../../src/index.js")
底部导航器
需要安装 React Navigation 的 @react-navigation/native,@react-navigation/bottom-tabs 依赖包,在 src/App.tsx 中编写代码:
const navigationEmit = (options: any) => {
return options;
};
// 创建底部标签
const Tabs = createBottomTabNavigator({
initialRouteName: 'Home',
screenOptions: {
animation: 'fade',
},
tabBar: props => (
<TabBar
{...{
...props,
navigation: {
...props.navigation,
emit: options => navigationEmit(options),
},
}}
/>
),
screens: {
Home: {
screen: Home,
options: {
tabBarLabel: '首页',
headerShown: false,
tabBarIcon: props => <HomeIcon {...props} />,
},
},
Components: {
screen: Components,
options: {
tabBarLabel: '组件',
headerShown: false,
tabBarIcon: props => <ComponentsIcon {...props} />,
},
},
Api: {
screen: Api,
options: {
tabBarLabel: '接口',
headerShown: false,
tabBarIcon: props => <ApiIcon {...props} />,
},
},
},
});
// 创建根导航
const RootStack = createNativeStackNavigator({
initialRouteName: 'Tabs',
screenOptions: {
animation: 'ios_from_right',
headerStyle: {
backgroundColor: screenBackgroundColor,
},
},
screens: {
Tabs: {
screen: Tabs,
options: {
headerShown: false,
},
},
'Components/ActivityIndicator': {
screen: ActivityIndicator,
options: {
headerTitle: '加载提示',
},
},
'Components/Button': {
screen: Button,
options: {
headerTitle: '按钮',
},
},
'Components/Modal': {
screen: Modal,
options: {
headerTitle: '弹窗',
},
},
'Api/Camera': {
screen: Camera,
options: {
headerTitle: '相机',
},
},
},
});
const Navigation = createStaticNavigation(RootStack);
export default function App(): React.JSX.Element {
return (
<>
<StatusBar
backgroundColor={screenBackgroundColor}
barStyle="dark-content"
/>
<SafeAreaProvider>
<Navigation />
</SafeAreaProvider>
</>
);
}
相机功能
使用第三方包 react-native-vision-camera,这里就省略了,具体可以看我的 github 项目地址。