From a470e93089a5bf7e39c7504ad5772b6482101b7a Mon Sep 17 00:00:00 2001 From: zeemyself Date: Fri, 12 Jun 2026 14:57:39 +0700 Subject: [PATCH 1/3] Migrate library to React Native New Architecture (TurboModules) --- android/build.gradle | 46 +++++++++--- .../powermanager/RNPowermanagerModule.java | 74 ------------------- .../RNPowermanagerModuleImpl.java | 56 ++++++++++++++ .../powermanager/RNPowermanagerPackage.java | 46 +++++++----- .../powermanager/RNPowermanagerModule.java | 29 ++++++++ .../powermanager/RNPowermanagerModule.java | 31 ++++++++ index.js | 25 +++++-- package.json | 10 ++- src/NativeRNPowermanager.ts | 11 +++ 9 files changed, 221 insertions(+), 107 deletions(-) delete mode 100644 android/src/main/java/com/zeemyself/powermanager/RNPowermanagerModule.java create mode 100644 android/src/main/java/com/zeemyself/powermanager/RNPowermanagerModuleImpl.java create mode 100644 android/src/newarch/java/com/zeemyself/powermanager/RNPowermanagerModule.java create mode 100644 android/src/oldarch/java/com/zeemyself/powermanager/RNPowermanagerModule.java create mode 100644 src/NativeRNPowermanager.ts diff --git a/android/build.gradle b/android/build.gradle index 1436845..a90e17d 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,37 +1,65 @@ +def isNewArchitectureEnabled() { + return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" +} buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' + classpath 'com.android.tools.build:gradle:7.4.2' } } apply plugin: 'com.android.library' +if (isNewArchitectureEnabled()) { + apply plugin: 'com.facebook.react' +} + android { - compileSdkVersion 27 - buildToolsVersion "28.0.3" + compileSdkVersion 34 + buildToolsVersion "34.0.0" defaultConfig { - minSdkVersion 16 - targetSdkVersion 22 + minSdkVersion 21 + targetSdkVersion 34 versionCode 1 versionName "1.0" + + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() } + + sourceSets { + main { + if (isNewArchitectureEnabled()) { + java.srcDirs += ['src/newarch/java'] + } else { + java.srcDirs += ['src/oldarch/java'] + } + } + } + + buildFeatures { + buildConfig true + } + lintOptions { abortOnError false } } repositories { + google() mavenCentral() } dependencies { - implementation 'com.facebook.react:react-native:+' -} - \ No newline at end of file + if (isNewArchitectureEnabled()) { + // RNGP handles dependencies under New Architecture + } else { + implementation 'com.facebook.react:react-native:+' + } +} \ No newline at end of file diff --git a/android/src/main/java/com/zeemyself/powermanager/RNPowermanagerModule.java b/android/src/main/java/com/zeemyself/powermanager/RNPowermanagerModule.java deleted file mode 100644 index ae7ce67..0000000 --- a/android/src/main/java/com/zeemyself/powermanager/RNPowermanagerModule.java +++ /dev/null @@ -1,74 +0,0 @@ - -package com.zeemyself.powermanager; - -import android.content.ComponentName; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; - -import java.util.HashMap; -import java.util.Map; - - -public class RNPowermanagerModule extends ReactContextBaseJavaModule { - - private final ReactApplicationContext reactContext; - - public RNPowermanagerModule(ReactApplicationContext reactContext) { - super(reactContext); - this.reactContext = reactContext; - } - - @Override - public String getName() { - return "RNPowermanager"; - } - - - private static final Intent[] POWERMANAGER_INTENTS = - { - new Intent().setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")), - new Intent().setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")), - new Intent().setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")), - // new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")), - // new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.StartupAppListActivity")), - new Intent().setComponent(new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity")), - new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity")), - new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.BgStartUpManager")), - new Intent().setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")), - new Intent().setComponent(new ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.entry.FunctionActivity")).setData(Uri.parse("mobilemanager://function/entry/AutoStart")), - new Intent().setComponent(new ComponentName("com.samsung.android.lool", "com.samsung.android.sm.ui.battery.BatteryActivity")) - }; - - @ReactMethod - public void startPowerManager() { - for (Intent intent : POWERMANAGER_INTENTS) - if (reactContext.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) { - // show dialog to ask user action - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - reactContext.startActivity(intent); - break; - } - } - - public Boolean isSupported() { - for (Intent intent : POWERMANAGER_INTENTS) { - if (reactContext.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) { - return true; - } - } - return false; - } - - @Override - public Map getConstants() { - final Map constants = new HashMap<>(); - constants.put("isSupported", isSupported()); - return constants; - } - -} diff --git a/android/src/main/java/com/zeemyself/powermanager/RNPowermanagerModuleImpl.java b/android/src/main/java/com/zeemyself/powermanager/RNPowermanagerModuleImpl.java new file mode 100644 index 0000000..1e89382 --- /dev/null +++ b/android/src/main/java/com/zeemyself/powermanager/RNPowermanagerModuleImpl.java @@ -0,0 +1,56 @@ +package com.zeemyself.powermanager; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import com.facebook.react.bridge.ReactApplicationContext; +import java.util.Map; +import java.util.HashMap; + +public class RNPowermanagerModuleImpl { + public static final String NAME = "RNPowermanager"; + + private final ReactApplicationContext reactContext; + + public RNPowermanagerModuleImpl(ReactApplicationContext reactContext) { + this.reactContext = reactContext; + } + + private static final Intent[] POWERMANAGER_INTENTS = { + new Intent().setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")), + new Intent().setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")), + new Intent().setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")), + new Intent().setComponent(new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity")), + new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity")), + new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.BgStartUpManager")), + new Intent().setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")), + new Intent().setComponent(new ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.entry.FunctionActivity")).setData(Uri.parse("mobilemanager://function/entry/AutoStart")), + new Intent().setComponent(new ComponentName("com.samsung.android.lool", "com.samsung.android.sm.ui.battery.BatteryActivity")) + }; + + public void startPowerManager() { + for (Intent intent : POWERMANAGER_INTENTS) { + if (reactContext.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + reactContext.startActivity(intent); + break; + } + } + } + + public Boolean isSupported() { + for (Intent intent : POWERMANAGER_INTENTS) { + if (reactContext.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) { + return true; + } + } + return false; + } + + public Map getConstants() { + final Map constants = new HashMap<>(); + constants.put("isSupported", isSupported()); + return constants; + } +} diff --git a/android/src/main/java/com/zeemyself/powermanager/RNPowermanagerPackage.java b/android/src/main/java/com/zeemyself/powermanager/RNPowermanagerPackage.java index 6336644..08ec7f6 100644 --- a/android/src/main/java/com/zeemyself/powermanager/RNPowermanagerPackage.java +++ b/android/src/main/java/com/zeemyself/powermanager/RNPowermanagerPackage.java @@ -1,27 +1,39 @@ package com.zeemyself.powermanager; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import com.facebook.react.ReactPackage; +import com.facebook.react.TurboReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; -import com.facebook.react.bridge.JavaScriptModule; -public class RNPowermanagerPackage implements ReactPackage { - @Override - public List createNativeModules(ReactApplicationContext reactContext) { - return Arrays.asList(new RNPowermanagerModule(reactContext)); - } +import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; +import java.util.HashMap; +import java.util.Map; - // Deprecated from RN 0.47 - public List> createJSModules() { - return Collections.emptyList(); +public class RNPowermanagerPackage extends TurboReactPackage { + + @Override + public NativeModule getModule(String name, ReactApplicationContext reactContext) { + if (name.equals(RNPowermanagerModuleImpl.NAME)) { + return new RNPowermanagerModule(reactContext); + } + return null; } @Override - public List createViewManagers(ReactApplicationContext reactContext) { - return Collections.emptyList(); + public ReactModuleInfoProvider getReactModuleInfoProvider() { + return () -> { + final Map moduleInfos = new HashMap<>(); + boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + moduleInfos.put( + RNPowermanagerModuleImpl.NAME, + new ReactModuleInfo( + RNPowermanagerModuleImpl.NAME, + RNPowermanagerModuleImpl.NAME, + false, // canOverrideExistingModule + false, // needsEagerInit + false, // isCxxModule + isTurboModule // isTurboModule + )); + return moduleInfos; + }; } } \ No newline at end of file diff --git a/android/src/newarch/java/com/zeemyself/powermanager/RNPowermanagerModule.java b/android/src/newarch/java/com/zeemyself/powermanager/RNPowermanagerModule.java new file mode 100644 index 0000000..26c385e --- /dev/null +++ b/android/src/newarch/java/com/zeemyself/powermanager/RNPowermanagerModule.java @@ -0,0 +1,29 @@ +package com.zeemyself.powermanager; + +import com.facebook.react.bridge.ReactApplicationContext; +import java.util.Map; + +public class RNPowermanagerModule extends NativeRNPowermanagerSpec { + + private final RNPowermanagerModuleImpl delegate; + + public RNPowermanagerModule(ReactApplicationContext reactContext) { + super(reactContext); + this.delegate = new RNPowermanagerModuleImpl(reactContext); + } + + @Override + public String getName() { + return RNPowermanagerModuleImpl.NAME; + } + + @Override + public void startPowerManager() { + delegate.startPowerManager(); + } + + @Override + protected Map getTypedExportedConstants() { + return delegate.getConstants(); + } +} diff --git a/android/src/oldarch/java/com/zeemyself/powermanager/RNPowermanagerModule.java b/android/src/oldarch/java/com/zeemyself/powermanager/RNPowermanagerModule.java new file mode 100644 index 0000000..95a6b5f --- /dev/null +++ b/android/src/oldarch/java/com/zeemyself/powermanager/RNPowermanagerModule.java @@ -0,0 +1,31 @@ +package com.zeemyself.powermanager; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import java.util.Map; + +public class RNPowermanagerModule extends ReactContextBaseJavaModule { + + private final RNPowermanagerModuleImpl delegate; + + public RNPowermanagerModule(ReactApplicationContext reactContext) { + super(reactContext); + this.delegate = new RNPowermanagerModuleImpl(reactContext); + } + + @Override + public String getName() { + return RNPowermanagerModuleImpl.NAME; + } + + @ReactMethod + public void startPowerManager() { + delegate.startPowerManager(); + } + + @Override + public Map getConstants() { + return delegate.getConstants(); + } +} diff --git a/index.js b/index.js index 558d456..fb74b8c 100644 --- a/index.js +++ b/index.js @@ -1,17 +1,30 @@ import { NativeModules, Platform } from 'react-native'; -const { RNPowermanager } = NativeModules; +const isTurboModuleEnabled = global.__turboModuleProxy != null; + +const RNPowermanager = isTurboModuleEnabled + ? require('./src/NativeRNPowermanager').default + : NativeModules.RNPowermanager; + +// Cache constants for isSupported if RNPowermanager exists +const constants = RNPowermanager + ? (typeof RNPowermanager.getConstants === 'function' + ? RNPowermanager.getConstants() + : RNPowermanager) + : null; export default PowerManager = { startPowerManager: () => { - if(Platform.OS === 'android') { - return RNPowermanager.startPowerManager() + if (Platform.OS === 'android' && RNPowermanager) { + return RNPowermanager.startPowerManager(); } }, isSupported: () => { - if(Platform.OS === 'android') { - return RNPowermanager.isSupported + if (Platform.OS === 'android' && constants) { + return constants.isSupported; } + return false; } -} +}; + diff --git a/package.json b/package.json index 2430269..3985392 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,19 @@ "author": "zeemyself", "license": "ISC", "peerDependencies": { - "react-native": ">=0.60.0" + "react-native": ">=0.71.0" }, "devDependencies": { "standard-version": "^9.5.0" }, + "codegenConfig": { + "name": "RNPowermanagerSpec", + "type": "modules", + "jsSrcsDir": "src", + "android": { + "javaPackageName": "com.zeemyself.powermanager" + } + }, "repository": { "type": "git", "url": "git+https://github.com/zeemyself/react-native-powermanager.git" diff --git a/src/NativeRNPowermanager.ts b/src/NativeRNPowermanager.ts new file mode 100644 index 0000000..1b0b47a --- /dev/null +++ b/src/NativeRNPowermanager.ts @@ -0,0 +1,11 @@ +import type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; + +export interface Spec extends TurboModule { + startPowerManager(): void; + getConstants(): { + isSupported: boolean; + }; +} + +export default TurboModuleRegistry.getEnforcing('RNPowermanager'); From a1e909196cfd4a6cde2447e836efcc4a6b9dae0d Mon Sep 17 00:00:00 2001 From: zeemyself Date: Fri, 12 Jun 2026 15:03:42 +0700 Subject: [PATCH 2/3] fix: address new architecture migration review issues - Remove deprecated __turboModuleProxy detection in index.js, use TurboModuleRegistry directly - Change TurboModuleRegistry.getEnforcing to .get to avoid iOS crash - Add @Nullable annotation to oldarch getConstants() override - Add namespace in build.gradle for AGP 8+ compatibility - Fix missing trailing newlines in build.gradle and RNPowermanagerPackage.java --- android/build.gradle | 1 + .../zeemyself/powermanager/RNPowermanagerModule.java | 2 ++ index.js | 10 ++-------- src/NativeRNPowermanager.ts | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index a90e17d..3ab3043 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -20,6 +20,7 @@ if (isNewArchitectureEnabled()) { } android { + namespace "com.zeemyself.powermanager" compileSdkVersion 34 buildToolsVersion "34.0.0" diff --git a/android/src/oldarch/java/com/zeemyself/powermanager/RNPowermanagerModule.java b/android/src/oldarch/java/com/zeemyself/powermanager/RNPowermanagerModule.java index 95a6b5f..7dffc40 100644 --- a/android/src/oldarch/java/com/zeemyself/powermanager/RNPowermanagerModule.java +++ b/android/src/oldarch/java/com/zeemyself/powermanager/RNPowermanagerModule.java @@ -3,6 +3,7 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; +import androidx.annotation.Nullable; import java.util.Map; public class RNPowermanagerModule extends ReactContextBaseJavaModule { @@ -24,6 +25,7 @@ public void startPowerManager() { delegate.startPowerManager(); } + @Nullable @Override public Map getConstants() { return delegate.getConstants(); diff --git a/index.js b/index.js index fb74b8c..eccb411 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,6 @@ -import { NativeModules, Platform } from 'react-native'; - -const isTurboModuleEnabled = global.__turboModuleProxy != null; - -const RNPowermanager = isTurboModuleEnabled - ? require('./src/NativeRNPowermanager').default - : NativeModules.RNPowermanager; +import { Platform } from 'react-native'; +import RNPowermanager from './src/NativeRNPowermanager'; // Cache constants for isSupported if RNPowermanager exists const constants = RNPowermanager @@ -27,4 +22,3 @@ export default PowerManager = { return false; } }; - diff --git a/src/NativeRNPowermanager.ts b/src/NativeRNPowermanager.ts index 1b0b47a..47d115c 100644 --- a/src/NativeRNPowermanager.ts +++ b/src/NativeRNPowermanager.ts @@ -8,4 +8,4 @@ export interface Spec extends TurboModule { }; } -export default TurboModuleRegistry.getEnforcing('RNPowermanager'); +export default TurboModuleRegistry.get('RNPowermanager'); From 05cc6b3d9a4b0874d321b0fe4e85ac4b9b63ccf5 Mon Sep 17 00:00:00 2001 From: zeemyself Date: Fri, 12 Jun 2026 20:44:29 +0700 Subject: [PATCH 3/3] chore: raise react-native peer dependency to >=0.77.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 6-arg ReactModuleInfo constructor (without hasConstants) used in RNPowermanagerPackage.java only exists in RN >=0.77. The previous minimum of >=0.71.0 would cause Android compilation failures for apps on RN 0.71–0.76. BREAKING CHANGE: drops support for react-native <0.77.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3985392..f9185e8 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "author": "zeemyself", "license": "ISC", "peerDependencies": { - "react-native": ">=0.71.0" + "react-native": ">=0.77.0" }, "devDependencies": { "standard-version": "^9.5.0"