在使用 MapView 和 Google 地图时,我应该怎样做才能防止应用程序崩溃?

问题描述 投票:0回答:1

嗨,我正在学习 React Native 并使用 expo go。

我想通过 MapView 和 Google Maps API 显示地图。 并且用模拟器测试也没有出现错误。 但是转换成apk文件后出现错误。 每当我尝试打开地图页面时它就会停止。

我正在搜索所有文档,但找不到解决我的问题的方法。

下面是我的页面的完整代码,其中有mapView。

import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, Pressable } from 'react-native';

import { PROVIDER_GOOGLE, Marker } from 'react-native-maps';
import MapView from 'react-native-maps';

import Header from '../components/fixed/Header';

import Colors from "../constants/Colors";
import { getSafeContentHeight } from '../constants/DeviceSize';
import deviceSize from "../constants/DeviceSize";

const deviceWidth = deviceSize.deviceWidth;
const deviceHeight = deviceSize.deviceHeight;

export default function MapPush({ navigation, route }) {

  const { myLocation } = route.params;

  const [safeContentHeight, safeContentHeightWithoutNav] = getSafeContentHeight();


  const [pressedMarkerInfo, setPressedMarkerInfo] = useState(null);

  const [isModalOpen, setIsModalOpen] = useState(false);

  return (
    <View style={{ width: deviceWidth, height: safeContentHeightWithoutNav, paddingTop: 50 }}>
      <Header title="홍대입구역 9번출구" isPush={true} navigation={navigation} />
      <MapView
        style={{ width: '100%', height: '100%' }}
        region={{
          latitude: 37.55604312175928,
          longitude: 126.92299623955266,
          latitudeDelta: 0.01827,
          longitudeDelta: 0.01198
        }}
        initialRegion={{
          latitude: 37.55604312175928,
          longitude: 126.92299623955266,
          latitudeDelta: 0.01827,
          longitudeDelta: 0.01198
        }}
        minZoomLevel={12}
        maxZoomLevel={20}
        showsUserLocation={true}
        showsMyLocationButton={true}
        provider={PROVIDER_GOOGLE}
      >
      <Marker
        coordinate={{
          latitude: 37.55604312175928,
          longitude: 126.92299623955266,
        }}
        pinColor="red"
        onPress={() => {
          setIsModalOpen(true)
        }}
      >
        <View style={[
          styles.markerContainer,
        ]}>
          <Text
            style={[
              styles.markerText,
            ]}
          >
            홍대입구역 9번출구
          </Text>
          
        </View>
        <View 
          style={[
            styles.markerTriangle,
          ]}
        />
      </Marker>
      </MapView>
    </View>
  )
};

const styles = StyleSheet.create({
  container: {},
  markerContainer: {
    position: 'relative',
    backgroundColor: Colors.white,
    paddingHorizontal: 10,
    paddingVertical: 7,
    borderRadius: 30,
    borderWidth: 1,
    borderColor: Colors.cool_gray2
  },
  markerText: {
    fontFamily: 'GothicA1-Bold',
    fontSize: deviceWidth / 400 * 16.5, 
    lineHeight: deviceWidth / 400 * 17.5, 
    color: Colors.cool_gray5
  },
  markerTriangle: {
    alignSelf: 'center',
    width: 0,
    height: 0,
    // borderWidth: 8,
    borderColor: 'transparent',
    borderTopColor: Colors.cool_gray2,
    borderWidth: 13,
    marginTop: -1
  },
})

我还会将 App.js 和其他导入的组件放入 MapPush 中

import React, { useEffect, useRef, useState } from "react";
import { View } from 'react-native';
import { useFonts } from 'expo-font';
// import LottieView from "lottie-react-native";
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator();



import PinUp from "./src/components/animations/PinUp";
// import LogIn from "./src/screens/LogIn";

import NavBar from './src/components/fixed/NavBar';

import Home from './src/screens/Home';
import PinDetail from './src/screens/PinDetail';
import MapPush from "./src/screens/MapView";

import Records from './src/screens/Records';

import FindPin from './src/screens/FindPin';
import MakePin from "./src/screens/MakePin";
import Search from './src/screens/Search';
import SearchMap from "./src/screens/SearchMap";
import MakePinSearch from "./src/screens/makePinSearch";
import Map from "./src/screens/Map";

import Invites from './src/screens/Invites';
import FriendRequest from './src/screens/FriendRequest';

import MyBoard from './src/screens/MyBoard';
import OthersBoard from './src/screens/OthersBoard';
import Settings from './src/screens/Settings';
import ProfileSetting from "./src/screens/ProfileSetting";

import Notice from './src/screens/Notice';

