Android React Native植入原生应用小记

一、React Native教程介绍

http://www.lcode.org/react-native/

http://reactnative.cn/docs/0.22/getting-started.html#content

二、植入流程:

0、准备工作及一些提示性:

本人系统为Win10系统,安装了visual studio2015,node.js4.1版本,curl,ssl,python2.7,Android Studio2.1版本及buildTools。

本人从github上down下来react-native,不过因本机之前曾经装过react-native-cli,所以报错。

Android React Native植入原生应用小记_第1张图片

本人本来打算卸掉react-native-cli重新编译react-native以作为全局性的react-native,但未获成功(可能中间哪步错了)。

注意:一个兼容性错误(react-native0.17.+和v7:23.2.+相冲突)

E/AndroidRuntime( 1530): Process: com.example.zhejiang.testapplication, PID: 1530

E/AndroidRuntime( 1530): java.lang.RuntimeException: An error occured while executing doInBackground()

E/AndroidRuntime( 1530):     at android.os.AsyncTask$3.done(AsyncTask.java:300)

E/AndroidRuntime( 1530):     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)

E/AndroidRuntime( 1530):     at java.util.concurrent.FutureTask.setException(FutureTask.java:222)

E/AndroidRuntime( 1530):     at java.util.concurrent.FutureTask.run(FutureTask.java:242)

E/AndroidRuntime( 1530):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)

E/AndroidRuntime( 1530):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)

E/AndroidRuntime( 1530):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)

E/AndroidRuntime( 1530):     at java.lang.Thread.run(Thread.java:864)

E/AndroidRuntime( 1530): Caused by: java.lang.IllegalAccessError: tried to access method android.support.v4.net.ConnectivityManagerCompat.:(Lcom/facebook/react/bridge/ReactApplicationContext;)V from class com.facebook.react.modules.netinfo.NetInfoModule

E/AndroidRuntime( 1530):     at com.facebook.react.modules.netinfo.NetInfoModule.(NetInfoModule.java:57)

E/AndroidRuntime( 1530):     at com.facebook.react.shell.MainReactPackage.createNativeModules(MainReactPackage.java:55)

E/AndroidRuntime( 1530):     at com.facebook.react.ReactInstanceManagerImpl.processPackage(ReactInstanceManagerImpl.java:692)

E/AndroidRuntime( 1530):     at com.facebook.react.ReactInstanceManagerImpl.createReactContext(ReactInstanceManagerImpl.java:633)

E/AndroidRuntime( 1530):     at com.facebook.react.ReactInstanceManagerImpl.access$600(ReactInstanceManagerImpl.java:78)

E/AndroidRuntime( 1530):     at com.facebook.react.ReactInstanceManagerImpl$ReactContextInitAsyncTask.doInBackground(ReactInstanceManagerImpl.java:169)

E/AndroidRuntime( 1530):     at com.facebook.react.ReactInstanceManagerImpl$ReactContextInitAsyncTask.doInBackground(ReactInstanceManagerImpl.java:155)

E/AndroidRuntime( 1530):     at android.os.AsyncTask$2.call(AsyncTask.java:288)

E/AndroidRuntime( 1530):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)

E/AndroidRuntime( 1530):     ... 4 more


解决方法:将support包版本改为

compile 'com.android.support:appcompat-v7:23.1.+'

1、在build.gradle中加入:

compile 'com.facebook.react:react-native:0.20.+'
2、修改minSdkVersion:

defaultConfig {
 ...
 minSdkVersion 16
 ...
}
3、增加网络权限:
<uses-permission android:name="android.permission.INTERNET" />
4、添加原生代码:

package com.zhejiangdaily;

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

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

/**
 * Created by zhejiang on 2016/3/24 0024.
 */
public class FirstReactActivity extends Activity implements DefaultHardwareBackBtnHandler {
    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, "MyAwesomeApp", null);

        setContentView(mReactRootView);
    }

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

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

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

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

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onResume(this, 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);
    }
}
5、把JS代码添加到原生应用:

在工程根目录,运行以下三个命令:

npm init
npm install --save react-native
curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig
上面的代码会创建一个node模块,然后 react-native作为npm依赖添加。现在打开新创建的 package.json文件然后在 scripts字段下添加如下内容:

