在Android上从SD卡加载ReactNative捆绑包

时间:2018-08-06 08:27:11

标签: android react-native android-permissions android-sdcard

我对简单的本机应用程序有疑问。它在活动内部运行默认包(通过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,但这不是我想要的。我需要能够将捆绑软件放入外部存储器。

创建实例管理器或应用程序委托有什么用吗?

0 个答案:

没有答案