Skip to content

Commit 0a94305

Browse files
feat: multi icon support
1 parent 7ebb3bb commit 0a94305

7 files changed

Lines changed: 298 additions & 98 deletions

File tree

config.xml

Lines changed: 142 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,142 @@
1-
<?xml version='1.0' encoding='utf-8'?>
2-
<widget id="com.foxdebug.acode" android-versionCode="1001" version="1.12.6"
3-
xmlns="http://www.w3.org/ns/widgets"
4-
xmlns:android="http://schemas.android.com/apk/res/android"
5-
xmlns:cdv="http://cordova.apache.org/ns/1.0">
6-
<name>Acode</name>
7-
<description>
8-
Light weight code editor and web IDE for android.
9-
</description>
10-
<author email="ajit@foxdebug.com" href="https://foxdebug.com">
11-
Foxdebug
12-
</author>
13-
<content src="index.html" />
14-
<access launch-external="yes" origin="*" />
15-
<allow-navigation href="https://*/*" />
16-
<allow-navigation href="http://*/*" />
17-
<allow-intent href="http://*/*" />
18-
<allow-intent href="https://*/*" />
19-
<allow-intent href="tel:*" />
20-
<allow-intent href="sms:*" />
21-
<allow-intent href="mailto:*" />
22-
<allow-intent href="geo:*" />
23-
24-
<platform name="android">
25-
<allow-intent href="market:*" />
26-
<preference name="fullscreen" value="false" />
27-
<preference name="SplashScreen" value="none" />
28-
<preference name="ShowTitle" value="true" />
29-
<preference name="DisallowOverscroll" value="true" />
30-
<preference name="BackgroundColor" value="0xFF313131" />
31-
<preference name="AndroidWindowSplashScreenBackground" value="@color/ic_splash_background" />
32-
<preference name="AndroidWindowSplashScreenAnimatedIcon"
33-
value="res/android/drawable/ic_launcher_foreground.xml" />
34-
<preference name="AndroidPostSplashScreenTheme" value="@style/Theme.App.Activity" />
35-
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
36-
<preference name="AndroidLaunchMode" value="singleTask" />
37-
<preference name="prerendered-icon" value="false" />
38-
<preference name="androidxEnabled" value="true" />
39-
<preference name="GradlePluginKotlinEnabled" value="true" />
40-
<preference name="android-targetSdkVersion" value="36" />
41-
<preference name="android-minSdkVersion" value="26" />
42-
43-
44-
<edit-config file="app/src/main/AndroidManifest.xml" mode="merge"
45-
target="/manifest/application">
46-
<application
47-
android:networkSecurityConfig="@xml/network_security_config"
48-
android:hardwareAccelerated="true"
49-
android:largeHeap="true"
50-
android:requestLegacyExternalStorage="true"
51-
android:usesCleartextTraffic="true"
52-
android:enableOnBackInvokedCallback="false" />
53-
</edit-config>
54-
55-
<edit-config file="app/src/main/AndroidManifest.xml" mode="merge"
56-
target="/manifest/application/activity[@android:name='MainActivity']">
57-
<activity android:resizeableActivity="true" />
58-
</edit-config>
59-
60-
<config-file parent="./application/activity" target="AndroidManifest.xml">
61-
<intent-filter>
62-
<action android:name="android.intent.action.VIEW" />
63-
<action android:name="android.intent.action.EDIT" />
64-
<category android:name="android.intent.category.DEFAULT" />
65-
<category android:name="android.intent.category.LAUNCHER" />
66-
<data android:scheme="file" android:mimeType="*/*" />
67-
<data android:scheme="content" android:mimeType="*/*" />
68-
</intent-filter>
69-
<!-- Allow app to open using url from browser -->
70-
<intent-filter android:autoVerify="true">
71-
<action android:name="android.intent.action.VIEW" />
72-
<category android:name="android.intent.category.DEFAULT" />
73-
<category android:name="android.intent.category.BROWSABLE" />
74-
<data android:scheme="acode" />
75-
</intent-filter>
76-
</config-file>
77-
78-
<config-file target="AndroidManifest.xml" parent="/manifest">
79-
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
80-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
81-
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
82-
<uses-permission android:name="android.permission.VIBRATE" />
83-
</config-file>
84-
85-
<hook type="before_prepare" src="hooks/restore-cordova-resources.js" />
86-
<hook type="before_prepare" src="hooks/modify-java-files.js" />
87-
<hook type="after_prepare" src="hooks/post-process.js" />
88-
</platform>
89-
<preference name="AndroidBlacklistSecureSocketProtocols" value="SSLv3,TLSv1" />
90-
</widget>
1+
<?xml version='1.0' encoding='utf-8' ?>
2+
<widget
3+
id="com.foxdebug.acode"
4+
android-versionCode="1001"
5+
version="1.12.6"
6+
xmlns="http://www.w3.org/ns/widgets"
7+
xmlns:android="http://schemas.android.com/apk/res/android"
8+
xmlns:cdv="http://cordova.apache.org/ns/1.0"
9+
>
10+
<name>Acode</name>
11+
<description>
12+
Light weight code editor and web IDE for android.
13+
</description>
14+
<author email="ajit@foxdebug.com" href="https://foxdebug.com">
15+
Foxdebug
16+
</author>
17+
<content src="index.html" />
18+
<access launch-external="yes" origin="*" />
19+
<allow-navigation href="https://*/*" />
20+
<allow-navigation href="http://*/*" />
21+
<allow-intent href="http://*/*" />
22+
<allow-intent href="https://*/*" />
23+
<allow-intent href="tel:*" />
24+
<allow-intent href="sms:*" />
25+
<allow-intent href="mailto:*" />
26+
<allow-intent href="geo:*" />
27+
28+
<platform name="android">
29+
<allow-intent href="market:*" />
30+
<preference name="fullscreen" value="false" />
31+
<preference name="SplashScreen" value="none" />
32+
<preference name="ShowTitle" value="true" />
33+
<preference name="DisallowOverscroll" value="true" />
34+
<preference name="BackgroundColor" value="0xFF313131" />
35+
<preference
36+
name="AndroidWindowSplashScreenBackground"
37+
value="@color/ic_splash_background"
38+
/>
39+
<preference
40+
name="AndroidWindowSplashScreenAnimatedIcon"
41+
value="res/android/drawable/ic_launcher_foreground.xml"
42+
/>
43+
<preference
44+
name="AndroidPostSplashScreenTheme"
45+
value="@style/Theme.App.Activity"
46+
/>
47+
<preference
48+
name="AndroidPersistentFileLocation"
49+
value="Compatibility"
50+
/>
51+
<preference name="AndroidLaunchMode" value="singleTask" />
52+
<preference name="prerendered-icon" value="false" />
53+
<preference name="androidxEnabled" value="true" />
54+
<preference name="GradlePluginKotlinEnabled" value="true" />
55+
<preference name="android-targetSdkVersion" value="36" />
56+
<preference name="android-minSdkVersion" value="26" />
57+
58+
59+
<edit-config
60+
file="app/src/main/AndroidManifest.xml"
61+
mode="merge"
62+
target="/manifest/application"
63+
>
64+
<application
65+
android:networkSecurityConfig="@xml/network_security_config"
66+
android:hardwareAccelerated="true"
67+
android:largeHeap="true"
68+
android:requestLegacyExternalStorage="true"
69+
android:usesCleartextTraffic="true"
70+
android:enableOnBackInvokedCallback="false"
71+
/>
72+
</edit-config>
73+
74+
<edit-config
75+
file="app/src/main/AndroidManifest.xml"
76+
mode="merge"
77+
target="/manifest/application/activity[@android:name='MainActivity']"
78+
>
79+
<activity android:resizeableActivity="true" />
80+
</edit-config>
81+
82+
<config-file
83+
parent="./application/activity"
84+
target="AndroidManifest.xml"
85+
>
86+
<intent-filter>
87+
<action android:name="android.intent.action.VIEW" />
88+
<action android:name="android.intent.action.EDIT" />
89+
<category android:name="android.intent.category.DEFAULT" />
90+
<category android:name="android.intent.category.LAUNCHER" />
91+
<data android:scheme="file" android:mimeType="*/*" />
92+
<data android:scheme="content" android:mimeType="*/*" />
93+
</intent-filter>
94+
<!-- Allow app to open using url from browser -->
95+
<intent-filter android:autoVerify="true">
96+
<action android:name="android.intent.action.VIEW" />
97+
<category android:name="android.intent.category.DEFAULT" />
98+
<category android:name="android.intent.category.BROWSABLE" />
99+
<data android:scheme="acode" />
100+
</intent-filter>
101+
</config-file>
102+
103+
<config-file target="AndroidManifest.xml" parent="/manifest">
104+
<uses-permission
105+
android:name="android.permission.READ_EXTERNAL_STORAGE"
106+
/>
107+
<uses-permission
108+
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
109+
/>
110+
<uses-permission
111+
android:name="android.permission.WRITE_MEDIA_STORAGE"
112+
/>
113+
<uses-permission android:name="android.permission.VIBRATE" />
114+
</config-file>
115+
116+
<config-file
117+
target="AndroidManifest.xml"
118+
parent="/manifest/application"
119+
>
120+
<activity-alias
121+
android:name=".MainActivityAlt1"
122+
android:enabled="false"
123+
android:exported="true"
124+
android:icon="@drawable/ic_alt"
125+
android:targetActivity=".MainActivity"
126+
>
127+
<intent-filter>
128+
<action android:name="android.intent.action.MAIN" />
129+
<category android:name="android.intent.category.LAUNCHER" />
130+
</intent-filter>
131+
</activity-alias>
132+
</config-file>
133+
134+
<hook type="before_prepare" src="hooks/restore-cordova-resources.js" />
135+
<hook type="before_prepare" src="hooks/modify-java-files.js" />
136+
<hook type="after_prepare" src="hooks/post-process.js" />
137+
</platform>
138+
<preference
139+
name="AndroidBlacklistSecureSocketProtocols"
140+
value="SSLv3,TLSv1"
141+
/>
142+
</widget>

