Skip to content

Commit

Permalink
Merge pull request #1217 from t-arn/android_intent
Browse files Browse the repository at this point in the history
Call arbitrary Android intents and get result back
  • Loading branch information
freakboy3742 authored May 23, 2021
2 parents 7926e28 + e005eea commit 183493a
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
46 changes: 46 additions & 0 deletions src/android/toga_android/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@
from .libs.activity import IPythonApp, MainActivity
from .window import Window

import asyncio


# `MainWindow` is defined here in `app.py`, not `window.py`, to mollify the test suite.
class MainWindow(Window):
pass


class TogaApp(IPythonApp):
last_intent_requestcode = -1 # always increment before using it for invoking new Intents
running_intents = {} # dictionary for currently running Intents

def __init__(self, app):
super().__init__()
self._interface = app
Expand Down Expand Up @@ -39,6 +44,25 @@ def onDestroy(self):
def onRestart(self):
print("Toga app: onRestart")

def onActivityResult(self, requestCode, resultCode, resultData):
"""
Callback method, called from MainActivity when an Intent ends
:param int requestCode: The integer request code originally supplied to startActivityForResult(),
allowing you to identify who this result came from.
:param int resultCode: The integer result code returned by the child activity through its setResult().
:param Intent resultData: An Intent, which can return result data to the caller (various data can be attached
to Intent "extras").
"""
print("Toga app: onActivityResult, requestCode={0}, resultData={1}".format(requestCode, resultData))
try:
# remove Intent from the list of running Intents,
# and set the result of the intent.
result_future = self.running_intents.pop(requestCode)
result_future.set_result({"resultCode": resultCode, "resultData": resultData})
except KeyError:
print("No intent matching request code {requestCode}")

@property
def native(self):
# We access `MainActivity.singletonThis` freshly each time, rather than
Expand Down Expand Up @@ -92,3 +116,25 @@ def set_on_exit(self, value):

def add_background_task(self, handler):
self.loop.call_soon(wrapped_handler(self, handler), self)

async def intent_result(self, intent):
"""
Calls an Intent and waits for its result.
A RuntimeError will be raised when the Intent cannot be invoked.
:param Intent intent: The Intent to call
:returns: A Dictionary containing "resultCode" (int) and "resultData" (Intent or None)
:rtype: dict
"""
if intent.resolveActivity(self.native.getPackageManager()) is None:
raise RuntimeError('No appropriate Activity found to handle this intent.')
self._listener.last_intent_requestcode += 1
code = self._listener.last_intent_requestcode

result_future = asyncio.Future()
self._listener.running_intents[code] = result_future

self.native.startActivityForResult(intent, code)
await result_future
return result_future.result()
1 change: 1 addition & 0 deletions src/android/toga_android/libs/android.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from rubicon.java import JavaClass, JavaInterface

Color = JavaClass("android/graphics/Color")
Intent = JavaClass("android/content/Intent")
MotionEvent = JavaClass("android/view/MotionEvent")
PorterDuff__Mode = JavaClass("android/graphics/PorterDuff$Mode")
View__OnTouchListener = JavaInterface("android/view/View$OnTouchListener")

0 comments on commit 183493a

Please sign in to comment.