You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android如何动态修改桌面Launcher图标与应用名称?

动态修改Android应用主屏幕图标与名称的解决方案

我的小型应用希望根据带有on-prem键的JSON值,动态修改主屏幕上显示的应用图标和名称。现有代码可修改运行应用标签中的图标及应用UI内的名称,但无法修改主屏幕上的图标与名称。请问应如何修改代码解决该问题?

现有代码

package com.example.whitelabelpreviousstep;

import androidx.appcompat.app.AppCompatActivity;

import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.util.Log;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONException;
import org.json.JSONObject;

import javax.net.ssl.HttpsURLConnection;

public class MainActivityy extends AppCompatActivity {

    private static final String FLASK_URL = "http://10.0.2.2:5000/get_data"; // loopback interface, i.e. localhost

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Allow insecure connections for testing purposes
        HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);

        // Initialize the Volley request queue
        RequestQueue queue = Volley.newRequestQueue(this);

        // Create a JSON object to send to the Flask server
        JSONObject jsonBody = new JSONObject();
        try {
            jsonBody.put("on-prem", "burak23"); // Change the value as needed
        } catch (JSONException e) {
            e.printStackTrace();
        }

        // Create a JsonObjectRequest to send the JSON object to the Flask server
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, FLASK_URL, jsonBody,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        // Process the response on the main thread
                        handleResponse(response);
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                // Handle error response on the main thread
                handleErrorResponse(error);
            }
        });

        // Add the request to the request queue
        queue.add(jsonObjectRequest);
    }

    private void handleResponse(JSONObject response) {
        try {
            if (response.has("on-prem")) {
                String value = response.getString("on-prem");
                // Check the value received from the server and change the app icon, launcher icon, and app name accordingly
                if ("burak23".equals(value)) {
                    changeAppIconAndName(R.mipmap.imga, R.string.launcher_name_one, R.drawable.imga, "Burak 23");
                } else if ("burak24".equals(value)) {
                    changeAppIconAndName(R.mipmap.imgb, R.string.launcher_name_two, R.drawable.imgb, "Burak 24");
                }

            } else {
                Log.e("FLASK_RESPONSE", "Key 'on-prem' not found in JSON data");
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private void handleErrorResponse(VolleyError error) {
        if (error.networkResponse != null && error.networkResponse.statusCode == 500) {
            Log.e("SSL_HANDSHAKE_ERROR", "SSL/TLS handshake failed: " + error.getMessage());
        } else {
            Log.e("VOLLEY_ERROR", error.toString());
        }
    }

    private void changeAppIconAndName(int launcherIconId, int appNameId, int homeIconId, String appName) {
        PackageManager packageManager = getApplicationContext().getPackageManager();

        // Set the new launcher icon
        getApplicationInfo().icon = launcherIconId;

        // Set the new app name
        getApplicationInfo().labelRes = appNameId;
        setTitle(getString(appNameId));

        // Set the new task description with the app icon
        BitmapDrawable bitmapDrawable = (BitmapDrawable) getResources().getDrawable(homeIconId);
        Bitmap bitmap = bitmapDrawable.getBitmap();
        ActivityManager.TaskDescription taskDescription = new ActivityManager.TaskDescription(getString(appNameId), bitmap, Color.TRANSPARENT);
        setTaskDescription(taskDescription);

        // Log a message to indicate that the app icon and name have been changed
        Log.d("FLASK_RESPONSE", "App icon and name changed successfully");
    }
}

解决方案

核心原理

Android主屏幕的图标和名称由**Launcher Activity别名(Activity Alias)**控制,无法通过直接修改ApplicationInfo实现。我们需要为每个白标配置创建对应的别名,通过启用/禁用不同别名来切换主屏幕显示内容。

步骤1:修改AndroidManifest.xml

为每个白标配置添加Activity Alias,主Activity保留默认但后续会禁用:

<!-- 主Activity(默认保留,后续通过代码禁用) -->
<activity
    android:name=".MainActivityy"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<!-- 别名1:对应burak23配置 -->
<activity-alias
    android:name=".Burak23Alias"
    android:enabled="false"
    android:exported="true"
    android:icon="@mipmap/imga"
    android:label="@string/launcher_name_one"
    android:targetActivity=".MainActivityy">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity-alias>

<!-- 别名2:对应burak24配置 -->
<activity-alias
    android:name=".Burak24Alias"
    android:enabled="false"
    android:exported="true"
    android:icon="@mipmap/imgb"
    android:label="@string/launcher_name_two"
    android:targetActivity=".MainActivityy">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity-alias>

步骤2:替换切换逻辑代码

删除原changeAppIconAndName方法,替换为以下代码:

private void changeAppIconAndName(String targetAliasName) {
    PackageManager packageManager = getPackageManager();
    String packageName = getPackageName();

    // 禁用所有Launcher入口(主Activity+所有别名)
    disableComponent(packageManager, packageName + ".MainActivityy");
    disableComponent(packageManager, packageName + ".Burak23Alias");
    disableComponent(packageManager, packageName + ".Burak24Alias");

    // 启用目标别名
    enableComponent(packageManager, packageName + "." + targetAliasName);

    // 更新应用内标题和任务栏图标
    if ("Burak23Alias".equals(targetAliasName)) {
        setTitle(getString(R.string.launcher_name_one));
        updateTaskDescription(R.drawable.imga, R.string.launcher_name_one);
    } else if ("Burak24Alias".equals(targetAliasName)) {
        setTitle(getString(R.string.launcher_name_two));
        updateTaskDescription(R.drawable.imgb, R.string.launcher_name_two);
    }

    Log.d("FLASK_RESPONSE", "主屏幕图标和名称已切换至:" + targetAliasName);
}

// 辅助方法:禁用组件
private void disableComponent(PackageManager pm, String componentName) {
    pm.setComponentEnabledSetting(
            new ComponentName(this, componentName),
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP
    );
}

// 辅助方法:启用组件
private void enableComponent(PackageManager pm, String componentName) {
    pm.setComponentEnabledSetting(
            new ComponentName(this, componentName),
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP
    );
}

// 更新任务栏描述
private void updateTaskDescription(int iconResId, int titleResId) {
    BitmapDrawable bitmapDrawable = (BitmapDrawable) getResources().getDrawable(iconResId);
    Bitmap bitmap = bitmapDrawable.getBitmap();
    ActivityManager.TaskDescription taskDescription = new ActivityManager.TaskDescription(
            getString(titleResId), bitmap, Color.TRANSPARENT
    );
    setTaskDescription(taskDescription);
}

步骤3:更新handleResponse调用

修改handleResponse方法中的调用逻辑:

private void handleResponse(JSONObject response) {
    try {
        if (response.has("on-prem")) {
            String value = response.getString("on-prem");
            if ("burak23".equals(value)) {
                changeAppIconAndName("Burak23Alias");
            } else if ("burak24".equals(value)) {
                changeAppIconAndName("Burak24Alias");
            }
        } else {
            Log.e("FLASK_RESPONSE", "JSON数据中未找到'on-prem'键");
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

注意事项

  • 切换后需重启Launcher生效(部分系统自动刷新,部分需用户手动重启或等待系统同步)。
  • 确保图标资源(@mipmap/imga、@mipmap/imgb)和字符串资源(@string/launcher_name_one、@string/launcher_name_two)已正确添加到项目中。

内容的提问来源于stack exchange,提问作者Beyza Ö.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 11:44:54