package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@
4242
"cordova-plugin-iap": {},
4343
"com.foxdebug.acode.rk.customtabs": {},
4444
"cordova-plugin-system": {},
45-
"cordova-plugin-advanced-http": {
46-
"ANDROIDBLACKLISTSECURESOCKETPROTOCOLS": "SSLv3,TLSv1"
47-
}
45+
"cordova-plugin-advanced-http": {}
4846
},
4947
"platforms": [
5048
"android"

res/android/drawable/ic_alt.png

28.8 KB
Loading

src/plugins/system/android/com/foxdebug/system/System.java

Lines changed: 127 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ public boolean execute(
215215
case "compare-texts":
216216
case "extractAsset":
217217
case "pin-file-shortcut":
218+
case "get-app-icons":
219+
case "set-app-icon":
218220
break;
219221
case "get-configuration":
220222
getConfiguration(callbackContext);
@@ -574,9 +576,15 @@ public void run() {
574576
case "is-powersave-mode":
575577
isPowerSaveMode(callbackContext);
576578
break;
577-
case "get-app-info":
578-
getAppInfo(callbackContext);
579-
break;
579+
case "get-app-info":
580+
getAppInfo(callbackContext);
581+
break;
582+
case "get-app-icons":
583+
getAppIcons(callbackContext);
584+
break;
585+
case "set-app-icon":
586+
setAppIcon(arg1, callbackContext);
587+
break;
580588
case "pin-file-shortcut":
581589
pinFileShortcut(args.optJSONObject(0), callbackContext);
582590
break;
@@ -2184,4 +2192,120 @@ private void extractAsset(String assetName, String destinationPath, CallbackCont
21842192
callback.error(sw.toString());
21852193
}
21862194
}
2195+
2196+
private void getAppIcons(CallbackContext callbackContext) {
2197+
try {
2198+
PackageManager pm = context.getPackageManager();
2199+
Intent intent = new Intent(Intent.ACTION_MAIN);
2200+
intent.addCategory(Intent.CATEGORY_LAUNCHER);
2201+
intent.setPackage(context.getPackageName());
2202+
2203+
int flags = PackageManager.GET_META_DATA;
2204+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
2205+
flags |= PackageManager.MATCH_DISABLED_COMPONENTS;
2206+
} else {
2207+
flags |= PackageManager.GET_DISABLED_COMPONENTS;
2208+
}
2209+
2210+
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, flags);
2211+
JSONArray result = new JSONArray();
2212+
2213+
for (ResolveInfo info : resolveInfos) {
2214+
JSONObject iconInfo = new JSONObject();
2215+
String name = info.activityInfo.name;
2216+
String label = info.loadLabel(pm).toString();
2217+
2218+
int iconRes = info.activityInfo.getIconResource();
2219+
String iconName = "";
2220+
if (iconRes != 0) {
2221+
try {
2222+
iconName = context.getResources().getResourceEntryName(iconRes);
2223+
} catch (Exception e) {
2224+
// ignore
2225+
}
2226+
}
2227+
2228+
// Check if currently enabled
2229+
ComponentName componentName = new ComponentName(context, name);
2230+
int enabledSetting = pm.getComponentEnabledSetting(componentName);
2231+
boolean isEnabled;
2232+
if (enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
2233+
isEnabled = info.activityInfo.enabled;
2234+
} else {
2235+
isEnabled = (enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
2236+
}
2237+
2238+
iconInfo.put("name", name);
2239+
iconInfo.put("label", label);
2240+
iconInfo.put("icon", iconName);
2241+
iconInfo.put("enabled", isEnabled);
2242+
result.put(iconInfo);
2243+
}
2244+
2245+
callbackContext.success(result);
2246+
} catch (Exception e) {
2247+
callbackContext.error(e.getMessage());
2248+
}
2249+
}
2250+
2251+
private void setAppIcon(String targetComponentName, CallbackContext callbackContext) {
2252+
try {
2253+
PackageManager pm = context.getPackageManager();
2254+
Intent intent = new Intent(Intent.ACTION_MAIN);
2255+
intent.addCategory(Intent.CATEGORY_LAUNCHER);
2256+
intent.setPackage(context.getPackageName());
2257+
2258+
int flags = PackageManager.GET_META_DATA;
2259+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
2260+
flags |= PackageManager.MATCH_DISABLED_COMPONENTS;
2261+
} else {
2262+
flags |= PackageManager.GET_DISABLED_COMPONENTS;
2263+
}
2264+
2265+
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, flags);
2266+
2267+
String target = targetComponentName;
2268+
if (target.startsWith(".")) {
2269+
target = context.getPackageName() + target;
2270+
}
2271+
2272+
boolean found = false;
2273+
2274+
// First pass: verify if targetComponentName is a valid launcher component
2275+
for (ResolveInfo info : resolveInfos) {
2276+
if (info.activityInfo.name.equals(target)) {
2277+
found = true;
2278+
break;
2279+
}
2280+
}
2281+
2282+
if (!found) {
2283+
callbackContext.error("Component " + target + " not found as a launcher activity or alias in the manifest");
2284+
return;
2285+
}
2286+
2287+
// Second pass: enable targetComponentName and disable others
2288+
for (ResolveInfo info : resolveInfos) {
2289+
String name = info.activityInfo.name;
2290+
ComponentName componentName = new ComponentName(context, name);
2291+
if (name.equals(target)) {
2292+
pm.setComponentEnabledSetting(
2293+
componentName,
2294+
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
2295+
PackageManager.DONT_KILL_APP
2296+
);
2297+
} else {
2298+
pm.setComponentEnabledSetting(
2299+
componentName,
2300+
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
2301+
PackageManager.DONT_KILL_APP
2302+
);
2303+
}
2304+
}
2305+
2306+
callbackContext.success();
2307+
} catch (Exception e) {
2308+
callbackContext.error(e.getMessage());
2309+
}
2310+
}
21872311
}

0 commit comments

Comments
 (0)