Android修行手册-集成Python开发环境

news2024/11/17 18:26:56
Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总
游戏脚本-辅助自动化Android控件全解手册再战Android系列
Scratch编程案例软考全系列Unity3D学习专栏
蓝桥系列ChatGPT和AIGC

👉关于作者

专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)
有什么需要欢迎底部卡片私我,交流让学习不再孤单

在这里插入图片描述

👉实践过程

😜前言

出于业余兴趣,我几年前一直想研究关于Python移植到Android上的实现方案,就像JNI开发一样真正的在Andorid中进行混合Python编程。但出于上班忙时间少,加上人生大事精力有限,人的惰性等等原因,一直没有深入探索,直到2024年有项目需要集成Python,就准备查询下资料,发现已经有人做了我一直想做的事,而且已经做得比较完善了,更可喜的是思路大体一致。

真是应了那句话:你能想到的东西,世界上一定已经存在了,只不过你还没见到而已。

支持AGP版本和Python运行版本
在这里插入图片描述

😜配置环境

首先你需要确保已经安装好了Python环境,并且环境变量也配置好了,Python 的安装包可以一键帮我们都处理好,只需要你仔细看清安装弹框中的说明做好勾选即可。

gradle的版本不同,build.gradle中的写法不同,读者根据自己的环境做好对应。

找到工程目录的 build.gradle

buildscript { //写法一
    repositories {
        google()
        maven { url 'https://jitpack.io' }
        maven { url 'https://maven.aliyun.com/nexus/content/repositories/releases/' }
        maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
        maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/public' }
        maven { url 'https://maven.aliyun.com/repository/jcenter' }
        maven { url "https://chaquo.com/maven" } //python插件的地址 
        mavenCentral()
    }

    dependencies {
        classpath("com.android.tools.build:gradle:7.0.2")
        classpath "com.chaquo.python:gradle:15.0.1" //python插件的版本,尽量用新的,支持的内容多 也修复了很多问题
//        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21"
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}
plugins { //写法二
    id 'com.android.application' version '8.0.2' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
    id 'com.chaquo.python' version '15.0.1' apply false   //这个是重点
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

具体项目的 build.gradle

plugins {
    id 'com.android.application'
    id 'com.chaquo.python'  //集成python必备
}

android {
    compileSdk 32
    defaultConfig {
        applicationId "com.example.myapplication"
        minSdk 26
        targetSdk 32
        versionCode 1
        versionName "1.0"
        ndk {
            abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
        }
        python {
            buildPython "D:\\Program Files\\Python\\python.exe" //不同的人电脑环境不同
            pip {
                install "matplotlib"  //如果想要安装三方包
//                // 需求说明符,带或不带版本号:
//                install "scipy"
//                install "requests==2.24.0"
//                // 相对于项目目录的sdist或wheel文件名:
//                install "MyPackage-1.2.3-py2.py3-none-any.whl"
//                // 包含setup.py的目录,相对于项目
//                // 目录(必须包含至少一个斜杠):
//                install "./MyPackage"
//                // "-r" '后面跟着一个需求文件名,相对于
//                // 项目目录:
//                install "-r", "requirements.txt"
            }
        }
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
}

在这里插入图片描述

工程下的 setting.gradle

//开发andorid的都知道 gradle 配置的写法 变动的很大 下方的设置看需要和你的当下项目是否类似再写。
pluginManagement {
    repositories {
        google()
        maven { url 'https://jitpack.io' }
        maven { url 'https://maven.aliyun.com/nexus/content/repositories/releases/' }
        maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
        maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
        maven { url "https://chaquo.com/maven" } //确保这个地址
        mavenCentral()
    }
    plugins {
        id 'com.android.application' version '7.1.0-alpha11'
        id 'com.android.library' version '7.1.0-alpha11'
        id 'org.jetbrains.kotlin.android' version '1.6.21'
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        maven { url 'https://jitpack.io' }
        maven { url 'https://maven.aliyun.com/nexus/content/repositories/releases/' }
        maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
        maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
        maven { url "https://chaquo.com/maven" } //确保这个地址
        mavenCentral()
    }
}
rootProject.name = "My Application"
include ':app'

😜代码实战

代码要写在具体项目的 main 目录的 python 文件夹。
在这里插入图片描述
Python中代码

from java import jclass
def sayHello():
    print("这是一个测试")


def greet(name):
    print("--- hello,%s ---" % name)

def add(a,b):
    return a + b

def sub(count,a=0,b=0,c=0):
    return count - a - b -c

def get_list(a,b,c,d):
    return [a,b,c,d]

def print_list(data):
    print(type(data))
    # 遍历Java的ArrayList对象
    for i in range(data.size()):
        print(data.get(i))

# python调用Java类
def get_java_bean():
    JavaBean = jclass("org.hello.JavaBean")  # 实体类的类名
    jb = JavaBean("python")
    jb.setData("json")
    jb.setData("xml")
    jb.setData("xhtml")
    return jb

Java中代码
核心思想便是对象转换,PyObject类是桥梁,fromJava函数将一个Java对象转换为相应的Python对象,toJava函数正好相反,将Python中的对象转换成Java中的对象

public class TestPython extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_python);
        if (!Python.isStarted()) {
            Python.start(new AndroidPlatform(this));  //可以放到app里进行初始化
        }
        Python python = Python.getInstance();
        PyObject pyObject = python.getModule("hello");  //调用的文件名
        pyObject.callAttr("sayHello"); //调用的方法名

        Python py = Python.getInstance();
        // 调用hello.py模块中的greet函数,并传一个参数
        // 等价用法:py.getModule("hello").get("greet").call("Android");
        py.getModule("hello").callAttr("greet", "Android");

        // 调用python内建函数help(),输出了帮助信息
        py.getBuiltins().get("help").call();

        PyObject obj1 = py.getModule("hello").callAttr("add", 2,3);
        // 将Python返回值换为Java中的Integer类型
        Integer sum = obj1.toJava(Integer.class);
        Log.d("TAG","add = "+sum.toString());

        // 调用python函数,命名式传参,等同 sub(10,b=1,c=3)
        PyObject obj2 = py.getModule("hello").callAttr("sub", 10,new Kwarg("b", 1), new Kwarg("c", 3));
        Integer result = obj2.toJava(Integer.class);
        Log.d("TAG","sub = "+result.toString());

        // 调用Python函数,将返回的Python中的list转为Java的list   也可以使用map
        PyObject obj3 = py.getModule("hello").callAttr("get_list", 10,"xx",5.6,'c');
        List<PyObject> pyList = obj3.asList();
        Log.d("TAG","get_list = "+pyList.toString());

        // 将Java的ArrayList对象传入Python中使用
        List<PyObject> params = new ArrayList<PyObject>();
        params.add(PyObject.fromJava("alex"));
        params.add(PyObject.fromJava("bruce"));
        py.getModule("hello").callAttr("print_list", params);

        // Python中调用Java类
        PyObject obj4 = py.getModule("hello").callAttr("get_java_bean");
        JavaBean data = obj4.toJava(JavaBean.class);
        data.print();


        Python pyTe = Python.getInstance(); //matplotlib库的方法
        PyObject module = pyTe.getModule("plot"); //文件名
        byte[] dddz = module.callAttr("plot", "1 2 3 4", "1 2 3 4").toJava(byte[].class);
        ImageView img = findViewById(R.id.testImg);
        img.setImageBitmap(BitmapFactory.decodeByteArray(dddz, 0, dddz.length));
    }
}
  • Python.getInstance():获取Python运行环境,映射为Java中的Python;
  • py.getModule:执行指定的Python文件,映射为Java中的PyObject;
  • module.callAttr:执行Python文件中指定的方法,并传递参数,返回PyObject对象;

kotlin代码自行转换即可。

😜原理

简单说就是以android的JNI技术为桥梁,JNI技术解决了Java与C/C++混合编程的问题,而Python官方解释器则是纯C语言实现的,名为CPython解释器,在Android上,Python解释器就是一个so动态库。JNI接口使得C语言能反射Java的类与方法,而Python运行在C语言之上,那么Python也就具备了调用Java的能力。整个过程就是Java调用C语言代码,C再调用CPython解释器从而执行Python代码;Python调用CPython解释器,CPython调用C语言代码,C语言代码再反射Java代码,完成一次反调。这之间,粘合Java与CPython解释器的一段C语言代码,也就是Chaquopy框架干的事。
在这里插入图片描述

😜可能得问题

  1. 当你刚配置好环境第一次运行了 python 的 hello word 后,就开始蠢蠢欲动准备搞一搞集成三方库。可以当你在 build.gradle 中配置好 pip 一运行,发现有可能出现下面的问题:
    Process ‘command ‘C:\Users\Administrator\AppData\Local\Programs\Python\Python312\python.exe’’ finished with non-zero exit value 1
    静下心来好好想想,区别就在 pip 安装三方库上,Android 上既然是 Chaquopy 远程安装那么就得往该插件上考虑。在整个过程中我们的配置只有两个地方是可变动的,
    一个是 python 的安装路径,一个是 Chaquopy 的版本号。本地安装路径如果和配置不一致,不是这个错误。那么只有一个问题,就是 Chaquopy 的版本。
    我们切换最新的试试,发现解决了。
  2. Chaquopy 不是支持所有的三方库,这是最难搞的事情。具体可从这查看。点击跳转
  3. 还可以实现 Python 自动生成 Java的类,但是该功能用处不大,想要了解的可自行搜索静态代理。
  4. Chaquopy是线程安全的。但是,因为它基于CPython(Python参考实现),所以它受到CPython的全局解释器锁(GIL)的限制。这意味着尽管Python代码可以在任意数量的线程上运行,但在任何给定时刻只会执行其中一个线程。
  5. 如果Python对象引用直接或间接引用原始Python对象的Java对象,则可以创建跨语言引用循环。任何一种语言的垃圾收集器都无法检测到这样的循环。所以避免内存泄漏很重要。Python代码就需要写的很合理。

