How to call Google Earth from Python app (on Android and iPhone)?

575 views
Skip to first unread message

Henrik R.

unread,
Nov 11, 2020, 4:41:38 PM11/11/20
to Kivy users support
Hi!

Can anyone tell me something about how my Kivy/Python app can open Google Earth and send geographic information to be shown to the user - on Android (and at a later time on iPhone)?
I know that Google Earth stores geographic information in KML files and I think I know how to create such a file containing my data. The question is how Python can first check that Google Earth is installed (on Android) and then call it and send the KML-file containing the data to be shown in Google Earth?

Thank you for any information or hints on that subject!

Henrik

PS: How do I switch back to the good old Google Groups user interface? This new interface is terrible! Totally flawed.

Robert Flatt

unread,
Nov 11, 2020, 6:54:30 PM11/11/20
to Kivy users support
No experience on this, but via duckduckgo: Is this what you want to do in the second part of the question?
I assume the equivalent Python would be similar.

This new interface is terrible! Totally flawed.
I agree, I think it sucks.

Henrik R.

unread,
Nov 12, 2020, 6:13:37 AM11/12/20
to Kivy users support
You refer to this piece of code:

File KML = new File("/sdcard/doc.kml");
Intent i = getPackageManager().getLaunchIntentForPackage("com.google.earth");
i.setDataAndType(Uri.fromFile(KML), "xml");
startActivity(i);

Yes. That looks right. Thank you.
But where do I find info on how to do something similar in Python?
Would it be in the chapter "Python Runtime Services" - https://docs.python.org/3.8/library/python.html ?
Or "Unix Specific Services" - https://docs.python.org/3.8/library/unix.html ?
Or?

Henrik R.

unread,
Nov 12, 2020, 1:28:30 PM11/12/20
to Kivy users support
I might have found the answer. I will need to study it further.

Henrik R.

unread,
Nov 15, 2020, 2:48:29 PM11/15/20
to Kivy users support
I guess I need to use Pyjnius/jnius to call/start the Google Earth app from a Kivy/Python app, and I have installed Pyjnius and tested it with the small code example at the bottom of this message.

But how do I convert the following (java?) code to Python/Pyjnius?:

File KML = new File("/sdcard/doc.kml");
Intent i = getPackageManager().getLaunchIntentForPackage("com.google.earth");
i.setDataAndType(Uri.fromFile(KML), "xml");
startActivity(i);

The Pyjnius test code that works:

from jnius import autoclass

Stack = autoclass('java.util.Stack')
stack = Stack()
stack.push('hello')
stack.push('world')

print(stack.pop()) # --> 'world'
print(stack.pop()) # --> 'hello'

Any help is deeply appreciated!

planckp...@gmail.com

unread,
Nov 15, 2020, 4:41:08 PM11/15/20
to Kivy users support
You get the idea, declare the java class in Python (using autoclass), and execute it's methods. For the most part data types are automatically translated between languages, but occasionally we have to explicitly cast(). And there is one magic class mActivity which is the app instance.

The following comes with no warranty, I blindly translated the Java to run under Python by depending on the android package (implying pyjnius), but I didn't test it - which is just irresponsible. 🙄 

## These 4 lines MUST be outside of a Python Class
from android import mActivity, autoclass
Intent = autoclass('android.content.Intent')
File = autoclass('java.io.File')
Uri = autoclass('android.net.Uri')

## In a Kivy app, these 4 lines will be inside a Python Class
KML = File("/sdcard/doc.kml")
i = mActivity.getPackageManager().getLaunchIntentForPackage("com.google.earth")
i.setDataAndType(Uri.fromFile(KML), "xml")
mActivity.startActivity(i)

One thing I wonder about is that "xml" setting the Intent type, it may be fine; but I suspect it might need to be a MIME type perhaps "text/xml", "application/xml" or ???? It com.google.earth accepts it as it is then ignore these two sentences.

I'd be interested to know what the user experience is like,  particularly is it easy to get back to the Kivy app from Earth?

planckp...@gmail.com

unread,
Nov 15, 2020, 4:49:02 PM11/15/20
to Kivy users support

Henrik R.

unread,
Nov 15, 2020, 5:00:46 PM11/15/20
to Kivy users support
Thank you very much!
I will study that tomorrow!

Henrik R.

unread,
Nov 16, 2020, 3:51:12 PM11/16/20
to Kivy users support
Again: Thank you for your help so far!

Am I correct, that I cannot test these things on Ubuntu? Only by building an APK-file with buildozer and deploying it on Android?

If I have understood anything, I need these imports:

from jnius import autoclass  # But not: , mActivity
from android import mActivity  # But not: , autoclass

NB: PyCharm says " Unresolved reference 'android' ".

So far, I have written the Kivy test app below, but is the following really correct?:

Intent = autoclass('android.content.Intent')

And does that in some way relate to this:

    i = mActivity.getPackageManager().getLaunchIntentForPackage("com.google.earth")

Should that have been:

    Intent = mActivity.getPackageManager().getLaunchIntentForPackage("com.google.earth")


Here comes the whole 'Pyjnius-test.py' (to be renamed to 'main.py' when 'buildozering' it):

from kivy.app import App
from kivy.lang import Builder
from jnius import autoclass # , mActivity
import kivy
from kivy.uix.boxlayout import BoxLayout

kivy.require('1.11.1')
# Developed in Python 3.6 (and 3.8)

Builder.load_string('''
#:kivy 1.11.1
#:import kivy kivy


''')


# These 4 lines MUST be outside of a Python Class
from android import mActivity # , autoclass
Intent = autoclass('android.content.Intent')
File = autoclass('java.io.File')
Uri = autoclass('android.net.Uri')


class PyjniusScreen(BoxLayout):

   def __init__(self, show_coord_sys, **kwargs):
     super().__init__(**kwargs)

     # In a Kivy app, these 4 lines will be inside a Python Class
     KML = File("myplaces-16x8-Emilie-Meng-pejlinger-2.kml") # /sdcard/doc.kml
     i = mActivity.getPackageManager().getLaunchIntentForPackage("com.google.earth")
     i.setDataAndType(Uri.fromFile(KML), "xml")
     mActivity.startActivity(i)


class MainApp(App):

   def build(self):
     pyjniusscreen = PyjniusScreen()
     return pyjniusscreen

   def on_stop(self):
     print("Closing Application")


if __name__ == '__main__':
   mainApp = MainApp()
   mainApp.run()

planckp...@gmail.com

unread,
Nov 16, 2020, 6:31:08 PM11/16/20
to Kivy users support
Am I correct, that I cannot test these things on Ubuntu?

The android package is only available in Android, and the Android Java API is only available on Android.

So far, I have written the Kivy test app below, but is the following really correct?:
Intent = autoclass('android.content.Intent')

Well caught, my bad, this line is not required in this case. Delete the line if you want.

Henrik R.

unread,
Nov 17, 2020, 3:57:05 PM11/17/20
to Kivy users support
Thank you!! But it fails here:
    i.setDataAndType(Uri.fromFile(KML), "application/vnd.google-earth.kml+xml")
    # These didn't work: "xml", "text/xml", "application/xml"

This doesn't work either:
    i.setData(Uri.fromFile(KML))

