react-native 从0.57.4升级到0.61.0之后遇

2020-01-02  本文已影响0人  程序猿isMe

1.react-native 升级到0.61.0,react-native-bottomsheet 库报了

ERROR: Unable to resolve dependency for ':rnspace@debug/compileClasspath': Failed to transform file 'bottomsheet-1.3.1.aar' to match attributes {artifactType=processed-aar} using transform JetifyTransform
这个错误
是由于react-native-bottomsheet也升级到适配androidX的时候,在rnspace库里面的build.gradle -> implementation 'com.cocosw:bottomsheet:1.3.1'对应的版本不对导致的。

解决办法

把版本升级到implementation 'com.cocosw:bottomsheet:1.5.0',才适配androidX

2 ERROR: Manifest merger failed with multiple errors, see logs

看了一下报错是在baidumap里
解决办法

1.打开AndroidStudio底部的Terminal, 执行
    ./gradlew processReleaseManifest --stacktrace
     (windows下,应该是gradlew processReleaseManifest --stacktrace)
看具体报错原因


./gradlew -q app:dependencies   
   查看冲突文件

3 错误:android.support.annotation 找不到 react-native-gesture-handler

react-native-gesture-handler 涉及AndroidX

解决办法

"scripts": {
   ...
    "postinstall": "npx jetify"
  },

然后运行一下

4 错误:java.lang.UnsatisfiedLinkError:couldn't find DSO to load: libhermes.so

解决办法在 app/build.gradle中添加如下

apply plugin: "com.android.application"

project.ext.react = [
    entryFile: "index.js",
    enableHermes: true,  // clean and rebuild if changing
]

/**
 * The preferred build flavor of JavaScriptCore.
 *
 * For example, to use the international variant, you can use:
 * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
 *
 * The international variant includes ICU i18n library and necessary data
 * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
 * give correct results when using with locales other than en-US.  Note that
 * this variant is about 6MiB larger per architecture than default.
 */
def jscFlavor = 'org.webkit:android-jsc:+'

/**
 * Whether to enable the Hermes VM.
 *
 * This should be set on project.ext.react and mirrored here.  If it is not set
 * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
 * and the benefits of using Hermes will therefore be sharply reduced.
 */
def enableHermes = project.ext.react.get("enableHermes", false);

android {
    compileSdkVersion 28

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        applicationId "com.test.lk"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
    }
    signingConfigs {
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.debug
        }
        release {
            signingConfig signingConfigs.releaseConfig
            minifyEnabled false
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }
  }

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "com.facebook.react:react-native:+"  // From node_modules

    if (enableHermes) {
      def hermesPath = "../../node_modules/hermes-engine/android/"
      debugImplementation files(hermesPath + "hermes-debug.aar")
      releaseImplementation files(hermesPath + "hermes-release.aar")
    } else {
      implementation jscFlavor
    }
}

5 WebView 从react-native 替换成react-native-webview之后postMessage发送不出去

主要是因为框架修改了,如果您希望在升级时与旧版本保持兼容性,则可以使用注入Javascript支持进行此操作,解决方法来自:
https://github.com/react-native-community/react-native-webview/releases/tag/v5.0.0

import React from 'react'
import {SafeAreaView, Text, TouchableOpacity, View} from 'react-native';
import {WebView} from 'react-native-webview';
import {connect} from "react-redux";
import {mapHosts} from "../../Config/Environment";
import geolocation from '@react-native-community/geolocation';


let location = {};

class SelectMapScreen extends React.Component {
    _watchID;
    static navigationOptions = ({navigation}) => ({
        headerTitle: '位置',
        headerRight: null
    });

    componentWillUnmount() {
        geolocation.clearWatch(this._watchID);
    }


    render() {
        let {dispatch} = this.props;
        let mapURl = mapHosts() + "map.html";
        return (
            <SafeAreaView style={{flex: 1, backgroundColor: '#ffffff'}}>
                <WebView
                    ref={"webview"}
                    style={[{flex: 1, backgroundColor: '#ffffff'}]}
                    source={{uri: mapURl, headers: { 'Cache-Control':'no-cache'}}}
                    javaScriptEnabled
                    injectedJavaScript={injectedJavascript}
                    onLoad={()=>{
                        this._watchID = geolocation.watchPosition((position) => {
                            let lastPosition = JSON.stringify(position);
                            console.log("initialPosition:" +lastPosition)
                            this.refs.webview.postMessage(JSON.stringify({
                                cmd: 'location',
                                data: {lat: position.coords.latitude, lng: position.coords.longitude}
                            }))
                        }, (error) => {
                            alert(error.message)
                        })
                    }}
                    onMessage={(event) => {
                        console.log("---event--", event);
                        const data = JSON.parse(event.nativeEvent.data);
                        console.log("---data--", data);
                        switch (data.cmd) {
                            case "location": {
                                location = data.data;
                                break;
                            }
                            default: {
                                break;
                            }
                        }

                    }}

                />
            </SafeAreaView>

        )
    }
}


