Android Studio现有工程接入React Native

公司要求使用RN开发项目,之前了解过一直没有写过,因网络上大量错误及不相关信息,此博客只记录最开始的配置及运行,不涉及太多代码。本篇基于已配置好RN环境,即npm命令可用,若没有搭建请移步:https://reactnative.cn/docs/0.47/getting-started.html

环境:MacOS + Android Studio3.0 + gradle3.0.0

1.Android Studio新建项目,常规建立项目,本篇Demo为“RNTest”。(注意最小SDK要选择16及以上,选择16即可)

2.Android Studio切换至Project目录结构,在根目录创建package.json,并粘贴以下代码:

{
  "name": "RNTest",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start"
  },
  "dependencies": {
    "react": "16.0.0-alpha.6",
    "react-native": "0.44.3"
  }
}

3.接下来打开终端/命令提示符,cd到该项目的根目录(RNTest),输入npm install

4.在app的gradle里添加:(忽略+的警告,用+是防止固定版本带来的更新找不到包等问题)

dependencies {
     ...
     compile "com.facebook.react:react-native:+" // From node_modules.
 }

5.在项目的gradle中添加maven:(这里有坑,详见最后坑3)

allprojects {
    repositories {
        ...
        maven {
            // All of React Native (JS, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
    }
    ...
}

6.在AndroidManifest.xml里添加权限:

<uses-permission android:name="android.permission.INTERNET" />

如果需要访问 DevSettingsActivity 界面(即开发者菜单),则还需要在 AndroidManifest.xml 中声明:

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

开发者菜单一般仅用于在开发时从Packager服务器刷新JavaScript代码,所以在正式发布时你可以去掉这一权限。

7.代码集成RN组建:根目录创建一个index.android.js文件,这是RN的门户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, React Native</Text>
      </View>
    )
  }
}
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

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

8.创建一个ReactActivity.java,添加如下代码:

package com.ccl.rntest;

import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;

//import com.facebook.react.LifecycleState;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.shell.MainReactPackage;

public class ReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
    public static final int OVERLAY_PERMISSION_REQ_CODE = 1235;
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_react);
        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);
            }
        }

        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModuleName("index.android")
                .addPackage(new MainReactPackage())
//                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setUseDeveloperSupport(true)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();// 注意这里的RNTest必须对应“index.android.js”中的
        // “AppRegistry.registerComponent()”的第一个参数
        mReactRootView.startReactApplication(mReactInstanceManager, "RNTest", null);
        setContentView(mReactRootView);
    }

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

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // super.onActivityResult(requestCode, resultCode, 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...
                }
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostPause(this);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostResume(this, this);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostDestroy(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);
    }
}

以上代码具体可参考最后的参考链接。

9.修改清单文件添加:

<activity
            android:name=".ReactActivity"
            android:label="@string/app_name"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar">
        </activity>

10.MainActivity修改如下:(就是添加了点击跳转事件)

package com.ccl.rntest;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.tv_react_native).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, ReactActivity.class);
                startActivity(intent);
            }
        });
    }
}

11.终端cd到项目根目录(RNTest),输入npm start。

12.Android Studio运行项目,点击跳转:

坑:

1.细心的话你会发现gradle的v7依赖包默认是26.1.0(compileSdkVersion及targetSdkVersion都是26),但不影响运行,运行之后报错:

Caused by: java.lang.IllegalAccessError: Method 'void android.support.v4.net.ConnectivityManagerCompat.<init>()' is inaccessible to class 'com.facebook.react.modules.netinfo.NetInfoModule' (declaration of 'com.facebook.react.modules.netinfo.NetInfoModule' appears in /data/app/xxc.application1-1/base.apk)

解决方式:修改app下gradle,v7依赖库为23.0.1,修改compileSdkVersion及targetSdkVersion为23。

compile 'com.android.support:appcompat-v7:23.0.1'

可参考:https://github.com/facebook/react-native/issues/6152

2.以上重新build,报如下错误:

error: attribute 'android:roundIcon' not found.

这个好说,按照提示把AndroidManifest.xml下的application里面roundIcon删掉就行,并将同时出现的v26(或其他)xml一并删掉。重新build,报build包下的AndroidManifest.xml错误:

Error:Execution failed for task ':app:preDebugAndroidTestBuild'.
> Conflict with dependency 'com.android.support:support-annotations' in project ':app'. Resolved versions for app (23.0.1) and test app (25.4.0) differ. See https://d.android.com/r/tools/test-apk-dependency-conflicts.html for details.

解决方法:Build -> ReBuild Project

3.继续报错:

Native: Got JS Exception: TypeError: undefined is not a function (evaluating '(bridgeConfig.remoteModuleConfig||[]).forEach')

解决方式:根目录的gradle修改url

allprojects {
    repositories {
        google()
        jcenter()
        maven {
            // All of React Native (JS, Android binaries) is installed from npm
            url "$rootDir/node_modules/react-native/android"
        }
    }
}

这里要说明一下:网络上对ReactInstanceManager的方法都是onHostXXX的形式,它就是从上面url来的。网路上还有一种版本是onXXX即不带Host的形式,这种是从开始的第5步带“...”的url来的。俩者的LifecycleState的包名也是不同的,不带...的是common包而非直接react包。

参考文献:https://reactnative.cn/docs/0.47/integration-with-existing-apps.html#content

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值