首先说说情况吧,公司需要原生嵌入ReactNative,迫于需要,要搞起来。看着iOS就搞了20分钟,感觉Android就算麻烦也不能太麻烦的,结果还是自己太年轻了。下面就是我遇到的各种问题,希望对看到的朋友能有帮助
(我用的是ReactNative版本为0.32.0)
1.首先集成的项目目录
我使用的是直接按照react-native init Project 的格式来导入的,也就是说,我的
Android项目目录是跟node_modules是在一个目录下的。
我试过把node_modules集成在Android项目下面的情况,不过没有弄成,所以我换乘来
这种了(有时间可以再试试)
2.第二步就是跟官网和很多教程一样的配置环境了
2.1 在我们Android项目的build.gradle中添加React Native依赖,然后同步,具体代码如下:
compile 'com.facebook.react:react-native:0.32.0'
在此说一下,我也是忘记在哪个大神博客下看的了,如果版本写的是“+”的话,下载的react native版本就是0.20.0的版本,会报一个错,就是版本不符合的错误,“Module 0 is not a registered callable moudle”,这个Google了一下,说是reactnative版本跟服务器的版本不符合,改正了就按着我的步骤三的第一种方法做就可以了,注释掉第三个重写的方法。
2.2紧接着我们需要在项目AndroidManifest.xml中加入网络访问权限
<uses-permission android:name="android.permission.INTERNET" />还有一个activity就是设置菜单,发现好多里面都没有,我就先放在这里了
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
2.3 在android/build.gradle
文件中(注意跟上面的路径不同)加入本地React Native的maven目录(现在React Native的所有组件,无论JS还是Android的预编译包,都是通过npm分发的了):
我是在两个 jcenter() 后面都添加了这个方法
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
3.在Activity中添加代码
这里有两种方法都是可以加载的。
第一种:
public class MainActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
return "<span style="font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", "Hiragino Sans GB", 微软雅黑, "WenQuanYi Micro Hei", STHeiti, SimSun, sans-serif; line-height: 2em;">MyAwesomeApp</span><span style="line-height: 2em; font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", "Hiragino Sans GB", 微软雅黑, "WenQuanYi Micro Hei", STHeiti, SimSun, sans-serif;">";</span>
}
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
// @Override
// protected List<ReactPackage> getPackages() {
// return Arrays.<ReactPackage>asList(
// new MainReactPackage()
// );
}
}
public class MainApplication extends Application implements ReactApplication {
private Application context;
@Override
public ReactNativeHost getReactNativeHost() {
context = this;
ReactNativeHost host = null;
if (host==null){
host = new ReactNativeHost(context) {
@Override
protected boolean getUseDeveloperSupport() {
return false;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new IntentReactPackage()
);
}
};
}
return host;
}
}
如果不写的话,会有一个Application强转错误的
public class MainActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建一个ReactRootView,把它设置成Activity的主视图
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, "MyAwesomeApp", null);
setContentView(mReactRootView);
}
@Override
public void invokeDefaultOnBackPressed() {
super.onBackPressed();
}
//传递一些Activity的生命周期事件到ReactInstanceManager,这是的JavaScript代码可以控制当前用户按下返回按钮的时候作何处理(譬如控制导航切换等等)。如果JavaScript端不处理相应的事件,你的invokeDefaultOnBackPressed方法会被调用。默认情况,这会直接结束你的Activity。
@Override
protected void onPause() {
super.onPause();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostResume(this,this);
}
}
@Override
public void onBackPressed() {
// mReactInstanceManager.showDevOptionsDialog();
Toast.makeText(this, "dianjialefanhuijian", Toast.LENGTH_SHORT).show();
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
}
//我们需要改动一下开发者菜单。默认情况下,任何开发者菜单都可以通过摇晃或者设备类触发,不过这对模拟器不是很有用。所以我们让它在按下Menu键的时候可以显示
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
mReactInstanceManager.showDevOptionsDialog();
return true;
}
return super.onKeyUp(keyCode, event);
}
}
我开始使用的是第一种,但是后来发现使用第一种的话,最后运行的话只能打包固定的代码,并不能实现热更新(毕竟新手,没有发现这么搞),所以果断改第二种了,修改js文件直接就能reload实现了,非常的嗨
$ npm init
跟着步骤回车就好了,然后好像输入个yes
然后就发现有了一个package.json文件
{
"name": "testRN",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"author": "",
"license": "ISC",
"dependencies": {
"react": "15.3.1",
"react-native": "^0.32.0"
}
}
千万要记住,这个里面的react-native版本一定要和前面gradle的版本一样,不然就出现了那个“Module 0”的版本不一致的错误了,这个错误就看第三步的方法一就好了
然后就是 npm install ,导入react包了
然后就是
curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig
做一下flow配置 虽然现在不知道是为了什么,但是每个人都这么做
5.添加Js代码
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
ToastAndroid
} from 'react-native';
var { NativeModules } = require('react-native');
class MyAwesomeApp extends Component {
constructor(props) {
super(props);
}
render() {
return(
<View >
<Text>哈哈哈哈哈哈哈哈</Text>
</View>
)
}
}
AppRegistry.registerComponent('MyAwesomeApp', () => MyAwesomeApp);
6.运行Demo
开开reactnative的服务器,npm start
在studio中运行demo,会发现,出现一行“哈哈哈哈”
注:可能会出现java.lang.RuntimeException: Could not get BatchedBridge, make sure your bundle is packaged correctly这个错误,Google就有解决方法,就是在命令行里运行
react-native bundle —platform android —dev false —entry-file index.android.js —bundle-output MyYhao/app/src/main/assets/index.android.bundle —sourcemap-output MyYhao/app/src/main/assets/index.android.map —assets-dest MyYhao/app/src/main/res/
react-native bundle —platform android —dev false —entry-file index.android.js —bundle-output MyYhao/app/src/main/assets/index.android.bundle —sourcemap-output MyYhao/app/src/main/assets/index.android.map —assets-dest MyYhao/app/src/main/res/
注意assets的目录,我是在里面直接新建了index.android.bundle和index.android.map两个空文件,然后运行的,会自动往里面写入代码,然后运行就可以了
本人第一次写这些自己的经验,有不足之处,希望大家海涵,因为是后来写的,有些东西可能还是忘记了,如果有碰到什么问题的话,可以直接回复,谢谢
我在自己做的时候,也参考了好多大神的文章,都有很大帮助,他们的文章都在百度的前几个,所以也好找,
谢谢观看