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

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 falseid 'org.jetbrains.kotlin.android' version '1.6.21' apply falseid '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 32defaultConfig {applicationId "com.example.myapplication"minSdk 26targetSdk 32versionCode 1versionName "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 falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility 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 + bdef sub(count,a=0,b=0,c=0):return count - a - b -cdef 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 {@Overrideprotected 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   也可以使用mapPyObject 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.mzph.cn/news/713467.shtml

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

相关文章

Apache Flink连载(三十五):Flink基于Kubernetes部署(5)-Kubernetes 集群搭建-1

🏡 个人主页:IT贫道-CSDN博客 🚩 私聊博主:私聊博主加WX好友,获取更多资料哦~ 🔔 博主个人B栈地址:豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录 ​编辑

Python爬虫——Urllib库-2

编解码 问题引入 例如&#xff1a; https://www.baidu.com/s?wd章若楠 https://www.baidu.com/s?wd%E7%AB%A0%E8%8B%A5%E6%A5%A0 第二部分的一串乱码就是章若楠 如果这里是写的章若楠就会 产生这样的错误 所以我们就可以使用get请求方式的quote方法了 get请求方式的q…

laravel ApiResponse接口统一响应封装

一&#xff0c;新增接口返回码配置文件 在config中新增配置文件apicode.php <?phpreturn [ apicodes>[/*** Message("OK")* 对成功的 GET、PUT、PATCH 或 DELETE 操作进行响应。也可以被用在不创建新资源的 POST 操作上*/HTTP_OK > 200,/*** Message(&qu…

使用el-form之表单校验自动定位到报错位置问题,,提升用户体验

需求描述 由于需要填写的表单项太多&#xff0c;提交的时候校验不通过&#xff0c; 如果没填写的表单项在最上面&#xff0c;用户看不到不知道发生了啥&#xff0c; 所以需要将页面滚动定位到第一个报错的表单项位置&#xff0c;提升用户体验实现步骤 1. 给form表单添加ref …

数据中心GPU集群高性能组网技术分析

数据中心GPU集群组网技术是指将多个GPU设备连接在一起&#xff0c;形成一个高性能计算的集群系统。通过集群组网技术&#xff0c;可以实现多个GPU设备之间的协同计算&#xff0c;提供更大规模的计算能力&#xff0c;适用于需要大规模并行计算的应用场景。 常用的组网技术&…

1209. 带分数 刷题笔记

思路 暴力匹配 读入目标数 n 看n是否与ab/c相等 因为c里面的除法是整除 我们将 nab/c 转换为 c*na*cb 那么如何获得a,b&#xff0c;c 依题意 a&#xff0c;b&#xff0c;c三个数由1-9九个数字组成 且每个数字只能出现一次 由此 我们可以搜出123456789的全部排列方式…

我做的app上架应用市场一天,快破400下载量,0差评

上集说到&#xff0c;我做了一个叫QB音乐的安卓app&#xff0c;经过一段时间的自我使用与测试终于算发布了。我昨天顺便把它上架了奇妙应用市场&#xff0c;截止目前3月1号过去了一天&#xff0c;下载量快到400&#xff0c;0差评。看来还是能正常使用的。 一、为什么做这个ap…

CleanMyMac X2024免费Mac电脑清理和优化工具

CleanMyMac X是一款专业的 Mac 清理和优化工具&#xff0c;它具备一系列强大的功能&#xff0c;可以帮助用户轻松管理和维护他们的 Mac 电脑。以下是一些关于 CleanMyMac X 的主要功能和特点&#xff1a; 智能清理&#xff1a;CleanMyMac X 能够智能识别并清理 Mac 上的无用文件…

深入剖析k8s-Pod篇

