Flutter来电管理插件flutter_incoming_call的使用
Flutter来电管理插件flutter_incoming_call的使用
插件介绍
flutter_incoming_call
是一个Flutter插件,用于在Flutter应用中显示来电界面。目前该插件处于Alpha版本,尚未准备好用于生产环境。
使用方法
1. 配置Android项目
在AndroidManifest.xml
文件中添加以下内容:
<activity
android:name="com.github.alezhka.flutter_incoming_call.IncomingCallActivity"
android:theme="@style/Theme.AppCompat"
android:screenOrientation="portrait"
android:showOnLockScreen="true">
<intent-filter>
<action android:name="com.github.alezhka.flutter_incoming_call.activity.ACTION_INCOMING_CALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<receiver android:name="com.github.alezhka.flutter_incoming_call.CallBroadcastReceiver"
android:enabled="true"
android:exported="false"/>
2. 配置Flutter插件
在Dart代码中配置插件:
FlutterIncomingCall.configure(
appName: 'example_incoming_call',
duration: 30000,
android: ConfigAndroid(
vibration: true,
ringtonePath: 'default',
channelId: 'calls',
channelName: 'Calls channel name',
channelDescription: 'Calls channel description',
),
ios: ConfigIOS(
iconName: 'AppIcon40x40',
ringtonePath: null,
includesCallsInRecents: false,
supportsVideo: true,
maximumCallGroups: 2,
maximumCallsPerCallGroup: 1,
)
);
3. 监听事件
监听来电相关的事件:
FlutterIncomingCall.onEvent.listen((event) {
if(event is CallEvent) { // Android | iOS
// 处理来电事件
} else if(event is HoldEvent) { // iOS
// 处理保持事件
} else if(event is MuteEvent) { // iOS
// 处理静音事件
} else if(event is DmtfEvent) { // iOS
// 处理DTMF事件
} else if(event is AudioSessionEvent) { // iOS
// 处理音频会话事件
}
});
4. 调用API
调用插件提供的API来显示或结束来电:
// 显示来电
FlutterIncomingCall.displayIncomingCall(String uid, String name, String avatar, String handle, String type, bool isVideo);
// 结束单个来电
FlutterIncomingCall.endCall(String uuid);
// 结束所有来电
FlutterIncomingCall.endAllCalls();
示例代码
以下是一个完整的示例代码,展示了如何在Flutter应用中使用flutter_incoming_call
插件:
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter_incoming_call/flutter_incoming_call.dart';
import 'package:uuid/uuid.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
[@override](/user/override)
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var uuid = Uuid();
BaseCallEvent? _lastEvent;
CallEvent? _lastCallEvent;
HoldEvent? _lastHoldEvent;
MuteEvent? _lastMuteEvent;
DmtfEvent? _lastDmtfEvent;
AudioSessionEvent? _lastAudioSessionEvent;
void _incomingCall() {
final uid = uuid.v4();
final name = 'Daenerys Targaryen';
final avatar = 'https://scontent.fhel6-1.fna.fbcdn.net/v/t1.0-9/62009611_2487704877929752_6506356917743386624_n.jpg?_nc_cat=102&_nc_sid=09cbfe&_nc_ohc=cIgJjOYlVj0AX_J7pnl&_nc_ht=scontent.fhel6-1.fna&oh=ef2b213b74bd6999cd74e3d5de235cf4&oe=5F6E3331';
final handle = 'example_incoming_call';
final type = HandleType.generic;
final isVideo = true;
FlutterIncomingCall.displayIncomingCall(uid, name, avatar, handle, type, isVideo);
}
void _endCurrentCall() {
if(_lastEvent != null && _lastCallEvent != null) {
FlutterIncomingCall.endCall(_lastCallEvent!.uuid);
}
}
void _endAllCalls() {
FlutterIncomingCall.endAllCalls();
}
[@override](/user/override)
void initState() {
super.initState();
FlutterIncomingCall.configure(
appName: 'example_incoming_call',
duration: 30000,
android: ConfigAndroid(
vibration: true,
ringtonePath: 'default',
channelId: 'calls',
channelName: 'Calls channel name',
channelDescription: 'Calls channel description',
),
ios: ConfigIOS(
iconName: 'AppIcon40x40',
ringtonePath: null,
includesCallsInRecents: false,
supportsVideo: true,
maximumCallGroups: 2,
maximumCallsPerCallGroup: 1,
)
);
FlutterIncomingCall.onEvent.listen((event) {
setState(() { _lastEvent = event; });
if(event is CallEvent) {
setState(() { _lastCallEvent = event; });
} else if(event is HoldEvent) {
setState(() { _lastHoldEvent = event; });
} else if(event is MuteEvent) {
setState(() { _lastMuteEvent = event; });
} else if(event is DmtfEvent) {
setState(() { _lastDmtfEvent = event; });
} else if(event is AudioSessionEvent) {
setState(() { _lastAudioSessionEvent = event; });
}
});
}
[@override](/user/override)
void dispose() {
_endAllCalls();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextButton(
child: Text('立即来电'),
onPressed: _incomingCall,
),
SizedBox(height: 16),
TextButton(
child: Text('5秒后来电'),
onPressed: () => Future.delayed(Duration(seconds: 5), _incomingCall),
),
SizedBox(height: 16),
TextButton(
child: Text('结束当前来电'),
onPressed: _endCurrentCall,
),
SizedBox(height: 16),
TextButton(
child: Text('结束所有来电'),
onPressed: _endAllCalls,
),
SizedBox(height: 16),
Text(
'最新事件:',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text(
_lastEvent != null ? _lastEvent.toString() : '无事件',
style: TextStyle(
fontSize: 16
),
),
if(_lastCallEvent != null) ...[
Text(
'最新来电事件:',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text(
_lastCallEvent.toString(),
style: TextStyle(
fontSize: 16
),
)
],
if(_lastHoldEvent != null) ...[
Text(
'最新保持事件:',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text(
_lastHoldEvent.toString(),
style: TextStyle(
fontSize: 16
),
)
],
if(_lastMuteEvent != null) ...[
Text(
'最新静音事件:',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text(
_lastMuteEvent.toString(),
style: TextStyle(
fontSize: 16
),
)
],
if(_lastDmtfEvent != null) ...[
Text(
'最新DTMF事件:',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text(
_lastDmtfEvent.toString(),
style: TextStyle(
fontSize: 16
),
)
],
if(_lastAudioSessionEvent != null) ...[
Text(
'最新音频会话事件:',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text(
_lastAudioSessionEvent.toString(),
style: TextStyle(
fontSize: 16
),
)
]
],
),
),
),
);
}
}
更多关于Flutter来电管理插件flutter_incoming_call的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter来电管理插件flutter_incoming_call的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用flutter_incoming_call
插件的示例代码。这个插件允许你在Flutter应用中处理来电显示和管理。
首先,确保你的Flutter项目已经设置好,并且已经添加了flutter_incoming_call
插件。你可以在pubspec.yaml
文件中添加以下依赖项:
dependencies:
flutter:
sdk: flutter
flutter_incoming_call: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
1. 配置Android权限
在android/app/src/main/AndroidManifest.xml
中添加必要的权限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yourapp">
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<!-- 其他配置 -->
</manifest>
2. 配置iOS权限
在ios/Runner/Info.plist
中添加必要的权限配置:
<key>NSMicrophoneUsageDescription</key>
<string>App needs access to microphone</string>
<key>NSCameraUsageDescription</key>
<string>App needs access to camera</string>
<key>UIBackgroundModes</key>
<array>
<string>voip</string>
</array>
3. 使用插件代码
在Flutter项目的lib
目录下创建一个新的Dart文件,比如call_manager.dart
,并添加以下代码:
import 'package:flutter/material.dart';
import 'package:flutter_incoming_call/flutter_incoming_call.dart';
class CallManager {
static FlutterIncomingCall? flutterIncomingCall;
static void init() {
flutterIncomingCall = FlutterIncomingCall();
// 监听来电事件
flutterIncomingCall?.incomingCallReceived().listen((event) {
print("Received incoming call: ${event.callInfo.callerNumber}");
// 显示来电界面
showIncomingCallUI(event.callInfo);
});
// 监听挂断事件
flutterIncomingCall?.callEnded().listen((event) {
print("Call ended: ${event.callInfo.callerNumber}");
// 隐藏来电界面
hideIncomingCallUI();
});
// 监听接听事件
flutterIncomingCall?.callAnswered().listen((event) {
print("Call answered: ${event.callInfo.callerNumber}");
});
}
static void showIncomingCallUI(CallInfo callInfo) {
// 你可以在这里显示一个自定义的来电界面
// 这里只是一个简单的示例,你可以使用Material或Cupertino组件来构建更复杂的UI
showDialog(
context: YourAppContextHere, // 请替换为你的上下文
builder: (context) => AlertDialog(
title: Text('Incoming Call'),
content: Text('Caller: ${callInfo.callerNumber}'),
actions: <Widget>[
TextButton(
onPressed: () {
// 拒绝来电
flutterIncomingCall?.rejectCall(callInfo.uuid);
Navigator.of(context).pop();
},
child: Text('Reject'),
),
TextButton(
onPressed: () {
// 接听来电
flutterIncomingCall?.answerCall(callInfo.uuid);
Navigator.of(context).pop();
},
child: Text('Answer'),
),
],
),
);
}
static void hideIncomingCallUI() {
// 隐藏来电界面的逻辑,比如关闭Dialog
// 这里只是示例,实际中你需要根据你的UI逻辑来处理
Navigator.of(YourAppContextHere).pop(); // 请替换为你的上下文
}
}
4. 在主应用中使用
在你的主应用文件(通常是main.dart
)中初始化CallManager
:
import 'package:flutter/material.dart';
import 'call_manager.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
CallManager.init();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Incoming Call Example'),
),
body: Center(
child: Text('Check your console for incoming call logs.'),
),
),
);
}
}
注意事项
- 确保你在适当的上下文中使用
Navigator
,例如你可以通过依赖注入或者全局状态管理(如Provider、Riverpod等)来传递上下文。 - 根据你的应用需求,可能需要更复杂的UI和逻辑来处理来电显示。
- 插件的使用可能会因平台(Android和iOS)的不同而有所差异,请确保测试你的应用在两个平台上的行为。
希望这个示例能帮助你在Flutter项目中集成和使用flutter_incoming_call
插件!