import KaKaoLogin from "./src/screens/KakaoLogin";



import { getLocationPermissionHandler } from "./src/expoSDK/expoLocation";

import Colors from './src/constants/Colors';
import deviceSize from "./src/constants/DeviceSize";
import LogIn from "./src/screens/LogIn";

const deviceWidth = deviceSize.deviceWidth;
const deviceHeight = deviceSize.deviceHeight;


export default function App() {

  let [fontsLoaded] = useFonts({
    'GothicA1-Thin': require('./assets/fonts/GothicA1-Thin.ttf'),
    'GothicA1-ExtraLight': require('./assets/fonts/GothicA1-ExtraLight.ttf'),
    'GothicA1-Light': require('./assets/fonts/GothicA1-Light.ttf'),
    'GothicA1-Regular': require('./assets/fonts/GothicA1-Regular.ttf'),
    'GothicA1-Medium': require('./assets/fonts/GothicA1-Medium.ttf'),
    'GothicA1-SemiBold': require('./assets/fonts/GothicA1-SemiBold.ttf'),
    'GothicA1-Bold': require('./assets/fonts/GothicA1-Bold.ttf'),
    'GothicA1-ExtraBold': require('./assets/fonts/GothicA1-ExtraBold.ttf'),
    'GothicA1-Black': require('./assets/fonts/GothicA1-Black.ttf'),
  });


  // const animationRef = useRef<LottieView>(null);

  const [login, setLogin] = useState(false);

  const [locationPermissionStatus, setLocationPermissionStatus] = useState();

  const [isSplash, setIsSplash] = useState(true)

  useEffect(() => {
    // animationRef.current?.play(30, 120);

    getLocationPermissionHandler()
      .then(status => setLocationPermissionStatus(status))


    setTimeout(() => {
      setIsSplash(false)
      setLogin(true);
    }, 3 * 1000)
  }, []);


  if (fontsLoaded && locationPermissionStatus === 'granted') {


    function TabNav() {
      return (
        <Tab.Navigator
          screenOptions={() => ({ headerShown: false })}
          tabBar={props => <NavBar {...props} />}
        >
          <Tab.Screen name="참여중" component={Home} />
          <Tab.Screen name="참여내역" component={Records} />
          <Tab.Screen name="방찾기" component={FindPin}
            options={{ headerShown: false }}
            initialParams={{ locationPermissionStatus: locationPermissionStatus }}
          />
          <Tab.Screen name="알림" component={Invites} />
          <Tab.Screen name="내 보드" component={MyBoard}
            initialParams={{ smoke: '비흡연', drink: '금주중', img: null }}
          />
        </Tab.Navigator>
      )
    }


    return (
      <>
        <View style={{ flex: 1, backgroundColor: Colors.cool_gray_minus_1 }}>
          <SafeAreaProvider>
            <SafeAreaView style={{ flex: 1 }}>

              {isSplash && <PinUp />}
              {login && <LogIn setLogin={setLogin} />}
              <NavigationContainer>

                {/* {login && <LogIn setLogin={setLogin} />} */}

                <Stack.Navigator screenOptions={{ headerShown: false }}>
                  <Stack.Screen name="TabNav" component={TabNav} />
                  <Stack.Screen name="공지" component={Notice} options={{ headerShown: false }} />
                  <Stack.Screen name="검색" component={Search} options={{ headerShown: false }} />
                  <Stack.Screen name="상대 보드" component={OthersBoard} options={{ headerShown: false }}
                    initialParams={{ isHost: null }}
                  />
                  <Stack.Screen name="설정" component={Settings} options={{ headerShown: false }} />
                  <Stack.Screen name="핀 상세" component={PinDetail} options={{ headerShown: false }}
                    initialParams={{ displayLeftDate: null, isIn: null, isOver: null }}
                  />
                  <Stack.Screen name="친구 요청" component={FriendRequest} options={{ headerShown: false }}
                    initialParams={{ isList: null, isBlock: null }}
                  />
                  <Stack.Screen name="핀 생성" component={MakePin} options={{ headerShown: false }}
                    initialParams={{ myLocation: null, selectedLocationInfo: null, selectedSchools: null, selectedFriends: null }}
                  />
                  <Stack.Screen name="장소 검색" component={SearchMap} options={{ headerShown: false }}
                    initialParams={{ myLocation: null }}
                  />
                  <Stack.Screen name="핀 생성 검색" component={MakePinSearch} options={{ headerShown: false }}
                    initialParams={{ isFriend: null, myLocation: null, selectedLocationInfo: null }}
                  />
                  <Stack.Screen name="지도보기" component={MapPush} options={{ headerShown: false }}
                    initialParams={{ myLocation: null }}
                  />
                  <Stack.Screen name="카카오로그인" component={KaKaoLogin} options={{ headerShown: false }} />
                  <Stack.Screen name="프로필 설정" component={ProfileSetting} options={{ headerShown: false }}
                    initialParams={{ smoking: null, drinking: null, img: null }}
                  />
                  <Stack.Screen name="방찾기 지도" component={Map}
                    initialParams={{ myLocation: null }}
                  />
                </Stack.Navigator>

              </NavigationContainer>
            </SafeAreaView>
          </SafeAreaProvider>
        </View>
      </>
    );
  }
}