I found the MIME type "application/vnd.google-earth.kml+xml" here:

This is the current version of my test app. (As I recall, the old Google Groups user interface supported formatting Python code nicely? The following looks awful!):

from kivy.app import App
from kivy.lang import Builder
import kivy
from kivy.uix.boxlayout import BoxLayout

kivy.require('1.11.1')
# Developed in Python 3.6 (and 3.8)

from jnius import autoclass # But not: , mActivity
from android import mActivity # But not: , autoclass

# These lines MUST be outside of a Python Class
# Intent = autoclass('android.content.Intent')
File = autoclass('java.io.File')
Uri = autoclass('android.net.Uri')

Builder.load_string('''
#:kivy 1.11.1
#:import kivy kivy


''')


class PyjniusScreen(BoxLayout):

   def __init__(self, **kwargs):
     super().__init__(**kwargs)
     print("NOW starting 'PyjniusScreen'")
     # In a Kivy app, these lines will be inside a Python Class
     try:

       KML = File("myplaces-16x8-Emilie-Meng-pejlinger-2.kml") # /sdcard/doc.kml
       try:
         print("TRY to find Google Earth.")

         i = mActivity.getPackageManager().getLaunchIntentForPackage("com.google.earth")
         print("TRY to set KML file for Google Earth.")
         i.setDataAndType(Uri.fromFile(KML), "application/vnd.google-earth.kml+xml")
         # These didn't work: "xml", "text/xml", "application/xml"
         # i.setData(Uri.fromFile(KML))  # Didn't work either.
         print("START Google Earth.")
         mActivity.startActivity(i)
       except:
         print("Google Earth didn't work.")
     except:
       print("The KML file could not be found.")


class MainApp(App):

   def build(self):
     print("NOW running 'mainApp'")

     pyjniusscreen = PyjniusScreen()
     return pyjniusscreen

   def on_stop(self):
     print("Closing Application")


if __name__ == '__main__':
   mainApp = MainApp()
   print("NOW running 'main'")
   mainApp.run()


I used this Terminal command to read the output from the Android device:
  $ adb logcat | grep -i " python "

Here comes the essence of the output of that command:

11-17 21:24:14.213 29015 29042 I python  : NOW running 'main'
11-17 21:24:14.215 29015 29042 I python  : NOW running 'mainApp'
11-17 21:24:14.438 29015 29042 I python  : NOW starting 'PyjniusScreen'
11-17 21:24:14.438 29015 29042 I python  : TRY to find Google Earth.
11-17 21:24:14.443 29015 29042 I python  : TRY to set KML file for Google Earth.
11-17 21:24:14.443 29015 29042 I python  : Google Earth didn't work.

Here comes a larger excerpt:

