React Native是个好东西,用它可以做到拿React写原生Android开发。

这样虽然也挺好的,效率很好,很原生。但很多时候我希望它真的能像Web一样,能用完整的CSS,能用Web上的各种库。

用React Native搭配Web View也不是不行吧,但这样感觉有点简陋,毕竟WebView可是承载了所有功能的啊。>︿<

所以,我希望有一个框架,可以让我能够真的像写Web一样写安卓原生。

Capacitor

首先是Electron,这个我熟,以前没少用它套壳。

但它啊,似乎并不支持给安卓套壳`(*>﹏<*)′

有没有能在安卓上跑的壳呢?

当然有!(此处省略800字卖关子)Capacitor!

https://capacitorjs.com/docs

Capacitor十分简单粗暴大道至简,不管项目是什么写的,React也好、Vue也好、原生也好,只要你能在浏览器里面跑,他就能做成手机APP。

在一切开始之前,请先确保你的机器上有装Android Studio。(・ω´・ )

(这些东西在Capacitor 6.2.0和7.0.1测试过,如果有找不到命令行什么的版本问题可以尝试这两个版本)

Web套壳APP工作流程

先不谈怎么从头开发APP,假设现在已经有一个写好的H5页面。(因为我手上刚好有几个手机端的H5页面

准备需要套壳的东西

首先确保这个项目是能够编译并跑起来的,然后编译项目。(不能编译或者跑不起来也没关系,只要./dist目录里面有能跑的东西就行)。

一般来说,项目编译会输出东西到dist目录下,接下来的操作只需要dist里面的东西(会对dist里面的东西套壳)。

目前,项目结构如下,可以以有其他多余的东西:

项目
├── dist
│   ├── (...)
├── package.json

安装套壳的包

接下来,需要在项目中安装几个包:

npm install @capacitor/cli
npm install @capacitor/core
npm install @capacitor/android

初始化壳

首先IOS我们不考虑,只考虑安卓。( ˘・з・)

首先初始化项目:

npx cap init

需要填写项目名(可以中文哦)和应用包名。

这条命令会在项目中创建capacitor.config.ts

接下来添加面向安卓的打包:

npx cap add android

这条命令会创建android 目录,里面是个安卓项目,如果需要修改图标之类的需要进这里面改,这个目录首次创建之后,除了放Web资源的目录,其他目录都不是临时的(有版本管理要放版本管理里,可以随意修改,不会有程序给覆盖掉)

假如这个android项目搞坏了,可以通过删除这个目录重新打命令的方式恢复。( ºΔº )

接下来最后一步,把dist里面的东西复制到android项目里面。

npx cap sync

直接用Android Studio去开项目是可以的,也可以用下面的命令来开项目:

npx cap open android

禁止横屏

现在直接编译就好啦,但是直接编译会出现一个不是很优雅的问题,那就是页面会随着手机旋转。

可以通过修改清单文件实现:

<manifest>
    <application>
        <activity
            android:screenOrientation="portrait"
        >
        </activity>
    </application>
</manifest>

但上述做法不够优雅,更优雅的做法是使用官方的屏幕方向控制插件@capacitor/screen-orientation ,,Ծ‸Ծ,,

然后用代码控制:

import {ScreenOrientation } from "@capacitor/screen-orientation"
ScreenOrientation.lock({
    orientation: "portrait"
})

(如果你用后面优雅的方式做了,记得要重新构建项目并重新执行复制命令)

允许混合内容

如果后端不是Https协议,软件运行起来会网络请求会被安卓本地拒掉,需要允许混合内容。

这里需要在两个地方加点儿东西。

首先是安卓APP的清单文件(android/app/src/main/androidmanifest.xml),给application标签添加一条android:usesCleartextTraffic="true" 允许APP使用明文流量。

<application
  ...
  android:usesCleartextTraffic="true">

然后是,在capacitor.config.ts 中,添加android配置项,里面配置allowMixedContent ,允许WebView的混合内容。

  android: {
        allowMixedContent: true,
  }

编译安卓APP

修改图标什么的,我就不多说啦。

接下来,架好梯子(对安卓开发来说,这是必要的),准备编译APP吧。

在项目加载之后,ADB连上手机直接点运行就能跑起来。但这里产生的APK是未签名的APK,不能分发,直接安装是装不上的。

(打包之前要先sync一次,据测试,如果刚刚实时实机调试过,打包打出来的是不正确的)

通过下面的步骤打包APK:

图片-lmcs.png

APK会放在./android/app/release/app-release.apk

Ionic

这个东西不是必须的,它就是一个UI库,相较于其他UI库,它的好处是,像原生APP。

如果是从头写一个APP的话,个人感觉用Ionic是挺好的。

怎么从头建一个项目,就参考Ionic的官方文档吧:

https://ionicframework.com/docs/

调试控制台

ADB接好手机后,是可以使用电脑上的开发工具调试WebView的。

官方提供了调试方法

具体来说,如果使用Chrome的调试器进行调试的话,进行如下操作:

  • ADB连接好

  • 手机打开APP

  • 电脑Chrome打开chrome://inspect/

  • 稍等片刻,就能够看到在手机上打开的WevView

同时,官方提供的插件可以直接在VSCode调试。

VSCode插件

官方提供了一个叫Ionic 的插件(但这个插件不是必须要用Ionic开发,只要是Capacitor就可以)

更换应用图标,修改软件名、包名什么的,用这个插件可以很方便的解决。

但据我的测试,React项目使用这个插件的实时热重载是有问题的。

实机实时调试

上面套壳的一通操作,是对dist目录里面已经编译的东西进行操作。

但万一我程序里要写陀螺仪、GPS之类的传感器设备,这些东西在电脑浏览器上是不能调试的,我要一遍又一遍往手机上编译吗?

先编译Web,再套壳,然后再编译APP,再安装,这一通操作实在不优雅。

这就需要在手机上实机调试啦。

VSCode插件提供的似乎存在问题,如果你和我一样存在问题,或者无法提供一个稳定的网络环境,那么参考下面的方法。

问题发生的原因是,插件执行两条命令,第一条编译APK安装,第二条打开开发服务器,但是第一条完成之后不退出,提示开发服务器已启动,但实际上并没有启动,第二条始终不执行。

而且,它要求手机和电脑必须同一局域网下,电脑也不能有防火墙阻止什么的。

下面是解决问题的方法:

既然是安卓开发,ADB肯定是要提前连好啦,接下来假定ADB已经连好啦。( •̀ ω •́ )✧

安装APP

首先第一个问题,它第一条命令不结束,那我们就手动执行嘛。

这一条命令带了参数--live-reload实测,会阻塞,但不开服务器:

npx cap run android --no-sync --port=3000 --host=127.0.0.1 --live-reload

这样会编译安装APP到手机上,并且这个APP会给http://127.0.0.1:3000套壳。

但APP是在手机上跑的,而开发服务器开在电脑上,所以,需要一个手段,上手机上的3000也是开发服务器。

ADB端口转发

ADB是一个相当强大的工具,在端口转发这一块,它支持两种。

  • forward 前向 服务器在手机上

  • reverse 反向 服务器在电脑上

用法:adb <forward/reverse> <源> <目标>

将在源上创建服务器,转发到目标。

(当然这里不仅支持tcp的转发,还有其他的)

使用以下命令在安卓端创建一个将流量转发到电脑端的服务器

adb reverse tcp:3000 tcp:3000

一键化的脚本

package.jsonscripts中添加下面这样一条:

{
  "android": "start react-scripts start & adb reverse tcp:3000 tcp:3000 & npx cap run android --no-sync --port=3000 --host=127.0.0.1 --live-reload"
}

以后就直接npm run android就好啦

Vite的一个小问题

如果你的前端项目是vite写的,它默认的监听地址可能是localhost:5173 ,据测试,这个地址不等于127.0.0.1:5173 ,端口转发时会出问题。我不知道为什么X_X

这里需要修改vite.config.ts ,设置server.host"0.0.0.0"

总结

咱也是能写出来好看移动端软件的人啦 ✧◝(⁰▿⁰)◜✧

我能想到的,最大的成功就是无愧于自己的心。