#Deprecated this article (Reference to New article)
iOSでURL連携を行うには、どのように行えば良いかを調べました。kivy-ios内にメールAPPとの連携の部分があったのでそれを参考に実装することができます。
1.呼び出し編
try:
from urllib.parse import quote
except ImportError:
from urllib import quote
from pyobjus import autoclass, objc_str
from pyobjus.dylib_manager import load_framework
load_framework('/System/Library/Frameworks/UIKit.framework')
NSURL = autoclass('NSURL')
NSString = autoclass('NSString')
UIApplication = autoclass('UIApplication')
uri = "mailto:mail@dom.com?subject=text&body=body"
nsurl = NSURL.alloc().initWithString_(objc_str(uri))
UIApplication.sharedApplication().openURL_(nsurl)
2.呼び出され編
参考サイトを参考にして、XCodeでurlschemeを定義します。これで、他のアプリケーションから呼び出されるようになりますが、ほとんどのアプリケーションは引数を受け取りたいと思うはずです。しかし、kivy-iosでは標準では引数を受け取れないようで、なんらかの仕組みで受け取る必要があります。kivyでは、ドロップファイルのイベントを生成する時にiOSのopenUrlのイベントを受け取るようになっています。しかし、これはアプリケーションまで、イベントが伝わってないため受け取れません。新規でイベントを追加するよりもこれを流用した方が簡単なので流用します。修正場所は、kivy-iosディレクトリのtmpの下です。
・kivy内のCython用のSDLイベント定義にドロップファイルのインターフェースを追加します。
.
.
.
ctypedef struct SDL_TouchFingerEvent:
long touchId
long fingerId
unsigned char state
unsigned short x
unsigned short y
short dx
short dy
unsigned short pressure
# add start
ctypedef struct SDL_DropEvent:
unsigned int timestamp
char *file
# add end
ctypedef struct SDL_Event:
unsigned int type
SDL_MouseMotionEvent motion
SDL_MouseButtonEvent button
SDL_WindowEvent window
SDL_KeyboardEvent key
SDL_TextInputEvent text
SDL_TouchFingerEvent tfinger
# add start
SDL_DropEvent drop
# add end
# Events
int SDL_QUIT
int SDL_WINDOWEVENT
int SDL_SYSWMEVENT
int SDL_KEYDOWN
int SDL_KEYUP
int SDL_MOUSEMOTION
int SDL_MOUSEBUTTONDOWN
int SDL_MOUSEBUTTONUP
int SDL_TEXTINPUT
int SDL_FINGERDOWN
int SDL_FINGERUP
int SDL_FINGERMOTION
# add start
int SDL_DROPFILE
# add end
.
.
.
elif event.type == SDL_TEXTINPUT:
s = PyUnicode_FromString(<char *>event.text.text)
return ('textinput', s)
# add start
elif event.type == SDL_DROPFILE:
s = PyUnicode_FromString(<char *>event.drop.file)
action = ('dropfile', s)
return action
# add end
else:
if __debug__:
print('receive unknown sdl event', event.type)
pass
.
.
.
・SDLのラッパーの部分で上記イベントを捕捉できるようにします。
.
.
.
def _mainloop(self):
EventLoop.idle()
while True:
event = sdl.poll()
.
.
.
elif action == 'textinput':
key = args[0][0]
# XXX on IOS, keydown/up don't send unicode anymore.
# With latest sdl, the text is sent over textinput
# Right now, redo keydown/up, but we need to seperate both call
# too. (and adapt on_key_* API.)
self.dispatch('on_key_down', key, None, args[0],
self.modifiers)
self.dispatch('on_keyboard', None, None, args[0],
self.modifiers)
self.dispatch('on_key_up', key, None, args[0],
self.modifiers)
# add start
elif action == 'dropfile':
self.dispatch('on_dropfile', args[0])
# add end
# # video resize
# elif event.type == pygame.VIDEORESIZE:
.
.
.
# XXX FIXME wait for sdl resume
while True:
event = sdl.poll()
if event is False:
continue
if event is None:
continue
action, args = event[0], event[1:]
if action == 'quit':
EventLoop.quit = True
self.close()
break
elif action == 'windowrestored':
break
# add start
elif action == 'dropfile':
app.dispatch('on_dropfile', args[0])
# add end
.
.
.
・メイン関数で受け取れるようにドロップファイルのイベントインターフェースを追加します。
.
.
.
# Return the current running App instance
_running_app = None
# modify start ( add on_dropfile )
__events__ = ('on_start', 'on_stop', 'on_pause', 'on_resume', 'on_dropfile')
# modify end
def __init__(self, **kwargs):
App._running_app = self
self._app_directory = None
self._app_name = None
.
.
.
def on_resume(self):
'''Event handler called when your application is resuming from
the Pause mode.
.. versionadded:: 1.1.0
.. warning::
When resuming, the OpenGL Context might have been damaged / freed.
This is where you can reconstruct some of your OpenGL state
e.g. FBO content.
'''
pass
# add start
def on_dropfile(self, filename):
'''Event called when a file is dropped on the application.
.. warning::
This event is currently used only on MacOSX with a patched version
of pygame, but is left in place for further evolution (ios,
android etc.)
.. versionadded:: 1.2.0
'''
pass
# add end
@staticmethod
def get_running_app():
.
.
.
・Tools/Build-all.shを実行後、自分のメイン関数に def on_dropfile(self, filename): を定義すると、イベントとして取得可能となります。注意点としてはURLエンコードされているので、取得後にURLデコードを行う必要があります(URLデコード参考)。
.
.
.
def on_dropfile(self, filename): <---- ここで、URL連携で呼び出された引数を取得可能になる。
print self.mydecode(filename)
def mydecode(self, value):
if isinstance(value, unicode):
value = value.encode('raw_unicode_escape')
value = urllib.unquote(value)
return value
if __name__ == '__main__':
TestApp().run()
※kivy-iosで連携が可能となりますが、このやり方は製作者の意図しない方法ですのでバージョンアップの際には使用できなくなる可能性がありますので、留意が必要です。