diff --git a/config.xml b/config.xml index a5123ff8d..dc125f26a 100644 --- a/config.xml +++ b/config.xml @@ -1,90 +1,142 @@ - - - Acode - - Light weight code editor and web IDE for android. - - - Foxdebug - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + Acode + + Light weight code editor and web IDE for android. + + + Foxdebug + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/package.json b/package.json index c111ae087..440e56dda 100644 --- a/package.json +++ b/package.json @@ -42,9 +42,7 @@ "cordova-plugin-iap": {}, "com.foxdebug.acode.rk.customtabs": {}, "cordova-plugin-system": {}, - "cordova-plugin-advanced-http": { - "ANDROIDBLACKLISTSECURESOCKETPROTOCOLS": "SSLv3,TLSv1" - } + "cordova-plugin-advanced-http": {} }, "platforms": [ "android" diff --git a/res/android/drawable/ic_alt.png b/res/android/drawable/ic_alt.png new file mode 100644 index 000000000..991687e72 Binary files /dev/null and b/res/android/drawable/ic_alt.png differ diff --git a/src/plugins/system/android/com/foxdebug/system/System.java b/src/plugins/system/android/com/foxdebug/system/System.java index 672a19e4d..bd237a137 100644 --- a/src/plugins/system/android/com/foxdebug/system/System.java +++ b/src/plugins/system/android/com/foxdebug/system/System.java @@ -215,6 +215,8 @@ public boolean execute( case "compare-texts": case "extractAsset": case "pin-file-shortcut": + case "get-app-icons": + case "set-app-icon": break; case "get-configuration": getConfiguration(callbackContext); @@ -574,9 +576,15 @@ public void run() { case "is-powersave-mode": isPowerSaveMode(callbackContext); break; - case "get-app-info": - getAppInfo(callbackContext); - break; + case "get-app-info": + getAppInfo(callbackContext); + break; + case "get-app-icons": + getAppIcons(callbackContext); + break; + case "set-app-icon": + setAppIcon(arg1, callbackContext); + break; case "pin-file-shortcut": pinFileShortcut(args.optJSONObject(0), callbackContext); break; @@ -2184,4 +2192,120 @@ private void extractAsset(String assetName, String destinationPath, CallbackCont callback.error(sw.toString()); } } + + private void getAppIcons(CallbackContext callbackContext) { + try { + PackageManager pm = context.getPackageManager(); + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + intent.setPackage(context.getPackageName()); + + int flags = PackageManager.GET_META_DATA; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + flags |= PackageManager.MATCH_DISABLED_COMPONENTS; + } else { + flags |= PackageManager.GET_DISABLED_COMPONENTS; + } + + List resolveInfos = pm.queryIntentActivities(intent, flags); + JSONArray result = new JSONArray(); + + for (ResolveInfo info : resolveInfos) { + JSONObject iconInfo = new JSONObject(); + String name = info.activityInfo.name; + String label = info.loadLabel(pm).toString(); + + int iconRes = info.activityInfo.getIconResource(); + String iconName = ""; + if (iconRes != 0) { + try { + iconName = context.getResources().getResourceEntryName(iconRes); + } catch (Exception e) { + // ignore + } + } + + // Check if currently enabled + ComponentName componentName = new ComponentName(context, name); + int enabledSetting = pm.getComponentEnabledSetting(componentName); + boolean isEnabled; + if (enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { + isEnabled = info.activityInfo.enabled; + } else { + isEnabled = (enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_ENABLED); + } + + iconInfo.put("name", name); + iconInfo.put("label", label); + iconInfo.put("icon", iconName); + iconInfo.put("enabled", isEnabled); + result.put(iconInfo); + } + + callbackContext.success(result); + } catch (Exception e) { + callbackContext.error(e.getMessage()); + } + } + + private void setAppIcon(String targetComponentName, CallbackContext callbackContext) { + try { + PackageManager pm = context.getPackageManager(); + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + intent.setPackage(context.getPackageName()); + + int flags = PackageManager.GET_META_DATA; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + flags |= PackageManager.MATCH_DISABLED_COMPONENTS; + } else { + flags |= PackageManager.GET_DISABLED_COMPONENTS; + } + + List resolveInfos = pm.queryIntentActivities(intent, flags); + + String target = targetComponentName; + if (target.startsWith(".")) { + target = context.getPackageName() + target; + } + + boolean found = false; + + // First pass: verify if targetComponentName is a valid launcher component + for (ResolveInfo info : resolveInfos) { + if (info.activityInfo.name.equals(target)) { + found = true; + break; + } + } + + if (!found) { + callbackContext.error("Component " + target + " not found as a launcher activity or alias in the manifest"); + return; + } + + // Second pass: enable targetComponentName and disable others + for (ResolveInfo info : resolveInfos) { + String name = info.activityInfo.name; + ComponentName componentName = new ComponentName(context, name); + if (name.equals(target)) { + pm.setComponentEnabledSetting( + componentName, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP + ); + } else { + pm.setComponentEnabledSetting( + componentName, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP + ); + } + } + + callbackContext.success(); + } catch (Exception e) { + callbackContext.error(e.getMessage()); + } + } } diff --git a/src/plugins/system/system.d.ts b/src/plugins/system/system.d.ts index aa2ef8bf7..d1ffc2337 100644 --- a/src/plugins/system/system.d.ts +++ b/src/plugins/system/system.d.ts @@ -295,6 +295,26 @@ interface System { onSuccess?: () => void, onFail?: OnFail, ): void; + /** + * Fetch all available launcher app icons (activities/activity-aliases). + * @param onSuccess + * @param onFail + */ + getAppIcons(onSuccess: (icons: AppIcon[]) => void, onFail: OnFail): void; + /** + * Set the active app icon by component/alias name. + * @param componentName + * @param onSuccess + * @param onFail + */ + setAppIcon(componentName: string, onSuccess: OnSuccessBool, onFail: OnFail): void; +} + +interface AppIcon { + name: string; + label: string; + icon: string; + enabled: boolean; } interface Window{ diff --git a/src/plugins/system/utils/changeProvider.js b/src/plugins/system/utils/changeProvider.js index 45095aa8d..1463b43d6 100644 --- a/src/plugins/system/utils/changeProvider.js +++ b/src/plugins/system/utils/changeProvider.js @@ -15,7 +15,7 @@ module.exports = { try { const fileData = fs.readFileSync(configXML, "utf8"); const manifest = fs.readFileSync(androidManifest, "utf8"); - const ID = reset ? "com.foxdebug" : /widget id="([0-9a-zA-Z\.\-_]*)"/.exec(fileData)[1]; + const ID = reset ? "com.foxdebug" : /widget\s+id="([0-9a-zA-Z\.\-_]*)"/.exec(fileData)[1]; const newFileData = manifest.replace( /(android:authorities=")([0-9a-zA-Z\.\-_]*)(")/, `$1${reset ? "com.foxdebug" : ID}.provider$3` diff --git a/src/plugins/system/www/plugin.js b/src/plugins/system/www/plugin.js index 8bebd47ef..1450ce387 100644 --- a/src/plugins/system/www/plugin.js +++ b/src/plugins/system/www/plugin.js @@ -272,5 +272,11 @@ module.exports = { [text1, text2] ); }); + }, + getAppIcons: function (success, error) { + cordova.exec(success, error, 'System', 'get-app-icons', []); + }, + setAppIcon: function (componentName, success, error) { + cordova.exec(success, error, 'System', 'set-app-icon', [componentName]); } -}; +};