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 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/
📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络——22TCP拥塞

TCP拥塞 TCP拥塞控制机制 端到端的拥塞控制机制 路由器不向主机有关拥塞的反馈信息 路由器的负担较轻符合网络核心简单的TCP/IP架构原则 端系统根据自身得到的信息&#xff0c;判断是否发生拥塞&#xff0c;从而采取动作 拥塞控制的几个问题 如何检测拥塞 轻微拥塞拥塞 控…

【Maven】Maven 基础教程(三):build、profile

《Maven 基础教程》系列&#xff0c;包含以下 3 篇文章&#xff1a; Maven 基础教程&#xff08;一&#xff09;&#xff1a;基础介绍、开发环境配置Maven 基础教程&#xff08;二&#xff09;&#xff1a;Maven 的使用Maven 基础教程&#xff08;三&#xff09;&#xff1a;b…

Vue+SpringBoot打造个人保险管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 登录注册模块2.2 保险档案模块2.3 保险订单模块2.4 保险理赔模块 三、系统展示四、核心代码4.1 查询保险产品4.2 新增保险预定4.3 订单支付4.4 新增理赔单4.5 查询保险理赔 五、免责说明 一、摘要 1.1 项目介绍 基于J…

计算以e为底1+x的自然对数 即ln(1+x) math.log1p(x)

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 计算以e为底 1x的自然对数 即ln(1x) math.log1p(x) [太阳]选择题 请问执行以下程序的运行结果是&#xff1a; import math print("【执行】math.log1p(0)") print (math.log1p(0)) …

服务端向客户端推送数据的实现方案

在日常的开发中&#xff0c;我们经常能碰见服务端需要主动推送给客户端数据的业务场景&#xff0c;比如数据大屏的实时数据&#xff0c;比如消息中心的未读消息&#xff0c;比如聊天功能等等。 本文主要介绍SSE的使用场景和如何使用SSE。 服务端向客户端推送数据的实现方案有哪…

Vue路由模式

聚沙成塔每天进步一点点 本文内容 ⭐ 专栏简介路由模式1. Hash 模式2. History 模式选择路由模式的考虑因素 ⭐ 写在最后 ⭐ 专栏简介 Vue学习之旅的奇妙世界 欢迎大家来到 Vue 技能树参考资料专栏&#xff01;创建这个专栏的初衷是为了帮助大家更好地应对 Vue.js 技能树的学习…

Node.js中的数据加密和安全传输

在当今日益数字化的世界中&#xff0c;数据安全一直是一个备受关注的话题。Node.js作为一种流行的后端开发技术&#xff0c;其在数据加密和安全传输方面的应用也备受关注。本篇博客将深入探讨Node.js中的数据加密和安全传输相关内容&#xff0c;并为读者提供一些示例代码&#…

vue实现水印功能

目录 一、应用场景 二、实现原理 三、详细开发 1.水印的实现方式 2.防止用户通过控制台修改样式去除水印效果&#xff08;可跳过&#xff0c;有弊端&#xff09; 3.水印的使用 &#xff08;1&#xff09;单页面/全局使用 &#xff08;2&#xff09;全局使用个别页面去掉…

【投稿优惠|快速见刊】2024年图像,机器学习和人工智能国际会议(ICIMLAI 2024)

【投稿优惠|快速见刊】2024年图像&#xff0c;机器学习和人工智能国际会议&#xff08;ICIMLAI 2024&#xff09; 重要信息 会议官网&#xff1a;http://www.icimlai.com会议地址&#xff1a;深圳召开日期&#xff1a;2024.03.30截稿日期&#xff1a;2024.03.20 &#xff08;先…

音视频开发之旅(72)- AI数字人-照片说话之SadTalker

目录 1.效果展示 2.SadTalker原理学习 3.SadTalker代码流程分析 4.性能优化 5.参考资料 AI数字人目前做的最好的无疑是heygen&#xff0c;但是费用也是很贵&#xff0c;也有一些其他的商业应用&#xff0c;比如&#xff1a;微软小冰、腾讯智影、万兴播爆和硅基智能等。 而…