"start": "node node_modules/react-native/local-cli/cli.js start"
复制并粘贴下面的这段代码到你工程根目录下的 index.android.js——这是一个简单的React Native应用:

'use strict';

var React = require('react-native');
var {
  Text,
  View
} = React;

class MyAwesomeApp extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.hello}>Hello, WorldText>
      View>
    )
  }
}
var styles = React.StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

React.AppRegistry.registerComponent('MyAwesomeApp', () => MyAwesomeApp);

6、开启服务器,编译包:

react-native start

gradlew.bat installDebug/assembleDebug

三、遇到的问题:

1、undefined is not an object (evaluating 'screenPhysicalPixels.width')

问题:所引用的react native版本过低,出错时所引用版本是0.17+

解决方法:

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

方法二:(没试过)

  1. Set "react-native": "^0.20.0", in package.json
  2. Delete node_modules
  3. Run react-native upgrade (updates android/app/build.gradle among others)
  4. Uninstall app on my phone
  5. react-native run-android

2、ReferenceError:Can't find variable:_fbBatchedBridge(line 1 in the generated

问题分析:Android手机和电脑服务器不在同一个网络下面

解决方法:

(Android 5.0及以上)使用adb reverse命令

首先把你的设备通过USB数据线连接到电脑上,并开启USB调试(关于如何开启USB调试,参见上面的章节)。

  1. 运行adb reverse tcp:8081 tcp:8081
  2. 不需要更多配置,你就可以使用Reload JS和其它的开发选项了。

(Android 5.0以下)通过Wi-Fi连接你的本地开发服务器

  1. 首先确保你的电脑和手机设备在同一个Wi-Fi环境下。
  2. 在设备上运行你的React Native应用。和打开其它App一样操作。
  3. 你应该会看到一个“红屏”错误提示。这是正常的,下面的步骤会解决这个报错。
  4. 摇晃设备,或者运行adb shell input keyevent 82,可以打开开发者菜单
  5. 点击进入Dev Settings
  6. 点击Debug server host for device
  7. 输入你电脑的IP地址和端口号(譬如10.0.1.1:8081)。在Mac上,你可以在系统设置/网络里找查询你的IP地址。在Windows上,打开命令提示符并输入ipconfig来查询你的IP地址。在Linux上你可以在终端中输入ifconfig来查询你的IP地址。
  8. 回到开发者菜单然后选择Reload JS

3、Unable to download JS bundle

问题分析:js名字(包括在package.json中)和React Native默认不一致。我当时的情况是js模板命名为index.js,在package.json中也是如此。但是运行时服务器提示

request:/index.android.bundle?platform=android&dev=true&hot=false

解决方法:将index.js改名为index.android.js,并且在package.json中也改名。重新运行gradlew.bat assembleDebug打包,并且重启服务器,运行react-native start


4、gradle编译 java.lang.OutOfMemoryError: GC overhead limit exceeded

问题分析:JVM7所设置的默认缓存大小太小导致编译失败。需要设置虚拟机堆内存空间大小,避免在编译期间OOM

解决方法:

在build.gradle中添加:

android {
 ...
 dexOptions {
    incremental true
    javaMaxHeapSize "4g"
 }
 ...
}

修改gradle.properties:(增加两处,当前主module下和node_modules下,搜一下全局的-Xmx)

org.gradle.jvmargs=-Xmx3096m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

5、com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536


问题分析:Android方法数65K限制,需要DEX分包

解决方法:(在build.gradle中修改)

dependencies { 
... 
   compile 'com.android.support:multidex:' 
   ... 
}

defaultConfig { 
   ... 
multiDexEnabled true 
... 
}
android:name="android.support.multidex.MultiDexApplication"

最后,重新build。


6、com.android.build.api.transform.TransformException: com.android.builder.packaging.DuplicateFileException: Duplicate files copied in APK lib/armeabi/libwebp.so

问题分析:so文件重复了(ImageLoader增加的WebP和Fresco本身所带有的WebP所冲突)

解决方法:删除冲突文件


写在最后的话:

转载请转自:

如有问题,请联系QQ838704711



你可能感兴趣的:(android)