RN做的Android应用反编译,将RN嵌入到现有的Android应用中

[参考]http://www.jianshu.com/p/99f2a4c21986

官方文档

RN的Guide文档详细地介绍了整个过程,不过其中有些地方没说清楚,可能会给初学者埋下深坑。自己走过一遍,把这些坑列出来。这里整篇地援引原文档,并对原有顺序作了调整。

开发环境准备

首先需要搭建开发环境 ,才能进行后面的步骤。

添加JS环境

命令行,cd到项目到根文件夹下,然后按顺序执行下列命令:

$ npm init

$ npm install --save react

$ npm install --save react-native

$ curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig

注意一:init命令记住name参数

init命令,需要填写诸如name、version等参数,输入后按回车接着输入下一个参数。init之后会生出package.json文件。name最为重要,工程名,在后面的index.android.js和MyJReactActivity里都要用到。其它的都可以一路回车使用默认值。

845cbddeb37a

package.json文件

注意二:别忘了引入react

上面npm install --save react,下载react相关的资源包。原文里缺了这步命令,最终导致App跑起来就crash,大概是这样的:

java.lang.RuntimeException: Error: Requiring unknown module "react" (index.android.bundle:2 )

注意三:添加start,Json格式

打开刚生出的 package.json文件,在“scripts”内添加“start”,注意符合Json格式,逗号别忘了。

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1",

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

},

注意四:

curl命令从网络上下载文件,可从示例工程中复制

注意五:index.android.js里的name

按理说init的时候已经指定了“main”,也就是index.android.js,可是没有看到自动生成的文件。我们可以手动创建这份文件,名字就按照它给的来吧,作为hello world,我们照抄AwesomeProject的好了。这里特别要注意的是,最后的AppRegistry.registerComponent,第一个参数是前面package.json里设置的name,第二个参数是自定义的component。为什么是这样,现在还没去深究。

'use strict'

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('rntest', () => HelloWorld);

到此为止,Js的环境就配置完成了,后面开始Native部分的配置。

配置Native部分

项目app的build.gradle

里添加react-native依赖:

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

项目的gradle的repositories里添加url:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {

repositories {

jcenter()

}

dependencies {

classpath 'com.android.tools.build:gradle:2.2.2'

// NOTE: Do not place your application dependencies here; they belong

// in the individual module build.gradle files

}

}

allprojects {

repositories {

mavenLocal()

jcenter()

maven {

// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm

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

}

}

}

task clean(type: Delete) {

delete rootProject.buildDir

}

添加权限:

AndroidManifest.xml

/**设置调试 的权限**/

...

授权限

我们刚开始都是先用debug模式,以自己的开发计算机作为服务器。那份index.android.js就是hello world界面。手机在debug模式下从自己的计算机下载index页面。下载的过程会有个提示的dialog,显示它需要上面的权限。6.0及以上的系统,除了在Manifest里授权,还需要在系统设置里的“应用”里的“在其他应用的上层显示”里,找到我们的应用,勾选上允许。不同厂家的设置不太一样,我的是这样的:

845cbddeb37a设置

如果没有这些权限和设置,会抛这样的异常:

android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@fc0db15 -- permission denied for this window type

添加RN界面

MyReactActivity完整代码如下。需要注意的是,

setUseDeveloperSupport可以直接设为true,在debug期间

mReactRootView.startReactApplication()的第二个参数,必须是package.json里的name

package xxc.application1;

/**

* Created by proud2008 on 2016/11/5.

*/

import android.app.Activity;

import android.content.Context;

import android.content.Intent;

import android.os.Bundle;

import com.facebook.react.ReactInstanceManager;

import com.facebook.react.ReactRootView;

import com.facebook.react.common.LifecycleState;

import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;

import com.facebook.react.shell.MainReactPackage;

/**

* Created by Byron on 16/9/6.

*/

public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler {

private ReactRootView mReactRootView;

private ReactInstanceManager mReactInstanceManager;

public static void startActivity(Context context){

Intent intent = new Intent(context, MyReactActivity.class);

context.startActivity(intent);

}

@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(true)

.setInitialLifecycleState(LifecycleState.RESUMED)

.build();

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

setContentView(mReactRootView);

}

@Override

protected void onResume() {

super.onResume();

if(mReactInstanceManager != null){

mReactInstanceManager.onHostResume(this, this);

}

}

@Override

protected void onPause() {

super.onPause();

if(mReactInstanceManager != null){

mReactInstanceManager.onHostPause();

}

}

@Override

protected void onDestroy() {

super.onDestroy();

if(mReactInstanceManager != null){

mReactInstanceManager.onHostDestroy();

}

}

@Override

public void onBackPressed() {

super.onBackPressed();

if(mReactInstanceManager != null){

mReactInstanceManager.onBackPressed();

}else{

super.onBackPressed();

}

}

@Override

public void invokeDefaultOnBackPressed() {

super.onBackPressed();

}

}

运行你的应用

还是在项目的根文件夹下,命令行运行如下命令,启动测试服务器。

$ npm start

或者:

$ react-native start

845cbddeb37a

npm start成功

然后回到Android Studio,跟平常一样,把App运行起来。如果要运行在真机上,要注意在设备上运行的相关事项是否已经做过。我的测试机是6.0点系统,那每次连上usb,都需要先命令行运行一次:

adb reverse tcp:8081 tcp:8081

运行app

然后再运行app,否则手机无法连上测试服务器,会出现“红屏”(添加了DevSettingsActivity的情况下)。同样,如果测试服务器没有开启,也会出现同样的错误,也就是取不到打好包的js,控制台的crash log:

java.lang.RuntimeException: Could not get BatchedBridge, make sure your bundle is packaged correctly

错误1

Caused by: java.lang.IllegalAccessError: Method 'void android.support.v4.net.ConnectivityManagerCompat.()' 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)

at com.facebook.react.modules.netinfo.NetInfoModule.(NetInfoModule.java:55)

at com.facebook.react.shell.MainReactPackage.createNativeModules(MainReactPackage.java:67)

at com.facebook.react.ReactInstanceManagerImpl.processPackage(ReactInstanceManagerImpl.java:793)

at com.facebook.react.ReactInstanceManagerImpl.createReactContext(ReactInstanceManagerImpl.java:730)

at com.facebook.react.ReactInstanceManagerImpl.access$600(ReactInstanceManagerImpl.java:91)

at com.facebook.react.ReactInstanceManagerImpl$ReactContextInitAsyncTask.doInBackground(ReactInstanceManagerImpl.java:184)

at com.facebook.react.ReactInstanceManagerImpl$ReactContextInitAsyncTask.doInBackground(ReactInstanceManagerImpl.java:169)

at android.os.AsyncTask$2.call(AsyncTask.java:288)

at java.util.concurrent.FutureTask.

解决

修改 app/build.gradle

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

高版的会出问题,看生成的示例项目是用这个v7包,编译环境也是23

方法来自:https://github.com/facebook/react-native/issues/6152

错误2

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

11-05 12:20:24.257 4879-5218/xxc.application1 E/unknown:React: Exception in native call from JS

com.facebook.react.bridge.JSExecutionException: TypeError: undefined is not a function (evaluating '(bridgeConfig.remoteModuleConfig||[]).forEach')

因为项目根目录的build.gradle下没添加

allprojects {

repositories {

jcenter()

maven {

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

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

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值