11-17 21:24:11.018 29015 29042 I python  : Android kivy bootstrap done. __name__ is __main__
11-17 21:24:11.018 29015 29042 I python  : AND: Ran string
11-17 21:24:11.018 29015 29042 I python  : Run user program, change dir and execute entrypoint
11-17 21:24:11.299 29015 29042 I python  : [WARNING] [Config      ] Older configuration version detected (0 instead of 21)
11-17 21:24:11.299 29015 29042 I python  : [WARNING] [Config      ] Upgrading configuration in progress.
11-17 21:24:11.315 29015 29042 I python  : [INFO   ] [Logger      ] Record log in /data/user/0/dk.transformation.geoespearthtest/files/app/.kivy/logs/kivy_20-11-17_0.txt
11-17 21:24:11.315 29015 29042 I python  : [INFO   ] [Kivy        ] v2.0.0rc3, git-Unknown, 20201117
11-17 21:24:11.316 29015 29042 I python  : [INFO   ] [Kivy        ] Installed at "/data/user/0/dk.transformation.geoespearthtest/files/app/_python_bundle/site-packages/kivy/__init__.pyc"
11-17 21:24:11.316 29015 29042 I python  : [INFO   ] [Python      ] v3.8.1 (default, Sep 17 2020, 10:34:53)
11-17 21:24:11.316 29015 29042 I python  : [Clang 8.0.2 (https://android.googlesource.com/toolchain/clang 40173bab62ec7462
11-17 21:24:11.316 29015 29042 I python  : [INFO   ] [Python      ] Interpreter at ""
11-17 21:24:13.201 29015 29042 I python  : [INFO   ] [Factory     ] 185 symbols loaded
11-17 21:24:14.077 29015 29042 I python  : [INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_pil (img_ffpyplayer, img_gif ignored)
11-17 21:24:14.213 29015 29042 I python  : NOW running 'main'
11-17 21:24:14.215 29015 29042 I python  : NOW running 'mainApp'
11-17 21:24:14.278 29015 29042 I python  : [INFO   ] [Window      ] Provider: sdl2
11-17 21:24:14.345 29015 29042 I python  : [INFO   ] [GL          ] Using the "OpenGL ES 2" graphics system
11-17 21:24:14.349 29015 29042 I python  : [INFO   ] [GL          ] Backend used <sdl2>
11-17 21:24:14.349 29015 29042 I python  : [INFO   ] [GL          ] OpenGL version <b'OpenGL ES 3.2 V@269.0 (GIT@bb5b86c, I77d3059488) (Date:06/07/18)'>
11-17 21:24:14.350 29015 29042 I python  : [INFO   ] [GL          ] OpenGL vendor <b'Qualcomm'>
11-17 21:24:14.350 29015 29042 I python  : [INFO   ] [GL          ] OpenGL renderer <b'Adreno (TM) 505'>
11-17 21:24:14.351 29015 29042 I python  : [INFO   ] [GL          ] OpenGL parsed version: 3, 2
11-17 21:24:14.351 29015 29042 I python  : [INFO   ] [GL          ] Texture max size <16384>
11-17 21:24:14.352 29015 29042 I python  : [INFO   ] [GL          ] Texture max units <16>
11-17 21:24:14.435 29015 29042 I python  : [INFO   ] [Window      ] auto add sdl2 input provider
11-17 21:24:14.436 29015 29042 I python  : [INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
11-17 21:24:14.438 29015 29042 I python  : NOW starting 'PyjniusScreen'
11-17 21:24:14.438 29015 29042 I python  : TRY to find Google Earth.
11-17 21:24:14.443 29015 29042 I python  : TRY to set KML file for Google Earth.
11-17 21:24:14.443 29015 29042 I python  : Google Earth didn't work.
11-17 21:24:14.445 29015 29042 I python  : [WARNING] [Base        ] Unknown <android> provider
11-17 21:24:14.445 29015 29042 I python  : [INFO   ] [Base        ] Start application main loop

And help would be deeply appreciated!

planckp...@gmail.com

unread,
Nov 17, 2020, 9:56:57 PM11/17/20
to Kivy users support
Write all the exception code like this, then you will see the error.

   except Exception as e:
         print("Google Earth didn't work.  " + str(e))

Henrik R.

unread,
Nov 18, 2020, 6:35:23 AM11/18/20
to Kivy users support
Oops! Sorry for not thinking about that!

This statement: i.setDataAndType(Uri.fromFile(KML), "application/vnd.google-earth.kml+xml")
Results in: 'NoneType' object has no attribute 'setDataAndType'
But why is the object i:
    i = mActivity.getPackageManager().getLaunchIntentForPackage("com.google.earth")
a 'NoneType' object?

Here is the output from '$ adb logcat | grep -i " python "' :

11-18 12:25:20.875 10044 10098 I python  : [INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
11-18 12:25:20.877 10044 10098 I python  : NOW starting 'PyjniusScreen'
11-18 12:25:20.878 10044 10098 I python  : TRY to find Google Earth.
11-18 12:25:20.882 10044 10098 I python  : TRY to set KML file for Google Earth.
11-18 12:25:20.882 10044 10098 I python  : Google Earth didn't work.'NoneType' object has no attribute 'setDataAndType'
11-18 12:25:20.884 10044 10098 I python  : [WARNING] [Base        ] Unknown <android> provider
11-18 12:25:20.884 10044 10098 I python  : [INFO   ] [Base        ] Start application main loop

planckp...@gmail.com

unread,
Nov 18, 2020, 11:41:43 AM11/18/20
to Kivy users support
As I said no warranty.  I can only read the docs, for example this says there are cases where one of the methods returns null.
What that means I can't say.

Henrik R.

unread,
Nov 21, 2020, 12:08:58 PM11/21/20
to Kivy users support
I temporarily forgot that I deliberately did NOT install Google Earth in order to determine what error that produces. That's what gives this:

<class 'AttributeError'>
'NoneType' object has no attribute 'setDataAndType'
<traceback object at 0x92db7948>

After installing Google Earth 'setDataAndType' works, but I get this error in the next statement:

<class 'jnius.jnius.JavaException'>
JVM exception occurred: file:///myplaces-16x8-Emilie-Meng-pejlinger-2.kml exposed beyond app through Intent.getData()
<traceback object at 0x91eb37e8>

It turns out that from Android ver. 7 (Nougat) you cannot just send a "file://" with an Intent. You have to do something more complicated, sending the URI through the "content://" scheme instead which is the URI scheme for Content Provider.

So according to - https://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed - and - https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en - I have to insert a <provider> tag in 'AndroidManifest.xml'. BUT it seems that Buildozer creates that file, and I can't really figure out how, because - in short - there are 11 version of 'AndroidManifest.xml' and 'AndroidManifest.tmpl.xml' in the '.buildozer' folder-tree...??

planckp...@gmail.com

unread,
Nov 21, 2020, 3:02:16 PM11/21/20
to Kivy users support
I know what you are talking about, I have worked on receiving shared files but not on sending them.
There are some buildozer options about inserting stuff in the manifest.
But I don't know enough to help you on this one, and currently don't have the spare time to teach myself.
Sorry.

Henrik R.

unread,
Nov 21, 2020, 3:58:22 PM11/21/20
to Kivy users support
Buildozer.spec contains these 4 settings, but I don't really understand whether they can be used for that...?:

# (list) Java classes to add as activities to the manifest.
#android.add_activities = com.example.ExampleActivity

# (str) XML file to include as an intent filters in <activity> tag
#android.manifest.intent_filters =

# (str) launchMode to set for the main activity
#android.manifest.launch_mode = standard

# (list) Android shared libraries which will be added to AndroidManifest.xml using <uses-library> tag
#android.uses_library =

planckp...@gmail.com

unread,
Nov 21, 2020, 8:35:42 PM11/21/20
to Kivy users support
The documentation only makes sense if you understand the Manifest structure, everything prior to this point assumes you don't even have to know the Manifest exists. It is (probably) completely accurate but not actionable.

The only way I know to do this is to look in
And try to decode which options insert stuff where.  Look for things of the general form  {% if args.whatever %}
 

Backup plan: make your own local copy of p4a, reference it in .spec, edit it's AndroidMainfest.tmpl.xml
You'll have to figure out any details.

Also in your App look out for using Java code from androidx , which might be the case. If this happens there will be some more switches that p4a does not support. Again I have not tried this so I can't give any useful input. But one step at a time.

Henrik R.

unread,
Nov 22, 2020, 4:57:24 PM11/22/20
to Kivy users support
Thank you for pointing me to the 'right' version of the AndroidManifest.tmpl.xml file!

After looking thoroughly at that AndroidManifest.tmpl.xml file I can't see any {% if args.whatever %} structure that allows me to insert a <provider> tag in the <application> section.

But now that you have pointed me to the right version of the AndroidManifest.tmpl.xml file, can't I just insert the <provider> tag directly in that file?

planckp...@gmail.com

unread,
Nov 22, 2020, 5:45:46 PM11/22/20
to Kivy users support
Yes, see "Backup plan" in previous post.

Henrik R.

unread,
Nov 23, 2020, 8:14:17 AM11/23/20
to Kivy users support
I am sorry for kind of repeating a question! But why would I need to make a copy of the whole python-for-android system in order to edit ONE file?

The next question is: Where do I put the new "provider_paths.xml" file?


"Then create a provider_paths.xml file in res/xml folder. Folder may be needed to created if it doesn't exist."

Put there are 10 'res'-folders in the '.buildozer'-folder-tree under my Kivy-project folder...:

(venv) xx@yy:/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer$ find /mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer -name res -type d
/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/build-armeabi-v7a/build/bootstrap_builds/sdl2/jni/SDL/android-project/app/src/main/res
/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/build-armeabi-v7a/build/bootstrap_builds/sdl2/src/main/res
/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/build-armeabi-v7a/dists/GeoESPEarthTest__armeabi-v7a/build/generated/res
/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/build-armeabi-v7a/dists/GeoESPEarthTest__armeabi-v7a/build/intermediates/blame/res
/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/build-armeabi-v7a/dists/GeoESPEarthTest__armeabi-v7a/build/intermediates/res
/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/build-armeabi-v7a/dists/GeoESPEarthTest__armeabi-v7a/jni/SDL/android-project/app/src/main/res
/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/build-armeabi-v7a/dists/GeoESPEarthTest__armeabi-v7a/src/main/res
/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/python-for-android/pythonforandroid/bootstraps/sdl2/build/src/main/res
/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/python-for-android/pythonforandroid/bootstraps/service_only/build/src/main/res
/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/python-for-android/pythonforandroid/bootstraps/webview/build/src/main/res
(venv) xx@yy:/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer$

I am starting to regret that I decided to learn Kivy in order to create my app in Kivy/Python...

Henrik R.

unread,
Nov 23, 2020, 9:58:50 AM11/23/20
to Kivy users support
I can add that the "provider_paths.xml" file is supposed to have this simple content:

<?xml version="1.0" encoding="utf-8"?> <paths> <external-path name="external_files" path="."/> </paths>

planckp...@gmail.com

unread,
Nov 23, 2020, 12:08:53 PM11/23/20
to Kivy users support
The local copy of p4a because its a bad idea to change the contents of .buildozer,  you don't manage that directory and it could get over written and you would loose your work. Also as you point out, you have to figure out which copy to change. Its gonna be a mess.

It seems to be the nature of design abstraction that it works really well until some suitably special case when the abstraction works really poorly. I'd suggest Kivy is such an abstraction, what was so attractive for most cases eventually results in an unattractive case. Turns out eventually there is no free lunch.

I have not done what you are trying to do, I do not have specific suggestions for you.
Message has been deleted

Henrik R.

unread,
Nov 23, 2020, 5:08:03 PM11/23/20
to Kivy users support
NB! I just deleted a message, because I was writing non-sense!
I wrote that I could not find the 'AndroidManifest.tmpl.xml' file. I must be tired... Now I found it again!

Henrik R.

unread,
Nov 24, 2020, 8:39:55 AM11/24/20
to Kivy users support

'Planck' wrote:

" Backup plan: make your own local copy of p4a, reference it in .spec, edit it's AndroidMainfest.tmpl.xml "

OK! I figured out that '/.buildozer/android/platform/python-for-android/' contains p4a, so I copied it's content (including sub-folders of course) to a new folder '/.buildozer/my-p4a-copy/' and I found the corresponding setting in buildozer.spec and set it like this:

# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
p4a.source_dir = ./.buildozer/my-p4a-copy/

I ran '$ buildozer android debug deploy run' which confirms that it works...

That folder-tree contains the 'AndroidManifest.tmpl.xml' file here:

/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/my-p4a-copy/pythonforandroid/bootstraps/sdl2/build/templates/

Where I have inserted this <provider> tag in the <application>-section:

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>   

It also contains a ’res’ folder here:

/mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/my-p4a-copy/pythonforandroid/bootstraps/sdl2/build/src/main/

Where I have added the following /folder/file - /xml/provider_paths.xml:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external_files" path="."/>
</paths>

Now the problem is to change the Python code from sending a 'file:' URI to sending a 'content:' URI.

At the moment I have this outside of any Python class:

from jnius import autoclass
from android import mActivity

File = autoclass('java.io.File')
Uri = autoclass('android.net.Uri')

And this inside my Python class PyjniusScreen(BoxLayout):

KML = File("myplaces-16x8-Emilie-Meng-pejlinger-2.kml") # /sdcard/doc.kml
i = mActivity.getPackageManager().getLaunchIntentForPackage("com.google.earth")
i.setDataAndType(Uri.fromFile(KML), "application/vnd.google-earth.kml+xml")
mActivity.startActivity(i)

I have found ONE suggestion on how to use the 'content:' URI provider instead of just the 'file:' URI, to SEND a file to another app, but I am not sure how to translate it to Python and incorporate it in the code above:

https://developer.android.com/reference/android/support/v4/content/FileProvider.html#GetUri - explains a lot, and gives the following code sample of how to create the 'content:' URI of an image file:

File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);

Any help would be deeply appreciated!

planckp...@gmail.com

unread,
Nov 24, 2020, 12:23:15 PM11/24/20
to Kivy users support
Great stuff, when you get this figured out I'm going to take what you have learned and make a small example for others.

I have found ONE suggestion on how to use the 'content:' URI provider instead of just the 'file:' URI, to SEND a file to another app, but I am not sure how to translate it to Python and incorporate it in the code above:

I have not done this.  Yes its is the same mechanism, from a users point of view the difference is in the SEND case the user sees a 'chooser' pane that asks which app it should be sent to. In this case we know what app it should go to and specify it, so the user goes not get a choice.

The only difference is the startActivity which in the SEND case something like:
  mActivity.startActivity(Intent.createChooser(send,None))   

As I said I have not done this, but I think you are on the right track.

Henrik R.

unread,
Nov 24, 2020, 12:44:28 PM11/24/20
to Kivy users support
I am not sure why you mention a 'chooser' pane? That makes it a bit more complicated.
I don't know how to translate the suggested Java code to Python, so introducing a 'chooser' pane just makes this more complicated... ;-)

planckp...@gmail.com

unread,
Nov 24, 2020, 2:27:33 PM11/24/20
to Kivy users support
I'm not suggesting using a chooser pane, just pointing out that with or without the chooser pane the rest of the functionality is (I think) the same. So if you have found an example creating a 'content url' for use by a chooser, the same (?) code should be useful for generating a 'content url' to send directly to a particular app.

Henrik R.

unread,
Nov 24, 2020, 2:38:43 PM11/24/20
to Kivy users support
I have found this Java code example for creating a 'content:' URI:

File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);

But I don't know how to translate it to Python.

planckp...@gmail.com

unread,
Nov 24, 2020, 3:38:08 PM11/24/20
to Kivy users support
OK top of my head, not tested, for you to debug:

from android.storage import app_storage_path
from android import mActivity
File   = autoclass('java.io.File')
FileProvider = autoclass('androidx.core.content.FileProvider')

newFile = File(join(app_storage_path(), 'images', 'default_image.jpg'))

context = cast('android.content.ContextWrapper',
 
mActivity.getApplicationContext())  # I'm not certain about this line

contentUri = FileProvider.getUriForFile(context, "com.mydomain.fileprovider", newFile)

Even assuming the translation is correct, which I did not check, there I two more issues I can see:

1) "com.mydomain.fileprovider" looks like a placeholder for something, but I don't know what.

   So there is some more tinkering to do with p4a,  https://developer.android.com/jetpack/androidx/migrate
  I have not looked at this at all, I don't know where gradle.properties is/should be, or if there are any side effects of doing this.

Good luck.....

planckp...@gmail.com

unread,
Nov 24, 2020, 10:43:36 PM11/24/20
to Kivy users support
My time freed up a bit and I looked at this and it may be possible to avoid androidx by using a backwards compatible package that contains FileProvider and specify with a .spec option.

It will look like this, here are two examples I found, I don't know what one would actually use in practice
android.gradle_dependencies = "com.android.support:support-core-utils:28.0.0"
android.gradle_dependencies = 'com.android.support:support-v4:26.1.0'

If this works, and we figure out what the version should be, it will be a lot simpler than messing with androidx
FileProvider would then be:
FileProvider = autoclass(' android.support.v4.content .FileProvider')

This is a potential solution, I did not put the pieces together.

Henrik R.

unread,
Nov 25, 2020, 4:42:22 PM11/25/20
to Kivy users support
Thank you for the 2 replies!

<provider android:name="androidx.core.content.FileProvider" ...
or:
<provider android:name="android.support.v4.content.FileProvider" ...

I have chosen "android.support.v4.content.FileProvider".

But I must admit that this is getting so complicated that I am getting close to the point where the most relevant question is: Who can make this work and at what price, in USD or Euro?

planckp...@gmail.com

unread,
Nov 25, 2020, 6:10:34 PM11/25/20
to Kivy users support
Good link, this whole thing will be really simple and make sense when we figure it out.

at what price, in USD or Euro?
Yes its really expensive for the first person, but free for everybody else....

We use free software, but every now and then we still have to pay the piper.

planckp...@gmail.com

unread,
Nov 27, 2020, 12:17:08 PM11/27/20
to Kivy users support
Hendrick,
I got this working. If you are still interested I can clean up what I have done and share it with you.

Henrik R.

unread,
Nov 27, 2020, 4:25:50 PM11/27/20
to Kivy users support
I am VERY interested!!
I feel that the app I am trying to create will be quite unique and even revolutionary.

planckp...@gmail.com

unread,
Nov 27, 2020, 9:38:36 PM11/27/20
to Kivy users support
Attached. I'm totally up for being part of the revolution.

All the setup instructions are in the README part of main.py  . The app is runnable.
I tried builds with android.api=27,  29, and 30  and tested on Android 11.
There are 3 share cases, the last is sharing directly. I only tested that case with Google Drive.
Let me know how it goes.

I also have a version that uses androidx, it requires an extra change to p4a, and android.api=28 or greater.
You are welcome to try it, but don't try both lest confusion ensues....
The androidx based app appears to work, but do not know of anybody else using androidx in the p4a context,
so there may be unknown side effects?  That may be uncertainty you don't need.
main.py

Henrik R.

unread,
Nov 28, 2020, 5:50:47 AM11/28/20
to Kivy users support
Thank you VERY much! That looks quite thorough!
I am working on something urgent, so it will be a few days before I get time to test it.
Could you send the buildozer.spec you used? For the more thick-headed like me... ;-)

The first thing I notice is that I used:
from jnius import autoclass

You don't use jnius, but:
from android import mActivity, autoclass, cast
from android.storage import app_storage_path

planckp...@gmail.com

unread,
Nov 28, 2020, 11:34:11 AM11/28/20
to Kivy users support
You don't use jnius, but:
same thing

I purposely didn't send a .spec,  I want ti know of the documentation is complete.

Henrik R.

unread,
Nov 29, 2020, 12:13:54 PM11/29/20
to Kivy users support
I am starting to implement it. You write:

" 3) Specify the folders that can be shared.
------------------------------------------
Create a file 'provider_paths.xml' containing:


<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="app storage" path="."/>
</paths>

Save the file in both of the following directories:
<App directory>/src/debug/res/xml/provider_paths.xml
<App directory>/src/main/res/xml/provider_paths.xml "

But what is <App directory>.
I thought that would mean the folder where I have my source files, but I can see it must be somewhere in the '.buildozer'-subfolder. But where? (There are dozens of folders with names like 'debug', or 'res' etc. ...)

planckp...@gmail.com

unread,
Nov 29, 2020, 2:34:27 PM11/29/20
to Kivy users support
You were right first time, for example main.py is directly inside <App_directory>

Henrik R.

unread,
Nov 29, 2020, 5:01:09 PM11/29/20
to Kivy users support
I don't have these folders:

<App directory>/src/debug/res/xml/provider_paths.xml
<App directory>/src/main/res/xml/provider_paths.xml

if <App directory> means my project folder - the folder with my python source code... So I don't understand what you are saying? 

That's why I presume you are referring to somewhere in the '.buildozer'-folder-tree - but where?

planckp...@gmail.com

unread,
Nov 29, 2020, 5:16:36 PM11/29/20
to Kivy users support
[one day there will be an add-xml-resource build option.]
Just create the directories in <the app_directory> , mkdir scr,  ...and so on....

Henrik R.

unread,
Nov 29, 2020, 5:24:50 PM11/29/20
to Kivy users support
Well... I didn't think of that... :-) Because in the other discussions I have read, the provider_paths.xml file had to be placed in a similarly named folder 'far' down in the sub-folders to '.buildozer'...

planckp...@gmail.com

unread,
Nov 29, 2020, 5:35:58 PM11/29/20
to Kivy users support
In my world view it is never a good idea to put things in .buildozer . We don't control what happens to it.

Just checking, I think in an earlier post you tried copying p4a from .buildozer; these instructions are different, do not use a p4a copied from .buildozer.

Henrik R.

unread,
Nov 29, 2020, 8:28:05 PM11/29/20
to Kivy users support
Yes, earlier I copied p4a from .buildozer. Now I am following your instructions instead.

Henrik R.

unread,
Dec 1, 2020, 2:40:24 PM12/1/20
to Kivy users support
Great! Thank you!
The app compiled and was deployed on my MOTO G5 phone perfectly.
And the "Share TEXT via ShareSheet" worked, at least when I send it to the SMS 'Messages' app.
But trying to share with Google Drive gave an exception - see screen shot:

Screenshot_20201201-201216.png

And strangely the Terminal command I have used to get log output didn't give anything:
$ adb logcat | grep -i " python "

Using this instead:
$ adb logcat | grep -i "python"
Gave some output, but not all the expected output.

Here comes the total of Terminal commands with some redundant output deleted:

h@hr:~$ cd /mnt/4AF15A0435E762B4/mypython/GeoESP/
h@hr:/mnt/4AF15A0435E762B4/mypython/GeoESP$ source venv/bin/activate
(venv) h@hr:/mnt/4AF15A0435E762B4/mypython/GeoESP$ buildozer android debug
# Check configuration tokens
[deleted stuff...]
# Gradle project detected, copy files /mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/build-armeabi-v7a/dists/GeoESPEarthTest__armeabi-v7a/src/main/java
# Android packaging done!
# APK GeoESPEarthTest-0.1-armeabi-v7a-debug.apk available in the bin directory
(venv) h@hr:/mnt/4AF15A0435E762B4/mypython/GeoESP$ buildozer android debug deploy run
# Check configuration tokens
[deleted stuff...]
# Gradle project detected, copy files /mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/build-armeabi-v7a/dists/GeoESPEarthTest__armeabi-v7a/src/main/java
# Android packaging done!
# APK GeoESPEarthTest-0.1-armeabi-v7a-debug.apk available in the bin directory
# Deploy on ZY3224R37X
# Application pushed.
# Run on ZY3224R37X
# Application started.
(venv) h@hr:/mnt/4AF15A0435E762B4/mypython/GeoESP$ adb logcat | grep -i " python "
adb server version (41) doesn't match this client (39); killing...
* daemon started successfully

^C
(venv) h@hr:/mnt/4AF15A0435E762B4/mypython/GeoESP$ adb logcat | grep -i "python"
12-01 20:06:10.497  1743  3927 I ActivityManager: START u0 {act=org.kivy.android.PythonActivity flg=0x10000000 cmp=dk.transformation.geoespearthtest/org.kivy.android.PythonActivity} from uid 2000
12-01 20:06:10.597  1743  3313 I ActivityManager: Start proc 3128:dk.transformation.geoespearthtest/u0a129 for activity dk.transformation.geoespearthtest/org.kivy.android.PythonActivity
12-01 20:06:11.436  1743  1814 I LaunchCheckinHandler: Displayed dk.transformation.geoespearthtest/org.kivy.android.PythonActivity,cp,ca,856
12-01 20:06:20.347   810   810 D SFPerfTracer:        layers: (4:9) (StatusBar#0 (0xaf2e2000): 0:68799) (com.android.systemui.ImageWallpaper#0 (0xaf2e7000): 0:1544)* (DimLayerController/Stack=0#0 (0xaf23d000): 0:273)* (animation background stackId=1#0 (0xaf2e0000): 0:68)* (Sprite#0 (0xaf26e000): 0:14)* (NavigationBar#0 (0xaf267000): 0:513) (com.google.android.apps.messaging/com.google.android.apps.messaging.conversation.screen.ConversationActivity#0 (0xaef0c000): 0:246)- (Splash Screen dk.transformation.geoespearthtest#0 (0xaf2fc000): 0:33)- (dk.transformation.geoespearthtest/org.kivy.android.PythonActivity#0 (0xaf264000): 1:24)

[deleted stuff...]

Should I just go on, trying to send my KML-file to Google Earth? Or is the above exception something serious? :-)

planckp...@gmail.com

unread,
Dec 1, 2020, 4:29:53 PM12/1/20
to Kivy users support
This message from Android is caught by my code; it says there is no FileProvider, so FileProvider is not set up correctly.

If the app package changed, a buildozer appclean should fix it.

The alternative is that the FileProvider really is not set up correctly, this is fatal.
Check these first:
Is p4a.source value correct ?
does python-for-android-master  contain a folder pythonforandroid  ?

After that re-read the instructions, check each step. If you make a change do an appclean.

Henrik R.

unread,
Dec 1, 2020, 6:16:07 PM12/1/20
to Kivy users support
I am sorry. I should have done a 'buildozer appclean'.
I DID wonder whether the changes in 'buildozer.spec' and the fact that your python/kivy code is actually a new app in the same project folder should 'trigger' a 'buildozer appclean'...

Yes - python-for-android-master contains a folder pythonforandroid.

And buildozer.spec points to it (outside the app project folder):

# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
p4a.source_dir = /mnt/4AF15A0435E762B4/mypython/my-p4a-copy-new/python-for-android-master/

The app project folder is: /mnt/4AF15A0435E762B4/mypython/GeoESP

But buildozer still fails, so I ran '$ buildozer android debug' with log level 2.
This seems to be the must relevant part of the output:

AAPT: error: resource xml/provider_paths (aka dk.transformation.geoespearthtest:xml/provider_paths) not found.

But why isn't the file 'provider_paths.xml' found?
I placed it in 2 'sub-sub'-folders to '/mnt/4AF15A0435E762B4/mypython/GeoESP/src/' :-)

Here is the context:

[INFO]:    Detected highest available build tools version to be 30.0.2
[DEBUG]:   -> running gradlew assembleDebug
[DEBUG]:      
[DEBUG]:       > Configure project :
[DEBUG]:       WARNING: Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
[DEBUG]:       It will be removed at the end of 2018. For more information see: http://d.android.com/r/tools/update-dependency-configurations.html
[DEBUG]:       /mnt/4AF15A0435E762B4/mypython/GeoESP/.buildozer/android/platform/build-armeabi-v7a/dists/GeoESPEarthTest__armeabi-v7a/build/intermediates/manifests/full/debug/AndroidManifest.xml:67: AAPT: error: resource xml/provider_paths (aka dk.transformation.geoespearthtest:xml/provider_paths) not found.
[DEBUG]:       > IDLE
[DEBUG]:       error: failed processing manifest.
[DEBUG]:      
[DEBUG]:       > Task :processDebugResources FAILED
[DEBUG]:      
[DEBUG]:       FAILURE: Build failed with an exception.
[DEBUG]:      
[DEBUG]:       * What went wrong:
[DEBUG]:       Execution failed for task ':processDebugResources'.
[DEBUG]:       > Failed to process resources, see aapt output above for details.

Any help deeply appreciated.

Henrik R.