import { Dimensions, Platform } from "react-native";
import { useSafeAreaInsets } from 'react-native-safe-area-context';

const deviceWidth = Dimensions.get('window').width;
const deviceHeight = Dimensions.get('window').height;

const deviceSize = { deviceWidth, deviceHeight };

export default deviceSize;

export function getSafeContentHeight() {
  const insets = useSafeAreaInsets();
  
  const safeContentHeight = deviceHeight - (insets.top + insets.bottom + (Platform.OS === 'ios' ? 58 : 68));
  const safeContentHeightWithoutNav = deviceHeight - (insets.top + insets.bottom);

  return [safeContentHeight, safeContentHeightWithoutNav];
};

import React from "react";
import { View, Text, Pressable, StyleSheet, TextInput, Platform } from "react-native";
import { LinearGradient } from 'expo-linear-gradient';

import { MaterialIcons } from '@expo/vector-icons';

import Colors from "../../constants/Colors";
import deviceSize from "../../constants/DeviceSize"

const deviceWidth = deviceSize.deviceWidth;
const deviceHeight = deviceSize.deviceHeight;

export default function Header({
  title, 
  toggleMenu, selected, setSelected, 
  isSearch, inputText, setInputText, keywordSearchHttpHandler,
  isPush, navigation, ContaienrStyle,

  isModalOpen, setIsModalOpen,
  pressedMarkerInfo, setPressedMarkerInfo,
  searchRes, setSearchRes,
  isSchoolPage, selectedSchools,
  myLocation,
  selectedLocationInfo
}) {

  if (title && !toggleMenu) {
    return (
      <View style={[styles.container, ContaienrStyle]}>
        {
          isPush ?
            <Pressable
              style={styles.titleBox}
              onPress={() => navigation.goBack()}
            >
              <MaterialIcons name="arrow-back-ios" size={19} color={Colors.black} />
              <Text style={[styles.title]}>
                {title}
              </Text>
            </Pressable>
            :
            <Text style={styles.title}>
              {title}
            </Text>
        }
      </View>
    )
  } else if (!title && toggleMenu) {
    return (
      <View style={[styles.container, ContaienrStyle]}>
        {
          isPush &&
          <Pressable onPress={() => navigation.goBack()}>
            <MaterialIcons name="arrow-back-ios" size={19} color={Colors.black} />
          </Pressable>
        }
        {
          toggleMenu.map((a, i) => {
            return (
              <Pressable
                style={styles.toggleMenuBox}
                onPress={() => setSelected(a)}
                key={i}
              >
                <Text style={[styles.toggleMenu, selected === a && { color: Colors.black }]}>{a}</Text>
              </Pressable>
            )
          })
        }
      </View>
    )
  } else if (isSearch) {
    return (
      <LinearGradient
        style={[styles.container, ContaienrStyle]}
        colors={[Colors.cool_gray02, Colors.cool_gray02_trans]}
      >
        {
          isPush &&
          <Pressable onPress={() => {
            if(isModalOpen) {
              if(pressedMarkerInfo) {
                setPressedMarkerInfo(null);
              } else if (searchRes){
                setSearchRes(null);
                setIsModalOpen(false)
              }
            } else {
              if (isSchoolPage) {
                console.log(selectedLocationInfo)
                navigation.navigate('핀 생성', {
                  myLocation: myLocation, 
                  selectedSchools: null, 
                  selectedLocationInfo: selectedLocationInfo
                })
              } else {
                navigation.goBack()
              }
            }
          }}>
            <MaterialIcons name="arrow-back-ios" size={19} color={Colors.cool_gray4} />
          </Pressable>
        }
        <View style={styles.textInputContainer}>
          <TextInput
            value={inputText}
            onChangeText={(text) => setInputText(text)}
            onSubmitEditing={() => keywordSearchHttpHandler()}
            placeholder="검색어를 입력하세요"
            style={styles.textInput}
          />
        </View>
      </LinearGradient>
    )
  }
};

