Android 集成RN 踩坑

版权声明:本文出自_莫逸的博客,转载必须注明出处。 https://blog.csdn.net/RedWolfChao/article/details/84328047
  • 1. 设置项目目录结构

  • 首先创建一个空目录用于存放React Native项目 , 然后在其中创建一个android子目录 , 把你现有的Android项目拷贝到android子目录中 ;

  • 2. 安装JavaScript依赖包

  • 在项目根目录下创建一个名为package.json的空文本文件,然后填入以下内容:

            

{

  "name": "MyReactNativeApp",

  "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"

  }

}

  • name 随意

  • version字段没有太大意义(除非你要把你的项目发布到npm仓库)

  • scripts中是用于启动packager服务的命令

  • dependencies中的react和react-native的版本取决于你的具体需求(一般来说照着复制就行 )

  • 然后在项目目录(根目录)中 命令行 (npm install) 安装React和ReactNative模块...等吧 需要点儿时间

  • 3. 配置AndroidStudio 将ReactNative添加到Android项目中

  • 坑① : 最小支持版本为 API 16 

  • 坑② : com.android.support:appcompat-v7 的版本为 23

  • 配置Maven

            

//    打个注释吧  这个是在app中的build.gradle文件中的

dependencies {

     ...

   // 此处用native:+ 就没问题,有强迫症的可以改成自己电脑上的版本

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

}

//    这个是在project中的build.gradle文件中的

allprojects {

    repositories {

        ...

        maven {

            // All of React Native (JS, Android binaries) is installed from npm

            // 只要npm install执行完成了 下面这个目录是真实存在的 不存在的话Gradle构建会失败

            url "$rootDir/../node_modules/react-native/android"

        }

    }

    ...

}

  • 权限申请 : 

        

<!--React-Native 需要网络权限-->

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

<!--悬浮窗权限-->

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

  • 如果需要访问 DevSettingsActivity 界面(即开发者菜单),则还需要在 AndroidManifest.xml 中声明:(此处直接复制比较好,打DevSett联想不出来)

<!--React-Native 开发者菜单-->

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

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

  • 4. 编写ReactNative代码

  • 根目录下新建index.js (index.js是React Native应用在Android上的入口文件 而且它是不可或缺的)

  • 首先是 index.js 代码

            

//    引入React库

import React from 'react';

//    引入文件NewClass

import NewClass from './NewClass';

//    引入AppRegistry

import {

  AppRegistry

} from 'react-native';

//    设置首页是哪一个类

AppRegistry.registerComponent('MyReactNativeApp', () => NewClass);

  • 然后是NewClass代码(中文网中的Text输入Demo)

        

import React, { Component } from 'react';

import {Text,TextInput,View} from 'react-native';

class TextInputDemo extends Component{

    constructor(props){

        super(props);

        //    在这里声明State

        this.state = {text : "",stateTest:""};

    }

    render(){

        return(

            <View style={{padding:10}}>

                <TextInput style={{height:40}} placeholder="Please Input XXXX" onChangeText={(text)=>this.setState({text})}/>

                <Text style={{padding :10,fontSize:42}}>

                {this.state.text}

                </Text>

            </View>    

        );

    }

}

export default class NewClass extends Component<Props> {

  render() {

    return (

        <TextInputDemo/>

    );

  }

}

  • 5. 6.0权限申请

  • 某个Activity中动态申请悬浮窗权限 申请代码如下(中文网示例)

        

private static final int OVERLAY_PERMISSION_REQ_CODE = 10001;

/**

* 请求弹窗权限

*/

private void initPermission() {

    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);

            }

        }

}

@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)) {

                    // TODO

                }

            }

        }

}

  • 6. 核心代码 ReactRootView ReactInstanceManager

/**

* @作者 RedWolfChao

* @时间 2018/2/22 16:38

* @描述 代码没有很好的弄6.0权限处理 所以在没有授权的情况下, APP会崩溃

*/

public class MainActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {

private static final int OVERLAY_PERMISSION_REQ_CODE = 10001;

// ReactNative核心类

private ReactRootView mReactRootView;

// ...

private ReactInstanceManager mReactInstanceManager;

@Override

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    initPermission();

    initReactNative();

}

/**

* 初始化ReactNative

*/

private void initReactNative() {

    mReactRootView = new ReactRootView(this);

    mReactInstanceManager = ReactInstanceManager.builder()

                                    .setApplication(getApplication())

                                     // 此处中文网中有点不一样 中文网中的文档感觉有点儿过时

                                     .setBundleAssetName("index.bundle")

                                     .setJSMainModuleName("index")

                                     .addPackage(new MainReactPackage())

                                     .setUseDeveloperSupport(BuildConfig.DEBUG)

                                     .setInitialLifecycleState(LifecycleState.RESUMED)

                                     .build();

    // 注意这里的MyReactNativeApp 必须对应 "index.js"中的"AppRegistry.registerComponent()"的第一个参数

    mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);

    setContentView(mReactRootView);

}

@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)) {

                // TODO

            }

        }

    }

}

/**

* 请求弹窗权限

*/

private void initPermission() {

    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);

        }

    }

}

@Override

public void invokeDefaultOnBackPressed() {

    super.onBackPressed();

}

@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);

}

@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);

        }

    }

}

  • 配置Manifest.xml

<activity android:name=".MainActivity">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

  • 7. 起 ReactNative 服务 在根目录命令行

        

npm start

  • 8. 运行即可 , 可以直接run app(AS的三角符号运行) , 也可以用gradlew installDebug命令行 (中文网说是直接运行会崩溃..我没遇见过)

  • 9. 打包 (未测试)

  • 你也可以使用Android Studio来打release包!其步骤基本和原生应用一样,只是在每次编译打包之前需要先执行js文件的打包(即生成离线的jsbundle文件)。具体的js打包命令如下:

$ react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/

  • 注意把上述命令中的路径替换为你实际项目的路径。如果assets目录不存在,则需要提前自己创建一个。

  • 然后在Android Studio中正常生成release版本即可!

猜你喜欢

转载自blog.csdn.net/RedWolfChao/article/details/84328047