diff --git a/.changelog/lang_ar.json b/.changelog/lang_ar.json index 472e5fe8..d2475615 100644 --- a/.changelog/lang_ar.json +++ b/.changelog/lang_ar.json @@ -129,7 +129,7 @@ "improvement": [ "تحسين حجم ملف APK في قالب التطبيق المعبأ", "التطبيق (والتطبيقات المعبأة) الآن يدعم المزيد من الأذونات _[`issue #338`](http://issues.autojs6.com/338)_", - "تمت إضافة خيار لمكتبة Pinyin في صفحة التعبئة", + "صفحة اعدادات حزم التطبيق تدعم الآن خيارات مكتبة Pinyin", "تحسين خلفية شريط الحالة ولون النص في الصفحة الرئيسية للتطبيقات المعبأة", "إضافة مفاتيح لتبديل الأذونات الخاصة (الوصول إلى جميع الملفات وإرسال الإشعارات) في صفحة إعدادات التطبيقات المعبأة _[`issue #354`](http://issues.autojs6.com/354)_", "التكيف التلقائي لألوان نصوص وأيقونات عناصر التحكم بناءً على سطوع لون الموضوع", @@ -181,7 +181,7 @@ "مشكلة فقدان الطرق والخصائص في مثيلات UiObjectCollection" ], "improvement": [ - "تدعم صفحة التغليف إعداد التوقيعات وإدارة مستودعات المفاتيح وإعداد الأذونات (بواسطة [luckyloogn]()) _[`pr #286`]()_", + "صفحة اعدادات حزم التطبيق تدعم الآن اعدادات التوقيع، وادارة keystore، واعدادات الاذونات (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", "تم تحسين دقة التعرف على اسم الحزمة الحالية واسم النشاط الحالي في النوافذ العائمة (الأولوية: Shizuku > Root > A11Y)", "تم تحسين دقة التعرف على currentPackage و currentActivity (الأولوية: Shizuku > Root > A11Y)", "استعادة إمكانية اختيار محتوى النص لكل عنصر في نافذة النشاط الخاصة بالسجلات بالنقر المزدوج أو الضغط المطول _[`issue #280`](http://issues.autojs6.com/280)_", @@ -264,7 +264,7 @@ "عدم القدرة على استخدام وحدة opencc مع التطبيقات المعبأة بشكل صحيح" ], "improvement": [ - "تحسين تجربة النقر على عنصر تحكم ABI غير متاح في صفحة التعبئة", + "تم تحسين تجربة تلميحات النقر لعنصر \"ABI غير المتاح\" في صفحة اعدادات حزم التطبيق", "دعم التحكم في تشغيل عرض مواقع المؤشر باستخدام Shizuku", "دعم التحكم في تشغيل \"إبراز وسائل الإعلام\" و\"تعديل إعدادات الأمان\" باستخدام Shizuku", "تدعم طرائق automator.gestureAsync/gesturesAsync معلمات دالة الاستدعاء", @@ -324,12 +324,12 @@ "feature": [ "إضافة وحدة opencc (مرجع إلى وثائق المشروع > [تحويل النصوص الصينية](https://docs.autojs6.com/#/opencc)) (مرجع إلى [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R268))", "إضافة طريقتي [plus](https://docs.autojs6.com/#/uiObjectType?id=m-plus) و [append](https://docs.autojs6.com/#/uiObjectType?id=m-append) إلى UiSelector - _[`issue #115`](http://issues.autojs6.com/115)_", - "إضافة دعم تصفية ABI والمكتبات في صفحة تغليف التطبيق (مرجع إلى [AutoX](https://github.com/kkevsekk1/AutoX)) - _[`issue #189`](http://issues.autojs6.com/189)_" + "صفحة اعدادات حزم التطبيق تدعم الآن تصفية ABI والمكتبات (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" ], "fix": [ "إصلاح مشكلة الحجم الكبير غير العادي للتطبيقات المغلفة (مرجع إلى [AutoX](https://github.com/kkevsekk1/AutoX) و [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-d932ac49867d4610f8eeb21b59306e8e923d016cbca192b254caebd829198856R61)) - _[`issue #176`](http://issues.autojs6.com/176)_", "إصلاح مشكلة عرض وطباعة بعض رسائل الخطأ في التطبيقات المغلفة", - "إصلاح مشكلة عرض أيقونة فارغة عند اختيار أيقونة التطبيق في صفحة التغليف", + "تم اصلاح مشكلة قد تؤدي الى ظهور ايقونة فارغة بعد اختيار ايقونة التطبيق في صفحة اعدادات حزم التطبيق", "إصلاح خطأ تهيئة السياق الغير مهيأ عند تضمين مكتبة MLKit Google OCR في التطبيقات المغلفة", "إصلاح عدم فعالية طرق ocr.recognizeText/detect", "إصلاح عدم تطابق لغة النصوص المعروضة مع لغة الإعدادات في بعض النصوص (مثل صفحة السجلات)", @@ -353,9 +353,9 @@ "improvement": [ "يتكيف لوح الوظائف السريع في وحدة محرر الأكواد مع الوضع الليلي.", "تتكيف صفحة البدء لتطبيق الحزمة مع الوضع الليلي ويتم تعديل تخطيط أيقونات التطبيق.", - "تدعم صفحة التطبيق المغلفة التنقل بالمؤشر باستخدام مفتاح ENTER على لوحة المفاتيح البرمجية.", - "تدعم صفحة التطبيق المغلفة تغيير حالة التحديد الكامل عند النقر فوق عناوين ABI والمكتبة.", - "تم جعل التحديد الافتراضي لـ ABI ذكيًا في صفحة التطبيق المغلفة مع إضافة مطالبات إرشادية للعناصر غير القابلة للتحديد.", + "صفحة اعدادات حزم التطبيق تدعم الآن استخدام مفتاح ENTER في لوحة المفاتيح البرمجية لنقل موضع المؤشر", + "صفحة اعدادات حزم التطبيق تدعم الآن النقر على عناوين ABI وعناوين المكتبات للتبديل بين حالة تحديد الكل", + "صفحة اعدادات حزم التطبيق تستخدم الآن اختيارا افتراضيا اكثر ذكاء لـ ABI وتضيف تلميحات ارشادية للعناصر غير القابلة للتحديد", "يقوم مدير الملفات بتعديل عرض عناصر القائمة بناءً على النوع وخصائص الملفات والمجلدات.", "يضيف قائمة النقر بزر الماوس الأيمن للمدير الملفات خيار تغليف التطبيقات.", "عند تمكين خدمات الوصول ولكنها تعمل بشكل غير صحيح، يتم عكس حالة الشذوذ في مفتاح التبديل في الصفحة الرئيسية لـ AutoJs6.", diff --git a/.changelog/lang_en.json b/.changelog/lang_en.json index 8b0fbb23..88be4f39 100644 --- a/.changelog/lang_en.json +++ b/.changelog/lang_en.json @@ -70,7 +70,7 @@ "Settings-page dialogs now offer a \"Use default value\" menu option", "Floating Action Button in File Manager auto-hides when tapping elsewhere", "Code formatter now supports operators such as `??`, `?.`, `??=`", - "Code editor supports reading and writing files encoded in GB18030 / UTF-16 (LE/BE) / Shift_JIS, etc.", + "Code editor supports reading and writing files encoded in GB18030 / UTF-16 (LE/BE) / Shift_JIS, etc", "Code editor supports displaying detailed file information (path/encoding/line break format/total bytes and characters, etc.) _[`issue #395`](http://issues.autojs6.com/395)_", "Added operation-error prompts for intent actions (edit / view / install / send / play, etc.)", "webview element's url attribute supports relative paths", @@ -101,7 +101,7 @@ "v6.6.2": { "released_date": "2025/04/16", "feature": [ - "Methods such as ui.statusBarAppearanceLight, statusBarAppearanceLightBy, navigationBarColor, etc.", + "Methods such as ui.statusBarAppearanceLight, statusBarAppearanceLightBy, navigationBarColor, etc", "ui.statusBarHeight attribute (getter) for obtaining the status bar height _[`issue #357`](http://issues.autojs6.com/357)_", "images.flip method for image flipping _[`issue #349`](http://issues.autojs6.com/349)_", "Added \"file extension\" option in the settings page", @@ -129,7 +129,7 @@ "improvement": [ "Streamlined the APK file size for the packaged application template", "Enhanced app (and packaged apps) support for more permissions _[`issue #338`](http://issues.autojs6.com/338)_", - "Added support for the Pinyin library option on the packaging page", + "Packaging app configuration page now supports Pinyin library options", "Optimized the status bar background and text color on the main activity page of packaged apps", "Added special permission toggles (such as access all files and send notifications) to the packaged app settings page _[`issue #354`](http://issues.autojs6.com/354)_", "Automatically switched control text and icon colors based on the brightness of the theme color", @@ -181,7 +181,7 @@ "Missing methods and properties on UiObjectCollection instances" ], "improvement": [ - "The packaging page supports signature configuration, keystore management, and permission settings (by [luckyloogn]()) _[`pr #286`]()_", + "Packaging app configuration page now supports signing configuration, keystore management, and permission settings (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", "Improved accuracy in identifying the current package name and activity name of the floating window (Priority: Shizuku > Root > A11Y)", "Improved accuracy in recognizing `currentPackage` and `currentActivity` (Priority: Shizuku > Root > A11Y)", "Restore the ability to select text content of individual entries in the log activity window via double-click or long press _[`issue #280`](http://issues.autojs6.com/280)_", @@ -202,7 +202,7 @@ "released_date": "2024/12/02", "released_hint": "Built-in module rewrite, upgrade cautiously", "hint": [ - "The built-in modules are rewritten in Kotlin to enhance script execution efficiency, but iterative improvements are needed.", + "The built-in modules are rewritten in Kotlin to enhance script execution efficiency, but iterative improvements are needed", "The built-in init.js file is empty by default, allowing developers to extend built-in modules or mount external modules." ], "feature": [ @@ -264,7 +264,7 @@ "Issue with packaged app unable to use opencc module properly" ], "improvement": [ - "Click prompt experience for 'Unavailable ABI' control on package page", + "Improved tap hint experience for the \"Unavailable ABI\" control on the packaging app configuration page", "Supports using Shizuku to control 'Pointer Location' display switch", "Supports using Shizuku to control 'Projection Media' and 'Modify Secure Settings' permission switches", "Automator.gestureAsync/gesturesAsync supports callback function parameters", @@ -324,12 +324,12 @@ "feature": [ "opencc module (Refer to project documentation > [Chinese Conversion](https://docs.autojs6.com/#/opencc)) (Ref to [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R268))", "UiSelector adds [plus](https://docs.autojs6.com/#/uiObjectType?id=m-plus) and [append](https://docs.autojs6.com/#/uiObjectType?id=m-append) methods _[`issue #115`](http://issues.autojs6.com/115)_", - "Packaging application page adds support for filtering ABIs and libraries (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" + "Packaging app configuration page now supports filtering for ABI and libraries (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" ], "fix": [ "Abnormally large file size issue in packaged applications (Ref to [AutoX](https://github.com/kkevsekk1/AutoX) / [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-d932ac49867d4610f8eeb21b59306e8e923d016cbca192b254caebd829198856R61)) _[`issue #176`](http://issues.autojs6.com/176)_", "Issue where packaged applications cannot display and print some exception messages", - "Issue where selecting application icon on packaging application page might show empty icon", + "Fixed an issue where a blank app icon could appear after selecting an app icon on the packaging app configuration page", "Context not initialized exception when packaging application includes MLKit Google OCR library", "ocr.recognizeText/detect methods not working", "Mismatch between displayed language and application setting language for some texts (such as log page)", @@ -351,14 +351,14 @@ "Issue where module function quick panel button function name might overflow in code editor" ], "improvement": [ - "The code editor module's quick function panel adapts to night mode.", - "The startup page of the packaged application is adapted to night mode, and the layout of application icons is adjusted.", - "The packaged application page supports cursor navigation using the ENTER key on the software keyboard.", - "The packaged application page supports toggling select-all state by clicking on ABI and library titles.", - "The default ABI selection is made intelligent on the packaged application page with added guide prompts for unselectable items.", - "The file manager adjusts the display of menu items based on the type and characteristics of files and folders.", - "The file manager's folder right-click menu adds a packaging application option.", - "When accessibility services are enabled but malfunction, an abnormal state is reflected in the drawer switch of the AutoJs6 homepage.", + "The code editor module's quick function panel adapts to night mode", + "The startup page of the packaged application is adapted to night mode, and the layout of application icons is adjusted", + "Packaging app configuration page now supports using the soft keyboard ENTER key to move the cursor focus", + "Packaging app configuration page now supports tapping ABI headings and library headings to toggle select-all state", + "Packaging app configuration page now uses smarter default ABI selection and adds guidance hints for unavailable options", + "The file manager adjusts the display of menu items based on the type and characteristics of files and folders", + "The file manager's folder right-click menu adds a packaging application option", + "When accessibility services are enabled but malfunction, an abnormal state is reflected in the drawer switch of the AutoJs6 homepage", "The console includes detailed stack information when printing error messages." ], "dependency": [ @@ -671,7 +671,7 @@ "released_date": "2023/01/21", "feature": [ "Redesign and rewrite of project documentation (partially completed)", - "Multi-language adaptation for Western/France/Russian/Arabic/Japanese/Korean/English/Traditional Chinese, etc.", + "Multi-language adaptation for Western/France/Russian/Arabic/Japanese/Korean/English/Traditional Chinese, etc", "Added path selection/history/default value intelligent suggestion functions to the work path setting options", "File manager supports jumping to the parent directory of any directory (up to \"Internal Storage\")", "File manager supports setting any directory as the work path shortcut", diff --git a/.changelog/lang_es.json b/.changelog/lang_es.json index 774160e9..ea08a3a7 100644 --- a/.changelog/lang_es.json +++ b/.changelog/lang_es.json @@ -70,7 +70,7 @@ "Las páginas de ajustes ofrecen la opción \"Usar valor predeterminado\" en los diálogos", "El botón flotante del administrador de archivos se oculta automáticamente al pulsar fuera", "El formateador de código admite operadores `??`, `?.`, `??=`", - "El editor de código admite la lectura y escritura de archivos con codificaciones GB18030 / UTF-16 (LE/BE) / Shift_JIS, etc.", + "El editor de código admite la lectura y escritura de archivos con codificaciones GB18030 / UTF-16 (LE/BE) / Shift_JIS, etc", "El editor de código ahora muestra información detallada del archivo (ruta/codificación/salto de línea/total de bytes y caracteres, etc.) _[`issue #395`](http://issues.autojs6.com/395)_", "Se añaden mensajes de error para acciones de intent (editar / ver / instalar / enviar / reproducir, etc.)", "El atributo url de webview admite rutas relativas", @@ -101,7 +101,7 @@ "v6.6.2": { "released_date": "2025/04/16", "feature": [ - "Métodos como ui.statusBarAppearanceLight, statusBarAppearanceLightBy y navigationBarColor, etc.", + "Métodos como ui.statusBarAppearanceLight, statusBarAppearanceLightBy y navigationBarColor, etc", "Atributo ui.statusBarHeight (getter), utilizado para obtener la altura de la barra de estado _[`issue #357`](http://issues.autojs6.com/357)_", "Método images.flip para voltear imágenes _[`issue #349`](http://issues.autojs6.com/349)_", "Se añadió la opción 'extensión de archivo' en la página de configuración", @@ -129,7 +129,7 @@ "improvement": [ "Optimización del tamaño del archivo APK en la plantilla de aplicaciones empaquetadas", "La aplicación (y las aplicaciones empaquetadas) ahora soportan más permisos _[`issue #338`](http://issues.autojs6.com/338)_", - "La página de empaquetado añade la opción para la biblioteca Pinyin", + "La pagina de configuracion de empaquetado ahora admite opciones de biblioteca Pinyin", "Optimización del fondo de la barra de estado y del color del texto en la página principal de la aplicación empaquetada", "La página de configuración de la aplicación empaquetada añade interruptores para permisos especiales (acceso a todos los archivos y envío de notificaciones) _[`issue #354`](http://issues.autojs6.com/354)_", "Los textos e iconos de los controles cambian automáticamente a un color adecuado en función de la luminosidad del tema", @@ -181,7 +181,7 @@ "Problema donde las instancias de UiObjectCollection carecían de métodos y propiedades propios" ], "improvement": [ - "La página de empaquetado admite configuración de firma, gestión de almacenes de claves y configuración de permisos (por [luckyloogn]()) _[`pr #286`]()_", + "La pagina de configuracion de empaquetado ahora admite configuracion de firma, gestion de keystore y ajustes de permisos (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", "Mejorada la precisión en la identificación del nombre del paquete y de la actividad actual de la ventana flotante (Prioridad: Shizuku > Root > A11Y)", "Mejorada la precisión en la identificación de currentPackage y currentActivity (Prioridad: Shizuku > Root > A11Y)", "Restaurar la capacidad de seleccionar el contenido del texto de entradas individuales en la ventana de actividad del registro mediante doble clic o pulsación larga _[`issue #280`](http://issues.autojs6.com/280)_", @@ -202,7 +202,7 @@ "released_date": "2024/12/02", "released_hint": "Reescritura de módulos integrados, actualización con precaución", "hint": [ - "Los módulos integrados se reescriben en Kotlin para mejorar la eficiencia de ejecución del script, pero se necesitan mejoras iterativas.", + "Los módulos integrados se reescriben en Kotlin para mejorar la eficiencia de ejecución del script, pero se necesitan mejoras iterativas", "El archivo init.js integrado está vacío por defecto, lo que permite a los desarrolladores ampliar los módulos integrados o montar módulos externos." ], "feature": [ @@ -264,7 +264,7 @@ "Problema con la aplicación empaquetada que no puede utilizar adecuadamente el módulo opencc" ], "improvement": [ - "Experiencia de aviso de clic para el control 'ABI no disponible' en la página de paquete", + "Se mejoro la experiencia del aviso al tocar el control \"ABI no disponible\" en la pagina de configuracion de empaquetado", "Admite el uso de Shizuku para controlar el interruptor de visualización 'Ubicación del puntero'", "Admite el uso de Shizuku para controlar los interruptores de permisos 'Medios de proyección' y 'Modificar configuraciones seguras'", "Automator.gestureAsync/gesturesAsync admite parámetros de función de devolución de llamada", @@ -324,12 +324,12 @@ "feature": [ "Módulo opencc (Consulte Documentación del proyecto > [Conversión China](https://docs.autojs6.com/#/opencc)) (Ref a [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R268))", "Métodos [plus](https://docs.autojs6.com/#/uiObjectType?id=m-plus) y [append](https://docs.autojs6.com/#/uiObjectType?id=m-append) agregados a UiSelector _[`issue #115`](http://issues.autojs6.com/115)_", - "Página de empaquetado de aplicaciones añade soporte para filtrado de ABI y bibliotecas (Ref a [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" + "La pagina de configuracion de empaquetado ahora admite filtrado de ABI y bibliotecas (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" ], "fix": [ "Problema de tamaño anormalmente grande del archivo empaquetado (Ref a [AutoX](https://github.com/kkevsekk1/AutoX) / [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-d932ac49867d4610f8eeb21b59306e8e923d016cbca192b254caebd829198856R61)) _[`issue #176`](http://issues.autojs6.com/176)_", "Problema en el que el paquete de la aplicación no muestra o imprime ciertos mensajes de error", - "Problema de ícono vacío después de seleccionar el ícono de la aplicación en la página de empaquetado", + "Se corrigio un problema por el que podia mostrarse un icono vacio tras seleccionar el icono de la app en la pagina de configuracion de empaquetado", "Problema de excepción de contexto no inicializado al incluir la biblioteca OCR de Google MLKit en el paquete", "Problema de métodos inoperativos ocr.recognizeText/detect", "Problema en el que algunos textos (como la página de registros) no coinciden con el idioma de configuración de la aplicación", @@ -351,14 +351,14 @@ "Problema de nombres de funciones de botón de panel de funciones rápidas que se desbordan en el editor de código" ], "improvement": [ - "El panel rápido de funciones del módulo del editor de código se adapta al modo nocturno.", - "La página de inicio de la aplicación empaquetada se adapta al modo nocturno y se ajusta el diseño de los iconos de la aplicación.", - "La página de la aplicación empaquetada admite la navegación del cursor utilizando la tecla ENTER en el teclado de software.", - "La página de la aplicación empaquetada admite alternar el estado de selección total al hacer clic en los títulos de ABI y librerías.", - "La selección predeterminada de ABI se realiza de manera inteligente en la página de la aplicación empaquetada con mensajes guía para elementos no seleccionables.", - "El administrador de archivos ajusta la visualización de los elementos del menú según el tipo y las características de los archivos y carpetas.", - "El menú de clic derecho en carpetas del administrador de archivos añade una opción para empaquetar aplicaciones.", - "Cuando los servicios de accesibilidad están habilitados pero funcionan incorrectamente, se refleja un estado de anomalía en el interruptor del cajón de la página de inicio de AutoJs6.", + "El panel rápido de funciones del módulo del editor de código se adapta al modo nocturno", + "La página de inicio de la aplicación empaquetada se adapta al modo nocturno y se ajusta el diseño de los iconos de la aplicación", + "La pagina de configuracion de empaquetado ahora admite usar la tecla ENTER del teclado virtual para mover el foco del cursor", + "La pagina de configuracion de empaquetado ahora admite tocar los titulos de ABI y de bibliotecas para alternar el estado de seleccionar todo", + "La pagina de configuracion de empaquetado ahora usa una seleccion predeterminada de ABI mas inteligente y agrega avisos para opciones no disponibles", + "El administrador de archivos ajusta la visualización de los elementos del menú según el tipo y las características de los archivos y carpetas", + "El menú de clic derecho en carpetas del administrador de archivos añade una opción para empaquetar aplicaciones", + "Cuando los servicios de accesibilidad están habilitados pero funcionan incorrectamente, se refleja un estado de anomalía en el interruptor del cajón de la página de inicio de AutoJs6", "La consola incluye información detallada de la pila al imprimir mensajes de error." ], "dependency": [ @@ -671,7 +671,7 @@ "released_date": "2023/01/21", "feature": [ "Rediseño y reescritura de la documentación del proyecto (parcialmente completado)", - "Adaptación multilingüe para español/francés/ruso/árabe/japonés/coreano/inglés/chino tradicional, etc.", + "Adaptación multilingüe para español/francés/ruso/árabe/japonés/coreano/inglés/chino tradicional, etc", "Opciones de configuración de la ruta de trabajo con selección de ruta/historial de rutas/sugerencias inteligentes de valores predeterminados", "El administrador de archivos soporta la navegación al directorio superior (hasta el directorio 'Almacenamiento interno')", "El administrador de archivos permite establecer cualquier directorio como ruta de trabajo rápidamente", @@ -724,49 +724,49 @@ "Problema donde la información del canal Alpha se perdía en colores con canal Alpha de 0 en el método colors.toString" ], "improvement": [ - "Redireccionar clases públicas de Auto.js 4.x para lograr la máxima compatibilidad descendente posible (limitada).", - "Fusionar todos los módulos del proyecto para evitar posibles problemas de referencia circular (eliminar temporalmente el módulo inrt).", - "Migrar la configuración de construcción de Gradle de Groovy a KTS.", - "Agregar soporte multilingüe para mensajes de excepción de Rhino.", - "El interruptor de permisos del cajón de la página principal solo muestra mensajes cuando está activado.", - "La disposición del cajón de la página principal se adhiere directamente debajo de la barra de estado para evitar incompatibilidades de la barra de color en la parte superior.", - "Compatibilidad de funciones de comprobación de actualizaciones, descarga y aviso de actualización con el sistema Android 7.x.", - "Rediseñar la página de configuración (migración a AndroidX).", - "La página de configuración admite la presión prolongada sobre las opciones de configuración para obtener información detallada.", - "Adición de la opción \"Seguir sistema\" para el modo nocturno (Android 9+).", - "Compatibilidad de la pantalla de inicio de la aplicación con el modo nocturno.", - "Agregar identificadores numéricos a los iconos de la aplicación para mejorar la experiencia del usuario con múltiples versiones de código abierto coexistentes.", - "Agregar más opciones de colores Material Design al tema de la aplicación.", - "Aligerar y adaptar los iconos de elementos de lista en el gestor de archivos/panel de tareas al color del tema.", - "Compatibilidad del color del texto de sugerencia en la caja de búsqueda de la página principal con el modo nocturno.", - "Compatibilidad de componentes como diálogos/textos/Fab/AppBar/elementos de lista con el modo nocturno.", - "Compatibilidad de páginas como documentos/configuración/sobre/colores del tema/análisis de diseño y menús de botones flotantes con el modo nocturno.", - "Compatibilidad del diseño de páginas con la disposición RTL (Right-To-Left) en la medida de lo posible.", - "Agregar efectos de animación de iconos a la página sobre.", - "Actualización automática del año en el texto de la declaración de derechos de autor en la página sobre.", - "Después de la instalación inicial de la aplicación, determinar y establecer automáticamente un directorio de trabajo adecuado.", - "Desactivar la función de zoom a dos dedos en la página de documentos para evitar la visualización anormal del contenido.", - "Simplificar el nombre y la ruta de las tareas mostradas en los elementos de la lista del panel de tareas por ruta relativa.", - "Abreviar el texto de los botones del editor de texto para evitar desbordamiento del contenido.", - "Soporte para restaurar el tamaño de fuente predeterminado en la configuración del editor de textos.", - "Mejorar la velocidad de respuesta al hacer clic en el botón flotante.", - "Hacer clic en el botón de análisis de diseño del botón flotante realiza directamente el análisis de rango de diseño.", - "El tema de análisis de diseño es adaptable (la ventana flotante sigue el tema de la aplicación, el panel de configuración rápida sigue el tema del sistema).", - "Reordenar la lista de información de control de diseño según la posible frecuencia de uso.", - "Optimizar el formato de salida automáticamente al hacer clic y copiar sobre información de control de diseño según el tipo de selector.", - "Al seleccionar archivos usando la ventana flotante, presionar la tecla de retorno lleva al directorio superior en lugar de cerrar directamente la ventana.", - "Soporte para detección de validez numérica y conversión automática de símbolos punteados mientras se ingresa una dirección en modo cliente conectándose a la computadora.", - "Mostrar la dirección IP del dispositivo correspondiente en el cajón de la página principal después de que el cliente y servidor se conecten.", - "Agregar protección contra sobrescritura a ciertos objetos globales y módulos integrados (consultar documentos del proyecto > Objetos globales > [Protección contra sobrescritura](https://docs.autojs6.com/#/global?id=%e8%a6%86%e5%86%99%e4%bf%9d%e6%8a%a4)).", - "importClass e importPackage admiten parámetros de cadena y parámetros de longitud variable.", - "ui.run admite la impresión de información de seguimiento de pila en caso de excepción.", - "ui.R y auto.R pueden obtener cómodamente el ID de recursos de AutoJs6.", - "Los métodos relacionados con el uso de aplicaciones en el módulo app admiten parámetros de tipo App y parámetros de alias de aplicación.", - "Los métodos relacionados con la devolución de llamada asincrónica en el módulo dialogs admiten la omisión de parámetros pre-rellenos.", - "app.startActivity y otros admiten parámetros de opción de URL (ver código de ejemplo > Aplicaciones > Intención).", - "El módulo device devuelve null en lugar de lanzar una excepción cuando la obtención de IMEI o número de serie de hardware falla.", - "Aumentar el brillo del texto en el log de ventana flotante que muestra console.show para mejorar la legibilidad del contenido.", - "ImageWrapper#saveTo admite guardar archivos de imagen en rutas relativas.", + "Redireccionar clases públicas de Auto.js 4.x para lograr la máxima compatibilidad descendente posible (limitada)", + "Fusionar todos los módulos del proyecto para evitar posibles problemas de referencia circular (eliminar temporalmente el módulo inrt)", + "Migrar la configuración de construcción de Gradle de Groovy a KTS", + "Agregar soporte multilingüe para mensajes de excepción de Rhino", + "El interruptor de permisos del cajón de la página principal solo muestra mensajes cuando está activado", + "La disposición del cajón de la página principal se adhiere directamente debajo de la barra de estado para evitar incompatibilidades de la barra de color en la parte superior", + "Compatibilidad de funciones de comprobación de actualizaciones, descarga y aviso de actualización con el sistema Android 7.x", + "Rediseñar la página de configuración (migración a AndroidX)", + "La página de configuración admite la presión prolongada sobre las opciones de configuración para obtener información detallada", + "Adición de la opción \"Seguir sistema\" para el modo nocturno (Android 9+)", + "Compatibilidad de la pantalla de inicio de la aplicación con el modo nocturno", + "Agregar identificadores numéricos a los iconos de la aplicación para mejorar la experiencia del usuario con múltiples versiones de código abierto coexistentes", + "Agregar más opciones de colores Material Design al tema de la aplicación", + "Aligerar y adaptar los iconos de elementos de lista en el gestor de archivos/panel de tareas al color del tema", + "Compatibilidad del color del texto de sugerencia en la caja de búsqueda de la página principal con el modo nocturno", + "Compatibilidad de componentes como diálogos/textos/Fab/AppBar/elementos de lista con el modo nocturno", + "Compatibilidad de páginas como documentos/configuración/sobre/colores del tema/análisis de diseño y menús de botones flotantes con el modo nocturno", + "Compatibilidad del diseño de páginas con la disposición RTL (Right-To-Left) en la medida de lo posible", + "Agregar efectos de animación de iconos a la página sobre", + "Actualización automática del año en el texto de la declaración de derechos de autor en la página sobre", + "Después de la instalación inicial de la aplicación, determinar y establecer automáticamente un directorio de trabajo adecuado", + "Desactivar la función de zoom a dos dedos en la página de documentos para evitar la visualización anormal del contenido", + "Simplificar el nombre y la ruta de las tareas mostradas en los elementos de la lista del panel de tareas por ruta relativa", + "Abreviar el texto de los botones del editor de texto para evitar desbordamiento del contenido", + "Soporte para restaurar el tamaño de fuente predeterminado en la configuración del editor de textos", + "Mejorar la velocidad de respuesta al hacer clic en el botón flotante", + "Hacer clic en el botón de análisis de diseño del botón flotante realiza directamente el análisis de rango de diseño", + "El tema de análisis de diseño es adaptable (la ventana flotante sigue el tema de la aplicación, el panel de configuración rápida sigue el tema del sistema)", + "Reordenar la lista de información de control de diseño según la posible frecuencia de uso", + "Optimizar el formato de salida automáticamente al hacer clic y copiar sobre información de control de diseño según el tipo de selector", + "Al seleccionar archivos usando la ventana flotante, presionar la tecla de retorno lleva al directorio superior en lugar de cerrar directamente la ventana", + "Soporte para detección de validez numérica y conversión automática de símbolos punteados mientras se ingresa una dirección en modo cliente conectándose a la computadora", + "Mostrar la dirección IP del dispositivo correspondiente en el cajón de la página principal después de que el cliente y servidor se conecten", + "Agregar protección contra sobrescritura a ciertos objetos globales y módulos integrados (consultar documentos del proyecto > Objetos globales > [Protección contra sobrescritura](https://docs.autojs6.com/#/global?id=%e8%a6%86%e5%86%99%e4%bf%9d%e6%8a%a4))", + "importClass e importPackage admiten parámetros de cadena y parámetros de longitud variable", + "ui.run admite la impresión de información de seguimiento de pila en caso de excepción", + "ui.R y auto.R pueden obtener cómodamente el ID de recursos de AutoJs6", + "Los métodos relacionados con el uso de aplicaciones en el módulo app admiten parámetros de tipo App y parámetros de alias de aplicación", + "Los métodos relacionados con la devolución de llamada asincrónica en el módulo dialogs admiten la omisión de parámetros pre-rellenos", + "app.startActivity y otros admiten parámetros de opción de URL (ver código de ejemplo > Aplicaciones > Intención)", + "El módulo device devuelve null en lugar de lanzar una excepción cuando la obtención de IMEI o número de serie de hardware falla", + "Aumentar el brillo del texto en el log de ventana flotante que muestra console.show para mejorar la legibilidad del contenido", + "ImageWrapper#saveTo admite guardar archivos de imagen en rutas relativas", "Rediseñar el objeto global colors e incluir el soporte de modos de color HSV / HSL (consultar documentos del proyecto > [Colores](https://docs.autojs6.com/#/color))." ], "dependency": [ diff --git a/.changelog/lang_fr.json b/.changelog/lang_fr.json index f690d06f..4b73343b 100644 --- a/.changelog/lang_fr.json +++ b/.changelog/lang_fr.json @@ -70,7 +70,7 @@ "Les boîtes de dialogue de la page Paramètres proposent l'option « Utiliser la valeur par défaut »", "Le bouton flottant du gestionnaire de fichiers se masque automatiquement lorsqu'on touche en dehors", "Le formateur de code prend désormais en charge les opérateurs `??`, `?.`, `??=`", - "L'éditeur de code prend en charge la lecture et l'écriture de fichiers aux encodages GB18030 / UTF-16 (LE/BE) / Shift_JIS, etc.", + "L'éditeur de code prend en charge la lecture et l'écriture de fichiers aux encodages GB18030 / UTF-16 (LE/BE) / Shift_JIS, etc", "L'éditeur de code prend en charge l'affichage des informations détaillées du fichier (chemin/encodage/retour à la ligne/nombre total d'octets et de caractères, etc.) _[`issue #395`](http://issues.autojs6.com/395)_", "Ajout de messages d'erreur pour les actions d'intent (éditer / voir / installer / envoyer / lire, etc.)", "L'attribut url de webview prend en charge les chemins relatifs", @@ -101,7 +101,7 @@ "v6.6.2": { "released_date": "2025/04/16", "feature": [ - "Méthodes telles que ui.statusBarAppearanceLight, statusBarAppearanceLightBy et navigationBarColor, etc.", + "Méthodes telles que ui.statusBarAppearanceLight, statusBarAppearanceLightBy et navigationBarColor, etc", "Attribut ui.statusBarHeight (getter) servant à obtenir la hauteur de la barre d'état _[`issue #357`](http://issues.autojs6.com/357)_", "Méthode images.flip pour retourner une image _[`issue #349`](http://issues.autojs6.com/349)_", "Ajout de l'option « extension de fichier » dans la page des paramètres", @@ -129,7 +129,7 @@ "improvement": [ "Optimisation de la taille du fichier APK pour le modèle d'application packagée", "L'application (et les applications packagées) prend désormais en charge davantage de permissions _[`issue #338`](http://issues.autojs6.com/338)_", - "Ajout de l'option pour la bibliothèque Pinyin dans la page de packaging", + "La page de configuration de packaging prend maintenant en charge les options de bibliothèque Pinyin", "Optimisation du fond de la barre d'état et de la couleur du texte dans la page principale des applications packagées", "Ajout d'interrupteurs pour les permissions spéciales (accès à tous les fichiers et envoi de notifications) dans la page des paramètres des applications packagées _[`issue #354`](http://issues.autojs6.com/354)_", "Les textes et icônes des contrôles s'ajustent automatiquement selon la luminosité du thème", @@ -181,7 +181,7 @@ "Problème d'absence des méthodes et propriétés propres aux instances UiObjectCollection" ], "improvement": [ - "La page de packaging prend en charge la configuration des signatures, la gestion des clés et la configuration des autorisations (par [luckyloogn]()) _[`pr #286`]()_", + "La page de configuration de packaging prend maintenant en charge la configuration de signature, la gestion du keystore et les parametres d'autorisation (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", "Amélioration de la précision de la reconnaissance du nom du package actuel et de l'activité en cours de la fenêtre flottante (Priorité : Shizuku > Root > A11Y)", "Amélioration de la précision de la reconnaissance de currentPackage et currentActivity (Priorité : Shizuku > Root > A11Y)", "Restauration de la possibilité de sélectionner le contenu texte d'une entrée individuelle dans la fenêtre de journal via un double-clic ou un appui long _[`issue #280`](http://issues.autojs6.com/280)_", @@ -202,7 +202,7 @@ "released_date": "2024/12/02", "released_hint": "Réécriture du module intégré, mise à jour avec prudence", "hint": [ - "Les modules intégrés sont réécrits en Kotlin pour améliorer l'efficacité d'exécution des scripts, mais des améliorations itératives sont nécessaires.", + "Les modules intégrés sont réécrits en Kotlin pour améliorer l'efficacité d'exécution des scripts, mais des améliorations itératives sont nécessaires", "Le fichier init.js intégré est vide par défaut, permettant aux développeurs d'étendre les modules intégrés ou de monter des modules externes." ], "feature": [ @@ -264,7 +264,7 @@ "Problème avec l'application empaquetée ne pouvant pas utiliser correctement le module opencc" ], "improvement": [ - "Expérience d'indication de clic pour le contrôle 'ABI non disponible' sur la page de paquet", + "Amelioration de l'experience des indications au toucher pour le controle \"ABI indisponible\" dans la page de configuration de packaging", "Prend en charge l'utilisation de Shizuku pour contrôler l'interrupteur d'affichage 'Localisation du pointeur'", "Prend en charge l'utilisation de Shizuku pour contrôler les interrupteurs de permission 'Médias de projection' et 'Modifier les paramètres sécurisés'", "Automator.gestureAsync/gesturesAsync prend en charge les paramètres de fonction de rappel", @@ -324,12 +324,12 @@ "feature": [ "Module opencc (référez-vous à la documentation du projet > [Conversion en Chinois](https://docs.autojs6.com/#/opencc)) (Réf à [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R268))", "Ajout des méthodes [plus](https://docs.autojs6.com/#/uiObjectType?id=m-plus) et [append](https://docs.autojs6.com/#/uiObjectType?id=m-append) pour UiSelector _[`issue #115`](http://issues.autojs6.com/115)_", - "Support amélioré pour le filtrage des ABI et des bibliothèques sur la page de l'application de packaging (Réf à [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" + "La page de configuration de packaging prend maintenant en charge le filtrage des ABI et des bibliotheques (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" ], "fix": [ "Problème de taille de fichier anormalement volumineux lors du packaging de l'application (Réf à [AutoX](https://github.com/kkevsekk1/AutoX) / [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-d932ac49867d4610f8eeb21b59306e8e923d016cbca192b254caebd829198856R61)) _[`issue #176`](http://issues.autojs6.com/176)_", "Problème d'affichage de certains messages d'exception lors du packaging de l'application", - "Problème potentiel d'icône blanche après la sélection d'une icône d'application sur la page de packaging de l'application", + "Correction d'un probleme ou une icone vide pouvait s'afficher apres la selection de l'icone de l'application dans la page de configuration de packaging", "Problème d'initialisation contextuelle lors de l'intégration de la bibliothèque OCR MLKit Google", "Problème d'inefficacité des méthodes ocr.recognizeText/detect", "Problème de langage d'affichage incohérent avec le paramètre de l'application dans certains textes (comme la page des logs)", @@ -351,14 +351,14 @@ "Problème de débordement de noms de fonctions sur le panneau de fonctions de module dans l'éditeur de code" ], "improvement": [ - "Le panneau de fonctions rapides du module d'édition de code s'adapte au mode nuit.", - "La page de démarrage de l'application emballée s'adapte au mode nuit et la disposition des icônes d'application est ajustée.", - "La page de l'application emballée prend en charge la navigation du curseur à l'aide de la touche ENTER sur le clavier logiciel.", - "La page de l'application emballée prend en charge le basculement de l'état de sélection totale en cliquant sur les titres ABI et de bibliothèque.", - "La sélection par défaut d'ABI est rendue intelligente sur la page de l'application emballée avec des invites guide pour les éléments non sélectionnables.", - "Le gestionnaire de fichiers ajuste l'affichage des éléments du menu en fonction du type et des caractéristiques des fichiers et dossiers.", - "Le menu contextuel du gestionnaire de fichiers pour les dossiers ajoute une option d'emballage d'application.", - "Lorsque les services d'accessibilité sont activés mais dysfonctionnent, un état anormal se reflète dans le commutateur du tiroir de la page d'accueil d'AutoJs6.", + "Le panneau de fonctions rapides du module d'édition de code s'adapte au mode nuit", + "La page de démarrage de l'application emballée s'adapte au mode nuit et la disposition des icônes d'application est ajustée", + "La page de configuration de packaging prend maintenant en charge la touche ENTER du clavier virtuel pour deplacer le focus du curseur", + "La page de configuration de packaging permet maintenant d'appuyer sur les titres ABI et les titres de bibliotheque pour basculer l'etat de selection globale", + "La page de configuration de packaging utilise maintenant une selection ABI par defaut plus intelligente et ajoute des indications pour les options indisponibles", + "Le gestionnaire de fichiers ajuste l'affichage des éléments du menu en fonction du type et des caractéristiques des fichiers et dossiers", + "Le menu contextuel du gestionnaire de fichiers pour les dossiers ajoute une option d'emballage d'application", + "Lorsque les services d'accessibilité sont activés mais dysfonctionnent, un état anormal se reflète dans le commutateur du tiroir de la page d'accueil d'AutoJs6", "La console inclut des informations détaillées sur la pile lors de l'impression des messages d'erreur." ], "dependency": [ @@ -724,49 +724,49 @@ "Problèmes de perte des informations du canal alpha dans les résultats de colors.toString lorsque la valeur alpha est 0" ], "improvement": [ - "Redirection des classes publiques de la version Auto.js 4.x pour assurer une compatibilité descendante maximale possible (dans une certaine mesure).", - "Fusionner tous les modules du projet pour éviter d'éventuels problèmes de référence circulaire (supprimer temporairement le module inrt).", - "Migrer la configuration de construction Gradle de Groovy à KTS.", - "Ajouter un support multilingue pour les messages d'exception de Rhino.", - "L'interrupteur de permissions du tiroir de la page d'accueil ne montre des messages que lorsqu'il est activé.", - "La disposition du tiroir de la page d'accueil s'attache directement sous la barre d'état pour éviter les incompatibilités de barre de couleur supérieure.", - "Compatibilité des fonctions de vérification de mise à jour, téléchargement et avis de mise à jour avec le système Android 7.x.", - "Reconcevoir la page des paramètres (migration vers AndroidX).", - "La page des paramètres prend en charge la pression longue sur les options de configuration pour afficher des informations détaillées.", - "Ajout de l'option \"Suivre le système\" pour le mode nocturne (Android 9+).", - "Compatibilité de l'écran de démarrage de l'application avec le mode nocturne.", - "Ajouter des identifiants numériques aux icônes d'application pour améliorer l'expérience utilisateur avec plusieurs versions open source coexistantes.", - "Ajouter plus d'options de couleurs Material Design au thème de l'application.", - "Alléger et adapter les icônes des éléments de liste dans le gestionnaire de fichiers/panneau des tâches à la couleur du thème.", - "Compatibilité de la couleur du texte indicatif dans la boîte de recherche de la page d'accueil avec le mode nocturne.", - "Compatibilité des composants tels que les dialogues/textes/Fab/AppBar/éléments de liste avec le mode nocturne.", - "Compatibilité des pages telles que les documents/paramètres/à propos/couleurs de thème/analyse de mise en page et des menus des boutons flottants avec le mode nocturne.", - "Compatibilité de la disposition des pages avec la disposition RTL (Right-To-Left) dans la mesure du possible.", - "Ajouter des effets d'animation des icônes à la page à propos.", - "Mise à jour automatique de l'année dans le texte de la déclaration de droits d'auteur sur la page à propos.", - "Après l'installation initiale de l'application, déterminer et définir automatiquement un répertoire de travail approprié.", - "Désactiver la fonction de zoom à deux doigts sur la page des documents pour éviter une anomalie de l'affichage du contenu.", - "Simplifier le nom et le chemin des tâches affichés dans les éléments de liste du panneau des tâches par un chemin relatif.", - "Abréger le texte des boutons de l'éditeur de texte pour éviter le débordement du contenu.", - "Prise en charge de la restauration de la taille de police par défaut dans la configuration de l'éditeur de texte.", - "Améliorer la vitesse de réponse au clic sur le bouton flottant.", - "Cliquer sur le bouton d'analyse de mise en page du bouton flottant effectue directement l'analyse de la plage de mise en page.", - "Le thème de l'analyse de mise en page est adaptable (la fenêtre flottante suit le thème de l'application, le panneau de configuration rapide suit le thème du système).", - "Réorganiser la liste des informations de contrôle de mise en page selon la fréquence d'utilisation potentielle.", - "Optimiser le format de sortie automatiquement lors du clic et copie sur les informations de contrôle de mise en page selon le type de sélecteur.", - "Lors de la sélection de fichiers à l'aide de la fenêtre flottante, appuyer sur la touche de retour ramène au répertoire supérieur au lieu de fermer directement la fenêtre.", - "Prise en charge de la détection de validité numérique et de la conversion automatique des symboles pointillés lors de la saisie d'une adresse en mode client se connectant à l'ordinateur.", - "Afficher l'adresse IP du périphérique correspondant dans le tiroir de la page d'accueil après que le client et le serveur se sont connectés.", - "Ajouter une protection contre la réécriture à certains objets globaux et modules intégrés (consultez la documentation du projet > Objets globaux > [Protection contre la réécriture](https://docs.autojs6.com/#/global?id=%e8%a6%86%e5%86%99%e4%bf%9d%e6%8a%a4)).", - "importClass et importPackage prennent en charge des paramètres de chaîne et des paramètres de longueur variable.", - "ui.run prend en charge l'impression des informations de trace de pile en cas d'exception.", - "ui.R et auto.R peuvent obtenir commodément l'ID de ressources d'AutoJs6.", - "Les méthodes associées à l'utilisation d'applications dans le module app prennent en charge des paramètres de type App et des paramètres d'alias d'application.", - "Les méthodes associées au rappel asynchrone dans le module dialogs prennent en charge l'omission des paramètres pré-remplis.", - "app.startActivity et autres prennent en charge des paramètres d'option d'URL (voir code d'exemple > Applications > Intention).", - "Le module device renvoie null au lieu de lancer une exception lorsque l'obtention de l'IMEI ou du numéro de série matériel échoue.", - "Augmenter la luminosité du texte dans le journal de la fenêtre flottante affichée par console.show pour améliorer la lisibilité du contenu.", - "ImageWrapper#saveTo prend en charge la sauvegarde de fichiers image dans des chemins relatifs.", + "Redirection des classes publiques de la version Auto.js 4.x pour assurer une compatibilité descendante maximale possible (dans une certaine mesure)", + "Fusionner tous les modules du projet pour éviter d'éventuels problèmes de référence circulaire (supprimer temporairement le module inrt)", + "Migrer la configuration de construction Gradle de Groovy à KTS", + "Ajouter un support multilingue pour les messages d'exception de Rhino", + "L'interrupteur de permissions du tiroir de la page d'accueil ne montre des messages que lorsqu'il est activé", + "La disposition du tiroir de la page d'accueil s'attache directement sous la barre d'état pour éviter les incompatibilités de barre de couleur supérieure", + "Compatibilité des fonctions de vérification de mise à jour, téléchargement et avis de mise à jour avec le système Android 7.x", + "Reconcevoir la page des paramètres (migration vers AndroidX)", + "La page des paramètres prend en charge la pression longue sur les options de configuration pour afficher des informations détaillées", + "Ajout de l'option \"Suivre le système\" pour le mode nocturne (Android 9+)", + "Compatibilité de l'écran de démarrage de l'application avec le mode nocturne", + "Ajouter des identifiants numériques aux icônes d'application pour améliorer l'expérience utilisateur avec plusieurs versions open source coexistantes", + "Ajouter plus d'options de couleurs Material Design au thème de l'application", + "Alléger et adapter les icônes des éléments de liste dans le gestionnaire de fichiers/panneau des tâches à la couleur du thème", + "Compatibilité de la couleur du texte indicatif dans la boîte de recherche de la page d'accueil avec le mode nocturne", + "Compatibilité des composants tels que les dialogues/textes/Fab/AppBar/éléments de liste avec le mode nocturne", + "Compatibilité des pages telles que les documents/paramètres/à propos/couleurs de thème/analyse de mise en page et des menus des boutons flottants avec le mode nocturne", + "Compatibilité de la disposition des pages avec la disposition RTL (Right-To-Left) dans la mesure du possible", + "Ajouter des effets d'animation des icônes à la page à propos", + "Mise à jour automatique de l'année dans le texte de la déclaration de droits d'auteur sur la page à propos", + "Après l'installation initiale de l'application, déterminer et définir automatiquement un répertoire de travail approprié", + "Désactiver la fonction de zoom à deux doigts sur la page des documents pour éviter une anomalie de l'affichage du contenu", + "Simplifier le nom et le chemin des tâches affichés dans les éléments de liste du panneau des tâches par un chemin relatif", + "Abréger le texte des boutons de l'éditeur de texte pour éviter le débordement du contenu", + "Prise en charge de la restauration de la taille de police par défaut dans la configuration de l'éditeur de texte", + "Améliorer la vitesse de réponse au clic sur le bouton flottant", + "Cliquer sur le bouton d'analyse de mise en page du bouton flottant effectue directement l'analyse de la plage de mise en page", + "Le thème de l'analyse de mise en page est adaptable (la fenêtre flottante suit le thème de l'application, le panneau de configuration rapide suit le thème du système)", + "Réorganiser la liste des informations de contrôle de mise en page selon la fréquence d'utilisation potentielle", + "Optimiser le format de sortie automatiquement lors du clic et copie sur les informations de contrôle de mise en page selon le type de sélecteur", + "Lors de la sélection de fichiers à l'aide de la fenêtre flottante, appuyer sur la touche de retour ramène au répertoire supérieur au lieu de fermer directement la fenêtre", + "Prise en charge de la détection de validité numérique et de la conversion automatique des symboles pointillés lors de la saisie d'une adresse en mode client se connectant à l'ordinateur", + "Afficher l'adresse IP du périphérique correspondant dans le tiroir de la page d'accueil après que le client et le serveur se sont connectés", + "Ajouter une protection contre la réécriture à certains objets globaux et modules intégrés (consultez la documentation du projet > Objets globaux > [Protection contre la réécriture](https://docs.autojs6.com/#/global?id=%e8%a6%86%e5%86%99%e4%bf%9d%e6%8a%a4))", + "importClass et importPackage prennent en charge des paramètres de chaîne et des paramètres de longueur variable", + "ui.run prend en charge l'impression des informations de trace de pile en cas d'exception", + "ui.R et auto.R peuvent obtenir commodément l'ID de ressources d'AutoJs6", + "Les méthodes associées à l'utilisation d'applications dans le module app prennent en charge des paramètres de type App et des paramètres d'alias d'application", + "Les méthodes associées au rappel asynchrone dans le module dialogs prennent en charge l'omission des paramètres pré-remplis", + "app.startActivity et autres prennent en charge des paramètres d'option d'URL (voir code d'exemple > Applications > Intention)", + "Le module device renvoie null au lieu de lancer une exception lorsque l'obtention de l'IMEI ou du numéro de série matériel échoue", + "Augmenter la luminosité du texte dans le journal de la fenêtre flottante affichée par console.show pour améliorer la lisibilité du contenu", + "ImageWrapper#saveTo prend en charge la sauvegarde de fichiers image dans des chemins relatifs", "Reconcevoir l'objet global colors et inclure la prise en charge des modes de couleur HSV / HSL (consultez la documentation du projet > [Couleurs](https://docs.autojs6.com/#/color))." ], "dependency": [ diff --git a/.changelog/lang_ja.json b/.changelog/lang_ja.json index 163f1138..3032e95c 100644 --- a/.changelog/lang_ja.json +++ b/.changelog/lang_ja.json @@ -129,7 +129,7 @@ "improvement": [ "パッケージアプリのテンプレートにおける APK ファイルサイズの最適化", "アプリ (およびパッケージアプリ) がより多くの権限に対応 _[`issue #338`](http://issues.autojs6.com/338)_", - "パッケージングページに Pinyin ライブラリのオプションを追加", + "アプリ打包設定ページで Pinyin ライブラリのオプションに対応", "パッケージアプリのメインページにおいて, ステータスバーの背景とテキスト色を最適化", "パッケージアプリの設定ページに, 特別な権限 (全ファイルアクセスや通知送信) 用のトグルスイッチを追加 _[`issue #354`](http://issues.autojs6.com/354)_", "コントロールのテキストとアイコンが, テーマの明るさに合わせて自動で調整されるよう改善", @@ -181,7 +181,7 @@ "UiObjectCollection インスタンスにメソッドおよびプロパティが欠如している問題" ], "improvement": [ - "パッケージ化ページで署名設定, キーストア管理, 権限設定をサポートします ([luckyloogn]() による) _[`pr #286`]()_", + "アプリ打包設定ページで署名設定, keystore 管理, 権限設定に対応 (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", "フローティングウィンドウの現在のパッケージ名および現在のアクティビティ名の認識精度を向上 (優先順位: Shizuku > Root > A11Y)", "currentPackage と currentActivity の認識精度を向上 (優先順位: Shizuku > Root > A11Y)", "ログアクティビティウィンドウの個別エントリのテキスト内容をダブルクリックまたは長押しで選択する機能を復元 _[`issue #280`](http://issues.autojs6.com/280)_", @@ -264,7 +264,7 @@ "アプリパッケージが opencc モジュールを正常に使用できない問題" ], "improvement": [ - "パッケージページ内の [利用不可 ABI] コントロールのクリックヒントユーザー体験", + "アプリ打包設定ページの \"利用不可 ABI\" コントロールのタップ時ヒント体験を改善", "Shizuku を使用して [ポインタ位置] 表示スイッチをコントロールするサポート", "Shizuku を使用して [メディアの投影] および [セキュリティ設定の変更] 許可スイッチをコントロールするサポート", "automator.gestureAsync/gesturesAsync がコールバック関数パラメータをサポート", @@ -324,12 +324,12 @@ "feature": [ "opencc モジュール (参照 プロジェクトドキュメント > [中文変換](https://docs.autojs6.com/#/opencc)) (Ref to [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R268))", "UiSelector に [plus](https://docs.autojs6.com/#/uiObjectType?id=m-plus) 及び [append](https://docs.autojs6.com/#/uiObjectType?id=m-append) メソッドを追加 _[`issue #115`](http://issues.autojs6.com/115)_", - "パッケージ化アプリページに ABI およびライブラリのフィルタリングを追加 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" + "アプリ打包設定ページで ABI とライブラリの絞り込みに対応 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" ], "fix": [ "パッケージ化アプリのファイルサイズが異常に大きい問題 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX) / [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-d932ac49867d4610f8eeb21b59306e8e923d016cbca192b254caebd829198856R61)) _[`issue #176`](http://issues.autojs6.com/176)_", "パッケージ化アプリで一部の例外メッセージが表示されないおよび印刷されない問題", - "パッケージ化ページでアプリアイコンを選択すると空のアイコンが表示される可能性のある問題", + "アプリ打包設定ページでアプリアイコン選択後に空白アイコンが表示されることがある問題を修正", "パッケージ化アプリに MLKit Google OCR ライブラリを含むと初期化コンテキスト例外が発生する可能性がある", "ocr.recognizeText/detect メソッドが無効である問題", "一部のテキスト (例:ログページ) 表示言語がアプリ設定言語と一致しない可能性のある問題", @@ -353,9 +353,9 @@ "improvement": [ "コードエディターのモジュール関数クイックパネルがナイトモードに適応します", "パッケージ化されたアプリケーションの起動画面がナイトモードに適応し, アプリアイコンのレイアウトが調整されます", - "パッケージ化されたアプリのページは, ソフトウェアキーボードの ENTER キーを使用してカーソルナビゲーションをサポートします", - "パッケージ化されたアプリのページでは, ABI およびライブラリのタイトルをクリックして全選択状態を切り替えることができます", - "パッケージ化されたアプリのページでは, デフォルトの ABI 選択がインテリジェントになり, 選択不可の項目にガイドプロンプトが追加されます", + "アプリ打包設定ページでソフトキーボードの ENTER キーによるカーソルフォーカス移動に対応", + "アプリ打包設定ページで ABI タイトルとライブラリタイトルのタップによる全選択切替に対応", + "アプリ打包設定ページでデフォルト ABI のスマート選択に対応し, 選択不可項目の案内ヒントを追加", "ファイルマネージャーは, ファイルとフォルダの種類と特性に基づいてメニュー項目の表示を調整します", "ファイルマネージャーのフォルダ右クリックメニューには, パッケージ化アプリのオプションが追加されます", "アクセシビリティサービスが有効になっているが機能していない場合, 異常状態は AutoJs6 ホームページのドロワースイッチに反映されます", diff --git a/.changelog/lang_ko.json b/.changelog/lang_ko.json index ac84b127..fe3169c6 100644 --- a/.changelog/lang_ko.json +++ b/.changelog/lang_ko.json @@ -129,7 +129,7 @@ "improvement": [ "패키지 앱 템플릿의 APK 파일 크기 최적화", "앱 (및 패키지 앱) 이 더 많은 권한을 지원하도록 개선 _[`issue #338`](http://issues.autojs6.com/338)_", - "패키징 페이지에 Pinyin 라이브러리 옵션 추가", + "앱 패키징 설정 페이지에서 Pinyin 라이브러리 옵션을 지원합니다", "패키지 앱 메인 페이지에서 상태 표시줄 배경과 텍스트 색상을 최적화", "패키지 앱 설정 페이지에 전체 파일 접근 및 알림 전송과 같은 특수 권한용 스위치 추가 _[`issue #354`](http://issues.autojs6.com/354)_", "컨트롤의 텍스트와 아이콘 색상이 테마의 밝기에 따라 자동으로 조정되도록 개선", @@ -181,7 +181,7 @@ "UiObjectCollection 인스턴스에서 메서드 및 속성이 누락된 문제" ], "improvement": [ - "패키징 페이지에서 서명 구성, 키 저장소 관리 및 권한 설정을 지원합니다. ([luckyloogn]()) _[`pr #286`]()_", + "앱 패키징 설정 페이지에서 서명 설정, keystore 관리, 권한 설정을 지원합니다 (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", "플로팅 윈도우의 현재 패키지 이름 및 현재 활동 이름의 인식 정확도가 향상되었습니다 (우선 순위: Shizuku > Root > A11Y)", "currentPackage 및 currentActivity 의 인식 정확도가 향상되었습니다 (우선 순위: Shizuku > Root > A11Y)", "로그 활동 창의 개별 항목 텍스트 내용을 더블 클릭 또는 길게 눌러 선택하는 기능 복원 _[`issue #280`](http://issues.autojs6.com/280)_", @@ -264,7 +264,7 @@ "앱 패키지가 opencc 모듈을 정상적으로 사용할 수 없는 문제" ], "improvement": [ - "패키지 페이지 내 '사용 불가 ABI' 컨트롤의 클릭 힌트 사용자 경험", + "앱 패키징 설정 페이지의 \"사용 불가 ABI\" 컨트롤에 대한 탭 안내 경험을 개선했습니다", "Shizuku 를 사용하여 '포인터 위치' 디스플레이 스위치를 제어하는 것을 지원", "Shizuku 를 사용하여 '미디어 프로젝션' 및 '보안 설정 수정' 권한 스위치를 제어하는 것을 지원", "automator.gestureAsync/gesturesAsync 가 콜백 함수 매개변수를 지원", @@ -324,12 +324,12 @@ "feature": [ "opencc 모듈 (프로젝트 문서 > [중국어 변환](https://docs.autojs6.com/#/opencc)) (참조 [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R268))", "UiSelector 에 [plus](https://docs.autojs6.com/#/uiObjectType?id=m-plus) 및 [append](https://docs.autojs6.com/#/uiObjectType?id=m-append) 메소드 추가 _[`issue #115`](http://issues.autojs6.com/115)_", - "번들 앱 페이지에 ABI 및 라이브러리 필터링 지원 추가 (참조 [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" + "앱 패키징 설정 페이지에서 ABI 및 라이브러리 필터링을 지원합니다 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" ], "fix": [ "번들 앱 파일 크기 비정상적으로 큰 문제 (참조 [AutoX](https://github.com/kkevsekk1/AutoX) / [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-d932ac49867d4610f8eeb21b59306e8e923d016cbca192b254caebd829198856R61)) _[`issue #176`](http://issues.autojs6.com/176)_", "번들 앱이 일부 예외 메시지를 표시하지 못하고 인쇄하지 않는 문제", - "번들 앱 페이지에서 앱 아이콘을 선택한 후 빈 아이콘이 표시될 수 있는 문제", + "앱 패키징 설정 페이지에서 앱 아이콘 선택 후 빈 아이콘이 표시될 수 있던 문제를 수정했습니다", "번들 앱이 MLKit Google OCR 라이브러리를 포함할 때 발생할 수 있는 초기화되지 않은 컨텍스트 예외", "ocr.recognizeText/detect 메소드가 작동하지 않는 문제", "일부 텍스트 (로그 페이지 등) 의 언어가 앱 설정 언어와 일치하지 않는 문제", @@ -351,14 +351,14 @@ "코드 편집기 모듈 함수 빠른 선택 패널에 표시되는 함수 이름이 넘칠 수 있는 문제" ], "improvement": [ - "코드 편집기 모듈의 빠른 기능 패널이 야간 모드에 적응합니다.", - "포장된 애플리케이션의 시작 페이지가 야간 모드에 적응하고 애플리케이션 아이콘의 레이아웃이 조정됩니다.", - "포장된 애플리케이션 페이지는 소프트웨어 키보드의 ENTER 키를 사용하여 커서 내비게이션을 지원합니다.", - "포장된 애플리케이션 페이지는 ABI 및 라이브러리 제목을 클릭하여 전체 선택 상태를 토글할 수 있습니다.", - "포장된 애플리케이션 페이지의 기본 ABI 선택은 비선택 항목에 대한 가이드 프롬프트가 추가된 지능형 방식으로 이루어집니다.", - "파일 관리자에서는 파일 및 폴더의 유형 및 특성에 따라 메뉴 항목의 표시가 조정됩니다.", - "파일 관리자의 폴더 마우스 오른쪽 클릭 메뉴에 애플리케이션 포장 옵션이 추가됩니다.", - "접근성 서비스가 활성화되었지만 제대로 작동하지 않는 경우, AutoJs6 홈페이지의 드로어 스위치에 비정상적인 상태가 반영됩니다.", + "코드 편집기 모듈의 빠른 기능 패널이 야간 모드에 적응합니다", + "포장된 애플리케이션의 시작 페이지가 야간 모드에 적응하고 애플리케이션 아이콘의 레이아웃이 조정됩니다", + "앱 패키징 설정 페이지에서 소프트 키보드 ENTER 키로 커서 초점을 이동할 수 있도록 지원합니다", + "앱 패키징 설정 페이지에서 ABI 제목과 라이브러리 제목을 눌러 전체 선택 상태를 전환할 수 있도록 지원합니다", + "앱 패키징 설정 페이지에서 기본 ABI를 더 똑똑하게 선택하고, 선택할 수 없는 항목에 대한 안내 힌트를 추가했습니다", + "파일 관리자에서는 파일 및 폴더의 유형 및 특성에 따라 메뉴 항목의 표시가 조정됩니다", + "파일 관리자의 폴더 마우스 오른쪽 클릭 메뉴에 애플리케이션 포장 옵션이 추가됩니다", + "접근성 서비스가 활성화되었지만 제대로 작동하지 않는 경우, AutoJs6 홈페이지의 드로어 스위치에 비정상적인 상태가 반영됩니다", "콘솔에는 오류 메시지를 인쇄할 때 상세한 스택 정보가 포함됩니다." ], "dependency": [ @@ -853,7 +853,7 @@ "new RootAutomator() 호출 시 발생할 수 있는 멈춤 문제" ], "improvement": [ - "RootAutomator 는 Root 권한이 없을 때 인스턴스화되지 않습니다.", + "RootAutomator 는 Root 권한이 없을 때 인스턴스화되지 않습니다", "\"앱 및 개발자 정보\" 페이지 재설계", "모든 내장 JavaScript 모듈 재구성", "모든 Gradle 빌드 스크립트 재구성 및 공통 구성 스크립트 추가 (config.gradle)", diff --git a/.changelog/lang_ru.json b/.changelog/lang_ru.json index dbf56a20..0e8f9f34 100644 --- a/.changelog/lang_ru.json +++ b/.changelog/lang_ru.json @@ -129,7 +129,7 @@ "improvement": [ "Оптимизация размера файла APK в шаблоне упакованных приложений", "Приложение (и упакованные приложения) теперь поддерживают больше разрешений _[`issue #338`](http://issues.autojs6.com/338)_", - "Добавлена опция для библиотеки Pinyin на странице упаковки", + "Страница настройки упаковки приложения теперь поддерживает параметры библиотеки Pinyin", "Оптимизация фона строки состояния и цвета текста на главном экране упакованных приложений", "Добавлены переключатели для специальных разрешений (доступ ко всем файлам и отправка уведомлений) на странице настроек упакованных приложений _[`issue #354`](http://issues.autojs6.com/354)_", "Цвета текста и иконок элементов управления автоматически адаптируются в зависимости от яркости темы", @@ -181,7 +181,7 @@ "Ошибка, из-за которой экземпляры UiObjectCollection теряли собственные методы и свойства" ], "improvement": [ - "Страница упаковки поддерживает настройку подписи, управление хранилищем ключей и настройку разрешений (автор [luckyloogn]()) _[`pr #286`]()_", + "Страница настройки упаковки приложения теперь поддерживает настройки подписи, управление keystore и параметры разрешений (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", "Улучшена точность распознавания текущего имени пакета и имени активности для плавающего окна (приоритет: Shizuku > Root > A11Y)", "Улучшена точность распознавания currentPackage и currentActivity (приоритет: Shizuku > Root > A11Y)", "Восстановлена возможность выбора текста в отдельных записях в окне лога двойным щелчком или длительным нажатием _[`issue #280`](http://issues.autojs6.com/280)_", @@ -264,7 +264,7 @@ "Проблема с упакованным приложением, не способным корректно использовать модуль opencc" ], "improvement": [ - "Индикация клика для контроля \"ABI недоступно\" на странице пакета", + "Улучшены подсказки при нажатии на элемент \"Недоступный ABI\" на странице настройки упаковки приложения", "Поддержка использования Shizuku для управления переключателем отображения \"Местоположение указателя\"", "Поддержка использования Shizuku для управления переключателями разрешения \"Медиа проекции\" и \"Изменение безопасных настроек\"", "Automator.gestureAsync/gesturesAsync поддерживает параметры функции обратного вызова", @@ -324,12 +324,12 @@ "feature": [ "Модуль opencc (см. Документацию проекта > [Конвертация китайских символов](https://docs.autojs6.com/#/opencc)) (см. [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R268))", "Добавлены методы [plus](https://docs.autojs6.com/#/uiObjectType?id=m-plus) и [append](https://docs.autojs6.com/#/uiObjectType?id=m-append) в UiSelector _[`issue #115`](http://issues.autojs6.com/115)_", - "Добавлена поддержка фильтрации ABI и библиотек на странице упаковки (см. [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" + "Страница настройки упаковки приложения теперь поддерживает фильтрацию ABI и библиотек (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" ], "fix": [ "Проблема с аномально большим размером упакованных приложений (см. [AutoX](https://github.com/kkevsekk1/AutoX) / [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-d932ac49867d4610f8eeb21b59306e8e923d016cbca192b254caebd829198856R61)) _[`issue #176`](http://issues.autojs6.com/176)_", "Проблема с невозможностью отображения и печати некоторых сообщений об ошибках в упакованных приложениях", - "Проблема с отображением пустого значка после выбора значка приложения на странице упаковки", + "Исправлена проблема, из-за которой после выбора значка приложения на странице настройки упаковки мог отображаться пустой значок", "Проблема с необработанным исключением при инициализации контекста при использовании библиотеки Google OCR MLKit", "Неисправность методов ocr.recognizeText/detect", "Проблема с несоответствием языка отображения текста (например, на странице журнала) языковому параметру приложения", @@ -353,9 +353,9 @@ "improvement": [ "Панель быстрых функций модуля редактора кода адаптируется к ночному режиму", "Стартовая страница упакованного приложения адаптируется к ночному режиму, а размещение значков приложения корректируется", - "Страница упакованного приложения поддерживает навигацию курсора с помощью клавиши ENTER на программной клавиатуре", - "Страница упакованного приложения поддерживает переключение состояния выбора всего при нажатии на заголовки ABI и библиотеки", - "Выбор ABI по умолчанию осуществляется интеллектуально на странице упакованного приложения с добавлением приглашений для неселектируемых элементов", + "Страница настройки упаковки приложения теперь поддерживает переход фокуса курсора по клавише ENTER на экранной клавиатуре", + "Страница настройки упаковки приложения теперь поддерживает нажатие на заголовки ABI и библиотек для переключения состояния \"выбрать все\"", + "Страница настройки упаковки приложения теперь использует более умный выбор ABI по умолчанию и добавляет подсказки для недоступных параметров", "Файловый менеджер корректирует отображение элементов меню в зависимости от типа и характеристик файлов и папок", "Контекстное меню для папок в файловом менеджере добавляет опцию упаковки приложений", "Когда службы доступности включены, но работают некорректно, аномальное состояние отображается в переключателе ящика на главной странице AutoJs6", diff --git a/.changelog/lang_zh-Hans.json b/.changelog/lang_zh-Hans.json index 5535f88e..5185bd0c 100644 --- a/.changelog/lang_zh-Hans.json +++ b/.changelog/lang_zh-Hans.json @@ -1,7 +1,7 @@ { "$data": { "v6.7.0": { - "released_date": "2026/03/08", + "released_date": "2026/03/14", "feature": [ "插件中心功能, 支持插件的安装/卸载/更新等操作 (入口: 主页抽屉按钮/主页标签页)", "版本历史功能, 支持查看/恢复可编辑文件的历史版本 (入口: 主页抽屉按钮/文件管理器菜单/代码编辑器菜单)", @@ -49,6 +49,10 @@ "设置页面增加 \"重启策略\" 设置选项, 用于设置主页抽屉栏重启按钮是否使用快速重启策略", "设置页面增加 \"屏幕捕获权限申请延迟\" 设置选项, 用于避免权限申请窗口遮挡屏幕", "设置页面启动器快捷方式增加 \"插件\" 选项, 用于通过快捷方式跳转到插件中心页面", + "打包应用支持开机自启动并在配置页面增加开关配置", + "打包应用支持应用快捷方式 (日志页面/设置页面)", + "打包应用配置页面增加撤销/重做/保存按钮", + "打包应用配置页面增加配置机制, 支持配置的建立/修改/删除/导入/导出 _[`issue #483`](http://issues.autojs6.com/483)_", "Scrapers 工具 (run-scrapers.mjs) 用于自动更新 Gradle 构建脚本结构化数据/README 通用数据/README 模板数据等", "Gradle Wrapper 切换工具 (gradle-wrapper-switcher), 用于切换本地 Gradle 主版本 (如 Gradle 8.x 与 Gradle 9.x)" ], @@ -96,6 +100,8 @@ "输入事件观察器 InputEventObserver 可能导致应用启动时明显卡顿的问题", "Shizuku 用户服务进程未能正常结束导致进程堆积的问题 _[`issue #474`](http://issues.autojs6.com/474)_", "打包应用无法正常使用 Paddle OCR 与 Rapid OCR 功能的问题", + "打包应用配置文件 project.json 中的 key 值可能被意外修改的问题", + "打包应用配置页面滑动 \"需要的权限\" 列表时可能出现复选框图标闪烁的问题", "发行历史页面部分系统因字体差别导致统计数据显示不完整的问题", "部分设备无法正常初始化 MLKit Google OCR 的问题 (试修) _[`issue #8`](http://issues.autojs6.com/8#issuecomment-3117061768)_", "部分设备无法正常触发文件管理器功能按钮点击事件的问题 (试修) _[`issue #465`](http://issues.autojs6.com/465)_", @@ -156,7 +162,9 @@ "代码编辑器支持 \"-\", \"=\", \"(\", \"[\", \"{\", \"<\" 等按键长按功能", "打包应用打包过程对话框增加 \"中止\" 按钮", "打包应用打包过程对话框的显示方式并增加耗时统计", - "打包应用页面默认勾选必要权限 (WAKE_LOCK/INTERNET/WRITE_EXTERNAL_STORAGE) _[`issue #397`](http://issues.autojs6.com/397)_", + "打包应用使用新配置安装时将覆盖旧应用的相关配置", + "打包应用配置页面默认勾选必要权限 (WAKE_LOCK/INTERNET/WRITE_EXTERNAL_STORAGE/...) _[`issue #397`](http://issues.autojs6.com/397)_", + "打包应用配置页面支持更多选项的读取及配置 (启动时显示日志/启动时显示启动页/启动页标语文本/...)", "打包应用设置页面增加前台服务开关 _[`issue #406`](http://issues.autojs6.com/406)_", "脚本项目配置文件保存时增加键名冲突检测机制防止键名歧义", "崩溃报告页面支持双指缩放调整字体大小并添加常用功能按钮", @@ -349,7 +357,7 @@ "improvement": [ "精简打包应用模板 APK 文件大小", "应用 (以及打包应用) 支持更多权限 _[`issue #338`](http://issues.autojs6.com/338)_", - "打包页面支持 Pinyin 库选项", + "打包应用配置页面支持 Pinyin 库选项", "打包应用主活动页面优化状态栏背景及文字颜色", "打包应用设置页面增加访问所有文件和发送通知等特殊权限开关 _[`issue #354`](http://issues.autojs6.com/354)_", "控件的文字及图标根据主题色亮度值自动切换合适的颜色", @@ -401,7 +409,7 @@ "UiObjectCollection 实例缺失自身方法及属性的问题" ], "improvement": [ - "打包页面支持签名配置/密钥库管理/权限设置 (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", + "打包应用配置页面支持签名配置/密钥库管理/权限设置 (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", "提升浮动窗口当前包名及当前活动名的识别准确性 (优先级: Shizuku > Root > A11Y)", "提升 currentPackage/currentActivity 识别准确性 (优先级: Shizuku > Root > A11Y)", "恢复日志活动窗口单个条目文本内容的双击或长按选择功能 _[`issue #280`](http://issues.autojs6.com/280)_", @@ -484,7 +492,7 @@ "打包应用无法正常使用 opencc 模块的问题" ], "improvement": [ - "打包页面中 \"不可用 ABI\" 控件的点击提示体验", + "打包应用配置页面中 \"不可用 ABI\" 控件的点击提示体验", "支持使用 Shizuku 控制 \"指针位置\" 显示开关", "支持使用 Shizuku 控制 \"投影媒体\" 及 \"修改安全设置\" 权限开关", "automator.gestureAsync/gesturesAsync 支持回调函数参数", @@ -544,12 +552,12 @@ "feature": [ "opencc 模块 (参阅 项目文档 > [中文转换](https://docs.autojs6.com/#/opencc)) (Ref to [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R268))", "UiSelector 增加 [plus](https://docs.autojs6.com/#/uiObjectType?id=m-plus) 及 [append](https://docs.autojs6.com/#/uiObjectType?id=m-append) 方法 _[`issue #115`](http://issues.autojs6.com/115)_", - "打包应用页面增加 ABI 及库的筛选支持 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" + "打包应用配置页面增加 ABI 及库的筛选支持 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" ], "fix": [ "打包应用文件体积异常庞大的问题 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX) / [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-d932ac49867d4610f8eeb21b59306e8e923d016cbca192b254caebd829198856R61)) _[`issue #176`](http://issues.autojs6.com/176)_", "打包应用无法显示并打印部分异常消息的问题", - "打包应用页面选择应用图标后可能显示空图标的问题", + "打包应用配置页面选择应用图标后可能显示空图标的问题", "打包应用包含 MLKit Google OCR 库时可能出现的上下文未初始化异常", "ocr.recognizeText/detect 方法无效的问题", "部分文本 (如日志页面) 显示语言与应用设置语言可能不相符的问题", @@ -573,9 +581,9 @@ "improvement": [ "代码编辑器模块函数快捷面板适配夜间模式", "打包应用启动页面适配夜间模式并调整应用图标布局", - "打包应用页面支持使用软键盘 ENTER 键实现光标跳转", - "打包应用页面支持点击 ABI 标题及库标题切换全选状态", - "打包应用页面默认 ABI 智能选择并增加不可选择项的引导提示", + "打包应用配置页面支持使用软键盘 ENTER 键实现光标跳转", + "打包应用配置页面支持点击 ABI 标题及库标题切换全选状态", + "打包应用配置页面默认 ABI 智能选择并增加不可选择项的引导提示", "文件管理器根据文件及文件夹的类型及特征调整菜单项的显示情况", "文件管理器文件夹右键菜单增加打包应用选项", "无障碍服务启用但功能异常时在 AutoJs6 主页抽屉开关处将体现异常状态", diff --git a/.changelog/lang_zh-Hant-HK.json b/.changelog/lang_zh-Hant-HK.json index 2e8e5cec..d2caff16 100644 --- a/.changelog/lang_zh-Hant-HK.json +++ b/.changelog/lang_zh-Hant-HK.json @@ -129,7 +129,7 @@ "improvement": [ "精簡打包應用模板 APK 文件大小", "應用 (以及打包應用) 支持更多權限 _[`issue #338`](http://issues.autojs6.com/338)_", - "打包頁面支持 Pinyin 庫選項", + "打包應用配置頁面支持 Pinyin 庫選項", "打包應用主活動頁面優化狀態欄背景及文字顏色", "打包應用設置頁面增加訪問所有文件和發送通知等特殊權限開關 _[`issue #354`](http://issues.autojs6.com/354)_", "控件的文字及圖標根據主題色亮度值自動切換合適的顏色", @@ -181,7 +181,7 @@ "UiObjectCollection 實例缺失自身方法及屬性的問題" ], "improvement": [ - "打包頁面支持簽名配置/密鑰庫管理/權限設置 (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", + "打包應用配置頁面支持簽名配置/密鑰庫管理/權限設置 (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", "提升浮動窗口當前包名及當前活動名的識別準確性 (優先級: Shizuku > Root > A11Y)", "提升 currentPackage/currentActivity 識別準確性 (優先級: Shizuku > Root > A11Y)", "恢復日誌活動窗口單個條目文本內容的雙擊或長按選擇功能 _[`issue #280`](http://issues.autojs6.com/280)_", @@ -264,7 +264,7 @@ "打包應用無法正常使用 opencc 模塊的問題" ], "improvement": [ - "打包頁面中 \"不可用 ABI\" 控件的點擊提示體驗", + "打包應用配置頁面中 \"不可用 ABI\" 控件的點擊提示體驗", "支持使用 Shizuku 控制 \"指針位置\" 顯示開關", "支持使用 Shizuku 控制 \"投影媒體\" 及 \"修改安全設置\" 權限開關", "automator.gestureAsync/gesturesAsync 支持回調函數參數", @@ -324,12 +324,12 @@ "feature": [ "opencc 模塊 (參閲 項目文檔 > [中文轉換](https://docs.autojs6.com/#/opencc)) (Ref to [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R268))", "UiSelector 增加 [plus](https://docs.autojs6.com/#/uiObjectType?id=m-plus) 及 [append](https://docs.autojs6.com/#/uiObjectType?id=m-append) 方法 _[`issue #115`](http://issues.autojs6.com/115)_", - "打包應用頁面增加 ABI 及庫的篩選支持 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" + "打包應用配置頁面增加 ABI 及庫的篩選支持 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" ], "fix": [ "打包應用文件體積異常龐大的問題 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX) / [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-d932ac49867d4610f8eeb21b59306e8e923d016cbca192b254caebd829198856R61)) _[`issue #176`](http://issues.autojs6.com/176)_", "打包應用無法顯示並打印部分異常消息的問題", - "打包應用頁面選擇應用圖標後可能顯示空圖標的問題", + "打包應用配置頁面選擇應用圖標後可能顯示空圖標的問題", "打包應用包含 MLKit Google OCR 庫時可能出現的上下文未初始化異常", "ocr.recognizeText/detect 方法無效的問題", "部分文本 (如日誌頁面) 顯示語言與應用設置語言可能不相符的問題", @@ -353,9 +353,9 @@ "improvement": [ "代碼編輯器模塊函數快捷面板適配夜間模式", "打包應用啓動頁面適配夜間模式並調整應用圖標佈局", - "打包應用頁面支持使用軟鍵盤 ENTER 鍵實現光標跳轉", - "打包應用頁面支持點擊 ABI 標題及庫標題切換全選狀態", - "打包應用頁面默認 ABI 智能選擇並增加不可選擇項的引導提示", + "打包應用配置頁面支持使用軟鍵盤 ENTER 鍵實現光標跳轉", + "打包應用配置頁面支持點擊 ABI 標題及庫標題切換全選狀態", + "打包應用配置頁面默認 ABI 智能選擇並增加不可選擇項的引導提示", "文件管理器根據文件及文件夾的類型及特徵調整菜單項的顯示情況", "文件管理器文件夾右鍵菜單增加打包應用選項", "無障礙服務啓用但功能異常時在 AutoJs6 主頁抽屜開關處將體現異常狀態", diff --git a/.changelog/lang_zh-Hant-TW.json b/.changelog/lang_zh-Hant-TW.json index 57f4c7ba..3976e975 100644 --- a/.changelog/lang_zh-Hant-TW.json +++ b/.changelog/lang_zh-Hant-TW.json @@ -129,7 +129,7 @@ "improvement": [ "精簡打包應用模板 APK 檔案大小", "應用 (以及打包應用) 支援更多許可權 _[`issue #338`](http://issues.autojs6.com/338)_", - "打包頁面支援 Pinyin 庫選項", + "打包應用配置頁面支援 Pinyin 庫選項", "打包應用主活動頁面最佳化狀態列背景及文字顏色", "打包應用設定頁面增加訪問所有檔案和傳送通知等特殊許可權開關 _[`issue #354`](http://issues.autojs6.com/354)_", "控制元件的文字及圖示根據主題色亮度值自動切換合適的顏色", @@ -181,7 +181,7 @@ "UiObjectCollection 例項缺失自身方法及屬性的問題" ], "improvement": [ - "打包頁面支援簽名配置/金鑰庫管理/許可權設定 (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", + "打包應用配置頁面支援簽名配置/金鑰庫管理/許可權設定 (by [luckyloogn](https://github.com/luckyloogn)) _[`pr #286`](http://pr.autojs6.com/286)_", "提升浮動視窗當前包名及當前活動名的識別準確性 (優先順序: Shizuku > Root > A11Y)", "提升 currentPackage/currentActivity 識別準確性 (優先順序: Shizuku > Root > A11Y)", "恢復日誌活動視窗單個條目文字內容的雙擊或長按選擇功能 _[`issue #280`](http://issues.autojs6.com/280)_", @@ -264,7 +264,7 @@ "打包應用無法正常使用 opencc 模組的問題" ], "improvement": [ - "打包頁面中 \"不可用 ABI\" 控制元件的點選提示體驗", + "打包應用配置頁面中 \"不可用 ABI\" 控制元件的點選提示體驗", "支援使用 Shizuku 控制 \"指標位置\" 顯示開關", "支援使用 Shizuku 控制 \"投影媒體\" 及 \"修改安全設定\" 許可權開關", "automator.gestureAsync/gesturesAsync 支援回撥函式引數", @@ -324,12 +324,12 @@ "feature": [ "opencc 模組 (參閱 專案文件 > [中文轉換](https://docs.autojs6.com/#/opencc)) (Ref to [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R268))", "UiSelector 增加 [plus](https://docs.autojs6.com/#/uiObjectType?id=m-plus) 及 [append](https://docs.autojs6.com/#/uiObjectType?id=m-append) 方法 _[`issue #115`](http://issues.autojs6.com/115)_", - "打包應用頁面增加 ABI 及庫的篩選支援 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" + "打包應用配置頁面增加 ABI 及庫的篩選支援 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX)) _[`issue #189`](http://issues.autojs6.com/189)_" ], "fix": [ "打包應用檔案體積異常龐大的問題 (Ref to [AutoX](https://github.com/kkevsekk1/AutoX) / [LZX284](https://github.com/SuperMonster003/AutoJs6/pull/187/files#diff-d932ac49867d4610f8eeb21b59306e8e923d016cbca192b254caebd829198856R61)) _[`issue #176`](http://issues.autojs6.com/176)_", "打包應用無法顯示並列印部分異常訊息的問題", - "打包應用頁面選擇應用圖示後可能顯示空圖示的問題", + "打包應用配置頁面選擇應用圖示後可能顯示空圖示的問題", "打包應用包含 MLKit Google OCR 庫時可能出現的上下文未初始化異常", "ocr.recognizeText/detect 方法無效的問題", "部分文字 (如日誌頁面) 顯示語言與應用設定語言可能不相符的問題", @@ -353,9 +353,9 @@ "improvement": [ "程式碼編輯器模組函式快捷面板適配夜間模式", "打包應用啟動頁面適配夜間模式並調整應用圖示佈局", - "打包應用頁面支援使用軟鍵盤 ENTER 鍵實現游標跳轉", - "打包應用頁面支援點選 ABI 標題及庫標題切換全選狀態", - "打包應用頁面預設 ABI 智慧選擇並增加不可選擇項的引導提示", + "打包應用配置頁面支援使用軟鍵盤 ENTER 鍵實現游標跳轉", + "打包應用配置頁面支援點選 ABI 標題及庫標題切換全選狀態", + "打包應用配置頁面預設 ABI 智慧選擇並增加不可選擇項的引導提示", "檔案管理器根據檔案及資料夾的型別及特徵調整選單項的顯示情況", "檔案管理器資料夾右鍵選單增加打包應用選項", "無障礙服務啟用但功能異常時在 AutoJs6 主頁抽屜開關處將體現異常狀態", diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 411bda6d..c1215110 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -227,6 +227,7 @@ android:name="org.autojs.autojs.ui.splash.SplashActivity" android:exported="true" android:theme="@style/AppTheme.Splash"> + @@ -247,7 +248,6 @@ - - + @@ -302,6 +302,7 @@ android:authorities="${authorities}" android:exported="false" android:grantUriPermissions="true"> + @@ -406,7 +407,6 @@ - @@ -414,6 +414,7 @@ + @@ -437,7 +438,6 @@ - - - - - + @@ -553,6 +550,7 @@ android:label="@string/text_run_script" android:taskAffinity="org.autojs.autojs.external.open.RunIntentActivity" android:theme="@android:style/Theme.NoDisplay"> + @@ -572,6 +570,7 @@ android:exported="true" android:label="@string/text_import_script" android:theme="@style/AppTheme.Transparent"> + @@ -591,6 +590,7 @@ android:exported="false" android:label="@string/app_name" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> + @@ -607,12 +607,12 @@ - + @@ -636,12 +636,34 @@ android:name="org.autojs.autojs.timing.BootCompletedReceiver" android:enabled="true" android:exported="true"> + + + + + + + + + + + + + + + + + @@ -687,7 +709,6 @@ - + @@ -709,21 +731,25 @@ android:name="org.autojs.autojs.inrt.SplashActivity" android:exported="true" android:theme="@style/AppTheme.Splash"> + - - - + + @@ -752,7 +778,5 @@ android:name="org.autojs.autojs.deviceid.DeviceIdProvider" android:authorities="${applicationId}.deviceid.provider" android:exported="true" /> - - - \ No newline at end of file + diff --git a/app/src/main/java/org/autojs/autojs/App.kt b/app/src/main/java/org/autojs/autojs/App.kt index 7bed78e2..d90a5b29 100644 --- a/app/src/main/java/org/autojs/autojs/App.kt +++ b/app/src/main/java/org/autojs/autojs/App.kt @@ -19,6 +19,8 @@ import com.hjq.toast.Toaster import io.reactivex.android.schedulers.AndroidSchedulers import org.autojs.autojs.app.GlobalAppContext import org.autojs.autojs.core.pref.Pref +import org.autojs.autojs.inrt.Pref as InrtPref +import org.autojs.autojs.inrt.InrtShortcuts import org.autojs.autojs.core.ui.inflater.ImageLoader import org.autojs.autojs.core.ui.inflater.util.Drawables import org.autojs.autojs.event.GlobalKeyObserver @@ -43,6 +45,7 @@ import java.lang.reflect.Method * Created by Stardust on Jan 27, 2017. * Modified by SuperMonster003 as of Feb 3, 2026. * Modified by JetBrains AI Assistant (GPT-5.2) as of Feb 7, 2026. + * Modified by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) as of Mar 9, 2026. */ class App : MultiDexApplication() { @@ -61,6 +64,10 @@ class App : MultiDexApplication() { setUpDefaultNightMode() } else /* Main process. */ -> { + if (AbstractAutoJs.isInrt) { + InrtPref.syncLaunchConfigWithBuild() + InrtShortcuts.syncToExplicitIntents() + } setUpDebugEnvironment() setUpLeakCanary() diff --git a/app/src/main/java/org/autojs/autojs/apkbuilder/ApkBuilder.kt b/app/src/main/java/org/autojs/autojs/apkbuilder/ApkBuilder.kt index f55ecde8..e4a61bdc 100644 --- a/app/src/main/java/org/autojs/autojs/apkbuilder/ApkBuilder.kt +++ b/app/src/main/java/org/autojs/autojs/apkbuilder/ApkBuilder.kt @@ -54,7 +54,8 @@ import java.util.zip.ZipFile /** * Created by Stardust on Oct 24, 2017. * Modified by JetBrains AI Assistant (GPT-5.2) as of Jan 17, 2026. - * Modified by SuperMonster003 as of Jan 18, 2026. + * Modified by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) as of Mar 9, 2026. + * Modified by SuperMonster003 as of Mar 13, 2026. */ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File, private val buildPath: String) { @@ -66,6 +67,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File private var mCancelSignal: AtomicBoolean? = null private var mPendingProjectConfigFile: File? = null private var mPendingProjectConfigJson: String? = null + private var mBundledProjectConfigJson: String? = null private lateinit var mProjectConfig: ProjectConfig @@ -74,8 +76,8 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File private val mAssetManager: AssetManager by lazy { globalContext.assets } private var mLibsIncludes = Lib.defaultLibsToInclude.toMutableList() - private var mAssetsFileIncludes = Lib.defaultAssetFilesToInclude.toMutableList() - private var mAssetsDirExcludes = Lib.defaultAssetDirsToExclude.toMutableList() + private var mAssetsFileIncludes = Lib.defaultAssetFilesToInclude.map(::normalizeAssetPath).toMutableList() + private var mAssetsDirExcludes = Lib.defaultAssetDirsToExclude.map(::normalizeAssetPath).toMutableList() private var mSplashThemeId: Int = 0 private var mNoSplashThemeId: Int = 0 @@ -90,13 +92,18 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File PFiles.ensureDir(outApkFile.path) } - fun setProgressCallback(callback: ProgressCallback?) = also { mProgressCallback = callback } + fun setProgressCallback(callback: ProgressCallback?) = also { + mProgressCallback = callback + } fun setCancelSignal(cancelSignal: AtomicBoolean?) = also { mCancelSignal = cancelSignal mApkPackager.setCancelSignal(cancelSignal) } + private fun getAssetsRoot(): File = + File(buildPath, "assets") + // Throw early when cancellation is requested to avoid partial outputs. // zh-CN: 当收到取消请求时尽早抛出, 以避免产生部分输出. private fun ensureNotCancelled() { @@ -119,6 +126,64 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File } } + private fun toAssetZipPrefix(path: String): String { + val normalized = normalizeAssetPath(path) + return if (normalized.isEmpty()) "assets/" else "assets/$normalized" + } + + private fun isAssetDirExcluded(assetPath: String): Boolean { + val normalized = normalizeAssetPath(assetPath) + return mAssetsDirExcludes.any { excluded -> + normalized == excluded || normalized.startsWith("$excluded/") + } + } + + private fun includeLibraryContributions(lib: Lib) { + mLibsIncludes += lib.libsToInclude.toSet() + mAssetsFileIncludes += lib.assetFilesToInclude.map(::normalizeAssetPath).toSet() + mAssetsDirExcludes -= lib.assetDirsToInclude.map(::normalizeAssetPath).toSet() + } + + private fun pruneTemplateAssetsByPolicy(context: Context) { + val assetsRoot = getAssetsRoot() + if (!assetsRoot.exists() || !assetsRoot.isDirectory) { + return + } + + val optionalAssetFiles = Lib.entries + .flatMap { it.assetFilesToInclude } + .map(::normalizeAssetPath) + .toSet() + + assetsRoot.listFiles()?.forEach { child -> + ensureNotCancelled() + val normalizedName = normalizeAssetPath(child.name) + if (normalizedName.isEmpty()) { + return@forEach + } + if (child.isDirectory) { + if (!isAssetDirExcluded(normalizedName)) { + return@forEach + } + notifyStepProgress( + ProgressStep.BUILD, + context.getString(R.string.text_pruning), + child.path, + ) + PFiles.deleteRecursively(child) + return@forEach + } + if (optionalAssetFiles.contains(normalizedName) && !mAssetsFileIncludes.contains(normalizedName)) { + notifyStepProgress( + ProgressStep.BUILD, + context.getString(R.string.text_pruning), + child.path, + ) + child.delete() + } + } + } + private fun notifyStepChanged(step: ProgressStep) { mProgressCallback?.let { callback -> GlobalAppContext.post { @@ -180,6 +245,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File it, ) copyDir(context, it, "assets/project/") + writeBundledProjectConfigIfNeeded(context) } else -> { notifyStepProgress( @@ -188,6 +254,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File it, ) replaceFile(context, it, "assets/project/main.js") + writeBundledProjectConfigIfNeeded(context) } } notifyStepProgress( @@ -315,10 +382,17 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File ensureNotCancelled() notifyStepProgress( ProgressStep.BUILD, - context.getString(R.string.text_copying_assets_to), - File(buildPath, "assets").path, + context.getString(R.string.text_processing), + getAssetsRoot().path, ) - copyAssetsRecursively(context, "", File(buildPath, "assets")) + pruneTemplateAssetsByPolicy(context) + ensureNotCancelled() + notifyStepProgress( + ProgressStep.BUILD, + context.getString(R.string.text_copying_assets_to), + getAssetsRoot().path, + ) + copyAssetsRecursively(context, "", getAssetsRoot()) ensureNotCancelled() notifyStepProgress( ProgressStep.BUILD, @@ -376,19 +450,21 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File @Throws(FileNotFoundException::class) fun editManifest(): ManifestEditor = ManifestEditorWithAuthorities(FileInputStream(mManifestFile)).also { mManifestEditor = it } + private fun writeBundledProjectConfigIfNeeded(context: Context) { + val json = mBundledProjectConfigJson ?: return + val configFile = File(buildPath, "assets/project/$CONFIG_FILE_NAME") + configFile.parentFile?.let { parent -> if (!parent.exists()) parent.mkdirs() } + notifyStepProgress( + ProgressStep.BUILD, + context.getString(R.string.text_writing_project_config), + configFile.path, + ) + configFile.writeText(json) + } + private fun updateProjectConfig(config: ProjectConfig) { ensureNotCancelled() - // 这里为什么要有这样的一个方法? ( - // 会不会是因为有些配置需要写入到文件中, 这些配置包括自增的版本号, 用户的选择或键入值等等 - // ) - // 参数 config 只是获取了一部分的字段用于设置新的 projectConfig, 为什么不直接使用全部的字段? ( - // 因为有些不需要更新. 如果我们需要将所有设置开放到 Activity 页面中, 那么其实所有配置都是需要更新的 - // ) - // 像 abis, libs, signatureScheme 等信息就全部丢失了. ( - // 所以需要添加到这个方法中 - // ) - val projectConfig = run { if (PFiles.isDir(config.sourcePath)) { // @Hint by SuperMonster003 on Jan 23, 2025. @@ -396,7 +472,21 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File // ! zh-CN: 打包项目目录. ProjectConfig.fromProjectDir(config.sourcePath)?.let { sourceProjectConfig -> sourceProjectConfig - .setBuildInfo(BuildInfo.generate(sourceProjectConfig.buildInfo.buildNumber + 1)) + .setName(config.name) + .setPackageName(config.packageName) + .setVersionName(config.versionName) + .setVersionCode(config.versionCode) + .setAbis(ArrayList(config.abis)) + .setLibs(ArrayList(config.libs)) + .setPermissions(ArrayList(config.permissions)) + .setSignatureScheme(config.signatureScheme) + sourceProjectConfig.launchConfig = config.launchConfig + val nextBuildInfo = BuildInfo.generate(sourceProjectConfig.buildInfo.buildNumber + 1) + sourceProjectConfig.buildInfo.apply { + buildId = nextBuildInfo.buildId + buildNumber = nextBuildInfo.buildNumber + buildTime = nextBuildInfo.buildTime + } mPendingProjectConfigFile = File(ProjectConfig.configFileOfDir(config.sourcePath)) mPendingProjectConfigJson = sourceProjectConfig.toJson(true) return@run sourceProjectConfig @@ -411,7 +501,12 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File .setPackageName(config.packageName) .setVersionName(config.versionName) .setVersionCode(config.versionCode) - .setBuildInfo(BuildInfo.generate(newProjectConfig.versionCode.toLong())) + .setAbis(ArrayList(config.abis)) + .setLibs(ArrayList(config.libs)) + .setPermissions(ArrayList(config.permissions)) + .setSignatureScheme(config.signatureScheme) + newProjectConfig.launchConfig = config.launchConfig + newProjectConfig.setBuildInfo(BuildInfo.generate(newProjectConfig.versionCode.toLong())) File(buildPath, "assets/project/$CONFIG_FILE_NAME").also { file -> file.parentFile?.let { parent -> if (!parent.exists()) parent.mkdirs() } }.writeText(newProjectConfig.toJson(true)) @@ -421,11 +516,10 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File mKey = MD5Utils.md5(projectConfig.run { packageName + versionName + mainScriptFileName }) mInitVector = MD5Utils.md5(projectConfig.run { buildInfo.buildId + name }).take(16) + mBundledProjectConfigJson = projectConfig.toJson(true) Lib.entries.forEach { entry -> if (config.libs.contains(entry.label)) { - mLibsIncludes += entry.libsToInclude.toSet() - mAssetsFileIncludes += entry.assetFilesToInclude.toSet() - mAssetsDirExcludes -= entry.assetDirsToInclude.toSet() + includeLibraryContributions(entry) } } } @@ -523,8 +617,8 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File if (targetFile.isFile && targetFile.exists()) return val list = mAssetManager.list(assetPath) ?: return if (list.isEmpty()) /* asset is a file */ { - if (!assetPath.contains(File.separatorChar)) /* assets root dir */ { - if (!mAssetsFileIncludes.contains(assetPath)) { + if (!assetPath.contains('/')) /* assets root dir */ { + if (!mAssetsFileIncludes.contains(normalizeAssetPath(assetPath))) { return } } @@ -540,7 +634,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File } } } else /* asset is folder */ { - if (mAssetsDirExcludes.any { assetPath.matches(Regex("$it(/[^/]+)*")) }) { + if (isAssetDirExcluded(assetPath)) { return } val displayPath = if (assetPath.isEmpty()) "/" else "/$assetPath" @@ -805,6 +899,26 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File } private inner class ManifestEditorWithAuthorities(manifestInputStream: InputStream?) : ManifestEditor(manifestInputStream) { + + override fun shouldIgnoreComponentNode(nodeName: String?, componentClassName: String?): Boolean = + when (componentClassName) { + // Disable static shortcuts in packaged apps. + // Will publish dynamic explicit shortcuts at runtime. + // zh-CN: + // 在打包应用中禁用静态快捷方式. + // 将在运行时发布动态显式快捷方式. + "android.app.shortcuts" -> nodeName == "meta-data" + + "org.autojs.autojs.external.open.EditIntentActivity", + "org.autojs.autojs.external.open.RunIntentActivity", + "org.autojs.autojs.external.open.ImportIntentActivity", + "org.autojs.autojs.external.tile.LayoutBoundsTile", + "org.autojs.autojs.external.tile.LayoutHierarchyTile", + -> true + + else -> false + } + override fun onAttr(attr: AxmlWriter.Attr) { attr.apply { @@ -1082,6 +1196,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File ): Boolean { ensureNotCancelled() var extractedAny = false + val zipPrefix = toAssetZipPrefix(assetPrefix) apkPaths.forEach { apkPath -> ensureNotCancelled() runCatching { @@ -1091,7 +1206,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File ensureNotCancelled() val entry: ZipEntry = entries.nextElement() val name = entry.name - if (!name.startsWith(assetPrefix)) continue + if (name != zipPrefix && !name.startsWith("$zipPrefix/")) continue if (entry.isDirectory) continue val relative = name.removePrefix("assets/") @@ -1255,29 +1370,6 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File } } - companion object { - - const val ICON_NAME = "ic_launcher" - const val ICON_RES_DIR = "mipmap" - const val LIBRARY_DIR = "lib" - - const val TEMPLATE_APK_NAME = "template.apk" - const val INRT_APP_ID = "org.autojs.autojs6.inrt" - - private val TAG = ApkBuilder::class.java.simpleName - - private val globalContext: Context by lazy { GlobalAppContext.get() } - - val appApkFile by lazy { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - File(globalContext.packageManager.getApplicationInfo(globalContext.packageName, ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES.toLong())).sourceDir) - } else { - File(globalContext.packageManager.getApplicationInfo(globalContext.packageName, 0).sourceDir) - } - } - - } - @Suppress("SpellCheckingInspection") enum class Lib( @JvmField val label: String, @@ -1288,7 +1380,6 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File internal val assetFilesToInclude: List = emptyList(), // Select, then include into packaging APK. (选择后, 会被打包进 APK 中.) internal val assetDirsToInclude: List = emptyList(), - internal val assetDirsToExclude: List = emptyList(), ) { TERMINAL_EMULATOR( @@ -1316,7 +1407,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File "libmlkit_google_ocr_pipeline.so", ), assetDirsToInclude = listOf( - "mlkit-google-ocr-models", + "assets/mlkit-google-ocr-models", ), ), @@ -1325,9 +1416,6 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File aliases = listOf("paddle", "paddleocr", "paddle-ocr", "paddle_ocr"), libsToInclude = emptyList(), assetDirsToInclude = emptyList(), - assetDirsToExclude = listOf( - "models", - ), plugin = PluginLib( action = "org.autojs.plugin.PADDLE_OCR", onServiceConnected = { binder: IBinder -> @@ -1378,7 +1466,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File "libonnxruntime.so", ), assetDirsToInclude = listOf( - "labels", + "assets/labels", ), ), @@ -1389,7 +1477,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File "libChineseConverter.so", ), assetDirsToInclude = listOf( - "openccdata", + "assets/openccdata", ), ), @@ -1397,10 +1485,10 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File label = "Pinyin", aliases = listOf("pin"), assetFilesToInclude = listOf( - "dict-chinese-words.db.gzip", - "dict-chinese-phrases.db.gzip", - "dict-chinese-chars.db.gzip", - "prob_emit.txt", + "assets/dict-chinese-words.db.gzip", + "assets/dict-chinese-phrases.db.gzip", + "assets/dict-chinese-chars.db.gzip", + "assets/prob_emit.txt", ), ), @@ -1411,7 +1499,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File "libbarhopper_v3.so", ), assetDirsToInclude = listOf( - "mlkit_barcode_models", + "assets/mlkit_barcode_models", ), ), @@ -1458,14 +1546,14 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File val defaultAssetFilesToInclude = listOf( "init.js", "roboto_medium.ttf", - ) + ).map(::normalizeAssetPath) val defaultAssetDirsToExclude = listOf( - "doc", "docs", "editor", "indices", "js-beautify", "sample", "stored-locales", - ) + entries.flatMap { it.assetDirsToInclude } + entries.flatMap { it.assetDirsToExclude } - + "doc", "docs", "editor", "indices", "js-beautify", "sample", "stored-locales", "models", + ).plus(entries.flatMap { it.assetDirsToInclude }) + .map(::normalizeAssetPath) + .distinct() } - } data class PluginLib( @@ -1481,4 +1569,39 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File val libsToInclude: List = emptyList(), ) + companion object { + + const val ICON_NAME = "ic_launcher" + const val ICON_RES_DIR = "mipmap" + const val LIBRARY_DIR = "lib" + + const val TEMPLATE_APK_NAME = "template.apk" + const val INRT_APP_ID = "org.autojs.autojs6.inrt" + + private val TAG = ApkBuilder::class.java.simpleName + + private val globalContext: Context by lazy { GlobalAppContext.get() } + + val appApkFile by lazy { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + File(globalContext.packageManager.getApplicationInfo(globalContext.packageName, ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES.toLong())).sourceDir) + } else { + File(globalContext.packageManager.getApplicationInfo(globalContext.packageName, 0).sourceDir) + } + } + + private fun normalizeAssetPath(path: String): String { + var out = path.trim().replace('\\', '/') + while (out.startsWith("/")) { + out = out.removePrefix("/") + } + if (out.startsWith("assets/")) { + out = out.removePrefix("assets/") + } + while (out.endsWith("/")) { + out = out.removeSuffix("/") + } + return out + } + } } diff --git a/app/src/main/java/org/autojs/autojs/apkbuilder/ManifestEditor.java b/app/src/main/java/org/autojs/autojs/apkbuilder/ManifestEditor.java index d325b329..af5db6b9 100644 --- a/app/src/main/java/org/autojs/autojs/apkbuilder/ManifestEditor.java +++ b/app/src/main/java/org/autojs/autojs/apkbuilder/ManifestEditor.java @@ -1,18 +1,19 @@ package org.autojs.autojs.apkbuilder; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - import pxb.android.StringItem; import pxb.android.axml.AxmlReader; import pxb.android.axml.AxmlWriter; import pxb.android.axml.NodeVisitor; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + import static org.autojs.autojs.apkbuilder.ApkBuilder.INRT_APP_ID; /** * Created by Stardust on Oct 23, 2017. + * Modified by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) as of Mar 9, 2026. */ public class ManifestEditor { @@ -94,6 +95,10 @@ public class ManifestEditor { return true; } + public boolean shouldIgnoreComponentNode(String nodeName, String componentClassName) { + return false; + } + private class MutableAxmlWriter extends AxmlWriter { private class MutableNodeImpl extends AxmlWriter.NodeImpl { @@ -103,7 +108,19 @@ public class ManifestEditor { @Override protected void onAttr(AxmlWriter.Attr a) { - if ("permission".equals(this.name.data) && "name".equals(a.name.data) && a.value instanceof StringItem) { + if (a.ns != null + && NS_ANDROID.equals(a.ns.data) + && "name".equals(a.name.data) + && a.value instanceof StringItem + && ManifestEditor.this.shouldIgnoreComponentNode(this.name.data, ((StringItem) a.value).data) + ) { + this.ignore = true; + return; + } + if ("permission".equals(this.name.data) + && "name".equals(a.name.data) + && a.value instanceof StringItem + ) { if ((INRT_APP_ID + ".DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION").equals(((StringItem) a.value).data)) { ((StringItem) a.value).data = mPackageName + ".DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"; super.onAttr(a); @@ -114,7 +131,10 @@ public class ManifestEditor { return; } } - if ("uses-permission".equals(this.name.data) && "name".equals(a.name.data) && a.value instanceof StringItem) { + if ("uses-permission".equals(this.name.data) + && "name".equals(a.name.data) + && a.value instanceof StringItem + ) { this.ignore = !ManifestEditor.this.isPermissionRequired(((StringItem) a.value).data); } ManifestEditor.this.onAttr(a); diff --git a/app/src/main/java/org/autojs/autojs/inrt/InrtBootCompletedReceiver.kt b/app/src/main/java/org/autojs/autojs/inrt/InrtBootCompletedReceiver.kt new file mode 100644 index 00000000..42ff5f83 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/inrt/InrtBootCompletedReceiver.kt @@ -0,0 +1,42 @@ +package org.autojs.autojs.inrt + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.util.Log +import org.autojs.autojs.AbstractAutoJs +import org.autojs.autojs.inrt.launch.GlobalProjectLauncher + +/** + * Created by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) on Mar 9, 2026. + */ +class InrtBootCompletedReceiver : BroadcastReceiver() { + + override fun onReceive(context: Context, intent: Intent?) { + if (!AbstractAutoJs.isInrt) { + return + } + val action = intent?.action ?: return + if (action != Intent.ACTION_BOOT_COMPLETED && action != Intent.ACTION_USER_UNLOCKED) { + return + } + val pendingResult = goAsync() + Thread { + try { + Pref.syncLaunchConfigWithBuild() + if (!Pref.shouldRunOnBoot()) { + return@Thread + } + GlobalProjectLauncher.launchOnBoot() + } catch (t: Throwable) { + Log.e(TAG, "Failed to launch script on boot action=$action", t) + } finally { + pendingResult.finish() + } + }.start() + } + + companion object { + private const val TAG = "InrtBootCompletedRcvr" + } +} diff --git a/app/src/main/java/org/autojs/autojs/inrt/InrtPackageReplacedReceiver.kt b/app/src/main/java/org/autojs/autojs/inrt/InrtPackageReplacedReceiver.kt new file mode 100644 index 00000000..e6b0af4c --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/inrt/InrtPackageReplacedReceiver.kt @@ -0,0 +1,26 @@ +package org.autojs.autojs.inrt + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import org.autojs.autojs.AbstractAutoJs + +/** + * Keep packaged app runtime launch configuration dominant after reinstall/update. + * 在重新安装/更新后保持打包应用运行时启动配置的优先级. + * + * Created by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) on Mar 9, 2026. + */ +class InrtPackageReplacedReceiver : BroadcastReceiver() { + + override fun onReceive(context: Context, intent: Intent?) { + if (!AbstractAutoJs.isInrt) { + return + } + if (intent?.action != Intent.ACTION_MY_PACKAGE_REPLACED) { + return + } + Pref.syncLaunchConfigWithBuild(force = true) + InrtShortcuts.syncToExplicitIntents() + } +} diff --git a/app/src/main/java/org/autojs/autojs/inrt/InrtShortcuts.kt b/app/src/main/java/org/autojs/autojs/inrt/InrtShortcuts.kt new file mode 100644 index 00000000..fc37f08f --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/inrt/InrtShortcuts.kt @@ -0,0 +1,59 @@ +package org.autojs.autojs.inrt + +import android.content.Intent +import android.content.pm.ShortcutInfo +import android.content.pm.ShortcutManager +import android.os.Build +import org.autojs.autojs.app.GlobalAppContext +import org.autojs.autojs6.R + +/** + * Created by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) on Mar 9, 2026. + */ +object InrtShortcuts { + + private const val ID_LOG = "id_inrt_launcher_shortcut_log" + private const val ID_SETTINGS = "id_inrt_launcher_shortcut_settings" + + @JvmStatic + fun syncToExplicitIntents() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) { + return + } + val context = GlobalAppContext.get() + val shortcutManager = context.getSystemService(ShortcutManager::class.java) ?: return + val packageName = context.packageName + + val shortcuts = listOf( + ShortcutInfo.Builder(context, ID_LOG) + .setShortLabel(context.getString(R.string.text_app_shortcut_log_short_label)) + .setLongLabel(context.getString(R.string.text_app_shortcut_log_short_label)) + .setIntent( + Intent(context, LogActivity::class.java) + .setAction("$packageName.action.INRT_SHORTCUT_LOG") + .setClass(context, LogActivity::class.java) + .setPackage(packageName) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) + ) + .build(), + ShortcutInfo.Builder(context, ID_SETTINGS) + .setShortLabel(context.getString(R.string.text_app_shortcut_settings_short_label)) + .setLongLabel(context.getString(R.string.text_app_shortcut_settings_short_label)) + .setIntent( + Intent(context, SettingsActivity::class.java) + .setAction("$packageName.action.INRT_SHORTCUT_SETTINGS") + .setClass(context, SettingsActivity::class.java) + .setPackage(packageName) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) + ) + .build(), + ) + + runCatching { + if (!shortcutManager.setDynamicShortcuts(shortcuts)) { + shortcutManager.removeDynamicShortcuts(listOf(ID_LOG, ID_SETTINGS)) + shortcutManager.addDynamicShortcuts(shortcuts) + } + } + } +} diff --git a/app/src/main/java/org/autojs/autojs/inrt/Pref.kt b/app/src/main/java/org/autojs/autojs/inrt/Pref.kt index af9ccb04..5b839bec 100644 --- a/app/src/main/java/org/autojs/autojs/inrt/Pref.kt +++ b/app/src/main/java/org/autojs/autojs/inrt/Pref.kt @@ -1,17 +1,21 @@ package org.autojs.autojs.inrt +import android.content.ComponentName import android.content.SharedPreferences +import android.content.pm.PackageManager import androidx.preference.PreferenceManager - +import org.autojs.autojs.project.ProjectConfig import org.autojs.autojs.app.GlobalAppContext import org.autojs.autojs6.R /** * Created by Stardust on Dec 8, 2017. + * Modified by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) as of Mar 9, 2026. */ object Pref { private const val KEY_FIRST_USING = "key_first_using" + private const val KEY_APPLIED_BUILD_ID = "key_inrt_applied_build_id" private var sPreferences: SharedPreferences? = null private val preferences: SharedPreferences @@ -47,4 +51,44 @@ object Pref { fun shouldStopAllScriptsWhenVolumeUp(): Boolean { return preferences.getBoolean(getString(R.string.key_use_volume_control_running), true) } + + fun shouldRunOnBoot(): Boolean { + return preferences.getBoolean(getString(R.string.key_run_on_boot_inrt), false) + } + + @JvmStatic + fun syncLaunchConfigWithBuild(force: Boolean = false) { + val context = GlobalAppContext.get() + val projectConfig = ProjectConfig.fromAssets(context, ProjectConfig.configFileOfDir("project")) ?: return + val launchConfig = projectConfig.launchConfig + val buildId = projectConfig.buildInfo.buildId.orEmpty() + val appliedBuildId = preferences.getString(KEY_APPLIED_BUILD_ID, null) + + val shouldApply = force || buildId != appliedBuildId + if (!shouldApply) { + return + } + + preferences.edit() + .putBoolean(getString(R.string.key_not_showing_main_activity), !launchConfig.isLogsVisible) + .putBoolean(getString(R.string.key_run_on_boot_inrt), launchConfig.isRunOnBoot) + .putString(KEY_APPLIED_BUILD_ID, buildId) + .apply() + + applyLauncherVisibility(launchConfig.isLauncherVisible) + } + + private fun applyLauncherVisibility(visible: Boolean) { + val state = if (visible) { + PackageManager.COMPONENT_ENABLED_STATE_ENABLED + } else { + PackageManager.COMPONENT_ENABLED_STATE_DISABLED + } + val context = GlobalAppContext.get() + context.packageManager.setComponentEnabledSetting( + ComponentName(context, SplashActivity::class.java), + state, + PackageManager.DONT_KILL_APP, + ) + } } diff --git a/app/src/main/java/org/autojs/autojs/inrt/SplashActivity.kt b/app/src/main/java/org/autojs/autojs/inrt/SplashActivity.kt index 485ac302..fd06fc0b 100644 --- a/app/src/main/java/org/autojs/autojs/inrt/SplashActivity.kt +++ b/app/src/main/java/org/autojs/autojs/inrt/SplashActivity.kt @@ -2,9 +2,12 @@ package org.autojs.autojs.inrt import android.Manifest.permission.WRITE_EXTERNAL_STORAGE import android.annotation.SuppressLint +import android.content.ComponentName import android.content.Intent +import android.content.pm.PackageManager import android.content.pm.PackageManager.PERMISSION_DENIED import android.graphics.Typeface +import android.os.Build import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity @@ -18,29 +21,50 @@ import org.autojs.autojs.inrt.autojs.AutoJs import org.autojs.autojs.inrt.launch.GlobalProjectLauncher import org.autojs.autojs.project.ProjectConfig import org.autojs.autojs.ui.splash.SplashActivity.Companion.INIT_TIMEOUT +import org.autojs.autojs6.R import org.autojs.autojs6.databinding.ActivitySplashInrtBinding /** * Created by Stardust on Feb 2, 2018. + * Modified by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) as of Mar 9, 2026. */ @SuppressLint("CustomSplashScreen") class SplashActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { - val binding = ActivitySplashInrtBinding.inflate(layoutInflater).apply { - setContentView(root) - } val projectConfig = ProjectConfig.fromAssets(this, ProjectConfig.configFileOfDir("project")) + val launchConfig = projectConfig.launchConfig + + val shouldHideMainPage = Pref.shouldHideLogs() || !launchConfig.isLogsVisible + val shouldShowSplash = launchConfig.isSplashVisible && !shouldHideMainPage + setTheme(if (shouldShowSplash) R.style.AppTheme_Splash else R.style.AppTheme_SevereTransparent) + + super.onCreate(savedInstanceState) + var timeout = INIT_TIMEOUT + applyLauncherVisibility(launchConfig.isLauncherVisible) + when { - !projectConfig.launchConfig.isSplashVisible -> { + !shouldShowSplash -> { timeout = 0L + window.setWindowAnimations(0) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + overrideActivityTransition(OVERRIDE_TRANSITION_OPEN, 0, 0) + } else { + @Suppress("DEPRECATION") + overridePendingTransition(0, 0) + } } else -> { + val binding = ActivitySplashInrtBinding.inflate(layoutInflater).apply { + setContentView(root) + } CoroutineScope(Dispatchers.Main).launch { binding.slug.typeface = Typeface.createFromAsset(assets, "roboto_medium.ttf") - binding.slug.isVisible = true + val slug = launchConfig.slug + binding.slug.text = slug + binding.slug.isVisible = slug.isNotBlank() binding.icon.isVisible = true } } @@ -51,7 +75,6 @@ class SplashActivity : AppCompatActivity() { } checkPermission(WRITE_EXTERNAL_STORAGE) } - super.onCreate(savedInstanceState) } private fun runScript() { @@ -89,6 +112,19 @@ class SplashActivity : AppCompatActivity() { list.toTypedArray() } + private fun applyLauncherVisibility(visible: Boolean) { + val state = if (visible) { + PackageManager.COMPONENT_ENABLED_STATE_ENABLED + } else { + PackageManager.COMPONENT_ENABLED_STATE_DISABLED + } + packageManager.setComponentEnabledSetting( + ComponentName(this, SplashActivity::class.java), + state, + PackageManager.DONT_KILL_APP, + ) + } + companion object { private const val PERMISSION_REQUEST_CODE = 11186 diff --git a/app/src/main/java/org/autojs/autojs/inrt/launch/AssetsProjectLauncher.kt b/app/src/main/java/org/autojs/autojs/inrt/launch/AssetsProjectLauncher.kt index 82715920..c3d3ecf7 100644 --- a/app/src/main/java/org/autojs/autojs/inrt/launch/AssetsProjectLauncher.kt +++ b/app/src/main/java/org/autojs/autojs/inrt/launch/AssetsProjectLauncher.kt @@ -3,6 +3,7 @@ package org.autojs.autojs.inrt.launch import android.app.Activity import android.content.Context import android.content.Intent +import android.os.Build import android.os.Handler import android.os.Looper import android.text.TextUtils @@ -25,12 +26,18 @@ import java.io.IOException * Created by Stardust on Jan 24, 2018. */ open class AssetsProjectLauncher(private val mAssetsProjectDir: String, private val mActivity: Context) { + private val mProjectDir: String = File(mActivity.filesDir, "project/").path private val mProjectConfig: ProjectConfig = ProjectConfig.fromAssets(mActivity, ProjectConfig.configFileOfDir(mAssetsProjectDir)) private val mMainScriptFile: File = File(mProjectDir, mProjectConfig.mainScriptFileName) private val mHandler: Handler = Handler(Looper.getMainLooper()) private var mScriptExecution: ScriptExecution? = null + // TODO by SuperMonster003 on Mar 9, 2026. + // ! 使其可配置. + // ! Make it configurable. + private val finishDelay = 200L // 2000L + init { prepare() } @@ -56,6 +63,10 @@ open class AssetsProjectLauncher(private val mAssetsProjectDir: String, private } } + fun launchOnBoot() { + runScript(null) + } + private fun runScript(activity: Activity?) { if (mScriptExecution != null && mScriptExecution!!.engine != null && !mScriptExecution!!.engine.isDestroyed @@ -68,7 +79,7 @@ open class AssetsProjectLauncher(private val mAssetsProjectDir: String, private if (source.executionMode and JavaScriptSource.EXECUTION_MODE_UI != 0) { config.intentFlags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME } else { - activity?.finish() + finishHostActivity(activity) } mScriptExecution = AutoJs.instance.scriptEngineService.execute(source, config) } catch (e: Exception) { @@ -76,6 +87,27 @@ open class AssetsProjectLauncher(private val mAssetsProjectDir: String, private } } + private fun finishHostActivity(activity: Activity?) { + val host = activity ?: return + val shouldDelayFinish = Pref.shouldHideLogs() || !mProjectConfig.launchConfig.isLogsVisible + if (!shouldDelayFinish) { + host.finish() + return + } + mHandler.postDelayed({ + if (host.isFinishing || host.isDestroyed) { + return@postDelayed + } + host.finish() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + host.overrideActivityTransition(Activity.OVERRIDE_TRANSITION_OPEN, 0, 0) + } else { + @Suppress("DEPRECATION") + host.overridePendingTransition(0, 0) + } + }, finishDelay) + } + private fun prepare() { val projectConfig = ProjectConfig.fromProjectDir(mProjectDir) if (projectConfig != null && @@ -106,7 +138,5 @@ open class AssetsProjectLauncher(private val mAssetsProjectDir: String, private } catch (e: Exception) { e.printStackTrace() } - } - } diff --git a/app/src/main/java/org/autojs/autojs/project/BuildInfo.java b/app/src/main/java/org/autojs/autojs/project/BuildInfo.java index 4e53e636..338dc168 100644 --- a/app/src/main/java/org/autojs/autojs/project/BuildInfo.java +++ b/app/src/main/java/org/autojs/autojs/project/BuildInfo.java @@ -1,12 +1,20 @@ package org.autojs.autojs.project; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import com.google.gson.annotations.SerializedName; import org.autojs.autojs.annotation.SerializedNameCompatible; import org.autojs.autojs.annotation.SerializedNameCompatible.With; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; import java.util.zip.CRC32; -public class BuildInfo { +/** + * Modified by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) as of Mar 9, 2026. + */ +public class BuildInfo implements FuzzyDeserializer.OriginalJsonKeyAware { @SerializedName(value = "id") @SerializedNameCompatible(with = {@With(value = "build_id", target = {"AutoJs4", "AutoX"})}) @@ -20,6 +28,8 @@ public class BuildInfo { @SerializedNameCompatible(with = {@With(value = "build_time", target = {"AutoJs4", "AutoX"})}) private long mBuildTime; + private final transient Map mOriginalJsonKeys = new LinkedHashMap<>(); + public String getBuildId() { return mBuildId; } @@ -57,4 +67,31 @@ public class BuildInfo { crc32.update((buildNumber + "" + buildTime).getBytes()); return String.format("%08X", crc32.getValue()) + "-" + buildNumber; } + + @Override + public void recordOriginalJsonKey(String canonicalKey, String originalKey) { + mOriginalJsonKeys.put(canonicalKey, originalKey); + } + + public void applyOriginalJsonKeys(JsonObject obj, boolean detectConflicts) { + for (Map.Entry entry : mOriginalJsonKeys.entrySet()) { + String canonicalKey = entry.getKey(); + String originalKey = entry.getValue(); + if (canonicalKey == null || originalKey == null || Objects.equals(canonicalKey, originalKey)) { + continue; + } + if (!obj.has(canonicalKey)) { + continue; + } + if (obj.has(originalKey)) { + if (detectConflicts) { + throw new IllegalStateException("Conflicting keys when serializing build: \"" + canonicalKey + "\" and \"" + originalKey + "\""); + } + obj.remove(canonicalKey); + continue; + } + JsonElement value = obj.remove(canonicalKey); + obj.add(originalKey, value); + } + } } diff --git a/app/src/main/java/org/autojs/autojs/project/LaunchConfig.kt b/app/src/main/java/org/autojs/autojs/project/LaunchConfig.kt index 3c7b14e2..e1fbefd3 100644 --- a/app/src/main/java/org/autojs/autojs/project/LaunchConfig.kt +++ b/app/src/main/java/org/autojs/autojs/project/LaunchConfig.kt @@ -1,20 +1,25 @@ package org.autojs.autojs.project +import com.google.gson.JsonObject import com.google.gson.annotations.SerializedName import org.autojs.autojs.annotation.SerializedNameCompatible import org.autojs.autojs.annotation.SerializedNameCompatible.With import org.autojs.autojs.app.GlobalAppContext import org.autojs.autojs6.R +import java.util.LinkedHashMap /** * Created by Stardust on Jan 25, 2018. - * Modified by SuperMonster003 as of Jan 15, 2025. * Created by SuperMonster003 on Jan 15, 2025. + * Modified by SuperMonster003 as of Mar 8, 2026. + * Modified by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) as of Mar 9, 2026. */ -class LaunchConfig { +class LaunchConfig : FuzzyDeserializer.OriginalJsonKeyAware { @Transient private val mContext = GlobalAppContext.get() + @Transient + private val mOriginalJsonKeys = LinkedHashMap() @SerializedName("logsVisible") @field:SerializedNameCompatible( @@ -40,6 +45,15 @@ class LaunchConfig { ) var isLauncherVisible = true + @SerializedName("runOnBoot") + @field:SerializedNameCompatible( + With(value = "bootRun"), + With(value = "autoRunOnBoot"), + With(value = "bootAutoStart"), + With(value = "autoStartOnBoot"), + ) + var isRunOnBoot = false + @SerializedName("slug") @field:SerializedNameCompatible( With(value = "slugText"), @@ -47,11 +61,35 @@ class LaunchConfig { ) var slug = mContext.getString(R.string.text_powered_by_autojs) - @SerializedName("permissions") - @field:SerializedNameCompatible( - With(value = "permission"), - With(value = "permissionList"), - ) - var permissions = emptyList() + // @SerializedName("permissions") + // @field:SerializedNameCompatible( + // With(value = "permission"), + // With(value = "permissionList"), + // ) + // var permissions = emptyList() + + override fun recordOriginalJsonKey(canonicalKey: String, originalKey: String) { + mOriginalJsonKeys[canonicalKey] = originalKey + } + + fun applyOriginalJsonKeys(json: JsonObject, detectConflicts: Boolean) { + mOriginalJsonKeys.forEach { (canonicalKey, originalKey) -> + if (canonicalKey == originalKey) { + return@forEach + } + if (!json.has(canonicalKey)) { + return@forEach + } + if (json.has(originalKey)) { + if (detectConflicts) { + throw IllegalStateException("Conflicting keys when serializing launchConfig: \"$canonicalKey\" and \"$originalKey\"") + } + json.remove(canonicalKey) + return@forEach + } + val value = json.remove(canonicalKey) + json.add(originalKey, value) + } + } } diff --git a/app/src/main/java/org/autojs/autojs/project/ProjectConfig.java b/app/src/main/java/org/autojs/autojs/project/ProjectConfig.java index 1b3d2885..1a1dda8f 100644 --- a/app/src/main/java/org/autojs/autojs/project/ProjectConfig.java +++ b/app/src/main/java/org/autojs/autojs/project/ProjectConfig.java @@ -43,6 +43,7 @@ import java.util.stream.Collectors; /** * Created by Stardust on Jan 24, 2018. * Modified by SuperMonster003 as of Jan 6, 2026. + * Modified by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) as of Mar 9, 2026. */ public class ProjectConfig implements FuzzyDeserializer.OriginalJsonKeyAware { @@ -54,7 +55,15 @@ public class ProjectConfig implements FuzzyDeserializer.OriginalJsonKeyAware { public static final List DEFAULT_PERMISSIONS = Arrays.asList( "android.permission.WAKE_LOCK", "android.permission.INTERNET", - "android.permission.WRITE_EXTERNAL_STORAGE" + "android.permission.READ_EXTERNAL_STORAGE", + "android.permission.WRITE_EXTERNAL_STORAGE", + "android.permission.MANAGE_EXTERNAL_STORAGE", + "android.permission.FOREGROUND_SERVICE", + "android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION", + "android.permission.FOREGROUND_SERVICE_SPECIAL_USE", + "android.permission.RECEIVE_BOOT_COMPLETED", + "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS", + "android.permission.SYSTEM_ALERT_WINDOW" ); private static final Gson sGson = new GsonBuilder() @@ -304,6 +313,12 @@ public class ProjectConfig implements FuzzyDeserializer.OriginalJsonKeyAware { Pattern launchConfigDisplaySplashPattern = Pattern.compile(booleanPatternWithKeyCapture("displaySplash"), Pattern.CASE_INSENSITIVE); Pattern launchConfigSplashVisiblePattern = Pattern.compile(booleanPatternWithKeyCapture("splashVisible"), Pattern.CASE_INSENSITIVE); + Pattern launchConfigDisplayLauncherPattern = Pattern.compile(booleanPatternWithKeyCapture("displayLauncher"), Pattern.CASE_INSENSITIVE); + Pattern launchConfigLauncherVisiblePattern = Pattern.compile(booleanPatternWithKeyCapture("launcherVisible"), Pattern.CASE_INSENSITIVE); + Pattern launchConfigAutoRunOnBootPattern = Pattern.compile(booleanPatternWithKeyCapture("autoRunOnBoot"), Pattern.CASE_INSENSITIVE); + Pattern launchConfigRunOnBootPattern = Pattern.compile(booleanPatternWithKeyCapture("runOnBoot"), Pattern.CASE_INSENSITIVE); + Pattern launchConfigSlugTextPattern = Pattern.compile(stringPatternWithKeyCapture("slugText"), Pattern.CASE_INSENSITIVE); + Pattern launchConfigSlugPattern = Pattern.compile(stringPatternWithKeyCapture("slug"), Pattern.CASE_INSENSITIVE); setFieldIfMatchesWithKey(namePattern, s, "name", projectConfig::setName, projectConfig, detectConflicts); setFieldIfMatchesWithKey(versionNamePattern, s, "versionName", projectConfig::setVersionName, projectConfig, detectConflicts); @@ -323,15 +338,21 @@ public class ProjectConfig implements FuzzyDeserializer.OriginalJsonKeyAware { setListIfMatchesWithKey(excludeDirsPattern, s, "excludeDirs", excludeDirs -> excludeDirs.forEach(projectConfig::excludeDir), projectConfig, detectConflicts); setListIfMatchesWithKey(excludedDirsPattern, s, "excludeDirs", excludedDirs -> excludedDirs.forEach(projectConfig::excludeDir), projectConfig, detectConflicts); - setFieldForDoubleIfMatchesWithKey(buildTimePattern, s, "buildTime", buildTime -> buildInfo.setBuildTime((long) buildTime), projectConfig, detectConflicts); - setFieldForDoubleIfMatchesWithKey(buildNumberPattern, s, "buildNumber", buildNumber -> buildInfo.setBuildNumber((long) buildNumber), projectConfig, detectConflicts); - setFieldIfMatchesWithKey(buildIdPattern, s, "buildId", buildInfo::setBuildId, projectConfig, detectConflicts); + setFieldForDoubleIfMatchesWithKey(buildTimePattern, s, "time", buildTime -> buildInfo.setBuildTime((long) buildTime), buildInfo, detectConflicts); + setFieldForDoubleIfMatchesWithKey(buildNumberPattern, s, "number", buildNumber -> buildInfo.setBuildNumber((long) buildNumber), buildInfo, detectConflicts); + setFieldIfMatchesWithKey(buildIdPattern, s, "id", buildInfo::setBuildId, buildInfo, detectConflicts); - setFieldForBooleanIfMatchesWithKey(launchConfigHideLogsPattern, s, "hideLogs", value -> launchConfig.setLogsVisible(!value), projectConfig, detectConflicts); - setFieldForBooleanIfMatchesWithKey(launchConfigLogsVisiblePattern, s, "logsVisible", launchConfig::setLogsVisible, projectConfig, detectConflicts); /* 优先. */ + setFieldForBooleanIfMatchesWithKey(launchConfigHideLogsPattern, s, "logsVisible", value -> launchConfig.setLogsVisible(!value), launchConfig, detectConflicts); + setFieldForBooleanIfMatchesWithKey(launchConfigLogsVisiblePattern, s, "logsVisible", launchConfig::setLogsVisible, launchConfig, detectConflicts); /* 优先. */ - setFieldForBooleanIfMatchesWithKey(launchConfigDisplaySplashPattern, s, "displaySplash", launchConfig::setSplashVisible, projectConfig, detectConflicts); - setFieldForBooleanIfMatchesWithKey(launchConfigSplashVisiblePattern, s, "splashVisible", launchConfig::setSplashVisible, projectConfig, detectConflicts); /* 优先. */ + setFieldForBooleanIfMatchesWithKey(launchConfigDisplaySplashPattern, s, "splashVisible", launchConfig::setSplashVisible, launchConfig, detectConflicts); + setFieldForBooleanIfMatchesWithKey(launchConfigSplashVisiblePattern, s, "splashVisible", launchConfig::setSplashVisible, launchConfig, detectConflicts); /* 优先. */ + setFieldForBooleanIfMatchesWithKey(launchConfigDisplayLauncherPattern, s, "launcherVisible", launchConfig::setLauncherVisible, launchConfig, detectConflicts); + setFieldForBooleanIfMatchesWithKey(launchConfigLauncherVisiblePattern, s, "launcherVisible", launchConfig::setLauncherVisible, launchConfig, detectConflicts); /* 优先. */ + setFieldForBooleanIfMatchesWithKey(launchConfigAutoRunOnBootPattern, s, "runOnBoot", launchConfig::setRunOnBoot, launchConfig, detectConflicts); + setFieldForBooleanIfMatchesWithKey(launchConfigRunOnBootPattern, s, "runOnBoot", launchConfig::setRunOnBoot, launchConfig, detectConflicts); /* 优先. */ + setFieldIfMatchesWithKey(launchConfigSlugTextPattern, s, "slug", launchConfig::setSlug, launchConfig, detectConflicts); + setFieldIfMatchesWithKey(launchConfigSlugPattern, s, "slug", launchConfig::setSlug, launchConfig, detectConflicts); /* 优先. */ if (projectConfig.getName() == null || projectConfig.getName().isBlank()) { if (jsonFilePath.endsWith(CONFIG_FILE_NAME)) { @@ -390,7 +411,7 @@ public class ProjectConfig implements FuzzyDeserializer.OriginalJsonKeyAware { String s, String canonicalKey, java.util.function.Consumer setter, - ProjectConfig recorder, + FuzzyDeserializer.OriginalJsonKeyAware recorder, boolean detectConflicts ) { Matcher matcher = pattern.matcher(s); @@ -415,7 +436,7 @@ public class ProjectConfig implements FuzzyDeserializer.OriginalJsonKeyAware { String s, String canonicalKey, java.util.function.DoubleConsumer setter, - ProjectConfig recorder, + FuzzyDeserializer.OriginalJsonKeyAware recorder, boolean detectConflicts ) { Matcher matcher = pattern.matcher(s); @@ -440,7 +461,7 @@ public class ProjectConfig implements FuzzyDeserializer.OriginalJsonKeyAware { String s, String canonicalKey, java.util.function.Consumer setter, - ProjectConfig recorder, + FuzzyDeserializer.OriginalJsonKeyAware recorder, boolean detectConflicts ) { Matcher matcher = pattern.matcher(s); @@ -465,7 +486,7 @@ public class ProjectConfig implements FuzzyDeserializer.OriginalJsonKeyAware { String s, String canonicalKey, java.util.function.Consumer> setter, - ProjectConfig recorder, + FuzzyDeserializer.OriginalJsonKeyAware recorder, boolean detectConflicts ) { Matcher matcher = pattern.matcher(s); @@ -689,9 +710,46 @@ public class ProjectConfig implements FuzzyDeserializer.OriginalJsonKeyAware { obj.add(originalKey, value); } + applyNestedOriginalKeys(obj, detectConflicts); + return sGson.toJson(obj); } + private void applyNestedOriginalKeys(@NonNull JsonObject root, boolean detectConflicts) { + applyNestedOriginalKeysForLaunchConfig(root, detectConflicts); + applyNestedOriginalKeysForBuildInfo(root, detectConflicts); + } + + private void applyNestedOriginalKeysForLaunchConfig(@NonNull JsonObject root, boolean detectConflicts) { + if (mLaunchConfig == null) { + return; + } + String key = resolveTopLevelJsonKey("launchConfig"); + JsonElement launchElement = root.get(key); + if (launchElement == null || !launchElement.isJsonObject()) { + return; + } + mLaunchConfig.applyOriginalJsonKeys(launchElement.getAsJsonObject(), detectConflicts); + } + + private void applyNestedOriginalKeysForBuildInfo(@NonNull JsonObject root, boolean detectConflicts) { + if (mBuildInfo == null) { + return; + } + String key = resolveTopLevelJsonKey("build"); + JsonElement buildElement = root.get(key); + if (buildElement == null || !buildElement.isJsonObject()) { + return; + } + mBuildInfo.applyOriginalJsonKeys(buildElement.getAsJsonObject(), detectConflicts); + } + + @NonNull + private String resolveTopLevelJsonKey(@NonNull String canonicalKey) { + String original = mOriginalJsonKeys.get(canonicalKey); + return original == null || original.isBlank() ? canonicalKey : original; + } + public String getIconPath() { return mIconPath; } diff --git a/app/src/main/java/org/autojs/autojs/ui/project/BuildActivity.java b/app/src/main/java/org/autojs/autojs/ui/project/BuildActivity.java index f04a60ad..920942ca 100644 --- a/app/src/main/java/org/autojs/autojs/ui/project/BuildActivity.java +++ b/app/src/main/java/org/autojs/autojs/ui/project/BuildActivity.java @@ -6,20 +6,27 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; import android.text.Editable; +import android.text.InputType; import android.text.TextUtils; +import android.text.TextWatcher; import android.text.util.Linkify; import android.util.Log; import android.view.Gravity; import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; +import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.PopupMenu; import android.widget.Spinner; import android.widget.TextView; import androidx.annotation.NonNull; @@ -42,6 +49,7 @@ import org.autojs.autojs.external.fileprovider.AppFileProvider; import org.autojs.autojs.model.explorer.Explorers; import org.autojs.autojs.model.script.ScriptFile; import org.autojs.autojs.pio.PFiles; +import org.autojs.autojs.project.LaunchConfig; import org.autojs.autojs.project.ProjectConfig; import org.autojs.autojs.runtime.api.AppUtils; import org.autojs.autojs.runtime.api.AppUtils.Companion.SimpleVersionInfo; @@ -56,6 +64,7 @@ import org.autojs.autojs.ui.main.scripts.ApkInfoDialogManager; import org.autojs.autojs.ui.shortcut.AppsIconSelectActivity; import org.autojs.autojs.ui.viewmodel.KeyStoreViewModel; import org.autojs.autojs.ui.widget.RoundCheckboxWithText; +import org.autojs.autojs.ui.widget.ToolbarMenuItem; import org.autojs.autojs.util.AndroidUtils; import org.autojs.autojs.util.AndroidUtils.Abi; import org.autojs.autojs.util.BitmapUtils; @@ -70,16 +79,24 @@ import org.autojs.autojs.util.WorkingDirectoryUtils; import org.autojs.autojs6.R; import org.autojs.autojs6.databinding.ActivityBuildBinding; import org.autojs.autojs6.databinding.DialogBuildProgressBinding; +import org.autojs.autojs6.databinding.FragmentSymbolsToolbarBinding; import org.jetbrains.annotations.NotNull; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -98,14 +115,18 @@ import static org.autojs.autojs.util.StringUtils.key; /** * Created by Stardust on Oct 22, 2017. * Modified by SuperMonster003 as of Jan 6, 2026. + * Modified by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) as of Mar 9, 2026. * * @noinspection ResultOfMethodCallIgnored, unused */ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCallback { private static final int REQUEST_CODE = 44401; + private static final int REQ_EXPORT_JSON = 44402; + private static final int REQ_IMPORT_JSON = 44403; public static final String EXTRA_SOURCE = BuildActivity.class.getName() + ".extra_source_file"; private static final String LOG_TAG = "BuildActivity"; + private static final int MAX_BUILD_UNDO_STACK = 120; private static final Pattern REGEX_PACKAGE_NAME = Pattern.compile("^([A-Za-z][A-Za-z\\d_]*\\.)+([A-Za-z][A-Za-z\\d_]*)$"); private static final ArrayList SUPPORTED_ABIS = new ArrayList<>() {{ @@ -229,6 +250,11 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa TextInputLayout mVersionCodeParentView; ImageView mIconView; LinearLayout mAppConfigView; + CheckBox mLaunchLogsVisibleView; + CheckBox mLaunchSplashVisibleView; + CheckBox mLaunchLauncherVisibleView; + CheckBox mLaunchRunOnBootView; + EditText mLaunchSlugView; @Nullable private ProjectConfig mProjectConfig; @@ -273,6 +299,39 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa private Spinner mVerifiedKeyStoresView; private FlexboxLayout mFlexboxPermissionsView; + private Spinner mBuildProfileSpinner; + private ImageView mIvBuildProfileNew; + private ImageView mIvBuildProfileDelete; + private ImageView mIvBuildProfileMore; + private ToolbarMenuItem mActionBuildUndo; + private ToolbarMenuItem mActionBuildRedo; + private ToolbarMenuItem mActionBuildSave; + + private final ArrayList mBuildProfileEntries = new ArrayList<>(); + private String mCurrentBuildProfileName = BuildConfigStore.PROFILE_DEFAULT_ID; + @NonNull + private BuildFieldPolicy mCurrentBuildFieldPolicy = BuildFieldPolicy.defaultPolicy(); + @NonNull + private BuildFieldPolicy mProjectJsonFieldPolicyInSession = BuildFieldPolicy.projectJsonPolicy(); + @Nullable + private BuildUiState mAutoBuildUiState; + + private final ArrayDeque mUndoStateStack = new ArrayDeque<>(); + private final ArrayDeque mRedoStateStack = new ArrayDeque<>(); + @Nullable + private BuildUiState mBaselineBuildUiState; + @Nullable + private BuildUiState mTrackedBuildUiState; + + private boolean mBuildConfigSaveSticky = false; + private boolean mBuildProfilesInitialized = false; + private boolean mApplyingBuildUiState = false; + private boolean mSuppressBuildProfileSpinnerCallback = false; + private boolean mSuppressBuildStateTracking = false; + private boolean mDeferBuildProfilesInitUntilSourceResolved = false; + @Nullable + private String mPendingKeyStorePathForStateApply; + private final ArrayList mInvalidAbis = new ArrayList<>(); private final ArrayList mUnavailableAbis = new ArrayList<>(); private final ArrayList mUnavailableStandardAbis = new ArrayList<>(); @@ -349,6 +408,18 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa mIconView.setOnClickListener(v -> selectIcon()); mAppConfigView = binding.appConfig; + mLaunchLogsVisibleView = binding.checkboxLaunchLogsVisible; + mLaunchSplashVisibleView = binding.checkboxLaunchSplashVisible; + mLaunchLauncherVisibleView = binding.checkboxLaunchLauncherVisible; + mLaunchRunOnBootView = binding.checkboxLaunchRunOnBoot; + mLaunchSlugView = binding.launchSlug; + + LaunchConfig defaultLaunchConfig = new LaunchConfig(); + mLaunchLogsVisibleView.setChecked(defaultLaunchConfig.isLogsVisible()); + mLaunchSplashVisibleView.setChecked(defaultLaunchConfig.isSplashVisible()); + mLaunchLauncherVisibleView.setChecked(defaultLaunchConfig.isLauncherVisible()); + mLaunchRunOnBootView.setChecked(defaultLaunchConfig.isRunOnBoot()); + mLaunchSlugView.setText(defaultLaunchConfig.getSlug()); mFlexboxAbisView = binding.flexboxAbis; initAbisChildren(); @@ -363,6 +434,15 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa mVerifiedKeyStoresView = binding.spinnerVerifiedKeyStores; mFlexboxPermissionsView = binding.flexboxPermissions; + mBuildProfileSpinner = binding.buildProfileSpinner; + mIvBuildProfileNew = binding.ivBuildProfileNew; + mIvBuildProfileDelete = binding.ivBuildProfileDelete; + mIvBuildProfileMore = binding.ivBuildProfileMore; + FragmentSymbolsToolbarBinding toolbarBinding = FragmentSymbolsToolbarBinding.inflate(getLayoutInflater(), binding.toolbarMenu, true); + mActionBuildUndo = toolbarBinding.actionUndo; + mActionBuildRedo = toolbarBinding.actionRedo; + mActionBuildSave = toolbarBinding.actionSave; + binding.fab.setOnClickListener(v -> buildApk()); ViewUtils.excludeFloatingActionButtonFromBottomNavigationBar(binding.fab); @@ -379,18 +459,44 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa binding.manageKeyStore.setOnClickListener(v -> ManageKeyStoreActivity.Companion.startActivity(this)); binding.textPermissions.setOnClickListener(v -> toggleAllFlexboxChildren(mFlexboxPermissionsView)); + mActionBuildUndo.setOnClickListener(v -> performBuildConfigUndo()); + mActionBuildRedo.setOnClickListener(v -> performBuildConfigRedo()); + mActionBuildSave.setOnClickListener(v -> saveCurrentBuildProfile()); + mActionBuildSave.setOnLongClickListener(v -> { + promptBuildFieldPolicyDialog(getCurrentBuildFieldPolicy(), false, selectedPolicy -> + promptCreateBuildProfileByName(captureCurrentBuildUiState(), selectedPolicy, null)); + return true; + }); + + mIvBuildProfileNew.setOnClickListener(v -> runWithUnsavedBuildConfigGuard(this::promptCreateBuildProfileWithBasePicker)); + mIvBuildProfileDelete.setOnClickListener(v -> runWithUnsavedBuildConfigGuard(this::promptDeleteBuildProfile)); + mIvBuildProfileMore.setOnClickListener(this::showBuildProfileMorePopup); + setToolbarAsBack(R.string.text_build_apk); mSource = getIntent().getStringExtra(EXTRA_SOURCE); if (mSource != null) { + mDeferBuildProfilesInitUntilSourceResolved = true; setupWithSourceFile(new ScriptFile(mSource)); } initSignatureSchemeSpinner(); initVerifiedKeyStoresSpinner(); initPermissionsChildren(); + attachBuildStateChangeListeners(); + updateBuildProfileActionButtons(); syncAbisCheckedStates(); syncLibsCheckedStates(); + if (mDeferBuildProfilesInitUntilSourceResolved + && mSource != null + && new File(mSource).isDirectory()) { + onSourcePresetReady(); + } + refreshAutoBuildUiStateSnapshot(); + + if (!mDeferBuildProfilesInitUntilSourceResolved) { + initBuildProfilesIfNeeded(); + } showHintDialogIfNeeded(); } @@ -401,42 +507,1206 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa mKeyStoreViewModel.updateVerifiedKeyStores(); } - private void toggleAllFlexboxChildren(FlexboxLayout mFlexboxLibs) { - boolean isAllChecked = true; - for (int i = 0; i < mFlexboxLibs.getChildCount(); i += 1) { - View child = mFlexboxLibs.getChildAt(i); - if (child instanceof RoundCheckboxWithText) { - if (!child.isEnabled()) { - continue; - } - if (!((RoundCheckboxWithText) child).isChecked()) { - isAllChecked = false; - break; - } - } else if (child instanceof CheckBox) { - if (!child.isEnabled()) { - continue; - } - if (!((CheckBox) child).isChecked()) { - isAllChecked = false; + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_build_profile_options, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if (item.getItemId() == R.id.action_import) { + runWithUnsavedBuildConfigGuard(this::startImportBuildProfileJson); + return true; + } + if (item.getItemId() == R.id.action_export) { + runWithUnsavedBuildConfigGuard(this::startExportBuildProfileJson); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void onPause() { + saveCurrentBuildProfileSilently(); + super.onPause(); + } + + @Override + public void finish() { + if (!mBuildProfilesInitialized || !mBuildConfigSaveSticky) { + super.finish(); + return; + } + runWithUnsavedBuildConfigGuard(() -> BuildActivity.super.finish()); + } + + private void onSourcePresetReady() { + refreshAutoBuildUiStateSnapshot(); + if (!mDeferBuildProfilesInitUntilSourceResolved) { + return; + } + mDeferBuildProfilesInitUntilSourceResolved = false; + initBuildProfilesIfNeeded(); + } + + private void initBuildProfilesIfNeeded() { + if (mBuildProfilesInitialized) { + return; + } + + BuildUiState fallback = getAutoBuildUiState(); + BuildConfigStore.ensureDefaultProfileExists(this, fallback.toJson(), BuildFieldPolicy.defaultPolicy().toJson()); + + mBuildProfilesInitialized = true; + String active = mIsProjectLevelBuilding + ? BuildConfigStore.PROFILE_PROJECT_JSON + : BuildConfigStore.getActiveProfileName(this); + rebuildBuildProfilesSpinnerAndSelect(active); + } + + private void rebuildBuildProfilesSpinnerAndSelect(@NonNull String internalName) { + ArrayList internalProfiles = new ArrayList<>(); + internalProfiles.add(BuildConfigStore.PROFILE_DEFAULT_ID); + if (mIsProjectLevelBuilding) { + internalProfiles.add(BuildConfigStore.PROFILE_PROJECT_JSON); + } + BuildConfigStore.listProfiles(this).forEach(name -> { + if (BuildConfigStore.PROFILE_DEFAULT_ID.equals(name)) return; + if (BuildConfigStore.PROFILE_PROJECT_JSON.equals(name)) return; + internalProfiles.add(name); + }); + + mBuildProfileEntries.clear(); + ArrayList displayNames = new ArrayList<>(internalProfiles.size()); + for (String internal : internalProfiles) { + String display = BuildConfigStore.PROFILE_DEFAULT_ID.equals(internal) + ? BuildConfigStore.getDefaultProfileDisplayName(this) + : internal; + mBuildProfileEntries.add(new ProfileEntry(internal, display)); + displayNames.add(display); + } + + ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, displayNames); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + + mSuppressBuildProfileSpinnerCallback = true; + mBuildProfileSpinner.setAdapter(adapter); + int index = 0; + for (int i = 0; i < mBuildProfileEntries.size(); i++) { + if (mBuildProfileEntries.get(i).internalName.equals(internalName)) { + index = i; + break; + } + } + if (mIsProjectLevelBuilding) { + for (int i = 0; i < mBuildProfileEntries.size(); i++) { + if (BuildConfigStore.PROFILE_PROJECT_JSON.equals(mBuildProfileEntries.get(i).internalName)) { + index = i; break; } } } - for (int i = 0; i < mFlexboxLibs.getChildCount(); i += 1) { - View child = mFlexboxLibs.getChildAt(i); - if (child instanceof RoundCheckboxWithText) { - if (!child.isEnabled()) { - continue; - } - ((RoundCheckboxWithText) child).setChecked(!isAllChecked); - } else if (child instanceof CheckBox) { - if (!child.isEnabled()) { - continue; - } - ((CheckBox) child).setChecked(!isAllChecked); + mBuildProfileSpinner.setSelection(index, false); + mSuppressBuildProfileSpinnerCallback = false; + + switchToBuildProfile(mBuildProfileEntries.get(index).internalName); + } + + private void reselectCurrentBuildProfileInSpinner() { + if (mBuildProfileEntries.isEmpty()) { + return; + } + int index = 0; + for (int i = 0; i < mBuildProfileEntries.size(); i++) { + if (mBuildProfileEntries.get(i).internalName.equals(mCurrentBuildProfileName)) { + index = i; + break; } } + mSuppressBuildProfileSpinnerCallback = true; + mBuildProfileSpinner.setSelection(index, false); + mSuppressBuildProfileSpinnerCallback = false; + } + + private void switchToBuildProfile(@NonNull String internalName) { + boolean isProjectJsonProfile = isProjectJsonProfile(internalName); + BuildUiState storedState; + BuildFieldPolicy fieldPolicy; + if (isProjectJsonProfile) { + storedState = buildUiStateFromProjectConfig(); + fieldPolicy = mProjectJsonFieldPolicyInSession.copy(); + } else { + BuildConfigStore.ProfilePayload payload = BuildConfigStore.loadProfilePayload(this, internalName); + storedState = payload == null + ? captureCurrentBuildUiState() + : BuildUiState.fromJson(payload.state); + fieldPolicy = payload == null + ? BuildFieldPolicy.defaultPolicy() + : BuildFieldPolicy.fromJson(payload.fields); + } + BuildUiState state = resolveBuildUiStateByFieldPolicy(storedState, getAutoBuildUiState(), fieldPolicy); + + mCurrentBuildProfileName = internalName; + mCurrentBuildFieldPolicy = fieldPolicy.copy(); + if (!mIsProjectLevelBuilding) { + BuildConfigStore.setActiveProfileName(this, internalName); + } + + applyBuildUiState(state); + + mUndoStateStack.clear(); + mRedoStateStack.clear(); + mTrackedBuildUiState = state.copy(); + mBaselineBuildUiState = state.copy(); + mBuildConfigSaveSticky = false; + updateBuildProfileActionButtons(); + } + + private void refreshAutoBuildUiStateSnapshot() { + mAutoBuildUiState = captureCurrentBuildUiState().copy(); + } + + @NonNull + private BuildUiState getAutoBuildUiState() { + return mAutoBuildUiState == null ? captureCurrentBuildUiState() : mAutoBuildUiState.copy(); + } + + @NonNull + private BuildFieldPolicy getCurrentBuildFieldPolicy() { + return mCurrentBuildFieldPolicy == null ? BuildFieldPolicy.defaultPolicy() : mCurrentBuildFieldPolicy.copy(); + } + + private boolean isProjectJsonProfile(@Nullable String internalName) { + return BuildConfigStore.PROFILE_PROJECT_JSON.equals(internalName); + } + + @NonNull + private BuildUiState buildUiStateFromProjectConfig() { + if (mProjectConfig == null) { + return captureCurrentBuildUiState(); + } + BuildUiState state = captureCurrentBuildUiState(); + String sourcePath = state.sourcePath == null ? "" : state.sourcePath.trim(); + if (TextUtils.isEmpty(sourcePath)) { + sourcePath = mSource == null ? "" : mSource; + } + state.sourcePath = sourcePath; + if (TextUtils.isEmpty(state.outputPath)) { + state.outputPath = new File(sourcePath, mProjectConfig.getBuildDir()).getPath(); + } + state.appName = Objects.requireNonNullElse(mProjectConfig.getName(), ""); + state.packageName = Objects.requireNonNullElse(mProjectConfig.getPackageName(), ""); + state.versionName = Objects.requireNonNullElse(mProjectConfig.getVersionName(), ""); + state.versionCode = String.valueOf(mProjectConfig.getVersionCode()); + state.signatureScheme = Objects.requireNonNullElse(mProjectConfig.getSignatureScheme(), ""); + LaunchConfig launchConfig = mProjectConfig.getLaunchConfig(); + if (launchConfig != null) { + state.launchLogsVisible = launchConfig.isLogsVisible(); + state.launchSplashVisible = launchConfig.isSplashVisible(); + state.launchLauncherVisible = launchConfig.isLauncherVisible(); + state.launchRunOnBoot = launchConfig.isRunOnBoot(); + state.launchSlug = Objects.requireNonNullElse(launchConfig.getSlug(), ""); + } + if (!mProjectConfig.getAbis().isEmpty()) { + state.abis = new ArrayList<>(mProjectConfig.getAbis()); + } + state.libs = new ArrayList<>(mProjectConfig.getLibs()); + state.permissions = new ArrayList<>(mProjectConfig.getPermissions()); + return state; + } + + @NonNull + private BuildUiState resolveBuildUiStateByFieldPolicy(@NonNull BuildUiState fixedState, @NonNull BuildUiState autoState, @NonNull BuildFieldPolicy policy) { + BuildUiState out = autoState.copy(); + if (policy.fixedSourcePath) out.sourcePath = fixedState.sourcePath; + if (policy.fixedOutputPath) out.outputPath = fixedState.outputPath; + if (policy.fixedAppName) out.appName = fixedState.appName; + if (policy.fixedPackageName) out.packageName = fixedState.packageName; + if (policy.fixedVersionName) out.versionName = fixedState.versionName; + if (policy.fixedVersionCode) out.versionCode = fixedState.versionCode; + if (policy.fixedLaunchLogsVisible) out.launchLogsVisible = fixedState.launchLogsVisible; + if (policy.fixedLaunchSplashVisible) out.launchSplashVisible = fixedState.launchSplashVisible; + if (policy.fixedLaunchLauncherVisible) out.launchLauncherVisible = fixedState.launchLauncherVisible; + if (policy.fixedLaunchRunOnBoot) out.launchRunOnBoot = fixedState.launchRunOnBoot; + if (policy.fixedLaunchSlug) out.launchSlug = fixedState.launchSlug; + if (policy.fixedAbis && !fixedState.abis.isEmpty()) out.abis = new ArrayList<>(fixedState.abis); + if (policy.fixedLibs) out.libs = new ArrayList<>(fixedState.libs); + if (policy.fixedSignatureScheme) out.signatureScheme = fixedState.signatureScheme; + if (policy.fixedKeyStore) out.keyStorePath = fixedState.keyStorePath; + if (policy.fixedPermissions) out.permissions = new ArrayList<>(fixedState.permissions); + return out; + } + + private void attachBuildStateChangeListeners() { + TextWatcher watcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + /* Ignored. */ + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + /* Ignored. */ + } + + @Override + public void afterTextChanged(Editable s) { + onBuildUiControlChanged(); + } + }; + + mSourcePathView.addTextChangedListener(watcher); + mOutputPathView.addTextChangedListener(watcher); + mAppNameView.addTextChangedListener(watcher); + mPackageNameView.addTextChangedListener(watcher); + mVersionNameView.addTextChangedListener(watcher); + mVersionCodeView.addTextChangedListener(watcher); + mLaunchSlugView.addTextChangedListener(watcher); + + mLaunchLogsVisibleView.setOnCheckedChangeListener((buttonView, isChecked) -> onBuildUiControlChanged()); + mLaunchSplashVisibleView.setOnCheckedChangeListener((buttonView, isChecked) -> onBuildUiControlChanged()); + mLaunchLauncherVisibleView.setOnCheckedChangeListener((buttonView, isChecked) -> onBuildUiControlChanged()); + mLaunchRunOnBootView.setOnCheckedChangeListener((buttonView, isChecked) -> onBuildUiControlChanged()); + + AdapterView.OnItemSelectedListener stateSpinnerListener = new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + onBuildUiControlChanged(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + /* Ignored. */ + } + }; + mSignatureSchemesView.setOnItemSelectedListener(stateSpinnerListener); + mVerifiedKeyStoresView.setOnItemSelectedListener(stateSpinnerListener); + + mBuildProfileSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + if (mSuppressBuildProfileSpinnerCallback) { + return; + } + if (position < 0 || position >= mBuildProfileEntries.size()) { + return; + } + String nextProfile = mBuildProfileEntries.get(position).internalName; + if (Objects.equals(nextProfile, mCurrentBuildProfileName)) { + return; + } + runWithUnsavedBuildConfigGuard(() -> switchToBuildProfile(nextProfile), BuildActivity.this::reselectCurrentBuildProfileInSpinner); + } + + @Override + public void onNothingSelected(AdapterView parent) { + /* Ignored. */ + } + }); + } + + private boolean canTrackBuildStateChanges() { + return mBuildProfilesInitialized + && !mApplyingBuildUiState + && !mSuppressBuildStateTracking; + } + + private void onBuildUiControlChanged() { + if (!canTrackBuildStateChanges()) { + return; + } + BuildUiState current = captureCurrentBuildUiState(); + if (mTrackedBuildUiState != null && current.equals(mTrackedBuildUiState)) { + return; + } + + if (mTrackedBuildUiState != null) { + mUndoStateStack.addLast(mTrackedBuildUiState.copy()); + while (mUndoStateStack.size() > MAX_BUILD_UNDO_STACK) { + mUndoStateStack.removeFirst(); + } + } + mTrackedBuildUiState = current.copy(); + mRedoStateStack.clear(); + + mBuildConfigSaveSticky = mBaselineBuildUiState == null || !current.equals(mBaselineBuildUiState); + updateBuildProfileActionButtons(); + } + + private void performBuildConfigUndo() { + if (mUndoStateStack.isEmpty()) { + return; + } + BuildUiState current = captureCurrentBuildUiState(); + BuildUiState target = mUndoStateStack.removeLast(); + mRedoStateStack.addLast(current.copy()); + + applyBuildUiState(target); + mTrackedBuildUiState = target.copy(); + mBuildConfigSaveSticky = mBaselineBuildUiState == null || !target.equals(mBaselineBuildUiState); + updateBuildProfileActionButtons(); + } + + private void performBuildConfigRedo() { + if (mRedoStateStack.isEmpty()) { + return; + } + BuildUiState current = captureCurrentBuildUiState(); + BuildUiState target = mRedoStateStack.removeLast(); + mUndoStateStack.addLast(current.copy()); + + applyBuildUiState(target); + mTrackedBuildUiState = target.copy(); + mBuildConfigSaveSticky = mBaselineBuildUiState == null || !target.equals(mBaselineBuildUiState); + updateBuildProfileActionButtons(); + } + + private void saveCurrentBuildProfile() { + saveCurrentBuildProfile(null); + } + + private void saveCurrentBuildProfile(@Nullable Runnable afterSaved) { + if (!mBuildProfilesInitialized || mCurrentBuildProfileName == null || mCurrentBuildProfileName.trim().isEmpty()) { + return; + } + if (!mBuildConfigSaveSticky && !BuildConfigStore.PROFILE_DEFAULT_ID.equals(mCurrentBuildProfileName)) { + if (afterSaved != null) { + afterSaved.run(); + } + return; + } + + BuildUiState current = captureCurrentBuildUiState(); + promptBuildFieldPolicyDialog(getCurrentBuildFieldPolicy(), selectedPolicy -> { + if (BuildConfigStore.PROFILE_DEFAULT_ID.equals(mCurrentBuildProfileName)) { + ViewUtils.showToast(this, R.string.text_default_profile_overwrite_hint, true); + promptCreateBuildProfileByName(current, selectedPolicy, afterSaved); + return; + } + if (isProjectJsonProfile(mCurrentBuildProfileName)) { + persistProjectJsonSnapshot(current, selectedPolicy, false); + if (afterSaved != null) { + afterSaved.run(); + } + return; + } + persistProfileSnapshot(mCurrentBuildProfileName, current, selectedPolicy, false); + if (afterSaved != null) { + afterSaved.run(); + } + }); + } + + private void saveCurrentBuildProfileSilently() { + if (!mBuildProfilesInitialized || mCurrentBuildProfileName == null || mCurrentBuildProfileName.trim().isEmpty()) { + return; + } + if (!mBuildConfigSaveSticky) { + return; + } + if (BuildConfigStore.PROFILE_DEFAULT_ID.equals(mCurrentBuildProfileName)) { + return; + } + if (isProjectJsonProfile(mCurrentBuildProfileName)) { + persistProjectJsonSnapshot(captureCurrentBuildUiState(), getCurrentBuildFieldPolicy(), true); + return; + } + persistProfileSnapshot(mCurrentBuildProfileName, captureCurrentBuildUiState(), getCurrentBuildFieldPolicy(), true); + } + + private void persistProfileSnapshot(@NonNull String profileName, @NonNull BuildUiState state, @NonNull BuildFieldPolicy fieldPolicy, boolean silent) { + BuildConfigStore.saveProfile(this, profileName, state.toJson(), fieldPolicy.toJson()); + mCurrentBuildFieldPolicy = fieldPolicy.copy(); + if (isProjectJsonProfile(profileName)) { + mProjectJsonFieldPolicyInSession = fieldPolicy.copy(); + } + mCurrentBuildProfileName = profileName; + BuildUiState current = captureCurrentBuildUiState(); + mBaselineBuildUiState = current.copy(); + mTrackedBuildUiState = current.copy(); + mBuildConfigSaveSticky = false; + updateBuildProfileActionButtons(); + if (!silent) { + ViewUtils.showToast(this, R.string.text_done); + } + } + + private void persistProjectJsonSnapshot(@NonNull BuildUiState state, @NonNull BuildFieldPolicy fieldPolicy, boolean silent) { + if (mProjectConfig == null) { + if (!silent) { + ViewUtils.showToast(this, R.string.text_failed_to_save_project_json, true); + } + return; + } + BuildUiState effectiveState = resolveBuildUiStateByFieldPolicy(state, getAutoBuildUiState(), fieldPolicy); + try { + ProjectConfig configToPersist = determineProjectConfig(effectiveState); + String sourcePath = configToPersist.getSourcePath(); + if (TextUtils.isEmpty(sourcePath)) { + throw new IllegalStateException("Source path is empty"); + } + mSource = sourcePath; + String projectConfigPath = ProjectConfig.configFileOfDir(sourcePath); + PFiles.write(projectConfigPath, configToPersist.toJson(true)); + + mProjectConfig = ProjectConfig.fromProjectDir(sourcePath); + if (mProjectConfig == null) { + mProjectConfig = configToPersist; + } + mProjectJsonFieldPolicyInSession = fieldPolicy.copy(); + mCurrentBuildFieldPolicy = fieldPolicy.copy(); + BuildUiState current = captureCurrentBuildUiState(); + mBaselineBuildUiState = current.copy(); + mTrackedBuildUiState = current.copy(); + mBuildConfigSaveSticky = false; + updateBuildProfileActionButtons(); + if (!silent) { + ViewUtils.showToast(this, R.string.text_done); + } + } catch (Throwable throwable) { + throwable.printStackTrace(); + if (!silent) { + ViewUtils.showToast(this, throwable.getMessage(), true); + } + } + } + + private void promptCreateBuildProfileWithBasePicker() { + BuildUiState baseState = captureCurrentBuildUiState(); + promptBuildFieldPolicyDialog(getCurrentBuildFieldPolicy(), false, selectedPolicy -> + promptCreateBuildProfileByName(baseState, selectedPolicy, null)); + } + + private void promptCreateBuildProfileByName(@NonNull BuildUiState baseState, @NonNull BuildFieldPolicy fieldPolicy, @Nullable Runnable afterCreated) { + MaterialDialog.Builder builder = new MaterialDialog.Builder(this) + .title(R.string.text_save_configuration_as) + .inputType(InputType.TYPE_CLASS_TEXT) + .input(getString(R.string.text_build_profile_name_hint), BuildConfigStore.getPrefillProfileName(this), false, (dialog, input) -> { + String raw = input == null ? "" : input.toString().trim(); + if (raw.isEmpty()) { + ViewUtils.showToast(this, R.string.text_symbols_profile_name_invalid, true); + return; + } + if (BuildConfigStore.isReservedProfileName(this, raw)) { + ViewUtils.showToast(this, R.string.text_build_profile_name_cannot_be_reserved, true); + return; + } + if (BuildConfigStore.listProfiles(this).contains(raw)) { + ViewUtils.showToast(this, R.string.text_symbols_profile_name_conflict, true); + return; + } + BuildConfigStore.saveProfile(this, raw, baseState.toJson(), fieldPolicy.toJson()); + if (!mIsProjectLevelBuilding) { + BuildConfigStore.setActiveProfileName(this, raw); + } + rebuildBuildProfilesSpinnerAndSelect(raw); + dialog.dismiss(); + ViewUtils.showToast(this, R.string.text_done); + if (afterCreated != null) { + afterCreated.run(); + } + }) + .negativeText(R.string.dialog_button_cancel) + .negativeColorRes(R.color.dialog_button_default) + .onNegative((dialog, which) -> dialog.dismiss()) + .positiveText(R.string.dialog_button_confirm) + .positiveColorRes(R.color.dialog_button_attraction) + .autoDismiss(false); + DialogUtils.widgetThemeColor(builder); + builder.show(); + } + + private void promptDeleteBuildProfile() { + if (BuildConfigStore.PROFILE_DEFAULT_ID.equals(mCurrentBuildProfileName)) { + ViewUtils.showToast(this, R.string.text_build_profile_cannot_delete_default, true); + return; + } + if (isProjectJsonProfile(mCurrentBuildProfileName)) { + ViewUtils.showToast(this, R.string.text_build_profile_cannot_delete_project_json, true); + return; + } + + String profileName = mCurrentBuildProfileName; + MaterialDialog.Builder builder = new MaterialDialog.Builder(this) + .title(R.string.text_prompt) + .content(getString(R.string.text_delete) + getString(R.string.symbol_colon_with_blank) + profileName) + .negativeText(R.string.dialog_button_cancel) + .negativeColorRes(R.color.dialog_button_default) + .onNegative((dialog, which) -> dialog.dismiss()) + .positiveText(R.string.dialog_button_confirm) + .positiveColorRes(R.color.dialog_button_caution) + .onPositive((dialog, which) -> { + BuildConfigStore.deleteProfile(this, profileName); + BuildConfigStore.ensureDefaultProfileExists(this, getAutoBuildUiState().toJson(), BuildFieldPolicy.defaultPolicy().toJson()); + rebuildBuildProfilesSpinnerAndSelect(BuildConfigStore.PROFILE_DEFAULT_ID); + dialog.dismiss(); + ViewUtils.showToast(this, R.string.text_done); + }) + .autoDismiss(false); + DialogUtils.widgetThemeColor(builder); + builder.show(); + } + + private void showBuildProfileMorePopup(View anchor) { + PopupMenu popupMenu = new PopupMenu(this, anchor); + popupMenu.getMenu().add(0, 1, 0, getString(R.string.text_save_configuration_as)); + popupMenu.getMenu().add(0, 2, 1, getString(R.string.text_rename)); + popupMenu.getMenu().add(0, 3, 2, getString(R.string.text_build_profile_fields_configure)); + popupMenu.setOnMenuItemClickListener(item -> { + if (item.getItemId() == 1) { + promptBuildFieldPolicyDialog(getCurrentBuildFieldPolicy(), false, selectedPolicy -> + promptCreateBuildProfileByName(captureCurrentBuildUiState(), selectedPolicy, null)); + return true; + } + if (item.getItemId() == 2) { + promptRenameCurrentBuildProfile(); + return true; + } + if (item.getItemId() == 3) { + promptEditCurrentBuildProfileFields(); + return true; + } + return false; + }); + popupMenu.show(); + } + + private void promptRenameCurrentBuildProfile() { + if (BuildConfigStore.PROFILE_DEFAULT_ID.equals(mCurrentBuildProfileName) + || isProjectJsonProfile(mCurrentBuildProfileName)) { + ViewUtils.showToast(this, R.string.text_build_profile_name_cannot_be_reserved, true); + return; + } + + String oldName = mCurrentBuildProfileName; + MaterialDialog.Builder builder = new MaterialDialog.Builder(this) + .title(R.string.text_rename) + .inputType(InputType.TYPE_CLASS_TEXT) + .input(getString(R.string.text_build_profile_name_hint), oldName, false, (dialog, input) -> { + String raw = input == null ? "" : input.toString().trim(); + if (raw.isEmpty()) { + ViewUtils.showToast(this, R.string.text_symbols_profile_name_invalid, true); + return; + } + if (BuildConfigStore.isReservedProfileName(this, raw)) { + ViewUtils.showToast(this, R.string.text_build_profile_name_cannot_be_reserved, true); + return; + } + if (Objects.equals(raw, oldName)) { + dialog.dismiss(); + return; + } + if (BuildConfigStore.listProfiles(this).contains(raw)) { + ViewUtils.showToast(this, R.string.text_symbols_profile_name_conflict, true); + return; + } + BuildConfigStore.ProfilePayload oldPayload = BuildConfigStore.loadProfilePayload(this, oldName); + JSONObject oldState = oldPayload == null ? captureCurrentBuildUiState().toJson() : oldPayload.state; + JSONObject oldFields = oldPayload == null ? getCurrentBuildFieldPolicy().toJson() : oldPayload.fields; + BuildConfigStore.saveProfile(this, raw, oldState, oldFields); + BuildConfigStore.deleteProfile(this, oldName); + if (!mIsProjectLevelBuilding) { + BuildConfigStore.setActiveProfileName(this, raw); + } + rebuildBuildProfilesSpinnerAndSelect(raw); + dialog.dismiss(); + ViewUtils.showToast(this, R.string.text_done); + }) + .negativeText(R.string.dialog_button_cancel) + .negativeColorRes(R.color.dialog_button_default) + .onNegative((dialog, which) -> dialog.dismiss()) + .positiveText(R.string.dialog_button_confirm) + .positiveColorRes(R.color.dialog_button_attraction) + .autoDismiss(false); + DialogUtils.widgetThemeColor(builder); + builder.show(); + } + + private void promptEditCurrentBuildProfileFields() { + BuildUiState current = captureCurrentBuildUiState(); + promptBuildFieldPolicyDialog(getCurrentBuildFieldPolicy(), selectedPolicy -> { + if (BuildConfigStore.PROFILE_DEFAULT_ID.equals(mCurrentBuildProfileName)) { + ViewUtils.showToast(this, R.string.text_default_profile_overwrite_hint, true); + promptCreateBuildProfileByName(current, selectedPolicy, null); + return; + } + if (isProjectJsonProfile(mCurrentBuildProfileName)) { + persistProjectJsonSnapshot(current, selectedPolicy, false); + return; + } + persistProfileSnapshot(mCurrentBuildProfileName, current, selectedPolicy, false); + }); + } + + private void promptBuildFieldPolicyDialog(@NonNull BuildFieldPolicy initialPolicy, @NonNull BuildFieldPolicySelectedCallback onSelected) { + promptBuildFieldPolicyDialog(initialPolicy, isProjectJsonProfile(mCurrentBuildProfileName), onSelected); + } + + private void promptBuildFieldPolicyDialog( + @NonNull BuildFieldPolicy initialPolicy, + boolean editableSourceAndIcon, + @NonNull BuildFieldPolicySelectedCallback onSelected + ) { + LinearLayout container = new LinearLayout(this); + container.setOrientation(LinearLayout.VERTICAL); + int horizontal = (int) (8 * getResources().getDisplayMetrics().density); + int vertical = (int) (4 * getResources().getDisplayMetrics().density); + container.setPadding(horizontal, vertical, horizontal, vertical); + + TextView hint = new TextView(this); + hint.setText(R.string.text_build_profile_fields_hint); + hint.setTextSize(13f); + hint.setPadding(0, 0, 0, (int) (6 * getResources().getDisplayMetrics().density)); + hint.setTextColor(getColor(R.color.text_color_primary_alpha_70)); + container.addView(hint); + + CheckBox icon = createFieldPolicyCheckBox(container, R.string.text_icon, initialPolicy.fixedIcon, editableSourceAndIcon); + addFieldPolicyDivider(container); + + CheckBox sourcePath = createFieldPolicyCheckBox(container, R.string.text_source_file_path, initialPolicy.fixedSourcePath, editableSourceAndIcon); + CheckBox outputPath = createFieldPolicyCheckBox(container, R.string.text_output_apk_path, initialPolicy.fixedOutputPath, true); + addFieldPolicyDivider(container); + + CheckBox appName = createFieldPolicyCheckBox(container, R.string.text_app_name, initialPolicy.fixedAppName, true); + CheckBox packageName = createFieldPolicyCheckBox(container, R.string.text_package_name, initialPolicy.fixedPackageName, true); + CheckBox versionName = createFieldPolicyCheckBox(container, R.string.text_version_name, initialPolicy.fixedVersionName, true); + CheckBox versionCode = createFieldPolicyCheckBox(container, R.string.text_version_code, initialPolicy.fixedVersionCode, true); + addFieldPolicyDivider(container); + + CheckBox launchRunOnBoot = createFieldPolicyCheckBox(container, R.string.text_launch_run_on_boot, initialPolicy.fixedLaunchRunOnBoot, true); + CheckBox launchLogsVisible = createFieldPolicyCheckBox(container, R.string.text_launch_logs_visible, initialPolicy.fixedLaunchLogsVisible, true); + CheckBox launchSplashVisible = createFieldPolicyCheckBox(container, R.string.text_launch_splash_visible, initialPolicy.fixedLaunchSplashVisible, true); + CheckBox launchLauncherVisible = createFieldPolicyCheckBox(container, R.string.text_launch_launcher_visible, initialPolicy.fixedLaunchLauncherVisible, true); + CheckBox launchSlug = createFieldPolicyCheckBox(container, R.string.text_launch_slug, initialPolicy.fixedLaunchSlug, true); + addFieldPolicyDivider(container); + + CheckBox abis = createFieldPolicyCheckBox(container, R.string.text_supported_abis_short, initialPolicy.fixedAbis, true); + CheckBox libs = createFieldPolicyCheckBox(container, R.string.text_supported_libraries_short, initialPolicy.fixedLibs, true); + CheckBox signatureScheme = createFieldPolicyCheckBox(container, R.string.text_signature_scheme, initialPolicy.fixedSignatureScheme, true); + CheckBox keyStore = createFieldPolicyCheckBox(container, R.string.text_key_store, initialPolicy.fixedKeyStore, true); + CheckBox permissions = createFieldPolicyCheckBox(container, R.string.text_supported_permissions_short, initialPolicy.fixedPermissions, true); + + MaterialDialog.Builder builder = new MaterialDialog.Builder(this) + .title(R.string.text_build_profile_fields) + .customView(container, true) + .positiveText(R.string.dialog_button_confirm) + .positiveColorRes(R.color.dialog_button_attraction) + .negativeText(R.string.dialog_button_cancel) + .negativeColorRes(R.color.dialog_button_default) + .onPositive((dialog, which) -> { + BuildFieldPolicy selected = new BuildFieldPolicy(); + selected.fixedSourcePath = sourcePath.isChecked(); + selected.fixedIcon = icon.isChecked(); + selected.fixedOutputPath = outputPath.isChecked(); + selected.fixedAppName = appName.isChecked(); + selected.fixedPackageName = packageName.isChecked(); + selected.fixedVersionName = versionName.isChecked(); + selected.fixedVersionCode = versionCode.isChecked(); + selected.fixedLaunchRunOnBoot = launchRunOnBoot.isChecked(); + selected.fixedLaunchLogsVisible = launchLogsVisible.isChecked(); + selected.fixedLaunchSplashVisible = launchSplashVisible.isChecked(); + selected.fixedLaunchLauncherVisible = launchLauncherVisible.isChecked(); + selected.fixedLaunchSlug = launchSlug.isChecked(); + selected.fixedAbis = abis.isChecked(); + selected.fixedLibs = libs.isChecked(); + selected.fixedSignatureScheme = signatureScheme.isChecked(); + selected.fixedKeyStore = keyStore.isChecked(); + selected.fixedPermissions = permissions.isChecked(); + onSelected.onSelected(selected); + }); + DialogUtils.widgetThemeColor(builder); + builder.show(); + } + + @NonNull + private CheckBox createFieldPolicyCheckBox(@NonNull LinearLayout container, int textRes, boolean checked, boolean enabled) { + CheckBox checkBox = new CheckBox(this); + checkBox.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + )); + checkBox.setText(textRes); + checkBox.setChecked(checked); + checkBox.setEnabled(enabled); + if (!enabled) { + checkBox.setAlpha(0.62f); + } + container.addView(checkBox); + return checkBox; + } + + private void addFieldPolicyDivider(@NonNull LinearLayout container) { + View divider = new View(this); + LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + Math.max(1, (int) (getResources().getDisplayMetrics().density)) + ); + int marginV = (int) (4 * getResources().getDisplayMetrics().density); + lp.setMargins(0, marginV, 0, marginV); + divider.setLayoutParams(lp); + divider.setBackgroundColor(getColor(android.R.color.darker_gray)); + container.addView(divider); + } + + private interface BuildFieldPolicySelectedCallback { + void onSelected(@NonNull BuildFieldPolicy selectedPolicy); + } + + private void runWithUnsavedBuildConfigGuard(@NonNull Runnable onProceed) { + runWithUnsavedBuildConfigGuard(onProceed, null); + } + + private void runWithUnsavedBuildConfigGuard(@NonNull Runnable onProceed, @Nullable Runnable onCancel) { + if (!mBuildConfigSaveSticky) { + onProceed.run(); + return; + } + + int unsavedChangesTextRes = isProjectJsonProfile(mCurrentBuildProfileName) + ? R.string.text_build_profile_unsaved_changes_project_json + : R.string.text_build_profile_unsaved_changes; + + DialogUtils.buildAndShowAdaptive(() -> { + MaterialDialog.Builder builder = new MaterialDialog.Builder(this) + .title(R.string.text_prompt) + .content(unsavedChangesTextRes) + .neutralText(R.string.dialog_button_back) + .neutralColorRes(R.color.dialog_button_default) + .negativeText(R.string.text_exit_directly) + .negativeColorRes(R.color.dialog_button_caution) + .positiveText(R.string.text_save_and_exit) + .positiveColorRes(R.color.dialog_button_warn) + .onPositive((dialog, which) -> { + saveCurrentBuildProfile(onProceed); + }) + .onNeutral((dialog, which) -> onProceed.run()) + .onNegative((dialog, which) -> { + if (onCancel != null) { + onCancel.run(); + } + }); + DialogUtils.widgetThemeColor(builder); + return builder.build(); + }); + } + + @SuppressWarnings("deprecation") + private void startExportBuildProfileJson() { + String name = mCurrentBuildProfileName; + if (name == null || name.trim().isEmpty() || BuildConfigStore.PROFILE_DEFAULT_ID.equals(name)) { + name = "default"; + } + Intent i = new Intent(Intent.ACTION_CREATE_DOCUMENT); + i.addCategory(Intent.CATEGORY_OPENABLE); + i.setType("application/json"); + i.putExtra(Intent.EXTRA_TITLE, "autojs6-build-profile-" + name + ".json"); + startActivityForResult(i, REQ_EXPORT_JSON); + } + + @SuppressWarnings("deprecation") + private void startImportBuildProfileJson() { + Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT); + i.addCategory(Intent.CATEGORY_OPENABLE); + i.setType("application/json"); + startActivityForResult(i, REQ_IMPORT_JSON); + } + + private void doExportBuildProfileToUri(@NonNull Uri uri) { + try { + JSONObject json; + if (isProjectJsonProfile(mCurrentBuildProfileName)) { + json = new JSONObject(); + json.put("name", BuildConfigStore.PROFILE_PROJECT_JSON); + json.put("state", captureCurrentBuildUiState().toJson()); + json.put("fields", getCurrentBuildFieldPolicy().toJson()); + } else { + json = BuildConfigStore.exportProfileToJson(this, mCurrentBuildProfileName); + } + try (var out = getContentResolver().openOutputStream(uri, "wt")) { + if (out == null) throw new IllegalStateException("Cannot open output stream"); + out.write(json.toString(2).getBytes(StandardCharsets.UTF_8)); + out.flush(); + } + ViewUtils.showToast(this, R.string.text_done); + } catch (Throwable e) { + e.printStackTrace(); + ViewUtils.showToast(this, e.getMessage(), true); + } + } + + private void doImportBuildProfileFromUri(@NonNull Uri uri) { + try { + byte[] raw; + try (InputStream in = getContentResolver().openInputStream(uri)) { + if (in == null) throw new IllegalStateException("Cannot open input stream"); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + byte[] chunk = new byte[8 * 1024]; + int read; + while ((read = in.read(chunk)) != -1) { + buffer.write(chunk, 0, read); + } + raw = buffer.toByteArray(); + } + JSONObject json = new JSONObject(new String(raw, StandardCharsets.UTF_8)); + BuildConfigStore.ProfilePayload payload = BuildConfigStore.importProfileFromJson(json); + + boolean reservedName = BuildConfigStore.isReservedProfileName(this, payload.name); + if (reservedName) { + handleImportNameConflictAndSave(payload.name, payload, false, true); + return; + } + handleImportNameConflictAndSave(payload.name, payload, true, false); + } catch (Throwable e) { + e.printStackTrace(); + ViewUtils.showToast(this, e.getMessage(), true); + } + } + + private void handleImportNameConflictAndSave( + @NonNull String desiredName, + @NonNull BuildConfigStore.ProfilePayload importedPayload, + boolean overwriteEnabled, + boolean forceConflict + ) { + LinkedHashSet existing = new LinkedHashSet<>(BuildConfigStore.listProfiles(this)); + boolean conflict = forceConflict || existing.contains(desiredName); + + if (!conflict) { + saveImportedProfileAndSwitch(desiredName, importedPayload); + return; + } + + ArrayList options = new ArrayList<>(); + options.add(getString(R.string.text_import_strategy_overwrite)); + options.add(getString(R.string.text_import_strategy_auto_rename)); + options.add(getString(R.string.text_import_strategy_manual_rename)); + + MaterialDialog.Builder builder = new MaterialDialog.Builder(this) + .title(R.string.text_import) + .content(getString(R.string.text_import_name_conflict, desiredName)) + .items(options) + .itemsCallback((dialog, itemView, which, text) -> { + dialog.dismiss(); + if (which == 0) { + if (!overwriteEnabled) return; + saveImportedProfileAndSwitch(desiredName, importedPayload); + return; + } + if (which == 1) { + String unique = makeUniqueProfileName(existing, desiredName); + saveImportedProfileAndSwitch(unique, importedPayload); + return; + } + if (which == 2) { + promptManualRenameAndImport(existing, desiredName, importedPayload); + } + }); + if (!overwriteEnabled) { + builder.itemsDisabledIndices(0); + } + DialogUtils.widgetThemeColor(builder); + builder.show(); + } + + private void promptManualRenameAndImport( + @NonNull LinkedHashSet existing, + @NonNull String suggestedName, + @NonNull BuildConfigStore.ProfilePayload payload + ) { + MaterialDialog.Builder builder = new MaterialDialog.Builder(this) + .title(R.string.text_import_strategy_manual_rename) + .inputType(InputType.TYPE_CLASS_TEXT) + .input(getString(R.string.text_build_profile_name_hint), suggestedName, false, (dialog, input) -> { + String raw = input == null ? "" : input.toString().trim(); + if (raw.isEmpty()) { + ViewUtils.showToast(this, R.string.text_symbols_profile_name_invalid, true); + return; + } + if (BuildConfigStore.isReservedProfileName(this, raw)) { + ViewUtils.showToast(this, R.string.text_build_profile_name_cannot_be_reserved, true); + return; + } + if (existing.contains(raw)) { + ViewUtils.showToast(this, R.string.text_symbols_profile_name_conflict, true); + return; + } + saveImportedProfileAndSwitch(raw, payload); + dialog.dismiss(); + }) + .negativeText(R.string.dialog_button_cancel) + .negativeColorRes(R.color.dialog_button_default) + .onNegative((dialog, which) -> dialog.dismiss()) + .positiveText(R.string.dialog_button_confirm) + .positiveColorRes(R.color.dialog_button_attraction) + .autoDismiss(false); + DialogUtils.widgetThemeColor(builder); + builder.show(); + } + + @NonNull + private String makeUniqueProfileName(@NonNull LinkedHashSet existing, @NonNull String baseName) { + if (!existing.contains(baseName) && !BuildConfigStore.isReservedProfileName(this, baseName)) return baseName; + int i = 2; + while (true) { + String candidate = baseName + " (" + i + ")"; + if (!existing.contains(candidate) && !BuildConfigStore.isReservedProfileName(this, candidate)) { + return candidate; + } + i++; + } + } + + private void saveImportedProfileAndSwitch(@NonNull String name, @NonNull BuildConfigStore.ProfilePayload payload) { + BuildConfigStore.saveProfile(this, name, payload.state, payload.fields); + if (!mIsProjectLevelBuilding) { + BuildConfigStore.setActiveProfileName(this, name); + } + rebuildBuildProfilesSpinnerAndSelect(name); + ViewUtils.showToast(this, R.string.text_done); + } + + private void updateBuildProfileActionButtons() { + setBuildActionEnabled(mActionBuildUndo, !mUndoStateStack.isEmpty()); + setBuildActionEnabled(mActionBuildRedo, !mRedoStateStack.isEmpty()); + setBuildActionEnabled(mActionBuildSave, mBuildConfigSaveSticky); + setBuildActionEnabled( + mIvBuildProfileDelete, + mBuildProfilesInitialized + && !BuildConfigStore.PROFILE_DEFAULT_ID.equals(mCurrentBuildProfileName) + && !isProjectJsonProfile(mCurrentBuildProfileName) + ); + } + + private void setBuildActionEnabled(@Nullable View view, boolean enabled) { + if (view == null) return; + view.setEnabled(enabled); + if (view instanceof ImageView) { + view.setAlpha(enabled ? 1.0f : 0.45f); + } + } + + private void applyBuildUiState(@NonNull BuildUiState state) { + boolean previousApplying = mApplyingBuildUiState; + boolean previousSuppress = mSuppressBuildStateTracking; + mApplyingBuildUiState = true; + mSuppressBuildStateTracking = true; + try { + setTextIfChanged(mSourcePathView, state.sourcePath); + setTextIfChanged(mOutputPathView, state.outputPath); + setTextIfChanged(mAppNameView, state.appName); + setTextIfChanged(mPackageNameView, state.packageName); + setTextIfChanged(mVersionNameView, state.versionName); + setTextIfChanged(mVersionCodeView, state.versionCode); + setCheckedIfChanged(mLaunchLogsVisibleView, state.launchLogsVisible); + setCheckedIfChanged(mLaunchSplashVisibleView, state.launchSplashVisible); + setCheckedIfChanged(mLaunchLauncherVisibleView, state.launchLauncherVisible); + setCheckedIfChanged(mLaunchRunOnBootView, state.launchRunOnBoot); + setTextIfChanged(mLaunchSlugView, state.launchSlug); + + applyStringSelectionsToFlexbox(mFlexboxAbisView, state.abis); + applyStringSelectionsToFlexbox(mFlexboxLibsView, state.libs); + applyStringSelectionsToFlexbox(mFlexboxPermissionsView, state.permissions); + + setSignatureSchemeByLabel(state.signatureScheme); + mPendingKeyStorePathForStateApply = state.keyStorePath; + tryApplyPendingKeyStorePathSelection(); + } finally { + mApplyingBuildUiState = previousApplying; + mSuppressBuildStateTracking = previousSuppress; + } + } + + private void setTextIfChanged(@NonNull EditText editText, @Nullable String value) { + String target = value == null ? "" : value; + String current = editText.getText() == null ? "" : editText.getText().toString(); + if (!Objects.equals(current, target)) { + editText.setText(target); + } + } + + private void setCheckedIfChanged(@NonNull CheckBox checkBox, boolean checked) { + if (checkBox.isChecked() != checked) { + checkBox.setChecked(checked); + } + } + + private void applyStringSelectionsToFlexbox(@NonNull FlexboxLayout flexboxLayout, @NonNull List selectedValues) { + LinkedHashSet normalized = selectedValues.stream() + .map(v -> v == null ? "" : v.trim().toLowerCase(Locale.ROOT)) + .filter(v -> !v.isEmpty()) + .collect(Collectors.toCollection(LinkedHashSet::new)); + + for (int i = 0; i < flexboxLayout.getChildCount(); i++) { + View child = flexboxLayout.getChildAt(i); + String label = parseWidgetLabel(child); + if (label == null) continue; + boolean checked = normalized.contains(label.trim().toLowerCase(Locale.ROOT)); + if (child instanceof RoundCheckboxWithText) { + ((RoundCheckboxWithText) child).setChecked(checked); + } else if (child instanceof CheckBox) { + ((CheckBox) child).setChecked(checked); + } + } + } + + @Nullable + private String parseWidgetLabel(@NonNull View child) { + CharSequence text = null; + if (child instanceof RoundCheckboxWithText) { + text = ((RoundCheckboxWithText) child).getText(); + } else if (child instanceof CheckBox) { + text = ((CheckBox) child).getText(); + } + if (text == null) return null; + return text.toString().split("\n")[0].trim(); + } + + private void setSignatureSchemeByLabel(@Nullable String rawLabel) { + if (rawLabel == null || rawLabel.trim().isEmpty()) { + return; + } + String target = rawLabel.trim(); + int index = -1; + for (int i = 0; i < SIGNATURE_SCHEMES.size(); i++) { + String standard = SIGNATURE_SCHEMES.get(i).first; + if (standard.equalsIgnoreCase(target)) { + index = i; + break; + } + } + if (index < 0) { + String normalized = normalizeSignatureSchemeLabel(target); + for (int i = 0; i < SIGNATURE_SCHEMES.size(); i++) { + String standard = SIGNATURE_SCHEMES.get(i).first; + if (standard.equalsIgnoreCase(normalized)) { + index = i; + break; + } + } + } + if (index >= 0 && mSignatureSchemesView.getSelectedItemPosition() != index) { + mSignatureSchemesView.setSelection(index); + } + } + + private void tryApplyPendingKeyStorePathSelection() { + if (mVerifiedKeyStoresView == null) return; + String pendingPath = mPendingKeyStorePathForStateApply; + if (pendingPath == null) return; + + if (pendingPath.trim().isEmpty()) { + mVerifiedKeyStoresView.setSelection(0); + mPendingKeyStorePathForStateApply = null; + return; + } + + for (int i = 1; i < mVerifiedKeyStoresView.getCount(); i++) { + Object item = mVerifiedKeyStoresView.getItemAtPosition(i); + if (!(item instanceof KeyStore)) continue; + KeyStore keyStore = (KeyStore) item; + if (pendingPath.equalsIgnoreCase(keyStore.getAbsolutePath())) { + mVerifiedKeyStoresView.setSelection(i); + mPendingKeyStorePathForStateApply = null; + return; + } + } + } + + @NonNull + private BuildUiState captureCurrentBuildUiState() { + BuildUiState state = new BuildUiState(); + state.sourcePath = mSourcePathView.getText() == null ? "" : mSourcePathView.getText().toString(); + state.outputPath = mOutputPathView.getText() == null ? "" : mOutputPathView.getText().toString(); + state.appName = mAppNameView.getText() == null ? "" : mAppNameView.getText().toString(); + state.packageName = mPackageNameView.getText() == null ? "" : mPackageNameView.getText().toString(); + state.versionName = mVersionNameView.getText() == null ? "" : mVersionNameView.getText().toString(); + state.versionCode = mVersionCodeView.getText() == null ? "" : mVersionCodeView.getText().toString(); + state.launchLogsVisible = mLaunchLogsVisibleView.isChecked(); + state.launchSplashVisible = mLaunchSplashVisibleView.isChecked(); + state.launchLauncherVisible = mLaunchLauncherVisibleView.isChecked(); + state.launchRunOnBoot = mLaunchRunOnBootView.isChecked(); + state.launchSlug = mLaunchSlugView.getText() == null ? "" : mLaunchSlugView.getText().toString(); + state.abis = collectCheckedItems(mFlexboxAbisView); + state.libs = collectCheckedItems(mFlexboxLibsView); + state.permissions = collectCheckedItems(mFlexboxPermissionsView); + state.signatureScheme = normalizeSignatureSchemeLabel( + mSignatureSchemesView.getSelectedItem() == null ? "" : mSignatureSchemesView.getSelectedItem().toString() + ); + if (mVerifiedKeyStoresView.getSelectedItemPosition() > 0) { + Object selected = mVerifiedKeyStoresView.getSelectedItem(); + if (selected instanceof KeyStore) { + state.keyStorePath = ((KeyStore) selected).getAbsolutePath(); + } + } + return state; + } + + @NonNull + private String normalizeSignatureSchemeLabel(@Nullable String raw) { + if (raw == null) return ""; + String value = raw.trim(); + if (value.isEmpty()) return value; + int index = value.indexOf(" ("); + if (index > 0) { + return value.substring(0, index).trim(); + } + int selectedIndex = mSignatureSchemesView == null ? -1 : mSignatureSchemesView.getSelectedItemPosition(); + if (selectedIndex >= 0 && selectedIndex < SIGNATURE_SCHEMES.size()) { + return SIGNATURE_SCHEMES.get(selectedIndex).first; + } + return value; + } + + private void toggleAllFlexboxChildren(FlexboxLayout mFlexboxLibs) { + boolean shouldTrack = canTrackBuildStateChanges(); + boolean previousSuppress = mSuppressBuildStateTracking; + if (shouldTrack) { + mSuppressBuildStateTracking = true; + } + + boolean isAllChecked = true; + try { + for (int i = 0; i < mFlexboxLibs.getChildCount(); i += 1) { + View child = mFlexboxLibs.getChildAt(i); + if (child instanceof RoundCheckboxWithText) { + if (!child.isEnabled()) { + continue; + } + if (!((RoundCheckboxWithText) child).isChecked()) { + isAllChecked = false; + break; + } + } else if (child instanceof CheckBox) { + if (!child.isEnabled()) { + continue; + } + if (!((CheckBox) child).isChecked()) { + isAllChecked = false; + break; + } + } + } + for (int i = 0; i < mFlexboxLibs.getChildCount(); i += 1) { + View child = mFlexboxLibs.getChildAt(i); + if (child instanceof RoundCheckboxWithText) { + if (!child.isEnabled()) { + continue; + } + ((RoundCheckboxWithText) child).setChecked(!isAllChecked); + } else if (child instanceof CheckBox) { + if (!child.isEnabled()) { + continue; + } + ((CheckBox) child).setChecked(!isAllChecked); + } + } + } finally { + mSuppressBuildStateTracking = previousSuppress; + } + if (shouldTrack) { + onBuildUiControlChanged(); + } } private void initAbisChildren() { @@ -445,6 +1715,7 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa child.setText(abiText); child.setChecked(false); child.setEnabled(false); + child.setOnCheckedChangeListener((buttonView, isChecked) -> onBuildUiControlChanged()); child.setOnBeingUnavailableListener(this::promptForUnavailability); mFlexboxAbisView.addView(child); }); @@ -457,10 +1728,10 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa NotAskAgainDialog.Builder builder = new NotAskAgainDialog.Builder(context, key); builder.title(R.string.text_prompt); builder.content(getString(R.string.text_unable_to_build_apk_as_autojs6_does_not_include_selected_abi, abiText) + "\n\n" + - getString(R.string.text_the_following_solutions_can_be_referred_to) + ":\n\n" + + getString(R.string.text_the_following_solutions_can_be_referred_to) + getString(R.string.symbol_colon_with_blank) + "\n\n" + "- " + getString(R.string.text_download_and_install_autojs6_including_above_abi, abiText) + "\n" + "- " + getString(R.string.text_download_and_install_autojs6_including_all_abis) + " [" + getString(R.string.text_recommended) + "]\n\n" + - getString(R.string.text_download_link_for_autojs6) + ":\n" + + getString(R.string.text_download_link_for_autojs6) + getString(R.string.symbol_colon_with_blank) + "\n" + getString(R.string.uri_autojs6_download_link)); builder.positiveText(R.string.dialog_button_dismiss); builder.positiveColorRes(R.color.dialog_button_hint); @@ -477,6 +1748,8 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa } private void syncAbisCheckedStates() { + mInvalidAbis.clear(); + mUnavailableStandardAbis.clear(); if (mProjectConfig != null) { List projectConfigAbis = mProjectConfig.getAbis(); if (!projectConfigAbis.isEmpty()) { @@ -513,17 +1786,20 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa RoundCheckboxWithText child = new RoundCheckboxWithText(this, null); child.setText(text); child.setChecked(false); + child.setOnCheckedChangeListener((buttonView, isChecked) -> onBuildUiControlChanged()); mFlexboxLibsView.addView(child); }); } private void syncLibsCheckedStates() { + mInvalidLibs.clear(); if (mProjectConfig == null) return; var configLibs = mProjectConfig.getLibs(); if (configLibs.isEmpty()) return; - // 创建一个新的副本 + // Create a new copy. + // zh-CN: 创建一个新的副本 var candidates = new ArrayList<>(configLibs); for (int i = 0; i < mFlexboxLibsView.getChildCount(); i += 1) { @@ -562,8 +1838,9 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa private void initVerifiedKeyStoresSpinner() { ArrayList verifiedKeyStores = new ArrayList<>(); - // 添加 默认密钥库 下拉选项 - KeyStore defaultKeyStore = new KeyStore("", getString(R.string.text_default_key_store), "", "", "", false); // 仅用于显示下拉列表 + // Add "default keystore" dropdown option. + // zh-CN: 添加 "默认密钥库" 下拉选项. + KeyStore defaultKeyStore = new KeyStore("", getString(R.string.text_default_key_store), "", "", "", false); verifiedKeyStores.add(defaultKeyStore); ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, verifiedKeyStores); @@ -571,12 +1848,26 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa mVerifiedKeyStoresView.setAdapter(adapter); mKeyStoreViewModel.getVerifiedKeyStores().observe(this, keyStores -> { - // 清空现有的选项, 但保留第一个元素, 即默认密钥库 + String selectedPath = null; + Object selected = mVerifiedKeyStoresView.getSelectedItem(); + if (selected instanceof KeyStore) { + selectedPath = ((KeyStore) selected).getAbsolutePath(); + } + + // Clear existing options, but keep the first element, + // that is, the default keystore. + // zh-CN: 清空现有的选项, 但保留第一个元素, 即默认密钥库. if (verifiedKeyStores.size() > 1) { verifiedKeyStores.subList(1, verifiedKeyStores.size()).clear(); } verifiedKeyStores.addAll(keyStores); adapter.notifyDataSetChanged(); + + if (!TextUtils.isEmpty(selectedPath)) { + mPendingKeyStorePathForStateApply = selectedPath; + } + tryApplyPendingKeyStorePathSelection(); + onBuildUiControlChanged(); }); } @@ -600,10 +1891,30 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa : ProjectConfig.DEFAULT_PERMISSIONS; boolean checked = hasPermission(permissions, permission); checkBox.setChecked(checked); + checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> onBuildUiControlChanged()); mFlexboxPermissionsView.addView(checkBox); }); } + private void syncPermissionsCheckedStates(@NonNull List permissions) { + for (int i = 0; i < mFlexboxPermissionsView.getChildCount(); i += 1) { + View child = mFlexboxPermissionsView.getChildAt(i); + CharSequence text = child instanceof RoundCheckboxWithText + ? ((RoundCheckboxWithText) child).getText() + : child instanceof CheckBox ? ((CheckBox) child).getText() : null; + if (text == null) { + continue; + } + String permission = text.toString().split("\n")[0].trim(); + boolean checked = hasPermission(permissions, permission); + if (child instanceof RoundCheckboxWithText) { + ((RoundCheckboxWithText) child).setChecked(checked); + } else if (child instanceof CheckBox) { + ((CheckBox) child).setChecked(checked); + } + } + } + private boolean hasPermission(List permissions, String permission) { return permissions.stream().anyMatch(p -> { var lc = p.toLowerCase(Locale.ROOT); @@ -642,6 +1953,10 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa @SuppressLint("CheckResult") private void setupWithSourceFile(ScriptFile file) { + if (file.isDirectory()) { + setSource(file); + return; + } String dir = file.getParent(); if (dir != null && dir.startsWith(getFilesDir().getPath())) { dir = WorkingDirectoryUtils.getPath(); @@ -678,6 +1993,7 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa mIconView.setVisibility(View.VISIBLE); updatePermissionsCheckboxes(packageName); + onSourcePresetReady(); }, throwable -> { mPackageNameView.setText(getString(R.string.format_default_package_name, file.getSimplifiedName().toLowerCase(Language.getPrefLanguage().getLocale()))); mVersionNameView.setText(R.string.default_build_apk_version_name); @@ -686,6 +2002,7 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa mVersionNameParentView.setHint(R.string.text_version_name); mVersionCodeParentView.setHint(R.string.text_version_code); mIconView.setVisibility(View.VISIBLE); + onSourcePresetReady(); }); setSource(file); @@ -766,8 +2083,13 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa } private void setSource(File file) { + mSource = file.getPath(); + mSourcePathView.setText(file.getPath()); if (!file.isDirectory()) { - mSourcePathView.setText(file.getPath()); + mIsProjectLevelBuilding = false; + mProjectConfig = null; + mAppConfigView.setVisibility(View.VISIBLE); + mSourcePathContainerView.setVisibility(View.VISIBLE); return; } mProjectConfig = ProjectConfig.fromProjectDir(file.getPath()); @@ -775,9 +2097,54 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa return; } mIsProjectLevelBuilding = true; - mOutputPathView.setText(new File(mSource, mProjectConfig.getBuildDir()).getPath()); - mAppConfigView.setVisibility(View.GONE); - mSourcePathContainerView.setVisibility(View.GONE); + mProjectConfig.setSourcePath(file.getPath()); + mOutputPathView.setText(new File(file, mProjectConfig.getBuildDir()).getPath()); + + mAppNameView.setText(mProjectConfig.getName()); + mPackageNameView.setText(mProjectConfig.getPackageName()); + mVersionNameView.setText(mProjectConfig.getVersionName()); + mVersionCodeView.setText(String.valueOf(mProjectConfig.getVersionCode())); + + mPackageNameParentView.setHint(R.string.text_package_name); + mVersionNameParentView.setHint(R.string.text_version_name); + mVersionCodeParentView.setHint(R.string.text_version_code); + + String iconPath = mProjectConfig.getIconPath(); + if (!TextUtils.isEmpty(iconPath)) { + String absoluteIconPath = new File(file, iconPath).getPath(); + Drawable iconDrawable = Drawable.createFromPath(absoluteIconPath); + if (iconDrawable != null) { + mIconView.setImageDrawable(iconDrawable); + mIsDefaultIcon = false; + } else { + mIsDefaultIcon = true; + } + } else { + mIsDefaultIcon = true; + } + mIconView.setVisibility(View.VISIBLE); + + boolean previousSuppress = mSuppressBuildStateTracking; + mSuppressBuildStateTracking = true; + try { + LaunchConfig launchConfig = mProjectConfig.getLaunchConfig(); + if (launchConfig != null) { + mLaunchLogsVisibleView.setChecked(launchConfig.isLogsVisible()); + mLaunchSplashVisibleView.setChecked(launchConfig.isSplashVisible()); + mLaunchLauncherVisibleView.setChecked(launchConfig.isLauncherVisible()); + mLaunchRunOnBootView.setChecked(launchConfig.isRunOnBoot()); + mLaunchSlugView.setText(launchConfig.getSlug()); + } + syncAbisCheckedStates(); + syncLibsCheckedStates(); + setSignatureSchemeByLabel(mProjectConfig.getSignatureScheme()); + syncPermissionsCheckedStates(mProjectConfig.getPermissions()); + } finally { + mSuppressBuildStateTracking = previousSuppress; + } + + mAppConfigView.setVisibility(View.VISIBLE); + mSourcePathContainerView.setVisibility(View.VISIBLE); } void selectOutputDirPath() { @@ -806,13 +2173,11 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa ViewUtils.showToast(this, getString(R.string.error_at_least_one_abi_needs_to_be_selected)); return; } + saveCurrentBuildProfileSilently(); doBuildingApk(); } private boolean checkInputs() { - if (mIsProjectLevelBuilding) { - return checkNotEmpty(mOutputPathView); - } return checkNotEmpty(mSourcePathView) & checkNotEmpty(mOutputPathView) & checkNotEmpty(mAppNameView) @@ -897,7 +2262,8 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa if (info.isEmpty()) return; - // 动态计算 splitLineLength, 考虑广范围的双宽字符 + // Compute splitLineLength dynamically, considering wide characters. + // zh-CN: 动态计算 splitLineLength, 考虑广范围的双宽字符. for (ArrayList>> mapsList : info) { for (Map> map : mapsList) { for (Map.Entry> entry : map.entrySet()) { @@ -913,11 +2279,12 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa final int finalSplitLineLength = splitLineLength; - // 生成对话框内容 + // Generate dialog content. + // zh-CN: 生成对话框内容. String content = info.stream() .map(mapsList -> mapsList.stream() .map(map -> map.entrySet().stream() - .map(entry -> getString(entry.getKey()) + ":\n[ " + String.join(", ", entry.getValue()) + " ]") + .map(entry -> getString(entry.getKey()) + getString(R.string.symbol_colon_with_blank) + "\n[ " + String.join(", ", entry.getValue()) + " ]") .collect(Collectors.joining("\n"))) .collect(Collectors.joining("\n"))) .collect(Collectors.joining("\n" + "-".repeat(finalSplitLineLength) + "\n")); @@ -931,7 +2298,8 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa .show(); } - // 判断字符是否是广范围双宽字符 + // Determine whether a character is a wide glyph. + // zh-CN: 判断字符是否是广范围双宽字符. private boolean isWideCharacter(char c) { Character.UnicodeBlock block = Character.UnicodeBlock.of(c); return block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || @@ -1020,32 +2388,95 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa } private ProjectConfig determineProjectConfig() { - ArrayList abis = collectCheckedItems(mFlexboxAbisView); - ArrayList libs = collectCheckedItems(mFlexboxLibsView); - ArrayList permissions = collectCheckedItems(mFlexboxPermissionsView); + return determineProjectConfig(captureCurrentBuildUiState()); + } + + private ProjectConfig determineProjectConfig(@NonNull BuildUiState state) { + ArrayList abis = new ArrayList<>(state.abis); + ArrayList libs = new ArrayList<>(state.libs); + ArrayList permissions = new ArrayList<>(state.permissions); + + String sourcePath = state.sourcePath == null ? "" : state.sourcePath.trim(); + if (TextUtils.isEmpty(sourcePath)) { + sourcePath = mSource == null ? "" : mSource; + } ProjectConfig projectConfig; if (mProjectConfig != null) { projectConfig = mProjectConfig .excludeDir(mProjectConfig.getBuildDir()) - .setSourcePath(mSource) - .setIconPath(mProjectConfig.getIconPath() == null ? null : new File(mSource, mProjectConfig.getIconPath()).getPath()); + .setSourcePath(sourcePath); + if (!mIsDefaultIcon && mIconView.getDrawable() != null) { + projectConfig.setIconGetter(() -> BitmapUtils.drawableToBitmap(mIconView.getDrawable())); + } else if (!TextUtils.isEmpty(mProjectConfig.getIconPath())) { + projectConfig.setIconPath(new File(sourcePath, Objects.requireNonNull(mProjectConfig.getIconPath())).getPath()); + } } else { projectConfig = new ProjectConfig() - .setName(mAppNameView.getText().toString()) - .setSourcePath(mSourcePathView.getText().toString()) - .setPackageName(mPackageNameView.getText().toString()) - .setVersionName(mVersionNameView.getText().toString()) - .setVersionCode(Integer.parseInt(mVersionCodeView.getText().toString())) + .setSourcePath(sourcePath) .setIconGetter(mIsDefaultIcon ? null : () -> BitmapUtils.drawableToBitmap(mIconView.getDrawable())); } - return projectConfig + int fallbackVersionCode = mProjectConfig == null ? 1 : mProjectConfig.getVersionCode(); + if (fallbackVersionCode <= 0) { + fallbackVersionCode = 1; + } + int versionCode = parseVersionCodeOrDefault(state.versionCode, fallbackVersionCode); + String signatureScheme = TextUtils.isEmpty(state.signatureScheme) + ? normalizeSignatureSchemeLabel(mSignatureSchemesView.getSelectedItem() == null ? "" : mSignatureSchemesView.getSelectedItem().toString()) + : state.signatureScheme; + LaunchConfig launchConfig = projectConfig.getLaunchConfig(); + if (launchConfig == null) { + launchConfig = new LaunchConfig(); + } + launchConfig.setLogsVisible(state.launchLogsVisible); + launchConfig.setSplashVisible(state.launchSplashVisible); + launchConfig.setLauncherVisible(state.launchLauncherVisible); + launchConfig.setRunOnBoot(state.launchRunOnBoot); + launchConfig.setSlug(state.launchSlug); + + ProjectConfig resolved = projectConfig + .setName(state.appName) + .setPackageName(state.packageName) + .setVersionName(state.versionName) + .setVersionCode(versionCode) .setAbis(abis) .setLibs(libs) - .setKeyStore(mVerifiedKeyStoresView.getSelectedItemPosition() > 0 ? (KeyStore) mVerifiedKeyStoresView.getSelectedItem() : null) - .setSignatureScheme(mSignatureSchemesView.getSelectedItem().toString()) + .setKeyStore(resolveKeyStoreByPath(state.keyStorePath)) + .setSignatureScheme(signatureScheme) .setPermissions(permissions); + resolved.setLaunchConfig(launchConfig); + return resolved; + } + + @Nullable + private KeyStore resolveKeyStoreByPath(@Nullable String keyStorePath) { + if (TextUtils.isEmpty(keyStorePath) || mVerifiedKeyStoresView == null) { + return null; + } + for (int i = 1; i < mVerifiedKeyStoresView.getCount(); i++) { + Object item = mVerifiedKeyStoresView.getItemAtPosition(i); + if (!(item instanceof KeyStore)) { + continue; + } + KeyStore keyStore = (KeyStore) item; + if (keyStorePath.equalsIgnoreCase(keyStore.getAbsolutePath())) { + return keyStore; + } + } + return null; + } + + private int parseVersionCodeOrDefault(@Nullable String rawVersionCode, int fallback) { + String value = rawVersionCode == null ? "" : rawVersionCode.trim(); + if (value.isEmpty()) { + return fallback; + } + try { + return Integer.parseInt(value); + } catch (NumberFormatException ignored) { + return fallback; + } } @NotNull @@ -1239,7 +2670,7 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa } // Abort build cooperatively and trigger cleanup as early as possible. - // zh-CN: 协作式中止构建, 并尽早触发清理. + // zh-CN: Abort build cooperatively and trigger cleanup as early as possible. private void requestBuildAbort() { if (!mBuildCancelled.compareAndSet(false, true)) { return; @@ -1269,7 +2700,7 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa } // Best-effort cleanup for workspace and output artifacts. - // zh-CN: 对工作区和输出产物执行尽力清理. + // zh-CN: Best-effort cleanup for workspace and output artifacts. private void cleanupBuildArtifacts(@Nullable File workspace, @Nullable File outApk, @Nullable File outApkBackup, boolean restoreOutputApk) { if (workspace != null && workspace.exists()) { PFiles.deleteRecursively(workspace); @@ -1436,10 +2867,15 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa } @SuppressWarnings("ResultOfMethodCallIgnored") - @SuppressLint({"CheckResult", "MissingSuperCall"}) + @SuppressLint("CheckResult") @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == RESULT_OK) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode != RESULT_OK) { + return; + } + + if (requestCode == REQUEST_CODE) { AppsIconSelectActivity.getDrawableFromIntent(getApplicationContext(), data) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -1447,6 +2883,300 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa mIconView.setImageDrawable(drawable); mIsDefaultIcon = false; }, Throwable::printStackTrace); + return; + } + + Uri uri = data == null ? null : data.getData(); + if (uri == null) { + return; + } + if (requestCode == REQ_EXPORT_JSON) { + doExportBuildProfileToUri(uri); + return; + } + if (requestCode == REQ_IMPORT_JSON) { + doImportBuildProfileFromUri(uri); + } + } + + private static final class BuildFieldPolicy { + boolean fixedSourcePath = false; + boolean fixedIcon = false; + boolean fixedOutputPath = false; + boolean fixedAppName = false; + boolean fixedPackageName = false; + boolean fixedVersionName = false; + boolean fixedVersionCode = false; + boolean fixedLaunchLogsVisible = false; + boolean fixedLaunchSplashVisible = false; + boolean fixedLaunchLauncherVisible = false; + boolean fixedLaunchRunOnBoot = false; + boolean fixedLaunchSlug = false; + boolean fixedAbis = false; + boolean fixedLibs = true; + boolean fixedSignatureScheme = true; + boolean fixedKeyStore = true; + boolean fixedPermissions = true; + + @NonNull + static BuildFieldPolicy defaultPolicy() { + return new BuildFieldPolicy(); + } + + @NonNull + static BuildFieldPolicy projectJsonPolicy() { + BuildFieldPolicy policy = new BuildFieldPolicy(); + policy.fixedSourcePath = true; + policy.fixedIcon = true; + policy.fixedOutputPath = true; + policy.fixedAppName = true; + policy.fixedPackageName = true; + policy.fixedVersionName = true; + policy.fixedVersionCode = true; + policy.fixedLaunchLogsVisible = true; + policy.fixedLaunchSplashVisible = true; + policy.fixedLaunchLauncherVisible = true; + policy.fixedLaunchRunOnBoot = true; + policy.fixedLaunchSlug = true; + policy.fixedAbis = true; + policy.fixedLibs = true; + policy.fixedSignatureScheme = true; + policy.fixedKeyStore = true; + policy.fixedPermissions = true; + return policy; + } + + @NonNull + BuildFieldPolicy copy() { + BuildFieldPolicy copied = new BuildFieldPolicy(); + copied.fixedSourcePath = fixedSourcePath; + copied.fixedIcon = fixedIcon; + copied.fixedOutputPath = fixedOutputPath; + copied.fixedAppName = fixedAppName; + copied.fixedPackageName = fixedPackageName; + copied.fixedVersionName = fixedVersionName; + copied.fixedVersionCode = fixedVersionCode; + copied.fixedLaunchLogsVisible = fixedLaunchLogsVisible; + copied.fixedLaunchSplashVisible = fixedLaunchSplashVisible; + copied.fixedLaunchLauncherVisible = fixedLaunchLauncherVisible; + copied.fixedLaunchRunOnBoot = fixedLaunchRunOnBoot; + copied.fixedLaunchSlug = fixedLaunchSlug; + copied.fixedAbis = fixedAbis; + copied.fixedLibs = fixedLibs; + copied.fixedSignatureScheme = fixedSignatureScheme; + copied.fixedKeyStore = fixedKeyStore; + copied.fixedPermissions = fixedPermissions; + return copied; + } + + @NonNull + JSONObject toJson() { + JSONObject out = new JSONObject(); + try { + out.put(BuildConfigStore.FIELD_FIXED_SOURCE_PATH, fixedSourcePath); + out.put(BuildConfigStore.FIELD_FIXED_ICON, fixedIcon); + out.put(BuildConfigStore.FIELD_FIXED_OUTPUT_PATH, fixedOutputPath); + out.put(BuildConfigStore.FIELD_FIXED_APP_NAME, fixedAppName); + out.put(BuildConfigStore.FIELD_FIXED_PACKAGE_NAME, fixedPackageName); + out.put(BuildConfigStore.FIELD_FIXED_VERSION_NAME, fixedVersionName); + out.put(BuildConfigStore.FIELD_FIXED_VERSION_CODE, fixedVersionCode); + out.put(BuildConfigStore.FIELD_FIXED_LAUNCH_LOGS_VISIBLE, fixedLaunchLogsVisible); + out.put(BuildConfigStore.FIELD_FIXED_LAUNCH_SPLASH_VISIBLE, fixedLaunchSplashVisible); + out.put(BuildConfigStore.FIELD_FIXED_LAUNCH_LAUNCHER_VISIBLE, fixedLaunchLauncherVisible); + out.put(BuildConfigStore.FIELD_FIXED_LAUNCH_RUN_ON_BOOT, fixedLaunchRunOnBoot); + out.put(BuildConfigStore.FIELD_FIXED_LAUNCH_SLUG, fixedLaunchSlug); + out.put(BuildConfigStore.FIELD_FIXED_ABIS, fixedAbis); + out.put(BuildConfigStore.FIELD_FIXED_LIBS, fixedLibs); + out.put(BuildConfigStore.FIELD_FIXED_SIGNATURE_SCHEME, fixedSignatureScheme); + out.put(BuildConfigStore.FIELD_FIXED_KEY_STORE, fixedKeyStore); + out.put(BuildConfigStore.FIELD_FIXED_PERMISSIONS, fixedPermissions); + } catch (JSONException ignored) { + // Keep best-effort snapshot for profile persistence. + } + return out; + } + + @NonNull + static BuildFieldPolicy fromJson(@Nullable JSONObject json) { + BuildFieldPolicy policy = defaultPolicy(); + if (json == null) return policy; + policy.fixedSourcePath = json.optBoolean(BuildConfigStore.FIELD_FIXED_SOURCE_PATH, policy.fixedSourcePath); + policy.fixedIcon = json.optBoolean(BuildConfigStore.FIELD_FIXED_ICON, policy.fixedIcon); + policy.fixedOutputPath = json.optBoolean(BuildConfigStore.FIELD_FIXED_OUTPUT_PATH, policy.fixedOutputPath); + policy.fixedAppName = json.optBoolean(BuildConfigStore.FIELD_FIXED_APP_NAME, policy.fixedAppName); + policy.fixedPackageName = json.optBoolean(BuildConfigStore.FIELD_FIXED_PACKAGE_NAME, policy.fixedPackageName); + policy.fixedVersionName = json.optBoolean(BuildConfigStore.FIELD_FIXED_VERSION_NAME, policy.fixedVersionName); + policy.fixedVersionCode = json.optBoolean(BuildConfigStore.FIELD_FIXED_VERSION_CODE, policy.fixedVersionCode); + policy.fixedLaunchLogsVisible = json.optBoolean(BuildConfigStore.FIELD_FIXED_LAUNCH_LOGS_VISIBLE, policy.fixedLaunchLogsVisible); + policy.fixedLaunchSplashVisible = json.optBoolean(BuildConfigStore.FIELD_FIXED_LAUNCH_SPLASH_VISIBLE, policy.fixedLaunchSplashVisible); + policy.fixedLaunchLauncherVisible = json.optBoolean(BuildConfigStore.FIELD_FIXED_LAUNCH_LAUNCHER_VISIBLE, policy.fixedLaunchLauncherVisible); + policy.fixedLaunchRunOnBoot = json.optBoolean(BuildConfigStore.FIELD_FIXED_LAUNCH_RUN_ON_BOOT, policy.fixedLaunchRunOnBoot); + policy.fixedLaunchSlug = json.optBoolean(BuildConfigStore.FIELD_FIXED_LAUNCH_SLUG, policy.fixedLaunchSlug); + policy.fixedAbis = json.optBoolean(BuildConfigStore.FIELD_FIXED_ABIS, policy.fixedAbis); + policy.fixedLibs = json.optBoolean(BuildConfigStore.FIELD_FIXED_LIBS, policy.fixedLibs); + policy.fixedSignatureScheme = json.optBoolean(BuildConfigStore.FIELD_FIXED_SIGNATURE_SCHEME, policy.fixedSignatureScheme); + policy.fixedKeyStore = json.optBoolean(BuildConfigStore.FIELD_FIXED_KEY_STORE, policy.fixedKeyStore); + policy.fixedPermissions = json.optBoolean(BuildConfigStore.FIELD_FIXED_PERMISSIONS, policy.fixedPermissions); + return policy; + } + } + + private static final class BuildUiState { + String sourcePath = ""; + String outputPath = ""; + String appName = ""; + String packageName = ""; + String versionName = ""; + String versionCode = ""; + boolean launchLogsVisible = true; + boolean launchSplashVisible = true; + boolean launchLauncherVisible = true; + boolean launchRunOnBoot = false; + String launchSlug = ""; + String signatureScheme = ""; + String keyStorePath = ""; + ArrayList abis = new ArrayList<>(); + ArrayList libs = new ArrayList<>(); + ArrayList permissions = new ArrayList<>(); + + @NonNull + BuildUiState copy() { + BuildUiState copied = new BuildUiState(); + copied.sourcePath = sourcePath; + copied.outputPath = outputPath; + copied.appName = appName; + copied.packageName = packageName; + copied.versionName = versionName; + copied.versionCode = versionCode; + copied.launchLogsVisible = launchLogsVisible; + copied.launchSplashVisible = launchSplashVisible; + copied.launchLauncherVisible = launchLauncherVisible; + copied.launchRunOnBoot = launchRunOnBoot; + copied.launchSlug = launchSlug; + copied.signatureScheme = signatureScheme; + copied.keyStorePath = keyStorePath; + copied.abis = new ArrayList<>(abis); + copied.libs = new ArrayList<>(libs); + copied.permissions = new ArrayList<>(permissions); + return copied; + } + + @NonNull + JSONObject toJson() { + JSONObject json = new JSONObject(); + try { + json.put(BuildConfigStore.STATE_SOURCE_PATH, sourcePath); + json.put(BuildConfigStore.STATE_OUTPUT_PATH, outputPath); + json.put(BuildConfigStore.STATE_APP_NAME, appName); + json.put(BuildConfigStore.STATE_PACKAGE_NAME, packageName); + json.put(BuildConfigStore.STATE_VERSION_NAME, versionName); + json.put(BuildConfigStore.STATE_VERSION_CODE, versionCode); + json.put(BuildConfigStore.STATE_LAUNCH_LOGS_VISIBLE, launchLogsVisible); + json.put(BuildConfigStore.STATE_LAUNCH_SPLASH_VISIBLE, launchSplashVisible); + json.put(BuildConfigStore.STATE_LAUNCH_LAUNCHER_VISIBLE, launchLauncherVisible); + json.put(BuildConfigStore.STATE_LAUNCH_RUN_ON_BOOT, launchRunOnBoot); + json.put(BuildConfigStore.STATE_LAUNCH_SLUG, launchSlug); + json.put(BuildConfigStore.STATE_SIGNATURE_SCHEME, signatureScheme); + json.put(BuildConfigStore.STATE_KEY_STORE_PATH, keyStorePath); + json.put(BuildConfigStore.STATE_ABIS, new JSONArray(abis)); + json.put(BuildConfigStore.STATE_LIBS, new JSONArray(libs)); + json.put(BuildConfigStore.STATE_PERMISSIONS, new JSONArray(permissions)); + } catch (JSONException ignored) { + // Keep best-effort snapshot for profile persistence. + } + return json; + } + + @NonNull + static BuildUiState fromJson(@NonNull JSONObject json) { + BuildUiState state = new BuildUiState(); + state.sourcePath = json.optString(BuildConfigStore.STATE_SOURCE_PATH, ""); + state.outputPath = json.optString(BuildConfigStore.STATE_OUTPUT_PATH, ""); + state.appName = json.optString(BuildConfigStore.STATE_APP_NAME, ""); + state.packageName = json.optString(BuildConfigStore.STATE_PACKAGE_NAME, ""); + state.versionName = json.optString(BuildConfigStore.STATE_VERSION_NAME, ""); + state.versionCode = json.optString(BuildConfigStore.STATE_VERSION_CODE, ""); + state.launchLogsVisible = json.optBoolean(BuildConfigStore.STATE_LAUNCH_LOGS_VISIBLE, true); + state.launchSplashVisible = json.optBoolean(BuildConfigStore.STATE_LAUNCH_SPLASH_VISIBLE, true); + state.launchLauncherVisible = json.optBoolean(BuildConfigStore.STATE_LAUNCH_LAUNCHER_VISIBLE, true); + state.launchRunOnBoot = json.optBoolean(BuildConfigStore.STATE_LAUNCH_RUN_ON_BOOT, false); + state.launchSlug = json.optString(BuildConfigStore.STATE_LAUNCH_SLUG, ""); + state.signatureScheme = json.optString(BuildConfigStore.STATE_SIGNATURE_SCHEME, ""); + state.keyStorePath = json.optString(BuildConfigStore.STATE_KEY_STORE_PATH, ""); + state.abis = readStringArray(json.optJSONArray(BuildConfigStore.STATE_ABIS)); + state.libs = readStringArray(json.optJSONArray(BuildConfigStore.STATE_LIBS)); + state.permissions = readStringArray(json.optJSONArray(BuildConfigStore.STATE_PERMISSIONS)); + return state; + } + + @NonNull + private static ArrayList readStringArray(@Nullable JSONArray array) { + ArrayList out = new ArrayList<>(); + if (array == null) return out; + LinkedHashSet dedup = new LinkedHashSet<>(); + for (int i = 0; i < array.length(); i++) { + String value = array.optString(i, "").trim(); + if (!value.isEmpty()) { + dedup.add(value); + } + } + out.addAll(dedup); + return out; + } + + @Override + public boolean equals(Object other) { + if (this == other) return true; + if (!(other instanceof BuildUiState)) return false; + BuildUiState that = (BuildUiState) other; + return Objects.equals(sourcePath, that.sourcePath) + && Objects.equals(outputPath, that.outputPath) + && Objects.equals(appName, that.appName) + && Objects.equals(packageName, that.packageName) + && Objects.equals(versionName, that.versionName) + && Objects.equals(versionCode, that.versionCode) + && launchLogsVisible == that.launchLogsVisible + && launchSplashVisible == that.launchSplashVisible + && launchLauncherVisible == that.launchLauncherVisible + && launchRunOnBoot == that.launchRunOnBoot + && Objects.equals(launchSlug, that.launchSlug) + && Objects.equals(signatureScheme, that.signatureScheme) + && Objects.equals(keyStorePath, that.keyStorePath) + && Objects.equals(abis, that.abis) + && Objects.equals(libs, that.libs) + && Objects.equals(permissions, that.permissions); + } + + @Override + public int hashCode() { + return Objects.hash( + sourcePath, + outputPath, + appName, + packageName, + versionName, + versionCode, + launchLogsVisible, + launchSplashVisible, + launchLauncherVisible, + launchRunOnBoot, + launchSlug, + signatureScheme, + keyStorePath, + abis, + libs, + permissions + ); + } + } + + private static final class ProfileEntry { + final String internalName; + final String displayName; + + ProfileEntry(@NonNull String internalName, @NonNull String displayName) { + this.internalName = internalName; + this.displayName = displayName; } } @@ -1455,5 +3185,4 @@ public class BuildActivity extends BaseActivity implements ApkBuilder.ProgressCa .putExtra(BuildActivity.EXTRA_SOURCE, extraSource); IntentUtils.startSafely(intent, context); } - } diff --git a/app/src/main/java/org/autojs/autojs/ui/project/BuildConfigStore.java b/app/src/main/java/org/autojs/autojs/ui/project/BuildConfigStore.java new file mode 100644 index 00000000..bc80497d --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/ui/project/BuildConfigStore.java @@ -0,0 +1,450 @@ +package org.autojs.autojs.ui.project; + +import android.content.Context; +import android.content.SharedPreferences; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import org.autojs.autojs.core.pref.Language; +import org.autojs.autojs.util.StringUtils; +import org.autojs.autojs6.R; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Objects; + +/** + * Persistent profile store for BuildActivity configuration snapshots. + * BuildActivity 配置快照的持久化配置文件存储. + *

+ * Created by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) on Mar 9, 2026. + */ +public final class BuildConfigStore { + + private static final String PREF_NAME = "build_apk_config_profiles"; + private static final String KEY_ACTIVE_PROFILE = "active_profile"; + private static final String KEY_PROFILES_JSON = "profiles_json"; + + private static final String KEY_ROOT_PROFILES = "profiles"; + private static final String KEY_ENTRY_STATE = "state"; + private static final String KEY_ENTRY_FIELDS = "fields"; + + private static final String KEY_EXPORT_NAME = "name"; + + public static final String PROFILE_DEFAULT_ID = "__default__"; + public static final String PROFILE_PROJECT_JSON = "project.json"; + + public static final String STATE_SOURCE_PATH = "sourcePath"; + public static final String STATE_OUTPUT_PATH = "outputPath"; + public static final String STATE_APP_NAME = "appName"; + public static final String STATE_PACKAGE_NAME = "packageName"; + public static final String STATE_VERSION_NAME = "versionName"; + public static final String STATE_VERSION_CODE = "versionCode"; + public static final String STATE_LAUNCH_LOGS_VISIBLE = "launchLogsVisible"; + public static final String STATE_LAUNCH_SPLASH_VISIBLE = "launchSplashVisible"; + public static final String STATE_LAUNCH_LAUNCHER_VISIBLE = "launchLauncherVisible"; + public static final String STATE_LAUNCH_RUN_ON_BOOT = "launchRunOnBoot"; + public static final String STATE_LAUNCH_SLUG = "launchSlug"; + public static final String STATE_SIGNATURE_SCHEME = "signatureScheme"; + public static final String STATE_KEY_STORE_PATH = "keyStorePath"; + public static final String STATE_ABIS = "abis"; + public static final String STATE_LIBS = "libs"; + public static final String STATE_PERMISSIONS = "permissions"; + + public static final String FIELD_FIXED_SOURCE_PATH = "fixedSourcePath"; + public static final String FIELD_FIXED_ICON = "fixedIcon"; + public static final String FIELD_FIXED_OUTPUT_PATH = "fixedOutputPath"; + public static final String FIELD_FIXED_APP_NAME = "fixedAppName"; + public static final String FIELD_FIXED_PACKAGE_NAME = "fixedPackageName"; + public static final String FIELD_FIXED_VERSION_NAME = "fixedVersionName"; + public static final String FIELD_FIXED_VERSION_CODE = "fixedVersionCode"; + public static final String FIELD_FIXED_LAUNCH_LOGS_VISIBLE = "fixedLaunchLogsVisible"; + public static final String FIELD_FIXED_LAUNCH_SPLASH_VISIBLE = "fixedLaunchSplashVisible"; + public static final String FIELD_FIXED_LAUNCH_LAUNCHER_VISIBLE = "fixedLaunchLauncherVisible"; + public static final String FIELD_FIXED_LAUNCH_RUN_ON_BOOT = "fixedLaunchRunOnBoot"; + public static final String FIELD_FIXED_LAUNCH_SLUG = "fixedLaunchSlug"; + public static final String FIELD_FIXED_ABIS = "fixedAbis"; + public static final String FIELD_FIXED_LIBS = "fixedLibs"; + public static final String FIELD_FIXED_SIGNATURE_SCHEME = "fixedSignatureScheme"; + public static final String FIELD_FIXED_KEY_STORE = "fixedKeyStore"; + public static final String FIELD_FIXED_PERMISSIONS = "fixedPermissions"; + + private BuildConfigStore() { + } + + public static final class ProfilePayload { + @NonNull + public final String name; + @NonNull + public final JSONObject state; + @NonNull + public final JSONObject fields; + + public ProfilePayload(@NonNull String name, @NonNull JSONObject state, @NonNull JSONObject fields) { + this.name = name; + this.state = state; + this.fields = fields; + } + } + + @NonNull + public static String getActiveProfileName(@NonNull Context context) { + SharedPreferences sp = prefs(context); + String name = sp.getString(KEY_ACTIVE_PROFILE, PROFILE_DEFAULT_ID); + if (name == null || name.trim().isEmpty()) { + return PROFILE_DEFAULT_ID; + } + return name; + } + + public static void setActiveProfileName(@NonNull Context context, @NonNull String name) { + prefs(context).edit().putString(KEY_ACTIVE_PROFILE, name).apply(); + } + + @NonNull + public static String getDefaultProfileDisplayName(@NonNull Context context) { + return context.getString(R.string.text_default); + } + + public static boolean isReservedDefaultName(@NonNull Context context, @Nullable String name) { + if (name == null) return false; + String n = name.trim(); + if (n.isEmpty()) return false; + var computed = new ArrayList<>() {{ + add(PROFILE_DEFAULT_ID); + }}; + for (Language language : Language.values()) { + if (language == Language.AUTO) continue; + String s = StringUtils.getStringForLocale(context, language.getLocale(), R.string.text_default); + if (s.isBlank()) continue; + computed.add(s); + } + return computed.contains(n) + || Objects.equals(n, getDefaultProfileDisplayName(context)); + } + + public static boolean isReservedProfileName(@NonNull Context context, @Nullable String name) { + if (name == null) return false; + String n = name.trim(); + if (n.isEmpty()) return false; + return isReservedDefaultName(context, n) + || Objects.equals(n, PROFILE_PROJECT_JSON); + } + + @NonNull + public static String getPrefillProfileName(@NonNull Context context) { + String prefix = "config-"; + List profiles = listProfiles(context); + int candidate = 1; + while (true) { + String name = prefix + candidate; + if (!profiles.contains(name)) { + return name; + } + candidate++; + } + } + + @NonNull + public static List listProfiles(@NonNull Context context) { + JSONObject root = readRootOrCreate(context); + JSONObject profiles = root.optJSONObject(KEY_ROOT_PROFILES); + ArrayList list = new ArrayList<>(); + if (profiles != null) { + profiles.keys().forEachRemaining(list::add); + } + list.sort(String::compareToIgnoreCase); + return list; + } + + public static void ensureDefaultProfileExists(@NonNull Context context, @Nullable JSONObject defaultState) { + ensureDefaultProfileExists(context, defaultState, null); + } + + public static void ensureDefaultProfileExists(@NonNull Context context, @Nullable JSONObject defaultState, @Nullable JSONObject defaultFields) { + JSONObject root = readRootOrCreate(context); + JSONObject profiles = root.optJSONObject(KEY_ROOT_PROFILES); + if (profiles == null) { + profiles = new JSONObject(); + putSafely(root, KEY_ROOT_PROFILES, profiles); + } + + boolean changed = false; + JSONObject expectedDefault = normalizeProfile(null, defaultState, defaultFields); + + JSONObject currentDefault = profiles.optJSONObject(PROFILE_DEFAULT_ID); + if (currentDefault == null || !Objects.equals(currentDefault.toString(), expectedDefault.toString())) { + putSafely(profiles, PROFILE_DEFAULT_ID, expectedDefault); + changed = true; + } + + String active = getActiveProfileName(context); + if (!profiles.has(active)) { + setActiveProfileName(context, PROFILE_DEFAULT_ID); + } + + if (changed) { + persistRoot(context, root); + } + } + + @Nullable + public static ProfilePayload loadProfilePayload(@NonNull Context context, @NonNull String name) { + JSONObject root = readRootOrCreate(context); + JSONObject profiles = root.optJSONObject(KEY_ROOT_PROFILES); + if (profiles == null) return null; + + JSONObject raw = profiles.optJSONObject(name); + if (raw == null) return null; + + JSONObject normalized = normalizeProfile(raw, null, null); + return new ProfilePayload( + name, + normalized.optJSONObject(KEY_ENTRY_STATE) == null + ? normalizeState(null) + : normalized.optJSONObject(KEY_ENTRY_STATE), + normalized.optJSONObject(KEY_ENTRY_FIELDS) == null + ? defaultFields() + : normalized.optJSONObject(KEY_ENTRY_FIELDS) + ); + } + + @Nullable + public static JSONObject loadProfile(@NonNull Context context, @NonNull String name) { + ProfilePayload payload = loadProfilePayload(context, name); + return payload == null ? null : payload.state; + } + + @NonNull + public static JSONObject loadProfileFields(@NonNull Context context, @NonNull String name) { + ProfilePayload payload = loadProfilePayload(context, name); + return payload == null ? defaultFields() : payload.fields; + } + + public static void saveProfile(@NonNull Context context, @NonNull String name, @Nullable JSONObject state) { + saveProfile(context, name, state, null); + } + + public static void saveProfile(@NonNull Context context, @NonNull String name, @Nullable JSONObject state, @Nullable JSONObject fields) { + JSONObject root = readRootOrCreate(context); + JSONObject profiles = root.optJSONObject(KEY_ROOT_PROFILES); + if (profiles == null) { + profiles = new JSONObject(); + putSafely(root, KEY_ROOT_PROFILES, profiles); + } + + JSONObject normalizedEntry = normalizeProfile(null, state, fields); + putSafely(profiles, name, normalizedEntry); + persistRoot(context, root); + } + + public static void deleteProfile(@NonNull Context context, @NonNull String name) { + if (PROFILE_DEFAULT_ID.equals(name) || PROFILE_PROJECT_JSON.equals(name)) { + return; + } + JSONObject root = readRootOrCreate(context); + JSONObject profiles = root.optJSONObject(KEY_ROOT_PROFILES); + if (profiles == null) return; + profiles.remove(name); + persistRoot(context, root); + if (Objects.equals(getActiveProfileName(context), name)) { + setActiveProfileName(context, PROFILE_DEFAULT_ID); + } + } + + @NonNull + public static JSONObject exportProfileToJson(@NonNull Context context, @NonNull String name) { + ProfilePayload payload = loadProfilePayload(context, name); + + JSONObject out = new JSONObject(); + putSafely(out, KEY_EXPORT_NAME, name); + putSafely(out, KEY_ENTRY_STATE, payload == null ? normalizeState(null) : normalizeState(payload.state)); + putSafely(out, KEY_ENTRY_FIELDS, payload == null ? defaultFields() : normalizeFields(payload.fields)); + return out; + } + + @NonNull + public static ProfilePayload importProfileFromJson(@NonNull JSONObject json) { + String name = json.optString(KEY_EXPORT_NAME, "").trim(); + if (name.isEmpty()) { + throw new IllegalArgumentException("Invalid profile name"); + } + + JSONObject state = json.optJSONObject(KEY_ENTRY_STATE); + if (state == null && looksLikeLegacyState(json)) { + state = json; + } + + JSONObject fields = json.optJSONObject(KEY_ENTRY_FIELDS); + + return new ProfilePayload(name, normalizeState(state), normalizeFields(fields)); + } + + @NonNull + private static SharedPreferences prefs(@NonNull Context context) { + return context.getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); + } + + @NonNull + private static JSONObject readRootOrCreate(@NonNull Context context) { + String raw = prefs(context).getString(KEY_PROFILES_JSON, null); + JSONObject root; + try { + root = raw == null || raw.trim().isEmpty() ? new JSONObject() : new JSONObject(raw); + } catch (Throwable ignored) { + root = new JSONObject(); + } + if (!root.has(KEY_ROOT_PROFILES) || !(root.opt(KEY_ROOT_PROFILES) instanceof JSONObject)) { + putSafely(root, KEY_ROOT_PROFILES, new JSONObject()); + } + return root; + } + + private static void persistRoot(@NonNull Context context, @NonNull JSONObject root) { + prefs(context).edit().putString(KEY_PROFILES_JSON, root.toString()).apply(); + } + + @NonNull + private static JSONObject normalizeProfile(@Nullable JSONObject rawProfile, @Nullable JSONObject fallbackState, @Nullable JSONObject fallbackFields) { + JSONObject stateSrc = null; + JSONObject fieldsSrc = null; + + if (rawProfile != null) { + if (rawProfile.has(KEY_ENTRY_STATE) || rawProfile.has(KEY_ENTRY_FIELDS)) { + stateSrc = rawProfile.optJSONObject(KEY_ENTRY_STATE); + fieldsSrc = rawProfile.optJSONObject(KEY_ENTRY_FIELDS); + } else if (looksLikeLegacyState(rawProfile)) { + stateSrc = rawProfile; + } + } + + JSONObject out = new JSONObject(); + putSafely(out, KEY_ENTRY_STATE, normalizeState(stateSrc != null ? stateSrc : fallbackState)); + putSafely(out, KEY_ENTRY_FIELDS, normalizeFields(fieldsSrc != null ? fieldsSrc : fallbackFields)); + return out; + } + + private static boolean looksLikeLegacyState(@NonNull JSONObject object) { + return object.has(STATE_SOURCE_PATH) + || object.has(STATE_OUTPUT_PATH) + || object.has(STATE_APP_NAME) + || object.has(STATE_PACKAGE_NAME) + || object.has(STATE_VERSION_NAME) + || object.has(STATE_VERSION_CODE) + || object.has(STATE_LAUNCH_LOGS_VISIBLE) + || object.has(STATE_LAUNCH_SPLASH_VISIBLE) + || object.has(STATE_LAUNCH_LAUNCHER_VISIBLE) + || object.has(STATE_LAUNCH_RUN_ON_BOOT) + || object.has(STATE_LAUNCH_SLUG) + || object.has(STATE_SIGNATURE_SCHEME) + || object.has(STATE_KEY_STORE_PATH) + || object.has(STATE_ABIS) + || object.has(STATE_LIBS) + || object.has(STATE_PERMISSIONS); + } + + @NonNull + private static JSONObject normalizeState(@Nullable JSONObject state) { + JSONObject out = new JSONObject(); + JSONObject src = state == null ? new JSONObject() : state; + + putSafely(out, STATE_SOURCE_PATH, src.optString(STATE_SOURCE_PATH, "")); + putSafely(out, STATE_OUTPUT_PATH, src.optString(STATE_OUTPUT_PATH, "")); + putSafely(out, STATE_APP_NAME, src.optString(STATE_APP_NAME, "")); + putSafely(out, STATE_PACKAGE_NAME, src.optString(STATE_PACKAGE_NAME, "")); + putSafely(out, STATE_VERSION_NAME, src.optString(STATE_VERSION_NAME, "")); + putSafely(out, STATE_VERSION_CODE, src.optString(STATE_VERSION_CODE, "")); + putSafely(out, STATE_LAUNCH_LOGS_VISIBLE, src.optBoolean(STATE_LAUNCH_LOGS_VISIBLE, true)); + putSafely(out, STATE_LAUNCH_SPLASH_VISIBLE, src.optBoolean(STATE_LAUNCH_SPLASH_VISIBLE, true)); + putSafely(out, STATE_LAUNCH_LAUNCHER_VISIBLE, src.optBoolean(STATE_LAUNCH_LAUNCHER_VISIBLE, true)); + putSafely(out, STATE_LAUNCH_RUN_ON_BOOT, src.optBoolean(STATE_LAUNCH_RUN_ON_BOOT, false)); + putSafely(out, STATE_LAUNCH_SLUG, src.optString(STATE_LAUNCH_SLUG, "")); + putSafely(out, STATE_SIGNATURE_SCHEME, src.optString(STATE_SIGNATURE_SCHEME, "")); + putSafely(out, STATE_KEY_STORE_PATH, src.optString(STATE_KEY_STORE_PATH, "")); + + putSafely(out, STATE_ABIS, normalizeStringArray(src.optJSONArray(STATE_ABIS))); + putSafely(out, STATE_LIBS, normalizeStringArray(src.optJSONArray(STATE_LIBS))); + putSafely(out, STATE_PERMISSIONS, normalizeStringArray(src.optJSONArray(STATE_PERMISSIONS))); + + return out; + } + + @NonNull + private static JSONObject defaultFields() { + JSONObject out = new JSONObject(); + putSafely(out, FIELD_FIXED_SOURCE_PATH, false); + putSafely(out, FIELD_FIXED_ICON, false); + putSafely(out, FIELD_FIXED_OUTPUT_PATH, false); + putSafely(out, FIELD_FIXED_APP_NAME, false); + putSafely(out, FIELD_FIXED_PACKAGE_NAME, false); + putSafely(out, FIELD_FIXED_VERSION_NAME, false); + putSafely(out, FIELD_FIXED_VERSION_CODE, false); + putSafely(out, FIELD_FIXED_LAUNCH_LOGS_VISIBLE, false); + putSafely(out, FIELD_FIXED_LAUNCH_SPLASH_VISIBLE, false); + putSafely(out, FIELD_FIXED_LAUNCH_LAUNCHER_VISIBLE, false); + putSafely(out, FIELD_FIXED_LAUNCH_RUN_ON_BOOT, false); + putSafely(out, FIELD_FIXED_LAUNCH_SLUG, false); + putSafely(out, FIELD_FIXED_ABIS, false); + putSafely(out, FIELD_FIXED_LIBS, true); + putSafely(out, FIELD_FIXED_SIGNATURE_SCHEME, true); + putSafely(out, FIELD_FIXED_KEY_STORE, true); + putSafely(out, FIELD_FIXED_PERMISSIONS, true); + return out; + } + + @NonNull + private static JSONObject normalizeFields(@Nullable JSONObject fields) { + JSONObject defaults = defaultFields(); + JSONObject src = fields == null ? new JSONObject() : fields; + + JSONObject out = new JSONObject(); + putSafely(out, FIELD_FIXED_SOURCE_PATH, src.optBoolean(FIELD_FIXED_SOURCE_PATH, defaults.optBoolean(FIELD_FIXED_SOURCE_PATH, false))); + putSafely(out, FIELD_FIXED_ICON, src.optBoolean(FIELD_FIXED_ICON, defaults.optBoolean(FIELD_FIXED_ICON, false))); + putSafely(out, FIELD_FIXED_OUTPUT_PATH, src.optBoolean(FIELD_FIXED_OUTPUT_PATH, defaults.optBoolean(FIELD_FIXED_OUTPUT_PATH, false))); + putSafely(out, FIELD_FIXED_APP_NAME, src.optBoolean(FIELD_FIXED_APP_NAME, defaults.optBoolean(FIELD_FIXED_APP_NAME, false))); + putSafely(out, FIELD_FIXED_PACKAGE_NAME, src.optBoolean(FIELD_FIXED_PACKAGE_NAME, defaults.optBoolean(FIELD_FIXED_PACKAGE_NAME, false))); + putSafely(out, FIELD_FIXED_VERSION_NAME, src.optBoolean(FIELD_FIXED_VERSION_NAME, defaults.optBoolean(FIELD_FIXED_VERSION_NAME, false))); + putSafely(out, FIELD_FIXED_VERSION_CODE, src.optBoolean(FIELD_FIXED_VERSION_CODE, defaults.optBoolean(FIELD_FIXED_VERSION_CODE, false))); + putSafely(out, FIELD_FIXED_LAUNCH_LOGS_VISIBLE, src.optBoolean(FIELD_FIXED_LAUNCH_LOGS_VISIBLE, defaults.optBoolean(FIELD_FIXED_LAUNCH_LOGS_VISIBLE, false))); + putSafely(out, FIELD_FIXED_LAUNCH_SPLASH_VISIBLE, src.optBoolean(FIELD_FIXED_LAUNCH_SPLASH_VISIBLE, defaults.optBoolean(FIELD_FIXED_LAUNCH_SPLASH_VISIBLE, false))); + putSafely(out, FIELD_FIXED_LAUNCH_LAUNCHER_VISIBLE, src.optBoolean(FIELD_FIXED_LAUNCH_LAUNCHER_VISIBLE, defaults.optBoolean(FIELD_FIXED_LAUNCH_LAUNCHER_VISIBLE, false))); + putSafely(out, FIELD_FIXED_LAUNCH_RUN_ON_BOOT, src.optBoolean(FIELD_FIXED_LAUNCH_RUN_ON_BOOT, defaults.optBoolean(FIELD_FIXED_LAUNCH_RUN_ON_BOOT, false))); + putSafely(out, FIELD_FIXED_LAUNCH_SLUG, src.optBoolean(FIELD_FIXED_LAUNCH_SLUG, defaults.optBoolean(FIELD_FIXED_LAUNCH_SLUG, false))); + putSafely(out, FIELD_FIXED_ABIS, src.optBoolean(FIELD_FIXED_ABIS, defaults.optBoolean(FIELD_FIXED_ABIS, false))); + putSafely(out, FIELD_FIXED_LIBS, src.optBoolean(FIELD_FIXED_LIBS, defaults.optBoolean(FIELD_FIXED_LIBS, true))); + putSafely(out, FIELD_FIXED_SIGNATURE_SCHEME, src.optBoolean(FIELD_FIXED_SIGNATURE_SCHEME, defaults.optBoolean(FIELD_FIXED_SIGNATURE_SCHEME, true))); + putSafely(out, FIELD_FIXED_KEY_STORE, src.optBoolean(FIELD_FIXED_KEY_STORE, defaults.optBoolean(FIELD_FIXED_KEY_STORE, true))); + putSafely(out, FIELD_FIXED_PERMISSIONS, src.optBoolean(FIELD_FIXED_PERMISSIONS, defaults.optBoolean(FIELD_FIXED_PERMISSIONS, true))); + + return out; + } + + @NonNull + private static JSONArray normalizeStringArray(@Nullable JSONArray source) { + LinkedHashSet dedup = new LinkedHashSet<>(); + if (source != null) { + for (int i = 0; i < source.length(); i++) { + String s = source.optString(i, "").trim(); + if (!s.isEmpty()) { + dedup.add(s); + } + } + } + JSONArray out = new JSONArray(); + for (String s : dedup) { + out.put(s); + } + return out; + } + + private static void putSafely(@NonNull JSONObject target, @NonNull String key, @Nullable Object value) { + try { + target.put(key, value); + } catch (JSONException ignored) { + // Ignore malformed value to keep profile storage resilient. + } + } +} diff --git a/app/src/main/java/org/autojs/autojs/ui/widget/RoundCheckboxWithText.kt b/app/src/main/java/org/autojs/autojs/ui/widget/RoundCheckboxWithText.kt index 03a0f3e2..b67f2dc9 100644 --- a/app/src/main/java/org/autojs/autojs/ui/widget/RoundCheckboxWithText.kt +++ b/app/src/main/java/org/autojs/autojs/ui/widget/RoundCheckboxWithText.kt @@ -5,12 +5,14 @@ import android.util.AttributeSet import android.view.MotionEvent import android.view.View import android.widget.CheckBox +import android.widget.CompoundButton import android.widget.LinearLayout import android.widget.TextView import org.autojs.autojs6.R /** * Created by SuperMonster003 on Nov 24, 2023. + * Modified by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) as of Mar 9, 2026. */ class RoundCheckboxWithText : LinearLayout { @@ -51,6 +53,10 @@ class RoundCheckboxWithText : LinearLayout { fun isChecked() = mCheckbox.isChecked + fun setOnCheckedChangeListener(listener: CompoundButton.OnCheckedChangeListener?) { + mCheckbox.setOnCheckedChangeListener(listener) + } + fun setText(text: String?) { mTextView.text = text } @@ -82,5 +88,4 @@ class RoundCheckboxWithText : LinearLayout { private fun isInside(v: View, e: MotionEvent): Boolean { return e.x in 0f..v.measuredWidth.toFloat() && e.y in 0f..v.measuredHeight.toFloat() } - -} \ No newline at end of file +} diff --git a/app/src/main/res/drawable/round_checkbox.xml b/app/src/main/res/drawable/round_checkbox.xml index 9b311975..2d8b8852 100644 --- a/app/src/main/res/drawable/round_checkbox.xml +++ b/app/src/main/res/drawable/round_checkbox.xml @@ -1,7 +1,6 @@ - - - + + diff --git a/app/src/main/res/layout/activity_build.xml b/app/src/main/res/layout/activity_build.xml index d8dca221..d69800bc 100644 --- a/app/src/main/res/layout/activity_build.xml +++ b/app/src/main/res/layout/activity_build.xml @@ -16,10 +16,18 @@ + app:contentInsetEndWithActions="2dp" + app:contentInsetStartWithNavigation="0dp" + app:popupTheme="@style/AppTheme.PopupOverlay"> + + + + + + + + + + + + + + + + + + + + + - - - - - - - @@ -176,7 +247,6 @@ android:layout_height="wrap_content" android:inputType="text" android:imeOptions="actionNext" /> - - - - - - + + + + + + + + + + + + + + - - - - - - - - \ No newline at end of file + diff --git a/app/src/main/res/menu/menu_build_profile_options.xml b/app/src/main/res/menu/menu_build_profile_options.xml new file mode 100644 index 00000000..5104ea40 --- /dev/null +++ b/app/src/main/res/menu/menu_build_profile_options.xml @@ -0,0 +1,16 @@ + +

+ + + + + + diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index c37b6de1..52045e9e 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -119,9 +119,11 @@ تخلَّ إيقاف إيقاف الاتصال + تفعيل اضافة متقدم تصحيح العنوان + تفويض @string/text_back يلغي يلغي @@ -231,6 +233,7 @@ فشل في التحقق من التحديثات يجب أن يتبع القولون عنوان IP صالحًا لا يمكن أن تكون البوصلة لاغية + يتطلب تسجيل السكربتات توفر شرط واحد على الاقل مما يلي:\n- صلاحيات Root\n- صلاحيات Shizuku لا يمكن الاتصال بالخادم البعيد: %s فشل الاتصال بـ \"%1$s\". انتهت مهلة الاتصال (%d مللي ثانية) @@ -254,6 +257,7 @@ فشل تحويل القيمة %s إلى قابل للرسم فشل النسخ فشل في انشاء + فشل في تفعيل الاضافة فشل فتح صفحة الإعدادات فشل منح Shizuku حق الوصول فشل إنشاء المثيل \"%s\" @@ -270,6 +274,7 @@ تعذّر جلب ملف version.properties لتحليل معلومات الإصدار فشل في إلغاء وصول Shizuku فشل في تشغيل البرنامج النصي + فشل الحفظ تعذّر حفظ إعدادات المشروع الملف في المسار \"%1$s\" غير موجود لا يمكن حظر مؤشر ترابط واجهة المستخدم. حاول تشغيل %s() في الخيط الفرعي أو النصف الفرعي @@ -330,6 +335,9 @@ بناء جملة نمط غير صالح ملف APK للمكوّن الإضافي لا يحتوي على الموارد المطلوبة لـ variant=\"%1$s\": %2$s. ملف APK للمكوّن الإضافي لا يحتوي على مكتبات native المطلوبة: %1$s. + الاضافة \"%1$s\" غير مُفوّضة في مركز الاضافات + الاضافة \"%1$s\" غير مُمكّنة في مركز الاضافات + لم يتم العثور على الاضافة \"%1$s\" ضمن التطبيقات المثبتة أعاد المكوّن الإضافي %1$s معلومات فارغة. أعاد المكوّن الإضافي %1$s variant غير صالح: %2$s. رقم المنفذ أكثر من 65535 @@ -371,6 +379,7 @@ نوع نتيجة غير معروف {name: %s ، params: %s} محدد غير معروف {الاسم: %s ، اكتب: %s} نوع غير معروف: %s + طريقة اتصال الاضافة غير مدعومة لا يمكن ضغط تنسيق WebP-Lossless باستخدام معامل الجودة؛ استخدم JPEG/PNG/WebP-Lossy بدلاً من ذلك الملف غير موجود او غير قابل للقراءة الملف غير موجود أو قابلاً للقراءة: %s @@ -387,6 +396,7 @@ تأخير قبل الحلقة 0 للحلقة اللانهائية يتم دعم IPv4 و IPv6 وأسماء النطاقات. + جرّب الضغط على زر \"تفعيل\" لتفعيل الاضافة مرة واحدة.\nاذا نجح التفعيل، فسيتم تشغيل الزر تلقائيا خلال فترة زمنية معينة. أدخل عنوان URL يشير إلى ملحق (Plugin) بعيد.\nمثال: \"https://example.com/plugin.apk\". حذف نهائيا نقل الى سلة المحذوفات @@ -433,6 +443,7 @@ آخر تثبيت آخر إزالة آخر تحديث + الالية حجم الحزمة إصدار متاح هل أنت متأكد من تجاهل إصدار التحديث الحالي؟\nيمكنك إدارة جميع الإصدارات التي تم تجاهلها بواسطة إعدادات التطبيق. @@ -463,6 +474,7 @@ أضف اختصارات إلى المشغل ابدأ أو توقف عن التسجيل الذي يتم التحكم فيه بواسطة مفتاح خفض مستوى الصوت عند عرض الزر العائم اضغط على مفتاح \"رفع الصوت\" لإيقاف تشغيل جميع البرامج النصية + ": " وحدة التخزين الداخلية خدمة إمكانية الوصول مطلوب من خلال العملية التلقائية البرنامج النصي (انقر فوق ، اضغط لفترة طويلة ، شريحة ، إلخ). @@ -485,6 +497,7 @@ التمرير للأمام (التمرير) تعيين النص (setText) عمل + تم التفعيل بنجاح لا مثبت APK هناك حاجة إلى أداة ADB إضافة مكتبة ألوان @@ -544,8 +557,11 @@ كود إصدار التطبيق اسم إصدار التطبيق مظهر + جارٍ تطبيق الموارد الثنائية يجب ملء حقل واحد على الأقل من [الاسم، اسم المنظمة، وحدة التنظيم، رمز الدولة، الولاية أو المقاطعة، المدينة أو المنطقة، الشارع] ينسب + تفويض الاضافة + هذه اضافة من طرف ثالث. يرجى الانتباه الى مصدر الاضافة وامان الاستخدام.\n\nاضغط زر \"تفويض\" لتمكين الاضافة. تحقق من التحديثات التلقائية تحقق من وجود التحديثات تلقائيًا وعرض تناول وجبة خفيفة على الصفحة الرئيسية وضع الليل التلقائي @@ -554,8 +570,27 @@ خلف عمل مهمة البث + بناء بناء APK + اكتمل البناء + ملف البناء + لا يمكن حذف الملف الافتراضي + لا يمكن حذف ملف project.json + حذف الملف + حقول الملف + اعداد حقول الملف + سيتم حفظ الحقول المحددة كقيم ثابتة في هذا الملف. + المزيد من اجراءات الملف + لا يمكن استخدام اسماء ملفات محجوزة (Default, project.json) + اسم ملف البناء + ملف جديد + توجد تغييرات غير محفوظة في اعدادات البناء الحالية. + توجد تغييرات غير محفوظة في اعدادات البناء الحالية، وسيتم كتابتها في project.json. + هل تريد حفظ التغييرات قبل المتابعة? نجح بناء + جارٍ بناء APK + جارٍ بناء الموارد + مسار APK المبني يلغي إلغاء لا يمكن حذف ملف التعريف الافتراضي @@ -587,6 +622,9 @@ اختر مسار الاستعادة المدينة أو المنطقة اسم الفئة / الحزمة + تنظيف + اكتمل التنظيف + جارٍ تنظيف مساحة العمل صافي مسح اختيار الملف مسح السيناريو قبل التنفيذ @@ -615,6 +653,8 @@ التوافق ثقة تكوين + جارٍ ضبط manifest + جارٍ ضبط اسم الحزمة هل أنت متأكد من مسح جميع العناصر؟ هل تريد مسح السجل? سيتم مسح السجل ادناه\n\n[ %1$s ]\n\nهل تريد المتابعة? @@ -630,6 +670,7 @@ لا يمكن إنشاء الاتصال فشل الاتصال وحدة التحكم + المحتوى يكمل ينسخ نسخ جميع @@ -644,8 +685,18 @@ نسخ إلى الحافظة نسخ القيمة جارٍ النسخ... + جارٍ نسخ asset + جارٍ نسخ assets الى + جارٍ نسخ المجلد + جارٍ نسخ الملف + جارٍ نسخ المكتبات لـ ABI + جارٍ نسخ المكتبة + جارٍ نسخ المكتبات الاصلية + جارٍ نسخ مجلد المشروع + جارٍ نسخ ملف السكربت رمز الدولة (XX) رمز الدولة يجب أن يكون حرفين كبيرين + جارٍ انشاء APK غير موقّع اعدادات الصفحة الحالية النسخة الحالية مهام يومية @@ -728,10 +779,12 @@ تمكين خدمة إمكانية الوصول مع إعدادات آمنة تفعيل الملحق مفعّل + جارٍ تشفير السكربت خطأ فشل نسخ الملف: %s تقرير الشوائب تقديري + معلومات الاستثناء نفذ - اعدم تنفيذ الرمز [%s] انتهى في %s.\n @@ -744,6 +797,11 @@ تصدير تمديد كائنات JavaScript المدمجة التمدد + تم استخراج assets الاضافة + تم استخراج مكتبات الاضافة + جارٍ استخراج asset الاضافة + جارٍ استخراج ملف so للاضافة + جارٍ استخراج APK القالب باءت بالفشل فشل في البناء فشل في إنشاء مفتاح التوقيع @@ -764,6 +822,7 @@ فشل في تسجيل فشل في تقديم فشل الجلب + فشل حفظ project.json فشل حفظ المشروع البعيد في التخزين المحلي فشل في إرسال إدخالات السجل فشل التحديث @@ -814,6 +873,7 @@ زر الإخفاء إخفاء هذه العقدة إخفاء العقدة ذات الإطار المماثل + تلميح السجل تم مسح السجل أيقونة @@ -869,6 +929,11 @@ أحدث حزمة إطلاق التكوين إطلاق الأخطاء + اظهار ايقونة التطبيق في المشغل + اظهار السجلات عند التشغيل + تشغيل السكربت عند الاقلاع + نص شعار شاشة البداية + اظهار شاشة البداية عند التشغيل رمز المشغّل اختصارات المشغل قد يؤدي تبديل رموز المشغّل على بعض الأجهزة إلى فقدان جميع اختصارات AutoJs6 الحالية, يرجى المتابعة بحذر @@ -984,9 +1049,9 @@ يسمح للتطبيق بإجراء عمليات الشراء داخل التطبيق يسمح للتطبيق بالوصول إلى أجهزة Bluetooth يسمح للتطبيق بتهيئة أجهزة Bluetooth + السماح للتطبيق بالإعلان عبر Bluetooth السماح للتطبيق بالوصول إلى أجهزة Bluetooth وحالة الاتصال السماح للتطبيق بالبحث عن أجهزة Bluetooth القريبة - السماح للتطبيق بالإعلان عبر Bluetooth يسمح للتطبيق بإرسال نية لإغلاق مربعات حوار النظام يسمح للتطبيق بإجراء مكالمات هاتفية يسمح للتطبيق بالوصول إلى الكاميرا @@ -1070,15 +1135,28 @@ اسم الإدخال الرجاء الانتظار... يرجى المحاولة مرة أخرى لاحقًا... + مفعّل + يوصى بالتفعيل + تم رفض التفويض + يتطلب تفويضا + مفوّض مركز الاضافات تفاصيل الملحق + رسمي + موثوق الاضافات موقع المؤشر فشل تبديل \"موقع المؤشر\".\nالوصول إلى الجذر مطلوب. نشر الإخطارات لضمان عمل خدمات المقدّمة في AutoJs6 وغيرها بشكل طبيعي، وتمكين السكربتات من نشر الإشعارات، يجب منح AutoJs6 إذن \"نشر الإشعارات\". البرنامج النصي مسبقا + تحضير + اكتمل التحضير خطة... + جارٍ تحضير مجلد assets + جارٍ تحضير اعدادات البناء + جارٍ تحضير keystore + جارٍ تحضير مساحة العمل محتوى مربع الحوار المعين مسبقاً عنوان مربع الحوار المعين مسبقاً اضغط مرة أخرى لرفض الحوار @@ -1087,14 +1165,19 @@ معاينة سجل العملية جارٍ المعالجة + جارٍ معالجة المصدر مشروع موقع المشروع وصول وسائل الإعلام المشروع مستعجل + %1$s: %1$s: %2$s %1$s: %2$d %3$s %1$s: %2$d%3$s + جارٍ التقليم يترك + جارٍ اعادة توقيع APK + جارٍ قراءة موارد شاشة البدء مُستَحسَن انتهى التسجيل موجه التسجيل @@ -1120,6 +1203,7 @@ يحل محل استبدل كل شيء يستبدل + جارٍ استبدال الملف عنوان URL لمستودع امتداد VSCode إرسال نجح يتطلب إصدار Android OS %s (API %s) ولكن الحالي هو %s (API %s) @@ -1128,6 +1212,7 @@ نجحت إعادة تعيين إعادة تعيين في البداية إعادة التعيين هي فقط للعينات + جارٍ تحليل مكتبات الاضافة الاصلية إعادة بدء استراتيجية إعادة التشغيل استعادة @@ -1169,6 +1254,7 @@ حفظ الاعدادات باسم احفظ حفظ في + جارٍ الحفظ... المحرّك تأخير البدء تأخير طلب إذن التقاط الشاشة @@ -1189,6 +1275,7 @@ حدد ملف للتحميل حدد أيقونة حدد صورة + الاضافة المحددة إرسال انشاء اختصار وضع الخادم @@ -1205,6 +1292,9 @@ عرض في حدود التصميم عرض في التسلسل الهرمي للتخطيط إظهار معلومات القطعة + توقيع + اكتمل التوقيع + اكتملت مرحلة التوقيع خوارزمية التوقيع تكوين التوقيع خطة التوقيع @@ -1222,6 +1312,7 @@ الوقت (الاحدث اولا) المصدر مسار رمز المصدر + اكتملت معالجة المصدر أذونات خاصة وضع مستقر نجمة @@ -1260,6 +1351,7 @@ مهمة توقيت محرك جدولة المهام المؤقتة توقيت + العنوان قيد الاختيار تبديل الكل أدوات @@ -1284,6 +1376,7 @@ وصف غير معروف عنوان غير معروف إصدار غير معروف + تم انشاء APK غير موقّع لم يتم التحقق قابل للتحديث تحديث @@ -1291,6 +1384,7 @@ تم مسح الحالات التي تم فحصها في وقت لاحق رأي + جارٍ تحديث اعدادات المشروع الاستخدام الإحصائيات الوصول استخدم اختصار Android 7.0 استخدام الرمز الافتراضي @@ -1300,6 +1394,7 @@ اسم المستخدم لا يمكن أن يكون فارغًا استخدم محدد DESC استخدم محدد المعرف + جارٍ استخدام keystore استخدم محدد النص المدة (سنوات) مدة الصلاحية لا يمكن أن تكون فارغة @@ -1331,86 +1426,12 @@ مسار دليل العمل اكتب إعدادات الأمان كتابة إعدادات النظام + جارٍ كتابة ايقونة التطبيق + جارٍ كتابة manifest + جارٍ كتابة اعدادات المشروع + جارٍ كتابة resources.arsc + جارٍ كتابة APK الموقّع النوافذ المنبثقة في الخلفية لم يتم حفظ الاعدادات. هل تريد المتابعة? لم يتم حفظ الاعدادات. هل تريد الخروج? - فشل الحفظ - جارٍ الحفظ... - ": " - فشل في تفعيل الاضافة - معلومات الاستثناء - تلميح - جرّب الضغط على زر \"تفعيل\" لتفعيل الاضافة مرة واحدة.\nاذا نجح التفعيل، فسيتم تشغيل الزر تلقائيا خلال فترة زمنية معينة. - تفعيل - تم التفعيل بنجاح - تفويض الاضافة - هذه اضافة من طرف ثالث. يرجى الانتباه الى مصدر الاضافة وامان الاستخدام.\n\nاضغط زر \"تفويض\" لتمكين الاضافة. - تفويض - رسمي - مفوّض - يتطلب تفويضا - تم رفض التفويض - يوصى بالتفعيل - مفعّل - موثوق - الالية - الاضافة \"%1$s\" غير مُمكّنة في مركز الاضافات - الاضافة \"%1$s\" غير مُفوّضة في مركز الاضافات - لم يتم العثور على الاضافة \"%1$s\" ضمن التطبيقات المثبتة - طريقة اتصال الاضافة غير مدعومة - %1$s: - العنوان - المحتوى - جارٍ بناء APK - مسار APK المبني - تنظيف - توقيع - بناء - تحضير - جارٍ تحضير مساحة العمل - جارٍ استخراج APK القالب - اكتمل التحضير - جارٍ نسخ مجلد المشروع - جارٍ نسخ ملف السكربت - اكتملت معالجة المصدر - جارٍ نسخ المجلد - جارٍ نسخ الملف - جارٍ تشفير السكربت - جارٍ استبدال الملف - جارٍ تحضير اعدادات البناء - جارٍ قراءة موارد شاشة البدء - جارٍ ضبط manifest - جارٍ ضبط اسم الحزمة - جارٍ نسخ assets الى - جارٍ معالجة المصدر - جارٍ تطبيق الموارد الثنائية - جارٍ نسخ المكتبات الاصلية - جارٍ تحديث اعدادات المشروع - اكتملت مرحلة التوقيع - جارٍ كتابة اعدادات المشروع - جارٍ بناء الموارد - اكتمل البناء - جارٍ كتابة resources.arsc - جارٍ كتابة manifest - جارٍ كتابة ايقونة التطبيق - جارٍ نسخ asset - جارٍ تحضير مجلد assets - جارٍ نسخ المكتبة - جارٍ تحضير keystore - تم انشاء APK غير موقّع - جارٍ انشاء APK غير موقّع - جارٍ استخدام keystore - جارٍ اعادة توقيع APK - جارٍ كتابة APK الموقّع - اكتمل التوقيع - اكتمل التنظيف - جارٍ تنظيف مساحة العمل - جارٍ تحليل مكتبات الاضافة الاصلية - جارٍ نسخ المكتبات لـ ABI - الاضافة المحددة - تم استخراج مكتبات الاضافة - تم استخراج assets الاضافة - جارٍ استخراج asset الاضافة - جارٍ استخراج ملف so للاضافة - يتطلب تسجيل السكربتات توفر شرط واحد على الاقل مما يلي:\n- صلاحيات Root\n- صلاحيات Shizuku \ No newline at end of file diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 76e8e9ab..673f03fa 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -114,9 +114,11 @@ Abandon Abort Abort + Activate Add Advanced Amend + Authorize @string/text_back Cancel Cancel @@ -226,6 +228,7 @@ Failed to check for updates Colon must follow a valid IP address Compass cannot be null + Script recording requires at least one of the following conditions:\n- Root access\n- Shizuku access Cannot connect to the remote server: %s Failed to connect to \"%1$s\". Connection timed out after %d ms @@ -249,6 +252,7 @@ Failed to convert value %s into a Drawable Failed to copy Failed to create + Failed to enable the plugin Failed to open the settings page Failed to grant Shizuku access Failed to instantiate \"%s\" @@ -265,6 +269,7 @@ Failed to retrieve version.properties to parse version information Failed to revoke Shizuku access Failed to run script + Failed to save Failed to save project config File in path \"%1$s\" does not exist UI thread cannot be blocked. Try running %s() in sub-thread or sub-script @@ -325,6 +330,9 @@ Invalid pattern syntax Plugin APK does not contain required assets for variant=\"%1$s\": %2$s. Plugin APK does not contain required native libraries: %1$s. + Plugin \"%1$s\" is not authorized in Plugin Center + Plugin \"%1$s\" is not enabled in Plugin Center + Plugin \"%1$s\" not found in installed apps %1$s plugin returned empty info. %1$s plugin returned invalid variant: %2$s. Port number over 65535 @@ -366,6 +374,7 @@ Unknown result type {name: %s, params: %s} Unknown selector {name: %s, type: %s} Unknown type: %s + Unsupported plugin connection Format WebP-Lossless cannot be compressed with a quality parameter, use JPEG/PNG/WebP-Lossy instead File does not exist or readable File does not exist or readable: %s @@ -382,6 +391,7 @@ Delay before loop 0 for infinite loop IPv4, IPv6 and domain are supported. + Try clicking the \"Activate\" button to activate the plugin once.\nIf activation is successful, the button will automatically turn on within a certain period of time. Enter a URL pointing to a remote plugin address.\nFor example \"https://example.com/plugin.apk\". Delete permanently Move to trash @@ -428,6 +438,7 @@ Last install Last uninstall Last update + Mechanism Package size Updatable ver. Are you sure to ignore current update version?\nYou can manage all ignored versions by app settings. @@ -458,6 +469,7 @@ Add shortcuts to launcher Start or stop recording controlled by \"Volume Down\" key when floating button is showing Press \"Volume Up\" key to stop all running scripts + ": " Internal Storage Accessibility service Required by the script automatic operation (click, long press, slide, etc.). @@ -480,6 +492,7 @@ Scroll forward (scrollForward) Set text (setText) Action + Activated successfully No APK installer ADB tool is needed Add a color library @@ -539,8 +552,11 @@ App version code App version name Appearance + Applying binary resources At least one field from [Full Name, Organization Name, Organizational Unit, Country Code, State or Province, City or Locality, Street] must be filled Attribute + Authorize Plugin + This is a third-party plugin. Please pay attention to the plugin source and usage safety.\n\nClick the \"Authorize\" button to enable the plugin. Auto check for updates Check for updates automatically and show a snackbar on homepage Auto night mode @@ -549,8 +565,27 @@ Back Action Broadcast task + Build Build APK + Build completed + Build profile + Default profile cannot be deleted + project.json profile cannot be deleted + Delete profile + Profile fields + Configure profile fields + Checked fields are saved as fixed values in this profile. + More profile actions + Cannot use reserved profile names (Default, project.json) + Build profile name + New profile + Current build configuration has unsaved changes. + Current build configuration has unsaved changes and will be written to project.json. + Save changes before continuing? Build succeeded + Building APK + Building resources + Built APK file path Cancel Cancel Default profile cannot be deleted @@ -582,6 +617,9 @@ Choose restore path City or Locality Class / Package name + Clean + Clean completed + Cleaning workspace Clear Clear file selection Clear pre-execute script @@ -610,6 +648,8 @@ Compatibility Confidence Config + Configuring manifest + Configuring package name Are you sure to clear all items? Are you sure to clear the history? The history below will be cleared\n\n[ %1$s ]\n\nAre you sure to clear? @@ -625,6 +665,7 @@ Connection cannot be established Connection failed Console + Content Continue Copy Copy all @@ -639,8 +680,18 @@ Copy to clipboard Copy value Copying... + Copying asset + Copying assets to + Copying directory + Copying file + Copying libraries for ABI + Copying library + Copying native libraries + Copying project directory + Copying script file Country Code (XX) Country code must be two capital letters + Creating unsigned APK Current page configuration Current version Daily task @@ -723,10 +774,12 @@ Enable accessibility service with secure settings timed out Enable plugin Enabled + Encrypting script Error Failed to copy file: %s Bug report Estimated + Exception info Execute Execute code [%s] finished in %s seconds.\n @@ -739,6 +792,11 @@ Exported Extending JavaScript build-in objects Extensibility + Extracted plugin assets + Extracted plugin libraries + Extracting plugin asset + Extracting plugin so + Extracting template APK Failed Failed to build Failed to create signature key @@ -759,6 +817,7 @@ Failed to register Failed to submit Failed to retrieve + Failed to save project.json Failed to save remote project to local storage Failed to send log entries Failed to update @@ -809,6 +868,7 @@ Hide button Hide this node Hide same frame nodes + Hint History The history has been cleared Icon @@ -864,6 +924,11 @@ Latest package Launch config Launch debugger + Show app icon in launcher + Show logs on launch + Run script on boot + Splash slug text + Show splash screen on launch Launcher icon Launcher shortcuts Switching launcher icons on some devices may cause all existing AutoJs6 shortcuts to be lost, please proceed with caution @@ -979,9 +1044,9 @@ Allow the app to perform in-app purchases Allow the app to access Bluetooth devices Allow the app to configure Bluetooth devices + Allow the app to advertise via Bluetooth Allow the app to access Bluetooth devices and connection state Allow the app to scan for nearby Bluetooth devices - Allow the app to advertise via Bluetooth Allow the app to send an intent to close system dialogs Allow the app to make phone calls Allow the app to access the camera @@ -1065,15 +1130,28 @@ Input name Please wait... Please wait a moment before trying again... + Activated + Activation recommended + Authorization denied + Authorization required + Authorized Plugin center Plugin details + Official + Trusted Plugins Pointer location Toggle \"pointer location\" failed.\nRoot access is required. Post notifications To ensure that AutoJs6 foreground services, etc. can work properly and that scripts can post notifications, AutoJs6 must be granted the \"post notifications\" permission. Pre-execute script + Prepare + Prepare completed Preparing... + Preparing assets dir + Preparing build config + Preparing keystore + Preparing workspace Preset dialog content Preset dialog title Press again to dismiss the dialog @@ -1082,14 +1160,19 @@ Preview Process log Processing + Processing source Project Project location Project media access Prompt + %1$s: %1$s: %2$s %1$s: %2$d %3$s %1$s: %2$d%3$s + Pruning Quit + Re-signing APK + Reading splash resources Recommended Recording finished Recording prompt @@ -1115,6 +1198,7 @@ Replace Replace all Replace + Replacing file Repository URL of VSCode extension Submit succeeded Requires Android OS version %s (API %s) but current is %s (API %s) @@ -1123,6 +1207,7 @@ Reset succeeded Reset initially Reset is only for samples + Resolving plugin native libraries Restart Restart strategy Restore @@ -1164,6 +1249,7 @@ Save configuration as Save Save to + Saving... Backend Start delay Screen capture permission request delay @@ -1184,6 +1270,7 @@ Select file to upload Select icon Select an image + Selected plugin Send Create shortcut Server mode @@ -1200,6 +1287,9 @@ View in layout bounds View in layout hierarchy Show widget information + Sign + Sign completed + Sign stage completed Signature Algorithm Signature Configuration Signature Scheme @@ -1217,6 +1307,7 @@ Time (newest first) Source Source code path + Source processing completed Special permissions Stable mode Star @@ -1255,6 +1346,7 @@ Timed task Timed task scheduling engine Timing + Title To be chosen Toggle all Tools @@ -1279,6 +1371,7 @@ Unknown Description Unknown Title Unknown Version + Unsigned APK created Unverified Updatable Update @@ -1286,6 +1379,7 @@ Updates checked states cleared Later View + Updating project config Usage stats access Use Android 7.0 shortcut Use default icon @@ -1295,6 +1389,7 @@ Username cannot be empty Use desc selector Use id selector + Using keystore Use text selector Validity (Years) Validity years cannot be empty @@ -1326,86 +1421,12 @@ Working directory path Write security settings Write system settings + Writing app icon + Writing manifest + Writing project config + Writing resources.arsc + Writing signed APK Display pop-up windows while running in the background The settings has not been saved, are you sure to continue the operation? The settings has not been saved, are you sure to exit? - Failed to save - Saving... - ": " - Failed to enable the plugin - Exception info - Hint - Try clicking the \"Activate\" button to activate the plugin once.\nIf activation is successful, the button will automatically turn on within a certain period of time. - Activate - Activated successfully - Authorize Plugin - This is a third-party plugin. Please pay attention to the plugin source and usage safety.\n\nClick the \"Authorize\" button to enable the plugin. - Authorize - Official - Authorized - Authorization required - Authorization denied - Activation recommended - Activated - Trusted - Mechanism - Plugin \"%1$s\" is not enabled in Plugin Center - Plugin \"%1$s\" is not authorized in Plugin Center - Plugin \"%1$s\" not found in installed apps - Unsupported plugin connection - %1$s: - Title - Content - Building APK - Built APK file path - Clean - Sign - Build - Prepare - Preparing workspace - Extracting template APK - Prepare completed - Copying project directory - Copying script file - Source processing completed - Copying directory - Copying file - Encrypting script - Replacing file - Preparing build config - Reading splash resources - Configuring manifest - Configuring package name - Copying assets to - Processing source - Applying binary resources - Copying native libraries - Updating project config - Sign stage completed - Writing project config - Building resources - Build completed - Writing resources.arsc - Writing manifest - Writing app icon - Copying asset - Preparing assets dir - Copying library - Preparing keystore - Unsigned APK created - Creating unsigned APK - Using keystore - Re-signing APK - Writing signed APK - Sign completed - Clean completed - Cleaning workspace - Resolving plugin native libraries - Copying libraries for ABI - Selected plugin - Extracted plugin libraries - Extracted plugin assets - Extracting plugin asset - Extracting plugin so - Script recording requires at least one of the following conditions:\n- Root access\n- Shizuku access \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 97257bf5..fcbc6388 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -117,9 +117,11 @@ Abandonar Abortar Interrumpir conexión + Activar Anadir Avanzado Corregir dirección + Autorizar @string/text_back Cancelar Cancelar @@ -229,6 +231,7 @@ Fallo en la comprobación de las actualizaciones Dos puntos deben seguir a una dirección IP válida La brújula no puede ser nula + La grabacion de scripts requiere al menos una de las siguientes condiciones:\n- Acceso root\n- Acceso Shizuku No se puede conectar con el servidor remoto: %s No se pudo conectar a \"%1$s\". La conexión agotó el tiempo de espera (%d ms) @@ -252,6 +255,7 @@ Fallo al convertir el valor %s en un Dibujable Error al copiar Fallo al crear + No se pudo activar el plugin No se pudo abrir la página de ajustes Fallo en la concesión de permisos Shizuku Error al instanciar \"%s\" @@ -268,6 +272,7 @@ No se pudo obtener version.properties para analizar la información de la versión Fallo en la revocación de permisos Shizuku Error al ejecutar el script + Error al guardar No se pudo guardar la configuración del proyecto El archivo en la ruta \"%1$s\" no existe El hilo de la interfaz de usuario no se puede bloquear. Intenta ejecutar %s() en un subhilo o subguión @@ -328,6 +333,9 @@ Sintaxis de patrón no válida El APK del plugin no contiene los recursos necesarios para variant=\"%1$s\": %2$s. El APK del plugin no contiene las bibliotecas nativas requeridas: %1$s. + El plugin \"%1$s\" no esta autorizado en el Centro de plugins + El plugin \"%1$s\" no esta habilitado en el Centro de plugins + No se encontro el plugin \"%1$s\" en las apps instaladas El plugin %1$s devolvió información vacía. El plugin %1$s devolvió una variante no válida: %2$s. Número de puerto superior a 65535 @@ -369,6 +377,7 @@ Tipo de resultado desconocido {nombre: %s, parámetro: %s} Selector desconocido {nombre: %s, tipo: %s} Tipo desconocido: %s + Conexion de plugin no compatible El formato WebP-Lossless no se puede comprimir con un parámetro de calidad; usa JPEG/PNG/WebP-Lossy en su lugar El archivo no existe o no se puede leer El archivo no existe o no se puede leer: %s @@ -385,6 +394,7 @@ Retraso antes del bucle 0 para bucle infinito Se admiten IPv4, IPv6 y dominios. + Prueba a pulsar el boton \"Activar\" para activar el plugin una vez.\nSi la activacion se realiza correctamente, el boton se activara automaticamente en un periodo de tiempo. Introduce una URL que apunte a la dirección de un complemento remoto.\nPor ejemplo, \"https://example.com/plugin.apk\". Eliminar definitivamente Mover a la papelera @@ -431,6 +441,7 @@ Última inst. Última desinst. Última act. + Mecanismo Tamaño paquete Vers. actualiz. ¿Está seguro de ignorar la versión actual de la actualización?\nPuedes gestionar todas las versiones ignoradas en los ajustes de la aplicación. @@ -461,6 +472,7 @@ Añadir accesos directos al lanzador Iniciar o detener la grabación controlada por la tecla de bajar el volumen cuando se muestra el botón flotante Pulse la tecla \"Subir volumen\" para detener todos los scripts en ejecución + ": " Almacenamiento interno Servicio de accesibilidad Requerido por el funcionamiento automático del script (clic, pulsación larga, deslizamiento, etc.). @@ -483,6 +495,7 @@ Desplazamiento hacia delante (scrollForward) Establecer texto (setText) Acción + Activado correctamente No hay instalador de APK Se necesita la herramienta ADB Agregar biblioteca de colores @@ -542,8 +555,11 @@ Código de la versión de la aplicación Nombre de la versión de la aplicación Aspecto + Aplicando recursos binarios Al menos uno de los campos [Nombre completo, Nombre de la organización, Unidad organizacional, Código de país, Estado o provincia, Ciudad o localidad, Calle] debe estar lleno Atributo + Autorizar plugin + Este es un plugin de terceros. Presta atencion al origen del plugin y a la seguridad de uso.\n\nPulsa el boton \"Autorizar\" para habilitar el plugin. Comprobación automática de actualizaciones Comprueba las actualizaciones automáticamente y muestra una barra de snacks en la página de inicio Modo nocturno automático @@ -552,8 +568,27 @@ Volver Acción Tarea de difusión + Compilar Construir APK + Compilacion completada + Perfil de compilacion + No se puede eliminar el perfil predeterminado + No se puede eliminar el perfil project.json + Eliminar perfil + Campos del perfil + Configurar campos del perfil + Los campos marcados se guardaran como valores fijos en este perfil. + Mas acciones del perfil + No se pueden usar nombres reservados de perfil (Default, project.json) + Nombre del perfil de compilacion + Nuevo perfil + La configuracion de compilacion actual tiene cambios sin guardar. + La configuracion de compilacion actual tiene cambios sin guardar y se escribira en project.json. + ¿Guardar los cambios antes de continuar? Construir con éxito + Compilando APK + Compilando recursos + Ruta del APK generado Cancelar Cancel No se puede eliminar el perfil predeterminado @@ -585,6 +620,9 @@ Elegir ruta de restauracion Ciudad o localidad Nombre de la clase/paquete + Limpiar + Limpieza completada + Limpiando el espacio de trabajo Borrar Borrar selección de archivos Borrar script de pre-ejecución @@ -613,6 +651,8 @@ Compatibilidad Confianza Configuración + Configurando manifest + Configurando nombre de paquete ¿Seguro que desea borrar todos los elementos? ¿Seguro que quieres borrar el historial? Se borrara el historial siguiente\n\n[ %1$s ]\n\n¿Seguro que quieres borrarlo? @@ -628,6 +668,7 @@ No se puede establecer la conexión Conexión fallida Consola + Contenido Continuar Copiar Copiar todo @@ -642,8 +683,18 @@ Copiar al portapapeles Copiar valor Copiando... + Copiando asset + Copiando assets a + Copiando directorio + Copiando archivo + Copiando bibliotecas para ABI + Copiando biblioteca + Copiando bibliotecas nativas + Copiando directorio del proyecto + Copiando archivo de script Código de país (XX) El código del país debe ser de dos letras mayúsculas + Creando APK sin firmar Configuracion de la pagina actual Versión actual Tarea diaria @@ -726,10 +777,12 @@ Habilitación del servicio de accesibilidad con configuración segura agotada Activar complemento Activado + Cifrando script Error No se ha podido copiar el archivo: %s Informe de error Estimado + Info de la excepcion Ejecutar Ejecutar código [%s] terminó en %s segundos.\n @@ -742,6 +795,11 @@ Exportado Extensión de los objetos incorporados de JavaScript Extensibilidad + Assets del plugin extraidos + Bibliotecas del plugin extraidas + Extrayendo asset del plugin + Extrayendo archivo so del plugin + Extrayendo APK plantilla Falló Fallo en la construcción Error al crear la clave de firma @@ -762,6 +820,7 @@ Fallo en el registro Fallo al enviar Error al obtener + No se pudo guardar project.json Error al guardar el proyecto remoto en el almacenamiento local Error al enviar entradas de registro Error al actualizar @@ -812,6 +871,7 @@ Botón de ocultar Ocultar este nodo Ocultar nodo del mismo marco + Sugerencia Historial El historial se ha borrado Icono @@ -867,6 +927,11 @@ Último paquete Iniciar la configuración Iniciar el depurador + Mostrar icono de la app en el lanzador + Mostrar registros al iniciar + Ejecutar script al iniciar + Texto del lema de inicio + Mostrar pantalla de inicio al iniciar Ícono del iniciador Atajos del lanzador Cambiar los íconos del iniciador en algunos dispositivos puede provocar la pérdida de todos los accesos directos existentes de AutoJs6, proceda con precaución @@ -982,9 +1047,9 @@ Permitir que la aplicación realice compras dentro de la aplicación Permitir que la aplicación acceda a dispositivos Bluetooth Permitir que la aplicación configure dispositivos Bluetooth + Permitir que la aplicación se anuncie mediante Bluetooth Permitir que la aplicación acceda a los dispositivos Bluetooth y al estado de conexión Permitir que la aplicación busque dispositivos Bluetooth cercanos - Permitir que la aplicación se anuncie mediante Bluetooth Permitir que la aplicación envíe una intención para cerrar los cuadros de diálogo del sistema Permitir que la aplicación realice llamadas telefónicas Permitir que la aplicación acceda a la cámara @@ -1068,15 +1133,28 @@ Nombre de entrada Por favor, espere... Por favor, inténtalo de nuevo más tarde... + Activado + Activacion recomendada + Autorizacion denegada + Requiere autorizacion + Autorizado Centro de plugins Detalles del complemento + Oficial + Confiable Plugins Ubicación del puntero Falló la conmutación de la \"ubicación del puntero\".\nSe requiere acceso a la raíz. Notificaciones postales Para garantizar que los servicios en primer plano de AutoJs6, etc. funcionen correctamente y que los scripts puedan publicar notificaciones, AutoJs6 debe recibir el permiso de \"publicar notificaciones\". Ejecutar previamente el script + Preparar + Preparacion completada Preparando... + Preparando dir de assets + Preparando configuracion de compilacion + Preparando keystore + Preparando el espacio de trabajo Contenido del diálogo predefinido Título de diálogo predefinido Pulse de nuevo para salir del diálogo @@ -1085,14 +1163,19 @@ Vista previa Registro de proceso Procesando + Procesando codigo fuente Proyecto Ubicación del proyecto Acceso a los medios del proyecto Indicación + %1$s: %1$s: %2$s %1$s: %2$d %3$s %1$s: %2$d%3$s + Recortando Salga de + Re-firmando APK + Leyendo recursos de inicio Recomendado Grabación terminada Aviso de grabación @@ -1118,6 +1201,7 @@ Reemplazar Reemplazar todo Sustit + Reemplazando archivo URL del repositorio de la extensión VSCode Enviar con éxito Requiere la versión del sistema operativo Android %s (API %s) pero la actual es %s (API %s) @@ -1126,6 +1210,7 @@ Restablecer con éxito Restablecer inicialmente El restablecimiento es sólo para las muestras + Resolviendo bibliotecas nativas del plugin Reiniciar Estrategia de reinicio Restaurar @@ -1167,6 +1252,7 @@ Guardar configuracion como Guarda Guardar en + Guardando... Motor Retraso de inicio Retraso de solicitud del permiso de captura de pantalla @@ -1187,6 +1273,7 @@ Seleccionar el archivo a cargar Seleccionar un icono Seleccionar una imagen + Plugin seleccionado Enviar Crear acceso directo Modo servidor @@ -1203,6 +1290,9 @@ Vista en los límites del diseño Vista en la jerarquía del diseño Mostrar información del widget + Firmar + Firma completada + Etapa de firma completada Algoritmo de firma Configuración de firma Esquema de firma @@ -1220,6 +1310,7 @@ Hora (mas reciente primero) Origen Ruta del código fuente + Procesamiento del codigo fuente completado Permisos especiales Modo estable Estrella @@ -1258,6 +1349,7 @@ Tarea cronometrada Motor de programación de tareas temporizadas Cronometraje + Titulo Por elegir Alternar todo Herramientas @@ -1282,6 +1374,7 @@ Descripción Desconocida Título Desconocido Versión Desconocida + APK sin firmar creado No verificado Actualizable Actualizar @@ -1289,6 +1382,7 @@ Actualizaciones comprobadas estados borrados Más adelante Ver + Actualizando configuracion del proyecto Acceso a las estadísticas de uso Utiliza el acceso directo de Android 7.0 Usar icono predeterminado @@ -1298,6 +1392,7 @@ El nombre de usuario no puede estar vacío Usar selector de desc Usar el selector id + Usando keystore Usar selector de texto Validez (años) El número de años de validez no puede estar vacío @@ -1329,86 +1424,12 @@ Ruta del directorio de trabajo Escribir la configuración de seguridad Escribir la configuración del sistema + Escribiendo icono de la app + Escribiendo manifest + Escribiendo configuracion del proyecto + Escribiendo resources.arsc + Escribiendo APK firmado Ventanas emergentes en segundo plano La configuracion no se ha guardado. ¿Seguro que quieres continuar? La configuracion no se ha guardado. ¿Seguro que quieres salir? - Error al guardar - Guardando... - ": " - No se pudo activar el plugin - Info de la excepcion - Sugerencia - Prueba a pulsar el boton \"Activar\" para activar el plugin una vez.\nSi la activacion se realiza correctamente, el boton se activara automaticamente en un periodo de tiempo. - Activar - Activado correctamente - Autorizar plugin - Este es un plugin de terceros. Presta atencion al origen del plugin y a la seguridad de uso.\n\nPulsa el boton \"Autorizar\" para habilitar el plugin. - Autorizar - Oficial - Autorizado - Requiere autorizacion - Autorizacion denegada - Activacion recomendada - Activado - Confiable - Mecanismo - El plugin \"%1$s\" no esta habilitado en el Centro de plugins - El plugin \"%1$s\" no esta autorizado en el Centro de plugins - No se encontro el plugin \"%1$s\" en las apps instaladas - Conexion de plugin no compatible - %1$s: - Titulo - Contenido - Compilando APK - Ruta del APK generado - Limpiar - Firmar - Compilar - Preparar - Preparando el espacio de trabajo - Extrayendo APK plantilla - Preparacion completada - Copiando directorio del proyecto - Copiando archivo de script - Procesamiento del codigo fuente completado - Copiando directorio - Copiando archivo - Cifrando script - Reemplazando archivo - Preparando configuracion de compilacion - Leyendo recursos de inicio - Configurando manifest - Configurando nombre de paquete - Copiando assets a - Procesando codigo fuente - Aplicando recursos binarios - Copiando bibliotecas nativas - Actualizando configuracion del proyecto - Etapa de firma completada - Escribiendo configuracion del proyecto - Compilando recursos - Compilacion completada - Escribiendo resources.arsc - Escribiendo manifest - Escribiendo icono de la app - Copiando asset - Preparando dir de assets - Copiando biblioteca - Preparando keystore - APK sin firmar creado - Creando APK sin firmar - Usando keystore - Re-firmando APK - Escribiendo APK firmado - Firma completada - Limpieza completada - Limpiando el espacio de trabajo - Resolviendo bibliotecas nativas del plugin - Copiando bibliotecas para ABI - Plugin seleccionado - Bibliotecas del plugin extraidas - Assets del plugin extraidos - Extrayendo asset del plugin - Extrayendo archivo so del plugin - La grabacion de scripts requiere al menos una de las siguientes condiciones:\n- Acceso root\n- Acceso Shizuku \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 6aec4e23..e531b116 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -117,9 +117,11 @@ Abandonner Interrompre Interrompre la connexion + Activer Ajouter Avancé Corriger l\'adresse + Autoriser @string/text_back Cancel Annulation @@ -229,6 +231,7 @@ Fail to check for updates Les deux points doivent suivre une adresse IP valide Compass ne peut pas être null + L\'enregistrement de scripts necessite au moins l\'une des conditions suivantes:\n- Acces root\n- Acces Shizuku Impossible de se connecter au serveur distant : %s Échec de la connexion à \"%1$s\". Délai de connexion dépassé (%d ms) @@ -252,6 +255,7 @@ Échec de la conversion de la valeur %s en un objet à dessiner Échec de la copie Fail to create + Echec de l\'activation du plugin Échec d\'ouverture de la page des paramètres Échec de l\'octroi de la permission de Shizuku Échec de l\'instanciation de \"%s\" @@ -268,6 +272,7 @@ Impossible de récupérer version.properties pour analyser les informations de version La révocation des droits de Shizuku a échoué Échec de l\'exécution du script + Echec de l\'enregistrement Échec de l\'enregistrement de la configuration du projet Le fichier dans le chemin \"%1$s\" n\'existe pas Le thread d\'interface utilisateur ne peut pas être bloqué. Essayez d\'exécuter %s() dans un sous-fil ou un sous-script. @@ -328,6 +333,9 @@ Syntaxe de motif invalide L\'APK du plugin ne contient pas les ressources requises pour variant=\"%1$s\" : %2$s. L\'APK du plugin ne contient pas les bibliothèques natives requises : %1$s. + Le plugin \"%1$s\" n\'est pas autorise dans le Centre des plugins + Le plugin \"%1$s\" n\'est pas active dans le Centre des plugins + Plugin \"%1$s\" introuvable parmi les applis installees Le plugin %1$s a renvoyé des informations vides. Le plugin %1$s a renvoyé une variante invalide : %2$s. Numéro de port supérieur à 65535 @@ -369,6 +377,7 @@ Type de résultat inconnu {nom : %s, params : %s} Sélecteur inconnu {nom : %s, type : %s} Type inconnu : %s + Connexion de plugin non prise en charge Le format WebP-Lossless ne peut pas être compressé avec un paramètre de qualité ; utilisez plutôt JPEG/PNG/WebP-Lossy Le fichier n\'existe pas ou n\'est pas lisible Le fichier n\'existe pas ou n\'est pas lisible : %s @@ -385,6 +394,7 @@ Délai avant boucle 0 pour une boucle infinie IPv4, IPv6 et les noms de domaine sont pris en charge. + Essayez d\'appuyer sur le bouton \"Activer\" pour activer le plugin une fois.\nSi l\'activation reussit, le bouton s\'activera automatiquement dans un certain delai. Saisissez une URL pointant vers l\'adresse d\'un plugin distant.\nPar exemple \"https://example.com/plugin.apk\". Supprimer definitivement Deplacer vers la corbeille @@ -431,6 +441,7 @@ Dern. inst. Dern. désinst. Dern. maj + Mecanisme Taille du paquet Ver. maj disp. Êtes-vous sûr d\'ignorer la version de mise à jour actuelle?\nVous pouvez gérer toutes les versions ignorées dans les paramètres de l\'application. @@ -461,6 +472,7 @@ Ajouter des raccourcis au lanceur Démarrer ou arrêter l\'enregistrement contrôlé par la touche de réduction du volume lorsque le bouton flottant est affiché. Appuyez sur la touche \"Volume fort\" pour arrêter tous les scripts en cours d\'exécution. + " : " Stockage interne Service d\'accessibilité Requise par le fonctionnement automatique du script (clic, appui long, glissement, etc.). @@ -483,6 +495,7 @@ Scroll forward (scrollForward) Définir le texte (setText) Action + Activation reussie Pas d\'installateur d\'APK L\'outil ADB est nécessaire Ajouter une bibliothèque de couleurs @@ -542,8 +555,11 @@ Code de la version de l\'application Nom de la version de l\'application Appearance + Application des ressources binaires Au moins un champ parmi [Nom complet, Nom de l\'organisation, Unité organisationnelle, Code du pays, État ou province, Ville ou localité, Rue] doit être renseigné Attribut + Autoriser le plugin + Il s\'agit d\'un plugin tiers. Faites attention a la source du plugin et a la securite d\'utilisation.\n\nAppuyez sur le bouton \"Autoriser\" pour activer le plugin. Vérification automatique des mises à jour Vérification automatique des mises à jour et affichage d\'un snackbar sur la page d\'accueil Mode nuit automatique @@ -552,8 +568,27 @@ Retour Action Tâche de diffusion + Compiler Construire un APK + Build termine + Profil de build + Le profil par defaut ne peut pas etre supprime + Le profil project.json ne peut pas etre supprime + Supprimer le profil + Champs du profil + Configurer les champs du profil + Les champs coches sont enregistres comme valeurs fixes dans ce profil. + Plus d\'actions du profil + Impossible d\'utiliser des noms de profil reserves (Default, project.json) + Nom du profil de build + Nouveau profil + La configuration de build actuelle contient des modifications non enregistrees. + La configuration de build actuelle contient des modifications non enregistrees et sera ecrite dans project.json. + Enregistrer les modifications avant de continuer? Construction réussie + Compilation de l\'APK + Compilation des ressources + Chemin de l\'APK genere Annulation Annul Le profil par defaut ne peut pas etre supprime @@ -585,6 +620,9 @@ Choisir le chemin de restauration Ville ou localité Nom de la classe ou du paquet + Nettoyer + Nettoyage termine + Nettoyage de l\'espace de travail Clear Effacer la sélection de fichiers Effacer le script de pré-exécution @@ -613,6 +651,8 @@ Compatibilité Confiance Configuration + Configuration du manifest + Configuration du nom de package Voulez-vous vraiment effacer tous les éléments ? Confirmer l\'effacement de l\'historique? L\'historique ci-dessous sera efface\n\n[ %1$s ]\n\nConfirmer l\'effacement? @@ -628,6 +668,7 @@ La connexion ne peut pas être établie Échec de la connexion Console + Contenu Continue Copie Copier tout @@ -642,8 +683,18 @@ Copie vers le presse-papiers Copie de la valeur Copie... + Copie d\'asset + Copie des assets vers + Copie du repertoire + Copie du fichier + Copie des bibliotheques pour ABI + Copie de bibliotheque + Copie des bibliotheques natives + Copie du repertoire du projet + Copie du fichier de script Code du pays (XX) Le code du pays doit être composé de deux lettres majuscules + Creation de l\'APK non signe Config de la page Version actuelle Tâche quotidienne @@ -726,10 +777,12 @@ Activer le service d\'accessibilité avec des paramètres sécurisés temporairement. Activer le plugin Activé + Chiffrement du script Erreur Failed to copy file : %s Rapport de bug Estimé + Infos de l\'exception Exécuter Exécuter le code [%s] finished in %s seconds.\n @@ -742,6 +795,11 @@ Exporté Extension des objets intégrés de JavaScript Extensibilité + Assets du plugin extraits + Bibliotheques du plugin extraites + Extraction d\'asset du plugin + Extraction du fichier so du plugin + Extraction de l\'APK modele Failed Failed to build Échec de la création de la clé de signature @@ -762,6 +820,7 @@ Failed to register Failed to submit Échec de la récupération + Echec de l\'enregistrement de project.json Échec de l\'enregistrement du projet distant dans le stockage local Échec de l\'envoi des entrées de journal Échec de la mise à jour @@ -812,6 +871,7 @@ Bouton de cacher Masquer ce nœud Masquer le nœud du même cadre + Astuce Historique L\'historique a ete efface Icône @@ -867,6 +927,11 @@ Dernier paquet Launch config Launch debugger + Afficher l\'icone de l\'appli dans le lanceur + Afficher les logs au lancement + Executer le script au demarrage + Texte du slogan de l\'ecran de demarrage + Afficher l\'ecran de demarrage au lancement Icône du lanceur Raccourcis du lanceur Le changement de l\'icône du lanceur sur certains appareils peut entraîner la perte de tous les raccourcis AutoJs6 existants, veuillez procéder avec prudence @@ -982,9 +1047,9 @@ Autoriser l\'application à effectuer des achats intégrés Autoriser l\'application à accéder aux périphériques Bluetooth Autoriser l\'application à configurer les périphériques Bluetooth + Autoriser l\'application à se rendre visible via Bluetooth Autoriser l\'application à accéder aux périphériques et à l\'état de connexion Bluetooth Autoriser l\'application à rechercher des périphériques Bluetooth à proximité - Autoriser l\'application à se rendre visible via Bluetooth Autoriser l\'application à envoyer une intention pour fermer les boîtes de dialogue système Autoriser l\'application à passer des appels téléphoniques Autoriser l\'application à accéder à la caméra @@ -1068,15 +1133,28 @@ Nom de l\'entrée Veuillez patienter... Veuillez réessayer cette opération plus tard... + Active + Activation recommandee + Autorisation refusee + Autorisation requise + Autorise Centre des plugins Détails du plugin + Officiel + De confiance Plugins L\'emplacement du pointeur Toggle \"pointer location\" failed.\nL\'accès à la racine est nécessaire. Notifications postales Afin de garantir que les services au premier plan d\'AutoJs6, etc. fonctionnent correctement et que les scripts puissent publier des notifications, AutoJs6 doit se voir accorder l\'autorisation de \"publier des notifications\". Pré-exécution du script + Preparer + Preparation terminee Préparation... + Preparation du dir des assets + Preparation de la config de build + Preparation du keystore + Preparation de l\'espace de travail Contenu de la boîte de dialogue prédéfinie Titre de la boîte de dialogue prédéfini Appuyez à nouveau sur la touche pour rejeter la boîte de dialogue. @@ -1085,14 +1163,19 @@ Préview Journal de processus Traitement + Traitement du code source Projet Localisation du projet Accès aux médias du projet Prompt + %1$s : %1$s : %2$s %1$s : %2$d %3$s %1$s : %2$d%3$s + Elagage Quit + Re-signature de l\'APK + Lecture des ressources d\'ecran de demarrage Recommandé Enregistrement terminé Demande d\'enregistrement @@ -1118,6 +1201,7 @@ Remplacer Remplacer tout Rempl + Remplacement du fichier URL du dépôt de l\'extension VSCode Submission réussie Requiert Android OS version %s (API %s) mais la version actuelle est %s (API %s) @@ -1126,6 +1210,7 @@ Réinitialisation réussie Réinitialisation initiale Reset n\'est que pour les échantillons + Resolution des bibliotheques natives du plugin Redémarrer Stratégie de redémarrage Restaurer @@ -1167,6 +1252,7 @@ Enregistrer la config sous Enreg Save to + Enregistrement... Moteur Délai de démarrage Délai de demande d\'autorisation de capture d\'écran @@ -1187,6 +1273,7 @@ Sélectionnez le fichier à télécharger Sélectionner l\'icône Sélectionner une image + Plugin selectionne Envoyer Créer un raccourci Mode serveur @@ -1203,6 +1290,9 @@ Afficher les bords de la disposition Afficher la hiérarchie de la disposition Afficher les informations du widget + Signer + Signature terminee + Etape de signature terminee Algorithme de signature Configuration de la signature Schéma de signature @@ -1220,6 +1310,7 @@ Heure (plus recent d\'abord) Source Chemin du code source + Traitement du code source termine Autorisations spéciales Mode stable Star @@ -1258,6 +1349,7 @@ Tâche chronométrée Moteur d\'ordonnancement des tâches planifiées Timing + Titre A choisir Basculer tout Outils @@ -1282,6 +1374,7 @@ Description Inconnue Titre Inconnu Version Inconnue + APK non signe cree Non vérifié Mise a jour dispo Mettre a jour @@ -1289,6 +1382,7 @@ Mise à jour des états vérifiés et effacés Plus tard Voir + Mise a jour de la config du projet Utilisation de l\'accès aux statistiques Utiliser le raccourci Android 7.0 Utiliser l\'icône par défaut @@ -1298,6 +1392,7 @@ Le nom d\'utilisateur ne peut pas être vide. Utiliser le sélecteur desc Utiliser le sélecteur d\'id + Utilisation du keystore Utiliser le sélecteur de texte Validité (années) Les années de validité ne peuvent pas être vides @@ -1329,86 +1424,12 @@ Chemin du répertoire de travail. Écrire les paramètres de sécurité. Écrire les paramètres système + Ecriture de l\'icone de l\'appli + Ecriture du manifest + Ecriture de la config du projet + Ecriture de resources.arsc + Ecriture de l\'APK signe Fenêtres contextuelles en arrière-plan Les parametres ne sont pas enregistres. Continuer? Les parametres ne sont pas enregistres. Quitter? - Echec de l\'enregistrement - Enregistrement... - " : " - Echec de l\'activation du plugin - Infos de l\'exception - Astuce - Essayez d\'appuyer sur le bouton \"Activer\" pour activer le plugin une fois.\nSi l\'activation reussit, le bouton s\'activera automatiquement dans un certain delai. - Activer - Activation reussie - Autoriser le plugin - Il s\'agit d\'un plugin tiers. Faites attention a la source du plugin et a la securite d\'utilisation.\n\nAppuyez sur le bouton \"Autoriser\" pour activer le plugin. - Autoriser - Officiel - Autorise - Autorisation requise - Autorisation refusee - Activation recommandee - Active - De confiance - Mecanisme - Le plugin \"%1$s\" n\'est pas active dans le Centre des plugins - Le plugin \"%1$s\" n\'est pas autorise dans le Centre des plugins - Plugin \"%1$s\" introuvable parmi les applis installees - Connexion de plugin non prise en charge - %1$s : - Titre - Contenu - Compilation de l\'APK - Chemin de l\'APK genere - Nettoyer - Signer - Compiler - Preparer - Preparation de l\'espace de travail - Extraction de l\'APK modele - Preparation terminee - Copie du repertoire du projet - Copie du fichier de script - Traitement du code source termine - Copie du repertoire - Copie du fichier - Chiffrement du script - Remplacement du fichier - Preparation de la config de build - Lecture des ressources d\'ecran de demarrage - Configuration du manifest - Configuration du nom de package - Copie des assets vers - Traitement du code source - Application des ressources binaires - Copie des bibliotheques natives - Mise a jour de la config du projet - Etape de signature terminee - Ecriture de la config du projet - Compilation des ressources - Build termine - Ecriture de resources.arsc - Ecriture du manifest - Ecriture de l\'icone de l\'appli - Copie d\'asset - Preparation du dir des assets - Copie de bibliotheque - Preparation du keystore - APK non signe cree - Creation de l\'APK non signe - Utilisation du keystore - Re-signature de l\'APK - Ecriture de l\'APK signe - Signature terminee - Nettoyage termine - Nettoyage de l\'espace de travail - Resolution des bibliotheques natives du plugin - Copie des bibliotheques pour ABI - Plugin selectionne - Bibliotheques du plugin extraites - Assets du plugin extraits - Extraction d\'asset du plugin - Extraction du fichier so du plugin - L\'enregistrement de scripts necessite au moins l\'une des conditions suivantes:\n- Acces root\n- Acces Shizuku \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index eaeaf387..42565d6d 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -118,9 +118,11 @@ 放棄 中止 接続を中止 + 有効化 追加 詳細 アドレスを修正 + 許可 @string/text_back 取消 取消 @@ -230,6 +232,7 @@ 更新のチェックに失敗しました 有効な IP アドレスの後にコロンが続くこと コンパスは null にできません + スクリプト録画には次の条件のうち少なくとも1つが必要です:\n- Root 権限\n- Shizuku 権限 リモートサーバーに接続できません. %s \"%1$s\" への接続に失敗しました. 接続がタイムアウトしました (%d ミリ秒) @@ -253,6 +256,7 @@ 値 %s を Drawable に変換するのに失敗しました コピーに失敗しました 作成に失敗しました + プラグインの有効化に失敗しました 設定画面を開けませんでした Shizuku の権限付与に失敗しました \"%s\" のインスタンス化に失敗しました @@ -269,6 +273,7 @@ version.properties を取得できず, バージョン情報を解析できません Shizuku 権限の取り消しに失敗しました スクリプトの実行に失敗しました + 保存に失敗しました プロジェクト設定の保存に失敗しました パス \"%1$s\" にファイルが存在しません \"UI スレッドをブロックできません. サブスレッドまたはサブスクリプトで %s() を実行してみてください @@ -329,6 +334,9 @@ 無効なパターン構文 プラグイン APK に variant=\"%1$s\" に必要な assets が含まれていません: %2$s. プラグイン APK に必要な native ライブラリが含まれていません: %1$s. + プラグイン \"%1$s\" はプラグインセンターで許可されていません + プラグイン \"%1$s\" はプラグインセンターで有効になっていません + インストール済みアプリにプラグイン \"%1$s\" が見つかりません %1$s プラグインが空の info を返しました. %1$s プラグインが無効な variant を返しました: %2$s. 65535 を超えるポート番号 @@ -370,6 +378,7 @@ 不明な結果タイプ {name: %s, params: %s} 不明なセレクタ {name: %s, type: %s} です 不明なタイプ: %s + サポートされていないプラグイン接続方式です WebP-Lossless 形式は品質パラメータで圧縮できません, 代わりに JPEG/PNG/WebP-Lossy を使用してください ファイルが存在しないか, 読み取れません ファイルが存在しないか, 読み取り可能でない: %s @@ -386,6 +395,7 @@ ループ前の遅延時間 無限ループの場合は 0 IPv4/IPv6/およびドメイン名に対応しています. + \"有効化\" ボタンをタップして, プラグインを一度有効化してみてください.\n有効化に成功すると, 一定時間内にボタンが自動的にオンになります. リモートプラグインの URL を入力してください. \n例: \"https://example.com/plugin.apk\" 完全に削除 ゴミ箱に移動 @@ -432,6 +442,7 @@ 最終インストール 最終アンインストール 最終更新 + 方式 パッケージサイズ 更新可 Ver. 現在のアップデートバージョンを無視して大丈夫ですか?\n無視したバージョンは, アプリの設定で管理することができます @@ -462,6 +473,7 @@ ランチャーへのショートカットの追加 フローティングボタンが表示されているときに, \"Volume Down\" キーで録画の開始/停止を制御できるようになりました \"Volume Up\" キーを押すと, 実行中のスクリプトをすべて停止します + ": " 内部ストレージ アクセシビリティサービス スクリプトの自動操作 (クリック, 長押し, スライドなど) で必要です @@ -484,6 +496,7 @@ 前方にスクロールする (scrollForward) テキストを設定する (setText) 動作 + 有効化しました APK インストーラーなし ADB ツールが必要 カラーライブラリを追加 @@ -543,8 +556,11 @@ アプリバージョンコード アプリのバージョン名 外観 + バイナリ資源を適用中 [氏名, 組織名, 組織単位, 国コード, 州または省, 市区町村, 街] のいずれかの項目を入力する必要があります 属性 + プラグインを許可 + これはサードパーティ製プラグインです. 提供元と利用上の安全性に注意してください.\n\n\"許可\" ボタンをタップしてプラグインを有効にします. 更新の自動チェック 自動的に更新をチェックし, ホームページにスナックバーを表示します オートナイトモード @@ -553,8 +569,27 @@ 戻る 動作 タスクの実行 + ビルド APK のビルド + ビルド完了 + ビルド設定 + デフォルト設定は削除できません + project.json 設定は削除できません + 設定を削除 + 設定フィールド + 設定フィールドを構成 + チェックしたフィールドは, この設定に固定値として保存されます. + その他の設定操作 + 予約済みの設定名は使用できません (Default, project.json) + ビルド設定名 + 新規設定 + 現在のビルド設定に未保存の変更があります. + 現在のビルド設定に未保存の変更があり, project.json に書き込まれます. + 続行する前に変更を保存しますか? ビルドに成功しました + APK をビルド中 + 資源をビルド中 + 生成された APK のパス 取消 取消 デフォルトは削除できません @@ -586,6 +621,9 @@ 復元先を選択 市区町村 クラス名/パッケージ名 + クリーン + クリーン完了 + ワークスペースをクリーン中 クリア ファイル選択の解除 実行前スクリプトのクリア @@ -614,6 +652,8 @@ 互換性 信頼度 設定 + manifest を設定中 + パッケージ名を設定中 すべての項目を削除しますか? 履歴を消去しますか? 以下の履歴を消去します\n\n[ %1$s ]\n\n消去しますか? @@ -629,6 +669,7 @@ 接続が確立できない 接続に失敗しました コンソール + 内容 続行 コピー すべてコピー @@ -643,8 +684,18 @@ クリップボードにコピーする 値をコピーする コピー中... + asset をコピー中 + assets をコピー中: + ディレクトリをコピー中 + ファイルをコピー中 + ABI 用ライブラリをコピー中 + ライブラリをコピー中 + ネイティブライブラリをコピー中 + プロジェクトディレクトリをコピー中 + スクリプトファイルをコピー中 国コード (XX) 国コードは 2 文字の大文字でなければなりません + 未署名 APK を作成中 現在のページ設定 現在のバージョン デイリータスク @@ -727,10 +778,12 @@ セキュアな設定でアクセシビリティサービスを有効化するとタイムアウトする プラグインを有効化 有効 + スクリプトを暗号化中 エラー ファイルのコピーに失敗しました. %s バグレポート 推定 + 例外情報 実行 実行コード [%s] は %s 秒で終了しました @@ -743,6 +796,11 @@ エクスポートされました JavaScript 組み込みオブジェクトの拡張 拡張性 + プラグインの資源を抽出しました + プラグインのライブラリを抽出しました + プラグイン資源を抽出中 + プラグインの so を抽出中 + テンプレート APK を展開中 失敗 ビルドに失敗しました 署名キーの作成に失敗しました @@ -763,6 +821,7 @@ 登録の失敗 投稿の失敗 取得に失敗 + project.json の保存に失敗しました リモートプロジェクトをローカルストレージに保存できませんでした ログ・エントリの送信に失敗しました 更新に失敗しました @@ -813,6 +872,7 @@ 隠しボタン このノードを隠す 同じフレームのノードを隠す + ヒント 履歴 履歴を消去しました アイコン @@ -868,6 +928,11 @@ 最新のパッケージ コンフィグを起動する デバッガを起動する + ランチャーにアプリアイコンを表示 + 起動時にログを表示 + 起動時にスクリプトを実行 + スプラッシュ標語テキスト + 起動時にスプラッシュ画面を表示 ランチャーアイコン ランチャーショートカット 一部のデバイスでランチャーアイコンを切り替えると既存の AutoJs6 ショートカットがすべて失われる可能性があります, 注意して操作してください @@ -983,9 +1048,9 @@ アプリがアプリ内購入を実行することを許可します アプリが Bluetooth デバイスにアクセスすることを許可します アプリが Bluetooth デバイスを設定することを許可します + アプリが Bluetooth でアドバタイズすることを許可します アプリが Bluetooth デバイスと接続状態にアクセスすることを許可します アプリが近くの Bluetooth デバイスをスキャンすることを許可します - アプリが Bluetooth でアドバタイズすることを許可します アプリがシステムダイアログを閉じるためのインテントを送信することを許可します アプリが電話をかけることを許可します アプリがカメラにアクセスすることを許可します @@ -1069,15 +1134,28 @@ 入力名 しばらくお待ちください... しばらくしてからもう一度お試しください... + 有効 + 有効化を推奨 + 許可が拒否されました + 許可が必要 + 許可済み プラグインセンター プラグイン詳細 + 公式 + 信頼済み プラグイン ポインターの位置 トグル [ポインターの位置] に失敗しました.\nroot 権限が必要です ゆうびんけいほう AutoJs6 のフォアグラウンドサービス等が正常に動作し, スクリプトが通知を投稿できるようにするため, AutoJs6 には \"通知の送信\" 権限を付与する必要があります. スクリプトの事前実行 + 準備 + 準備完了 準備中... + assets ディレクトリを準備中 + ビルド設定を準備中 + keystore を準備中 + ワークスペースを準備中 プリセット・ダイアログ・内容 プリセット・ダイアログ・タイトル ダイアログを閉じるにはもう一度押してください @@ -1086,14 +1164,19 @@ プレビュー プロセスログ 処理中 + ソースを処理中 プロジェクト プロジェクトの場所 プロジェクト・メディア・アクセス プロンプト + %1$s: %1$s: %2$s %1$s: %2$d %3$s %1$s: %2$d%3$s + 剪定中 終了 + APK を再署名中 + スプラッシュ資源を読み込み中 推奨 記録終了 録画のプロンプト @@ -1119,6 +1202,7 @@ 置換 すべてを置き換える 置換 + ファイルを置換中 VSCode 拡張機能のリポジトリ URL 送信に成功しました Android OS バージョン %s (API %s) が必要ですが, 現在のバージョンは %s (API %s)です @@ -1127,6 +1211,7 @@ リセット成功 初期リセット リセットはサンプルのみ + プラグインのネイティブライブラリを解決中 再起動 再起動戦略 復元 @@ -1168,6 +1253,7 @@ 設定を別名で保存 保存 保存先 + 保存中... エンジン 開始遅延 画面キャプチャ権限リクエスト遅延 @@ -1188,6 +1274,7 @@ アップロードするファイルを選択します アイコンを選択する 画像を選択する + 選択したプラグイン 送信する ショートカットの作成 サーバーモード @@ -1204,6 +1291,9 @@ レイアウト境界内のビュー レイアウト階層内の表示 ウィジェット情報を表示する + 署名 + 署名完了 + 署名ステージ完了 署名アルゴリズム 署名設定 署名スキーム @@ -1221,6 +1311,7 @@ 時間 (新しい順) ソース ソースコードのパス + ソース処理完了 特殊な権限 安定モード スター @@ -1259,6 +1350,7 @@ 時間指定タスク 定時タスクのスケジューリングエンジン タイミング + タイトル 未選択 全て切替 ツール @@ -1283,6 +1375,7 @@ 不明な説明 不明なタイトル 不明なバージョン + 未署名 APK を作成しました 未確認 更新あり 更新 @@ -1290,6 +1383,7 @@ 更新のチェック状態を解除 後日 表示 + プロジェクト設定を更新中 使用統計へのアクセス Android 7.0 のショートカットを使用 デフォルトのアイコンを使用する @@ -1299,6 +1393,7 @@ ユーザー名を空にすることはできません 降順セレクタを使用する ID セレクタを使用する + keystore を使用中 テキストセレクタを使用する 有効期限(年) 有効期限の年数は空にできません @@ -1330,86 +1425,12 @@ 作業ディレクトリのパス セキュリティ設定の書き込み システム設定の書き込み + アプリアイコンを書き込み中 + manifest を書き込み中 + プロジェクト設定を書き込み中 + resources.arsc を書き込み中 + 署名済み APK を書き込み中 バックグラウンドでのポップアップ表示 設定が保存されていません. 続行しますか? 設定が保存されていません. 終了しますか? - 保存に失敗しました - 保存中... - ": " - プラグインの有効化に失敗しました - 例外情報 - ヒント - \"有効化\" ボタンをタップして, プラグインを一度有効化してみてください.\n有効化に成功すると, 一定時間内にボタンが自動的にオンになります. - 有効化 - 有効化しました - プラグインを許可 - これはサードパーティ製プラグインです. 提供元と利用上の安全性に注意してください.\n\n\"許可\" ボタンをタップしてプラグインを有効にします. - 許可 - 公式 - 許可済み - 許可が必要 - 許可が拒否されました - 有効化を推奨 - 有効 - 信頼済み - 方式 - プラグイン \"%1$s\" はプラグインセンターで有効になっていません - プラグイン \"%1$s\" はプラグインセンターで許可されていません - インストール済みアプリにプラグイン \"%1$s\" が見つかりません - サポートされていないプラグイン接続方式です - %1$s: - タイトル - 内容 - APK をビルド中 - 生成された APK のパス - クリーン - 署名 - ビルド - 準備 - ワークスペースを準備中 - テンプレート APK を展開中 - 準備完了 - プロジェクトディレクトリをコピー中 - スクリプトファイルをコピー中 - ソース処理完了 - ディレクトリをコピー中 - ファイルをコピー中 - スクリプトを暗号化中 - ファイルを置換中 - ビルド設定を準備中 - スプラッシュ資源を読み込み中 - manifest を設定中 - パッケージ名を設定中 - assets をコピー中: - ソースを処理中 - バイナリ資源を適用中 - ネイティブライブラリをコピー中 - プロジェクト設定を更新中 - 署名ステージ完了 - プロジェクト設定を書き込み中 - 資源をビルド中 - ビルド完了 - resources.arsc を書き込み中 - manifest を書き込み中 - アプリアイコンを書き込み中 - asset をコピー中 - assets ディレクトリを準備中 - ライブラリをコピー中 - keystore を準備中 - 未署名 APK を作成しました - 未署名 APK を作成中 - keystore を使用中 - APK を再署名中 - 署名済み APK を書き込み中 - 署名完了 - クリーン完了 - ワークスペースをクリーン中 - プラグインのネイティブライブラリを解決中 - ABI 用ライブラリをコピー中 - 選択したプラグイン - プラグインのライブラリを抽出しました - プラグインの資源を抽出しました - プラグイン資源を抽出中 - プラグインの so を抽出中 - スクリプト録画には次の条件のうち少なくとも1つが必要です:\n- Root 権限\n- Shizuku 権限 \ No newline at end of file diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index a065c57f..4f829a3a 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -119,9 +119,11 @@ 포기 중지 연결 중지 + 활성화 추가 고급 주소 수정 + 권한 부여 @string/text_back 취소 취소 @@ -231,6 +233,7 @@ 업데이트를 확인하지 못했습니다 콜론은 유효한 IP 주소를 따라야 합니다 나침반은 무효가 될 수 없다 + 스크립트 녹화에는 다음 조건 중 하나 이상이 필요합니다:\n- Root 권한\n- Shizuku 권한 원격 서버에 연결할 수 없습니다: %s \"%1$s\"에 연결하지 못했습니다. 연결 시간 초과 (%d 밀리초) @@ -254,6 +257,7 @@ %s 값을 Drawable 로 변환하지 못했습니다 복사하지 못했습니다 만들지 못했습니다 + 플러그인을 활성화하지 못했습니다 설정 페이지를 열지 못했습니다 Shizuku 권한을 부여하지 못했습니다 \"%s\" 인스턴스 생성에 실패했습니다 @@ -270,6 +274,7 @@ version.properties 를 가져올 수 없어 버전 정보를 분석할 수 없습니다 Shizuku 권한 해지에 실패했습니다 스크립트 실행 실패 + 저장에 실패했습니다 프로젝트 설정을 저장하지 못했습니다 경로 \"%1$s\" 에 파일이 존재하지 않습니다 UI 스레드는 차단할 수 없습니다. 하위 스레드 또는 하위 스크립트에서 %s() 를 실행하십시오 @@ -330,6 +335,9 @@ 잘못된 패턴 구문 플러그인 APK에 variant=\"%1$s\"에 필요한 assets가 포함되어 있지 않습니다: %2$s. 플러그인 APK에 필요한 native 라이브러리가 포함되어 있지 않습니다: %1$s. + 플러그인 \"%1$s\" 이 (가) 플러그인 센터에서 권한이 부여되지 않았습니다 + 플러그인 \"%1$s\" 이(가) 플러그인 센터에서 활성화되어 있지 않습니다 + 설치된 앱에서 플러그인 \"%1$s\" 을 (를) 찾을 수 없습니다 %1$s 플러그인이 빈 info를 반환했습니다. %1$s 플러그인이 잘못된 variant를 반환했습니다: %2$s. 65535 이상의 포트 번호 @@ -371,6 +379,7 @@ 알 수없는 결과 유형 {이름: %s, 매개 변수: %s} 알 수없는 선택기 {이름: %s, 유형: %s} 알 수없는 유형: %s + 지원되지 않는 플러그인 연결 방식입니다 WebP-Lossless 형식은 품질 파라미터로 압축할 수 없습니다, 대신 JPEG/PNG/WebP-Lossy를 사용하세요 파일이 없거나 읽을 수 없습니다 파일이 존재하지 않거나 읽을 수 없습니다: %s @@ -387,6 +396,7 @@ 루프 전 지연 무한 루프의 경우 0 IPv4, IPv6 및 도메인을 지원합니다. + \"활성화\" 버튼을 눌러 플러그인을 한 번 활성화해 보세요.\n활성화에 성공하면 일정 시간 내에 버튼이 자동으로 켜집니다. 원격 플러그인 주소를 가리키는 URL을 입력하세요.\n예: \"https://example.com/plugin.apk\" 영구 삭제 휴지통으로 이동 @@ -433,6 +443,7 @@ 마지막 설치 마지막 제거 마지막 업데이트 + 방식 패키지 크기 업데이트 가능 현재 업데이트 버전을 무시해야합니까?\n앱 설정으로 무시 된 버전을 모두 관리 할 수 있습니다. @@ -463,6 +474,7 @@ 런처에 바로 가기 추가 부동 버튼이 표시 될 때 볼륨 다운 키로 제어 된 녹음 시작 또는 중지 실행 중인 모든 스크립트를 중지하려면 \"볼륨 크게\" 키를 누르십시오. + ": " 내부 저장소 접근성 서비스 스크립트 자동 작동에 필요합니다 (클릭, 긴 프레스, 슬라이드 등). @@ -485,6 +497,7 @@ 앞으로 스크롤 (scrollForward) 텍스트 설정 (setText) 동작 + 활성화되었습니다 APK 설치 프로그램이 없습니다 ADB 도구가 필요합니다 색상 라이브러리 추가 @@ -544,8 +557,11 @@ 앱 버전 코드 앱 버전 이름 모습 + 바이너리 리소스 적용 중 [성명, 조직명, 조직 단위, 국가 코드, 주 또는 도, 시 또는 지역, 거리] 중 하나 이상을 입력해야 합니다 기인하다 + 플러그인 권한 부여 + 이 플러그인은 타사 플러그인입니다. 플러그인 출처와 사용 안전에 유의하세요.\n\n\"권한 부여\" 버튼을 눌러 플러그인을 활성화하세요. 자동 확인 업데이트 자동으로 업데이트를 확인하고 홈페이지에 스낵바를 표시합니다. 자동 밤 모드 @@ -554,8 +570,27 @@ 동작 방송 작업 + 빌드 APK 빌드 + 빌드 완료 + 빌드 프로필 + 기본 프로필은 삭제할 수 없습니다 + project.json 프로필은 삭제할 수 없습니다 + 프로필 삭제 + 프로필 필드 + 프로필 필드 설정 + 체크된 필드는 이 프로필에 고정 값으로 저장됩니다. + 더 많은 프로필 작업 + 예약된 프로필 이름은 사용할 수 없습니다 (Default, project.json) + 빌드 프로필 이름 + 새 프로필 + 현재 빌드 설정에 저장되지 않은 변경 사항이 있습니다. + 현재 빌드 설정에 저장되지 않은 변경 사항이 있으며, project.json에 기록됩니다. + 계속하기 전에 변경 사항을 저장할까요? 빌드가 성공했습니다 + APK 빌드 중 + 리소스 빌드 중 + 생성된 APK 경로 취소 취소 기본 프로필은 삭제할 수 없습니다 @@ -587,6 +622,9 @@ 복원 경로 선택 시 또는 지역 클래스 / 패키지 이름 + 정리 + 정리 완료 + 작업 공간 정리 중 분명한 파일 선택을 지우십시오 사전 에코 슈트 스크립트를 지우십시오 @@ -615,6 +653,8 @@ 호환성 신뢰도 구성 + manifest 설정 중 + 패키지 이름 설정 중 모든 항목을 삭제하시겠습니까? 기록을 삭제하시겠습니까? 아래 기록이 삭제됩니다\n\n[ %1$s ]\n\n삭제하시겠습니까? @@ -630,6 +670,7 @@ 연결을 설정할 수 없습니다 연결 실패 콘솔 + 내용 계속하다 복사 모두 복사하십시오 @@ -644,8 +685,18 @@ 클립 보드에 복사 값을 복사하십시오 복사 중... + asset 복사 중 + assets 복사 중: + 디렉터리 복사 중 + 파일 복사 중 + ABI용 라이브러리 복사 중 + 라이브러리 복사 중 + 네이티브 라이브러리 복사 중 + 프로젝트 디렉터리 복사 중 + 스크립트 파일 복사 중 국가 코드 (XX) 국가 코드는 두 개의 대문자로 입력해야 합니다 + 서명되지 않은 APK 생성 중 현재 페이지 설정 현재 버전 일상적인 작업 @@ -728,10 +779,12 @@ 안전한 설정 시간이 초과되는 접근성 서비스를 활성화하십시오 플러그인 활성화 활성화됨 + 스크립트 암호화 중 오류 파일을 복사하지 못했습니다: %s 버그 보고서 추정 + 예외 정보 실행하다 코드를 실행하십시오 [%s] 는 %s 초 만에 완료되었습니다.\n @@ -744,6 +797,11 @@ 내보낸 JavaScript 내장 개체 확장 확장성 + 플러그인 assets를 추출함 + 플러그인 라이브러리를 추출함 + 플러그인 asset 추출 중 + 플러그인 so 파일 추출 중 + 템플릿 APK 추출 중 실패한 건축에 실패했습니다 서명 키 생성에 실패했습니다 @@ -764,6 +822,7 @@ 등록하지 못했습니다 제출하지 못했습니다 가져오기 실패 + project.json 저장에 실패했습니다 원격 프로젝트를 로컬 저장소에 저장하지 못했습니다 로그 항목을 보내지 못했습니다 업데이트 실패 @@ -814,6 +873,7 @@ 버튼 숨기기 이 노드를 숨기기 동일 프레임의 노드를 숨기기 + 힌트 기록 기록이 삭제되었습니다 @@ -869,6 +929,11 @@ 최신 패키지 구성을 시작하십시오 디버거를 시작하십시오 + 런처에 앱 아이콘 표시 + 실행 시 로그 표시 + 부팅 시 스크립트 실행 + 시작 화면 슬로건 텍스트 + 실행 시 시작 화면 표시 런처 아이콘 런처 바로 가기 일부 기기에서 런처 아이콘을 변경하면 기존 AutoJs6 바로가기가 모두 삭제될 수 있으니 주의하십시오 @@ -984,9 +1049,9 @@ 앱이 인앱 구매를 수행하도록 허용합니다 앱이 블루투스 기기에 접근하도록 허용합니다 앱이 블루투스 기기를 구성하도록 허용합니다 + 앱이 블루투스로 광고하도록 허용합니다 앱이 블루투스 장치 및 연결 상태에 접근하도록 허용합니다 앱이 근처 블루투스 장치를 검색하도록 허용합니다 - 앱이 블루투스로 광고하도록 허용합니다 앱이 시스템 대화 상자를 닫기 위한 인텐트를 보내도록 허용합니다 앱이 전화를 걸도록 허용합니다 앱이 카메라에 접근하도록 허용합니다 @@ -1070,15 +1135,28 @@ 입력 이름 잠시만 기다려주세요... 잠시 후 다시 시도해 주세요... + 활성화됨 + 활성화 권장 + 권한 거부됨 + 권한 필요 + 권한 부여됨 플러그인 센터 플러그인 상세 + 공식 + 신뢰됨 플러그인 포인터 위치 \"포인터 위치\"토글이 실패했습니다.\n루트 액세스가 필요합니다. 게시물 알림 AutoJs6 포그라운드 서비스 등이 정상적으로 동작하고 스크립트가 알림을 게시할 수 있도록 하려면, AutoJs6 에 \"알림 게시\" 권한을 부여해야 합니다. 사전 배제 스크립트 + 준비 + 준비 완료 준비 ... + assets 디렉터리 준비 중 + 빌드 설정 준비 중 + keystore 준비 중 + 작업 공간 준비 중 사전 설정 대화 상자 내용 사전 설정 대화 상자 제목 다시 눌러 대화 상자를 무시하십시오 @@ -1087,14 +1165,19 @@ 시사 프로세스 로그 처리 중 + 소스 처리 중 프로젝트 프로젝트 위치 프로젝트 미디어 액세스 즉각적인 + %1$s: %1$s: %2$s %1$s: %2$d %3$s %1$s: %2$d%3$s + 가지치기 중 그만두다 + APK 재서명 중 + 스플래시 리소스 읽는 중 권장 녹음 완료 녹음 프롬프트 @@ -1120,6 +1203,7 @@ 바꾸다 모두 다 바꿔 교체 + 파일 교체 중 VSCode 확장의 리포지토리 URL 제출 성공 Android OS 버전 %s (API %s) 가 필요하지만 현재는 %s (API %s) 입니다. @@ -1128,6 +1212,7 @@ 재설정이 성공했습니다 처음에 재설정하십시오 재설정은 샘플에만 해당됩니다 + 플러그인 네이티브 라이브러리 확인 중 재시작 재시작 전략 복원 @@ -1169,6 +1254,7 @@ 다른 이름으로 저장 구하다 저장 + 저장 중... 엔진 시작 지연 화면 캡처 권한 요청 지연 @@ -1189,6 +1275,7 @@ 업로드 할 파일을 선택하십시오 아이콘을 선택하십시오 이미지를 선택하십시오 + 선택된 플러그인 보내다 바로 가기를 만듭니다 서버 모드 @@ -1205,6 +1292,9 @@ 레이아웃 경계보기 레이아웃 계층 구조보기 위젯 정보를 보여줍니다 + 서명 + 서명 완료 + 서명 단계 완료 서명 알고리즘 서명 설정 서명 스킴 @@ -1222,6 +1312,7 @@ 시간 (최신순) 원본 소스 코드 경로 + 소스 처리 완료 특수 권한 안정적인 모드 @@ -1260,6 +1351,7 @@ 시간이 정한 작업 정시 작업 스케줄링 엔진 타이밍 + 제목 선택 대기 전체 전환 도구 @@ -1284,6 +1376,7 @@ 알 수 없는 설명 알 수 없는 제목 알 수 없는 버전 + 서명되지 않은 APK가 생성됨 미확인 업데이트 가능 업데이트 @@ -1291,6 +1384,7 @@ 확인 된 상태가 지워졌습니다 나중 보다 + 프로젝트 설정 업데이트 중 사용 통계 액세스 Android 7.0 바로 가기를 사용하십시오 기본 아이콘 사용 @@ -1300,6 +1394,7 @@ 사용자 이름은 비어있을 수 없습니다 desc 선택기를 사용하십시오 id 선택기를 사용하십시오 + keystore 사용 중 text 선택기를 사용하십시오 유효 기간 (년) 유효 기간을 입력해야 합니다 @@ -1331,86 +1426,12 @@ 작업 디렉토리 경로 보안 설정을 작성하십시오 시스템 설정을 작성하십시오 + 앱 아이콘 기록 중 + manifest 기록 중 + 프로젝트 설정 기록 중 + resources.arsc 기록 중 + 서명된 APK 기록 중 백그라운드 팝업 설정이 저장되지 않았습니다. 계속할까요? 설정이 저장되지 않았습니다. 종료할까요? - 저장에 실패했습니다 - 저장 중... - ": " - 플러그인을 활성화하지 못했습니다 - 예외 정보 - 힌트 - \"활성화\" 버튼을 눌러 플러그인을 한 번 활성화해 보세요.\n활성화에 성공하면 일정 시간 내에 버튼이 자동으로 켜집니다. - 활성화 - 활성화되었습니다 - 플러그인 권한 부여 - 이 플러그인은 타사 플러그인입니다. 플러그인 출처와 사용 안전에 유의하세요.\n\n\"권한 부여\" 버튼을 눌러 플러그인을 활성화하세요. - 권한 부여 - 공식 - 권한 부여됨 - 권한 필요 - 권한 거부됨 - 활성화 권장 - 활성화됨 - 신뢰됨 - 방식 - 플러그인 \"%1$s\" 이(가) 플러그인 센터에서 활성화되어 있지 않습니다 - 플러그인 \"%1$s\" 이 (가) 플러그인 센터에서 권한이 부여되지 않았습니다 - 설치된 앱에서 플러그인 \"%1$s\" 을 (를) 찾을 수 없습니다 - 지원되지 않는 플러그인 연결 방식입니다 - %1$s: - 제목 - 내용 - APK 빌드 중 - 생성된 APK 경로 - 정리 - 서명 - 빌드 - 준비 - 작업 공간 준비 중 - 템플릿 APK 추출 중 - 준비 완료 - 프로젝트 디렉터리 복사 중 - 스크립트 파일 복사 중 - 소스 처리 완료 - 디렉터리 복사 중 - 파일 복사 중 - 스크립트 암호화 중 - 파일 교체 중 - 빌드 설정 준비 중 - 스플래시 리소스 읽는 중 - manifest 설정 중 - 패키지 이름 설정 중 - assets 복사 중: - 소스 처리 중 - 바이너리 리소스 적용 중 - 네이티브 라이브러리 복사 중 - 프로젝트 설정 업데이트 중 - 서명 단계 완료 - 프로젝트 설정 기록 중 - 리소스 빌드 중 - 빌드 완료 - resources.arsc 기록 중 - manifest 기록 중 - 앱 아이콘 기록 중 - asset 복사 중 - assets 디렉터리 준비 중 - 라이브러리 복사 중 - keystore 준비 중 - 서명되지 않은 APK가 생성됨 - 서명되지 않은 APK 생성 중 - keystore 사용 중 - APK 재서명 중 - 서명된 APK 기록 중 - 서명 완료 - 정리 완료 - 작업 공간 정리 중 - 플러그인 네이티브 라이브러리 확인 중 - ABI용 라이브러리 복사 중 - 선택된 플러그인 - 플러그인 라이브러리를 추출함 - 플러그인 assets를 추출함 - 플러그인 asset 추출 중 - 플러그인 so 파일 추출 중 - 스크립트 녹화에는 다음 조건 중 하나 이상이 필요합니다:\n- Root 권한\n- Shizuku 권한 \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 9f0d8c33..57b60eec 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -117,9 +117,11 @@ Отказаться Прервать Прервать соединение + Активировать Добавить Доп. Исправить адрес + Авторизовать @string/text_back Отменить Отменить @@ -229,6 +231,7 @@ Не удалось проверить наличие обновлений Двоеточие должно следовать за действительным IP-адресом Компас не может быть нулевым + Запись скриптов требует выполнения хотя бы одного из следующих условий:\n- Доступ root\n- Доступ Shizuku Не удается подключиться к удаленному серверу: %s Не удалось подключиться к \"%1$s\". Тайм-аут подключения (%d мс) @@ -252,6 +255,7 @@ Не удалось преобразовать значение %s в Drawable Не удалось скопировать Не удалось создать + Не удалось включить плагин Не удалось открыть страницу настроек Не удалось предоставить права на использование Shizuku Ошибка создания экземпляра \"%s\" @@ -268,6 +272,7 @@ Не удалось получить файл version.properties для анализа информации о версии Не удалось отозвать права на Shizuku Ошибка выполнения скрипта + Не удалось сохранить Не удалось сохранить конфигурацию проекта Файл в пути \"%1$s\" не существует Поток пользовательского интерфейса не может быть заблокирован. Попробуйте запустить %s() в подпотоке или подскрипте @@ -328,6 +333,9 @@ Неверный синтаксис шаблона APK плагина не содержит требуемые ресурсы для variant=\"%1$s\": %2$s. APK плагина не содержит требуемые native-библиотеки: %1$s. + Плагин \"%1$s\" не авторизован в Центре плагинов + Плагин \"%1$s\" не включен в Центре плагинов + Плагин \"%1$s\" не найден среди установленных приложений Плагин %1$s вернул пустую информацию. Плагин %1$s вернул недопустимый variant: %2$s. Номер порта более 65535 @@ -369,6 +377,7 @@ Неизвестный тип результата {имя: %s, params: %s} Неизвестный селектор {имя: %s, тип: %s} Неизвестный тип: %s + Неподдерживаемое подключение плагина Формат WebP-Lossless нельзя сжать с параметром качества; используйте вместо этого JPEG/PNG/WebP-Lossy Файл не существует или недоступен для чтения \"Файл не существует или не доступен для чтения: %s\". @@ -385,6 +394,7 @@ Задержка перед циклом 0 для бесконечного цикла Поддерживаются IPv4, IPv6 и доменные имена. + Попробуйте нажать кнопку \"Активировать\", чтобы активировать плагин один раз.\nЕсли активация пройдет успешно, кнопка автоматически включится в течение некоторого времени. Введите URL, указывающий на удалённый плагин.\nНапример: \"https://example.com/plugin.apk\". Удалить навсегда Переместить в корзину @@ -431,6 +441,7 @@ Посл. устан. Посл. удал. Посл. обновл. + Механизм Размер пакета Обновл. вер. Вы уверены, что игнорируете текущую версию обновления?\nВы можете управлять всеми игнорируемыми версиями в настройках приложения. @@ -461,6 +472,7 @@ Добавление ярлыков в пусковую установку Запуск или остановка записи, управляемая клавишей уменьшения громкости, когда отображается плавающая кнопка Нажмите клавишу \"Громкость вверх\", чтобы остановить все запущенные скрипты + ": " Внутреннее хранилище Служба доступности Требуется для автоматической работы сценария (щелчок, длительное нажатие, скольжение и т.д.). @@ -483,6 +495,7 @@ Прокрутка вперед (scrollForward) Установить текст (setText) Действие + Активация выполнена Нет установщика APK Необходим инструмент ADB Добавить цветовую библиотеку @@ -542,8 +555,11 @@ Код версии приложения Название версии приложения Внешний вид + Применение бинарных ресурсов Необходимо заполнить хотя бы одно поле из: [Полное имя, Название организации, Организационная единица, Код страны, Штат или провинция, Город или населенный пункт, Улица] Атрибут + Авторизовать плагин + Это сторонний плагин. Обратите внимание на источник плагина и безопасность использования.\n\nНажмите кнопку \"Авторизовать\", чтобы включить плагин. Автоматическая проверка обновлений Автоматическая проверка обновлений и отображение закуски на домашней странице Автоматический ночной режим @@ -552,8 +568,27 @@ Назад Действие Трансляция задачи + Собрать Сборка APK + Сборка завершена + Профиль сборки + Профиль по умолчанию нельзя удалить + Профиль project.json нельзя удалить + Удалить профиль + Поля профиля + Настроить поля профиля + Отмеченные поля сохраняются как фиксированные значения в этом профиле. + Другие действия профиля + Нельзя использовать зарезервированные имена профиля (Default, project.json) + Имя профиля сборки + Новый профиль + В текущей конфигурации сборки есть несохраненные изменения. + В текущей конфигурации сборки есть несохраненные изменения; они будут записаны в project.json. + Сохранить изменения перед продолжением? Сборка прошла успешно + Сборка APK + Сборка ресурсов + Путь к собранному APK Отменить Отмен Профиль по умолчанию нельзя удалить @@ -585,6 +620,9 @@ Выберите путь восстановления Город или населенный пункт Имя класса / пакета + Очистить + Очистка завершена + Очистка рабочей области Очистить Очистить выбор файла Очистить сценарий предварительного выполнения @@ -613,6 +651,8 @@ Совместимость Доверие Конфигурация + Настройка manifest + Настройка имени пакета Вы уверены, что хотите удалить все элементы? Очистить историю? Следующая история будет очищена\n\n[ %1$s ]\n\nОчистить? @@ -628,6 +668,7 @@ Соединение не может быть установлено Не удалось подключиться Консоль + Содержимое Продолжить Скопировать Скопировать все @@ -642,8 +683,18 @@ Копировать в буфер обмена Копировать значение Копирование... + Копирование asset + Копирование assets в + Копирование каталога + Копирование файла + Копирование библиотек для ABI + Копирование библиотеки + Копирование нативных библиотек + Копирование каталога проекта + Копирование файла скрипта Код страны (XX) Код страны должен состоять из двух заглавных букв + Создание неподписанного APK Конфигурация страницы Текущая версия Ежедневная задача @@ -726,10 +777,12 @@ Включить службу доступа с безопасными настройками по таймеру Включить плагин Включено + Шифрование скрипта Ошибка Не удалось скопировать файл: %s Отчет об ошибке Оценка + Сведения об исключении Выполнить Код выполнения [%s] завершилось через %s секунд.\n @@ -742,6 +795,11 @@ Экспортировано Расширение встроенных объектов JavaScript Расширяемость + Assets плагина извлечены + Библиотеки плагина извлечены + Извлечение asset плагина + Извлечение файла so плагина + Извлечение шаблонного APK Не удалось Не удалось создать Не удалось создать ключ подписи @@ -762,6 +820,7 @@ Не удалось зарегистрироваться Не удалось отправить Не удалось получить + Не удалось сохранить project.json Не удалось сохранить удаленный проект в локальное хранилище Не удалось отправить записи журнала Не удалось обновить @@ -812,6 +871,7 @@ Кнопка скрытия Скрыть этот узел Скрыть узел того же фрейма + Подсказка История История очищена Значок @@ -867,6 +927,11 @@ Последний пакет Запуск конфигурации Запуск отладчика + Показывать значок приложения в лаунчере + Показывать логи при запуске + Запускать скрипт при загрузке + Текст слогана заставки + Показывать заставку при запуске Значок запуска Ярлыки лаунчера Смена значков запуска на некоторых устройствах может привести к потере всех существующих ярлыков AutoJs6, действуйте с осторожностью @@ -982,9 +1047,9 @@ Разрешить приложению выполнять покупки внутри приложения Разрешить приложению доступ к устройствам Bluetooth Разрешить приложению настраивать устройства Bluetooth + Разрешить приложению рекламировать себя через Bluetooth Разрешить приложению доступ к устройствам Bluetooth и состоянию подключения Разрешить приложению сканировать близлежащие устройства Bluetooth - Разрешить приложению рекламировать себя через Bluetooth Разрешить приложению отправлять намерение для закрытия системных диалогов Разрешить приложению совершать телефонные звонки Разрешить приложению доступ к камере @@ -1068,15 +1133,28 @@ Имя ввода Пожалуйста, подождите... Пожалуйста, повторите попытку позже... + Активирован + Рекомендуется активация + Авторизация отклонена + Требуется авторизация + Авторизован Центр плагинов Сведения о плагине + Официальный + Доверенный Плагины Расположение указателя Переключение \"Расположение указателя\" не удалось.\nТребуется корневой доступ. почтовые уведомления Чтобы обеспечить корректную работу фоновых служб переднего плана AutoJs6 и возможность публикации уведомлений скриптами, AutoJs6 необходимо предоставить разрешение \"публикации уведомлений\". Предварительное выполнение сценария + Подготовить + Подготовка завершена Подготовка... + Подготовка каталога assets + Подготовка конфигурации сборки + Подготовка keystore + Подготовка рабочей области Содержимое предустановленного диалога Предустановленный заголовок диалога Нажмите еще раз, чтобы закрыть диалог @@ -1085,14 +1163,19 @@ Предварительный просмотр Журнал процесса Обработка + Обработка исходников Проект Расположение проекта Доступ к носителям проекта Запрос + %1$s: %1$s: %2$s %1$s: %2$d %3$s %1$s: %2$d%3$s + Обрезка Выйти + Повторная подпись APK + Чтение ресурсов заставки Рекомендуемый Запись завершена Запрос записи @@ -1118,6 +1201,7 @@ Заменить Заменить все Замен + Замена файла URL репозитория расширения VSCode Отправить успешно Требуется версия Android OS %s (API %s), но текущая версия %s (API %s) @@ -1126,6 +1210,7 @@ Сброс выполнен успешно Сброс первоначально Сброс выполняется только для образцов + Разбор нативных библиотек плагина Перезапустить Стратегия перезагрузки Восстановить @@ -1167,6 +1252,7 @@ Сохранить конфигурацию как Сохран Сохранить в + Сохранение... Движок Задержка старта Задержка запроса разрешения на захват экрана @@ -1187,6 +1273,7 @@ Выберите файл для загрузки Выбрать значок Выбрать изображение + Выбранный плагин Отправить Создать ярлык Режим сервера @@ -1203,6 +1290,9 @@ Вид в границах макета Вид в иерархии макета Показать информацию о виджете + Подписать + Подпись завершена + Этап подписи завершен Алгоритм подписи Конфигурация подписи Схема подписи @@ -1220,6 +1310,7 @@ Время (сначала новые) Источник Путь к исходному коду + Обработка исходников завершена Специальные разрешения Стабильный режим Звезда @@ -1258,6 +1349,7 @@ Задание по времени Движок планирования таймерных задач Время + Заголовок Выбрать Переключить все Инструменты @@ -1282,6 +1374,7 @@ Неизвестное Описание Неизвестный Заголовок Неизвестная Версия + Неподписанный APK создан Не подтверждено Доступно обновление Обновить @@ -1289,6 +1382,7 @@ Обновления проверенные состояния очищены Позже Просмотр + Обновление конфигурации проекта Доступ к статистике использования Использовать ярлык Android 7.0 Использовать значок по умолчанию @@ -1298,6 +1392,7 @@ Имя пользователя не может быть пустым Использовать селектор по описанию Использовать селектор id + Использование keystore Использовать текстовый селектор Срок действия (годы) Срок действия не может быть пустым @@ -1329,86 +1424,12 @@ Путь к рабочему каталогу Параметры безопасности записи Запись системных настроек + Запись значка приложения + Запись manifest + Запись конфигурации проекта + Запись resources.arsc + Запись подписанного APK Всплывающие окна в фоне Настройки не сохранены. Продолжить? Настройки не сохранены. Выйти? - Не удалось сохранить - Сохранение... - ": " - Не удалось включить плагин - Сведения об исключении - Подсказка - Попробуйте нажать кнопку \"Активировать\", чтобы активировать плагин один раз.\nЕсли активация пройдет успешно, кнопка автоматически включится в течение некоторого времени. - Активировать - Активация выполнена - Авторизовать плагин - Это сторонний плагин. Обратите внимание на источник плагина и безопасность использования.\n\nНажмите кнопку \"Авторизовать\", чтобы включить плагин. - Авторизовать - Официальный - Авторизован - Требуется авторизация - Авторизация отклонена - Рекомендуется активация - Активирован - Доверенный - Механизм - Плагин \"%1$s\" не включен в Центре плагинов - Плагин \"%1$s\" не авторизован в Центре плагинов - Плагин \"%1$s\" не найден среди установленных приложений - Неподдерживаемое подключение плагина - %1$s: - Заголовок - Содержимое - Сборка APK - Путь к собранному APK - Очистить - Подписать - Собрать - Подготовить - Подготовка рабочей области - Извлечение шаблонного APK - Подготовка завершена - Копирование каталога проекта - Копирование файла скрипта - Обработка исходников завершена - Копирование каталога - Копирование файла - Шифрование скрипта - Замена файла - Подготовка конфигурации сборки - Чтение ресурсов заставки - Настройка manifest - Настройка имени пакета - Копирование assets в - Обработка исходников - Применение бинарных ресурсов - Копирование нативных библиотек - Обновление конфигурации проекта - Этап подписи завершен - Запись конфигурации проекта - Сборка ресурсов - Сборка завершена - Запись resources.arsc - Запись manifest - Запись значка приложения - Копирование asset - Подготовка каталога assets - Копирование библиотеки - Подготовка keystore - Неподписанный APK создан - Создание неподписанного APK - Использование keystore - Повторная подпись APK - Запись подписанного APK - Подпись завершена - Очистка завершена - Очистка рабочей области - Разбор нативных библиотек плагина - Копирование библиотек для ABI - Выбранный плагин - Библиотеки плагина извлечены - Assets плагина извлечены - Извлечение asset плагина - Извлечение файла so плагина - Запись скриптов требует выполнения хотя бы одного из следующих условий:\n- Доступ root\n- Доступ Shizuku \ No newline at end of file diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 0963b2d5..0053c5b6 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -113,9 +113,11 @@ 放棄 中止 中止連接 + 激活 添加 高級設置 修正地址 + 授權 @string/text_back 取消 取消下載 @@ -225,6 +227,7 @@ 檢查更新失敗 冒號需跟隨有效的 IP 地址 羅盤參數不能為 null + 腳本錄製需至少滿足以下條件之一:\n- Root 權限\n- Shizuku 權限 連接失敗: %s 連接至 \"%1$s\" 失敗. 連接超時 (%d 毫秒) @@ -248,6 +251,7 @@ 無法將值 %s 轉換為 Drawable 實例 複製失敗 創建失敗 + 插件啓用失敗 跳轉設置頁面失敗 Shizuku 權限授予失敗 實例 \"%s\" 創建失敗 @@ -264,6 +268,7 @@ 獲取 version.properties 失敗, 無法解析版本信息 Shizuku 權限撤銷失敗 腳本運行失敗 + 保存失敗 保存項目配置失敗 路徑 \"%1$s\" 對應文件不存在 UI 線程內無法執行阻塞操作. 可嘗試在子線程或子腳本中執行 %s() @@ -324,6 +329,9 @@ 正則表達式句法錯誤 插件 APK 不包含變體 \"%1$s\" 所需的資源文件: %2$s. 插件 APK 不包含所需的 native 庫文件: %1$s. + 插件 \"%1$s\" 未在插件中心獲得授權 + 插件 \"%1$s\" 未在插件中心啓用 + 已安裝應用中未找到插件 \"%1$s\" %1$s 插件返回的 info 為空. %1$s 插件返回的 variant 無效: %2$s. 端口號超過 65535 @@ -365,6 +373,7 @@ 未知結果類型 {名稱: %s, 參數: %s} 未知選擇器 {名稱: %s, 類型: %s} 未知類型: %s + 不支持的插件連接方式 WebP-Lossless 格式無法使用 quality 質量參數進行壓縮, 可改用 JPEG/PNG/WebP-Lossy 文件不存在或不可讀 文件不存在或不可讀: %s @@ -381,6 +390,7 @@ 開始循環前的延遲 0 表示無限循環 支持 IPv4, IPv6 及域名. + 可嘗試點擊 \"激活\" 按鈕激活一次插件.\n如激活成功, 按鈕將在一定時間內自動開啓. 輸入一個指向遠程插件地址的 URL.\n例如 \"https://example.com/plugin.apk\". 永久刪除 移入回收站 @@ -427,6 +437,7 @@ 最近安裝 最近卸載 最近更新 + 機制 安裝包大小 可更新版本 確定忽略當前更新版本嗎?\n在應用設置中可管理已忽略的所有版本. @@ -457,6 +468,7 @@ 添加快捷方式到啓動器 按 \"音量減\" 鍵開始或停止腳本錄製 (需開啓浮動按鈕) 按 \"音量加\" 鍵停止所有正在運行的腳本 + ": " 內部存儲 無障礙服務 腳本自動操作 (點擊/長按/滑動等) 所需 @@ -479,6 +491,7 @@ 向前/右/下滑動 (scrollForward) 設置文本 (setText) 動作 + 激活成功 找不到 APK 安裝器 需要 ADB 命令行工具 添加顏色庫 @@ -538,8 +551,11 @@ 應用版本號 應用版本名 外觀 + 正在應用二進制資源 [姓名, 組織名稱, 組織單位, 國家代碼, 州或省份, 城市或區域, 街道] 至少填寫一個 屬性 + 授權插件 + 這是一個第三方插件, 請注意插件來源及使用安全.\n\n點擊 \"授權\" 按鈕以啓用插件. 自動檢查更新 自動檢查更新並在首頁下方顯示通知條 自動夜間模式 @@ -548,8 +564,27 @@ 返回 動作 (Action) 廣播觸發任務 + 構建 打包應用 + 構建完成 + 構建配置 + 默認配置不可刪除 + project.json 配置不可刪除 + 刪除配置 + 配置字段 + 配置字段設置 + 已勾選字段將作為固定值保存在此配置中. + 更多配置操作 + 不能使用保留的配置名稱 (默認, project.json) + 構建配置名稱 + 新建配置 + 當前構建配置存在未保存的更改. + 當前構建配置存在未保存的更改, 將被寫入 project.json. + 是否在繼續前保存更改 打包成功 + 正在打包應用 + 正在構建資源 + 打包應用文件路徑 取消 取消 默認配置不可刪除 @@ -581,6 +616,9 @@ 選擇恢復路徑 城市或區域 類/包名 + 清理 + 清理完成 + 正在清理工作區 清空 清空文件選擇 清空預執行腳本 @@ -609,6 +647,8 @@ 兼容性 置信度 配置 + 正在配置清單文件 + 正在配置包名 是否確定清空全部記錄 是否確定清空歷史記錄 以下歷史記錄將被清空\n\n[ %1$s ]\n\n是否確定清空 @@ -624,6 +664,7 @@ 無法建立連接 連接失敗 控制枱 + 內容 繼續 複製 複製全部 @@ -638,8 +679,18 @@ 複製到剪貼板 複製值 複製中... + 正在複製資源 + 正在複製資源到 + 正在複製目錄 + 正在複製文件 + 正在複製 ABI 庫文件 + 正在複製庫文件 + 正在複製原生庫 + 正在複製項目目錄 + 正在複製腳本文件 國家代碼 (XX) 國家代碼必須為兩個大寫字母 + 正在創建未簽名 APK 當前頁面配置 當前版本 每日任務 @@ -722,10 +773,12 @@ 使用修改安全設置權限啓用無障礙服務超時 啓用插件 已啓用 + 正在加密腳本 錯誤 文件複製失敗: %s 錯誤報告 預估 + 異常信息 執行 執行代碼 [%s] 運行結束 (用時 %s 秒)\n @@ -738,6 +791,11 @@ 已導出 JavaScript 內置對象擴展 擴展性 + 已提取插件資源 + 已提取插件庫文件 + 正在提取插件資源 + 正在提取插件 so 文件 + 正在提取模板 APK 失敗 打包失敗 生成簽名密鑰失敗 @@ -758,6 +816,7 @@ 註冊失敗 提交失敗 獲取失敗 + 保存 project.json 失敗 無法保存遠程項目至本地 日誌條目發送失敗 更新失敗 @@ -808,6 +867,7 @@ 隱藏按鈕 隱藏此節點 隱藏同框節點 + 提示 歷史記錄 歷史記錄已清空 圖標 @@ -863,6 +923,11 @@ 最近包名 運行配置 啓動調試 + 在啓動器中顯示應用圖標 + 啓動時顯示日誌 + 開機時運行腳本 + 啓動頁標語文本 + 啓動時顯示啓動頁 啓動器圖標 啓動器快捷方式 部分設備切換啓動器圖標可能導致已創建的 AutoJs6 快捷方式全部丟失, 需謹慎操作 @@ -978,9 +1043,9 @@ 允許應用執行應用內購買 允許應用訪問藍牙設備 允許應用配置藍牙設備 + 允許應用透過藍牙廣播 允許應用訪問藍牙設備及連接狀態 允許應用搜尋附近的藍牙設備 - 允許應用透過藍牙廣播 允許應用發送一個意圖來關閉系統對話框 允許應用撥打電話 允許應用訪問相機 @@ -1064,15 +1129,28 @@ 請輸入名稱 請稍候... 請稍後再嘗試此操作... + 已激活 + 建議激活 + 授權拒絕 + 需要授權 + 已授權 插件中心 插件詳情 + 官方 + 受信任 插件 指針位置 切換 \"指針位置\" 顯示狀態失敗\n可能缺少 root 權限 發佈通知權限 為確保 AutoJs6 前台服務等能夠正常運行, 腳本能夠發佈通知, AutoJs6 需要被授予 \"發佈通知權限\". 預執行腳本 + 準備 + 準備完成 準備中... + 正在準備資源目錄 + 正在準備構建配置 + 正在準備密鑰庫 + 正在準備工作區 預設對話框內容 預設對話框標題 再按一次關閉對話框 @@ -1081,14 +1159,19 @@ 預覽 流程日誌 正在處理 + 正在處理源代碼 項目 項目位置 投影媒體權限 提示 + %1$s: %1$s: %2$s %1$s: %2$d %3$s %1$s: %2$d%3$s + 正在修剪 放棄 + 正在重新簽名 APK + 正在讀取啓動頁資源 推薦 錄製完成 錄製提示 @@ -1114,6 +1197,7 @@ 替換 全部替換 替換 + 正在替換文件 VSCode 插件項目地址 提交成功 要求最低安卓系統版本 %s (API %s), 當前為 %s (API %s) @@ -1122,6 +1206,7 @@ 重置成功 重置為初始內容 只能重置示例代碼文件 + 正在解析插件原生庫 重啓 重啓策略 恢復 @@ -1163,6 +1248,7 @@ 配置另存為 保存 保存到 + 正在保存... 調度引擎 啓動延遲 屏幕捕獲權限申請延遲 @@ -1183,6 +1269,7 @@ 選擇要上傳的文件 選擇圖標 選擇圖片 + 已選擇插件 發送 創建快捷方式 服務端模式 @@ -1199,6 +1286,9 @@ 在佈局範圍中查看 在佈局層次中查看 顯示控件信息 + 簽名 + 簽名完成 + 簽名階段完成 簽名算法 簽名配置 簽名方案 @@ -1216,6 +1306,7 @@ 時間 (最新優先) 來源 源代碼路徑 + 源代碼處理完成 特殊權限 穩定模式 收藏 @@ -1254,6 +1345,7 @@ 定時任務 定時任務調度引擎 定時 + 標題 待選擇 全選切換 工具 @@ -1278,6 +1370,7 @@ 未知描述 未知標題 未知版本 + 未簽名 APK 已創建 未驗證 可更新 更新 @@ -1285,6 +1378,7 @@ 更新檢查狀態已清除 稍後提示 查看更新 + 正在更新項目配置 查看使用情況權限 使用安卓 7.0 快捷方式 使用默認圖標 @@ -1294,6 +1388,7 @@ 用户名不能為空 使用描述選擇器 (desc) 使用 id 選擇器 (id) + 正在使用密鑰庫 使用文本選擇器 (text) 有效期 (年) 有效年份不能為空 @@ -1325,86 +1420,12 @@ 工作路徑 修改安全設置 修改系統設置 + 正在寫入應用圖標 + 正在寫入清單文件 + 正在寫入項目配置 + 正在寫入 resources.arsc + 正在寫入已簽名 APK 後台彈出界面 設置尚未保存, 確定要繼續操作嗎 設置尚未保存, 確定要退出嗎 - 保存失敗 - 正在保存... - ": " - 插件啓用失敗 - 異常信息 - 提示 - 可嘗試點擊 \"激活\" 按鈕激活一次插件.\n如激活成功, 按鈕將在一定時間內自動開啓. - 激活 - 激活成功 - 授權插件 - 這是一個第三方插件, 請注意插件來源及使用安全.\n\n點擊 \"授權\" 按鈕以啓用插件. - 授權 - 官方 - 已授權 - 需要授權 - 授權拒絕 - 建議激活 - 已激活 - 受信任 - 機制 - 插件 \"%1$s\" 未在插件中心啓用 - 插件 \"%1$s\" 未在插件中心獲得授權 - 已安裝應用中未找到插件 \"%1$s\" - 不支持的插件連接方式 - %1$s: - 標題 - 內容 - 正在打包應用 - 打包應用文件路徑 - 清理 - 簽名 - 構建 - 準備 - 正在準備工作區 - 正在提取模板 APK - 準備完成 - 正在複製項目目錄 - 正在複製腳本文件 - 源代碼處理完成 - 正在複製目錄 - 正在複製文件 - 正在加密腳本 - 正在替換文件 - 正在準備構建配置 - 正在讀取啓動頁資源 - 正在配置清單文件 - 正在配置包名 - 正在複製資源到 - 正在處理源代碼 - 正在應用二進制資源 - 正在複製原生庫 - 正在更新項目配置 - 簽名階段完成 - 正在寫入項目配置 - 正在構建資源 - 構建完成 - 正在寫入 resources.arsc - 正在寫入清單文件 - 正在寫入應用圖標 - 正在複製資源 - 正在準備資源目錄 - 正在複製庫文件 - 正在準備密鑰庫 - 未簽名 APK 已創建 - 正在創建未簽名 APK - 正在使用密鑰庫 - 正在重新簽名 APK - 正在寫入已簽名 APK - 簽名完成 - 清理完成 - 正在清理工作區 - 正在解析插件原生庫 - 正在複製 ABI 庫文件 - 已選擇插件 - 已提取插件庫文件 - 已提取插件資源 - 正在提取插件資源 - 正在提取插件 so 文件 - 腳本錄製需至少滿足以下條件之一:\n- Root 權限\n- Shizuku 權限 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index c71727dd..df8cbfd4 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -113,9 +113,11 @@ 放棄 中止 中止連線 + 啟用 新增 高階設定 修正地址 + 授權 @string/text_back 取消 取消下載 @@ -225,6 +227,7 @@ 檢查更新失敗 冒號需跟隨有效的 IP 地址 羅盤引數不能為 null + 指令碼錄製需至少滿足以下條件之一:\n- Root 許可權\n- Shizuku 許可權 連線失敗: %s 連線至 \"%1$s\" 失敗. 連線超時 (%d 毫秒) @@ -248,6 +251,7 @@ 無法將值 %s 轉換為 Drawable 例項 複製失敗 建立失敗 + 外掛啟用失敗 跳轉設定頁面失敗 Shizuku 許可權授予失敗 例項 \"%s\" 建立失敗 @@ -264,6 +268,7 @@ 獲取 version.properties 失敗, 無法解析版本資訊 Shizuku 許可權撤銷失敗 指令碼執行失敗 + 儲存失敗 儲存專案配置失敗 路徑 \"%1$s\" 對應檔案不存在 UI 執行緒內無法執行阻塞操作. 可嘗試在子執行緒或子指令碼中執行 %s() @@ -324,6 +329,9 @@ 正則表示式句法錯誤 外掛 APK 不包含變體 \"%1$s\" 所需的資原始檔: %2$s. 外掛 APK 不包含所需的 native 庫檔案: %1$s. + 外掛 \"%1$s\" 未在外掛中心獲得授權 + 外掛 \"%1$s\" 未在外掛中心啟用 + 已安裝應用中未找到外掛 \"%1$s\" %1$s 外掛返回的 info 為空. %1$s 外掛返回的 variant 無效: %2$s. 埠號超過 65535 @@ -365,6 +373,7 @@ 未知結果型別 {名稱: %s, 引數: %s} 未知選擇器 {名稱: %s, 型別: %s} 未知型別: %s + 不支援的外掛連線方式 WebP-Lossless 格式無法使用 quality 質量引數進行壓縮, 可改用 JPEG/PNG/WebP-Lossy 檔案不存在或不可讀 檔案不存在或不可讀: %s @@ -381,6 +390,7 @@ 開始迴圈前的延遲 0 表示無限迴圈 支援 IPv4, IPv6 及域名. + 可嘗試點選 \"啟用\" 按鈕啟用一次外掛.\n如啟用成功, 按鈕將在一定時間內自動開啟. 輸入一個指向遠端外掛地址的 URL.\n例如 \"https://example.com/plugin.apk\". 永久刪除 移入回收站 @@ -427,6 +437,7 @@ 最近安裝 最近解除安裝 最近更新 + 機制 安裝包大小 可更新版本 確定忽略當前更新版本嗎?\n在應用設定中可管理已忽略的所有版本. @@ -457,6 +468,7 @@ 新增快捷方式到啟動器 按 \"音量減\" 鍵開始或停止指令碼錄製 (需開啟浮動按鈕) 按 \"音量加\" 鍵停止所有正在執行的指令碼 + ": " 內部儲存 無障礙服務 指令碼自動操作 (點選/長按/滑動等) 所需 @@ -479,6 +491,7 @@ 向前/右/下滑動 (scrollForward) 設定文字 (setText) 動作 + 啟用成功 找不到 APK 安裝器 需要 ADB 命令列工具 新增顏色庫 @@ -538,8 +551,11 @@ 應用版本號 應用版本名 外觀 + 正在應用二進位制資源 [姓名, 組織名稱, 組織單位, 國家代碼, 州或省份, 城市或區域, 街道] 至少填寫一個 屬性 + 授權外掛 + 這是一個第三方外掛, 請注意外掛來源及使用安全.\n\n點選 \"授權\" 按鈕以啟用外掛. 自動檢查更新 自動檢查更新並在首頁下方顯示通知條 自動夜間模式 @@ -548,8 +564,27 @@ 返回 動作 (Action) 廣播觸發任務 + 構建 打包應用 + 構建完成 + 構建配置 + 預設配置不可刪除 + project.json 配置不可刪除 + 刪除配置 + 配置欄位 + 配置欄位設定 + 已勾選欄位將作為固定值儲存在此配置中. + 更多配置操作 + 不能使用保留的配置名稱 (預設, project.json) + 構建配置名稱 + 新建配置 + 當前構建配置存在未儲存的更改. + 當前構建配置存在未儲存的更改, 將被寫入 project.json. + 是否在繼續前儲存更改 打包成功 + 正在打包應用 + 正在構建資源 + 打包應用檔案路徑 取消 取消 預設配置不可刪除 @@ -581,6 +616,9 @@ 選擇恢復路徑 城市或區域 類/包名 + 清理 + 清理完成 + 正在清理工作區 清空 清空檔案選擇 清空預執行指令碼 @@ -609,6 +647,8 @@ 相容性 置信度 配置 + 正在配置清單檔案 + 正在配置包名 是否確定清空全部記錄 是否確定清空歷史記錄 以下歷史記錄將被清空\n\n[ %1$s ]\n\n是否確定清空 @@ -624,6 +664,7 @@ 無法建立連線 連線失敗 控制檯 + 內容 繼續 複製 複製全部 @@ -638,8 +679,18 @@ 複製到剪貼簿 複製值 複製中... + 正在複製資源 + 正在複製資源到 + 正在複製目錄 + 正在複製檔案 + 正在複製 ABI 庫檔案 + 正在複製庫檔案 + 正在複製原生庫 + 正在複製專案目錄 + 正在複製指令碼檔案 國家代碼 (XX) 國家代碼必須是兩個大寫字母 + 正在建立未簽名 APK 當前頁面配置 當前版本 每日任務 @@ -722,10 +773,12 @@ 使用修改安全設定許可權啟用無障礙服務超時 啟用外掛 已啟用 + 正在加密指令碼 錯誤 檔案複製失敗: %s 錯誤報告 預估 + 異常資訊 執行 執行程式碼 [%s] 執行結束 (用時 %s 秒)\n @@ -738,6 +791,11 @@ 已匯出 JavaScript 內建物件擴充套件 擴充套件性 + 已提取外掛資源 + 已提取外掛庫檔案 + 正在提取外掛資源 + 正在提取外掛 so 檔案 + 正在提取模板 APK 失敗 打包失敗 生成簽名密鑰失敗 @@ -758,6 +816,7 @@ 註冊失敗 提交失敗 獲取失敗 + 儲存 project.json 失敗 無法儲存遠端專案至本地 日誌條目傳送失敗 更新失敗 @@ -808,6 +867,7 @@ 隱藏按鈕 隱藏此節點 隱藏同框節點 + 提示 歷史記錄 歷史記錄已清空 圖示 @@ -863,6 +923,11 @@ 最近包名 執行配置 啟動除錯 + 在啟動器中顯示應用圖示 + 啟動時顯示日誌 + 開機時執行指令碼 + 啟動頁標語文字 + 啟動時顯示啟動頁 啟動器圖示 啟動器快捷方式 部分裝置切換啟動器圖示可能導致已建立的 AutoJs6 快捷方式全部丟失, 需謹慎操作 @@ -978,9 +1043,9 @@ 允許應用執行應用內購買 允許應用訪問藍牙設備 允許應用配置藍牙設備 + 允許應用透過藍牙廣播 允許應用訪問藍牙設備及連接狀態 允許應用搜尋附近的藍牙設備 - 允許應用透過藍牙廣播 允許應用發送一個意圖來關閉系統對話框 允許應用撥打電話 允許應用訪問相機 @@ -1064,15 +1129,28 @@ 請輸入名稱 請稍候... 請稍後再嘗試此操作... + 已啟用 + 建議啟用 + 授權拒絕 + 需要授權 + 已授權 外掛中心 外掛詳情 + 官方 + 受信任 外掛 指標位置 切換 \"指標位置\" 顯示狀態失敗\n可能缺少 root 許可權 釋出通知許可權 為確保 AutoJs6 前臺服務等能夠正常執行, 指令碼能夠釋出通知, AutoJs6 需要被授予 \"釋出通知許可權\". 預執行指令碼 + 準備 + 準備完成 準備中... + 正在準備資源目錄 + 正在準備構建配置 + 正在準備金鑰庫 + 正在準備工作區 預設對話方塊內容 預設對話方塊標題 再按一次關閉對話方塊 @@ -1081,14 +1159,19 @@ 預覽 流程日誌 正在處理 + 正在處理原始碼 專案 專案位置 投影媒體許可權 提示 + %1$s: %1$s: %2$s %1$s: %2$d %3$s %1$s: %2$d%3$s + 正在修剪 放棄 + 正在重新簽名 APK + 正在讀取啟動頁資源 推薦 錄製完成 錄製提示 @@ -1114,6 +1197,7 @@ 替換 全部替換 替換 + 正在替換檔案 VSCode 外掛專案地址 提交成功 要求最低安卓系統版本 %s (API %s), 當前為 %s (API %s) @@ -1122,6 +1206,7 @@ 重置成功 重置為初始內容 只能重置示例程式碼檔案 + 正在解析外掛原生庫 重啟 重啟策略 恢復 @@ -1163,6 +1248,7 @@ 配置另存為 儲存 儲存到 + 正在儲存... 排程引擎 啟動延遲 螢幕捕獲許可權申請延遲 @@ -1183,6 +1269,7 @@ 選擇要上傳的檔案 選擇圖示 選擇圖片 + 已選擇外掛 傳送 建立快捷方式 服務端模式 @@ -1199,6 +1286,9 @@ 在佈局範圍中檢視 在佈局層次中檢視 顯示控制元件資訊 + 簽名 + 簽名完成 + 簽名階段完成 簽名演算法 簽名設定 簽名方案 @@ -1216,6 +1306,7 @@ 時間 (最新優先) 來源 原始碼路徑 + 原始碼處理完成 特殊許可權 穩定模式 收藏 @@ -1254,6 +1345,7 @@ 定時任務 定時任務排程引擎 定時 + 標題 待選擇 全選切換 工具 @@ -1278,6 +1370,7 @@ 未知描述 未知標題 未知版本 + 未簽名 APK 已建立 未驗證 可更新 更新 @@ -1285,6 +1378,7 @@ 更新檢查狀態已清除 稍後提示 檢視更新 + 正在更新專案配置 檢視使用情況許可權 使用安卓 7.0 快捷方式 使用預設圖示 @@ -1294,6 +1388,7 @@ 使用者名稱不能為空 使用描述選擇器 (desc) 使用 id 選擇器 (id) + 正在使用金鑰庫 使用文字選擇器 (text) 有效期 (年) 有效年份不能為空 @@ -1325,86 +1420,12 @@ 工作路徑 修改安全設定 修改系統設定 + 正在寫入應用圖示 + 正在寫入清單檔案 + 正在寫入專案配置 + 正在寫入 resources.arsc + 正在寫入已簽名 APK 後臺彈出介面 設定尚未儲存, 確定要繼續操作嗎 設定尚未儲存, 確定要退出嗎 - 儲存失敗 - 正在儲存... - ": " - 外掛啟用失敗 - 異常資訊 - 提示 - 可嘗試點選 \"啟用\" 按鈕啟用一次外掛.\n如啟用成功, 按鈕將在一定時間內自動開啟. - 啟用 - 啟用成功 - 授權外掛 - 這是一個第三方外掛, 請注意外掛來源及使用安全.\n\n點選 \"授權\" 按鈕以啟用外掛. - 授權 - 官方 - 已授權 - 需要授權 - 授權拒絕 - 建議啟用 - 已啟用 - 受信任 - 機制 - 外掛 \"%1$s\" 未在外掛中心啟用 - 外掛 \"%1$s\" 未在外掛中心獲得授權 - 已安裝應用中未找到外掛 \"%1$s\" - 不支援的外掛連線方式 - %1$s: - 標題 - 內容 - 正在打包應用 - 打包應用檔案路徑 - 清理 - 簽名 - 構建 - 準備 - 正在準備工作區 - 正在提取模板 APK - 準備完成 - 正在複製專案目錄 - 正在複製指令碼檔案 - 原始碼處理完成 - 正在複製目錄 - 正在複製檔案 - 正在加密指令碼 - 正在替換檔案 - 正在準備構建配置 - 正在讀取啟動頁資源 - 正在配置清單檔案 - 正在配置包名 - 正在複製資源到 - 正在處理原始碼 - 正在應用二進位制資源 - 正在複製原生庫 - 正在更新專案配置 - 簽名階段完成 - 正在寫入專案配置 - 正在構建資源 - 構建完成 - 正在寫入 resources.arsc - 正在寫入清單檔案 - 正在寫入應用圖示 - 正在複製資源 - 正在準備資源目錄 - 正在複製庫檔案 - 正在準備金鑰庫 - 未簽名 APK 已建立 - 正在建立未簽名 APK - 正在使用金鑰庫 - 正在重新簽名 APK - 正在寫入已簽名 APK - 簽名完成 - 清理完成 - 正在清理工作區 - 正在解析外掛原生庫 - 正在複製 ABI 庫檔案 - 已選擇外掛 - 已提取外掛庫檔案 - 已提取外掛資源 - 正在提取外掛資源 - 正在提取外掛 so 檔案 - 指令碼錄製需至少滿足以下條件之一:\n- Root 許可權\n- Shizuku 許可權 \ No newline at end of file diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 4eb96b23..2d959d9b 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -3,7 +3,6 @@ - 构建中 清理临时文件 打包中 @@ -114,9 +113,11 @@ 放弃 中止 中止连接 + 激活 添加 高级设置 修正地址 + 授权 @string/text_back 取消 取消下载 @@ -226,6 +227,7 @@ 检查更新失败 冒号需跟随有效的 IP 地址 罗盘参数不能为 null + 脚本录制需至少满足以下条件之一:\n- Root 权限\n- Shizuku 权限 连接失败: %s 连接至 \"%1$s\" 失败. 连接超时 (%d 毫秒) @@ -249,6 +251,7 @@ 无法将值 %s 转换为 Drawable 实例 复制失败 创建失败 + 插件启用失败 跳转设置页面失败 Shizuku 权限授予失败 实例 \"%s\" 创建失败 @@ -265,6 +268,7 @@ 获取 version.properties 失败, 无法解析版本信息 Shizuku 权限撤销失败 脚本运行失败 + 保存失败 保存项目配置失败 路径 \"%1$s\" 对应文件不存在 UI 线程内无法执行阻塞操作. 可尝试在子线程或子脚本中执行 %s() @@ -325,6 +329,9 @@ 正则表达式句法错误 插件 APK 不包含变体 \"%1$s\" 所需的资源文件: %2$s. 插件 APK 不包含所需的 native 库文件: %1$s. + 插件 \"%1$s\" 未在插件中心获得授权 + 插件 \"%1$s\" 未在插件中心启用 + 已安装应用中未找到插件 \"%1$s\" %1$s 插件返回的 info 为空. %1$s 插件返回的 variant 无效: %2$s. 端口号超过 65535 @@ -366,6 +373,7 @@ 未知结果类型 {名称: %s, 参数: %s} 未知选择器 {名称: %s, 类型: %s} 未知类型: %s + 不支持的插件连接方式 WebP-Lossless 格式无法使用 quality 质量参数进行压缩, 可改用 JPEG/PNG/WebP-Lossy 文件不存在或不可读 文件不存在或不可读: %s @@ -382,6 +390,7 @@ 开始循环前的延迟 0 表示无限循环 支持 IPv4, IPv6 及域名. + 可尝试点击 \"激活\" 按钮激活一次插件.\n如激活成功, 按钮将在一定时间内自动开启. 输入一个指向远程插件地址的 URL.\n例如 \"https://example.com/plugin.apk\". 永久删除 移入回收站 @@ -428,6 +437,7 @@ 最近安装 最近卸载 最近更新 + 机制 安装包大小 可更新版本 确定忽略当前更新版本吗?\n在应用设置中可管理已忽略的所有版本. @@ -458,6 +468,7 @@ 添加快捷方式到启动器 按 \"音量减\" 键开始或停止脚本录制 (需开启浮动按钮) 按 \"音量加\" 键停止所有正在运行的脚本 + ": " 内部存储 无障碍服务 脚本自动操作 (点击/长按/滑动等) 所需 @@ -480,6 +491,7 @@ 向前/右/下滑动 (scrollForward) 设置文本 (setText) 动作 + 激活成功 找不到 APK 安装器 需要 ADB 命令行工具 添加颜色库 @@ -539,8 +551,11 @@ 应用版本号 应用版本名 外观 + 正在应用二进制资源 [姓名, 组织名称, 组织单位, 国家代码, 州或省份, 城市或区域, 街道] 至少填写一个 属性 + 授权插件 + 这是一个第三方插件, 请注意插件来源及使用安全.\n\n点击 \"授权\" 按钮以启用插件. 自动检查更新 自动检查更新并在首页下方显示通知条 自动夜间模式 @@ -549,8 +564,27 @@ 返回 动作 (Action) 广播触发任务 + 构建 打包应用 + 构建完成 + 构建配置 + 默认配置不可删除 + project.json 配置不可删除 + 删除配置 + 配置字段 + 配置字段设置 + 已勾选字段将作为固定值保存在此配置中. + 更多配置操作 + 不能使用保留的配置名称 (默认, project.json) + 构建配置名称 + 新建配置 + 当前构建配置存在未保存的更改. + 当前构建配置存在未保存的更改, 将被写入 project.json. + 是否在继续前保存更改 打包成功 + 正在打包应用 + 正在构建资源 + 打包应用文件路径 取消 取消 默认配置不可删除 @@ -582,6 +616,9 @@ 选择恢复路径 城市或区域 类/包名 + 清理 + 清理完成 + 正在清理工作区 清空 清空文件选择 清空预执行脚本 @@ -610,6 +647,8 @@ 兼容性 置信度 配置 + 正在配置清单文件 + 正在配置包名 是否确定清空全部记录 是否确定清空历史记录 以下历史记录将被清空\n\n[ %1$s ]\n\n是否确定清空 @@ -625,6 +664,7 @@ 无法建立连接 连接失败 控制台 + 内容 继续 复制 复制全部 @@ -639,8 +679,18 @@ 复制到剪贴板 复制值 复制中... + 正在复制资源 + 正在复制资源到 + 正在复制目录 + 正在复制文件 + 正在复制 ABI 库文件 + 正在复制库文件 + 正在复制原生库 + 正在复制项目目录 + 正在复制脚本文件 国家代码 (XX) 国家代码必须为两个大写字母 + 正在创建未签名 APK 当前页面配置 当前版本 每日任务 @@ -723,10 +773,12 @@ 使用修改安全设置权限启用无障碍服务超时 启用插件 已启用 + 正在加密脚本 错误 文件复制失败: %s 错误报告 预估 + 异常信息 执行 执行代码 [%s] 运行结束 (用时 %s 秒)\n @@ -739,6 +791,11 @@ 已导出 JavaScript 内置对象扩展 扩展性 + 已提取插件资源 + 已提取插件库文件 + 正在提取插件资源 + 正在提取插件 so 文件 + 正在提取模板 APK 失败 打包失败 生成签名密钥失败 @@ -759,6 +816,7 @@ 注册失败 提交失败 获取失败 + 保存 project.json 失败 无法保存远程项目至本地 日志条目发送失败 更新失败 @@ -809,6 +867,7 @@ 隐藏按钮 隐藏此节点 隐藏同框节点 + 提示 历史记录 历史记录已清空 图标 @@ -864,6 +923,11 @@ 最近包名 运行配置 启动调试 + 在启动器中显示应用图标 + 启动时显示日志 + 开机时运行脚本 + 启动页标语文本 + 启动时显示启动页 启动器图标 启动器快捷方式 部分设备切换启动器图标可能导致已创建的 AutoJs6 快捷方式全部丢失, 需谨慎操作 @@ -979,9 +1043,9 @@ 允许应用执行应用内购买 允许应用访问蓝牙设备 允许应用配置蓝牙设备 + 允许应用通过蓝牙广播 允许应用访问蓝牙设备及连接状态 允许应用扫描附近的蓝牙设备 - 允许应用通过蓝牙广播 允许应用发送一个意图来关闭系统对话框 允许应用拨打电话 允许应用访问相机 @@ -1065,15 +1129,28 @@ 请输入名称 请稍候... 请稍后再尝试此操作... + 已激活 + 建议激活 + 授权拒绝 + 需要授权 + 已授权 插件中心 插件详情 + 官方 + 受信任 插件 指针位置 切换 \"指针位置\" 显示状态失败\n可能缺少 root 权限 发布通知权限 为确保 AutoJs6 前台服务等能够正常运行, 脚本能够发布通知, AutoJs6 需要被授予 \"发布通知权限\". 预执行脚本 + 准备 + 准备完成 准备中... + 正在准备资源目录 + 正在准备构建配置 + 正在准备密钥库 + 正在准备工作区 预设对话框内容 预设对话框标题 再按一次关闭对话框 @@ -1082,14 +1159,19 @@ 预览 流程日志 正在处理 + 正在处理源代码 项目 项目位置 投影媒体权限 提示 + %1$s: %1$s: %2$s %1$s: %2$d %3$s %1$s: %2$d%3$s + 正在修剪 放弃 + 正在重新签名 APK + 正在读取启动页资源 推荐 录制完成 录制提示 @@ -1115,6 +1197,7 @@ 替换 全部替换 替换 + 正在替换文件 VSCode 插件项目地址 提交成功 要求最低安卓系统版本 %s (API %s), 当前为 %s (API %s) @@ -1123,6 +1206,7 @@ 重置成功 重置为初始内容 只能重置示例代码文件 + 正在解析插件原生库 重启 重启策略 恢复 @@ -1164,6 +1248,7 @@ 配置另存为 保存 保存到 + 正在保存... 调度引擎 启动延迟 屏幕捕获权限申请延迟 @@ -1184,6 +1269,7 @@ 选择要上传的文件 选择图标 选择图片 + 已选择插件 发送 创建快捷方式 服务端模式 @@ -1200,6 +1286,9 @@ 在布局范围中查看 在布局层次中查看 显示控件信息 + 签名 + 签名完成 + 签名阶段完成 签名算法 签名配置 签名方案 @@ -1217,6 +1306,7 @@ 时间 (最新优先) 来源 源代码路径 + 源代码处理完成 特殊权限 稳定模式 收藏 @@ -1255,6 +1345,7 @@ 定时任务 定时任务调度引擎 定时 + 标题 待选择 全选切换 工具 @@ -1279,6 +1370,7 @@ 未知描述 未知标题 未知版本 + 未签名 APK 已创建 未验证 可更新 更新 @@ -1286,6 +1378,7 @@ 更新检查状态已清除 稍后提示 查看更新 + 正在更新项目配置 查看使用情况权限 使用安卓 7.0 快捷方式 使用默认图标 @@ -1295,6 +1388,7 @@ 用户名不能为空 使用描述选择器 (desc) 使用 id 选择器 (id) + 正在使用密钥库 使用文本选择器 (text) 有效期 (年) 有效年份不能为空 @@ -1326,86 +1420,12 @@ 工作路径 修改安全设置 修改系统设置 + 正在写入应用图标 + 正在写入清单文件 + 正在写入项目配置 + 正在写入 resources.arsc + 正在写入已签名 APK 后台弹出界面 设置尚未保存, 确定要继续操作吗 设置尚未保存, 确定要退出吗 - 保存失败 - 正在保存... - ": " - 插件启用失败 - 异常信息 - 提示 - 可尝试点击 \"激活\" 按钮激活一次插件.\n如激活成功, 按钮将在一定时间内自动开启. - 激活 - 激活成功 - 授权插件 - 这是一个第三方插件, 请注意插件来源及使用安全.\n\n点击 \"授权\" 按钮以启用插件. - 授权 - 官方 - 已授权 - 需要授权 - 授权拒绝 - 建议激活 - 已激活 - 受信任 - 机制 - 插件 \"%1$s\" 未在插件中心启用 - 插件 \"%1$s\" 未在插件中心获得授权 - 已安装应用中未找到插件 \"%1$s\" - 不支持的插件连接方式 - %1$s: - 标题 - 内容 - 正在打包应用 - 打包应用文件路径 - 清理 - 签名 - 构建 - 准备 - 正在准备工作区 - 正在提取模板 APK - 准备完成 - 正在复制项目目录 - 正在复制脚本文件 - 源代码处理完成 - 正在复制目录 - 正在复制文件 - 正在加密脚本 - 正在替换文件 - 正在准备构建配置 - 正在读取启动页资源 - 正在配置清单文件 - 正在配置包名 - 正在复制资源到 - 正在处理源代码 - 正在应用二进制资源 - 正在复制原生库 - 正在更新项目配置 - 签名阶段完成 - 正在写入项目配置 - 正在构建资源 - 构建完成 - 正在写入 resources.arsc - 正在写入清单文件 - 正在写入应用图标 - 正在复制资源 - 正在准备资源目录 - 正在复制库文件 - 正在准备密钥库 - 未签名 APK 已创建 - 正在创建未签名 APK - 正在使用密钥库 - 正在重新签名 APK - 正在写入已签名 APK - 签名完成 - 清理完成 - 正在清理工作区 - 正在解析插件原生库 - 正在复制 ABI 库文件 - 已选择插件 - 已提取插件库文件 - 已提取插件资源 - 正在提取插件资源 - 正在提取插件 so 文件 - 脚本录制需至少满足以下条件之一:\n- Root 权限\n- Shizuku 权限 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2f894d30..6845df06 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -144,6 +144,7 @@ key_$_night_mode_follow_system key_$_night_mode_null key_$_not_showing_main_activity + key_$_run_on_boot_inrt key_$_pc_server_address_histories key_$_post_notifications_permission key_$_post_notifications_permission_auto_request_done @@ -387,9 +388,11 @@ Abandon Abort Abort + Activate Add Advanced Amend + Authorize @string/text_back Cancel Cancel @@ -502,6 +505,7 @@ Failed to check for updates Colon must follow a valid IP address Compass cannot be null + Script recording requires at least one of the following conditions:\n- Root access\n- Shizuku access Cannot connect to the remote server: %s Failed to connect to \"%1$s\". Connection timed out after %d ms @@ -525,6 +529,7 @@ Failed to convert value %s into a Drawable Failed to copy Failed to create + Failed to enable the plugin Failed to open the settings page Failed to grant Shizuku access Failed to instantiate \"%s\" @@ -541,6 +546,7 @@ Failed to retrieve version.properties to parse version information Failed to revoke Shizuku access Failed to run script + Failed to save Failed to save project config File in path \"%1$s\" does not exist UI thread cannot be blocked. Try running %s() in sub-thread or sub-script @@ -601,6 +607,9 @@ Invalid pattern syntax Plugin APK does not contain required assets for variant=\"%1$s\": %2$s. Plugin APK does not contain required native libraries: %1$s. + Plugin \"%1$s\" is not authorized in Plugin Center + Plugin \"%1$s\" is not enabled in Plugin Center + Plugin \"%1$s\" not found in installed apps %1$s plugin returned empty info. %1$s plugin returned invalid variant: %2$s. Port number over 65535 @@ -642,6 +651,7 @@ Unknown result type {name: %s, params: %s} Unknown selector {name: %s, type: %s} Unknown type: %s + Unsupported plugin connection Format WebP-Lossless cannot be compressed with a quality parameter, use JPEG/PNG/WebP-Lossy instead File does not exist or readable File does not exist or readable: %s @@ -658,6 +668,7 @@ Delay before loop 0 for infinite loop IPv4, IPv6 and domain are supported. + Try clicking the \"Activate\" button to activate the plugin once.\nIf activation is successful, the button will automatically turn on within a certain period of time. Enter a URL pointing to a remote plugin address.\nFor example \"https://example.com/plugin.apk\". Delete permanently Move to trash @@ -704,6 +715,7 @@ Last install Last uninstall Last update + Mechanism Package size Updatable ver. Are you sure to ignore current update version?\nYou can manage all ignored versions by app settings. @@ -734,6 +746,7 @@ Add shortcuts to launcher Start or stop recording controlled by \"Volume Down\" key when floating button is showing Press \"Volume Up\" key to stop all running scripts + ": " Internal Storage Accessibility service Required by the script automatic operation (click, long press, slide, etc.). @@ -756,6 +769,7 @@ Scroll forward (scrollForward) Set text (setText) Action + Activated successfully No APK installer ADB tool is needed Add a color library @@ -815,8 +829,11 @@ App version code App version name Appearance + Applying binary resources At least one field from [Full Name, Organization Name, Organizational Unit, Country Code, State or Province, City or Locality, Street] must be filled Attribute + Authorize Plugin + This is a third-party plugin. Please pay attention to the plugin source and usage safety.\n\nClick the \"Authorize\" button to enable the plugin. Auto check for updates Check for updates automatically and show a snackbar on homepage Auto night mode @@ -825,8 +842,27 @@ Back Action Broadcast task + Build Build APK + Build completed + Build profile + Default profile cannot be deleted + project.json profile cannot be deleted + Delete profile + Profile fields + Configure profile fields + Checked fields are saved as fixed values in this profile. + More profile actions + Cannot use reserved profile names (Default, project.json) + Build profile name + New profile + Current build configuration has unsaved changes. + Current build configuration has unsaved changes and will be written to project.json. + Save changes before continuing? Build succeeded + Building APK + Building resources + Built APK file path Cancel Cancel Default profile cannot be deleted @@ -858,6 +894,9 @@ Choose restore path City or Locality Class / Package name + Clean + Clean completed + Cleaning workspace Clear Clear file selection Clear pre-execute script @@ -886,6 +925,8 @@ Compatibility Confidence Config + Configuring manifest + Configuring package name Are you sure to clear all items? Are you sure to clear the history? The history below will be cleared\n\n[ %1$s ]\n\nAre you sure to clear? @@ -901,6 +942,7 @@ Connection cannot be established Connection failed Console + Content Continue Copy Copy all @@ -915,8 +957,18 @@ Copy to clipboard Copy value Copying... + Copying asset + Copying assets to + Copying directory + Copying file + Copying libraries for ABI + Copying library + Copying native libraries + Copying project directory + Copying script file Country Code (XX) Country code must be two capital letters + Creating unsigned APK Current page configuration Current version Daily task @@ -999,10 +1051,12 @@ Enable accessibility service with secure settings timed out Enable plugin Enabled + Encrypting script Error Failed to copy file: %s Bug report Estimated + Exception info Execute Execute code [%s] finished in %s seconds.\n @@ -1015,6 +1069,11 @@ Exported Extending JavaScript build-in objects Extensibility + Extracted plugin assets + Extracted plugin libraries + Extracting plugin asset + Extracting plugin so + Extracting template APK Failed Failed to build Failed to create signature key @@ -1035,6 +1094,7 @@ Failed to register Failed to submit Failed to retrieve + Failed to save project.json Failed to save remote project to local storage Failed to send log entries Failed to update @@ -1085,6 +1145,7 @@ Hide button Hide this node Hide same frame nodes + Hint History The history has been cleared Icon @@ -1140,6 +1201,11 @@ Latest package Launch config Launch debugger + Show app icon in launcher + Show logs on launch + Run script on boot + Splash slug text + Show splash screen on launch Launcher icon Launcher shortcuts Switching launcher icons on some devices may cause all existing AutoJs6 shortcuts to be lost, please proceed with caution @@ -1255,9 +1321,9 @@ Allow the app to perform in-app purchases Allow the app to access Bluetooth devices Allow the app to configure Bluetooth devices + Allow the app to advertise via Bluetooth Allow the app to access Bluetooth devices and connection state Allow the app to scan for nearby Bluetooth devices - Allow the app to advertise via Bluetooth Allow the app to send an intent to close system dialogs Allow the app to make phone calls Allow the app to access the camera @@ -1341,15 +1407,28 @@ Input name Please wait... Please wait a moment before trying again... + Activated + Activation recommended + Authorization denied + Authorization required + Authorized Plugin center Plugin details + Official + Trusted Plugins Pointer location Toggle \"pointer location\" failed.\nRoot access is required. Post notifications To ensure that AutoJs6 foreground services, etc. can work properly and that scripts can post notifications, AutoJs6 must be granted the \"post notifications\" permission. Pre-execute script + Prepare + Prepare completed Preparing... + Preparing assets dir + Preparing build config + Preparing keystore + Preparing workspace Preset dialog content Preset dialog title Press again to dismiss the dialog @@ -1358,14 +1437,19 @@ Preview Process log Processing + Processing source Project Project location Project media access Prompt + %1$s: %1$s: %2$s %1$s: %2$d %3$s %1$s: %2$d%3$s + Pruning Quit + Re-signing APK + Reading splash resources Recommended Recording finished Recording prompt @@ -1391,6 +1475,7 @@ Replace Replace all Replace + Replacing file Repository URL of VSCode extension Submit succeeded Requires Android OS version %s (API %s) but current is %s (API %s) @@ -1399,6 +1484,7 @@ Reset succeeded Reset initially Reset is only for samples + Resolving plugin native libraries Restart Restart strategy Restore @@ -1440,6 +1526,7 @@ Save configuration as Save Save to + Saving... Backend Start delay Screen capture permission request delay @@ -1460,6 +1547,7 @@ Select file to upload Select icon Select an image + Selected plugin Send Create shortcut Server mode @@ -1476,6 +1564,9 @@ View in layout bounds View in layout hierarchy Show widget information + Sign + Sign completed + Sign stage completed Signature Algorithm Signature Configuration Signature Scheme @@ -1493,6 +1584,7 @@ Time (newest first) Source Source code path + Source processing completed Special permissions Stable mode Star @@ -1531,6 +1623,7 @@ Timed task Timed task scheduling engine Timing + Title To be chosen Toggle all Tools @@ -1555,6 +1648,7 @@ Unknown Description Unknown Title Unknown Version + Unsigned APK created Unverified Updatable Update @@ -1562,6 +1656,7 @@ Updates checked states cleared Later View + Updating project config Usage stats access Use Android 7.0 shortcut Use default icon @@ -1571,6 +1666,7 @@ Username cannot be empty Use desc selector Use id selector + Using keystore Use text selector Validity (Years) Validity years cannot be empty @@ -1602,86 +1698,12 @@ Working directory path Write security settings Write system settings + Writing app icon + Writing manifest + Writing project config + Writing resources.arsc + Writing signed APK Display pop-up windows while running in the background The settings has not been saved, are you sure to continue the operation? The settings has not been saved, are you sure to exit? - Failed to save - Saving... - ": " - Failed to enable the plugin - Exception info - Hint - Try clicking the \"Activate\" button to activate the plugin once.\nIf activation is successful, the button will automatically turn on within a certain period of time. - Activate - Activated successfully - Authorize Plugin - This is a third-party plugin. Please pay attention to the plugin source and usage safety.\n\nClick the \"Authorize\" button to enable the plugin. - Authorize - Official - Authorized - Authorization required - Authorization denied - Activation recommended - Activated - Trusted - Mechanism - Plugin \"%1$s\" is not enabled in Plugin Center - Plugin \"%1$s\" is not authorized in Plugin Center - Plugin \"%1$s\" not found in installed apps - Unsupported plugin connection - %1$s: - Title - Content - Building APK - Built APK file path - Clean - Sign - Build - Prepare - Preparing workspace - Extracting template APK - Prepare completed - Copying project directory - Copying script file - Source processing completed - Copying directory - Copying file - Encrypting script - Replacing file - Preparing build config - Reading splash resources - Configuring manifest - Configuring package name - Copying assets to - Processing source - Applying binary resources - Copying native libraries - Updating project config - Sign stage completed - Writing project config - Building resources - Build completed - Writing resources.arsc - Writing manifest - Writing app icon - Copying asset - Preparing assets dir - Copying library - Preparing keystore - Unsigned APK created - Creating unsigned APK - Using keystore - Re-signing APK - Writing signed APK - Sign completed - Clean completed - Cleaning workspace - Resolving plugin native libraries - Copying libraries for ABI - Selected plugin - Extracted plugin libraries - Extracted plugin assets - Extracting plugin asset - Extracting plugin so - Script recording requires at least one of the following conditions:\n- Root access\n- Shizuku access \ No newline at end of file diff --git a/app/src/main/res/xml-v25/inrt_app_shortcuts.xml b/app/src/main/res/xml-v25/inrt_app_shortcuts.xml new file mode 100644 index 00000000..600290f4 --- /dev/null +++ b/app/src/main/res/xml-v25/inrt_app_shortcuts.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/xml/fragment_preferences_inrt.xml b/app/src/main/res/xml/fragment_preferences_inrt.xml index 22a413c3..6680c258 100644 --- a/app/src/main/res/xml/fragment_preferences_inrt.xml +++ b/app/src/main/res/xml/fragment_preferences_inrt.xml @@ -49,6 +49,12 @@ android:key="@string/key_use_volume_control_running" android:title="@string/text_use_volume_key_to_control_script_running" /> + + - \ No newline at end of file + diff --git a/version.properties b/version.properties index e87f00d0..f0d2e882 100644 --- a/version.properties +++ b/version.properties @@ -1,5 +1,5 @@ -#Sun Mar 08 15:56:02 CST 2026 -BUILD_TIME=1772956562907 +#Thu Mar 12 21:00:26 CST 2026 +BUILD_TIME=1773320426437 COMPILE_SDK_VERSION=36 IMAGE_QUANT_CMAKE_VERSION=3.22.1 IMAGE_QUANT_NDK_VERSION=26.1.10909125 @@ -27,6 +27,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3 TARGET_SDK_VERSION=36 TARGET_SDK_VERSION_INRT=29 -VERSION_BUILD=3782 +VERSION_BUILD=3803 VERSION_NAME=6.7.0 Alpha23 VSCODE_EXT_REQUIRED_VERSION=1.0.13