Android 混合开发



最近自己也是刚在学习React Native的知识,在学习到React Native 嵌入到原生应用的时候,感觉遇到了各种坑,这里做一下记录。若有说得不对的地方,谢谢大家纠正。

React Native嵌入到原生应用的教程在其官方指导文档里也有,但是感觉很多注意点没讲到,现在,我们就一步步来,我们这里的前提是开发环境已经搭配好。

第一步,在 Android Studio 上新建一个工程,这一步没什么好说的,然后在main目录下面创建一个assets 的文件夹。

第二步,打开下面的终端 Terminal,分别执行以下三条语句:

npm init
npm install --save react react-native
curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig

先输入 npm init ,然后会出现下面的情况,划红线的都是需要自己输入的,看着我的随便写点就行



执行第二条命令

npm install --save react react-native
,执行完之后你会发觉多了一个叫node_modules的文件夹,接着执行第三条命令
curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig
执行完,第三条命令之后又会生成一个.flowconfig的文件


第三步,将

"start": "node node_modules/react-native/local-cli/cli.js start"
这条语句copy到 data.json中的scripts中,如下图

第四步,项目根目录中创建index.android.js文件,然后将下面的代码复制粘贴进来:

'use strict';

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, World</Text>
      </View>
    )
  }
}
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

AppRegistry.registerComponent('HelloWorld', () => HelloWorld);

第五步,给工程添加React Native依赖包,如果你想下载一个随意版本的依赖包【建议下载最新版本的React Native依赖包】,就在你APP module下面的build.gradile文件中  的 dependencies中添加 compile "com.facebook.react:react-native:+" // From node_modules.

dependencies {
     ...
     compile "com.facebook.react:react-native:+" // From node_modules.
 }
如果你不想下载一个随意的版本的React Native依赖包,你可以指定下你要下载的React Native依赖包的版本,首先查询下当前最新的React Native依赖包版本,执行下面这段话, (react native npm 包的地址为 : https://www.npmjs.com/package/react-native ) ,或者采用命令 npm info react-native 进行查看 :



发觉当前最新的版本是0.39.2,那你就将 compile "com.facebook.react:react-native:+"改成 compile "com.facebook.react:react-native:0.39.2"即可



若发觉报错,说找不到当前的依赖包,如下面的错误:


说明你下载的依赖包版本 与当前APP  的build.gradile中dependiences 中过的依赖包的版本不一致,这时你可以执行如下的如句,下载特定的依赖包,

npm install  --save react-native@版本号  //我这里就输入:npm install  --save react-native@0.39.2


第六步,向你的工程随对应的build.gradile文件中添加如下这段

allprojects {
    repositories {
        ...
        maven {
            // All of React Native (JS, Android binaries) is installed from npm
          //  url "$rootDir/../node_modules/react-///native/android" 官方给的是这一句,但是用这一句有时有问题
        url "$rootDir/node_modules/react-native/android"
        }
    }
    ...
}
然后, 因为修改了build.guild文件,所以要async 一下工程,



不出意外,可能就会报下面的错误:


不要慌,在你的应用程序build.gradle添加内的下列Android { }:

configurations.all {
    resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
}

添加完成之后,再重新Async Now  一下,就行了

第七步,添加

<uses-permission android:name="android.permission.INTERNET" />
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
到AndroidManifest.xml中


检查下刚才下载的React native依赖包版本是否正确,展开 External Libraries,发觉当前React native依赖包版本是0.39.2【也可以输入命令:react-native  --version  查看当前react native的版本号,若不一致,则可执行

npm install  --save react-native@版本号
下载特定的版本】,正确,执行下一步,添加原生代码


第八步,添加原生代码

创建一个类,继承ReactActivity,然后必须要重写 getMainComponentName方法,将你index.android.js中注册的组件的名字作为返回值,即默认为HelloWorld

AppRegistry.registerComponent('HelloWorld', () => HelloWorld);

以下是我创建的ReactActivity子类:

package com.example.administrator.reactejp;

import android.os.Bundle;
import android.view.KeyEvent;

import com.facebook.react.ReactActivity;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.shell.MainReactPackage;

/**
 * Created by Administrator on 2017/1/8.
 */

public class MyReactActivity extends ReactActivity {
    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();
        mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorld", 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
    protected void onDestroy() {
        super.onDestroy();

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

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

    //该方法与弹出Reload的dialog相关,不重写,可能不能弹出dialog
    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }
}


除此之外,我们还需要定义一个ReactApplication的子类,不然运行时时会报错的,以下是我的重写的

package com.example.administrator.reactnativedemo;

import android.app.Application;
import android.support.v4.*;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;

import java.util.Arrays;
import java.util.List;

/**
 * Created by Administrator on 2016/12/23.
 */

public class MyReactApplication extends Application implements ReactApplication {
    private final ReactNativeHost mReactNativeHost=new ReactNativeHost(this) {
        @Override
        protected boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

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

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


这里有一点需要注意:

这两个类中的BuildConfig并没有导包,而是用了自动生成的一个BuildConfig.java的文件,如下



我们修改一下当前程序的入口,修改AndroidMainfaist.xml清单文件,将MyReactActivity作为程序的入口,开启Genymotion模拟器,然后在Terminal 窗口,执行 npm start  命令【如果出错可以多试几次】,最后像正常的程序一样启动即可,发觉程序直接崩了,报了这样的错:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.administrator.reactnativedemo/com.example.administrator.reactnativedemo.MyReactActivity}: java.lang.ClassCastException: android.app.Application cannot be cast to com.facebook.react.ReactApplication

我一直不知道为什么会报类型转换异常的错误,找了好久才知道,已经要在AndroidMainfaist.xml清单文件中指明当前Application的name属性值为你定义的那个ReactApplication子类的名字,这里即为MyReactApplication


检查一下刚才执行的npm start 命令是否异常,若异常了重写执行一下该命令即可,然后再重新运行一下程序,发觉还是报错了,但错误发生了变化,如下所示:


以下方法来自百度。

方法一:【推荐使用方法】

进入项目,在android/app/src/main下新建assets目录,关闭掉原来的npm,分别执行以下命令:

react-native start
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/
在assets文件夹下会生成index.android.bundle文件


方法二:

进入项目,在android/app/src/main下新建assets目录
在package.json中配置下面代码

"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 app/src/main/assets/index.android.bundle --sourcemap-output app/src/main/assets/index.android.map --assets-dest android/app/src/main/res/"
  },


再重新运行下程序,若还是有错,再重新运行试两次,一般都可以,到此为止,你就会看到下面的画面:【注:要确定模拟器连接网络了】


在确保npm没挂的情况下,运行结果如下:


到这里为止,终于成功了!


补充:若出现Could not connect to development server,一般是npm报异常了,如果是的话,就执行 npm start 命令即可,如果不是,很有可能就是网络问题,这里提供种方法解决网络问题:


第一种:最常见的方式,点击上图红框区域,弹出一个dialog,选择Dev Setting,以下几张图片来自:http://www.jianshu.com/users/e630681e7001/latest_articles



将localHost换成,你的电脑的IP地址



最后,感谢http://www.jianshu.com/users/e630681e7001/latest_articles

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值