Android原生项目集成React Native

转载https://blog.csdn.net/xiangzhihong8/article/details/80594483

最近,很多的公司,特别是小公司、小项目,为了解决人力成本的问题,都开发将移动原生开发转到了跨平台开发,或者原生+h5的混合开发,今天要说的是如何在原生项目中集成React Native。

如果是一个新项目,并且以应用为主的,大可以使用React Native来进行开发,关于这方面的内容,不做讲解,读者可以查看我之前的博客,或者阅读《React Native移动开发实战》。

1,安装React Native

首先,在你的安卓项目的根目录下执行如下命令:

npm init
  • 1

操作完成之后,在你的Android项目根目录下会出现一个package.json文件。 
这里写图片描述 
package.json主要是项目的RN的依赖配置文件,其内容如下:

{
  "name": "kingtv",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node node_modules/react-native/local-cli/cli.js start"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^16.4.0",
    "react-native": "^0.51.1"
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

从配置信息可以看出,react安装的是16.4.0,react-native安装的是0.51.1。然后执行命令:

 npm install
  • 1

此时,你会发现Android项目根目录下多了一个node_modules文件夹。 
然后使用如下命令安装React和React Native

npm install -save react
npm install -save react-native
  • 1
  • 2

2,依赖添加

配置Android项目react-native依赖库:

compile"com.facebook.react:react-native:+"//(+号代表使用最新版本)
  • 1

然后,添加NDK支持。

ndk {
   abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
}
  • 1
  • 2
  • 3

这里借用网络的一张图,我原生的项目的依赖比较多。 
这里写图片描述

然后在项目的根目录下的build.gradle中添加maven配置。

maven {
      url "$rootDir/node_modules/react-native/android"
    }
  • 1
  • 2
  • 3

如果上面配置的时候报如下错误:

Error:Conflict with dependency 'com.google.code.findbugs:jsr305' in project ':app'. Resolved versions for app (3.0.0) and test app (2.0.1) differ. See http://g.co/androidstudio/app-test-app-conflict for details.
  • 1

请将下面的配置添加到app的build.gradle,配置的脚本信息如下:

android {
    configurations.all {
        resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5

到此,React Native的相关环境就配置完成了,接下来就可以编写代码了,下面我们以一个原生的页面跳转到React Native页面为例。

3, 实例

1、Application修改

想要项目中使用React Native,需要重写ReactNativeHost,一般的写法是直接在Application中做如下的添加。

public class RNApplication extends Application implements ReactApplication {

private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
        //注意:BuildConfig需要导入自己项目包名下的BuildConfig
        return BuildConfig.DEBUG;
    }

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

@Override
public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
}

@Override
public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

但是,由于我的项目的Application中的配置比较多,所以我将上的配置部分单独抽取出来,也就是下面的方式。 
这里写图片描述

2,创建index.android.js文件

然后我们在项目的根目录下创建index.android.js文件,文件的内容如下:

import React from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

class HelloWorld extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.hello}>Hello, 我是React Native</Text>
      </View>
    )
  }
}
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

AppRegistry.registerComponent('ReactHost', () => HelloWorld);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

3,绑定原生界面

方法一

想要通过原生代码调用 React Native页面 ,我们需要在一个 Activity 中创建一个 ReactRootView 对象,将它关联一个 React application ,并将该界面设置为主视图。例如,ReactActivity的源码如下:

