11 Deep Linking with iOS and Android
Olivier Boesch edited this page 2021-05-02 12:24:00 +02:00

There is an updated version in this repository: https://github.com/olivier-boesch/intent-demo-for-kivy I used the code below as a starting point


Summary

  • author: Hunter Knight
  • kivy: >= 1.9.1

Thanks to Python for Dads for the Android tips and ideas for how to handle simultaneous launch of on_resume and on_new_intent.

Also, for iOS you need to Register a Custom URL Scheme, and you'll want to read up on [securing inter-app communication] (https://developer.apple.com/library/content/documentation/Security/Conceptual/SecureCodingGuide/Articles/ValidatingInput.html#//apple_ref/doc/uid/TP40007246)

Please note that this is not a complete, working app demo. You need to integrate the functionality of these methods, and particularly the bindings at the bottom during initialization.

Usage

#!python

from kivy.app import App
from kivy.core.window import Window
from kivy.clock import Clock


class TestApp(App):

    resuming = False
    processing_uri = False
    
    def on_pause(self):

        #
        # Handle pause behavior here
        #
        # set resuming to True so on_new_intent will definitely wait for on_resume 
        # to finish
        self.resuming = True

        # Important! on_dropfile events are not received while the event loop is 
        # paused! This ensures that the event loop will resume before any 
        # on_dropfile event is fired. Many Bothans died to  bring us this information...
        if platform == 'ios':
            # Set this to True elsewhere in your code if you are pausing to wait for a 
            # deeplink redirect back to your app (e.g. after FB OAUTH)
            if self.processing_uri:
                self.processing_uri = False
                Clock.schedule_once(self.resume_tasks, -1)
                Clock.schedule_once(self.on_resume, -1)
            
        return True

    def resume_tasks(self, *args):
        Window._pause_loop = False

    def on_resume(self):
        # In case on_resume and on_new_intent are triggered at launch
        self.resuming = True
            
        #
        # Handle resume behavior here
        #

        self.resuming = False

    def android_message(self, intent):
        while self.resuming:
            sleep(0.1)
        intent_data = intent.getData()
        uri = intent_data.toString()
        # send full URI to a cross-platform function to process
        self.process_deep_link(uri)

    def ios_message(self, window, uri):
        # send full URI to a cross-platform function to process
        self.process_deep_link(uri)

    def process_deep_link(self, uri):
        # Validate, parse, do things...
        pass


if __name__ == '__main__':
    app_instance = TestApp()
    if platform == 'android':
        import android.activity
        android.activity.bind(on_new_intent=app_instance.android_message)
    elif platform == 'ios':
        Window.bind(on_dropfile=app_instance.ios_message)
    app_instance.run()