Android项目引入RN的步骤

之前在学习RN时,创建RN项目一般都是通过react-native init xxx来实现。最近需要在项目中运用到RN,查看官网的说明也不是很详细,网上也有很多帖子,但是也遇到很多坑,这篇主要是记录一下项目添加RN的步骤以及过程中遇的到问题和解决方法。都是固定的套路和步骤,没有太多技术含量,记录一下。

首先肯定是需要配置RN开发环境,这里就不再累赘。

一、项目根目录创建package.json

cmd或者Terminal进入项目根目录,通过npm init依次输入name(不能为大写) description author password等等,其中的name最为重要,其他的可以不用写。这个name对应接下来注册用到的必须一致,否则运行时会出现Module AppRegistry is not a registered callable moduleundefined is not an object(ecaluating 'ReactInternals.ReactCurrentOwner')的错误。完成后会生成一个如下所示的json文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"name": "aspactjdemo",
"version": "1.0.0",
"description": "aspactjdemo",
"main": "index.js",
"scripts": {
// 注意:这行启动脚本,生成json时并没有,需要手动粘贴上,粘贴时注意遵循json格式
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "jzm",
"license": "ISC",
"dependencies": {
"react": "^15.6.1",
"react-native": "^0.47.2"
}
}

二、添加react和react-native 模块

在根目录执行如下代码:
npm install --save react react-native
下载react-native模块,时间较长,两分钟左右。执行完成后会出现下图的node_modules:
rn_01.png

二、添加index.android.js文件到项目中:

这个就不用多说了,很简单,注意一下AppRegistry.registerComponent(‘aspactjdemo’, () => Demo)就行。

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
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
export default class Demo extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.android.js
</Text>
<Text style={styles.instructions}>
这是一个ReactNative界面,{'\n'}测试
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
// 这个名字必须要和第一步中的name一致,这个Demo对应 上面的Class Demo extends Component
AppRegistry.registerComponent('aspactjdemo', () => Demo);

三、添加ReactNative相关依赖

  1. 在app的build.gradle文件中添加react-native依赖库
    compile "com.facebook.react:react-native:+"
  2. 在project的build.gradle文件中添加react-native路径
    注意:这里注意不要使用maven中的,因为我们使用的是我们本地的node_modules

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    allprojects {
    repositories {
    jcenter()
    maven {
    // All of React Native (JS, Android binaries) is installed from npm
    // node_modules的路径检查一遍,复制网上帖子的
    // url "$rootDir/../node_modules/react-native/android"给坑了,在重写Application时,找不到ReactApplictaion这个接口
    url "$rootDir/node_modules/react-native/android"
    }
    }
    }
  3. 同步,会报错:
    Error:Conflict with dependency 'com.google.code.findbugs:jsr305'. Resolved versions for app (3.0.0) and test app (2.0.1) differ.

  • 解决方法:在module层的build.gradle中添加:
    1
    2
    3
    4
    5
    6
    7
    android {
    ...
    ...
    configurations.all {
    resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.0'
    }
    }

四、添加相关权限和支持NDK:

  1. 在AndroidManifest.xml中添加如下代码:
    <uses-permission android:name="android.permission.INTERNET" />
  2. 1
    2
    3
    4
    5
    6
    7
    8
    9
    android {
    ...
    defaultConfig {
    ...
    ndk {
    abiFilters "armeabi-v7a", "x86"
    }
    }
    }
  3. gradle.properties:
    android.useDeprecatedNdk=true

五、添加reactnative组件:

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
<com.facebook.react.ReactRootView
android:id="@+id/react_root_view"
android:layout_width="300dp"
android:layout_height="300dp"/>
</LinearLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MainActivity extends AppCompatActivity {
ReactRootView react_root_view ;
ReactInstanceManager mReactInstanceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
react_root_view = (ReactRootView) findViewById(R.id.react_root_view);
mReactInstanceManager =ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
// aspectjdemo是项目名,需要和index.adnroid.js、json中的保持一致
react_root_view.startReactApplication(mReactInstanceManager, "aspectjdemo", null);
}
}

也可以通过Activity继承ReactActivity来实现。

六、添加DevSettingsActivity配置

<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

七、自定义Appliction

需要自定义Application然后去实现ReactApplication接口。

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
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import java.util.Arrays;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
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);
}
}

七、 运行:

Unable to load script form assets'index.android.bunlde'.Make sure your bundle is packaged correctly...

rn_02.png

嗯是的,忘了开服务:进项目根目录,通过npm start开启服务,摇一摇配置一下IP+端口。

也可以通过打包的方式生成bundle

  1. main下创建assets
  2. 根目录下执行:
    react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output AspectJDemo/app/src/main/assets/index.android.bundle --assets-dest AspectJDemo/app /src/main/res/
    生成如下图两个文件,再运行就OK了,这种适合上线打包,平时的调试使用server较方便,在开发环境下,为方便调试,APP会在启动时从JS Server服务器将index.android.bundle文件加载到APP。。
    rn_03.png