เป็นไปได้ไหมที่จะเปลี่ยนไอคอนแอปพลิเคชันโดยตรงจากโปรแกรม?
ฉันหมายถึงการเปลี่ยนแปลงicon.pngในres\drawableโฟลเดอร์
ฉันต้องการให้ผู้ใช้เปลี่ยนไอคอนของแอปพลิเคชันจากโปรแกรมดังนั้นในครั้งต่อไปพวกเขาจะเห็นไอคอนที่เลือกไว้ก่อนหน้าในตัวเรียกใช้งาน
เป็นไปได้ไหมที่จะเปลี่ยนไอคอนแอปพลิเคชันโดยตรงจากโปรแกรม?
ฉันหมายถึงการเปลี่ยนแปลงicon.pngในres\drawableโฟลเดอร์
ฉันต้องการให้ผู้ใช้เปลี่ยนไอคอนของแอปพลิเคชันจากโปรแกรมดังนั้นในครั้งต่อไปพวกเขาจะเห็นไอคอนที่เลือกไว้ก่อนหน้าในตัวเรียกใช้งาน
คำตอบ:
มันเป็นคำถามเก่า แต่ยังคงใช้งานอยู่เนื่องจากไม่มีคุณสมบัติ Android ที่ชัดเจน และพวกที่มาจาก facebook ก็พบว่ามีวิธีแก้ไขอยู่บ้าง วันนี้ฉันพบวิธีที่เหมาะกับฉัน ไม่สมบูรณ์ (ดูคำพูดท้ายคำตอบนี้) แต่ใช้งานได้!
แนวคิดหลักคือฉันอัปเดตไอคอนทางลัดของแอพของฉันซึ่งสร้างโดยตัวเรียกใช้งานบนหน้าจอหลักของฉัน เมื่อฉันต้องการเปลี่ยนบางสิ่งบางอย่างบนไอคอนทางลัดฉันจะลบออกก่อนแล้วสร้างมันใหม่ด้วยบิตแมปใหม่
นี่คือรหัส incrementมันมีปุ่ม เมื่อกดปุ่มลัดจะถูกแทนที่ด้วยหมายเลขที่มีหมายเลขนับใหม่
ก่อนอื่นคุณต้องมีสิทธิ์ทั้งสองนี้ในรายการของคุณ:
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
จากนั้นคุณต้องใช้สองวิธีในการติดตั้งและถอนการติดตั้งทางลัด shortcutAddวิธีการสร้างบิตแมปที่มีจำนวนอยู่ในนั้นด้วย นี่เป็นเพียงการแสดงให้เห็นว่ามันเปลี่ยนแปลงจริง คุณอาจต้องการเปลี่ยนส่วนนั้นด้วยบางอย่างที่คุณต้องการในแอปของคุณ
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วิธีนี้ยังสามารถใช้งานได้หากแอปควบคุมทางลัดมากขึ้นบนหน้าจอหลักเช่นกับพิเศษแตกต่างกันใน พวกเขาต้องการชื่อที่ต่างกันเพื่อให้ถอนการติดตั้งและติดตั้งใหม่อีกครั้ง
การจัดการทางลัดของโปรแกรมใน Android เป็นคุณสมบัติที่รู้จักกันดีใช้กันอย่างแพร่หลาย แต่ไม่รองรับคุณสมบัติ Android อย่างเป็นทางการ ดูเหมือนว่าจะทำงานกับตัวเรียกใช้เริ่มต้นและฉันไม่เคยลองที่อื่นเลย ดังนั้นอย่าโทษฉันเมื่อคุณได้รับอีเมลผู้ใช้ "มันใช้งานไม่ได้กับ XYZ ของฉันโทรศัพท์สองครั้งที่ถูกฝังรากและเสียหายเป็นพิเศษ"
ตัวเรียกใช้งานจะเขียน a Toastเมื่อมีการติดตั้งทางลัดและอีกหนึ่งทางลัดเมื่อถอนการติดตั้ง ดังนั้นฉันจะได้รับสองToastครั้งทุกครั้งที่เปลี่ยนไอคอน นี่ไม่สมบูรณ์แบบ แต่ก็ดีตราบใดที่แอพที่เหลือของฉันสมบูรณ์แบบ ...
ลองสิ่งนี้มันใช้งานได้ดีสำหรับฉัน:
1. แก้ไขMainActivityส่วนของคุณในAndroidManifest.xml, ลบออกจากมัน, สอดคล้องกับMAINหมวดหมู่ในintent-filterส่วน
<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. สร้าง<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 ให้เหมาะสมactivity-alias
getPackageManager().setComponentEnabledSetting(
new ComponentName("ru.quickmessage.pa", "ru.quickmessage.pa.MainActivity-Red"),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
หมายเหตุต้องเปิดใช้งานอย่างน้อยหนึ่งรายการตลอดเวลา
คุณไม่สามารถเปลี่ยนไฟล์ Manifest หรือทรัพยากรใน APK ที่ลงชื่อและได้รับการประทับตรายกเว้นการอัปเกรดซอฟต์แวร์
โดยทางโปรแกรมคุณอาจต้องการเผยแพร่ตัวเรียกใช้งานแอปพลิเคชันด้วยตนเอง:
หมายเหตุ: วิธีนี้ใช้ไม่ได้กับ Android 8.0 - Oreo อีกต่อไป
ใน AndroidManifest.xml ของคุณเพิ่ม:
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
จากนั้นคุณจำเป็นต้องสร้างตัวเรียกใช้งานแอปของคุณ:
Intent myLauncherIntent = new Intent();
myLauncherIntent.setClassName("your.package.name", "YourLauncherActivityName");
myLauncherIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
สร้างเจตนาติดตั้งทางลัดด้วยตัวเรียกใช้แอปและไอคอนที่กำหนดเอง
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);
สมมติว่าคุณหมายถึงการเปลี่ยนไอคอนที่แสดงบนหน้าจอหลักสิ่งนี้สามารถทำได้อย่างง่ายดายโดยการสร้างวิดเจ็ตที่ทำสิ่งนี้ ต่อไปนี้เป็นบทความที่แสดงให้เห็นถึงวิธีการทำให้สำเร็จสำหรับแอปพลิเคชันประเภท "ข้อความใหม่" ที่คล้ายกับ iPhone:
@ โซลูชันของ PA ทำงานได้บางส่วนสำหรับฉัน รายละเอียดการค้นพบของฉันด้านล่าง:
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) ควรใช้รหัสต่อไปนี้เพื่อปิดการใช้งานไอคอนทั้งหมดก่อนที่จะเปิดใช้งานอีกอันหนึ่งมิฉะนั้นมันจะเพิ่มไอคอนใหม่แทนที่จะแทนที่มัน
getPackageManager().setComponentEnabledSetting(
getComponentName(), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
แต่ถ้าคุณใช้รหัสด้านบนทางลัดบนหน้าจอหลักจะถูกลบออก! และจะไม่ถูกเพิ่มกลับโดยอัตโนมัติ คุณอาจสามารถเพิ่มไอคอนกลับโดยทางโปรแกรม แต่อาจไม่อยู่ในตำแหน่งเดิมเหมือนเดิม
3) โปรดทราบว่าไอคอนจะไม่เปลี่ยนแปลงทันทีอาจใช้เวลาหลายวินาที หากคุณคลิกทันทีหลังจากเปลี่ยนคุณอาจได้รับข้อผิดพลาดที่แจ้งว่า: "ไม่ได้ติดตั้งแอป"
ดังนั้น IMHO วิธีนี้เหมาะสำหรับการเปลี่ยนไอคอนในตัวเรียกใช้งานแอปเท่านั้นไม่ใช่สำหรับทางลัด (เช่นไอคอนบนหน้าจอหลัก)
ลองวิธีนี้
<activity android:name=".SplashActivity"
android:label="@string/app_name"
android:icon="@drawable/ic_launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity-alias android:label="ShortCut"
android:icon="@drawable/ic_short_cut"
android:name=".SplashActivityAlias"
android:enabled="false"
android:targetActivity=".SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
เพิ่มรหัสต่อไปนี้เมื่อคุณต้องการเปลี่ยนไอคอนแอปของคุณ
PackageManager pm = getPackageManager();
pm.setComponentEnabledSetting(
new ComponentName(YourActivity.this,
"your_package_name.SplashActivity"),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
pm.setComponentEnabledSetting(
new ComponentName(YourActivity.this,
"your_package_name.SplashActivityAlias"),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
AndroidManifest.xml ตัวอย่าง:
<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);
com.pritesh.resourceidentifierexample.MainActivity-Red doesn't exist in com.pritesh.resourceidentifierexampleยกเว้น ที่นี่ฉันใช้ชื่อรายการของคุณเพื่อแสดงให้เห็นถึงปัญหาของฉัน
เพื่อให้การแก้ปัญหาโดย Markus ทำงานฉันต้องการ Intent แรกดังนั้น:
Intent myLauncherIntent = new Intent(Intent.ACTION_MAIN);
myLauncherIntent.setClassName(this, this.getClass().getName());
myLauncherIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
การใช้คำแนะนำที่กล่าวถึงฉันประสบปัญหาแอพที่ถูกฆ่าเมื่อใดก็ตามที่ไอคอนเริ่มต้นเปลี่ยนเป็นไอคอนใหม่ ดังนั้นจึงมีการใช้รหัสด้วย tweaks ขั้นตอนที่ 1). ในไฟล์ AndroidManifest.xml ให้สร้างสำหรับกิจกรรมเริ่มต้นด้วย android: enabled = "true" และนามแฝงอื่น ๆ ที่มี android: enabled = "false" คุณจะไม่ได้มี แต่จะผนวกสิ่งเหล่านั้นด้วย Android: enabled = "true"
<activity
android:name=".activities.SplashActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/SplashTheme">
</activity>
<!-- <activity-alias used to change app icon dynamically> : default icon, set enabled true -->
<activity-alias
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:name=".SplashActivityAlias1" <!--put any random name started with dot-->
android:enabled="true"
android:targetActivity=".activities.SplashActivity"> <!--target activity class path will be same for all alias-->
<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 used to change app icon dynamically> : sale icon, set enabled false initially -->
<activity-alias
android:label="@string/app_name"
android:icon="@drawable/ic_store_marker"
android:roundIcon="@drawable/ic_store_marker"
android:name=".SplashActivityAlias" <!--put any random name started with dot-->
android:enabled="false"
android:targetActivity=".activities.SplashActivity"> <!--target activity class path will be same for all alias-->
<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>
ขั้นตอนที่ 2). สร้างวิธีที่จะใช้ในการปิดใช้งานนามแฝงกิจกรรมแรกที่มีไอคอนเริ่มต้นและเปิดใช้งานนามแฝงที่ 2 ที่มีไอคอนจำเป็นต้องเปลี่ยน
/**
* method to change the app icon dynamically
*
* @param context
* @param isNewIcon : true if new icon need to be set; false to set default
* icon
*/
public static void changeAppIconDynamically(Context context, boolean isNewIcon) {
PackageManager pm = context.getApplicationContext().getPackageManager();
if (isNewIcon) {
pm.setComponentEnabledSetting(
new ComponentName(context,
"com.example.dummy.SplashActivityAlias1"), //com.example.dummy will be your package
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
pm.setComponentEnabledSetting(
new ComponentName(context,
"com.example.dummy.SplashActivityAlias"),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
} else {
pm.setComponentEnabledSetting(
new ComponentName(context,
"com.example.dummy.SplashActivityAlias1"),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
pm.setComponentEnabledSetting(
new ComponentName(context,
"com.example.dummy.SplashActivityAlias"),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
}
ขั้นตอนที่ 3) ตอนนี้เรียกวิธีการนี้ขึ้นอยู่กับความต้องการของคุณพูดบนปุ่มคลิกหรือวันที่เฉพาะหรือเงื่อนไขเฉพาะโอกาสเช่น -
// Switch app icon to new icon
GeneralUtils.changeAppIconDynamically(EditProfileActivity.this, true);
// Switch app icon to default icon
GeneralUtils.changeAppIconDynamically(EditProfileActivity.this, false);
หวังว่านี่จะช่วยให้ผู้ที่ประสบปัญหาการแอพถูกฆ่าเมื่อเปลี่ยนไอคอน Happy Coding :)