{"id":411746,"date":"2024-06-29T22:08:46","date_gmt":"2024-06-29T22:08:46","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=411746"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-06-29T22:08:46","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=411746","title":{"rendered":"<span>Java \u0438\u0437 Python (Kivy) \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043d\u0430 Android<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<div style=\"text-align:center;\"><img decoding=\"async\" alt=\"main\" width=\"500\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/sy\/ra\/fq\/syrafqsvd4_mmn0mirip50wfiig.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/sy\/ra\/fq\/syrafqsvd4_mmn0mirip50wfiig.jpeg\" data-blurred=\"true\"\/><\/div>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/656453\/\">C\/C++ \u0438\u0437 Python (ctypes) \u043d\u0430 Android<\/a>. \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>Java<\/strong> \u0438\u0437 <strong>Python<\/strong>, \u0432\u0435\u0434\u044c \u0434\u043b\u044f <strong>android<\/strong> \u044d\u0442\u043e \u0440\u043e\u0434\u043d\u043e\u0439 \u044f\u0437\u044b\u043a \u0438 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043d\u0443\u0436\u043d\u044b\u0435 \u0432\u0435\u0449\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 \u043d\u0435\u043c. \u041d\u0430\u0443\u0447\u0438\u043c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u044b, \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438 \u0434\u0435\u0440\u0433\u0430\u0442\u044c callback-\u0438. \u041d\u0430 <strong>Linux<\/strong> \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h2 id=\"java\">Java<\/h2>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0434\u0432\u0430 \u0444\u0430\u0439\u043b\u0430 Test.java \u0438 CallbackWrapper.java. \u0418 \u0437\u0430\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0438\u0445 \u0432 \u043f\u0430\u043f\u043a\u0443 <strong>java\/some\/kivy_test<\/strong> \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0412 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043f\u0430\u043f\u043a\u0443 <strong>java<\/strong> \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0432 <strong>buildozer.spec<\/strong>.<\/p>\n<p>  <\/p>\n<p>Test.java:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">package some.kivy_test;  \/\/ \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 CallbackWrapper \u0438\u0437 CallbackWrapper.java import some.kivy_test.CallbackWrapper;  \/**     \\brief \u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441.      \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0430\u0431\u043e\u0440 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 \u0438\u0437 python \u0438 \u0432 python (main.py). *\/ public class Test {     CallbackWrapper wrapper = null;      \/**         \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u0430         \\param callback_wrapper \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 callback_wrapper \u0438\u0437 main.py     *\/     public Test(CallbackWrapper callback_wrapper) {         this.wrapper = callback_wrapper;     }      \/**         \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u0441\u0442\u0440\u043e\u043a\u0438         \\return \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443     *\/     public String hello() {         return \"Hello from Test.java\";     }      \/**         \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u0441\u0442\u0440\u043e\u043a\u0438         \\param arg1 \u0441\u0442\u0440\u043e\u043a\u0430         \\return \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443     *\/     public String hello2(String arg1) {         return arg1;     }      \/**         \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u0437\u043e\u0432\u0430 callback1 \u0438\u0437 callback_wrapper (main.py)     *\/     public void callback1() {         this.wrapper.callback1();     }      \/**         \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u0437\u043e\u0432\u0430 callback2 \u0438\u0437 callback_wrapper (main.py)     *\/     public void callback2() {         this.wrapper.callback2(\"callback\");     }      \/**         \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u0437\u043e\u0432\u0430 callback3 \u0438\u0437 callback_wrapper (main.py)     *\/     public void callback3() {         this.wrapper.callback3(11, (byte) 22);     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043b\u0430\u0441\u0441 <strong>Test<\/strong> \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430;<\/li>\n<li>\u0432\u044b\u0437\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043a\u043b\u0430\u0441\u0441\u0430;<\/li>\n<li>\u0432\u044b\u0437\u043e\u0432 callback-\u043e\u0432.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>CallbackWrapper.java:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">package some.kivy_test;  \/\/ \u041e\u0431\u0435\u0440\u0442\u043a\u0430 \u0434\u043b\u044f python callback-\u043e\u0432 public interface CallbackWrapper {     public void callback1();     public boolean callback2(String arg1);     public int callback3(int arg1, byte arg2); }<\/code><\/pre>\n<p>  <\/p>\n<p><strong>CallbackWrapper<\/strong> \u2014 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 Java \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432 python.<\/p>\n<p>  <\/p>\n<h2 id=\"python\">Python<\/h2>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a <strong>Kivy<\/strong>, <strong>buildozer<\/strong> \u2014 \u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f apk \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0438 <strong><a href=\"https:\/\/pyjnius.readthedocs.io\/en\/stable\/\" rel=\"nofollow noopener noreferrer\">jnius<\/a><\/strong> \u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043a\u043b\u0430\u0441\u0441\u0430\u043c Java. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043b \u043f\u043e \u0441\u0442\u0430\u0442\u044c\u0435: <a href=\"https:\/\/habr.com\/ru\/post\/479236\/\">Kivy. \u0421\u0431\u043e\u0440\u043a\u0430 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u043f\u043e\u0434 Android \u0438 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u0433\u0438\u0438<\/a><\/p>\n<p>  <\/p>\n<h3 id=\"ustanovka-kivy-buildozer--jnius\">\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 kivy, buildozer &amp; jnius<\/h3>\n<p>  <\/p>\n<pre><code class=\"bash\">sudo pip3 install kivy sudo pip3 install buildozer sudo pip3 install pyjnius<\/code><\/pre>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0432 kivy, buildozer \u0438 jnius \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0430\u043f\u043a\u0443 \u043f\u043e\u0434 \u043d\u0435\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">mkdir android_python cd android_python<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c <strong>main.py<\/strong>, \u044d\u0442\u043e \u0442\u043e\u0447\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043d\u0430\u0448\u0435\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">touch main.py<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u043c \u0435\u0433\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"python\">#!\/usr\/bin\/python3 #-*- coding: utf-8 -*-  import kivy kivy.require(\"2.1.0\") from kivy.app import App from kivy.uix.button import Button  from kivy.utils import platform  import jnius from jnius import cast from jnius import autoclass, PythonJavaClass, java_method  # \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 System System = autoclass('java.lang.System')  # \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 Android if platform == 'android':     PythonActivity = autoclass('org.kivy.android.PythonActivity')     currentActivity = cast('android.app.Activity', PythonActivity.mActivity)  # \u041a\u043b\u0430\u0441\u0441 \u0433\u0440\u0430\u0444\u0438\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 \u0434\u043b\u044f \u0432\u044b\u0445\u043e\u0434\u0430 \u0438\u0437 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. class ButtonApp(App):      def build(self):         # use a (r, g, b, a) tuple         btn = Button(text =\"Push Me !\",                    font_size =\"20sp\",                    background_color = (1, 1, 1, 1),                    color = (1, 1, 1, 1),                    size_hint = (.2, .1),                    pos_hint = {'x':.4, 'y':.45})          # bind() use to bind the button to function callback         btn.bind(on_press = self.callback)         return btn      # callback function tells when button pressed     def callback(self, event):         if platform == 'android':             currentActivity.finishAndRemoveTask()          System.exit(0)  ## # \u041a\u043b\u0430\u0441\u0441 \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u0439 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437 Java ## class CallbackWrapper(PythonJavaClass):     __javacontext__ = 'app'      # \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430     # CallbackWrapper \u0438\u0437 \u043f\u0430\u043a\u0435\u0442\u0430 some.kivy_test     __javainterfaces__ = ['some\/kivy_test\/CallbackWrapper']      def __init__(self):         super().__init__()      ##     # \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f callback-\u043e\u0432 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0432 CallbackWrapper.java.     # \u0418\u043c\u0435\u043d\u0430 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435.     ##     @java_method('()V')     def callback1(self):         print(\"Python: @java_method('()V')\")      @java_method('(Ljava\/lang\/String;)Z')     def callback2(self, arg1):         print(\"Python: @java_method('(Ljava\/lang\/String;)Z'), \", arg1)         return True      @java_method('(IB)I')     def callback3(self, arg1, arg2):         print(\"Python: @java_method('(IB)I'), \", arg1, arg2)         return 555  ## #  \u0421\u0442\u0430\u0440\u0442. ## if __name__ == \"__main__\":     # \u041f\u0435\u0447\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0439 python     print(\"Python: Hello world!\")      # \u0412\u044b\u0437\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u0430 \u043f\u0435\u0447\u0430\u0442\u0438 \u0438\u0437 \u043a\u043b\u0430\u0441\u0441\u0430 System.     System.out.println('I\/python: Java: Hello world!')      if platform == 'android':         # \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u043a\u043b\u0430\u0441\u0441 Test \u0438\u0437 Test.java         Test = autoclass('some.kivy_test.Test')          # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 \u0441 callback-\u043c\u0438, \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f          # \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u0438\u043b\u0438 \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439          # \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430. \u0418\u043d\u0430\u0447\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 Python \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u0440\u0430\u043c\u043a\u0438          # \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430 Python, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043d\u0435\u0433\u043e \u0432\u0441\u0435 \u0435\u0449\u0435          # \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 Java.         global callback_wrapper         callback_wrapper = CallbackWrapper()          # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 Test \u0438\u0437 Test.java, \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0432 \u043d\u0435\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c          # \u043d\u0430 \u043a\u043b\u0430\u0441\u0441 callback-\u043e\u0432         test = Test(callback_wrapper)          # \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438\u0437 \u043a\u043b\u0430\u0441\u0441\u0430 Test         print(\"Python: \", test.hello())         print(\"Python: \", test.hello2(\"test.hello2()\"))          # \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 CallbackWrapper \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445         # \u0437\u0434\u0435\u0441\u044c \u0438\u0437 \u043a\u043b\u0430\u0441\u0441\u0430 Test         test.callback1()         test.callback2()         test.callback3()      # \u041e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f     ButtonApp().run() <\/code><\/pre>\n<p>  <\/p>\n<p><strong>Callback<\/strong>-\u0438 \u0438\u0437 CallbackWrapper \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440 <strong>java_method<\/strong>. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u043d\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 <a href=\"https:\/\/pyjnius.readthedocs.io\/en\/latest\/api.html#java-signature-format\" rel=\"nofollow noopener noreferrer\">java_method<\/a>.<\/p>\n<p>  <\/p>\n<p><strong>main.py<\/strong> c\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0441 \u043e\u0434\u043d\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0435\u0442 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 <strong>Java<\/strong>, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0443\u0432\u0438\u0434\u0438\u043c \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438.<\/p>\n<p>  <\/p>\n<h2 id=\"buildozer\">Buildozer<\/h2>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u0436\u0435 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0444\u0430\u0439\u043b \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 buildozer, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0430\u043a\u0435\u0442\u0430 <strong>apk<\/strong>. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0435\u0433\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">touch buildozer.spec<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">[app]  # (str) Title of your application title = KivyTest  # (str) Package name package.name = kivy_test  # (str) Package domain (needed for android\/ios packaging) package.domain = some.kivy_test  # (str) Source code where the main.py live source.dir = .  # (list) Source files to include (let empty to include all the files) source.include_exts = py,png,jpg,jpeg,ttf,kv,mp3, #,so,2,6,2,1,a  source.include_patterns = img\/*, font\/*, ui\/*, music\/*  # (list) Application version version = 0.0.28  # (list) Application requirements # comma separated e.g. requirements = sqlite3,kivy requirements = android,                python3,                hostpython3,                kivy,                jnius  # (str) Custom source folders for requirements # Sets custom source for any requirements with recipes # requirements.source.kivy = ..\/..\/kivy #requirements.source.libtest = lib\/libtest  # (str) Supported orientation (one of landscape, sensorLandscape, portrait or all) orientation = portrait  # (bool) Indicate if the application should be fullscreen or not fullscreen = 1  # (list) Permissions android.permissions = WRITE_EXTERNAL_STORAGE  # (int) Target Android API, should be as high as possible. android.api = 31  # (int) Minimum API your APK will support. android.minapi = 21  # (str) Android NDK version to use android.ndk = 25b  # (bool) If True, then skip trying to update the Android sdk # This can be useful to avoid excess Internet downloads or save time # when an update is due and you just want to test\/build your package android.skip_update = False  # (bool) If True, then automatically accept SDK license # agreements. This is intended for automation only. If set to False, # the default, you will be shown the license when first running # buildozer. android.accept_sdk_license = True  # (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64 android.archs = arm64-v8a  # (list) Android additionnal libraries to copy into libs\/armeabi android.add_src = %(source.dir)s\/java android.add_libs_arm64_v8a = %(source.dir)s\/libs\/libs_arm64_v8a\/*.* android.add_libs_armeabi_v7a = %(source.dir)s\/libs\/libs_armeabi-v7a\/*.*  #android.copy_libs = 1  [buildozer]  # (int) Log level (0 = error only, 1 = info, 2 = debug (with command output)) log_level = 2  # (int) Display warning if buildozer is run as root (0 = False, 1 = True) warn_on_root = 0  # (str) Path to build artifact storage, absolute or relative to spec file build_dir = .\/.buildozer  # (str) Path to build output (i.e. .apk, .ipa) storage bin_dir = .\/bin<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 buildozer.spec \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0434 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 <strong>arm64-v8a<\/strong>.<br \/>  \u0412 \u043f\u043e\u043b\u0435 <strong>android.add_src<\/strong> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0430\u043f\u043a\u0430 \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f java \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043e\u043a \u0441 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0430\u043c\u0438 \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c \u0441\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u0438\u043c\u0435\u043d\u0438 java \u043f\u0430\u043a\u0435\u0442\u0430.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0431\u0435\u0440\u0435\u043c apk \u043f\u0430\u043a\u0435\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">buildozer android debug<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043e\u0447\u0435\u043d\u044c \u0434\u043e\u043b\u0433\u0430\u044f \u0438 \u0440\u0430\u0441\u0442\u044f\u043d\u0435\u0442\u0441\u044f \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u0435\u0441\u044f\u0442\u043a\u043e\u0432 \u043c\u0438\u043d\u0443\u0442. \u0422\u0430\u043a \u0436\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0440\u044f\u0434\u043a\u0430 1.5 GB \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430, \u0442.\u043a. buildozer \u043f\u043e\u0434\u0442\u044f\u043d\u0435\u0442 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438.<br \/>  \u041f\u043e\u0441\u043b\u0435 \u0443\u0434\u0430\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432 \u043f\u0430\u043f\u043a\u0435 bin \u0441\u043e\u0431\u0435\u0440\u0435\u0442\u0441\u044f \u043f\u0430\u043a\u0435\u0442 kivy_test-0.0.1-arm64-v8a-debug.apk.<\/p>\n<p>  <\/p>\n<h2 id=\"android\">Android<\/h2>\n<p>  <\/p>\n<p>\u041d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u043f\u043e <strong>USB<\/strong> \u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 <strong>USB<\/strong>.<\/p>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" alt=\"main\" width=\"300\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/53\/dg\/bj\/53dgbjcchbcypis05uzqdyi7n58.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/53\/dg\/bj\/53dgbjcchbcypis05uzqdyi7n58.jpeg\" data-blurred=\"true\"\/><\/div>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">adb install -r .\/bin\/kivy_test-*.apk<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430\u0445\u043e\u0434\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0435:<\/p>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" alt=\"main\" width=\"300\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/rw\/9v\/wm\/rw9vwmh-reotpkzhj9yjsw1hkpi.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/rw\/9v\/wm\/rw9vwmh-reotpkzhj9yjsw1hkpi.jpeg\" data-blurred=\"true\"\/><\/div>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u043a \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">adb logcat | grep python<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u2014 <strong>Java<\/strong> \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430 \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">I\/python  (21423): [INFO   ] [Text        ] Provider: sdl2 I\/python  (21423): Python: Hello world! I\/System.out(21423): I\/python: Java: Hello world! I\/python  (21423): Python:  Hello from Test.java I\/python  (21423): Python:  test.hello2() I\/python  (21423): Python: @java_method('()V') I\/python  (21423): Python: @java_method('(Ljava\/lang\/String;)Z'),  callback I\/python  (21423): Python: @java_method('(IB)I'),  11 22 I\/python  (21423): [INFO   ] [Window      ] Provider: sdl2 I\/python  (21423): [INFO   ] [GL          ] Using the \"OpenGL ES 2\" graphics system<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u0432\u0438\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443:<\/p>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" alt=\"main\" width=\"300\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/dv\/xg\/qj\/dvxgqjdrunzpibh8ormbrhbe6l4.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/dv\/xg\/qj\/dvxgqjdrunzpibh8ormbrhbe6l4.jpeg\" data-blurred=\"true\"\/><\/div>\n<p>  <\/p>\n<p>\u041d\u0430\u0436\u0430\u0442\u0438\u0435 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<p>  <\/p>\n<h2 id=\"linux\">Linux<\/h2>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u0436\u0435 <strong>main.py<\/strong> \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438\u0437 \u043f\u043e\u0434 <strong>linux<\/strong>, \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d \u043a\u043b\u0430\u0441\u0441 <strong>java.lang.System<\/strong> \u0438 \u0432\u044b\u0437\u0432\u0430\u043d \u043c\u0435\u0442\u043e\u0434:<\/p>\n<p>  <\/p>\n<pre><code class=\"python\">System.out.println('I\/python: Java: Hello world!')<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u043e\u0448\u043b\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e, \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0441 \u0446\u0435\u043b\u044c\u044e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0432\u0441\u0435\u0433\u043e \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435.<br \/>  \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435.<\/p>\n<p>  <\/p>\n<h2 id=\"ssylki\">\u0421\u0441\u044b\u043b\u043a\u0438<\/h2>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/dvjdjvu\/java_from_python_android\" rel=\"nofollow noopener noreferrer\">\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u0434\u044b \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432<\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/656453\/\"><strong>C\/C++ \u0438\u0437 Python (ctypes) \u043d\u0430 Android<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/479236\/\">Kivy. \u0421\u0431\u043e\u0440\u043a\u0430 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u043f\u043e\u0434 Android \u0438 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u0433\u0438\u0438<\/a><\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/683536\/\"> https:\/\/habr.com\/ru\/articles\/683536\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<div style=\"text-align:center;\"><img decoding=\"async\" alt=\"main\" width=\"500\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/sy\/ra\/fq\/syrafqsvd4_mmn0mirip50wfiig.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/sy\/ra\/fq\/syrafqsvd4_mmn0mirip50wfiig.jpeg\" data-blurred=\"true\"\/><\/div>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/656453\/\">C\/C++ \u0438\u0437 Python (ctypes) \u043d\u0430 Android<\/a>. \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>Java<\/strong> \u0438\u0437 <strong>Python<\/strong>, \u0432\u0435\u0434\u044c \u0434\u043b\u044f <strong>android<\/strong> \u044d\u0442\u043e \u0440\u043e\u0434\u043d\u043e\u0439 \u044f\u0437\u044b\u043a \u0438 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043d\u0443\u0436\u043d\u044b\u0435 \u0432\u0435\u0449\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 \u043d\u0435\u043c. \u041d\u0430\u0443\u0447\u0438\u043c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u044b, \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438 \u0434\u0435\u0440\u0433\u0430\u0442\u044c callback-\u0438. \u041d\u0430 <strong>Linux<\/strong> \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-411746","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/411746","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=411746"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/411746\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=411746"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=411746"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=411746"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}