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]);
}
-};
+};