You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
Add auto_start_app setting
This commit is contained in:
@@ -36,10 +36,13 @@ class SettingsActivity(Activity):
|
||||
("Turquoise", "40e0d0")
|
||||
]
|
||||
self.settings = [
|
||||
# Novice settings, alphabetically:
|
||||
{"title": "Light/Dark Theme", "key": "theme_light_dark", "value_label": None, "cont": None, "ui": "radiobuttons", "ui_options": [("Light", "light"), ("Dark", "dark")]},
|
||||
{"title": "Theme Color", "key": "theme_primary_color", "value_label": None, "cont": None, "placeholder": "HTML hex color, like: EC048C", "ui": "dropdown", "ui_options": theme_colors},
|
||||
{"title": "Restart to Bootloader", "key": "boot_mode", "value_label": None, "cont": None, "ui": "radiobuttons", "ui_options": [("Normal", "normal"), ("Bootloader", "bootloader")]}, # special that doesn't get saved
|
||||
{"title": "Timezone", "key": "timezone", "value_label": None, "cont": None, "ui": "dropdown", "ui_options": self.get_timezone_tuples(), "changed_callback": lambda : mpos.time.refresh_timezone_preference()},
|
||||
# Advanced settings, alphabetically:
|
||||
{"title": "Auto Start App", "key": "auto_start_app", "value_label": None, "cont": None, "ui": "radiobuttons", "ui_options": [("Launcher", "com.micropythonos.launcher"), ("LightningPiggy", "com.lightningpiggy.displaywallet")]},
|
||||
{"title": "Restart to Bootloader", "key": "boot_mode", "value_label": None, "cont": None, "ui": "radiobuttons", "ui_options": [("Normal", "normal"), ("Bootloader", "bootloader")]}, # special that doesn't get saved
|
||||
# This is currently only in the drawer but would make sense to have it here for completeness:
|
||||
#{"title": "Display Brightness", "key": "display_brightness", "value_label": None, "cont": None, "placeholder": "A value from 0 to 100."},
|
||||
# Maybe also add font size (but ideally then all fonts should scale up/down)
|
||||
|
||||
@@ -17,6 +17,7 @@ def good_stack_size():
|
||||
return stacksize
|
||||
|
||||
# Run the script in the current thread:
|
||||
# Returns True if successful
|
||||
def execute_script(script_source, is_file, cwd=None, classname=None):
|
||||
import utime # for timing read and compile
|
||||
thread_id = _thread.get_ident()
|
||||
@@ -55,26 +56,32 @@ def execute_script(script_source, is_file, cwd=None, classname=None):
|
||||
#print("Classes:", classes.keys())
|
||||
#print("Functions:", functions.keys())
|
||||
#print("Variables:", variables.keys())
|
||||
if classname:
|
||||
main_activity = script_globals.get(classname)
|
||||
if main_activity:
|
||||
start_time = utime.ticks_ms()
|
||||
Activity.startActivity(None, Intent(activity_class=main_activity))
|
||||
end_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"execute_script: Activity.startActivity took {end_time}ms")
|
||||
else:
|
||||
print("Warning: could not find main_activity")
|
||||
if not classname:
|
||||
print("Running without a classname isn't supported right now.")
|
||||
return False
|
||||
main_activity = script_globals.get(classname)
|
||||
if main_activity:
|
||||
start_time = utime.ticks_ms()
|
||||
Activity.startActivity(None, Intent(activity_class=main_activity))
|
||||
end_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"execute_script: Activity.startActivity took {end_time}ms")
|
||||
else:
|
||||
print(f"Warning: could not find app's main_activity {main_activity}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Thread {thread_id}: exception during execution:")
|
||||
# Print stack trace with exception type, value, and traceback
|
||||
tb = getattr(e, '__traceback__', None)
|
||||
traceback.print_exception(type(e), e, tb)
|
||||
print(f"Thread {thread_id}: script {compile_name} finished")
|
||||
return False
|
||||
print(f"Thread {thread_id}: script {compile_name} finished, restoring sys.path to {sys.path}")
|
||||
sys.path = path_before
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Thread {thread_id}: error:")
|
||||
tb = getattr(e, '__traceback__', None)
|
||||
traceback.print_exception(type(e), e, tb)
|
||||
return False
|
||||
|
||||
""" Unused:
|
||||
# Run the script in a new thread:
|
||||
@@ -104,6 +111,7 @@ def execute_script_new_thread(scriptname, is_file):
|
||||
print("main.py: execute_script_new_thread(): error starting new thread thread: ", e)
|
||||
"""
|
||||
|
||||
# Returns True if successful
|
||||
def start_app(fullname):
|
||||
mpos.ui.set_foreground_app(fullname)
|
||||
import utime
|
||||
@@ -119,7 +127,7 @@ def start_app(fullname):
|
||||
print(f"WARNING: start_app can't start {fullname} because it doesn't have a main_launcher_activity")
|
||||
return
|
||||
start_script_fullpath = f"{app.installed_path}/{app.main_launcher_activity.get('entrypoint')}"
|
||||
execute_script(start_script_fullpath, True, app.installed_path + "/assets/", app.main_launcher_activity.get("classname"))
|
||||
result = execute_script(start_script_fullpath, True, app.installed_path + "/assets/", app.main_launcher_activity.get("classname"))
|
||||
# Launchers have the bar, other apps don't have it
|
||||
if app.is_valid_launcher():
|
||||
mpos.ui.topmenu.open_bar()
|
||||
@@ -127,6 +135,8 @@ def start_app(fullname):
|
||||
mpos.ui.topmenu.close_bar()
|
||||
end_time = utime.ticks_diff(utime.ticks_ms(), start_time)
|
||||
print(f"start_app() took {end_time}ms")
|
||||
return result
|
||||
|
||||
|
||||
# Starts the first launcher that's found
|
||||
def restart_launcher():
|
||||
@@ -134,9 +144,5 @@ def restart_launcher():
|
||||
# Stop all apps
|
||||
mpos.ui.remove_and_stop_all_activities()
|
||||
# No need to stop the other launcher first, because it exits after building the screen
|
||||
for app in PackageManager.get_app_list():
|
||||
if app.is_valid_launcher():
|
||||
print(f"Found launcher, starting {app.fullname}")
|
||||
start_app(app.fullname)
|
||||
break
|
||||
return start_app(PackageManager.get_launcher().fullname)
|
||||
|
||||
|
||||
@@ -73,8 +73,17 @@ class PackageManager:
|
||||
|
||||
@classmethod
|
||||
def get(cls, fullname):
|
||||
if not cls._app_list:
|
||||
cls.refresh_apps()
|
||||
return cls._by_fullname.get(fullname)
|
||||
|
||||
@classmethod
|
||||
def get_launcher(cls):
|
||||
for app in cls.get_app_list():
|
||||
if app.is_valid_launcher():
|
||||
print(f"Found launcher {app.fullname}")
|
||||
return app
|
||||
|
||||
@classmethod
|
||||
def clear(cls):
|
||||
"""Empty the internal caches. Call ``get_app_list()`` afterwards to repopulate."""
|
||||
@@ -223,4 +232,3 @@ class PackageManager:
|
||||
print(f"Checking if app {app_fullname} is installed...")
|
||||
return PackageManager.is_installed_by_path(f"apps/{app_fullname}") or PackageManager.is_installed_by_path(f"builtin/apps/{app_fullname}")
|
||||
|
||||
|
||||
|
||||
@@ -271,10 +271,10 @@ def create_drawer(display=None):
|
||||
launcher_btn.set_size(lv.pct(drawer_button_pct),lv.pct(20))
|
||||
launcher_btn.align(lv.ALIGN.CENTER,0,0)
|
||||
launcher_label=lv.label(launcher_btn)
|
||||
launcher_label.set_text(lv.SYMBOL.HOME+" Home")
|
||||
launcher_label.set_text(lv.SYMBOL.HOME+" Launch")
|
||||
launcher_label.center()
|
||||
def launcher_event(e):
|
||||
print("Home button pressed!")
|
||||
print("Launch button pressed!")
|
||||
close_drawer(True)
|
||||
mpos.apps.restart_launcher()
|
||||
launcher_btn.add_event_cb(launcher_event,lv.EVENT.CLICKED,None)
|
||||
|
||||
@@ -12,6 +12,7 @@ import mpos.config
|
||||
import mpos.ui
|
||||
import mpos.ui.topmenu
|
||||
from mpos.ui.display import init_rootscreen
|
||||
from mpos.content.package_manager import PackageManager
|
||||
|
||||
prefs = mpos.config.SharedPreferences("com.micropythonos.settings")
|
||||
|
||||
@@ -71,7 +72,13 @@ try:
|
||||
except Exception as e:
|
||||
print(f"Couldn't start mpos.wifi.WifiService.auto_connect thread because: {e}")
|
||||
|
||||
mpos.apps.restart_launcher()
|
||||
# Start launcher so it's always at bottom of stack
|
||||
launcher_app = PackageManager.get_launcher()
|
||||
mpos.apps.start_app(launcher_app.fullname)
|
||||
# Then start another app if configured
|
||||
auto_start_app = prefs.get_string("auto_start_app", None)
|
||||
if auto_start_app and launcher_app.fullname != auto_start_app:
|
||||
mpos.apps.start_app(auto_start_app)
|
||||
|
||||
# If we got this far without crashing, then no need to rollback the update:
|
||||
try:
|
||||
|
||||
@@ -14,7 +14,10 @@ mkdir -p "$output"
|
||||
#rm "$output"/*.png
|
||||
rm "$outputjson"
|
||||
|
||||
blacklist="com.micropythonos.filemanager com.example.bla"
|
||||
# These apps are for testing, or aren't ready yet:
|
||||
# com.quasikili.quasidoodle doesn't work on touch screen devices
|
||||
# com.micropythonos.filemanager doesn't do anything other than let you browse the filesystem, so it's confusing
|
||||
blacklist="com.micropythonos.filemanager com.quasikili.quasidoodle"
|
||||
|
||||
echo "[" | tee -a "$outputjson"
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import unittest
|
||||
|
||||
import sdl_display
|
||||
import lcd_bus
|
||||
import lvgl as lv
|
||||
import mpos.ui
|
||||
import task_handler
|
||||
import mpos.apps
|
||||
import mpos.ui.topmenu
|
||||
import mpos.config
|
||||
from mpos.ui.display import init_rootscreen
|
||||
|
||||
class TestStartApp(unittest.TestCase):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
TFT_HOR_RES=320
|
||||
TFT_VER_RES=240
|
||||
|
||||
bus = lcd_bus.SDLBus(flags=0)
|
||||
buf1 = bus.allocate_framebuffer(320 * 240 * 2, 0)
|
||||
display = sdl_display.SDLDisplay(data_bus=bus,display_width=TFT_HOR_RES,display_height=TFT_VER_RES,frame_buffer1=buf1,color_space=lv.COLOR_FORMAT.RGB565)
|
||||
display.init()
|
||||
init_rootscreen()
|
||||
mpos.ui.topmenu.create_notification_bar()
|
||||
mpos.ui.topmenu.create_drawer(display)
|
||||
mpos.ui.th = task_handler.TaskHandler(duration=5) # 5ms is recommended for MicroPython+LVGL on desktop (less results in lower framerate)
|
||||
|
||||
|
||||
def test_normal(self):
|
||||
self.assertTrue(mpos.apps.start_app("com.micropythonos.launcher"), "com.micropythonos.launcher should start")
|
||||
|
||||
def test_nonexistent(self):
|
||||
self.assertFalse(mpos.apps.start_app("com.micropythonos.nonexistent"), "com.micropythonos.nonexistent should not start")
|
||||
|
||||
def test_restart_launcher(self):
|
||||
self.assertTrue(mpos.apps.restart_launcher(), "restart_launcher() should succeed")
|
||||
Reference in New Issue
Block a user