Is there any way to dynamically change an app icon like Calendar app does?
Whatever your home screen is has special hooks for whatever your calendar app is and whatever your alarm clock app is. In general, apps cannot update their icons.
What do you mean by hooks?
For example, Samsung can ship a Samsung calendar app on Samsung devices. Samsung's home screen on those same Samsung devices can have special rules for rendering an icon for Samsung's calendar app, rules that involve showing the day of the month. This is because Samsung wrote the home screen. If you install a third-party home screen, it may not do the same thing. After all, I can write a home screen in an hour or so, and I feel quite confident that I don't have to do anything special for Samsung's calendar app.
There's nothing stopping Samsung from exposing some sort of API to allow developers to hook into Samsung's home screen and notify it about this sort of thing. Whether Samsung intends for third parties to use that API, or whether it is somebody hacking into how Samsung does it for their own apps, I can't say.
(BTW, I am citing Samsung here as a possible example -- I don't know that they actually have this sort of feature, and if so on which devices they have it)
I seem to recall that somebody has a GitHub project that tries to wrap the proprietary APIs of various home screens. IIRC, some supported capabilities included either replacing the app icon or adding a badge (e.g., unread message count). However:
Only a small percentage of devices will support those proprietary APIs
Undocumented and unsupported APIs, discovered through reverse-engineering apps, are subject to change and may break in unexpected ways
I am quite certain that there is nothing in the Android SDK that supports dynamic app icons. The only thing that I know of, that people have tried, is using <activity-alias>
to have N different "activities", all pointing to the same implementation, but having different icons. Using PackageManager
and setComponentEnabledSetting()
, the app disables the old launcher alias and enables a different one, in hopes that home screens will pick up on this and show the new icon. A few do. Others only would find out about the change on a reboot.
To flip the problem around, I can write a home screen. Perhaps I want to offer some way for apps to change their icons on the fly, even though there are no standards for it. Perhaps I don't. Perhaps I do not intend to use icons at all, as my home screen is optimized for the visually impaired, and so it is using text-to-speech and hardware key input. It's my home screen implementation, and I can do what I want.
Updating the App icon like Calendar app
No this is not possible, the app bundle is readonly and there for you can not change the app icon.
You will have to update the app every month the change the icon.
How to create dynamic icon like calendar icon of ios 7?
You can not do this, there is no API allowing this.
Your apps icon is in your application bundle which is readonly and therefor can not be modified.
How to change an application icon programmatically in Android?
It's an old question, but still active as there is no explicit Android feature. And the guys from facebook found a work around - somehow. Today, I found a way that works for me. Not perfect (see remarks at the end of this answer) but it works!
Main idea is, that I update the icon of my app's shortcut, created by the launcher on my home screen. When I want to change something on the shortcut-icon, I remove it first and recreate it with a new bitmap.
Here is the code. It has a button increment
. When pressed, the shortcut is replaced with one that has a new counting number.
First you need these two permissions in your manifest:
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
Then you need this two methods for installing and uninstalling shortcuts. The shortcutAdd
method creates a bitmap with a number in it. This is just to demonstrate that it actually changes. You probably want to change that part with something, you want in your app.
private void shortcutAdd(String name, int number) {
// Intent to be send, when shortcut is pressed by user ("launched")
Intent shortcutIntent = new Intent(getApplicationContext(), Play.class);
shortcutIntent.setAction(Constants.ACTION_PLAY);
// Create bitmap with number in it -> very default. You probably want to give it a more stylish look
Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Paint paint = new Paint();
paint.setColor(0xFF808080); // gray
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(50);
new Canvas(bitmap).drawText(""+number, 50, 50, paint);
((ImageView) findViewById(R.id.icon)).setImageBitmap(bitmap);
// Decorate the shortcut
Intent addIntent = new Intent();
addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap);
// Inform launcher to create shortcut
addIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
getApplicationContext().sendBroadcast(addIntent);
}
private void shortcutDel(String name) {
// Intent to be send, when shortcut is pressed by user ("launched")
Intent shortcutIntent = new Intent(getApplicationContext(), Play.class);
shortcutIntent.setAction(Constants.ACTION_PLAY);
// Decorate the shortcut
Intent delIntent = new Intent();
delIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
delIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
// Inform launcher to remove shortcut
delIntent.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT");
getApplicationContext().sendBroadcast(delIntent);
}
And finally, here are two listener to add the first shortcut and update the shortcut with an incrementing counter.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
findViewById(R.id.add).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
shortcutAdd("changeIt!", count);
}
});
findViewById(R.id.increment).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
shortcutDel("changeIt!");
count++;
shortcutAdd("changeIt!", count);
}
});
}
Remarks:
This way works also if your App controls more shortcuts on the home screen, e.g. with different extra's in the
Intent
. They just need different names so that the right one is uninstalled and reinstalled.The programmatical handling of shortcuts in Android is a well known, widely used but not officially supported Android feature. It seems to work on the default launcher and I never tried it anywhere else. So dont blame me, when you get this user-emails "It does not work on my XYZ, double rooted, super blasted phone"
The launcher writes a
Toast
when a shortcut was installad and one when a shortcut was uninstalled. So I get twoToast
s every time I change the icon. This is not perfect, but well, as long as the rest of my app is perfect...
in React Native, How to change Android app icon dynamically?
There are few steps to enable dynamic icon change on Android. Seems a lot of work, but actually very easy.
1. Put all your icons on mipmap
folder.
2. AndroidManifest.xml
(Create activity alias for each icon)
Under <application>
, Main <activity>
should not contain intent-filter
& android:exported
should be set to true
. this will make MainActivity
available always without showing shortcut icon.
<activity
android:name=".MainActivity"
android:label="Test App"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:exported="true"
>
</activity>
3. Now, for each icon you want to display, create <activity-alias>
. Set android:enabled
to true
for your defailt icon. All enabled icons will be displayed on desktop. So make sure you enable only one activity alias.
<activity-alias
android:label="Test App :: Default"
android:icon="@mipmap/icon1"
android:name="First"
android:enabled="true"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:label="Test App :: Special"
android:icon="@mipmap/icon2"
android:name="Second"
android:enabled="false"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:label="Test App :: Very Special"
android:icon="@mipmap/icon3"
android:name="Third"
android:enabled="false"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
4. Create a Java Classes
Create empty class for each of your activity alias.
package com.your.package;
class First {
}
5. Create IconChanger class
@ReactMethod
allows accessing it from react-native. You can change com.your.package
to BuildConfig.APPLICATION_ID
to avoid writing your package name multiple times.
package your.package.name;
import android.os.Bundle;
import com.facebook.react.ReactActivity;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.util.Map;
import java.util.HashMap;
import android.content.pm.PackageManager;
import android.content.ComponentName;
import com.facebook.react.bridge.Promise;
import android.os.Bundle;
import android.widget.Toast;
public class IconChanger extends ReactContextBaseJavaModule {
private final ReactApplicationContext reactContext;
public IconChanger(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}
@Override
public String getName() {
return "IconChanger";
}
@ReactMethod
public void changeIcon(String enableIntent, String disableIntent, Promise response) {
try {
PackageManager packageManager = this.reactContext.getPackageManager();
int action;
String activeIntent="com.your.package."+enableIntent;
Toast.makeText( this.reactContext,"Enabling "+enableIntent,Toast.LENGTH_SHORT).show();
packageManager.setComponentEnabledSetting(
new ComponentName("com.your.package", activeIntent),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
);
if(!disableIntent.equals(null) && !disableIntent.equals(enableIntent)){
activeIntent="com.your.package.."+disableIntent;
Toast.makeText( this.reactContext,"Disabling "+disableIntent,Toast.LENGTH_SHORT).show();
packageManager.setComponentEnabledSetting(
new ComponentName("com.your.package.", activeIntent),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
);
}
response.resolve(enableIntent);
} catch (Exception e) {
response.reject("Error", e);
}
}
}
6. Register it as NativeModule
Create CustomPackages.java
package com.your.package;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CustomPackages implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new IconChanger(reactContext));
return modules;
}
}
7. Now add this package to your MainApplication.java
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new CustomPackages());
return packages;
}
8. Access IconChanger
from react-native
import { NativeModules } from 'react-native';
const { IconChanger } = NativeModules;
IconChanger.changeIcon(newIcon, oldIcon);
[NOTES]
This will enable new activity & then close old activity.
Change icon on app close or in background, as changing activity closes the app.
Related Topics
Tablayout Tab Title Text in Lower Case
Capturing Images with Mediastore.Action_Image_Capture Intent in Android
How to Use the Speechrecognizer API Directly for Speech Input
How to Limit Fling in Android Gallery to Just One Item Per Fling
How to Launch the 'Add Contact' Activity in Android
How to Download a Video File to Sd Card
How to Force a Cache Clearing Using Universal Image Loader Android
Detecting Gps On/Off Switch in Android Phones
How to Sign My Application with the System Signature Key
Do Gcm Registration Id's Expire
Failed to Import New Gradle Project in Android Studio
How to Download a File from a Server and Save It in Specific Folder in Sd Card in Android
Does Retrofit Make Network Calls on Main Thread
Scoping States in Jetpack Compose
What Actually Happens When Persistence Is Enabled in Firebase