为什么需要Pod&#xff1f; 进程是以进程组的方式组织在一起。受限制容器的“单进程模型”&#xff0c; 成组调用没有被妥善处理&#xff08;资源调用有限&#xff09;&#xff0c;使用资源囤积则导致复杂度上升。 在k8s项目中&#xff0c;Pod的实现需要使用一个中间容器——…

css【详解】—— 圣杯布局 vs 双飞翼布局 (含手写清除浮动 clearfix)

两者功能效果相同&#xff0c;实现方式不同 效果预览 两侧宽度固定&#xff0c;中间宽度自适应&#xff08;三栏布局&#xff09;中间部分优先渲染允许三列中的任意一列成为最高列 圣杯布局 通过左右栏填充容器的左右 padding 实现&#xff0c;更多细节详见注释。 <!DOCTYP…

《无线网络技术》考试版笔记

第一章 无线网络介绍 什么是多径效应&#xff0c;如何去克服&#xff1a; 在发射机和接收机之间没有明显的直线路径时&#xff0c;就会产生多径传播。如果两个信号彼此叠加&#xff0c;那么接收设备就无法正确解调信号&#xff0c;无法还原为它的原始数据形式。 可以稍微调整接…

USLE模型-LS因子的计算

目录 计算坡度计算填洼计算流向计算水流长度计算水平投影![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/75e015b2d6874ce9b6652f2b8730b90f.png)计算可变的坡度指数m计算坡长因子L计算坡度因子S计算LS因子参考视频 计算坡度 准备好30米分辨率的dem 计算填洼 计…

速看!深夜悄悄分享一个电力优化代码集合包!

代码集合包如下&#xff1a; 主从博弈的智能小区定价策略及电动汽车调度策略 碳交易机制下的综合能源优化调度 两阶段鲁棒优化算法的微网多电源容量配置 冷热电多能互补综合能源系统优化调度 考虑预测不确定性的综合能源调度优化 考虑柔性负荷的综合能源系统低碳经济优化调度 考…

C语言学生成绩信息管理系统【结构体+文本】

功能描述&#xff1a; 1、录入成绩 2、显示不及格学生信息 3、统计每档学生数量 4、总成绩统计 代码&#xff1a; #include<stdio.h>#define N 30//结构体&#xff1a;typedef struct STUDENT{char id[10];//学号char name[20];//姓名float score[3];//三门成绩,分别代…

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

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

生成式人工智能治理:入门的基本技巧

GenAI 以前所未有的速度调解并扰乱了“一切照旧”&#xff0c;同时带来了令人难以置信的力量&#xff0c;但也带来了不可否认的责任。当然&#xff0c;现代企业非常熟悉技术进步。然而&#xff0c;人工智能的到来&#xff08;和实施&#xff09;无疑引起了相当大的冲击&#xf…

Linux服务:Nginx反向代理与负载均衡

一、Nginx反向代理 1、什么是反向代理&#xff1f; 代理分为两类&#xff0c;正向代理和反向代理。 ①正向代理&#xff1a;帮助用户访问服务器&#xff0c;缓存服务器内容。 ②反向代理&#xff1a;代理服务器处理用户的请求&#xff0c;决定转发请求给谁处理负载均衡的作…

Go 与 Rust:导航编程语言景观

在当今构建软件时&#xff0c;开发者在编程语言上有着丰富的选择。两种脱颖而出的语言是 Go 和 Rust - 都很强大但却截然不同。本文将从各种因素比较这两种语言&#xff0c;以帮助您确定哪种更适合您的需求。 我们将权衡它们在并发、安全性、速度、互操作性等方面的方法。我们将…

Ubuntu篇——crontab修改编辑器

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

Node.js基础---Express中间件

1. 概念 1.什么是中间件 中间件(Middleware)&#xff0c;特指业务流程的中间处理环节 2. Express 中间件的调用流程 当一个请求到达 Express 的服务器后&#xff0c;可以连续调用多个中间件&#xff0c;从而对这次请求进行预处理 3. Express 中间件格式 Express 的中间件&…