1. 程式人生 > >Android React Native植入原生應用小記

Android React Native植入原生應用小記

一、React Native教程介紹

二、植入流程:

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
上面的程式碼會建立一個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.+"
}

方法二:(沒試過)

  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

http://i.stack.imgur.com/bNYBH.png

問題分析: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

問題分析: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 React Native植入原生應用小記

一、React Native教程介紹 二、植入流程: 0、準備工作及一些提示性: 本人系統為Win10系統,安裝了visual studio2015,node.js4.1版本,curl,ssl,python2.7,Android Studio2.1版本及buildToo

React Native嵌入原生應用的坑

今天試著在原生應用中引入React Native,本以為按照官網的步驟來做就沒問題,結果著實踩了很多坑。現記錄下來,防止以後踩同樣的坑 一、React Native專案在64位android手機上執行,會提示 "/data/data/com.xxx.xxx/lib-main/libgnustl_shared.

Android React Native使用原生模組

有時候我們的App需要訪問平臺API,並且React Native可能還沒有相應的模組包裝;或者你需要複用一些Java程式碼,而不是用Javascript重新實現一遍;又或者你需要實現某些高效能的、多執行緒的程式碼,譬如圖片處理、資料庫、或者各種高階擴充套

React-Native原生的3種互動通訊(Android

前言 最近到新公司,採用React-Native開發App。在某些效能方面有問題或者模組特殊的開發情況,不可避免的需要我們原生開發(Android\IOS)給予前端開發支援。 在為前端書寫模組部分,不可避免的要接觸核心的通訊部分。 大致分為2種情況:

基於React Native封裝的表單提交Container,用於替代RN官方元件KeyboardAvoidingView(不相容Android)react-native-keyboardavoidv

react-native-keyboardavoidview 基於React Native封裝的表單提交Container,用於替代RN官方元件KeyboardAvoidingView(不相容Android) Theory 重寫TextInput的onFocus方法,藉助Sc

[Android] React Native技術精講與高質量上線APP開發 多棧技術

【多棧技術更有競爭力】本課程將手把手帶你用RN技術開發、優化、直到最後釋出上線一款完整的跨平臺APP;讓你擁有一次真正參與上線專案開發的歷程,同時全面掌握React Native技術,使你的技術能力和專案經驗都得到前所未有的提升! https://pan.baidu.com/s/1p4c

動手建立一個自己的「React native原生模組

前言 我們在使用RN的時候,會發現RN提供了很多Module供JS呼叫,這些Module能夠滿足我們一些基礎的應用場景,但是在實際的專案中,必定會有一些互動邏輯需要我們自己去實現,這時候就需要我們自定義一些Module供JS呼叫,那麼怎麼才能讓JS呼叫到我們自定義的Module呢? 下面我們就一步步的去實現

react native接入原生專案(mac pro)

首先保證安裝了node,watchman,yarn。 1.新建一個資料夾A,裡面新建一個資料夾android,然後把專案根目錄下所有內容放入這個android裡。直接全選複製的話沒有git,可以把整個專案移過去再改名為android。 2.在A下新建package.json: {

React Native iOS原生模組開發實戰|教程|心得|如何建立React Native iOS原生模組

尊重版權,未經授權不得轉載 本文出自:賈鵬輝的技術部落格(http://blog.csdn.net/fengyuzhengfan/article/details/54691432) 告訴大家一個好訊息,為大家精心準備的React Native視訊教程釋出了,大家

React Native原生iOS Objective-C的互動解決方案

用一個RCTRootView作為iOS裡一個Controller的view。在RN層的左上角返回按鈕點選後pop回iOS層。發現無法執行,除錯發現controller的navigationCont的值是空的。發現與RN互動的這個self地址和iOS層的self並不是同一個

React Native封裝原生元件釋出到npm

因為一個任務,要寫原生的獲取使用者手機資料夾,實現使用者自定義資料夾的功能,寫好了之後嘗試封裝成元件。1. 首先,有一個rn專案,用Adnroid Studio開啟 android -> app -> build.gradle如圖新建一個 Android Modu

React Native原生互動

React Native 與原生互動一般有三種方式,分別是Callback,Promise,RCTDeviceEventEmitter import {   AppRegistry,   StyleSheet,   Text,   View,   NativeModule

React Native在直播應用中的實踐

React Native是近年來最值得花時間學習的移動開發新技術,其在不斷進化、成熟的同時,效能也在持續提升。卜赫主要分享了React Native Pili在開發過程中的設計斟酌和踩過的坑。以下是正文: React Native是什麼 React Native的i

React Native原生之間的通訊(iOS)

本文將講述下在原生和React Native之間的通訊方式。方式和邏輯綜合了自己的思維方式,主要參考了React Native中文官方文件,因為感覺它講的方式有些不妥,所以就按自己思路組織了下文。 雖然發覺一遍文章要把所有通訊方式講清楚不太科學,不過把思路講講倒是可以,

React Native原生app通訊機制詳解

概述 React Native用iOS自帶的JavaScriptCore作為JS的解析引擎,但並沒有用到JavaScriptCore提供的一些可以讓JS與OC互調的特性,而是自己實現了一套機制,這套機制可以通用於所有JS引擎上,在沒有JavaScriptCor

react-native 呼叫原生方法

第一步,新建MyReactPackage.java: package com.goodthingshappeneverday; import com.facebook.react.ReactPackage; import com.facebook.react.bridge

react native原生和RN的互動

前言:前端時間隨著自己的學習和研究,也寫了幾篇關於react native的文章,雖然都是比較簡的,但是都是根據自己的效果來做的流程,所以還是比較實用的,可以避免很多的坑。這篇react native

react-native封裝原生下拉重新整理元件

之前改進過一個react-native-pull元件解決了iOS上重新整理頭部出現空白問題,並且將listview改成了flatlist。 github如下: react-native-pullvi

react-native 呼叫原生模組詳解

 一,繼承 ReactContextBaseJavaModule 實現如下方法 自定義方法用 @ReactMethod註釋 /** * 日誌列印module * Created by ybj on 2016/2/26.

React Native 使用原生 UI 元件

在之前的一篇文章中,我記錄了已有的Android專案如何接入React Native,介紹了RN如何呼叫原生的方法,本篇文章上在之前的一篇的文章的基礎上續寫的,這一篇文章中我將記錄Android如何封裝原生元件,然後RN來使用它。如果對接入RN還不太瞭解的,可以看看我的另一篇文章 Android原生專案接