public class ReactHostActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    @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();

        // 注意这里的react-example必须对应“index.android.js”中的
        // “AppRegistry.registerComponent()”的第一个参数
        mReactRootView.startReactApplication(mReactInstanceManager, "ReactHost", null);

        setContentView(mReactRootView);
    }

    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostPause(this);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostResume(this, this);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostDestroy();
        }
    }

    @Override
    public void onBackPressed() {
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onBackPressed();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

方法二

当然也可以使用继承自ReactActivity,然后重写getMainComponentName()即可。

public class ReactHostActivity extends ReactActivity  {
    @Nullable
    @Override
    protected String getMainComponentName() {
        return "ReactHost";
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意这里的返回组件的名称和index.js文件中名称的对于关系。例如:

AppRegistry.registerComponent('ReactHost', () => ReactHost);
  • 1

由于ReactActivity 的许多组件都使用了 Theme.AppCompat.Light.NoActionBar这一主题 ,所以需要将ReactHostActivity的主题设置为Theme.AppCompat.Light.NoActionBar。

<activity 
      android:name=".ReactHostActivity"
      android:label="@string/app_name"
      android:theme="@style/Theme.AppCompat.Light.NoActionBar">
        </activity>
  • 1
  • 2
  • 3
  • 4
  • 5

4,配置权限

如果你的项目还没有添加如下权限,需要先添加如下的权限。

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
  • 1
  • 2

为了简单,我们给原生项目的设置页面绑定一个跳转事件,使用Intent方式先跳转到ReactHostActivity页面即可。如图: 
这里写图片描述

5,启动云运行

要想运行混合的项目,需要先启动开发服务器(Packager),也就是启动React Native相关的环境,启动的命令如下:

npm start
  • 1

然后在Android Studio中启动Android原生项目,不出意外的话,当你点击项目的设置按钮的时候,将会看到js的加载渲染,不错这就是React Native在在加载js。 
这里写图片描述

这里写图片描述

到此,简单集成就ok了,然后就可以使用React Native愉快的开发了,下面给大家提供一个完整的RN学习项目:React Native美团项目

同时,如果大家在集成过程中遇到什么问题,欢迎大家留意,我会第一时间回复。

附:Android原生集成RN源码

转载https://blog.csdn.net/xiangzhihong8/article/details/80594483

最近,很多的公司,特别是小公司、小项目,为了解决人力成本的问题,都开发将移动原生开发转到了跨平台开发,或者原生+h5的混合开发,今天要说的是如何在原生项目中集成React Native。

如果是一个新项目,并且以应用为主的,大可以使用React Native来进行开发,关于这方面的内容,不做讲解,读者可以查看我之前的博客,或者阅读《React Native移动开发实战》。

1,安装React Native

首先,在你的安卓项目的根目录下执行如下命令:

npm init
  • 1

操作完成之后,在你的Android项目根目录下会出现一个package.json文件。 
这里写图片描述 
package.json主要是项目的RN的依赖配置文件,其内容如下:

{
  "name": "kingtv",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node node_modules/react-native/local-cli/cli.js start"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^16.4.0",
    "react-native": "^0.51.1"
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

从配置信息可以看出,react安装的是16.4.0,react-native安装的是0.51.1。然后执行命令:

 npm install
  • 1

此时,你会发现Android项目根目录下多了一个node_modules文件夹。 
然后使用如下命令安装React和React Native

npm install -save react
npm install -save react-native
  • 1
  • 2

2,依赖添加

配置Android项目react-native依赖库:

compile"com.facebook.react:react-native:+"//(+号代表使用最新版本)
  • 1

然后,添加NDK支持。

ndk {
   abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
}
  • 1
  • 2
  • 3

这里借用网络的一张图,我原生的项目的依赖比较多。 
这里写图片描述

然后在项目的根目录下的build.gradle中添加maven配置。

maven {
      url "$rootDir/node_modules/react-native/android"
    }
  • 1
  • 2
  • 3

如果上面配置的时候报如下错误:

Error:Conflict with dependency 'com.google.code.findbugs:jsr305' in project ':app'. Resolved versions for app (3.0.0) and test app (2.0.1) differ. See http://g.co/androidstudio/app-test-app-conflict for details.
  • 1

请将下面的配置添加到app的build.gradle,配置的脚本信息如下:

android {
    configurations.all {
        resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5

到此,React Native的相关环境就配置完成了,接下来就可以编写代码了,下面我们以一个原生的页面跳转到React Native页面为例。

3, 实例

1、Application修改

想要项目中使用React Native,需要重写ReactNativeHost,一般的写法是直接在Application中做如下的添加。

public class RNApplication extends Application implements ReactApplication {

private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
        //注意:BuildConfig需要导入自己项目包名下的BuildConfig
        return BuildConfig.DEBUG;
    }

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

@Override
public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
}

@Override
public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

但是,由于我的项目的Application中的配置比较多,所以我将上的配置部分单独抽取出来,也就是下面的方式。 
这里写图片描述

2,创建index.android.js文件

然后我们在项目的根目录下创建index.android.js文件,文件的内容如下:

import React from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

class HelloWorld extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.hello}>Hello, 我是React Native</Text>
      </View>
    )
  }
}
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

AppRegistry.registerComponent('ReactHost', () => HelloWorld);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

3,绑定原生界面

方法一

想要通过原生代码调用 React Native页面 ,我们需要在一个 Activity 中创建一个 ReactRootView 对象,将它关联一个 React application ,并将该界面设置为主视图。例如,ReactActivity的源码如下:

public class ReactHostActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    @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();

        // 注意这里的react-example必须对应“index.android.js”中的
        // “AppRegistry.registerComponent()”的第一个参数
        mReactRootView.startReactApplication(mReactInstanceManager, "ReactHost", null);

        setContentView(mReactRootView);
    }

    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostPause(this);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostResume(this, this);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostDestroy();
        }
    }

    @Override
    public void onBackPressed() {
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onBackPressed();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

方法二

当然也可以使用继承自ReactActivity,然后重写getMainComponentName()即可。

public class ReactHostActivity extends ReactActivity  {
    @Nullable
    @Override
    protected String getMainComponentName() {
        return "ReactHost";
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意这里的返回组件的名称和index.js文件中名称的对于关系。例如:

AppRegistry.registerComponent('ReactHost', () => ReactHost);
  • 1

由于ReactActivity 的许多组件都使用了 Theme.AppCompat.Light.NoActionBar这一主题 ,所以需要将ReactHostActivity的主题设置为Theme.AppCompat.Light.NoActionBar。

<activity 
      android:name=".ReactHostActivity"
      android:label="@string/app_name"
      android:theme="@style/Theme.AppCompat.Light.NoActionBar">
        </activity>
  • 1
  • 2
  • 3
  • 4
  • 5

4,配置权限

如果你的项目还没有添加如下权限,需要先添加如下的权限。

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
  • 1
  • 2

为了简单,我们给原生项目的设置页面绑定一个跳转事件,使用Intent方式先跳转到ReactHostActivity页面即可。如图: 
这里写图片描述

5,启动云运行

要想运行混合的项目,需要先启动开发服务器(Packager),也就是启动React Native相关的环境,启动的命令如下:

npm start
  • 1

然后在Android Studio中启动Android原生项目,不出意外的话,当你点击项目的设置按钮的时候,将会看到js的加载渲染,不错这就是React Native在在加载js。 
这里写图片描述

这里写图片描述

到此,简单集成就ok了,然后就可以使用React Native愉快的开发了,下面给大家提供一个完整的RN学习项目:React Native美团项目

同时,如果大家在集成过程中遇到什么问题,欢迎大家留意,我会第一时间回复。

附:Android原生集成RN源码

猜你喜欢

转载自blog.csdn.net/sinat_17775997/article/details/81030804