Skip to content

Commit b9465eb

Browse files
Merge branch 'doc'
2 parents a56a624 + b9004ab commit b9465eb

File tree

2 files changed

+333
-275
lines changed

2 files changed

+333
-275
lines changed

README.md

Lines changed: 288 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,305 @@
1-
# @computools/react-native-dynamic-app-icon
1+
# @computools/react-native-dynamic-app-icon 🚀
22

33
Dynamically change the app icon in React Native with cross-platform support for iOS and Android. Perfect for themes, events, and personalization.
44

5+
<table>
6+
<tr>
7+
<th style="text-align: center;">iOS</th>
8+
<th style="text-align: center;">Android</th>
9+
</tr>
10+
<tr>
11+
<td>
12+
<img src="https://ik.imagekit.io/Computools/RN%20Dynamic%20App%20Icons%20/ios_dynamic_app_icon_preview.gif?updatedAt=1737115408393" width="300">
13+
</td>
14+
<td">
15+
<img src="https://ik.imagekit.io/Computools/RN%20Dynamic%20App%20Icons%20/android_dynamic_app_icon_preview.gif?updatedAt=1737115956222" width="300">
16+
</td>
17+
</tr>
18+
</table>
19+
520
## Installation
621

7-
```sh
8-
npm install @computools/react-native-dynamic-app-icon
22+
**Using Yarn**
23+
24+
```bash
25+
yarn add @computools/react-native-dynamic-app-icon
926
```
1027

28+
**Using npm**
29+
30+
```bash
31+
npm i @computools/react-native-dynamic-app-icon
32+
```
33+
### iOS Set Up
34+
35+
After installing the package, run:
36+
37+
```bash
38+
cd ios
39+
pod install
40+
```
41+
42+
## Generate App Icons
43+
44+
Generate app icons using a tool like [appicon.co](https://www.appicon.co/) to ensure all required sizes and formats are included.
45+
46+
<img src="https://ik.imagekit.io/Computools/RN%20Dynamic%20App%20Icons%20/app_icon_generator.png?updatedAt=1737458948009" width="400"/>
47+
48+
## App Icons Set Up
49+
50+
### Android
51+
52+
#### Step 1: Add App Icons Files
53+
54+
1. Rename generated files to *ic_launcher_<icon_type>.png* e.g. `ic_launcher_orange.png`.
55+
2. Rename default icon files to to `ic_launcher_default.png`
56+
3. Move app icons files to `android/app/src/main/res/mipmap-*`.
57+
58+
<img src="https://ik.imagekit.io/Computools/RN%20Dynamic%20App%20Icons%20/icons_files_android.png?updatedAt=1737456324691" width="400">
59+
60+
#### Step 2: Modify `AndroidManifest.xml`
61+
62+
1. Add activity-alias for each icon.
63+
64+
```kotlin
65+
<activity-alias
66+
android:name=".MainActivityPineapple" // .MainActivity + <icon-type>
67+
android:enabled="false"
68+
android:exported="true"
69+
android:icon="@mipmap/ic_launcher_pineapple"
70+
android:targetActivity=".MainActivity">
71+
<intent-filter>
72+
<action android:name="android.intent.action.MAIN" />
73+
<category android:name="android.intent.category.LAUNCHER" />
74+
</intent-filter>
75+
</activity-alias>
76+
```
77+
78+
**Important**: `android:enabled="true"` should be only for **default** activity-alias, other should have `android:enabled="false"`.
79+
80+
2. Remove `<category android:name="android.intent.category.LAUNCHER" />` for activity-alias with `android:enabled="true"`.
81+
82+
**Notes:**
83+
1. Don’t forget to use the correct file for `android:icon` and `android:name`. `android:name` is **.MainActivity + <icon-type>** e.g for `android:icon=ic_launcher_orange` `android:name=".MainActivityOrange"`.
84+
2. Don't forget to change `android:icon` to `"@mipmap/ic_launcher_default"` in `<application>` tag.
85+
3. Make sure you have activity-alias with `android:icon=ic_launcher_default`, `android:name=".MainActivityDefault"`.
86+
87+
**`AndroidManifest.xml` example:**
88+
89+
```kotlin
90+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
91+
92+
<uses-permission android:name="android.permission.INTERNET" />
93+
94+
<application
95+
android:name=".MainApplication"
96+
android:label="@string/app_name"
97+
android:icon="@mipmap/ic_launcher_default"
98+
android:allowBackup="false"
99+
android:theme="@style/AppTheme"
100+
android:supportsRtl="true">
101+
<activity
102+
android:name=".MainActivity"
103+
android:label="@string/app_name"
104+
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
105+
android:launchMode="singleTask"
106+
android:windowSoftInputMode="adjustResize"
107+
android:exported="true">
108+
<intent-filter>
109+
<action android:name="android.intent.action.MAIN" />
110+
<category android:name="android.intent.category.LAUNCHER" />
111+
</intent-filter>
112+
</activity>
113+
<activity-alias
114+
android:name=".MainActivityDefault"
115+
android:enabled="true"
116+
android:exported="true"
117+
android:icon="@mipmap/ic_launcher_default"
118+
android:targetActivity=".MainActivity">
119+
<intent-filter>
120+
<action android:name="android.intent.action.MAIN" />
121+
</intent-filter>
122+
</activity-alias>
123+
<activity-alias
124+
android:name=".MainActivityPineapple"
125+
android:enabled="false"
126+
android:exported="true"
127+
android:icon="@mipmap/ic_launcher_pineapple"
128+
android:targetActivity=".MainActivity">
129+
<intent-filter>
130+
<action android:name="android.intent.action.MAIN" />
131+
<category android:name="android.intent.category.LAUNCHER" />
132+
</intent-filter>
133+
</activity-alias>
134+
<activity-alias
135+
android:name=".MainActivityStrawberry"
136+
android:enabled="false"
137+
android:exported="true"
138+
android:icon="@mipmap/ic_launcher_strawberry"
139+
android:targetActivity=".MainActivity">
140+
<intent-filter>
141+
<action android:name="android.intent.action.MAIN" />
142+
<category android:name="android.intent.category.LAUNCHER" />
143+
</intent-filter>
144+
</activity-alias>
145+
<activity-alias
146+
android:name=".MainActivityOrange"
147+
android:enabled="false"
148+
android:exported="true"
149+
android:icon="@mipmap/ic_launcher_orange"
150+
android:targetActivity=".MainActivity">
151+
<intent-filter>
152+
<action android:name="android.intent.action.MAIN" />
153+
<category android:name="android.intent.category.LAUNCHER" />
154+
</intent-filter>
155+
</activity-alias>
156+
</application>
157+
</manifest>
158+
```
159+
160+
### iOS
161+
162+
#### Step 1: Add App Icons Files
163+
164+
1. Rename generated `AppIcon.appiconset` folders to `<icon-type>Icon.appiconset`.
165+
2. Rename default `AppIcon.appiconset` to `DefaultIcon.appiconset`.
166+
3. Move all .appiconset folders into `ios/<app-name>/Images.xcassets`.
167+
4. Update `folder` values in each `Contents.json` file e.g `"folder": "Images.xcassets/PineappleIcon.appiconset/"`.
168+
169+
<img src="https://ik.imagekit.io/Computools/RN%20Dynamic%20App%20Icons%20/icons_files_ios.png?updatedAt=1737456324725" width="400">
170+
171+
#### Step 2: Set up App Icon in Xcode
172+
173+
1. Open Xcode;
174+
2. Go to app's `General` settings;
175+
3. Scroll to `App Icons and Launch Screen`;
176+
4. Set `App Icon` to *`DefaultIcon`* and check the `Include all app icon assets` checkbox below.
177+
178+
<img src="https://ik.imagekit.io/Computools/RN%20Dynamic%20App%20Icons%20/xcode_general.png?updatedAt=1737456324703" width="400">
179+
180+
#### Step 3: Modify Info.plist
181+
182+
1. Open Xcode, go to `Info` and insert a key for `CFBundleIcons.`
183+
2. Within `CFBundleIcons` dictionary add key `CFBundleAlternateIcons`.
184+
3. Within `CFBundleAlternateIcons` add keys for alternative icons:
185+
- The `key` is the name you will reference from within code.
186+
- Set the first `array` item to the name of the target .appiconset.
187+
4. Within `CFBundleIcons` set the default icon name in `CFBundlePrimaryIcon` and `UINewsstandIcon` -> Icon files -> Item 0.
188+
189+
<img src="https://ik.imagekit.io/Computools/RN%20Dynamic%20App%20Icons%20/info_plist.png?updatedAt=1737456324778" width="400">
190+
191+
<br />
192+
193+
**`Info.plist` example:**
194+
195+
```
196+
<key>CFBundleIcons</key>
197+
<dict>
198+
<key>CFBundleAlternateIcons</key>
199+
<dict>
200+
<key>DefaultIcon</key>
201+
<dict>
202+
<key>CFBundleIconFiles</key>
203+
<array>
204+
<string>DefaultIcon</string>
205+
</array>
206+
<key>UIPrerenderedIcon</key>
207+
<false/>
208+
</dict>
209+
<key>OrangeIcon</key>
210+
<dict>
211+
<key>CFBundleIconFiles</key>
212+
<array>
213+
<string>OrangeIcon</string>
214+
</array>
215+
<key>UIPrerenderedIcon</key>
216+
<false/>
217+
</dict>
218+
<key>PineappleIcon</key>
219+
<dict>
220+
<key>CFBundleIconFiles</key>
221+
<array>
222+
<string>PineappleIcon</string>
223+
</array>
224+
<key>UIPrerenderedIcon</key>
225+
<false/>
226+
</dict>
227+
<key>StrawberryIcon</key>
228+
<dict>
229+
<key>CFBundleIconFiles</key>
230+
<array>
231+
<string>StrawberryIcon</string>
232+
</array>
233+
<key>UIPrerenderedIcon</key>
234+
<false/>
235+
</dict>
236+
</dict>
237+
<key>CFBundlePrimaryIcon</key>
238+
<dict>
239+
<key>CFBundleIconFiles</key>
240+
<array>
241+
<string>DefaultIcon</string>
242+
</array>
243+
<key>CFBundleIconName</key>
244+
<string></string>
245+
<key>UIPrerenderedIcon</key>
246+
<false/>
247+
</dict>
248+
<key>UINewsstandIcon</key>
249+
<dict>
250+
<key>CFBundleIconFiles</key>
251+
<array>
252+
<string>DefaultIcon</string>
253+
</array>
254+
<key>UINewsstandBindingEdge</key>
255+
<string>UINewsstandBindingEdgeLeft</string>
256+
<key>UINewsstandBindingType</key>
257+
<string>UINewsstandBindingTypeMagazine</string>
258+
</dict>
259+
</dict>
260+
```
261+
262+
## Methods
263+
264+
Method | Description | Parameters | Returns |
265+
--- | --- | --- | --- |
266+
**changeIcon(iconName: string)** | Changes the app's icon to the specified icon. <br/> **Note:** The package automatically closes the app on Android after changing the app icon. This behavior is implemented to prevent duplicate icons and requires no additional action from the user. | iconName (string): The name of the icon to switch to. | `Promise<void>`: Resolves with void or rejects with an error. |
267+
**getIcon()** | Retrieves the name of the currently active app icon. | None | `Promise<string>`: Resolves with the name of the current used icon or rejects with an error. |
268+
11269
## Usage
12270

271+
### Change Icon
13272

14-
```js
15-
import { multiply } from '@computools/react-native-dynamic-app-icon';
273+
```typescript
274+
import { changeIcon } from '@computools/react-native-dynamic-app-icon';
16275

17-
// ...
276+
const setAppIcon = async () => {
277+
try {
278+
await changeIcon('Orange');
279+
} catch (error) {
280+
// error handling
281+
}
282+
}
18283

19-
const result = await multiply(3, 7);
284+
setAppIcon();
20285
```
21286

287+
### Get Icon
288+
289+
```typescript
290+
import { getIcon } from '@computools/react-native-dynamic-app-icon';
291+
292+
const getCurrentIcon = async () => {
293+
try {
294+
const currentIcon = await getIcon();
295+
// the logic of saving the currentIcon or other
296+
} catch (error) {
297+
// error handling
298+
}
299+
}
300+
301+
getCurrentIcon();
302+
```
22303

23304
## Contributing
24305

0 commit comments

Comments
 (0)