Flutter原生功能调用插件flutter_native_helper的使用
Flutter原生功能调用插件flutter_native_helper的使用
flutter_native_helper
向Flutter端提供原生Android功能,包括:
- 应用内升级
- 获取系统铃声/通知/警报列表
- 播放、暂停铃声/通知/警报
安装
在 pubspec.yaml
内.
最新版本:查看
dependencies:
flutter_native_helper: ^$latestVersion
导入
在你要使用的类中.
import 'package:flutter_native_helper/flutter_native_helper.dart';
配置
1. 在 android/build.gradle
,找到:
ext.kotlin_version = '1.3.10'
或
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.10"
将 1.3.10
修改为 1.5.20
2. 在 android/app/src/main/res
下,新建 xml
文件夹,
随后在 xml
内新建 file_provider_path.xml
文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<root-path name="root" path="."/>
<files-path
name="files"
path="."/>
<cache-path
name="cache"
path="."/>
<external-path
name="external"
path="."/>
<external-cache-path
name="external_cache"
path="."/>
<external-files-path
name="external_file"
path="."/>
</paths>
最后,打开 android/app/src/main/AndroidManifest.xml
文件,
在 application
标签下添加:
<provider
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true"
android:name="androidx.core.content.FileProvider">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_path" />
</provider>
使用
一、应用内升级
在之前,想要完成当前应用内升级,在Flutter端是不太便捷的事情,但现在,它将改变 - 你只需要一行代码,即可完成应用内升级(无需关注权限问题)。
1. 下载并安装
/// 注意:该方法仅会将apk下载到沙盒目录下
/// 这个示例最终生成的文件路径就是 '/data/user/0/$applicationPackageName/files/updateApk/new.apk'
/// 如果我想指定两层目录怎么办呢,很简单,只需要将 [fileDirectory] 设置为 'updateApk/second'
/// 那么他就会生成 '/data/user/0/$applicationPackageName/files/updateApk/second/new.apk'
///
/// 如果,连续多次调用此方法,并且三个参数为完全相同的,那么 Native 端将等待第一个下载完成后才允许继续下载。
FlutterNativeHelper.instance.downloadAndInstallApk(
fileUrl: "https://xxxx.apk",
fileDirectory: "updateApk",
fileName: "new.apk");
参数名称 | 参数意义 | 是否必传 |
---|---|---|
fileUrl | 要下载apk的url地址 | 是 |
fileDirectory | 文件夹路径(首尾无须拼接反斜杠) | 是 |
fileName | 文件名称(无需拼接反斜杠) | 是 |
isDeleteOriginalFile | 如果本地已存在相同文件,是否要删除(默认为true) | 否 |
2. 获取下载apk进度
建议参考这里
/// 在 initState 中调用
FlutterNativeHelper.instance.setMethodCallHandler((call) async {
if (call.method == FlutterNativeConstant.methodDownloadProgress) {
if (call.argument is String) {
final cancelTag = call.argument as String;
}
}
});
3. 取消下载
建议参考这里
/// [cancelTag] 在 'initState' 中:
/// 调用 [FlutterNativeHelper.instance.setMethodCallHandler],'method': [FlutterNativeConstant.methodCancelTag],
FlutterNativeHelper.instance.cancelDownload(cancelTag: "$_cancelTag");
4. 仅安装
/// [filePath] apk文件地址,必传
FlutterNativeHelper.instance.installApk(
filePath: "/data/user/0/$applicationPackageName/files/updateApk/new.apk"
);
5. 打开应用市场当前详情页
简单来说,如果你有指定的应用市场,就传递 targetMarketPackageName
为对应的包名;如果你没有指定的应用市场,但是想让大部分机型都打开厂商应用商店,那么就设置 isOpenSystemMarket
为true
FlutterNativeHelper.instance.openAppMarket(
targetMarketPackageName: "$targetPackageName", // 指定的应用市场包名,默认为空
isOpenSystemMarket: true // 如果未指定包名,是否要打开系统自带-应用市场,默认为true
);
二、控制手机发出通知、铃声
1. 播放通知、铃声
/// [assignUri] 指定铃声uri,如不指定,会播放系统默认铃声
///
/// 如需指定铃声,可调用 [FlutterNativeHelper.instance.getSystemRingtoneList],选择心仪的铃声
/// 如连续播放调用多个铃声则会自动中断上一个
/// 返回是否播放成功
val isSuccess = await FlutterNativeHelper.instance.playSystemRingtone(
assignUri: assignUri);
2. 暂停播放
/// 返回是否暂停成功
val isSuccess = await FlutterNativeHelper.instance.stopSystemRingtone();
3. 是否正在播放
val isPlaying = await FlutterNativeHelper.instance.isPlayingSystemRingtone();
4. 获取系统通知/铃声/警报列表
/// 参数:systemRingtoneType,铃声类型
final List<SystemRingtoneModel> list = await FlutterNativeHelper.instance.getSystemRingtoneList(FlutterNativeConstant.systemRingtoneTypeNotification);
铃声类型 | 含义 |
---|---|
FlutterNativeConstant.systemRingtoneTypeNotification | 通知声 |
FlutterNativeConstant.systemRingtoneTypeAlarm | 警报 |
FlutterNativeConstant.systemRingtoneTypeRingtone | 铃声 |
FlutterNativeConstant.systemRingtoneTypeAll | 全部 |
SystemRingtoneModel
字段 | 含义 |
---|---|
ringtoneTitle | 铃声名称 |
ringtoneUri | 铃声Uri |
三、其他API
1. 将Uri转换为真实路径
/// 如果出现异常,将返回空字符串
final String realPath = await FlutterNativeHelper.instance.transformUriToRealPath(String? targetUri);
2. 控制设备震动
FlutterNativeHelper.instance.callPhoneToShake();
参数名称 | 参数意义 | 是否必传 |
---|---|---|
millSeconds | 震动时长,默认为500 | 否 |
amplitude | 震动强度 1~255之间 | 否 |
3. 下载文件
/// 该方法与 'downloadAndInstallApk' 参数一致,仅负责下载
///
/// 如果你想预下载apk或其他什么骚操作,可以根据此方法+installApk来完成
/// 返回:文件的真实路径
/// 如需获取下载进度,可参考 第一项第二小节
///
/// 如果,连续多次调用此方法,并且三个参数为完全相同的,那么 Native 端将等待第一个下载完成后才允许继续下载。
final String filePath = await FlutterNativeHelper.instance.downloadFile(fileUrl: "https://xxxx.apk",
fileDirectory: "updateApk",
fileName: "new.apk");
4. 进入应用设置详情页
final bool intoResult = await FlutterNativeHelper.instance.intoAppSettingDetail();
5. 获取设备名称
final String deviceName = await FlutterNativeHelper.instance.deviceName;
示例代码
以下是完整的示例代码:
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_native_helper/flutter_native_helper.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
String _cancelTag = "";
[@override](/user/override)
void initState() {
super.initState();
initPlatformState();
listenNativeMessage();
}
/// 监听 Native 端发送的信息
void listenNativeMessage() {
FlutterNativeHelper.instance.setMethodCallHandler((call) async {
switch (call.method) {
case FlutterNativeConstant.methodDownloadProgress:
// 获取下载进度
if (call.arguments is double) {
final progress = call.arguments as double;
if (progress < 100) {
String stringProgress = progress.toString();
if (stringProgress.length > 5) {
stringProgress = stringProgress.substring(0, 5);
}
EasyLoading.showProgress(progress / 100,
status: "下载中 $stringProgress%");
} else {
EasyLoading.showSuccess("下载成功");
}
}
break;
case FlutterNativeConstant.methodCancelTag:
// 得到 cancelTag
if (call.arguments is String) {
_cancelTag = call.arguments as String;
}
break;
}
});
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String platformVersion;
try {
platformVersion = await FlutterNativeHelper.instance.platformVersion ??
'Unknown platform version';
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
builder: EasyLoading.init(),
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Running on: $_platformVersion\n'),
_buildButton("下载并安装apk", () {
EasyLoading.show(status: "开始下载");
FlutterNativeHelper.instance.downloadAndInstallApk(
fileUrl: "https://xxxxx.apk",
fileDirectory: "updateApk",
fileName: "newApk.apk");
}),
_buildButton("取消下载", () async {
if (_cancelTag.isNotEmpty) {
await FlutterNativeHelper.instance.cancelDownload(_cancelTag);
EasyLoading.dismiss();
}
}),
_buildButton('打开应用市场', () async {}),
_buildButton("得到铃声列表", () async {
final List<SystemRingtoneModel> list =
await FlutterNativeHelper.instance.getSystemRingtoneList(
FlutterNativeConstant.systemRingtoneTypeNotification);
for (var value in list) {
print(
"lxlx ringtoneTitle: ${value.ringtoneTitle}, ${value.ringtoneUri}");
}
}),
],
),
),
),
);
}
Widget _buildButton(String text, Function function) {
return MaterialButton(
color: Colors.blue,
child: Text(
text,
style: const TextStyle(color: Colors.white),
),
onPressed: () {
function();
},
);
}
[@override](/user/override)
void dispose() {
FlutterNativeHelper.instance.dispose();
super.dispose();
}
}
更多关于Flutter原生功能调用插件flutter_native_helper的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter原生功能调用插件flutter_native_helper的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用flutter_native_helper
插件来调用原生功能的一个简单示例。flutter_native_helper
是一个用于在Flutter中方便地调用原生(Android和iOS)代码的插件。
1. 添加依赖
首先,你需要在pubspec.yaml
文件中添加flutter_native_helper
的依赖:
dependencies:
flutter:
sdk: flutter
flutter_native_helper: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来获取依赖。
2. 配置原生代码
Android
在android/app/src/main/kotlin/[your_package_name]/MainActivity.kt
(或Java文件)中,你需要定义一个原生方法。例如:
package com.example.yourapp
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
private val CHANNEL = "com.example.yourapp/channel"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
GeneratedPluginRegistrant.registerWith(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "showToast") {
val message = call.argument<String>("message")
showToast(message)
result.success(null)
} else {
result.notImplemented()
}
}
}
private fun showToast(message: String?) {
message?.let {
Toast.makeText(this, it, Toast.LENGTH_SHORT).show()
}
}
}
iOS
在ios/Runner/AppDelegate.swift
中,你需要配置一个方法通道并处理调用:
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(name: "com.example.yourapp/channel", binaryMessenger: controller)
channel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
if call.method == "showToast" {
if let message = call.arguments as? String {
self.showToast(message: message)
}
result(nil)
} else {
result(FlutterMethodNotImplemented)
}
})
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func showToast(message: String) {
let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
let window = UIApplication.shared.keyWindow
window?.rootViewController?.present(alert, animated: true, completion: nil)
}
}
3. 在Flutter中调用原生方法
在你的Dart代码中,你可以使用MethodChannel
来调用原生方法。首先,确保你导入了flutter_native_helper
包(如果它提供了额外的封装,否则直接使用MethodChannel
):
import 'package:flutter/services.dart';
import 'package:flutter_native_helper/flutter_native_helper.dart'; // 如果插件提供了封装
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
static const platform = const MethodChannel('com.example.yourapp/channel');
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Native Helper Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: _showToast,
child: Text('Show Toast'),
),
),
),
);
}
Future<void> _showToast() async {
try {
await platform.invokeMethod('showToast', <String, dynamic>{'message': 'Hello from Flutter!'});
} on PlatformException catch (e) {
print("Failed to invoke: '${e.message}'.");
}
}
}
注意事项
- 确保你已经在
AndroidManifest.xml
和Info.plist
中配置了必要的权限和配置。 - 插件的具体使用方法可能会根据版本有所不同,请参考官方文档或仓库中的示例代码。
- 上述代码只是一个基础示例,实际项目中可能需要更多的错误处理和边界情况考虑。
这个示例展示了如何在Flutter中通过flutter_native_helper
(或直接使用MethodChannel
)来调用原生功能。希望这对你有所帮助!