diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 0d403611..eb601acd 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -52,5 +52,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/java/fun/upup/musicfree/MainApplication.java b/android/app/src/main/java/fun/upup/musicfree/MainApplication.java index ae3b0b80..eacac5e6 100644 --- a/android/app/src/main/java/fun/upup/musicfree/MainApplication.java +++ b/android/app/src/main/java/fun/upup/musicfree/MainApplication.java @@ -11,6 +11,7 @@ import com.facebook.react.config.ReactFeatureFlags; import com.facebook.soloader.SoLoader; +import fun.upup.musicfree.appIconUtil.AppIconUtilPackage; import fun.upup.musicfree.newarchitecture.MainApplicationReactNativeHost; import java.lang.reflect.InvocationTargetException; @@ -39,6 +40,7 @@ protected List getPackages() { packages.add(new UtilsPackage()); packages.add(new Mp3UtilPackage()); packages.add(new LyricUtilPackage()); + packages.add(new AppIconUtilPackage(getPackageName())); return packages; } diff --git a/android/app/src/main/java/fun/upup/musicfree/appIconUtil/AppIconUtilModule.java b/android/app/src/main/java/fun/upup/musicfree/appIconUtil/AppIconUtilModule.java new file mode 100644 index 00000000..9434ecb6 --- /dev/null +++ b/android/app/src/main/java/fun/upup/musicfree/appIconUtil/AppIconUtilModule.java @@ -0,0 +1,173 @@ +// 参考:https://blog.stackademic.com/change-the-app-icon-at-runtime-for-react-native-by-creating-a-nativemodule-5bfb285bd69b +package fun.upup.musicfree.appIconUtil; + +import android.Manifest; +import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.app.Activity; +import android.app.Application; +import android.content.ComponentName; +import android.content.pm.PackageManager; +import android.os.Bundle; + + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; + +import java.util.HashSet; +import java.util.Set; + + +public class AppIconUtilModule extends ReactContextBaseJavaModule implements Application.ActivityLifecycleCallbacks { + private static ReactApplicationContext reactContext; + + private final String packageName; + + public static final String MAIN_ACTVITY_BASE_NAME = ".MainActivity"; + + private String componentClass = ""; + + private final Set classesToKill = new HashSet<>(); + + public AppIconUtilModule(ReactApplicationContext context, String packageName) { + super(context); + reactContext = context; + this.packageName = packageName; + } + + @NonNull + @Override + public String getName() { + return "AppIconUtil"; + } + + @ReactMethod + public void getIcon(Promise promise) { + final Activity activity = getCurrentActivity(); + if (activity == null) { + promise.reject("ACTIVITY_NOT_FOUND", "Activity was not found"); + return; + } + + final String activityName = activity.getComponentName().getClassName(); + + if (activityName.endsWith(MAIN_ACTVITY_BASE_NAME)) { + promise.resolve("Default"); + return; + } + String[] activityNameSplit = activityName.split("MainActivity"); + if (activityNameSplit.length != 2) { + promise.reject("ANDROID:UNEXPECTED_COMPONENT_CLASS:", this.componentClass); + return; + } + promise.resolve(activityNameSplit[1]); + } + + @ReactMethod + public void changeIcon(String iconName, Promise promise) { + + final Activity activity = getCurrentActivity(); + + if (activity == null) { + promise.reject("ACTIVITY_NOT_FOUND", "The activity is null. Check if the app is running properly."); + return; + } + if (iconName.isEmpty()) { + promise.reject("EMPTY_ICON_STRING", "Icon name is missing i.e. changeIcon('YOUR_ICON_NAME_HERE')"); + return; + } + if (this.componentClass.isEmpty()) { + this.componentClass = activity.getComponentName().getClassName(); // i.e. MyActivity + } + + final String activeClass = this.packageName + MAIN_ACTVITY_BASE_NAME + iconName; + + if (this.componentClass.equals(activeClass)) { + promise.reject("ICON_ALREADY_USED", "This icons is the current active icon. " + this.componentClass); + return; + } + + try { + activity.getPackageManager().setComponentEnabledSetting( + new ComponentName(this.packageName, activeClass), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP + ); + promise.resolve(iconName); + } catch (Exception e) { + promise.reject("ICON_INVALID", e.getLocalizedMessage()); + return; + } + + this.classesToKill.add(this.componentClass); + this.componentClass = activeClass; + activity.getApplication().registerActivityLifecycleCallbacks(this); +// The completeIconChange() is what makes the current active class disabled. +// Move it to onActivityPaused or onActivityStopped etc to change the icon only when the app closes or goes to background + completeIconChange(); + } + + private void completeIconChange() { + final Activity activity = getCurrentActivity(); + if (activity == null) return; + +// Works for minSdkVersion = 23 + for (String className : classesToKill) { + activity.getPackageManager().setComponentEnabledSetting( + new ComponentName(this.packageName, className), + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP + ); + } +/* + // Works for minSdkVersion = 24 and above + classesToKill.forEach((cls) -> activity.getPackageManager().setComponentEnabledSetting( + new ComponentName(this.packageName, cls), + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP + )); +*/ + classesToKill.clear(); + } + + @Override + public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle bundle) { + + } + + @Override + public void onActivityStarted(@NonNull Activity activity) { + + } + + @Override + public void onActivityResumed(@NonNull Activity activity) { + + } + + @Override + public void onActivityPaused(@NonNull Activity activity) { + + } + + @Override + public void onActivityStopped(@NonNull Activity activity) { + + } + + @Override + public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle bundle) { + + } + + @Override + public void onActivityDestroyed(@NonNull Activity activity) { + + } +} \ No newline at end of file diff --git a/android/app/src/main/java/fun/upup/musicfree/appIconUtil/AppIconUtilPackage.java b/android/app/src/main/java/fun/upup/musicfree/appIconUtil/AppIconUtilPackage.java new file mode 100644 index 00000000..424a258e --- /dev/null +++ b/android/app/src/main/java/fun/upup/musicfree/appIconUtil/AppIconUtilPackage.java @@ -0,0 +1,35 @@ +package fun.upup.musicfree.appIconUtil; + +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 AppIconUtilPackage implements ReactPackage { + + private final String packageName; + + public AppIconUtilPackage(String packageName) { + this.packageName = packageName; + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List createNativeModules( + ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + + modules.add(new AppIconUtilModule(reactContext, this.packageName)); + + return modules; + } + +} \ No newline at end of file diff --git a/android/app/src/main/musicfree_logo_1-playstore.png b/android/app/src/main/musicfree_logo_1-playstore.png new file mode 100644 index 00000000..213604a8 Binary files /dev/null and b/android/app/src/main/musicfree_logo_1-playstore.png differ diff --git a/android/app/src/main/res/drawable-v24/musicfree_logo_1_foreground.xml b/android/app/src/main/res/drawable-v24/musicfree_logo_1_foreground.xml new file mode 100644 index 00000000..d790786b --- /dev/null +++ b/android/app/src/main/res/drawable-v24/musicfree_logo_1_foreground.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/mipmap-anydpi-v26/musicfree_logo_1.xml b/android/app/src/main/res/mipmap-anydpi-v26/musicfree_logo_1.xml new file mode 100644 index 00000000..d7fd15f5 --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/musicfree_logo_1.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/musicfree_logo_1_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/musicfree_logo_1_round.xml new file mode 100644 index 00000000..d7fd15f5 --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/musicfree_logo_1_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/musicfree_logo_1.png b/android/app/src/main/res/mipmap-hdpi/musicfree_logo_1.png new file mode 100644 index 00000000..206e1450 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/musicfree_logo_1.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/musicfree_logo_1_round.png b/android/app/src/main/res/mipmap-hdpi/musicfree_logo_1_round.png new file mode 100644 index 00000000..0e5b0ead Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/musicfree_logo_1_round.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/musicfree_logo_1.png b/android/app/src/main/res/mipmap-mdpi/musicfree_logo_1.png new file mode 100644 index 00000000..ae1844f6 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/musicfree_logo_1.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/musicfree_logo_1_round.png b/android/app/src/main/res/mipmap-mdpi/musicfree_logo_1_round.png new file mode 100644 index 00000000..45e631df Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/musicfree_logo_1_round.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/musicfree_logo_1.png b/android/app/src/main/res/mipmap-xhdpi/musicfree_logo_1.png new file mode 100644 index 00000000..38e3a779 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/musicfree_logo_1.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/musicfree_logo_1_round.png b/android/app/src/main/res/mipmap-xhdpi/musicfree_logo_1_round.png new file mode 100644 index 00000000..98dad35a Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/musicfree_logo_1_round.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/musicfree_logo_1.png b/android/app/src/main/res/mipmap-xxhdpi/musicfree_logo_1.png new file mode 100644 index 00000000..673d5133 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/musicfree_logo_1.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/musicfree_logo_1_round.png b/android/app/src/main/res/mipmap-xxhdpi/musicfree_logo_1_round.png new file mode 100644 index 00000000..42268056 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/musicfree_logo_1_round.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/musicfree_logo_1.png b/android/app/src/main/res/mipmap-xxxhdpi/musicfree_logo_1.png new file mode 100644 index 00000000..579d1b8f Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/musicfree_logo_1.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/musicfree_logo_1_round.png b/android/app/src/main/res/mipmap-xxxhdpi/musicfree_logo_1_round.png new file mode 100644 index 00000000..999c364e Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/musicfree_logo_1_round.png differ diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index 7d20811f..3537a279 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -1,3 +1,3 @@ - #FFF7C1 + #F7F7F1 \ No newline at end of file diff --git a/android/app/src/main/res/values/musicfree_logo_1_background.xml b/android/app/src/main/res/values/musicfree_logo_1_background.xml new file mode 100644 index 00000000..f236b946 --- /dev/null +++ b/android/app/src/main/res/values/musicfree_logo_1_background.xml @@ -0,0 +1,4 @@ + + + #F1F2F3 + \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index 3ef64030..1280cb6a 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -5,7 +5,7 @@ @drawable/rn_edit_text_material -