-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat: multi icon support #2396
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: multi icon support #2396
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,90 +1,142 @@ | ||
| <?xml version='1.0' encoding='utf-8'?> | ||
| <widget id="com.foxdebug.acode" android-versionCode="1001" version="1.12.6" | ||
| xmlns="http://www.w3.org/ns/widgets" | ||
| xmlns:android="http://schemas.android.com/apk/res/android" | ||
| xmlns:cdv="http://cordova.apache.org/ns/1.0"> | ||
| <name>Acode</name> | ||
| <description> | ||
| Light weight code editor and web IDE for android. | ||
| </description> | ||
| <author email="ajit@foxdebug.com" href="https://foxdebug.com"> | ||
| Foxdebug | ||
| </author> | ||
| <content src="index.html" /> | ||
| <access launch-external="yes" origin="*" /> | ||
| <allow-navigation href="https://*/*" /> | ||
| <allow-navigation href="http://*/*" /> | ||
| <allow-intent href="http://*/*" /> | ||
| <allow-intent href="https://*/*" /> | ||
| <allow-intent href="tel:*" /> | ||
| <allow-intent href="sms:*" /> | ||
| <allow-intent href="mailto:*" /> | ||
| <allow-intent href="geo:*" /> | ||
|
|
||
| <platform name="android"> | ||
| <allow-intent href="market:*" /> | ||
| <preference name="fullscreen" value="false" /> | ||
| <preference name="SplashScreen" value="none" /> | ||
| <preference name="ShowTitle" value="true" /> | ||
| <preference name="DisallowOverscroll" value="true" /> | ||
| <preference name="BackgroundColor" value="0xFF313131" /> | ||
| <preference name="AndroidWindowSplashScreenBackground" value="@color/ic_splash_background" /> | ||
| <preference name="AndroidWindowSplashScreenAnimatedIcon" | ||
| value="res/android/drawable/ic_launcher_foreground.xml" /> | ||
| <preference name="AndroidPostSplashScreenTheme" value="@style/Theme.App.Activity" /> | ||
| <preference name="AndroidPersistentFileLocation" value="Compatibility" /> | ||
| <preference name="AndroidLaunchMode" value="singleTask" /> | ||
| <preference name="prerendered-icon" value="false" /> | ||
| <preference name="androidxEnabled" value="true" /> | ||
| <preference name="GradlePluginKotlinEnabled" value="true" /> | ||
| <preference name="android-targetSdkVersion" value="36" /> | ||
| <preference name="android-minSdkVersion" value="26" /> | ||
|
|
||
|
|
||
| <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" | ||
| target="/manifest/application"> | ||
| <application | ||
| android:networkSecurityConfig="@xml/network_security_config" | ||
| android:hardwareAccelerated="true" | ||
| android:largeHeap="true" | ||
| android:requestLegacyExternalStorage="true" | ||
| android:usesCleartextTraffic="true" | ||
| android:enableOnBackInvokedCallback="false" /> | ||
| </edit-config> | ||
|
|
||
| <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" | ||
| target="/manifest/application/activity[@android:name='MainActivity']"> | ||
| <activity android:resizeableActivity="true" /> | ||
| </edit-config> | ||
|
|
||
| <config-file parent="./application/activity" target="AndroidManifest.xml"> | ||
| <intent-filter> | ||
| <action android:name="android.intent.action.VIEW" /> | ||
| <action android:name="android.intent.action.EDIT" /> | ||
| <category android:name="android.intent.category.DEFAULT" /> | ||
| <category android:name="android.intent.category.LAUNCHER" /> | ||
| <data android:scheme="file" android:mimeType="*/*" /> | ||
| <data android:scheme="content" android:mimeType="*/*" /> | ||
| </intent-filter> | ||
| <!-- Allow app to open using url from browser --> | ||
| <intent-filter android:autoVerify="true"> | ||
| <action android:name="android.intent.action.VIEW" /> | ||
| <category android:name="android.intent.category.DEFAULT" /> | ||
| <category android:name="android.intent.category.BROWSABLE" /> | ||
| <data android:scheme="acode" /> | ||
| </intent-filter> | ||
| </config-file> | ||
|
|
||
| <config-file target="AndroidManifest.xml" parent="/manifest"> | ||
| <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | ||
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | ||
| <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" /> | ||
| <uses-permission android:name="android.permission.VIBRATE" /> | ||
| </config-file> | ||
|
|
||
| <hook type="before_prepare" src="hooks/restore-cordova-resources.js" /> | ||
| <hook type="before_prepare" src="hooks/modify-java-files.js" /> | ||
| <hook type="after_prepare" src="hooks/post-process.js" /> | ||
| </platform> | ||
| <preference name="AndroidBlacklistSecureSocketProtocols" value="SSLv3,TLSv1" /> | ||
| </widget> | ||
| <?xml version='1.0' encoding='utf-8' ?> | ||
| <widget | ||
| id="com.foxdebug.acode" | ||
| android-versionCode="1001" | ||
| version="1.12.6" | ||
| xmlns="http://www.w3.org/ns/widgets" | ||
| xmlns:android="http://schemas.android.com/apk/res/android" | ||
| xmlns:cdv="http://cordova.apache.org/ns/1.0" | ||
| > | ||
| <name>Acode</name> | ||
| <description> | ||
| Light weight code editor and web IDE for android. | ||
| </description> | ||
| <author email="ajit@foxdebug.com" href="https://foxdebug.com"> | ||
| Foxdebug | ||
| </author> | ||
| <content src="index.html" /> | ||
| <access launch-external="yes" origin="*" /> | ||
| <allow-navigation href="https://*/*" /> | ||
| <allow-navigation href="http://*/*" /> | ||
| <allow-intent href="http://*/*" /> | ||
| <allow-intent href="https://*/*" /> | ||
| <allow-intent href="tel:*" /> | ||
| <allow-intent href="sms:*" /> | ||
| <allow-intent href="mailto:*" /> | ||
| <allow-intent href="geo:*" /> | ||
|
|
||
| <platform name="android"> | ||
| <allow-intent href="market:*" /> | ||
| <preference name="fullscreen" value="false" /> | ||
| <preference name="SplashScreen" value="none" /> | ||
| <preference name="ShowTitle" value="true" /> | ||
| <preference name="DisallowOverscroll" value="true" /> | ||
| <preference name="BackgroundColor" value="0xFF313131" /> | ||
| <preference | ||
| name="AndroidWindowSplashScreenBackground" | ||
| value="@color/ic_splash_background" | ||
| /> | ||
| <preference | ||
| name="AndroidWindowSplashScreenAnimatedIcon" | ||
| value="res/android/drawable/ic_launcher_foreground.xml" | ||
| /> | ||
| <preference | ||
| name="AndroidPostSplashScreenTheme" | ||
| value="@style/Theme.App.Activity" | ||
| /> | ||
| <preference | ||
| name="AndroidPersistentFileLocation" | ||
| value="Compatibility" | ||
| /> | ||
| <preference name="AndroidLaunchMode" value="singleTask" /> | ||
| <preference name="prerendered-icon" value="false" /> | ||
| <preference name="androidxEnabled" value="true" /> | ||
| <preference name="GradlePluginKotlinEnabled" value="true" /> | ||
| <preference name="android-targetSdkVersion" value="36" /> | ||
| <preference name="android-minSdkVersion" value="26" /> | ||
|
|
||
|
|
||
| <edit-config | ||
| file="app/src/main/AndroidManifest.xml" | ||
| mode="merge" | ||
| target="/manifest/application" | ||
| > | ||
| <application | ||
| android:networkSecurityConfig="@xml/network_security_config" | ||
| android:hardwareAccelerated="true" | ||
| android:largeHeap="true" | ||
| android:requestLegacyExternalStorage="true" | ||
| android:usesCleartextTraffic="true" | ||
| android:enableOnBackInvokedCallback="false" | ||
| /> | ||
| </edit-config> | ||
|
|
||
| <edit-config | ||
| file="app/src/main/AndroidManifest.xml" | ||
| mode="merge" | ||
| target="/manifest/application/activity[@android:name='MainActivity']" | ||
| > | ||
| <activity android:resizeableActivity="true" /> | ||
| </edit-config> | ||
|
|
||
| <config-file | ||
| parent="./application/activity" | ||
| target="AndroidManifest.xml" | ||
| > | ||
| <intent-filter> | ||
| <action android:name="android.intent.action.VIEW" /> | ||
| <action android:name="android.intent.action.EDIT" /> | ||
| <category android:name="android.intent.category.DEFAULT" /> | ||
| <category android:name="android.intent.category.LAUNCHER" /> | ||
| <data android:scheme="file" android:mimeType="*/*" /> | ||
| <data android:scheme="content" android:mimeType="*/*" /> | ||
| </intent-filter> | ||
| <!-- Allow app to open using url from browser --> | ||
| <intent-filter android:autoVerify="true"> | ||
| <action android:name="android.intent.action.VIEW" /> | ||
| <category android:name="android.intent.category.DEFAULT" /> | ||
| <category android:name="android.intent.category.BROWSABLE" /> | ||
| <data android:scheme="acode" /> | ||
| </intent-filter> | ||
| </config-file> | ||
|
|
||
| <config-file target="AndroidManifest.xml" parent="/manifest"> | ||
| <uses-permission | ||
| android:name="android.permission.READ_EXTERNAL_STORAGE" | ||
| /> | ||
| <uses-permission | ||
| android:name="android.permission.WRITE_EXTERNAL_STORAGE" | ||
| /> | ||
| <uses-permission | ||
| android:name="android.permission.WRITE_MEDIA_STORAGE" | ||
| /> | ||
| <uses-permission android:name="android.permission.VIBRATE" /> | ||
| </config-file> | ||
|
|
||
| <config-file | ||
| target="AndroidManifest.xml" | ||
| parent="/manifest/application" | ||
| > | ||
| <activity-alias | ||
| android:name=".MainActivityAlt1" | ||
| android:enabled="false" | ||
| android:exported="true" | ||
| android:icon="@drawable/ic_alt" | ||
| android:targetActivity=".MainActivity" | ||
| > | ||
| <intent-filter> | ||
| <action android:name="android.intent.action.MAIN" /> | ||
| <category android:name="android.intent.category.LAUNCHER" /> | ||
| </intent-filter> | ||
| </activity-alias> | ||
| </config-file> | ||
|
|
||
| <hook type="before_prepare" src="hooks/restore-cordova-resources.js" /> | ||
| <hook type="before_prepare" src="hooks/modify-java-files.js" /> | ||
| <hook type="after_prepare" src="hooks/post-process.js" /> | ||
| </platform> | ||
| <preference | ||
| name="AndroidBlacklistSecureSocketProtocols" | ||
| value="SSLv3,TLSv1" | ||
| /> | ||
| </widget> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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<ResolveInfo> 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<ResolveInfo> 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; | ||
|
Comment on lines
+2261
to
+2278
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The second pass iterates every entry returned by The standard pattern for icon switching is: (1) remove the |
||
| } | ||
| } | ||
|
|
||
| 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()); | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
caseblocks have an extra leading space compared to the surroundingcase "pin-file-shortcut"and others (29 spaces vs 28). This creates an inconsistent indentation in an otherwise uniform switch block.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!