您的位置:首页 > Web前端 > React

Android React Native植入原生应用小记

2016-03-28 15:55 701 查看
一、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,所以报错。



本人本来打算卸掉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.<init>:(Lcom/facebook/react/bridge/ReactApplicationContext;)V from class com.facebook.react.modules.netinfo.NetInfoModule

E/AndroidRuntime( 1530): at com.facebook.react.modules.netinfo.NetInfoModule.<init>(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[/code] 上面的代码会创建一个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, World</Text>
</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.+"
}


方法二:(没试过)

Set
"react-native": "^0.20.0",
in
package.json

Delete
node_modules

Run
react-native upgrade
(updates
android/app/build.gradle
among others)
Uninstall app on my phone
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调试,参见上面的章节)。

运行
adb reverse tcp:8081 tcp:8081

不需要更多配置,你就可以使用
Reload JS
和其它的开发选项了。

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

首先确保你的电脑和手机设备在同一个Wi-Fi环境下。
在设备上运行你的React Native应用。和打开其它App一样操作。
你应该会看到一个“红屏”错误提示。这是正常的,下面的步骤会解决这个报错。
摇晃设备,或者运行
adb shell input keyevent 82
,可以打开开发者菜单
点击进入
Dev Settings

点击
Debug server host for device

输入你电脑的IP地址和端口号(譬如10.0.1.1:8081)。在Mac上,你可以在系统设置/网络里找查询你的IP地址。在Windows上,打开命令提示符并输入
ipconfig
来查询你的IP地址。在Linux上你可以在终端中输入
ifconfig
来查询你的IP地址。
回到开发者菜单然后选择
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


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: