0.前言
前几天看大佬给自己网站套了一个APP,看起来很有意思,于是决定自己也整一个。由于自己比较菜,整出来的肯定不如大佬好。
实际上套壳APP并不复杂,实际上是利用Android系统的webview来展示网页,所以首先有一个可以在手机浏览器端工作良好的网页可以套,这里我套的是https://m.dogcraft.top,misskey对移动端的适配确实不错,平时在手机端上都是直接那Firefox
浏览的。
开发Android套壳应用有很多途径,既可以用原生的Android工具链直接用Java
或者Kotlin
来安排,也可以利用RN这样的框架来安排,还可以利用其他的生成器之类的。这些方式各有利弊,原生Android工具链需要用Java或kotlin,这个都不会啊,用第三方的生成器没有灵魂,而且存在安全性的问题,最后决定用React Native,这个是用JavaScript的,之前JavaScript好歹会一点点后来的事实证明会的这一点点完全没有卵用 ( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
实践证明利用RN搞套壳应用还是很快的,仅仅用了两天的时间就整了个勉强能用的套壳APP(其中多半天在配置Android开发环境,多半天在画启动图)。
零基础的解释:从零搭建Android开发环境、从零开始用React
、完全不会kotlin
或Java
、不懂ES6
1.配置开发环境
搭建环境难,是所有步骤里面最难的一部分,可以按照文档里的Android开发环境搭建来安排,上面的一些说法可能有些过时了,具体的内容要根据实际的开发环境来安排。比如Android Studio的安装,实际上在国内(我这里)是完全可以正常下载的,不需要用什么奇奇怪怪的工具,而且用ubuntu的可以直接通过snap
来安装。
$ snap list android-studio
Name Version Rev Tracking Publisher Notes
android-studio 4.0.1.0 91 latest/stable snapcrafters classic
下面是几个文档上没提到的注意事项
在Android Studio内安装各种组件的时候可以用内置的自动化代理来提速,在设置里面就有,仔细找一找很容易找得到,我是用的mirrors.neusoft.edu.cn:80
这一个代理,速度很快。
还有不要忘记安装安装react-native-cli
我就是所有都搞完了最后运行react-native start
的时候说找不到命令……
sudo cnpm install -g react-native-cli
还有就是yarn可以换成淘宝镜像来提速
yarn config set registry http://registry.npm.taobao.org/
如果连接Android设备调试的时候遇到adb版本问题,可以尝试卸载之前自行安装的adb工具(如果有的话)
实践证明,如果手机开了USB调试,直接插上usb数据线就行了,用不到改udev
那一套东西,如果连不上开发服务器,很有可能是adb版本的问题。正确的版本应该在随着Android studio
安装的Android SDK
里面。
第一次运行yarn react-native run-android
会特别慢,也是整个过程中最艰难的环节之一。运行之前记得安装手机,手机上显示通过usb安装应用的时候要及时点击同意。
如果一切正常手机上就会有应用了。
最后就是不要忘了运行react-native start
,否则会手机端红屏报错。
2.安排webview
webview要安装一个react-native-webview
。
yarn add react-native-webview
react-native link react-native-webview
然后在App.js
里面引入这个东西。
import {WebView} from 'react-native-webview';
最后安排在渲染界面的地方。
<View style=
flex>
<WebView
source= uri
style= width
ref="webView"
onNavigationStateChange={this.onNavigationStateChange}
/>
</View>
其中onNavigationStateChange={this.onNavigationStateChange
是为了解决返回问题的。
如果一切正常,运行yarn react-native run-android
之后应该可以正常使用了,然而会面临一个问题,在手机上按下返回键的时候会直接退出应用而不是回到网页的上一层。这个问题网上已经有了成熟的解决方案,多试几次应该会解决。
import React, {Component} from 'react';
import {
StyleSheet,
View,
Text,
TouchableOpacity,
Linking,
Alert,
Button,
ToastAndroid
} from 'react-native'
import SplashScreen from 'react-native-splash-screen';
import { Platform, BackHandler } from 'react-native';
import {WebView} from 'react-native-webview';
export default class example extends Component {
componentDidMount() {
setTimeout(SplashScreen.hide,2000)
if (Platform.OS === 'android') {
BackHandler.addEventListener('hardwareBackPress', this.onBackAndroid);
}
}
onNavigationStateChange = navState => {
this.setState({
backButtonEnabled: navState.canGoBack
});
};
reloaddog =() =>{
this.refs['webView'].reload();
}
onBackAndroid = () => {
// 官网中描述:backButtonEnabled: false,表示webView中没有返回事件,为true则表示该webView有回退事件
if (this.state.backButtonEnabled) {
this.refs['webView'].goBack();
return true;
} else {
if (this.lastBackPressed && this.lastBackPressed + 2000 >= Date.now()) {
//最近2秒内按过back键,可以退出应用。
return false;
}
this.lastBackPressed = Date.now();
ToastAndroid.show('再按一次退出应用', ToastAndroid.SHORT);
return true;
}
};
render() {
return (
<View style=
flex>
<WebView
source= uri
style= width
ref="webView"
onNavigationStateChange={this.onNavigationStateChange}
/>
</View>
)
}
}
3.添加APP启动图
这一步骤比较麻烦了,这涉及到Java部分了,而且安装也比较麻烦。
启动图的安装与配置比较麻烦,而且相关说明与现实情况出现了较大的偏离,不过可以根据给出的例子对照自己的项目一点点的摸索。
yarn add react-native-splash-screen
react-native link react-native-splash-screen
运行完 react-native link react-native-splash-screen
还要再改好几个地方,按照上面所说的继续安排下去会报错的。
要改的几个地方(包括但不限于)
在MainActivity.java
里面加上这个
@Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen.show(this); // here
super.onCreate(savedInstanceState);
}
还要看一下几个java文件里面有没有import org.devio.rn.splashscreen.SplashScreen;
实际上确保`里面有
import org.devio.rn.splashscreen.SplashScreenReactPackage;之后不需要往
MainApplication.java`里面添加任何东西了。
然后在android/app/src/main/res/layout/launch_screen.xml
里面设置启动布局。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="#F0F0F0" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/launch_screen" />
</LinearLayout>
把图片放到android/app/src/main/res/drawable-xxhdpi/launch_screen.png
和android/app/src/main/res/drawable-xhdpi/launch_screen.png
里面。样式在android/app/src/main/res/layout/launch_screen.xml
里面调整。
4.改图标名称以及版本号
名称在android/app/src/main/res/values/strings.xml
里面改。
包名称以及版本号在android/app/build.gradle
里面
defaultConfig {
applicationId "cn.dogcraft.apk"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.1"
}
图标在android/app/src/main/res
使用生成工具直接替换就行,我是用的这一个https://icon.wuruihong.com/。
这个启动图要收费的,没必要,自己画一个就完事了。
5.打包apk
按照说明一步一步来就行了。
就是android/app/build.gradle
这里改的的东西不好找
android {
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "cn.dogcraft.apk"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.1"
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}
}
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
}
}
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
6.效果展示
APP 下载地址