const props = (state) => {
    return {}
};
export default connect(props)(SelectMapScreen)

const injectedJavascript = `(function() {
  window.postMessage = function(data) {
    window.ReactNativeWebView.postMessage(data);
  };
})()`;

5 Error: Unable to resolve module react-navigation/src/NavigationActions from app\Screen\Home\BackLogCaseScreen\Action.js

这个问题是因为引用的改变
之前的引用是 import NavigationActions from "react-navigation/src/NavigationActions";
需要改成 import NavigationActions from "react-navigation";

6 createBottomTabNavigator() has been moved to react-navigation-tabs

升级到0.61.0之后引用变了
之前的引用是 import {createBottomTabNavigator,} from 'react-navigation';
需要改成 import {createBottomTabNavigator} from 'react-navigation-tabs';

7 createStackNavigator() has been moved to react-navigation-stack

升级到0.61.0之后引用变了
之前的引用是 import {createStackNavigator} from "react-navigation";
需要改成 import {createStackNavigator} from "react-navigation-stack";

8 TypeError: Cannot read property 'routeName' of null

在我这是因为升级后
const initialState = RootModalNavigation.router.getStateForAction(RootModalNavigation.router.getActionForPathAndParams());这个里面修改了
得改成const initialState = RootModalNavigation.router.getStateForAction(RootModalNavigation.router.getActionForPathAndParams('Main'));
'Main'写什么都可以

9 TypeError: navStateSelector is not a function

我这是因为
export const navigationMiddleware = createReactNavigationReduxMiddleware(
"root",
state => state.nav,
);
改成
export const navigationMiddleware = createReactNavigationReduxMiddleware(
state => state.nav,
"root",
);

10 Error: There is no route defined for key LoginScreen.

错误原因
const resetAction = StackActions.reset({
                    index: 0,
                    actions: [NavigationActions.navigate({routeName: 'LoginScreen'})]
                });
                navigation.dispatch(resetAction);

经过github上搜索发现,需要添加  key: undefined,
     const resetAction = StackActions.reset({
                    index: 0,
                    key: undefined,
                    actions: [NavigationActions.navigate({routeName: 'LoginScreen'})]
                });
                navigation.dispatch(resetAction);

11 redux-persist failed to create sync storage. falling back to noop storage.

是在redux的存储有了变化
之前是:

import {applyMiddleware, createStore} from 'redux';
import thunkMiddleware from 'redux-thunk'
import {persistCombineReducers, persistStore} from 'redux-persist'
import storage from 'redux-persist/es/storage'
import {navigationMiddleware} from "../Navigation/Reducer";
import {rootReducers} from "../Reducer/RootReducer";
import {composeWithDevTools} from 'redux-devtools-extension';


const middleWares = [
    navigationMiddleware,
    thunkMiddleware
];

const config = {
    key: 'root',
    storage,
    whitelist: ['onSaveLoginInfo','onRequestStaticHeader'],
    debug: false
};

const reducers = persistCombineReducers(config, rootReducers);
const enhances = [applyMiddleware(...middleWares)];
let store;

export const configState = (initialState) => {
    store = createStore(reducers, initialState, composeWithDevTools(...enhances));

    persistStore(store);
    return store
};

export const getStore = () => {

    return store;
};

我们需要将import storage from 'redux-persist/es/storage'去掉,换成import AsyncStorage from '@react-native-community/async-storage'; 最终是

import {applyMiddleware, createStore} from 'redux';
import thunkMiddleware from 'redux-thunk'
import {persistCombineReducers, persistStore} from 'redux-persist'
import AsyncStorage from '@react-native-community/async-storage';
import {navigationMiddleware} from "../Navigation/Reducer";
import {rootReducers} from "../Reducer/RootReducer";
import {composeWithDevTools} from 'redux-devtools-extension';


const middleWares = [
    navigationMiddleware,
    thunkMiddleware
];

const config = {
    key: 'root',
    storage: AsyncStorage,
    whitelist: ['onSaveLoginInfo','onRequestStaticHeader'],
    debug: false
};

const reducers = persistCombineReducers(config, rootReducers);
const enhances = [applyMiddleware(...middleWares)];
let store;

export const configState = (initialState) => {
    store = createStore(reducers, initialState, composeWithDevTools(...enhances));

    persistStore(store);
    return store
};

export const getStore = () => {

    return store;
};

12 Invariant Violation: Could not find "store" in the context of "Connect(TabBarComponent)". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(TabBarComponent) in connect options.

