• android 嵌入python 互交

    前言

    都知道,之所以python十分强大,是因为其包含许多的库,通过这些库的拓展,实现许多需要的功能,由此想到了如果这些功能能够被移植到android平台的app上,应用一定十分广泛。

    Google开发的android studio就能够直接使用Python开发app,实现java与Python互交。

    实现

    既然要实现在android平台,python与Java互交,就必须想到一个工具,ChaquopyChaquopy的作用就是在Android Studio添加Python环境,java与Python互调,打包安装后安卓apk文件能够正常运行。

    • 前提在Windows设备上已经安装了Android Studio和Python环境
    • Android Studio的Gradle的版本需要在3.1.0以上
    • Android SDK的版本在16以上

    配置

    新建一个Android工程,在项目的目录下的build.gradle文件中,添加下面内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    buildscript {
    repositories {
    ...
    maven { url "https://chaquo.com/maven" } #add code
    }
    dependencies {
    ...
    classpath "com.chaquo.python:gradle:8.0.0" #add code
    }
    }

    image-20211223212151622

    在app/build.gradle文件里面需要使用插件com.chaquo.python

    1
    apply plugin: 'com.chaquo.python'

    可以指定一下abi,如果需要在模拟器下运行,可以增加x86,但是一般指定armeabi-v7a即可

    1
    2
    3
    4
    ndk {
    // 指定abi,如需在模拟器调试,增加"x86",否则指定"armeabi-v7a"即可
    abiFilters "armeabi-v7a", "x86" #add code
    }

    在此,还得指明python的路径,C:/Users/admin/AppData/Local/Programs/Python/Python39/python.exe是我python3.9的默认安装目录,这里必须替换成自己的python路径。

    项目需要安装运行的python库可以通过pip安装,比如,安装numpy

    1
    2
    3
    4
    5
    6
    7
    8
    9
    python {
    // 指定python路径
    buildPython "C:/Users/admin/AppData/Local/Programs/Python/Python39/python.exe"
    // 安装python库
    pip {
    install "numpy"
    install "scipy"
    }
    }

    image-20211223213026353

    配置完成后,可以通过右上角的”Sync Now”检查一下,如果没有报错,就代表配置成功了。build框中会提示synced successfully

    为了在Android Studio直接编写python文件,可以安装一下编辑的插件

    点击File -> setting 到设置界面,点击plugin,搜索python,在搜索结果中选择并安装Python Community Edition,安装成功之后,按钮会变为Restart IDE,重启Android Studio即可;

    在python文件夹上点击右键,如果在“new”中可以看到“Python File”,则表示配置文件成功!!!

    重启后右击前文提及的src/main目录下名为“python”的文件夹,如果在“new”中有“Python File”,则表示配置文件成功!!!

    image-20211223222743731

    实现

    首先新建一个python文件夹,在app/src/main/文件夹下鼠标右键,在new里面的python package新建一个Python文件夹,里面会默认生成一个__init__.py的python的python文件。

    image-20211225143534656

    Java调用python

    用于实例,就在python这个文件夹下新建一个mypython.py文件,可以在里面写入以下内容用于测试。

    app/src/main/python/mypython.py:

    1
    2
    3
    def getString():
    str="hi python"
    return str

    就是用python定义了一个函数,getString(),用来返回字符串“hi python”

    image-20211225144721421

    下面,在MainActivity里面初始化一下python,可以使用

    1
    2
    3
    4
    5
    6
    // 初始化python
    private void initPython(){
    if (! Python.isStarted()) {
    Python.start(new AndroidPlatform(this));
    }
    }

    并把initPython()放在onCreate()方法里面调用。

    为了显示Java调用python 的效果,可以使用一个TextView来显示调用python传过来的值

    1
    TextView tv=(TextView)findViewById(R.id.my_id);

    下面就开始调用,把调用代码就放在startpython()私有方法里面吧,可以随意

    1
    2
    3
    4
    5
    private void startpython(){
    Python py = Python.getInstance();
    PyObject pyo= Python py = Python.getInstance();
    tv.setText(pyo.toJava(String.class));
    }
    • 第二行Python py = Python.getInstance();是用来创建一个python的接口
    • 第三行py.getModule("mypython").callAttr("getString");的意思是调用mypython文件里面的getStrintg函数,得到一个PyObject的对象
    • pyo.toJava(String.class)就是将PyObject转换为java的数据类型

    pyo表示调用函数之后的返回值,因为Python中的数据类型和Java中有些不一样,所以一般不能直接使用,需要进行转换,比如:

    1
    2
    3
    4
    5
    6
    7
    8
    //1.如果Python函数return(以上述obj1为例)为int类型,需要使用一下语句进行转换:  
    Integer result = obj1.toJava(Integer.class);

    //2.如果Python函数return为一维int的list类型,使用以下语句进行转换:
    int[] result = obj1.toJava(int[].class);

    //3.如果Python函数return为二维int的list类型,使用以下语句进行转换:
    int[][] result = obj1.toJava(int[][].class);

    然后,java调用python的完整代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public class MainActivity extends AppCompatActivity {
    Python py;
    TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tv=(TextView)findViewById(R.id.my_id);
    initPython();
    startpython();
    }
    // 初始化python
    private void initPython(){
    if (! Python.isStarted()) {
    Python.start(new AndroidPlatform(this));
    }
    }
    private void startpython(){
    py = Python.getInstance();
    PyObject pyo= py.getModule("mypython").callAttr("getString");
    tv.setText(pyo.toJava(String.class));
    }
    }

    image-20211225151155554

    通过编译在真机中的显示如下

    image-20211225151732442

    显然,java调用python成功,并返回了python中字符串的值

    python调用java

    首先,为了演示例子,新建一个java的储存类pythonclass

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public class pythonclass {

    private String name;
    private int age;
    private String val;

    public pythonclass(String val){
    this.val=val;
    }

    public String getAll() {
    return "name:"+name+"-age:"+age+"-val:"+val;
    }

    public void setName(String name) {
    this.name = name;
    }

    public void setAge(int age) {
    this.age = age;
    }

    }

    image-20211225152449996

    然后新建一个python的文件来调用java代码

    app/src/main/python/pythonUsejava.py:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from java import jclass
    # python调用Java类
    def get_java_test():
    pythonclass = jclass("com.qqq.pytest.pythonclass")#用自己的包名
    javaobj = pythonclass("good success")
    javaobj.setName("python-java")
    javaobj.setAge(1)

    return javaobj

    在python代码里面,可以引入一些python库的文件,必须在app/build.gradle里面安装,安装后编写python代码可能报错未找到这些pyyhon库,可以无视,编译后安装的app可以运行的

    为了调用这个python文件,还是得先使用java调用python,然后python调用java,实现代码之间的互交。

    Python py = Python.getInstance();执行之后,使用java调用一下pythonUsejava.py里面的代码

    1
    2
    3
    4
    5
    private void pythontojava(){
    PyObject pyo=py.getModule("pythonUsejava").callAttr("get_java_test");
    pythonclass pc= pyo.toJava(pythonclass.class);
    Toast.makeText(this,pc.getAll(),Toast.LENGTH_LONG).show();
    }

    之后使用Toast显示调用后返回修改的内容

    为了方便,就在TextView添加点击事件,调用“pythontojava()”函数

    1
    2
    3
    4
    5
    6
    tv.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    pythontojava();
    }
    });

    最后,全文完整的MainActivity的代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    public class MainActivity extends AppCompatActivity {
    Python py;
    TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tv=(TextView)findViewById(R.id.my_id);
    initPython();
    startpython();
    tv.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    pythontojava();
    }
    });
    }
    // 初始化python
    private void initPython(){
    if (! Python.isStarted()) {
    Python.start(new AndroidPlatform(this));
    }
    }

    private void startpython(){
    py = Python.getInstance();
    PyObject pyo= py.getModule("mypython").callAttr("getString");
    tv.setText(pyo.toJava(String.class));
    }

    private void pythontojava(){
    PyObject pyo=py.getModule("pythonUsejava").callAttr("get_java_test");
    pythonclass pc= pyo.toJava(pythonclass.class);
    Toast.makeText(this,pc.getAll(),Toast.LENGTH_LONG).show();
    }

    }

    image-20211225154516548

    运行并点击TextView 的效果如下

    image-20211225154822233

    运行成功

    参考链接

    Chaquopy(Python SDK for Android)官方链接:
    https://chaquo.com/chaquopy/

    Android-Python混合开发 1 (java和python互相调用):

    https://www.jianshu.com/p/a875b0f37a88

    Android studio中编写Python代码-1:

    https://www.jianshu.com/p/73bd89712ddb

    上一篇:
    打造Android最简单优雅的Linux面板
    下一篇:
    对 栈 的理解
    本文目录
    本文目录