👉其他

📢作者:小空和小芝中的小空
📢转载说明-务必注明来源:https://zhima.blog.csdn.net/
📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

温馨提示点击下方卡片获取更多意想不到的资源。
空名先生

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

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

相关文章

redis实现分布式全局唯一id

目录 一、前言二、如何通过Redis设计一个分布式全局唯一ID生成工具2.1 使用 Redis 计数器实现2.2 使用 Redis Hash结构实现 三、通过代码实现分布式全局唯一ID工具3.1 导入依赖配置3.2 配置yml文件3.3 序列化配置3.4 编写获取工具3.5 测试获取工具 四、运行结果 一、前言 在很…

PySide6+VSCode Python可视化环境搭建

#记住在cmd中运行&#xff0c;不要在vscode里运行&#xff0c;否则env会装到工程目录下 python -m venv env #env\Scripts\activate.bat pip install pyside6 下载本期源码 vscode装一个PYQT Integration插件&#xff0c;设置好两个路径&#xff08;下面有个脚本用于获取路径&…

陶瓷工业5G智能制造工厂数字孪生可视化平台,推进行业数字化转型

陶瓷工业5G智能制造工厂数字孪生可视化平台&#xff0c;推进行业数字化转型。在陶瓷工业领域&#xff0c;5G智能制造工厂数字孪生可视化平台的应用正在改变着行业的传统生产模式&#xff0c;推动着数字化转型的进程。本文将围绕这一主题展开探讨&#xff0c;分析数字孪生可视化…

Socket网络编程(四)——点对点传输场景方案

目录 场景如何去获取到TCP的IP和Port&#xff1f;UDP的搜索IP地址、端口号方案UDP搜索取消实现相关的流程&#xff1a;代码实现逻辑服务端实现客户端实现UDP搜索代码执行结果 TCP点对点传输实现代码实现步骤点对点传输测试结果 源码下载 场景 在一个局域网当中&#xff0c;不知…

Win11系统安装安卓子系统教程

随着Win11系统的不断普及&#xff0c;以及硬件设备的更新换代&#xff0c;我相信很多同学都已经更新并使用到了最新的Win11系统。那么&#xff0c;Win11系统最受期待的功能“Windows Subsystem for Android”&#xff08;简称WSA&#xff09;&#xff0c;即《安卓子系统》。他可…

CAPL组装IPv4分片包的三种思路(2)

2、使用CAPL的函数自动生成一条完整的ICMPv4 Echo Request报文,然后把数据手动放入两个分片报文中 首先生成一条完整的icmp报文: ethernetPacket ppkt1;//icmpv4 echo requestbyte data[1] = {10};//icmpv4 echo request datappkt1.icmpv4.echo…

湖南湘菜 7页面 美食主题 带设计说明 美食网页设计制作 HTML美食网页成品 美食网页成品 HTML美食网页设计

湖南湘菜 7页面 美食主题 带设计说明 jquery图片轮播特效 滚动文字 aspaccess数据库注册登录留言功能 美食网页设计制作 HTML美食网页成品 美食网页成品 HTML美食网页设计制作 前端美食网页开发 热门美食特产网页制作 静态网页成品 asp/php动态网站设计制作DW定制定做 web前…

佛山50公里徒步组团|真北敏捷社区佛山敏捷DevOps社区

真北敏捷社区&佛山敏捷DevOps社区有两个宗旨&#xff0c;一是求知&#xff0c;二是连接。连接有识之士&#xff0c;同修友士之识。峨峨乎高山&#xff0c;洋洋乎流水。谈笑有鸿儒&#xff0c;往来无白丁。 《柳叶刀》上的研究显示&#xff0c;运动的情绪价值&#xff0c;相…

