fix Android: load shell.rml, add loadAppContent function, fallback to built-in apps
This commit is contained in:
70
install-device.bat
Normal file
70
install-device.bat
Normal file
@@ -0,0 +1,70 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
echo ========================================
|
||||
echo Mosis Device Installation Script
|
||||
echo ========================================
|
||||
echo.
|
||||
|
||||
:: Package name
|
||||
set PACKAGE=com.omixlab.mosis
|
||||
set DEVICE_APPS_DIR=files/apps
|
||||
|
||||
:: Step 1: Build and install APK
|
||||
echo [1/3] Building and installing debug APK...
|
||||
call gradlew installDebug
|
||||
if errorlevel 1 (
|
||||
echo ERROR: Failed to install APK
|
||||
exit /b 1
|
||||
)
|
||||
echo.
|
||||
|
||||
:: Step 2: Push base-apps to temp location
|
||||
echo [2/3] Pushing base-apps to temp location...
|
||||
adb shell "rm -rf /data/local/tmp/mosis-apps" 2>nul
|
||||
adb push base-apps /data/local/tmp/mosis-apps
|
||||
if errorlevel 1 (
|
||||
echo ERROR: Failed to push base-apps
|
||||
exit /b 1
|
||||
)
|
||||
echo.
|
||||
|
||||
:: Step 3: Copy to private data using run-as
|
||||
echo [3/3] Installing apps to internal storage...
|
||||
echo Using run-as for /data/data/%PACKAGE%/%DEVICE_APPS_DIR%/
|
||||
echo.
|
||||
|
||||
:: Create apps directory
|
||||
adb shell "run-as %PACKAGE% mkdir -p %DEVICE_APPS_DIR%"
|
||||
|
||||
:: List of apps to install
|
||||
for /d %%A in (base-apps\com.mosis.*) do (
|
||||
set APP_ID=%%~nxA
|
||||
echo Installing !APP_ID!...
|
||||
|
||||
:: Create app directory structure
|
||||
adb shell "run-as %PACKAGE% mkdir -p %DEVICE_APPS_DIR%/!APP_ID!"
|
||||
|
||||
:: Copy files using tar through run-as (faster than individual files)
|
||||
adb shell "cd /data/local/tmp/mosis-apps/!APP_ID! && tar cf - . | run-as %PACKAGE% tar xf - -C %DEVICE_APPS_DIR%/!APP_ID!/"
|
||||
)
|
||||
|
||||
:: Cleanup temp files
|
||||
echo.
|
||||
echo Cleaning up temp files...
|
||||
adb shell "rm -rf /data/local/tmp/mosis-apps"
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo Installation complete!
|
||||
echo ========================================
|
||||
echo.
|
||||
echo APK: %PACKAGE%
|
||||
echo Apps: /data/data/%PACKAGE%/%DEVICE_APPS_DIR%/
|
||||
echo.
|
||||
echo Verify with:
|
||||
echo adb shell "run-as %PACKAGE% ls -la %DEVICE_APPS_DIR%"
|
||||
echo.
|
||||
echo Launch with:
|
||||
echo adb shell am start -n %PACKAGE%/.MainActivity
|
||||
echo.
|
||||
@@ -385,17 +385,31 @@ function getAppColor(package_id)
|
||||
return color
|
||||
end
|
||||
|
||||
-- Built-in system apps (fallback when mosis.apps not available or empty)
|
||||
local builtin_apps = {
|
||||
{package_id = "com.mosis.browser", name = "Browser", icon = "../../icons/browser.tga"},
|
||||
{package_id = "com.mosis.camera", name = "Camera", icon = "../../icons/camera.tga"},
|
||||
{package_id = "com.mosis.contacts", name = "Contacts", icon = "../../icons/contacts.tga"},
|
||||
{package_id = "com.mosis.dialer", name = "Phone", icon = "../../icons/phone.tga"},
|
||||
{package_id = "com.mosis.messages", name = "Messages", icon = "../../icons/message.tga"},
|
||||
{package_id = "com.mosis.music", name = "Music", icon = "../../icons/music.tga"},
|
||||
{package_id = "com.mosis.settings", name = "Settings", icon = "../../icons/settings.tga"},
|
||||
{package_id = "com.mosis.store", name = "Store", icon = "../../icons/store.tga"},
|
||||
}
|
||||
|
||||
-- Populate home screen with discovered apps
|
||||
function populateHomeApps()
|
||||
if not mosis or not mosis.apps then
|
||||
print("[Shell] mosis.apps not available")
|
||||
return
|
||||
local apps = nil
|
||||
|
||||
-- Try to get installed apps from mosis.apps API
|
||||
if mosis and mosis.apps then
|
||||
apps = mosis.apps.getInstalled()
|
||||
end
|
||||
|
||||
local apps = mosis.apps.getInstalled()
|
||||
-- Fall back to built-in apps if none discovered
|
||||
if not apps or #apps == 0 then
|
||||
print("[Shell] No apps discovered")
|
||||
return
|
||||
print("[Shell] Using built-in system apps")
|
||||
apps = builtin_apps
|
||||
end
|
||||
|
||||
print("[Shell] Populating home with " .. #apps .. " apps")
|
||||
@@ -468,37 +482,48 @@ end
|
||||
|
||||
-- Launch a discovered app by package_id
|
||||
function launchDiscoveredApp(package_id)
|
||||
if not mosis or not mosis.apps then
|
||||
print("[Shell] mosis.apps not available")
|
||||
showToast("Cannot launch app", "error")
|
||||
return
|
||||
print("[Shell] Launching app: " .. package_id)
|
||||
|
||||
-- Check if it's a built-in system app
|
||||
local app_id = package_id:gsub("com.mosis.", "")
|
||||
local builtin_ids = {
|
||||
browser = true, camera = true, contacts = true, dialer = true,
|
||||
messages = true, music = true, settings = true, store = true
|
||||
}
|
||||
|
||||
if builtin_ids[app_id] then
|
||||
-- Use shellNavigateTo for built-in apps
|
||||
return shellNavigateTo(app_id)
|
||||
end
|
||||
|
||||
local apps = mosis.apps.getInstalled()
|
||||
for _, app in ipairs(apps) do
|
||||
if app.package_id == package_id then
|
||||
print("[Shell] Launching discovered app: " .. package_id)
|
||||
-- Try to find in installed apps
|
||||
if mosis and mosis.apps then
|
||||
local apps = mosis.apps.getInstalled()
|
||||
for _, app in ipairs(apps) do
|
||||
if app.package_id == package_id then
|
||||
print("[Shell] Launching installed app: " .. package_id)
|
||||
|
||||
-- Push current to history
|
||||
if current_app then
|
||||
table.insert(nav_history, {
|
||||
app_id = current_app,
|
||||
app_path = current_app_path
|
||||
})
|
||||
print("[Shell] Pushed to history: " .. current_app .. " (depth: " .. #nav_history .. ")")
|
||||
-- Push current to history
|
||||
if current_app then
|
||||
table.insert(nav_history, {
|
||||
app_id = current_app,
|
||||
app_path = current_app_path
|
||||
})
|
||||
print("[Shell] Pushed to history: " .. current_app .. " (depth: " .. #nav_history .. ")")
|
||||
end
|
||||
|
||||
-- Build content path - convert entry.rml to entry_content.rml
|
||||
local entry = app.entry_point or "main.rml"
|
||||
local content_entry = entry:gsub("%.rml$", "_content.rml")
|
||||
local content_path = "apps/" .. package_id:gsub("com.mosis.", "") .. "/" .. content_entry
|
||||
|
||||
-- Switch sandbox if available
|
||||
if switchAppSandbox then
|
||||
switchAppSandbox(package_id, app.install_path)
|
||||
end
|
||||
|
||||
return loadAppContent_internal(package_id, content_path)
|
||||
end
|
||||
|
||||
-- Build content path - convert entry.rml to entry_content.rml
|
||||
local entry = app.entry_point or "main.rml"
|
||||
local content_entry = entry:gsub("%.rml$", "_content.rml")
|
||||
local content_path = "apps/" .. package_id:gsub("com.mosis.", "") .. "/" .. content_entry
|
||||
|
||||
-- Switch sandbox if available
|
||||
if switchAppSandbox then
|
||||
switchAppSandbox(package_id, app.install_path)
|
||||
end
|
||||
|
||||
return loadAppContent_internal(package_id, content_path)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <chrono>
|
||||
#include <format>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
|
||||
// Sandbox API includes for RmlUi integration
|
||||
@@ -390,8 +391,8 @@ static int LuaGoHome(lua_State* L)
|
||||
// Switch sandbox context back to home screen
|
||||
SwitchAppSandbox("com.mosis.home", g_data_root);
|
||||
|
||||
// Load home screen
|
||||
const char* home_path = "apps/home/home.rml";
|
||||
// Load shell (which shows home by default)
|
||||
const char* home_path = "apps/shell/shell.rml";
|
||||
|
||||
// Unload current document
|
||||
if (g_document)
|
||||
@@ -525,6 +526,57 @@ static int LuaSwitchAppSandbox(lua_State* L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Load app content fragment into a container element
|
||||
static int LuaLoadAppContent(lua_State* L)
|
||||
{
|
||||
// Get element from first argument
|
||||
Rml::Element* element = Rml::Lua::LuaType<Rml::Element>::check(L, 1);
|
||||
if (!element) {
|
||||
Logger::Log("loadAppContent: Invalid element argument");
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get path from second argument
|
||||
const char* path = luaL_checkstring(L, 2);
|
||||
Logger::Log(std::format("loadAppContent: Loading {} into element", path));
|
||||
|
||||
// Read file content - try assets first, then filesystem
|
||||
std::string content;
|
||||
AAssetManager* am = AssetsManager::Native();
|
||||
AAsset* asset = AAssetManager_open(am, path, AASSET_MODE_BUFFER);
|
||||
|
||||
if (asset) {
|
||||
// Load from assets
|
||||
size_t length = AAsset_getLength(asset);
|
||||
const char* data = static_cast<const char*>(AAsset_getBuffer(asset));
|
||||
content = std::string(data, length);
|
||||
AAsset_close(asset);
|
||||
Logger::Log(std::format(" -> Loaded {} bytes from assets", length));
|
||||
} else {
|
||||
// Try filesystem (for installed apps)
|
||||
std::string fs_path = GetFilesDir() + "/" + path;
|
||||
std::ifstream file(fs_path);
|
||||
if (file.is_open()) {
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
content = buffer.str();
|
||||
Logger::Log(std::format(" -> Loaded {} bytes from filesystem", content.size()));
|
||||
} else {
|
||||
Logger::Log(std::format("loadAppContent: Cannot open file: {}", path));
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Set inner RML
|
||||
element->SetInnerRML(content);
|
||||
Logger::Log("loadAppContent: Content loaded successfully");
|
||||
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Register Lua functions for navigation
|
||||
static void RegisterLuaFunctions(const std::string& current_app_id, bool is_system_app)
|
||||
{
|
||||
@@ -535,7 +587,9 @@ static void RegisterLuaFunctions(const std::string& current_app_id, bool is_syst
|
||||
lua_setglobal(L, "goHome");
|
||||
lua_pushcfunction(L, LuaSwitchAppSandbox);
|
||||
lua_setglobal(L, "switchAppSandbox");
|
||||
Logger::Log("Registered Lua loadScreen, goHome, and switchAppSandbox functions");
|
||||
lua_pushcfunction(L, LuaLoadAppContent);
|
||||
lua_setglobal(L, "loadAppContent");
|
||||
Logger::Log("Registered Lua loadScreen, goHome, switchAppSandbox, and loadAppContent functions");
|
||||
|
||||
// Register app management APIs
|
||||
if (g_app_manager && g_update_service) {
|
||||
@@ -633,11 +687,11 @@ void Kernel::main_loop()
|
||||
Rml::LoadFontFace("fonts/Roboto/Roboto-VariableFont_wdth,wght.ttf");
|
||||
Rml::LoadFontFace("fonts/Roboto/Roboto-Italic-VariableFont_wdth,wght.ttf");
|
||||
|
||||
// Load home screen document
|
||||
g_document = g_context->LoadDocument("apps/home/home.rml");
|
||||
// Load shell document (provides persistent status bar, nav bar, and loads home content)
|
||||
g_document = g_context->LoadDocument("apps/shell/shell.rml");
|
||||
if (!g_document)
|
||||
{
|
||||
Logger::Log("Failed to load home.rml document");
|
||||
Logger::Log("Failed to load shell.rml document");
|
||||
Rml::Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user