unread,
Dec 1, 2020, 6:29:32 PM12/1/20
to Kivy users support
Just to be 100% clear:
I have attached a zip-file of the 'src' folder which is situated in '/mnt/4AF15A0435E762B4/mypython/GeoESP/'.
src-folder.zip

planckp...@gmail.com

unread,
Dec 1, 2020, 7:25:58 PM12/1/20
to Kivy users support
Directories in the zip look OK
I notice the order in this line was changed <files-path name="app storage" path="."/> but I don't think that would matter.

I have:
~/ex/share_snd>ls
bin  buildozer.spec  main.py  src
~/ex/share_snd>ls src/debug/res/xml
provider_paths.xml 

error: resource xml/provider_paths (aka dk.transformation.geoespearthtest:xml/provider_paths) not found.
I interpret this as it is finding the manifest change, which is good, all the local p4a stuff is OK.
But doesn't understand what to do with it, which is bad.

1) If the @ in this line?   android:resource="@xml/provider_paths" />

2) Do the src directories and file have read permission?

3) take a step back: make a new app directory copy my main.py and the src tree there
buildozer init
Make ONLY the two changes to buildozer.spec:
p4a.source_dir = ../my-p4a-copy-new/python-for-android-master
android.gradle_dependencies = "com.android.support:support-core-utils:27.0.0"
buildozer android debug

