Solo  当前访客:1 开始使用

布丁与画家的博客

努力改变一小部分人解决问题的方式

ReactNative:0.6从入坑到打包APK到发布@布谷老人语音天气

2020-03-18 20:32:08 iwh718
0  评论    0  浏览

最近买了一本书,ReactNative开发原生应用,以前都是直接使用Kotlin开发,但是感觉最近一直写JS,不如用JS开发
吧,然后就边看书边开发了,写了一个简单的语音天气APP,基本上该遇到的坑和功能都使用了,tips:应用很小,所以没有使用Redux.

ReactNative和一些套壳的框架相比好多了,编译后是原生的代码,这个就是很有意思了,还能和原生混合开发.

布谷天气酷安下载:https://www.coolapk.com/apk/com.qiuguo.studio

前排提示一个很坑的问题:RN0.6开始拆分了特定平台的组件到公共库里了,比如android的Toolbar,你直接在React-native引入是没用的.需要专门安装,一会会提到.

看看成品吧,会在酷安上架哦,我的酷安ID:IWH暖

null

本文总的结构如下:

1.安装RN环境并解决一些坑

2.开始编写android应用并使用android特定的组件

3.打包APK,精简体积,签名,发布应用.

1.准备开发环境

安装RN脚手架

yarn global add react-native-cli

null

创建项目

react-native init demo 

null

如果创建项目特别慢,甚至出现网络超时,更换yarn源

yarn config set registry https://registry.npm.taobao.org -g

yarn config set sass_binary_site http://cdn.npm.taobao.org/dist/node-sass -g


null

启动项目,报错没有命令的,查看自己是否全局安装了.

react-native run-android

null

为了预览与调试,你需要一个模拟器,我这里是直接用的android手机开启USB调试.

使用 ADB devices 看看有没有你的设备.

如果你没有安装android的SDK工具,会报错,你要安装好SDK(如果你用了androidStudio,那么进入demo项目的android目录

项目android/local.properties  
追加 sdk.dir = /sdk目录 linux /home/userName/android...

如果你遇到license错误

android 许可错误  
进入sdk目录的 Sdk/tools/bin 执行 ./sdkmanager --licenses 同意许可...

建议也检查以下你的bash配置,尤其是用ZSH的同学..

nano ~/.bash_profile

export ANDROID_HOME=/home/qiuguo/Android/Sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/platform-tools/adb

null

如果手机设备出现 服务连接失败,一般都是没启动服务

项目根目录 yarn start 即可,注意默认端口8081不要被其他应用用了.或者你可以摇晃设备弹出调试菜单,手动更改ip与地址,然后

adb reverse tcp:8081 tcp:8081 来自定义

如果你遇到资源文件出错,或者未找到,执行以下命令

react-native bundle --platform android --dev false --entry-file index.js  --bundle-output android/app/sr
c/main/assets/index.android.bundle  --assets-dest android/app/src/main/res/

null

既然可以预览了,那我们开始编写应用了.

编写前,其实我画了一个简单的原型图

查看原型演示:布谷天气墨刀原型演示

2.开始编写

这里不会讲解React如何编写,只说说RN的东西

看一下初始化的项目的结构:其中Android是RN编译后的原生目录

看到有 APP.js Index.js 这两个是入口文件,其他的和平时一样,自己创建组件目录或者资源目录就行了和web开发一样.

null

看看index.js这是入口,其中registerComponent()是不是很熟悉,和web开发里面.APP是我们的最外层组件

/**
 * @format
 */

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);

null

看看 APP.js

import React from 'react';
//style.js 是一个json格式的css样式
import {APP_STYLE} from './styles';
//导入常用组件
import {
    SafeAreaView,
    StyleSheet,
    ScrollView,
    Modal,
    ToastAndroid,
    View,

    Animated,
    TouchableNativeFeedback,
    Touchable,
    RefreshControl,
    TouchableHighlight,
    Image,
    Text,
    NativeEventEmitter,
    StatusBar,
} from 'react-native';

