摘要:在應用內添加依賴回到,到的文件級別的里添加依賴最后一行的就是我們新增的,注意這里的版本號要和里的一致。因此,建議用這樣的寫法,并檢查版本號是否和里的一致。
引言
React Native是現在移動開發新的可選方案,也帶來了原屬于Web領域的React的優秀開發特性。另一方面,React Native的技術棧一經掌握,可以用于iOS、Android及Windows(見此)多個平臺,即所說的“learn once, write anywhere”。
開始使用React Native的問題如何使用React Native?參照官方指南,你會發現官方告訴你的是:請用react-native init命令來創建一個React Native項目。這個項目的根目錄結構是這樣:
但是,以Android為例,一個普通原生項目的根目錄結構卻是這樣(Android Studio 2.1.2):
可以看到,Android原生項目(上圖的Drill根目錄)平級于生成的React Native項目的android目錄。那么,如果一直以來都是Android原生開發,現在想要引入React Native,考慮部分頁面用React Native實現,應該如何做呢?
這就是React Native植入原生應用的問題。顯然,react-native init命令生成的項目在結構上不太相符,它的出發點更像是“完全用React Native做一個多平臺應用”,但我們可能需要的是“一個原生應用但有部分內容是用React Native做的”。
在本文的時間點,React Native的最新版是0.27。官方對此已給出植入原生Android應用的指南,但它不夠準確,也缺少一些細節。因此,本文將提供一個React Native植入原生Android應用的更詳細一點的流程。
如果你想了解iOS版的,可以閱讀這篇文章。
植入Android流程 基本環境這篇流程是windows及Android Studio,如果你已經是一個Android Studio原生應用開發者,以及Node.js用戶,那么所需的環境你基本已經有了。詳情請參考windows環境搭建文字教程以及開始使用React Native,什么都沒有也沒關系,正好從頭搭建。
此外,Android模擬器使用了Genymotion,注冊后就可以供個人使用,會比官方模擬器性能要好一些。
新建Android項目讓我們從一個全新的Android原生應用開始。
用Android Studio創建一個新項目,注意Minimum SDK應設置為API 16及以上(React Native要求Android4.1以上的環境):
添加npm組件到Android原生項目的根目錄(也可以新建一個目錄,但根目錄比較常用)新建一個文件package.json,內容如下(這里起名為react-native-module):
{ "name": "react-native-module", "version": "0.0.1", "private": true, "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start" }, "dependencies": { "react": "^15.1.0", "react-native": "^0.27.2" } }
下面的dependencies的內容要如何得知呢?答案是參考react-native init生成的項目,畢竟版本號是會不斷更新的。如果你已經init生成過項目,可以運行react-native upgrade更新后再參考。
然后,在這個package.json的所在位置,執行:
npm install
安裝好所需的npm組件。
添加index.android.js文件同樣在根目錄,增加一個文件index.android.js,這是React Native開發的具體內容,是任意的,這里給一個簡單的例子:
import React, { Component } from "react"; import { AppRegistry, StyleSheet, Text, View } from "react-native"; class App extends Component { render() { return (); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", alignItems: "center", }, note: { fontSize: 20 } }); AppRegistry.registerComponent("react-native-module", () => App); acgtofe.com with react native
注意上面代碼最后的react-native-module這個名字比較重要,可以自定,但后面還會在其他地方用到,需要保持一致。
在Android應用內添加依賴回到Android Studio,到app的build.gradle文件(module級別的gradle)里添加依賴:
dependencies { compile fileTree(dir: "libs", include: ["*.jar"]) testCompile "junit:junit:4.12" compile "com.android.support:appcompat-v7:23.4.0" compile "com.facebook.react:react-native:0.27.2" }
最后一行的react-native就是我們新增的,注意這里的版本號要和package.json里的一致。
運行一次Gradle Sync,你必然會得到這個錯誤:
這是因為Android項目默認的依賴包的源jcenter()并不包含最新版的React Native(它只到0.20.1)。新版的React Native都只在npm里發布,因此你需要增加一下依賴包的源,到根目錄的build.gradle文件(project級別的gradle)內增加以下內容(從官方的這句注釋也可以了解到這一點):
allprojects { repositories { jcenter() maven { // All of React Native (JS, Android binaries) is installed from npm url "$projectDir/../node_modules/react-native/android" } } }
這里的url路徑,將取決于你放置node_modules的位置(你可以根據需要選擇放置在其他地方)。以上是node_modules位于根目錄時的url路徑,把它改為"$rootDir/node_modules/react-native/android"也是可以的,它們等效。如何知道這個路徑寫對了呢?反復試就可以了,如果路徑不對,Gradle Sync的時候一定會提示你前面的錯誤。
你可能在很多別的地方看到的都是這樣的寫法:
compile "com.facebook.react:react-native:+"
不太建議這樣做,因為沒有明確的版本號,你無法讓系統幫你判斷前面的url路徑寫的是否正確。如果寫錯,Android將使用發布在jcenter()的舊版React Native,而這將引發其他錯誤(見后文)。
新建React Native的Activity新建一個繼承自ReactActivity的activity(這里起名為LiveActivity),Android Studio會提醒你必須實現3個方法,一般寫成這樣:
public class LiveActivity extends ReactActivity { @Override protected String getMainComponentName() { return "react-native-module"; } @Override protected boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected ListgetPackages() { return Arrays. asList( new MainReactPackage() ); } }
getMainComponentName()的字符串返回值,必須和前面的index.android.js內的組件名一致。
getUseDeveloperSupport()是一個邏輯返回值,表示是否啟用開發者模式。這里寫BuildConfig.DEBUG就可以自動根據gradle構建的類型(debug或release)來決定。
getPackages是模塊列表,一般像上面代碼這樣就可以。如果你需要在JavaScript里調用原生Java模塊,就要把它們添加到這里,具體可以參考這篇文章。
清單文件添加聲明到Android清單文件AndroidManifest.xml添加以下內容(省略了無關部分):
...
前面的權限都是React Native開發環境需要用到的。后面的LiveActivity是剛才的React Native運行界面,DevSettingsActivity則是以下這個Dev Settings的界面:
它也是開發版所必需的。
啟動packager server到package.json的位置,打開命令行,運行packager server:
react-native start
也可以用npm start。啟動后的狀態看起來像這樣:
運行起來這是最后一步了。build這個Android項目,安裝到模擬器里,然后打開應用,切換到LiveActivity界面(用按鈕跳轉,或者直接設置為啟動界面都可以),這時候應該只看到一片空白。
按ctrl + m(這是Genymotion的用法,事實上,這是Android的Menu鍵,現在的實體設備基本沒有這個鍵,但搖一搖可以觸發)開啟調試菜單,選擇Dev Settings,打開前面貼過圖的DevSettingsActivity,設置Debug server host & port for device為本機ip地址(命令行內ipconfig查看)。最后,回到LiveActivity,開啟調試菜單選擇Reload JS,等待一會兒,如果你看到了像下圖這樣的界面:
就說明完成了!對應的,packager server里應該可以看到每一次請求的記錄:
接下來,你就可以開始React Native的開發了,改動保存后,重新Reload JS,就可以看到新的效果。
建議及改進建議使用Android 5.0+的設備(包括模擬器),它們支持直接USB傳輸packager server返回的那個bundle js文件。如果是Android 5.0+,可以USB連接電腦后(如果是模擬器,那就等于已經連接)運行以下命令:
adb reverse tcp:8081 tcp:8081
然后就可以省略掉前面流程里設置本機ip地址那一步,直接Reload JS。注意設備需要開啟USB調試(模擬器不用),而且電腦同時只連接一個設備。
相對于前面設置本機ip地址的方式,這幫你免去了同一WiFi環境、代理等麻煩。
不順利的情況雖然流程看起來輕松愉快,但并不怎么能一次成功。下面是我在流程中碰到過的一些問題及其記錄,可以用作參考。
版本不匹配錯誤提示如下:
參照github上的issue,這個錯誤的引發原因是packager server的React Native版本和Android應用內的不一致。比如應用內的gradle依賴寫的是compile "com.facebook.react:react-native:+"但url路徑寫得不對,結果用的就是jcenter()里的0.20.1的舊版,就會有這個問題。
因此,建議用compile "com.facebook.react:react-native:0.27.2"這樣的寫法,并檢查版本號是否和package.json里的一致。
404這是說index.android.js文件不存在的錯誤。但我碰見的是文件就在那,也出這個錯誤。
這可能是由不正確的緩存引起,我的解決方法:關閉server,刪除index.android.js,然后重啟server,刷新,得到真正的404,然后還原index.android.js,再刷新即解決。
無法連接到server先按照Try the following to fix the issue: 下給出的解決方法依次檢查和嘗試。如果仍不能解決,刪除掉node_modules目錄,重新npm install,然后重開server。
windows下刪除node_modules目錄可能有路徑過長的問題,推薦用rimraf來刪除。
500這個問題需要具體看server的輸出,我這里的錯誤信息是:Error: Unable to find file with path: ......polyfillsprelude_dev.js。類似前面的無法連接server,我也是刪除node_modules后重新安裝得到解決。
有用的調試方法流程中可能碰到的問題可以分為兩類,Android應用(client)和server。如果看到錯誤,打開瀏覽器訪問http://localhost:8081/index.android.bundle?platform=android,如果能看到輸出的JavaScript代碼,那說明server是比較正常的,更可能是Android應用的問題。反過來,如果瀏覽器里同樣看到錯誤信息,那更可能就是server的問題。
沒有Flow和Nuclide你可能在開始用React Native的過程中聽說了Flow和Nuclide,它們分別是JavaScript類型檢查工具及React Native的推薦IDE。
但請注意,在本文的時間點,它們還沒有windows版。我是用Atom來開發React Native的。
發布正式版React Native的開發版是需要有一個packager server來隨時發送更新后的bundle js文件的。但如果要得到真正簽名的正式版(app-release),你需要把bundle js文件保存到Android應用的資源目錄內。這樣,正式版不再需要server支持,可以獨立運行。
參照官方的發行APK包指南,你只需要這樣幾步:
創建目錄app/src/main/assets。
運行以下命令(對應本文流程的目錄結構),將bundle js文件保存到資源目錄。
react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --assets-dest app/src/main/res/
在Android Studio里選擇Build→Generate Signed APK...,生成正式版的apk。
官方有提到使用react.gradle文件的方法,但我覺得像上面這樣不用它更簡單。
正式版的即時更新看起來正式版把bundle js文件保存到了apk內,這好像就丟失了React Native的即時更新?對的,但仍然有辦法實現它,你可以看看React-Native-Remote-Update,這個項目已經過時了,但里面貼出的原理很值得參考。
現在,你可以用react-native-auto-updater來幫助你實現React Native的即時更新。
參考資料集我在寫本文的過程中參考了下面三個資料集合,覺得非常棒,在此也貼出來:
React-Native學習指南
Android開發技術周報特刊之React Native
react-native-android-guide
結語React Native的Android版本是去年9月(2015.9.15)才推出,此前只有iOS版。相對來說,Android的相關教程要比iOS少很多。因此,我覺得有這樣一份windows + React Native for Android的組合流程會很有幫助。
來嘗試新的移動開發方案吧!
(重新編輯自我的博客,原文地址:http://acgtofe.com/posts/2016/06/react-native-embedding-android)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79740.html
摘要:閱讀本期周刊,你將快速入門,開啟甜蜜之旅。然則的原理負責發送以及處理消息,創建消息隊列并不斷從隊列中取出消息交給,則用于保存消息。 showImg(/img/bVCN99?w=900&h=385); 2016 年 8 月,Android 7.0 Nougat(牛軋糖)正式發布,那么問題來了,你 Marshmallow 了么(? -? ?) Cupcake、Donut、Gingerbre...
閱讀 2127·2019-08-29 16:53
閱讀 2705·2019-08-29 16:07
閱讀 2047·2019-08-29 13:13
閱讀 3271·2019-08-26 13:57
閱讀 1336·2019-08-26 13:31
閱讀 2439·2019-08-26 13:22
閱讀 1227·2019-08-26 11:43
閱讀 2089·2019-08-23 17:14