How to import python package in flutter using Starflut?

1,607

You can use chaquopy plugin for flutter, if you want to integrate python packages inside your android app.

Share:
1,607
Vayhuit
Author by

Vayhuit

Updated on December 25, 2022

Comments

  • Vayhuit
    Vayhuit over 1 year

    I'm building an app with Flutter and I need to use some Python code. For that I use the Starflut plugin (https://pub.dev/packages/starflut). I succeed to run the Python code, no issue here, but I want to import extra package.

    To do so, I created a virtual environment where my app is located, then I downloaded by the pip installer numpy, cv2 and Pillow, still no issue there, the downloading went fine.

    But, when I try to import numpy for example, my IDE (Visual Studio Code) tell me that there's an error :

    Unable to import 'numpy' 
    

    So here's my main.dart code (the only dart file, it's a test app):

    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    
    import 'package:starflut/starflut.dart';
    
    void main() => runApp(Main());
    
    class Main extends StatefulWidget {
      @override
      _MainState createState() => _MainState();
    }
    
    class _MainState extends State<Main> {
      var _outputString = '';
      StarSrvGroupClass srvGroup;
      dynamic python;
    
      _MainState() {
        _initStarCore();
      }
    
      void showOutput(String info) async {
        if (info == null || info.length == 0) return;
        _outputString = info;
        setState(() {});
      }
    
      void _initStarCore() async {
        StarCoreFactory starcore = await Starflut.getFactory();
        StarServiceClass service =
            await starcore.initSimple("test", "123", 0, 0, []);
        String resPath = await Starflut.getResourcePath();
        await starcore.regMsgCallBackP(
            (int serviceGroupID, int uMsg, Object wParam, Object lParam) async {
          if (uMsg == Starflut.MSG_DISPMSG || uMsg == Starflut.MSG_DISPLUAMSG) {
            showOutput(wParam);
          }
          print("$serviceGroupID  $uMsg   $wParam   $lParam");
          return null;
        });
        srvGroup = await service["_ServiceGroup"];
        bool isAndroid = await Starflut.isAndroid();
        if (isAndroid == true) {
          String libraryDir = await Starflut.getNativeLibraryDir();
          String docPath = await Starflut.getDocumentPath();
          if (libraryDir.indexOf("arm64") > 0) {
            Starflut.unzipFromAssets("lib-dynload-arm64.zip", docPath, true);
          } else if (libraryDir.indexOf("x86_64") > 0) {
            Starflut.unzipFromAssets("lib-dynload-x86_64.zip", docPath, true);
          } else if (libraryDir.indexOf("arm") > 0) {
            Starflut.unzipFromAssets("lib-dynload-armeabi.zip", docPath, true);
          } else {
            //x86
            Starflut.unzipFromAssets("lib-dynload-x86.zip", docPath, true);
          }
          await Starflut.copyFileFromAssets("python3.6.zip",
              "flutter_assets/starfiles", null); //desRelatePath must be null
          await Starflut.copyFileFromAssets(
              "program.py", "flutter_assets/starfiles", "flutter_assets/starfiles");
        }
        if (await srvGroup.initRaw("python36", service) == true) {
          _outputString = "init starcore and python 3.6 successfully";
        } else {
          _outputString = "init starcore and python 3.6 failed";
        }
    
        await srvGroup.loadRawModule("python", "",
            resPath + "/flutter_assets/starfiles/" + "program.py", false);
        python = await service.importRawContext("python", "", false, "");
    
        setState(() {
          // This call to setState tells the Flutter framework that something has
          // changed in this State, which causes it to rerun the build method below
          // so that the display can reflect the updated values. If we changed
          // _counter without calling setState(), then the build method would not be
          // called again, and so nothing would appear to happen.
          //_counter++;
        });
      }
    
      void runScriptCode() async {
        var result = await python.call("multiply", [5, 2]);
        _outputString = result.toString();
    
        setState(() {});
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: Center(
              child: FlatButton(
                color: Colors.red,
                child: Text(_outputString),
                onPressed: () {
                  runScriptCode();
                },
              ),
            ),
          ),
        );
      }
    }
    
    

    and my Python file:

    import numpy as np # (to test)
    
    def multiply(a, b):
        return a*b
    

    Here's my tree structure if it can help: The tree structure of my Flutter project

    Hopping you can help me.

    Thanks in advance !

  • Vayhuit
    Vayhuit over 3 years
    I already tried it with flask, and it worked pretty well but, I don't need to pay a domain name or something if I want to deploy my app ? Or even though I deploy it, Can I steel use a local server ? And a little last question, the library import is more easy if I use this way ? Thanks for your answer !
  • bitinerant
    bitinerant almost 3 years
    Note that using Chaquo requires a license, though it says that license is free for open-source apps. They also have a "Python SDK for Android" on GitHub but I think it's just a demo project. I don't think Chaquopy itself is open-source.
  • Jay Dangar
    Jay Dangar almost 3 years
    yes it's not but if you are creating open source app, then you can contact Chaquopy creator and you'll get free license to use.