//这里是初始化项目自带的引导组件,你可以删除掉
import {
    Header,
    LearnMoreLinks,
    Colors,
    DebugInstructions,
    ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';

//组件
class App extends React.Component {

    state = {
        isSpeaching: false,
        helpStatus: false,
        refresh:false,
        voiceText: '',
        //是否选择地区
        isSelect: false,
        //语音状态
        voiceHide: true,
        //天气信息
        weatherData: {},
    };
    ....
    ....
    //样式使用styles
    render(){
        return(
                //你也可以直接使用行内写法
              <View style={styles.weatherBox}>
        )
    }

    
}
//创建样式表对象
const styles = StyleSheet.create(APP_STYLE);
export default App;

null

APP_STYLE.js 样式表

const APP_STYLE ={

    weatherBig: {
        fontSize: 70,
        marginTop: 30,
        marginLeft: 30,
        zIndex: 99

    }
}

null

1.你应该注意到了,全是驼峰写法,格式是json格式,这里有一个可能会遇到的困惑,就是 层级显示,用两个:Zindex和Elevation在android里面.

其中 elevation优先.这个也是原生Android里面的z方向,会出现阴影,具体css你可以去RN官方文档查看哦,这里提一下默认的布局,你可以使用position为relative和absolute,不可以用fixed,还有就是RN的基础组件,如View这个组件,都是使用Flexbox,但是又有区别,比如,你想让子组件填充父组件,设置父组件 Flex:1 就行了.其他属性比如width支持百分比,记得加引号.

2.样式基本了解后,我们看看如何编写事件

和web有区别的是你需要在以下的组件内部编写按压事件

 TouchableNativeFeedback
 Touchable
 TouchableHighlight

null

 <TouchableHighlight onPress={this.props.closeHelp}>
                            <Text style={{marginTop: 20, color: '#BA1904',fontSize:20}}>关闭说明书</Text>
                        </TouchableHighlight>

null

3.引入公共组件,看原型,好像我们用到了一个toolbar组件,如果你在React-native引入,会发现,无法使用,百度一圈,都是从rn包导入,那都是旧的版本,新版本你需要额外安装新的toolbar包

facebook公共组件仓库 这里有额外的所有包,如video,netInfo等,这里演示一个toolbar,如果你的RN是0.6 不需要使用link ,网上说link是旧版的.

yarn add @react-native-community/toolbar-android

null

然后就可以愉快的使用了.

 <ToolbarAndroid
                        style={{ height: 50, backgroundColor: '#fff', color: '#000',elevation:2}}
                        actions={[{
                            title: '说明书',
                            icon: require('./res/images/help2.png'),
                            show: 'always',
                            showWithText: true,
                        },
                            {title: '关于', icon: require('./icon.png'), show: 'never'}]}
                        onActionSelected={this.onActionSelected.bind(this)}>
                        <Image source={require('./icon.png')} style={{width: 40, height: 30}}/>
                        <Text>布谷天气语音版</Text>
                    </ToolbarAndroid>

null

  1. 使用Gif与图片资源

上面的代码里会发现用的 require().这里提一下一个坑,RN不支持路径使用动态拼接,也就是说你没有办法使用变量拼接!

然后我们处理GIF的问题

进入android/app/目录 找到 gradle文件 在dependencis 添加依赖

implementation 'com.facebook.fresco:animated-gif:2.0.0'

null

一些小伙伴发现图片不动,升级你的依赖,网上很多都是旧的..

5.使用权限管理

android有一些权限是需要申请使用的,fb也提供了在上面的公共库里哦,用法,这里不说了,提一句就是,没开发过Android的小伙伴经常会忘记在manifest文件声明权限!

6.使用存储

如果你用AsyncStorage 会遇到警告,因为它也被剥离出来了,你需要专门安装哦

这里是一个封装片段

 async setData(key,value){
        try{
            await AsyncStorage.setItem(key,value);
            console.log('保存数据成功.')
            return  true;
        }catch (e) {
            console.log('保存错误:' + e)
            return false;
        }
    },

null

7.使用网络

RN使用默认支持Fetch,你也可以用axios,不过很遗憾jQuery不可以,因为它有涉及DOM的功能...

注意RN不存在跨域的,你可以看看postman就知道了.

8.动画 等有空再写.

3.打包

下面说说最重要的一项,打包APK出来,因为主要是说说遇到的错误,至于如何生成你的开发者秘钥,请自行百度哦,因为我以前用AndroidStudio开发应用,所以有一个jks的文件,如果你用的命令行创建会有好几个文件.

配置你的秘钥,进入android/app/gradle.properties 设置几个变量,一会要用到的.jks文件也是在同级目录


android.useAndroidX=true
android.enableJetifier=true
MYAPP_RELEASE_STORE_FILE=xxx.jks
MYAPP_RELEASE_KEY_ALIAS=xx
MYAPP_RELEASE_STORE_PASSWORD=xx
MYAPP_RELEASE_KEY_PASSWORD=xxx

null

然后修改构建文件

android/app/build.gradle

找到这个块,替换

signingConfigs {
        release {
            storeFile file(MYAPP_RELEASE_STORE_FILE)
            storePassword MYAPP_RELEASE_STORE_PASSWORD
            keyAlias MYAPP_RELEASE_KEY_ALIAS
            keyPassword MYAPP_RELEASE_KEY_PASSWORD
        }
    }

null

然后进入android根目录

执行./gradlew assembleRelease

Rn打包的时候,会经常遇到以下错误,资源文件重复,部分依赖包出错(比如本应用使用的讯飞语音SDK,由于gradle不兼容,总是报错),正常来说,打包后,资源文件重复,要么是你的资源文件重名了,要么就是你打包之前,没有clean build后的项目.

资源文件重复后,如果你执行了clean也是一样,手动把app/build/genera... 删除

进入 android目录执行 ./gradlew clean 清理项目,再次 ./gradlew assembleRelease 构建APK

当你打包后,你会发现,安装包非常大,不到1000行的代码有30M,因为RN默认打包了全平台版本,你可以自己选择是否支持其他平台

我们修改一下 gradle文件 我只保留了arm架构版本,不过也生成一个通用的安装包,单独版本的大小现在是10M左右

def enableSeparateBuildPerCPUArchitecture = true
...

splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk true  // If true, also generate a universal APK
            include "armeabi-v7a","arm64-v8a"
        }
    }
...
 universalApk true

null

最后最重要的提示就是:一定要看清楚自己的RM版本,构建APK失败,先Clean一下,如果是第三方SDK可以去看看依赖包的gradle...

...等待更新

公众号:秋果科技工作室

酷安ID:IWH暖 来玩啊

null


标题:ReactNative:0.6从入坑到打包APK到发布@布谷老人语音天气
作者:iwh718
地址:看看我的CSDN

web站点:骇客猫科技资讯
, , ,



今日诗词
QQ交流群:914105779

目录

TOP