const styles = StyleSheet.create({
  container: {
    width: deviceWidth,
    height: 50,
    position: 'absolute',
    top: 0,
    flexDirection: 'row',
    alignItems: 'flex-end',
    backgroundColor: Colors.cool_gray_minus_1,
    paddingHorizontal: 20,
    paddingBottom: 13,
    shadowColor: "black",
    shadowOffset: {
      width: 1,
      height: 2
    },
    shadowOpacity: 0.05,
    elevation: 1
  },

  titleBox: {
    flexDirection: 'row',
    alignItems: 'center'
    // justifyContent: 
  },
  title: {
    fontSize: 16.5,
    // lineHeight: 17.5,
    // fontFamily: 'GothicA1-Bold',
    fontWeight: 700,
    marginTop: Platform.OS === 'ios' ? null : - deviceWidth / 400 * 3
  },

  toggleMenuBox: {
    marginRight: 13
  },
  toggleMenu: {
    fontSize: 16.5,
    // lineHeight: 17,
    // fontFamily: 'GothicA1-Bold',
    fontWeight: 700,
    color: Colors.cool_gray3,
    marginTop: Platform.OS === 'ios' ? null : - deviceWidth / 400 * 3
  },

  textInputContainer: {
    width: deviceWidth * 0.85,
    height: 30,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: Colors.white_semiTrans,
    marginLeft: deviceWidth / 400 * 5,
    marginBottom: -5,
    borderRadius: 10
  },
  textInput: {
    width: deviceWidth * 0.8,
    height: 27,
    // backgroundColor: 'red',
    // fontFamily: 'GothicA1-SemiBold',
    fontSize: 15.5,
    // lineHeight: 16,

    // fontWeight: 600,
    paddingTop: 2,
    color: Colors.cool_gray5
  },
})

还有我的 package.json 文件

{
  "name": "pinup",
  "version": "1.0.0",
  "scripts": {
    "start": "expo start --dev-client",
    "android": "expo run:android",
    "ios": "expo run:ios",
    "web": "expo start --web"
  },
  "dependencies": {
    "@jiggag/react-native-kakao-maps": "^0.0.10",
    "@react-native-async-storage/async-storage": "1.17.11",
    "@react-native-community/datetimepicker": "6.7.3",
    "@react-native-community/masked-view": "^0.1.11",
    "@react-native-community/slider": "4.4.2",
    "@react-native-seoul/kakao-login": "^5.3.0",
    "@react-navigation/bottom-tabs": "^6.5.8",
    "@react-navigation/native": "^6.1.7",
    "@react-navigation/native-stack": "^6.9.13",
    "@react-navigation/stack": "^6.3.17",
    "axios": "^1.4.0",
    "expo": "~48.0.18",
    "expo-build-properties": "~0.6.0",
    "expo-camera": "~13.2.1",
    "expo-font": "~11.1.1",
    "expo-image-picker": "~14.1.1",
    "expo-linear-gradient": "~12.1.2",
    "expo-linking": "~4.0.1",
    "expo-location": "~15.1.1",
    "expo-splash-screen": "~0.18.2",
    "expo-status-bar": "~1.4.4",
    "lottie-react-native": "5.1.4",
    "react": "18.2.0",
    "react-kakao-maps-sdk": "^1.1.11",
    "react-native": "0.71.8",
    "react-native-asset": "^2.1.1",
    "react-native-gesture-handler": "~2.9.0",
    "react-native-image-picker": "^5.6.0",
    "react-native-maps": "1.3.2",
    "react-native-paper": "^5.9.1",
    "react-native-reanimated": "~2.14.4",
    "react-native-safe-area-context": "4.5.0",
    "react-native-screens": "~3.20.0",
    "react-native-status-bar-height": "^2.6.0",
    "react-native-vector-icons": "^9.2.0",
    "react-native-webview": "11.26.0",
    "react-navigation": "^4.4.4",
    "react-navigation-stack": "^2.10.4"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0"
  },
  "private": true,
  "rnpm": {
    "assets": [
      "./assets/fonts/"
    ]
  }
}

我应该怎样做才能让我的应用程序不崩溃并停止?

react-native build expo crash apk
1个回答
0
投票

我通过在 android.config.googleMaps.apiKey 下的 app.json 中正确添加我的 api 密钥解决了这个问题

    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "com.your.app",
      "NSAppTransportSecurity": {
        "NSAllowsArbitraryLoads": true,
        "NSAllowsArbitraryLoadsInWebContent": true
      },
      "config": {
        "googleMapsApiKey": "YOUR API KEY"
      }
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#ffffff"
      },
      "package": "com.your.app",
      "config": {
        "googleMaps": {
          "apiKey" : "YOUR API KEY"
        }
      }
    },

© www.soinside.com 2019 - 2024. All rights reserved.