我对简单的本机应用程序有疑问。它在活动内部运行默认包(通过react-native init
创建的经过稍微修改的js代码)。事实是,我希望能够“动态”切换捆绑代码,因此我将其保留在sdcard上。
我遇到的问题是,启动后向应用程序(READ_EXTERNAL_STORAGE
)授予权限后,react-native似乎没有启动。我必须终止该应用程序,然后重新启动它,以使捆绑包正确加载并显示基于反应本机的ui。
这是我的代码:
MainActivity
(应该显示RN ui的一个):
public class MainActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private ReactAppDelegate mDelegate;
private com.karumi.dexter.listener.single.PermissionListener listener;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
listener = DialogOnDeniedPermissionListener.Builder
.withContext(this)
.withTitle("Error")
.withMessage("Please grant access to storage to use the app.")
.withButtonText("Ok")
.build();
Log.d(TAG, "checking perm");
Dexter.withActivity(this)
.withPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
.withListener(listener)
.check();
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_DENIED) {
//start react
Log.d(TAG, "have perm, onCreate delegate");
getActivityDelegate().onCreate(savedInstanceState);
}
}
@Override
protected void onPause() {
Log.d(TAG, "onPause");
super.onPause();
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_DENIED) {
getActivityDelegate().onPause();
}
}
@Override
protected void onResume() {
Log.d(TAG, "onResume");
super.onResume();
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_DENIED) {
//start react
Log.d(TAG, "have perm, onResume delegate");
getActivityDelegate().onResume();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_DENIED) {
getActivityDelegate().onDestroy();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_DENIED) {
getActivityDelegate().onActivityResult(requestCode, resultCode, data);
}
}
@Override
public void requestPermissions(
String[] permissions,
int requestCode,
PermissionListener listener) {
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_DENIED) {
getActivityDelegate().requestPermissions(permissions, requestCode, listener);
}
}
@Override
public void onRequestPermissionsResult(
int requestCode,
String[] permissions,
int[] grantResults) {
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_DENIED) {
getActivityDelegate().onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private ReactAppDelegate getActivityDelegate() {
if (mDelegate == null) {
mDelegate = createReactActivityDelegate();
}
return mDelegate;
}
protected ReactAppDelegate createReactActivityDelegate() {
Bundle initialProps = null;
Log.d(TAG, "createReactActivityDelegate");
return new ReactAppDelegate(this, getMainComponentName(), initialProps);
}
protected String getMainComponentName() {
return "ReactApp";
}
}
在ReactAppDelegate
中使用的 MainActivity
public class ReactAppDelegate extends ReactActivityDelegate {
private static final String TAG = ReactAppDelegate.class.getSimpleName();
private Bundle initialProps;
@Inject
protected ReactNativeHost reactNativeHost;
public ReactAppDelegate(Activity activity, @Nullable String mainComponentName, Bundle initialProps) {
super(activity, mainComponentName);
this.initialProps = initialProps;
MainApplication.getInstance().getAppComponent().inject(this);
}
@Nullable
@Override
public Bundle getLaunchOptions() {
return initialProps;
}
@Override
public ReactNativeHost getReactNativeHost() {
return this.reactNativeHost;
}
@Override
public boolean onNewIntent(Intent intent) {
Log.d(TAG, "new intent extras:" + intent.getExtras());
return super.onNewIntent(intent);
}
}
最后是将ReactNativeHost
注入ReactAppDelegate
的匕首模块
@Module
public class ReactNativeModule {
@Singleton
@Provides
public ReactNativeHost provideReactNativeHost(final Application application) {
return new ReactNativeHost(application) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new ArrayList<>();
packages.add(new MainReactPackage());
packages.add(new AppReactPackage());
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@Nullable
@Override
protected String getJSBundleFile() {
File sd = Environment.getExternalStorageDirectory();
File bundleDir = new File(sd,"react_bundles");
File bundle = new File(bundleDir, "index.android.bundle");
return bundle.getAbsolutePath();
}
@Nullable
@Override
protected String getBundleAssetName() {
return super.getBundleAssetName();
}
@Override
protected ReactInstanceManager createReactInstanceManager() {
ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_START);
ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
.setApplication(MainApplication.getInstance())
.setJSMainModulePath(getJSMainModuleName())
.setUseDeveloperSupport(getUseDeveloperSupport())
.setRedBoxHandler(getRedBoxHandler())
.setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
.setUIImplementationProvider(getUIImplementationProvider())
.setJSIModulesPackage(getJSIModulePackage())
.setInitialLifecycleState(LifecycleState.RESUMED);
for (ReactPackage reactPackage : getPackages()) {
builder.addPackage(reactPackage);
}
String jsBundleFile = getJSBundleFile();
if (jsBundleFile != null) {
builder.setJSBundleFile(jsBundleFile);
} else {
builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName()));
}
ReactInstanceManager reactInstanceManager = builder.build();
ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_END);
reactInstanceManager.createReactContextInBackground();
return reactInstanceManager;
}
};
}
}
这里的index.js文件中的内容无关紧要,捆绑包包含由React打包程序吐出的内容(可以在运行本地节点服务器时用于调试的相同内容)。
我知道我可以将捆绑软件放入assets
目录中,或使用例如。 codepush,但这不是我想要的。我需要能够将捆绑软件放入外部存储器。
创建实例管理器或应用程序委托有什么用吗?