Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Native组件集成到Android原生项目 #26

Open
lin-xin opened this issue May 21, 2018 · 2 comments
Open

React Native组件集成到Android原生项目 #26

lin-xin opened this issue May 21, 2018 · 2 comments

Comments

@lin-xin
Copy link
Owner

lin-xin commented May 21, 2018

前言

为了把 React Native 集成到 Android 原生项目中,踩了很多坑,因为作为web前端开发,本来就不熟悉安卓,参考了网上很多文章,但是都很旧了,而 React Native 已经升级到了 0.55 版本了,入口文件已经合成了一个 index.js,下面的内容也是基于这个版本实践的。

环境搭建

已经搭建好 React Native 环境的可以跳过,还没有的可以参考 React Native 中文网的 搭建教程,比较详细。

创建Android原生项目

安卓开发者自然很熟悉这个步骤,然而对于web前端开发者还是比较迷茫的。可以参考一下 使用Android Studio创建一个新的Android工程,创建一个 Empty Activity,接下来会比较好操作。

集成React Native

步骤一:安装相关依赖
在项目根目录下执行 npm init 命令,生成 package.json 文件,添加以下命令

"scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start"
}

执行 npm i react react-native -S 安装 react 和 react-native

步骤二:配置maven
在你的 app/ 目录下的 build.gradle 文件中的 dependencies 里添加 React Native 依赖:

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

在项目根目录下的 build.gradle 文件中为 React Native 添加一个 maven 依赖的入口,必须写在 "allprojects" 代码块中:

allprojects {
    repositories {
        ...
        maven {
            url "$rootDir/node_modules/react-native/android"
        }
    }
}

步骤三:代码集成,创建我们的 react-native 组件,在根目录下创建 index.js,(在 react-native 0.49.0版本以前,是 index.android.js 和 index.ios.js 作为入口文件,现在合成一个 index.js 文件了)

import React, {Component} from 'react';
import {AppRegistry,View,Text} from 'react-native';

class App extends Component{
	render(){
		return (
			<View>
				<Text>哈哈哈</Text>
			</View>
		)
	}
}

AppRegistry.registerComponent('ReactNativeView', () => App);

然后创建 MyReactActivity,Activity 是安卓中基本的页面单元,简单的说,可以看做 web 开发中的一个 html 页面。
在上面创建安卓项目的时候,已经创建了一个 MainActivity,在它的同级目录下,在 Android Studio右键新建一个 Activity,命名为 MyReactActivity,然后把内容改为如下:

package com.example.administrator.androidreactnative;

import javax.annotation.Nullable;
import com.facebook.react.ReactActivity;

public class MyReactActivity extends ReactActivity {
    @Nullable
    @Override
    protected String getMainComponentName() {
        return "ReactNativeView";
    }
}

接着创建 MainApplication

package com.example.administrator.androidreactnative;

import android.app.Application;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import java.util.Arrays;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

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

    };

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

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this,false);
    }
}

最后在 app/src/main/AndroidManifest.xml 文件中,添加一些权限,以及声明MainApplication 跟 MyReactActivity

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="com.example.administrator.androidreactnative">

    <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"/> <!-- 窗体覆盖权限 -->
	<!-- 声明MainApplication -->
    <application
        android:name=".MainApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
		<!-- 声明MyReactActivity -->
        <activity
            android:name=".MyReactActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme">
        </activity>
		<!-- 声明可以通过晃动手机或者点击Menu菜单打开相关的调试页面 -->
        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
    </application>
</manifest>

原生页面跳转到react-native页面

在 MainActivity 添加一个按钮跳转到 MyReactActivity,首先在 app/src/main/res/layout 下的 activity_main.xml 添加一个按钮元素

<Button
	android:id="@+id/btn"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:text="点击跳转到RN界面"/>

然后在 MainActivity 里添加点击跳转事件

package com.example.administrator.androidreactnative;

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

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		// 点击按钮跳转到 react-native 页面
        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(MainActivity.this,MyReactActivity.class));
            }
        });
    }
}

然后在Android Studio 的模拟器中打开就可以看到以下页面:

同时执行 npm start 启动本地服务器,点击按钮,出现了红屏,也就是错误页面。

从错误信息 error: bundling failed: NotFoundError: Cannot find entry file index.android.js in any of the roots 我们可以看出找不到入口文件index.android.js,而我们的入口文件是 index.js,因此我们需要另外加一些配置让它知道我们的入口文件其实是 index.js
解决方法参考 react-native/issues/16517。在 app/ 目录下的 build.gradle 文件中最上面添加

apply plugin: 'com.android.application'	// 这时原来存在的
apply from: "../node_modules/react-native/react.gradle"
project.ext.react = [
    entryFile: "index.js"
]

然后在 MainApplication 的 ReactNativeHost 类中添加:

private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
	...
	// 这是需要添加的
	@Override
	protected String getJSMainModuleName() {
		return "index";
	}
}

重新在模拟器中运行,就可以正常跳转到 react-native 的页面了。

源码地址:lin-xin/ReactNativeInAndroid

@qld-cf
Copy link

qld-cf commented Nov 27, 2018

需要更改:
1、 url "$rootDir/node_modules/react-native/android" => url "$rootDir/../node_modules/react-native/android"
2、 compile "com.facebook.react:react-native:+" => implementation "com.facebook.react:react-native:+"

@qld-cf
Copy link

qld-cf commented Nov 27, 2018

还有一处需要修改:apply from: "$rootDir/../node_modules/react-native/react.gradle"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants