操作步骤
一、创建一个Flutter Package
使用以下指令创建一个Flutter Package
flutter create --template=plugin --platforms=android,ios -a java flutter_package_python |
二、修改android/build.gradle文件
在buildscript——>dependencies中添加以下内容
//导入Chaquopy插件,使Android可以使用Python
classpath "com.chaquo.python:gradle:15.0.1" |
在android上方导入chaquo.python插件
apply plugin: 'com.chaquo.python' |
在android——>defaultConfig中添加ndk和python配置
ndk {
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
}
python {
version "3.8"
pip {
//根据python用到的依赖进行下载
install "scipy"
install "numpy"
install "PyWavelets"
install "scikit-image"
install "tflite-runtime"
install "statsmodels"
}
} |
三、编写python文件
在android——>src——>main目录下创建名称为calc的python文件,写一个简单的加法函数:
# calc.py
def add(a, b):
return a + b |
四、创建一个工厂函数,用于初始化Python以及引用Python函数
在android——>src——>main——>com——>expample——>flutter_package_python下创建PythonFactory.java文件,对Python进行初始化,以及调用Python中的加法函数
package com.example.flutter_package_python;
import android.content.Context;
import com.chaquo.python.PyObject;
import com.chaquo.python.Python;
import com.chaquo.python.android.AndroidPlatform;
public class PythonFactory {
private static PythonFactory instance = null; // 静态实例
private Python pythonInstance; // Python 环境实例
private PyObject calcModule; // Python 模块
private static boolean isInitialized = false;
// 私有化构造函数,确保外部无法直接实例化
private PythonFactory(Context context) {
if (!isInitialized) {
Python.start(new AndroidPlatform(context)); // 需要传入上下文
isInitialized = true;
}
pythonInstance = Python.getInstance(); // 初始化 Python 环境
calcModule = pythonInstance.getModule("calc"); // 加载 calc.py 模块
}
// 获取单例工厂实例
public static synchronized PythonFactory getInstance(Context context) {
if (instance == null) {
instance = new PythonFactory(context); // 初始化一次
}
return instance;
}
// 工厂方法:调用 Python 中的加法函数
public int addTwoNumbers(int a, int b) {
PyObject result = calcModule.callAttr("add", a, b); // 调用 Python 中的 add 方法
return result.toInt(); // 将结果返回为整数
}
}
|
五、在FlutterPackagePythonPlugin中使用工厂函数
1.定义pythonFactory变量,在onAttachedToEngine中初始化工厂函数并将结果返回给pythonFactory
private PythonFactory pythonFactory;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
// 其他代码
pythonFactory = PythonFactory.getInstance(flutterPluginBinding.getApplicationContext());
} |
2. 在onMethodCall添加判断,当dart中调用了addTwoNumbers函数则使用Python进行相加计算
if (call.method.equals("addTwoNumbers")) {
int a = call.argument("a");
int b = call.argument("b");
// 使用工厂类调用 Python 的加法函数
int sum = pythonFactory.addTwoNumbers(a, b);
result.success(sum); // 将结果返回给 Flutter 端
} |
六、编写dart代码调用安卓中的java
在lib/flutter_packages_audio_analysis_platform_interface.dart中添加一个addTwoNumbers函数
Future<int?> addTwoNumbers(int a, int b) {
throw UnimplementedError('addTwoNumbers() has not been implemented.');
} |
在lib/flutter_packages_audio_analysis_method_channel.dart中重写addTwoNumbers方法
@override
Future<int> addTwoNumbers(int a, int b) async {
try {
final result =
await methodChannel.invokeMethod('addTwoNumbers', {'a': a, 'b': b});
return result;
} on PlatformException catch (e) {
print("调用 Python 失败: '${e.message}'.");
return -1;
}
} |
3.在lib/FlutterPackagesAudioAnalysis类中添加addTwoNumbers函数
Future<int?> addTwoNumbers(int a, int b) {
return FlutterPackagesAudioAnalysisPlatform.instance.addTwoNumbers(a, b);
} |
七、写测试代码
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_packages_audio_analysis/flutter_packages_audio_analysis.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
final _flutterPackagesAudioAnalysisPlugin = FlutterPackagesAudioAnalysis();
@override
void initState() {
super.initState();
initPlatformState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
// We also handle the message potentially returning null.
try {
platformVersion =
await _flutterPackagesAudioAnalysisPlugin.getPlatformVersion() ??
'Unknown platform version';
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
});
}
int addRes = 0;
add() async {
int a = 8;
int b = 9;
addRes =
await _flutterPackagesAudioAnalysisPlugin.addTwoNumbers(a, b) ?? 100;
setState(() {});
}
add1() async {
int a = 8;
int b = 19;
addRes =
await _flutterPackagesAudioAnalysisPlugin.addTwoNumbers(a, b) ?? 100;
setState(() {});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Running on: $_platformVersion\n'),
ElevatedButton(onPressed: add, child: Text('Add')),
Text("相加结果:${addRes}"),
ElevatedButton(onPressed: add1, child: Text('Add1')),
],
),
),
),
);
}
}
|