如何确保JDK版本与操作系统架构匹配?

1. 序言 最近的工作中&#xff0c;需要升级JDK版本到17.0.7&#xff0c;以解决一个JDK bug&#xff1a;JDK-8299626该bug的core dump关键字如下&#xff1a;SIGSEGV in PhaseIdealLoop::build_loop_late_post_work公司JDK团队提供的、包含JDK的基础镜像&#xff0c;有aarch64和…

基于C#开发OPC DA客户端——搭建KEPServerEX服务

简介 OPC DA (OLE for Process Control Data Access) 是一种工业自动化领域中的通信协议标准&#xff0c;它定义了应用程序如何访问由OPC服务器提供的过程控制数据。OPC DA标准允许软件应用程序&#xff08;客户端&#xff09;从OPC服务器读取实时数据或向服务器写入数据&…

elment-ui table表格排序后 清除排序箭头/恢复默认排序 的高亮样式

问题描述&#xff1a; 1.默认排序是按照名称升序排列&#xff08;图一&#xff09; 2.在选择了筛选项以及其他排序方式之后&#xff0c;箭头高亮是这样的&#xff08;图二&#xff09; 3.当我点击清空按钮后&#xff0c;类型清空了&#xff0c;并且传给后端的排序方式是名称/升…

数据库管理-第157期 Oracle Vector DB AI-08(20240301)

数据库管理157期 2024-03-01 数据库管理-第157期 Oracle Vector DB & AI-08&#xff08;20240301&#xff09;1 创建示例向量2 查找最近向量3 基于向量簇组的最近向量查询总结 数据库管理-第157期 Oracle Vector DB & AI-08&#xff08;20240301&#xff09; 作者&…

蓝桥杯-单片机组基础5——外部中断与LED的控制(附小蜜蜂课程代码)

蓝桥杯单片机组备赛指南请查看这篇文章&#xff1a;戳此跳转蓝桥杯备赛指南文章 本文章针对蓝桥杯-单片机组比赛开发板所写&#xff0c;代码可直接在比赛开发板上使用。 型号&#xff1a;国信天长4T开发板&#xff08;绿板&#xff09;&#xff0c;芯片&#xff1a;IAP15F2K6…

二叉搜索树在线OJ题讲解

二叉树创建字符串 我们首先进行题目的解读&#xff1a; 大概意思就是用&#xff08;&#xff09;把每个节点的值给括起来&#xff0c;然后再经过一系列的省略的来得到最后的结果 大家仔细观察题目给出的列子就可以发现&#xff0c;其实这个题目可以大致分为三种情况&#xff1…

git安装与使用4.3

一、git的安装 1、下载git包 下载git包url&#xff1a;https://git-scm.com/download/win 下载包分为&#xff1a;64位和32位 2、点击安装包 2、选择安装路径 3、 点击下一步 4、点击next 5、点击next 6、点击next 7、 8、 9、 10、 11、 12、在桌面空白处&#xff0c;右键…

服务器上部署WEb服务方法

部署Web服务在服务器上是一个比较复杂的过程。这不仅仅涉及到配置环境、选择软件和设置端口&#xff0c;更有众多其它因素需要考虑。以下是在服务器上部署WEb服务的步骤&#xff1a; 1. 选择服务器&#xff1a;根据项目规模和预期访问量&#xff0c;选择合适的服务器类型和配置…

2024.02.29作业

1. TCP模型 server #include "test.h"#define SER_IP "192.168.191.128" #define SER_PORT 9999int main(int argc, char const *argv[]) {int sfd -1;sfd socket(AF_INET, SOCK_STREAM, 0);if (-1 sfd){perror("socket error");return -1;…

Tomcat部署Web服务器及基础功能配置

前言 Tomcat作为一款网站服务器&#xff0c;目前市面上Java程序使用的比较多&#xff0c;作为运维工人&#xff0c;有必要了解一款如何去运行Java环境的网站服务。 目录 一、Java相关介绍 1. Java历史 2. Java跨平台服务 3. Java实现动态网页功能 3.1 servelt 3.2 jsp …