Henrik R.

unread,
Dec 2, 2020, 12:59:01 PM12/2/20
to Kivy users support
Sigh! Same problem...

Point 1): Yes:
    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="{{ args.package }}.fileprovider"
        android:grantUriPermissions="true"
        android:exported="false">

        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>

Point 2): Yes. 'rwx'. It's an NTFS partition originally created by Windows.

Point 3): Done. But same result:
AndroidManifest.xml:67: AAPT: error: resource xml/provider_paths (aka org.test.myapp:xml/provider_paths) not found.

Context:

[INFO]:    Detected highest available build tools version to be 30.0.2
[DEBUG]:   -> running gradlew assembleDebug
[DEBUG]:      
[DEBUG]:       > Configure project :
[DEBUG]:       WARNING: Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
[DEBUG]:       It will be removed at the end of 2018. For more information see: http://d.android.com/r/tools/update-dependency-configurations.html
[DEBUG]:       /mnt/4AF15A0435E762B4/mypython/GeoESP-android/.buildozer/android/platform/build-armeabi-v7a/dists/myapp__armeabi-v7a/build/intermediates/manifests/full/debug/AndroidManifest.xml:67: AAPT: error: resource xml/provider_paths (aka org.test.myapp:xml/provider_paths) not found.
[DEBUG]:      
[DEBUG]:       error: failed processing manifest.
[DEBUG]:      
[DEBUG]:       > Task :processDebugResources FAILED
[DEBUG]:      
[DEBUG]:       FAILURE: Build failed with an exception.
[DEBUG]:      
[DEBUG]:       * What went wrong:
[DEBUG]:       Execution failed for task ':processDebugResources'.
[DEBUG]:       > Failed to process resources, see aapt output above for details.

Henrik R.

unread,
Dec 2, 2020, 1:04:11 PM12/2/20
to Kivy users support
Additional info:

h@hr:/mnt/4AF15A0435E762B4/mypython/GeoESP-android$ ls -l
total 20
drwxrwxrwx 1 root root     0 Dec  2 18:34 bin
-rwxrwxrwx 1 root root 10658 Dec  2 18:32 buildozer.spec
-rwxrwxrwx 1 root root  8109 Nov 29 11:26 main.py
drwxrwxrwx 1 root root     0 Nov 29 23:26 src

The '.buildozer' folder isn't shown.

h@hr:/mnt/4AF15A0435E762B4/mypython/GeoESP-android/src/main/res/xml$ ls -l
total 1
-rwxrwxrwx 1 root root 161 Nov 29 18:04 provider_paths.xml

Henrik R.