是因为之前的connect 是 import connect from "react-redux/es/connect/connect";引用的,所以报错
现在需要改成import {connect} from "react-redux";

13 Invariant Violation: [715,"RCTView",181,{"width":0,"height":"<<NaN>>","backgroundColor":0}] is not usable as a native method argument

是因为react-native-page-scrollview
在更新到新版本后不适配,可以参考https://github.com/geek-prince/react-native-page-scrollview/issues/9

14 WebView has been removed from React Native. It can now be installed and imported from 'react-native-webview' instead of 'react-native'.

在升级到0.61.0后webview被拆分出去了,引用不能用import {WebView} from "react-native";
修改成 import {WebView} from 'react-native-webview';

15 权限

import {request, PERMISSIONS, RESULTS} from 'react-native-permissions';
import { Platform } from 'react-native'

export const PermissionType = {
    Photo: Platform.OS === 'android' ? PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE : PERMISSIONS.IOS.PHOTO_LIBRARY, // 相册
    Camera: Platform.OS === 'android' ? PERMISSIONS.ANDROID.CAMERA : PERMISSIONS.IOS.CAMERA, // 相机
    Location: Platform.OS === 'android' ? PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION : PERMISSIONS.IOS.LOCATION_WHEN_IN_USE, // 定位
    Storage:  Platform.OS === 'android' ? PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE : "",           // 读写权限

    Notification: 'notification', // 推送
    CallPhone: Platform.OS === 'android' ? PERMISSIONS.ANDROID.CALL_PHONE : ""
};

export const CheckPermission = (type) => new Promise(function (resolve, reject) {
    request(type)
        .then(result => {
            console.log("--------", result)
            switch (result) {
                case RESULTS.UNAVAILABLE:
                    console.log('This feature is not available (on this device / in this context)');
                    break;
                case RESULTS.DENIED:
                    console.log('The permission has not been requested / is denied but requestable');
                    reject(new Error(message(type)));
                    break;
                case RESULTS.GRANTED:     // 授予
                    console.log('The permission is granted');
                    resolve(result);
                    break;
                case RESULTS.BLOCKED:
                    console.log('The permission is denied and not requestable anymore');
                    reject(new Error(message(type)));
                    break;
            }
        })
        .catch(err => {
            reject(err);
        })
});

export const CheckMultiple = () => new Promise(function (resolve, reject) {
    let permission1 = CheckPermission(PermissionType.CallPhone);
    let permission2 = CheckPermission(PermissionType.Location);
    let permission3 = CheckPermission(PermissionType.Storage);
    Promise.all([permission1,permission2,permission3]).then((res)=>{
        resolve(res)
    }).catch(e=>{
        reject(new Error(message(PermissionType.CallPhone)+message(PermissionType.Location)+message(PermissionType.Storage)));
    })
});


const message = (type) => {
    switch (type) {
        case PermissionType.Photo:
            return '应用需要使用您的相册,请前往设置去开启相册权限';
        case PermissionType.Camera:
            return '应用需要使用您的相机,请前往设置去开启相机权限';
        case PermissionType.Location:
            return '应用需要使用您的位置,请前往设置去开启定位权限';
        case PermissionType.Storage:
            return '应用需要使用您的读写权限,请前往设置去开启读写权限';
        default:
            return null;
    }
};

16 解决Android Studio提示:安装包有异常,无法安装

问题描述:在使用Android Studio运行程序时,手机为oppo手机,遇到安装失败,在其他手机上安装正常,经查询后发现Android Studio 3.0会在debug apk的manifest文件application标签里自动添加 android:testOnly="true"属性。
该属性导致在IDE中使用Run生成的apk在大部分手机上只能用adb install -t 来安装。
这种apk在oppo手机上甚至安装不了。

解决办法是

在gradle.properties 文件中添加如下指令:

android.injected.testOnly=false

在运行安装,好使

17 程序正常安装debug模式,服务的ip和端口号输入后却链接不上服务

Screenshot_2020-04-10-16-35-08-40.png

原来9.0系统已经默认不支持http请求了,谷歌默认要求链接是加密链接了
解决方案:
在res目录添加一个xml文件夹,新建一个network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<!--Android 9.0 https请求适配-->
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>

然后在AndroidManifest.xml清单文件上加入

 <application
        android:name=""
        android:icon="@drawable/logo_icon"
        android:label="@string/app_name"
        android:roundIcon="@drawable/logo_icon"
        android:theme="@style/AppTheme"
        android:networkSecurityConfig="@xml/network_security_config"
       > 
 </application>

由于工作原因只记录了,其中一部分的问题,其他的根据提示相信各位也能很好的解决,谢谢大家!!

上一篇下一篇

猜你喜欢

热点阅读