GitHub Copilot extension activation error: ‘No access to GitHub Copilot found‘

好不容易学生认证通过了&#xff0c;打开vscode用copilot结果一直报这个错误。我的原因是&#xff1a;还未给copilot授权&#xff0c; 通过了学生认证后要进入这里进行授权&#xff1a;

数据分析-Pandas数据探查初步圆饼图

数据分析-Pandas数据探查初步圆饼图 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&am…

PHP使用imap_open读取QQ邮箱

PHP代码&#xff1a; /** PHP使用imap_open读取QQ邮箱imap_open 官方文档&#xff1a;https://www.php.net/function.imap_open */function parse_mailstr($subject) {$a explode(?,$subject);$n count($a);$a $a[$n-2];return base64_decode($a); }function recevie_emai…

点亮城市名片丨计讯物联智慧灯杆系统在通讯基地的成功应用

项目背景 在国家新型城镇化大背景下&#xff0c;十四五规划纲要强调“加快数字化发展&#xff0c;建设数字中国”&#xff0c;明确提出“以数字化助推城乡发展和治理模式创新”&#xff0c;全面提高城市的运行效率和宜居程度。 项目概况 为满足灯杆灯光亮度的远程智能管理、对…

docker构建hyperf环境

一&#xff0c;构建hyperf 镜像 官网git https://github.com/hyperf/hyperf-docker 使用dockerfile构建镜像 根据需要这里我使用8.1 swoole版本的镜像 在/home/hyperfdocker 目录中新建一个Dockerfile文件&#xff0c;将这个git上的Dockerfile内容复制粘贴进去 docker build…

Linux--使用 Haproxy搭建Web群集

1、 案例概述 Haproxy是目前比较流行的一种群集调度工具&#xff0c;同类群集调度工具有很多&#xff0c;如LVS 和 Nginx。相比较而言&#xff0c;LVS性能最好&#xff0c;但是搭建相对复杂&#xff1a;Nginx的upstream 模块支持群集功能&#xff0c;但是对群集节点健康检查功能…

java 基础上(1)(核心知识搭配代码)

前言 java的学习分为了上部分以及下部分进行学习&#xff0c;上部分就是对于java的基础知识&#xff0c;面向对象上&#xff0c;面向对象下&#xff0c;异常操作&#xff0c;javaApi&#xff1b;下部主要是集合&#xff0c;泛型&#xff0c;反射&#xff0c;IO流&#xff0c;J…

Ubuntu篇——crontab修改编辑器

输入命令: crontab -e 如果你的系统是第一次使用crontab服务&#xff0c;会首先让你选择一个编辑器 如果已经选择过编辑器&#xff0c;后续想要修改默认编辑器&#xff0c;可以输入sudo select-editor进行修改。

【市工信】2024年青岛市绿色工厂、绿色工业园区等绿色制造示范申报

科大睿智小编从青岛市工信局了解到&#xff0c;为深入贯彻绿色发展理念&#xff0c;牢固树立绿色低碳发展导向&#xff0c;进一步完善绿色制造体系&#xff0c;培育绿色制造先进典型&#xff0c;根据《工业和信息化部关于印发<绿色工厂梯度培育及管理暂行办法>的通知》&a…

【PyTorch][chapter 20][李宏毅深度学习]【无监督学习][ GAN]【实战】

前言 本篇主要是结合手写数字例子,结合PyTorch 介绍一下Gan 实战 第一轮训练效果 第20轮训练效果,已经可以生成数字了 68 轮 目录&#xff1a; 谷歌云服务器&#xff08;Google Colab&#xff09; 整体训练流程 Python 代码 一 谷歌云服务器&#xff08;Google Colab&…

List<Object>集合对象属性拷贝工具类

目录 问题现象&#xff1a; 问题分析&#xff1a; 解决方法&#xff1a; 问题现象&#xff1a; 最近在项目中经常会使用到BeanUtils工具类来作对象的属性字段拷贝&#xff0c;但如果应用到List集合的话就需要遍历去操作了&#xff0c;如下&#xff1a; 打印结果&#xff1a; …

分类问题经典算法 | 二分类问题 | Logistic回归:公式推导

目录 一. Logistic回归的思想1. 分类任务思想2. Logistic回归思想 二. Logistic回归算法&#xff1a;线性可分推导 一. Logistic回归的思想 1. 分类任务思想 分类问题通常可以分为二分类&#xff0c;多分类任务&#xff1b;而对于不同的分类任务&#xff0c;训练的主要目标是…