Source code for enamlnative.android.android_activity
"""
Copyright (c) 2017-2022, CodeLV.
Distributed under the terms of the MIT License.
The full license is in the file LICENSE, distributed with this software.
Created on July 24, 2017
"""
from atom.api import Int, Typed, Instance
from enamlnative.widgets.activity import ProxyActivity
from .android_content import Context, Intent
from .android_view import View
from .android_window import Window
from .android_utils import HashMap
from .bridge import JavaCallback, JavaMethod
class Activity(Context):
"""Access to the activity over the bridge"""
#: As long as the user subclasses the EnamlActivity
#: everything in this class will work
__nativeclass__ = "com.codelv.enamlnative.EnamlActivity"
#: ID of -1 is a special reference on the bridge to the activity.
__id__ = Int(-1)
ORIENTATIONS = ("square", "portrait", "landscape")
#: Tracing methods
startTrace = JavaMethod(str)
stopTrace = JavaMethod(str)
resetBridgeStats = JavaMethod()
resetBridgeCache = JavaMethod()
setView = JavaMethod(View)
showLoading = JavaMethod(str)
setActionBar = JavaMethod("android.widget.Toolbar")
setSupportActionBar = JavaMethod("androidx.appcompat.widget.Toolbar")
setContentView = JavaMethod(View)
getWindow = JavaMethod(returns=Window)
getSupportFragmentManager = JavaMethod(
returns="androidx.fragment.app.FragmentManager"
)
getBuildInfo = JavaMethod(returns=HashMap)
#: Permissions
checkSelfPermission = JavaMethod(str, returns=int)
requestPermissions = JavaMethod(list[str], int)
onRequestPermissionsResult = JavaCallback(int, list[str], list[int])
#: Method added so we can listen externally
setPermissionResultListener = JavaMethod(
"com.codelv.enamlnative.EnamlActivity$PermissionResultListener"
)
PERMISSION_GRANTED = 0
PERMISSION_DENIED = -1
#: Activity results
addActivityResultListener = JavaMethod(
"com.codelv.enamlnative.EnamlActivity$ActivityResultListener"
)
removeActivityResultListener = JavaMethod(
"com.codelv.enamlnative.EnamlActivity$ActivityResultListener"
)
onActivityResult = JavaCallback(int, int, Intent, returns=bool)
#: Activity lifecycle listener
addActivityLifecycleListener = JavaMethod(
"com.codelv.enamlnative.EnamlActivity$ActivityLifecycleListener"
)
removeActivityLifecycleListener = JavaMethod(
"com.codelv.enamlnative.EnamlActivity$ActivityLifecycleListener"
)
#: Called with the lifecycle state like 'pause', 'resume', etc...
onActivityLifecycleChanged = JavaCallback(str)
#: Back pressed listener
addBackPressedListener = JavaMethod(
"com.codelv.enamlnative.EnamlActivity$BackPressedListener"
)
removeBackPressedListener = JavaMethod(
"com.codelv.enamlnative.EnamlActivity$BackPressedListener"
)
#: Called with the lifecycle state like 'pause', 'resume', etc...
onBackPressed = JavaCallback(returns=bool)
#: Back pressed listener
addConfigurationChangedListener = JavaMethod(
"com.codelv.enamlnative.EnamlActivity$ConfigurationChangedListener"
)
removeConfigurationChangedListener = JavaMethod(
"com.codelv.enamlnative.EnamlActivity$ConfigurationChangedListener"
)
#: Called with the lifecycle state like 'pause', 'resume', etc...
onConfigurationChanged = JavaCallback(HashMap)
[docs]class AndroidActivity(ProxyActivity):
#: Reference to the activty
widget = Typed(Activity)
#: Default window id
window = Typed(Window)
#: View currently displayed
view = Instance(View)
def create_widget(self):
self.widget = Activity(__id__=-1)
[docs] async def start(self):
"""Start the activity and retrieve the window id"""
# NOTE: This does NOT inherit from the AndroidToolkitObject
# so it must be initialized here
self.create_widget()
self.init_widget()
activity = self.widget
d = self.declaration
info = d.build_info = await activity.getBuildInfo()
d.dp = info["DISPLAY_DENSITY"]
d.width = info["DISPLAY_WIDTH"]
d.height = info["DISPLAY_HEIGHT"]
d.orientation = Activity.ORIENTATIONS[info["DISPLAY_ORIENTATION"]]
d.api_level = info["SDK_INT"]
self.window = await activity.getWindow()
[docs] def activate_bottom_up(self):
"""Show the first child view of the window"""
self.reload_view()
[docs] def child_added(self, child):
super().child_added(child)
if self.window is not None:
self.reload_view()
def reload_view(self):
activity = self.widget
window = next(self.children())
view = self.view = next(window.child_widgets())
activity.setView(view)
def show_loading(self, message):
self.widget.showLoading(message)
[docs] def on_activity_lifecycle_changed(self, state):
"""Update the state when the android app is paused, resumed, etc..
Widgets can observe this value for changes if they need to react
to app lifecycle changes.
"""
d = self.declaration
d.state = state
if state == "started":
d.started()
elif state == "paused":
d.paused()
elif state == "resumed":
d.resumed()
elif state == "stopped":
d.stopped()
[docs] def on_back_pressed(self):
"""Fire the `back_pressed` event with a dictionary with a 'handled'
key when the back hardware button is pressed
If 'handled' is set to any value that evaluates to True the
default event implementation will be ignored.
"""
d = self.declaration
try:
return bool(d.on_back_pressed())
except Exception as e:
d.app.show_error(f"Error handling back press: {e}")
#: Must return a boolean or we will cause android to abort
return True
[docs] def on_configuration_changed(self, config):
"""Handles a screen configuration change."""
self.width = config["width"]
self.height = config["height"]
self.orientation = Activity.ORIENTATIONS[config["orientation"]]