从React-Native代码调用Android活动 [英] Call Android activity from React-Native code

查看:89
本文介绍了从React-Native代码调用Android活动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用REACT-NATIVE来构建android应用. 我想从React-Native代码中调用android活动. (例如,当我单击我的React本机代码中的按钮时,它应该调用android活动)

我有4个课程文件

  • MainActivity.java(在Android Studio中打开时由react-native创建)
  • MainApplication.java(由react-native创建)
  • Login.java(Android活动文件)
  • Example.java(Android活动文件)

想要实现以下流程:

Login.java-> React-Native js-> Example.java

我已经浏览了以下链接,但无法理解

https://stackoverflow.com/a/32825290/4849554

在这里问类似的问题

React Native Android:显示来自Java的活动

解决方案

要启动Android活动,您需要创建一个自定义的本机模块.假设一个叫ActivityStarter;可以按如下方式在JavaScript中使用它:

import { ..., NativeModules, ... } from 'react-native';

export default class DemoComponent extends Component {
    render() {
        return (
        <View>
            <Button
                onPress={() => NativeModules.ActivityStarter.navigateToExample()}
                title='Start example activity'
            />
        </View>
        );
    }
}

ActivityStarter只是一个Java类,实现了称为NativeModule的React Native Java接口.该接口的繁重工作已经由BaseJavaModule完成,因此通常可以扩展为那个或ReactContextBaseJavaModule:

class ActivityStarterModule extends ReactContextBaseJavaModule {

    ActivityStarterModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "ActivityStarter";
    }

    @ReactMethod
    void navigateToExample() {
        ReactApplicationContext context = getReactApplicationContext();
        Intent intent = new Intent(context, ExampleActivity.class);
        context.startActivity(intent);
    }
}

该类的名称无关紧要; JavaScript公开的ActivityStarter模块名称来自getName()方法.

react-native init生成的默认应用程序包含一个MainApplication类,用于初始化React Native.它扩展了ReactNativeHost以覆盖其getPackages方法:

@Override
protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            new MainReactPackage()
    );
}

如果您要将React Native添加到现有应用程序,请

注意addPackage(new MainReactPackage()).无论使用哪种方法,都需要添加一个自定义包以公开我们的自定义模块.可能看起来像这样:

class ActivityStarterReactPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new ActivityStarterModule(reactContext));
        return modules;
    }

    // UPDATE: This method was deprecated in 0.47
    // @Override
    // public List<Class<? extends JavaScriptModule>> createJSModules() {
    //     return Collections.emptyList();
    // }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

最后,更新MainApplication以包括我们的新软件包:

@Override
protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            new ActivityStarterReactPackage(), // This is it!
            new MainReactPackage()
    );
}

或者您可以addPackage(new ActivityStartecReactPackage())ReactInstanceManager.builder().

您可以在此处找到完整,独立的示例. >


更新

createJSModules已从版本0.47的ReactPackage界面中删除,并已从示例中删除.如果由于某种原因而使用旧版本的RN,您仍然会需要它.


2019年3月更新

示例项目现在支持iOS的类似功能.

I am using REACT-NATIVE to build android app. I want to call android activity from React-Native code. (say when I clicked the button in my react native code, it should call android activity)

I have 4 class files

  • MainActivity.java (created by react-native when opened in android studio)
  • MainApplication.java (created by react-native)
  • Login.java (android activity file)
  • Example.java (android activity file)

Want to achieve following flow:

Login.java -> React-Native js -> Example.java

I already went through following links, but unable to understand

https://stackoverflow.com/a/32825290/4849554

Similar question asked here

React Native Android: Showing an Activity from Java

解决方案

To start an Android activity, you need to create a custom native module. Assume one called ActivityStarter; it might be used from JavaScript as follows:

import { ..., NativeModules, ... } from 'react-native';

export default class DemoComponent extends Component {
    render() {
        return (
        <View>
            <Button
                onPress={() => NativeModules.ActivityStarter.navigateToExample()}
                title='Start example activity'
            />
        </View>
        );
    }
}

ActivityStarter is just a Java class that implements a React Native Java interface called NativeModule. The heavy lifting of this interface is already done by BaseJavaModule, so one normally extends either that one or ReactContextBaseJavaModule:

class ActivityStarterModule extends ReactContextBaseJavaModule {

    ActivityStarterModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "ActivityStarter";
    }

    @ReactMethod
    void navigateToExample() {
        ReactApplicationContext context = getReactApplicationContext();
        Intent intent = new Intent(context, ExampleActivity.class);
        context.startActivity(intent);
    }
}

The name of this class doesn't matter; the ActivityStarter module name exposed to JavaScript comes from the getName() method.

The default app generated by react-native init contains a MainApplication class that initializes React Native. Among other things it extends ReactNativeHost to override its getPackages method:

@Override
protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            new MainReactPackage()
    );
}

If you're adding React Native to an existing app, this page has you override your Activity's onCreate as follows:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mReactRootView = new ReactRootView(this);
    mReactInstanceManager = ReactInstanceManager.builder()
            .setApplication(getApplication())
            .setBundleAssetName("index.android.bundle")
            .setJSMainModuleName("index.android")
            .addPackage(new MainReactPackage())
            .setUseDeveloperSupport(BuildConfig.DEBUG)
            .setInitialLifecycleState(LifecycleState.RESUMED)
            .build();
    mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorld", null);

    setContentView(mReactRootView);
}

Note addPackage(new MainReactPackage()). Regardless of which approach you use, you need to add a custom package that exposes our custom module. It might look like this:

class ActivityStarterReactPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new ActivityStarterModule(reactContext));
        return modules;
    }

    // UPDATE: This method was deprecated in 0.47
    // @Override
    // public List<Class<? extends JavaScriptModule>> createJSModules() {
    //     return Collections.emptyList();
    // }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

Finally, update MainApplication to include our new package:

@Override
protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            new ActivityStarterReactPackage(), // This is it!
            new MainReactPackage()
    );
}

Or you can do addPackage(new ActivityStartecReactPackage()) to ReactInstanceManager.builder().

You can find a complete, self-contained example here.


UPDATE

createJSModules was removed from the ReactPackage interface in version 0.47, and has been commented out of the sample. You'll still need it if you're stuck with an older version of RN for some reason.


UPDATE MARCH 2019

The sample project now supports similar functionality for iOS.

这篇关于从React-Native代码调用Android活动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