unread,
Dec 3, 2020, 3:51:28 PM12/3/20
to Kivy users support
Dear 'Planck'!
(I know your name isn't Planck, but I presume you want some privacy.)

I am sorry that I haven't had a lot of time lately to investigate this complex Java/Android/Buildozer issue myself!

I have been VERY busy:
I just sent a comprehensive report to all members of the Danish parliament, quoting approximately 60 people as sources, primarily medical professionals. Combined, they reference many hundreds of scientific studies.
My purpose was to try to make the politicians realize and understand that their COVID-19 policies so far have been extremely misguided and destructive. And that the vaccine is VERY risky and very unnecessary in the light of numerous effective treatments that have been actively suppressed in order to sell the vaccine...!
I have put the report on my website here:
Title:
"Many warn: The COVID-19 vaccine will be a disaster! - There will be a legal aftermath! - The statistics: There is no COVID-19 epidemic in Denmark! - 'Infection numbers' are meaningless!"
It's in Danish, but the vast majority of sources are in English.

I am not trying to start a COVID-19 discussion here on Kivy-users. (You can discuss that in the comment section on my webpage mentioned above. I am just explaining why I haven't had more time for my revolutionary GeoESP app. That being said, I think the Java/Android/Buildozer issue is so complex that I am not able to cope with it... So I REALLY hope you can help me figure out why it STILL doesn't work...?

Love,
Henrik

planckp...@gmail.com

unread,
Dec 3, 2020, 4:27:06 PM12/3/20
to Kivy users support
Skipping the flame bait ;)

Try the main.py as a new project, make the two changes to the default buildozer.spec
That way we at least know we are looking at the same thing.

Henrik R.

unread,
Dec 3, 2020, 4:39:14 PM12/3/20
to Kivy users support
Yes - that's what I did...
I attach the buildozer.spec here, so you can check if 'my' buildozer creates the same file as yours.
buildozer.spec

planckp...@gmail.com

unread,
Dec 3, 2020, 7:52:53 PM12/3/20
to Kivy users support
diff -b buildozer.spec hendrick.spec
243c241
< p4a.source_dir = ~/ex/python-for-android-master
---
> p4a.source_dir = /mnt/4AF15A0435E762B4/mypython/my-p4a-copy-new/python-for-android-master/

Try comparing these two, share the 'diff -b' results
AndroidManifest.tmpl.xml
provider_paths.xml

Henrik R.

unread,
Dec 4, 2020, 7:29:31 AM12/4/20
to Kivy users support
Yes. Good idea:

$ diff -b Robert-AndroidManifest.tmpl.xml AndroidManifest.tmpl.xml
137a138
>
146a148
>
(My file is 2 bytes larger, because I inserted 2 blank lines...)

$ diff -b Robert-provider_paths.xml provider_paths.xml
$
(But your file is 4 bytes larger than mine. They are both 4 lines...)

Henrik R.

unread,
Dec 4, 2020, 7:58:56 AM12/4/20
to Kivy users support
I am not sure how to make buildozer reveal it's version?

$ which buildozer
/home/henrik/.local/bin/buildozer

That file contains this:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from buildozer.scripts.client import main
if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(main())

planckp...@gmail.com

unread,
Dec 4, 2020, 11:42:15 AM12/4/20
to Kivy users support
pip3 list

Henrik R.

unread,
Dec 4, 2020, 3:20:32 PM12/4/20
to Kivy users support
OK!:
buildozer              1.2.0

Henrik R.

unread,
Dec 5, 2020, 9:26:32 AM12/5/20
to Kivy users support
Could it be that you have a copy of 'provider_paths.xml' located somewhere else, and forgot about it?

Henrik R.

unread,
Dec 5, 2020, 9:46:58 AM12/5/20
to Kivy users support
I have attached the Terminal output of Buildozer with ‘log_level = 2’ for ‘Example of sharing from an app’.
Buildozer log_level 2 for ‘Example of sharing from an app’.odt

Henrik R.

unread,
Dec 5, 2020, 11:15:23 AM12/5/20
to Kivy users support
The buildozer log for gradlew (the step that fails) says:

[DEBUG]: * Try:
[DEBUG]: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full

But I haven't found a way to pass such arguments to gradlew through buildozer.

planckp...@gmail.com

unread,
Dec 5, 2020, 12:05:30 PM12/5/20
to Kivy users support
I'm sorry I have no idea why these instructions will not build for you.

Yesterday I checked the instructions here, and rebuilt the app with no issue. 

I do not know where the issue is, I can't replicate it so I have nothing to work with.

Henrik R.

unread,
Dec 6, 2020, 2:41:05 PM12/6/20
to Kivy users support
I am running Ubuntu 20.04 LTS. Which OS are you running?

planckp...@gmail.com

unread,
Dec 6, 2020, 6:14:55 PM12/6/20
to Kivy users support
Same, but not as root.

In step 3 try replacing

Create these directories:
<App directory>/src/debug/res/xml
<App directory>/src/main/res/xml
Save the file a copy of the file in each /xml

with

Place it in (create the xml directory) :
<some_path>/python-for-android-master/pythonforandroid/bootstraps/sdl2/build/src/main/res/xml


then appclean, before build.

Henrik R.

unread,
Dec 7, 2020, 8:00:45 AM12/7/20
to Kivy users support
THAT worked!
Thank you very much!
And thank you for reminding me to do 'appclean'. I probably would not have thought about that. Buildozer is still very in-transparent and 'mysterious' to me... :-)
Now I will try to implement Google Earth into your example app.

planckp...@gmail.com

unread,
Dec 7, 2020, 12:10:44 PM12/7/20
to Kivy users support
Excellent

Henrik R.

