Flutter Android Package调用python

news2024/9/20 17:23:45

操作步骤

一、创建一个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')),
            ],
          ),
        ),
      ),
    );
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2145607.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

接口幂等性和并发安全的区别?

目录标题 幂等性并发安全总结 接口幂等性和并发安全是两个不同的概念&#xff0c;虽然它们在设计API时都很重要&#xff0c;但侧重点不同。 幂等性 定义&#xff1a;幂等性指的是无论对接口进行多少次相同的操作&#xff0c;结果都是一致的。例如&#xff0c;HTTP的PUT和DELE…

TON基金会与Curve Finance合作:推出基于TON的新型稳定币互换项目

2024年&#xff0c;TON基金会宣布与去中心化金融&#xff08;DeFi&#xff09;领域的知名协议Curve Finance建立战略合作&#xff0c;携手推出一个全新的基于TON区块链的稳定币交换项目。这一合作标志着TON生态系统在DeFi领域的进一步扩展&#xff0c;并将通过Curve Finance的核…

玖逸云黑系统源码 v1.3.0全解无后门 +搭建教程

功能带有卡密生成和添加黑名单等&#xff0c;反正功能也不是很多具体的自己看程序截图即可。 搭建教程 完成 1.我们先添加一个站点 2.PHP选择7.3 3.上传源码解压 4.导入数据库 5.配置数据库信息config.php 源码下载&#xff1a;https://download.csdn.net/download/m0_6…

Python包管理工具pip 入门

主要参考资料&#xff1a; 全面解析 python 包管理工具 pip: https://blog.csdn.net/maiya_yayaya/article/details/135341026 目录 pypi社区pip工具安装 piprequirements.txt 记录python包管理工具8.1 什么是 requirements.txt8.2 requirements.txt 格式8.3 示例8.4 pip 安装 …

鸿蒙手势交互(二:单一手势)

二、单一手势 有六种&#xff1a;点击手势(TapGesture)、长按手势(LongPressGesture)、拖动手势(PanGesture) 捏合手势(PinchGesture)、旋转手势(RotationGesture)、滑动手势(SwipeGesture) 点击手势(TapGesture) TapGesture(value?:{count?:number, fingers?:number}) /…

7.7opencv中(基于C++) 翻转图像

基本概念 在OpenCV中&#xff0c;翻转图像指的是沿着一个或多个轴翻转图像。OpenCV提供了一个函数 flip 来完成这个任务。这个函数可以沿着水平轴、垂直轴或者同时沿着水平和垂直轴翻转图像。 函数原型 void flip(InputArray src,OutputArray dst,int flipCode );参数说明 •…

vulnhub-prime1

目录 靶场环境解题过程 靶场环境 项目ip靶机&#xff08;prime&#xff09;未知攻击机&#xff08;kali&#xff09;10.128.129.128 解题过程 打开靶机&#xff0c;我们只能看见一个登录界面&#xff0c;上面只有半截提示 我们首先要做的是主机发现&#xff0c;因为是网络适…

使用 HFD 加快 Hugging Face 模型和数据集的下载

Hugging Face 提供了丰富的预训练模型和数据集&#xff0c;而且使用 Hugging Face 提供的 from_pretrained() 方法可以轻松加载它们&#xff0c;但是&#xff0c;模型和数据集文件通常体积庞大&#xff0c;用默认方法下载起来非常花时间。 本文将指导你如何使用 HFD&#xff08…

makefile 的语法(9):函数 file foreach

&#xff08;57&#xff09; 之前学了处理文本的函数&#xff0c;处理文件名的函数&#xff0c;现在学习读取文件的函数 file &#xff1a; &#xff08;58&#xff09;可以对文本中每一项进行函数处理的 foreach &#xff1a; &#xff08;59&#xff09; &#xff08;60&…

路由原理介绍

定义与过程 定义&#xff1a;是指导IP报文发送的路径信息 过程&#xff1a; 检查数据包的目的地确定信息源发现可能的路径选择最佳路径验证和维护路由信息 路由来源 直连路由&#xff1a;不需配置&#xff0c;路由器配置IP后自动生效 静态路由&#xff1a;手动配置 ip r…

小商品市场配电系统安全用电解决方案

1.概述 随着市场经济的快速发展和人民生活水平的不断提高,全国各地相继建起了大批大型小商品批发市场,此类市场以其商品种类繁多、价格实惠、停车方便等特点吸引了大量的顾客,成为人们日常光顾的重要场所,地方便了广大人民群众的日常生活。 小商品市场集商品销售和短时货物储…

分享一个 在线拍卖系统 商品竞拍平台Java、python、php三个技术版本(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

【zookeeper安装】zookeeper安装详细教程(单机/集群部署)(linux版)

文章目录 前言一、zookeeper简介二、获取Zookeeper安装包2.1. 离线获取2.2. 在线获取2.3. 解压包 三、单机部署3.1. 配置conf文件3.2. 启动服务 四、集群部署4.1. 概念4.2. 配置conf文件4.3. 创建myid文件4.3. 启动每个节点的zookeeper服务 五、配置systemctl管理&#xff08;选…

neo4j:ubuntu环境下的安装与使用

一、neo4j安装 1. 下载安装包 进入网站&#xff1a;https://neo4j.com/deployment-center/#community 在上图中选择下载即可&#xff08;社区版免费&#xff09; 注意&#xff1a;neo4j的版本要和电脑安装的jdk版本对应&#xff0c;jdk版本使用java --version查看&#xff1a;…

不得不说 Sam‘s Club 的数字化做得挺好

因正好有东西要退货就顺便看了下订单如何退货。 但发现 Sam’s Club 的所有交易都能够从后台查到&#xff0c;同时还提供了个 CSV 文件的下载。 打开下载文件就能看到全部的数字化的交易记录。 就拿加油这个事情来说&#xff0c;能够非常清楚这一年在 Sam’s Club 加油多少加…

【docker】命令之容器操作

一、前言 在上篇博客介绍了关于如何从应用市场&#xff0c;下载镜像后&#xff0c;对镜像的相关操作了。这篇博客呢我们就要讲解我们把镜像下载下来了&#xff0c;启动这个镜像后&#xff0c;就是我们说的容器了&#xff0c;那么容器的具体操作又有那些呢&#xff1f; 二、容器…

基于深度学习的眼部疾病检测识别系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 眼部疾病的早期诊断对于防止视力下降乃至失明至关重要。然而&#xff0c;专业的医疗资源分布不均&#xff0c;尤其是在偏远地区&#xff0c;人们很难获得专业的眼科医生提供的及时诊断服务。本系统…

【devops】devops-gitlab之部署与日常使用

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

XTuner 微调个人小助手认知任务

基础任务 使用 XTuner 微调 InternLM2-Chat-1.8B 实现自己的小助手认知&#xff0c;如下图所示&#xff08;图中的伍鲜同志需替换成自己的昵称&#xff09;&#xff0c;记录复现过程并截图。 创建虚拟环境 在安装 XTuner 之前&#xff0c;我们需要先创建一个虚拟环境。使用 A…

八戒农场小程序V2最新源码

一.介绍 八戒农场V2小程序源码&#xff0c;前端工具上传&#xff0c;包更新、这个是源码&#xff0c;覆盖即可升级版&#xff08;修复很多问题&#xff09;&#xff1b;