Chocolatey:Chocolatey是一个Windows上的包管理器,用于安装windows程序
Python 2:
NodeJS:NodeJS是基于javascript的服务端。将本地的js文件(RN里,将返回的js文件通过依赖React翻译成React格式,再通过依赖react-native,翻译为react-native格式)返回客户端(即android端)。
bundle文件:react-native格式的js文件(react-native格式的js代码可以说是一个转换器,在nodejs端可以依赖react-native插件对应js代码,在android可以依赖react-native插件对应java代码,react-native插件是翻译官)是放在bundle文件内的,android端是和它交互的。当android端和nodejs端离线时,放在assets目录下;服务端启动时,直接返回bundle文件。android端一个RN界面从bundle中拿取当前界面需要的内容(如下图),并依赖react-native插件将这些内容映射为原生视图和事件处理。
android端一个RN页面需要的内容如下,需要和NodeJS端的主js文件导出的组件名一致(可以理解为将此页面的所有内容打包到这个名字下了):
android:
Js:
react-native-cli:相当于node.js的一个插件,相当于nodejs的一个入口。两个作用:1.初始化出一个带有支持RN组件的android Demo工程,2.该插件的作用还有当node.js服务启动后,当native端的APP发起JS请求时,检查服务端的js信息是否有更新,并将它们转化为react-native格式传给native端。
npm:node packege manage,node包管理器,负责nodejs的模块安装。装nodejs时,npm就已经自动安装好了。
很简单,直接调用”react-native init”命令即可。会从相关的远程copy配置好的工程目录层次到本地。
NodeJS端环境:
1、将原生工程放入android文件夹内
2、在根目录下新建packege.json文件,填入以下内容(也可通过“npm init”命令实现),类似gradle配置文件:
version字段没有太大意义(除非你要把你的项目发布到npm仓库)。scripts中是用于启动packager服务的命令。dependencies中的react和react-native的版本取决于你的具体需求。一般来说我们推荐使用最新版本。你可以使用npm info react和npm info react-native来查看当前的最新版本。另外,react-native对react的版本有严格要求,高于或低于某个范围都不可以。
3、执行“npm install”命令安装后,就会生成”node_moudles”文件夹。
Android端环境:
1、在你的app中 build.gradle 文件中添加 React Native 依赖:
2、为确保android端和nodejs端react-native版本一致,在项目的 build.gradle 文件中为 React Native 添加一个 maven 依赖的入口,必须写在 “allprojects” 代码块中:
3、因为要和nodejs端交互,添加网络权限
4、如果需要访问 DevSettingsActivity 界面(即开发者菜单),则还需要在 AndroidManifest.xml 中声明,开发者菜单一般仅用于在开发时从Packager服务器刷新JavaScript代码,所以在正式发布时你可以去掉这一权限。
android端代码:
一个rn界面:
//该Activity不用直接继承ReactActivity,但是实现DefaultHardwareBackBtnHandler接口,以处理相关的手机按键事件
public class RNSceActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
private static final int OVERLAY_PERMISSION_REQ_CODE = 102;
private static final String TAG = "---";
private ReactRootView mReactRootView;//JS对应的Native的根布局
private ReactInstanceManager mReactInstanceManager;//Instance 管理器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main); //RN中不需要此处填充view 使用解析到的JS端的view填充
initRNRootView();//初始化RN的rootView,所有解析到的view都按规则添加到该View上
//打开悬浮窗(overlay)权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
}
}
}
private void initRNRootView() {
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder().setApplication(getApplication())
.setBundleAssetName("index.android.jsbundle")//main.jsbundle
.setJSMainModuleName("index.android")//index.android
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)//BuildConfig.DEBUG 直接用debug 出现crash ---http://blog.csdn.net/guxiao1201/article/details/50899136
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager, "RNFirstComponent", null);
setContentView(mReactRootView);
}
@Override
public void invokeDefaultOnBackPressed() {
super.onBackPressed();
}
@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() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (mReactInstanceManager != null && keyCode == KeyEvent.KEYCODE_MENU) {
mReactInstanceManager.showDevOptionsDialog();
return true;
}
return super.onKeyUp(keyCode, event);
}
//打开悬浮窗(overlay)权限
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
// SYSTEM_ALERT_WINDOW permission not granted...
Log.d(TAG, "onActivityResult: ");
}
}
}
}
}
js端代码:
import React from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
class HelloWorld extends React.Component {
render() {
return (
Hello, World
)
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
AppRegistry.registerComponent('RNFirstComponent', () => HelloWorld);//名字必须和上图android端请求的一致
1、当nodejs服务端启动不起来时,停留在下图所示:
此时需要通过命令行生成离线bundle。
2、 手动生成bundle文件,需要我们执行如下命令:
react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --assets-dest app/src/main/res/
3、React Native项目在64位Android手机上运行,会提示
“/data/data/com.xxx.xxx/lib-main/libgnustl_shared.so” is 32-bit instead of 64-bit 这个错误。
解决方法就是取消掉所有的64位的.so文件,全部加载32位的就可以了,下面是步骤
a、在项目的根目录的 gradle.properties 里面添加一行代码 android.useDeprecatedNdk=true.
b、在 build.gradle 文件里添加以下代码
android {
...
defaultConfig {
...
ndk {
abiFilters "armeabi-v7a", "x86"
}
packagingOptions {
exclude "lib/arm64-v8a/librealm-jni.so"
}
}
}
4、可以通过数据线和服务端连接即时拿取bundle文件;也可通过wifi和服务端连接即时拿取bundle文件(要求手机和电脑在同一个wifi下);也可以通过命令直接生成离线bundle。
5、服务端执行npm start 窗口会显示打包bundle的进度如下
http://reactnative.cn/docs/0.50/integration-with-existing-apps.html#content
http://blog.csdn.net/chichengjunma/article/details/53815299
http://m.blog.csdn.net/M075097/article/details/76551415