unread,
Dec 7, 2020, 2:55:29 PM12/7/20
to Kivy users support
I have no luck with Google Earth so far.
But there is something strange:
It seems that button2 and 3 only works once, even after I compile and deploy again.
Button2 -> I choose File Manager+ -> "Could not load the file"
Button3:
The second time (etc.) the file 'from_earth.txt' has been renamed to 'rom_earth.txt' (when I am ask for Titel of Document to save on Google Drive. And whether I change it or not, I get "Upload failed".
And sometimes the buttons disappear all together until I press the screen...

planckp...@gmail.com

unread,
Dec 7, 2020, 3:16:58 PM12/7/20
to Kivy users support
Button2 -> I choose File Manager+ -> "Could not load the file"
I only tested with Google Dive, other apps may behave differently.
I'm not going to look at that, proof of concept is as far as I go.

The second time (etc.) the file 'from_earth.txt' has been renamed to '
I do not see this. I get Toast messages and multiple files displayed with the same name in Drive.

And sometimes the buttons disappear all together until I press the screen...
Phone power saving?

Henrik R.

unread,
Dec 7, 2020, 6:30:59 PM12/7/20
to Kivy users support
I haven't tested Google Earth yet, but now your 3 buttons work (again).
You must know something about join() that I (and PyCharm) don't know, because I need to write this (to satisfy PyCharm) AND make it work:

    def on_start(self):
        # Create some test data
        self.filename1 = '/'.join([app_storage_path(),'from_space.html'])

While you just write this:

    def on_start(self):
        # Create some test data
        self.filename1 = join(app_storage_path(),'from_space.html')

planckp...@gmail.com

unread,
Dec 7, 2020, 7:59:33 PM12/7/20
to Kivy users support
I'm using os.path.join( ) not the string method join()
But the string method is fine.

Apparently Pycharm is not able to figure out what is importing join().

Henrik R.

unread,
Dec 8, 2020, 4:34:40 AM12/8/20
to Kivy users support
Isn't that because you don't explicitly import 'os'. So the string version is default.

Henrik R.

unread,
Dec 8, 2020, 9:46:31 AM12/8/20
to Kivy users support
Sending a KML file to Google Earth doesn't work yet.

(Are there other forums where these questions are more appropriate?)

Solution 1: Using ShareSheet seems the easy way, but when I do this:

    self.filename3 = os.path.join(app_storage_path(),'myplaces-16x8-Emilie-Meng-pejlinger-2.kml')

    def button5_pressed(self,b):
         # FYI, other apps filter what they can receive using MIMEtype
         self.share_file_choose(self.filename3, "application/vnd.google-earth.kml+xml")

Android gives me a few apps to choose from, Google Earth NOT being one of them, although it is installed.

Solution 2: Sending it 'directly':

But where do you find the app domain for each app - like 'com.google.android.apps.docs'
I haven't been able to find that information for Google Earth yet.
I have tried guessing the following 2 app domains without luck:
'com.google.android.apps.earth' and 'com.google.earth'.
My earlier testing seemed to indicate that the latter is correct, but your information seems to indicate the contrary...

planckp...@gmail.com

unread,
Dec 8, 2020, 12:22:34 PM12/8/20
to Kivy users support
Perhaps the issue is MIME type ? That is how apps filer what they will receive?

Henrik R.

unread,
Dec 8, 2020, 1:57:17 PM12/8/20
to Kivy users support
I think I understand that. I found that MIME type for instance here: https://en.wikipedia.org/wiki/Keyhole_Markup_Language

But I just discovered a more basic and embarrassing problem:
The app cannot find the KML-file...
It's in the app folder just as main.py and buidozer.spec. And I changed this setting in buidozer.spec:

# (list) Source files to include (let empty to include all the files)
# source.include_exts = py,png,jpg,kv,atlas
source.include_exts =

I even did a 'buildozer appclean' and then "$ buildozer android debug deploy run". But when I do this command in Terminal:

$ adb logcat | grep -i " python "

I see this error in the output:

FileNotFoundError: [Errno 2] No such file or directory: '/data/user/0/org.test.myapp/files/myplaces-new.kml'

I think I understand quite a lot in life... but Buildozer is beyond anything I can understand...

By the way:
I just rediscovered that the app domain ("com.google.earth") is in the original information we started out with - how embarrassing!:

File KML = new File("/sdcard/doc.kml");
 Intent i = getPackageManager().getLaunchIntentForPackage("com.google.earth"); i.setDataAndType(Uri.fromFile(KML), "xml");
 startActivity(i);

planckp...@gmail.com

unread,
Dec 8, 2020, 4:20:08 PM12/8/20
to Kivy users support
If I understand the kml file is in '.' not app_storage_path  ?
The demo only allows sharing from app_storage_path
So just have the app move the file (if it exists)

Henrik R.

unread,
Dec 8, 2020, 5:54:10 PM12/8/20
to Kivy users support
Oops... I never considered that they were 2 different directories. In my other file operations I just use the filename.
Yes, the file exists. Thank you. :-)

I have not tried moving or copying a file before, and the 2 following attempts didn't work. I will have to find another way tomorrow:

self.filename4 = 'myplaces-new.kml'
self.filename3 = shutil.copy(self.filename4, app_storage_path)

self.filename4 = './myplaces-new.kml'
self.filename3 = shutil.copy(self.filename4, app_storage_path)

Good night. :-)

planckp...@gmail.com

unread,
Dec 8, 2020, 8:11:32 PM12/8/20
to Kivy users support
app_storage_path()

Henrik R.

unread,
Dec 9, 2020, 4:30:59 AM12/9/20
to Kivy users support
Oooh... I haven't fully accustomed to Python's error messages. I would have expected something like:
"Unknown identifier 'app_storage_path'"
Or:
"Parenthesis expected after 'app_storage_path'"

I also accidentally created a variable called 'str' with the result that the function str() stopped working and was regarded as the variable. I would have preferred the error that I had accidentally used a reserved word or something like that. :-)

But back the serious problems:

I asked about app package domain and MIME type for Google Earth here: https://support.google.com/earth/thread/87413940

And received this quite disappointing answer:

"There's currently no API for Google Earth.  You might be able to do something with the Google Maps API.  The support options are at the bottom of that page."

That's disappointing and surprising considering that our whole discussion started with a 5 years old page stating that you can send a KML file to Google Earth on Android with the code below:

File KML = new File("/sdcard/doc.kml");
 Intent i = getPackageManager().getLaunchIntentForPackage("com.google.earth"); i.setDataAndType(Uri.fromFile(KML), "xml");
 startActivity(i);

I tried both 'com.google.android.apps.earth' and 'com.google.earth' anyway, but both give the exception below. So I guess I will have to settle for just asking the user to put the KML file in a place where he/she can find it from inside Google Earth...:

Screenshot_20201209-085757.png

I attach my version of the test 'main.py', where 'button4_pressed' is the method that does NOT work.

main.py

planckp...@gmail.com

unread,
Dec 9, 2020, 12:13:32 PM12/9/20
to Kivy users support
I think perhaps "API" was interpreted as something different, as a programing interface, not as a file interface.

I would interpret the error message as either the app name is incorrect, or the MIME type is incorrect.But it might be something else.

It seems reasonable that one can share a file with Google Earth.
It is just a question of figuring out the details.
I have other priorities,  and I'm not going to do that work for you.

Henrik R.

unread,
Dec 9, 2020, 12:58:24 PM12/9/20
to Kivy users support
I agree that it's strange if there is no file interface AND that it is not your job to solve that! :-)

Henrik R.

unread,
Dec 10, 2020, 7:21:31 AM12/10/20
to Kivy users support
Conclusion:
I can now send my KML file to Downloads or Google Drive via ShareSheet. From there it's just a click to open it with Google Earth! THANK YOU very much to Robert 'Planck'!

I hate to ask this: But how do you do it on iOS/iPhone....?
One of the reasons I originally chose Python/Kivy is that it is supposedly cross-platform...

planckp...@gmail.com

unread,
Dec 10, 2020, 12:09:10 PM12/10/20
to Kivy users support
I know nothing of iOS

Henrik R.

unread,
Dec 10, 2020, 2:27:29 PM12/10/20
to Kivy users support
OK. I guess you didn't choose Python/Kivy for it's supposed cross-platform abilities. :-)
But thank you again!

Henrik R.

unread,
Jul 6, 2021, 5:06:45 AM7/6/21
to Kivy users support
Dear Robert

Elliot found a post from 2018 on how to send a KML file to Google Earth (in Java):
The newest answer, from October 2018 says that you can send a KML file to Google Earth (in Java) in the following way:

Uri uriFromFile = FileProvider.getUriForFile(context, GenericFileProvider.class.getName(), file);

Intent intent = new Intent(Intent.ACTION_VIEW);

intent.setDataAndType(uriFromFile, "application/vnd.google-earth.kml+xml");

intent.putExtra("com.google.earth.EXTRA.tour_feature_id", "my_track");

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(intent);


Do you know if this is still relevant? Or obsolete/deprecated by now?

Robert

unread,
Jul 6, 2021, 12:22:04 PM7/6/21
to Kivy users support
No idea
Reply all
Reply to author
Forward
0 new messages