如何在Android中以编程方式更改应用程序图标?

是否可以直接从程序中更改应用程序图标?
我的意思是,在res\drawable文件夹中更改icon.png
我想让用户从程序中更改应用程序的图标,以便下次他们能够看到启动器中以前select的图标。

这是一个古老的问题,但仍然活跃,因为没有明确的Androidfunction。 而来自facebook的人发现了一个工作 – 不知何故。 今天,我find了一种适合我的方式。 不完美(见这个答案的结尾处的评论),但它的工作原理!

主要的想法是,我更新了我的主屏幕上启动器创build的应用程序快捷方式的图标。 当我想要更改快捷方式图标上的某些内容时,首先将其删除,然后用新的位图重新创build。

这是代码。 它有一个buttonincrement 。 按下时,快捷键被replace为具有新的计数编号的快捷键。

首先,你需要清单中的这两个权限:

 <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /> <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" /> 

那么你需要这两种方法来安装和卸载快捷方式。 shortcutAdd方法创build一个包含数字的位图。 这只是为了certificate它实际上发生了变化。 您可能想要在应用程序中使用某些东西来更改该部分。

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

最后,这里有两个监听器添加第一个快捷方式,并使用递增计数器更新快捷方式。

 @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); } }); } 

备注:

  • 如果您的应用在主屏幕上控制更多的快捷方式,例如在Intent使用不同的额外function,这种方式也可以。 他们只需要不同的名称,以便正确的名称被卸载并重新安装。

  • Android中的快捷方式的程序化处理是众所周知的,广泛使用但没有正式支持的Androidfunction。 它似乎工作在默认的启动器,我从来没有尝试过任何其他地方。 所以不要怪我,当你得到这个用户的电子邮件“这不适合我的XYZ,双根,超级爆炸手机”

  • 启动程序在安装快捷方式时写Toast ,在卸载快捷方式时写一个Toast 。 所以我每次更换图标都会得到两个Toast 。 这并不完美,但是,只要我的应用程序的其余部分是完美的… …

试试这个,对我来说工作正常=)

1。 在AndroidManifest.xml中修改您的MainActivity部分,从中删除,在intent-filter部分填入MAIN类别

 <activity android:name="ru.quickmessage.pa.MainActivity" android:configChanges="keyboardHidden|orientation" android:screenOrientation="portrait" android:label="@string/app_name" android:theme="@style/CustomTheme" android:launchMode="singleTask"> <intent-filter> ==> <action android:name="android.intent.action.MAIN" /> <== Delete this line <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> 

2。 为每个图标创build<activity-alias> 。 喜欢这个

 <activity-alias android:label="@string/app_name" android:icon="@drawable/icon" android:name=".MainActivity-Red" 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> 

3。 以编程方式设置:为相应的活动别名设置ENABLE属性

  getPackageManager().setComponentEnabledSetting( new ComponentName("ru.quickmessage.pa", "ru.quickmessage.pa.MainActivity-Red"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); 

请注意,必须始终启用至less一个。

除非通过软件升级,否则无法更改已签名且密封的APK中的清单或资源。

以编程方式,您可能想要自己发布应用程序启动器:

在你的AndroidManifest.xml中,添加:

 <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/> 

那么你需要创build你的应用程序启动器的意图:

 Intent myLauncherIntent = new Intent(); myLauncherIntent.setClassName("your.package.name", "YourLauncherActivityName"); myLauncherIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 

使用您的应用启动器和自定义图标创build安装快捷方式:

 Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, myLauncherIntent); intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Application Name"); intent.putExtra ( Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext ( getApplicationContext(), R.drawable.app_icon ) ); intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); 

最后发布广播意图:

 getApplicationContext().sendBroadcast(intent); 

假设你的意思是改变主屏幕上显示的图标,这可以通过创build一个完全做到这一点的小部件来完成。 下面是一篇文章,演示了如何实现类似于iPhone的“新消息”types应用程序:

http://www.cnet.com/8301-19736_1-10278814-251.html

PA的解决scheme部分适用于我。 下面详细介绍我的发现

1)第一个代码片段不正确,如下所示:

 <activity ... <intent-filter> ==> <action android:name="android.intent.action.MAIN" /> <== This line shouldn't be deleted, otherwise will have compile error <category android:name="android.intent.category.LAUNCHER" /> //DELETE THIS LINE </intent-filter> </activity> 

2)在启用另一个图标之前,应使用以下代码禁用所有图标,否则将添加一个新图标,而不是replace它。

 getPackageManager().setComponentEnabledSetting( getComponentName(), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); 

但是,如果你使用上面的代码,那么主屏幕上的快捷方式将被删除! 它不会被自动添加回来。 您可能能够以编程方式将图标添加回来,但可能不会像以前一样保留原位。

3)请注意,图标不会立即改变,可能需要几秒钟。 如果您在更改后立即点击它,您可能会收到错误消息:“应用程序未安装”。

所以,恕我直言,这个解决scheme只适用于更改应用程序启动器中的图标,而不是快捷方式(即主屏幕上的图标)

为了得到Markus工作的解决scheme,我需要第一个Intent,

 Intent myLauncherIntent = new Intent(Intent.ACTION_MAIN); myLauncherIntent.setClassName(this, this.getClass().getName()); myLauncherIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 

请参考这个例子

 <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name="com.pritesh.resourceidentifierexample.MainActivity" android:label="@string/app_name" android:launchMode="singleTask"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <!--<category android:name="android.intent.category.LAUNCHER"/>--> </intent-filter> </activity> <activity-alias android:label="RED" android:icon="@drawable/ic_android_red" android:name="com.pritesh.resourceidentifierexample.MainActivity-Red" android:enabled="true" android:targetActivity="com.pritesh.resourceidentifierexample.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <activity-alias android:label="GREEN" android:icon="@drawable/ic_android_green" android:name="com.pritesh.resourceidentifierexample.MainActivity-Green" android:enabled="false" android:targetActivity="com.pritesh.resourceidentifierexample.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <activity-alias android:label="BLUE" android:icon="@drawable/ic_android_blue" android:name="com.pritesh.resourceidentifierexample.MainActivity-Blue" android:enabled="false" android:targetActivity="com.pritesh.resourceidentifierexample.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> </application> 

请参阅上面的答案后,请按照下面给出的MainActivity中的代码

 ImageView imageView = (ImageView)findViewById(R.id.imageView); int imageResourceId; String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date()); int hours = new Time(System.currentTimeMillis()).getHours(); Log.d("DATE", "onCreate: " + hours); getPackageManager().setComponentEnabledSetting( getComponentName(), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); if(hours == 13) { imageResourceId = this.getResources().getIdentifier("ic_android_red", "drawable", this.getPackageName()); getPackageManager().setComponentEnabledSetting( new ComponentName("com.pritesh.resourceidentifierexample", "com.pritesh.resourceidentifierexample.MainActivity-Red"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); }else if(hours == 14) { imageResourceId = this.getResources().getIdentifier("ic_android_green", "drawable", this.getPackageName()); getPackageManager().setComponentEnabledSetting( new ComponentName("com.pritesh.resourceidentifierexample", "com.pritesh.resourceidentifierexample.MainActivity-Green"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); }else { imageResourceId = this.getResources().getIdentifier("ic_android_blue", "drawable", this.getPackageName()); getPackageManager().setComponentEnabledSetting( new ComponentName("com.pritesh.resourceidentifierexample", "com.pritesh.resourceidentifierexample.MainActivity-Blue"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); } imageView.setImageResource(imageResourceId);