您的位置:首页 > Web前端 > React

react-native移植到android项目中详细步骤

2017-02-10 16:38 447 查看

开篇胡扯:

刚刚过完年假回来上班,公司并没有特别的任务安排。闲来无事,就莫名的开始了人生第一篇的博客之旅

。本来不想特意将自己get到的东西写到博客上。

一是担心自己的经验不够,写了害怕误人子弟;

二是自己可以随便在云笔记上写自己懂的东西,不必花费很多时间在斟酌字句上,担心有什么疏漏。

好了,既然决定写了就认真的分享下(免得真的误人),自己也再次巩固所学到的,还可以无意之中的帮助别人,何乐不为!

回归正题,对于react-native,去年就开始稍微了解过,尝试写过些小demo,但由于自己的懒惰就没有去尝试性的往下面继续研究了,主要是公司还没用到,自己就想偷个懒。恰巧昨天看到鸿神推送的关于react-native的文章,于是就下定决心开始重拾起来。下面就开始说说个人昨天一天对于rn集成到android项目中实践心得吧,希望各位给出意见!

前提rn的环境配置完毕(以下说的拷贝是react-native init之后的工程里的文件)

第一步:

进入android工程根目录使用npm init命令创建package.json文件(或者将生成好的rn项目拷贝过去)千万要记住,这个里面的react-native版本一定要和android工程里gradle配置的版本一样,不然就出现了那个“Module  0”的版本不一致的错误了。

第二步:

在android工程的根目录使用npm install -save react react-native下载源文件,最后会生成一个node_modules文件夹(当然也可以拷贝原来的)

第三步:

拷贝或者下载.flowconfig文件(下载链接https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig),主要是给folw用的,用来做静态代码检查,下载完后放在android的根目录下即可。

第四步:

配置Android项目react-native依赖库,版本号一定要和本地rn的版本一致



第五步:

配置react-native本地代码路径,本步骤是制定Android-studio编译react-native时用制定路径下的代码,大致这个意思。这里添加是在根目录下的build.gradle中修改,放在在allprojects节点下。截图如下:




同步工程在External Libraries看到这个匹配的版本的依赖包就说明成功了。

第六步:

修改package.json文件,修改信息如下:

{
"name": "myapplication",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"bundle-android":"react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output MyApplication/app/src/main/assets/index.android.bundle --sourcemap-output MyApplication/app/src/main/assets/index.android.map --assets-dest MyApplication/app/src/main/res/"
},
"author": "0",
"license": "ISC",
"dependencies": {
"react": "^15.3.
b7e6
1",
"react-native": "^0.33.0"
}
}

name是工程名字字母都小写,scripts一定要根据自己的实际配置不然会报错,dependencies按照自己的版本来修改(最好参照原生的react-native的package.json)

第七步:

创建原生安卓类,作为加载rn容器,再将index.android.js(rn的核心代码文件)文件直接放在android项目根目录就行或者自己创建添加如下代码:

import React,{Component} 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}>这是React-Native组件</Text>
</View>
)
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor:'#ccc',
},
hello: {
fontSize: 20,
color: '#fff',
textAlign: 'center',
margin: 10,
},
});
//注意这里的reactdemo哦
AppRegistry.registerComponent('reactdemo', () => HelloWorld);


再创建一个ReactActivity

public class ReactActivity extends Activity implements DefaultHardwareBackBtnHandler {

private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
private LinearLayout ll;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.myreactdemo);
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();
//reactdemo这个名字要与package.json、以及react-native中index.android.js中的项目名要一致,否则会出错。
mReactRootView.startReactApplication(mReactInstanceManager, "reactdemo", null);
ll= (LinearLayout) findViewById(R.id.ll);
ll.addView(mReactRootView);

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

@Override
protected void onResume() {
super.onResume();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostResume(this, this);
}
}

@Override
protected void onPause() {
super.onPause();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostPause(MyReactActivity.this);
}
}

@Override
protected void onDestroy() {
super.onDestroy();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostDestroy(MyReactActivity.this);
}
}

@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);
}
}
再在MainActivity里添加点击事件跳入ReactActivity
findViewById(R.id.tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (Build.VERSION.SDK_INT>=23){
if (!Settings.canDrawOverlays(MainActivity.this)){
startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));
return;
}else{

}
}else{
//绘UI代码,这里android6.0以下的系统可以直接绘出即可
}
startActivity(new Intent(MainActivity.this,ReactActivity.class));
}
});


第八步:

修改AndroidManifest.xml配置文件如下:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
<activity android:name=".MyReactActivity"/>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>


第九步:

打开cmd进入到android的目录下,运行react-native start ,启动服务,再运行android项目,就可以看见一部分是android原生控件,一部分是rn控件

常见错误

java.lang.IllegalAccessError: Method 'void android.support.v4.net.ConnectivityManagerCompat.()' is inaccessible to class 'com.f

acebook.react.modules.netinfo.NetInfoModule' (declaration of 'com.facebook.react.modules.netinfo.NetInfoModule' appears in 

/data/app/package.name-2/base.apk)
解决办法:(老外也遇到了这样的问题https://github.com/facebook/react-native/issues/6152#issuecomment-200759453)在项目下修改以下的文件内容:
.gitignore(在该文件里添加排除项,node_modules/ 和 npm-debug.log)
app/build.gradle (将 'com.android.support:appcompat-v7:24.2.1' 改为 'com.android.support:appcompat-v7:23.0.1')
gradle.properties (在文件末尾添加,android.useDeprecatedNdk=true)

红屏问题"Could not get BatchedBridge, make sure your bundle is packaged correctly"解决方法: 主要就只遇到这一个问题, 更改ip和port没有解决了, 后来在package.json中的"scripts"中添加"bundle-android":"react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output 工程名/app/src/main/assets/index.android.bundle --sourcemap-output 工程名/app/src/main/assets/index.android.map --assets-dest 工程名/app/src/main/res/",如果没有assets目录,手动添加下,不过运行时没有效果, 在cmd中手动执行下(去掉命令的工程名如果在根路径下执行命令), assets目录中会多出几个文件, 即可解决这个问题
参考资料:
如何把React Native嵌入到原生android应用中

React Native 集成到已有项目




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: