使用react-native-call-log在Expo环境中遇加载错误求助
问题根源与解决方案
react-native-call-log是依赖原生代码的模块,Expo Managed Workflow(托管环境)不支持这类未纳入Expo官方SDK的原生模块,这就是你遇到CallLog为null、方法不可用的核心原因。以下是具体解决步骤:
1. 切换到Expo Bare Workflow
如果当前是托管环境,先转为裸工作流,生成原生项目文件:
expo prebuild
2. 配置权限
Android端
在android/app/src/main/AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.READ_CALL_LOG" /> <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
iOS端
在ios/[你的项目名]/Info.plist中添加权限说明:
<key>NSCallKitUsageDescription</key> <string>应用需要访问通话记录以展示历史记录</string>
3. 确保模块正确链接
Expo Bare Workflow支持自动链接,但如果仍有问题,手动在MainApplication.kt中注册包:
// 顶部导入包 import com.wscodelabs.calllog.CallLogPackage; // 修改getPackages方法 override fun getPackages(): List<ReactPackage> = PackageList(this).packages.apply { add(CallLogPackage()) // 手动添加CallLog包 }
4. 修复代码:先请求权限再调用接口
调用通话记录接口前必须先获取权限,修改你的Call.js:
import React, { useEffect, useState } from 'react'; import { View, Text, PermissionsAndroid, Platform } from 'react-native'; import CallLog from 'react-native-call-log'; import { request, PERMISSIONS } from 'react-native-permissions'; const CallsScreen = () => { const [callLogs, setCallLogs] = useState([]); useEffect(() => { requestPermissionsThenFetch(); }, []); const requestPermissionsThenFetch = async () => { let hasPermission = false; // Android权限请求 if (Platform.OS === 'android') { const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.READ_CALL_LOG, { title: '通话记录权限申请', message: '需要访问您的通话记录以展示历史', buttonPositive: '允许' } ); hasPermission = granted === PermissionsAndroid.RESULTS.GRANTED; } // iOS权限请求 else if (Platform.OS === 'ios') { const { status } = await request(PERMISSIONS.IOS.CALL_LOGS); hasPermission = status === 'granted'; } if (hasPermission) { fetchCallLogs(); } else { console.error('未获得通话记录权限'); } }; const fetchCallLogs = async () => { try { if (CallLog?.load) { const logs = await CallLog.load(50); setCallLogs(logs); } else { console.error('CallLog.load 方法不可用,请检查模块链接'); } } catch (error) { console.error('获取通话记录失败:', error); } }; return ( <View style={{ padding: 16 }}> <Text style={{ fontSize: 18, marginBottom: 12 }}>通话记录:</Text> {callLogs.map((log, index) => ( <View key={index} style={{ marginVertical: 8, padding: 8, borderBottomWidth: 1, borderBottomColor: '#eee' }}> <Text>号码: {log.number}</Text> <Text>类型: {log.type === 1 ? '来电' : log.type === 2 ? '去电' : '未接'}</Text> <Text>时间: {new Date(log.timestamp).toLocaleString()}</Text> </View> ))} </View> ); }; export default CallsScreen;
5. 清理缓存并重新构建
# 清除npm缓存 npm cache clean --force # 清除Expo缓存 expo r -c # 重新构建Android项目 cd android && ./gradlew clean && cd .. && expo run:android
内容的提问来源于stack exchange,提问作者Utsav Maji
相关产品推荐
相关产品推荐

