簡體   English   中英

在 React Native 中,如何“動態”更改 Android 應用程序圖標?

[英]in React Native, How to change Android app icon "dynamically"?

我在互聯網上查找了一些類似這樣的包,它們不支持 React Native Android 並且沒有很好文檔記錄......

React Native Android 還有其他模塊嗎? 或者有什么方法可以讓應用程序動態更改圖標。

例如,當系統為深色主題時,圖標變為深色主題。 或者像日歷圖標更改在圖標上顯示當前日期。 或者時鍾顯示指針隨着秒數的流逝而移動,等等。

在 Android 上啟用動態圖標更改的步驟很少。 看起來工作量很大,但實際上很容易

1. 將所有圖標放在mipmap文件夾中。

AndroidManifest.xml (為每個圖標創建activity別名)

<application>下,Main <activity>不應包含intent-filter & android:exported應設置為true 這將使MainActivity始終可用而不顯示快捷方式圖標。

<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. 現在,對於您要顯示的每個圖標,創建<activity-alias> 為您的默認圖標設置android:enabledtrue 所有啟用的圖標將顯示在桌面上。 因此,請確保您只啟用一個活動別名。

<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.創建Java類

為您的每個活動別名創建空類。

package com.your.package;

class First {
}

5. 創建 IconChanger 類

@ReactMethod允許從 react-native 訪問它。 您可以將com.your.package更改為BuildConfig.APPLICATION_ID以避免多次寫入您的包名稱。

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.注冊為NativeModule

創建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. 現在將此包添加到您的MainApplication.java

@Override
protected List<ReactPackage> getPackages() {
    @SuppressWarnings("UnnecessaryLocalVariable")
    List<ReactPackage> packages = new PackageList(this).getPackages();
    packages.add(new CustomPackages());
    return packages;
}

8. 從react-native訪問IconChanger

import { NativeModules } from 'react-native';
const { IconChanger } = NativeModules;
IconChanger.changeIcon(newIcon, oldIcon);

[筆記]

  • 這將啟用新活動,然后關閉舊活動。

  • 在應用關閉或后台更改圖標,因為更改活動會關閉應用。

您可以編寫本機代碼來實現這一點。 或者使用以下 npm 庫。

React Native 動態應用程序圖標

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM