大概是2017年底接觸的RN,當(dāng)時(shí)項(xiàng)目開發(fā)中遇到很多問題,都是自己一步一個(gè)坑走過來的。看了下當(dāng)時(shí)的筆記,覺得還是在這里記錄下,防丟失。
React-native APP 開始
App Store下載Xcode并安裝(about one hour)
下載并安裝Android studio:https://developer.android.com/studio/index.html(需翻墻,take too long)
npm install -g react-native-cli
-
react-native init MyApp(最新版可能下載失敗導(dǎo)致無法成功run ios,所以用下面的version)
react-native init MyApp --version 0.44.3
iOS模擬器調(diào)試
cd 進(jìn)入MyApp目錄下(你的項(xiàng)目目錄)
react-native run-ios
-
若報(bào)錯(cuò):
xcrun: error: unable to find utility "instruments", not a developer tool or in PATH
解決:
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer/
-
若模擬器爆紅:No bundle URL present
解決1:在模擬器運(yùn)行期間 項(xiàng)目目錄下執(zhí)行npm install
解決2:檢查翻墻的代理,由全局模式改為自動(dòng)模式即可
?
iOS真機(jī)調(diào)試
打開Xcode
綁定Apple ID:Xcode 》preferences 》accounts
選中左側(cè)project根目錄,點(diǎn)擊右側(cè)General配置
identity 》Bundle identifier 輸入唯一標(biāo)識(shí)(保證唯一即可)
Signing 》Team 選中剛剛綁定的Apple ID對(duì)應(yīng)的team
點(diǎn)擊左上角run 按鈕右側(cè)運(yùn)行設(shè)備選項(xiàng),選中USB已連接的你的設(shè)備
run
過程中出問題按照提示對(duì)設(shè)備進(jìn)行授權(quán)配置
若build時(shí)就出錯(cuò),嘗試重啟Xcode,再run
若connect server error:查看手機(jī)電腦wiffi是否一致,若不一致,停掉服務(wù)重新run
若報(bào)錯(cuò)
The application does not have a valid signature.
clean下重跑
android調(diào)試
cd進(jìn)入MyApp目錄
react-native run-android
-
若報(bào)錯(cuò):Error watching file for changes: EMFILE
解決辦法:watchman出錯(cuò),卸載并重裝
brew uninstall --force watchman
rm -rf/usr/local/var/run/watchman/
brew install watchman
錯(cuò)誤信息不明時(shí)可打開android studio查看詳情
-
若gradle的問題:可能因?yàn)閍ndroid studio 的gradle沒加載成功,修改gradle-wrapper.properties文件內(nèi)url為其他版本,例:
https://services.gradle.org/distributions/gradle-3.3-all.zip
或改成本地地址在setting內(nèi)加以配置
可通過http://localhost:8081/index.android.bundle?platform=android去驗(yàn)證服務(wù)是否成功開啟
-
報(bào)錯(cuò)could not connect development server:(坑!)
(1). android studio debug運(yùn)行模式,
(2). 打開命令行,cd到當(dāng)前目錄,react-native start
(3). 真機(jī)或模擬器reload,成功與否
(4). 若失敗:adb reverse tcp:8081 tcp:8081,reload(5). 若command adb not found:"adb"不是內(nèi)部命令和sudo: adb: command not found
-
真機(jī)adb無響應(yīng):(可能因?yàn)槠渌麘?yīng)用占用adb的5037端口)
解決:netstat -aon|findstr “5037” 找到占用端口的進(jìn)程PID,? 打開任務(wù)管理器,殺掉對(duì)應(yīng)進(jìn)程。? 重新run
?
react-native學(xué)習(xí)指南
參考:給所有開發(fā)者的React Native詳細(xì)入門指南
引用antd-mobile的坑
對(duì)于莫名其妙的問題,確保自己antd-mobile的版本不要太低,坑
對(duì)于找不到module的問題,請(qǐng)用yarn安裝,cnpm安裝可能會(huì)漏掉一些依賴
對(duì)于antd-mobile not defined 的錯(cuò)誤,確保安裝了react-dom,antd-mobile,babel-plugin-import,并且修改.babelrc 文件,例:
{
"plugins": [["import", { "libraryName": "antd-mobile" }]], "presets": ["react-native"]
}
在react-native使用Icon
-
使用antd-mobile的Icon
RN 版本由于 Icon 無法做純 UI,需要 native 支持
下載
https://at.alicdn.com/t/font_r5u29ls31bgldi.ttf
重命名為anticon.ttf
打開 iOS 項(xiàng)目
info.plist
文件,添加Fonts provided by application
,指定一個(gè) item 的值為anticon.ttf
, 將anticon.ttf
拖進(jìn)項(xiàng)目;Android 項(xiàng)目將
anticon.ttf
放在android/app/src/main/assets/fonts/
目錄下;
使用方式:
內(nèi)置的幾個(gè)圖標(biāo): <Icon type="check" size="md" color="red" />
自定義圖標(biāo):<Icon type={'\ue601'} size={55} /> (具體參看 demo)
自定義圖標(biāo):<Icon type={'\ue601'} size={55} /> (具體參看 demo)</pre>
-
使用react-native-vector-icons
參考react-native-vector-icons的簡(jiǎn)單使用
Icon選用參考:http://fontawesome.io/icons/
?
若出現(xiàn)搜不到的問題,嘗試卸載APP重啟
native-echarts
-
Android 上圖表有時(shí)不顯示問題
原因:圖形渲染支持的不好?
解決:隱藏包含echart的div,數(shù)據(jù)填充渲染結(jié)束后顯示div,中間要有一定時(shí)間的延遲,比如100ms
?
android打包
根據(jù)RN官網(wǎng)推薦方式打包
-
若類似錯(cuò):
Could not find com.android.tools.build:gradle:3.0.0.
可能:自己android studio版本不是3.0.0,換成對(duì)應(yīng)版本
或者:android/build.gradle下
buildscript {
repositories {
...
google()
}
}
-
若報(bào)錯(cuò):
Could not get unknown property 'MYAPP_RELEASE_STORE_FILE'
原因:將如下代碼加入到android/gradle.properties, **改為密鑰
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=****
MYAPP_RELEASE_KEY_PASSWORD=****
-
項(xiàng)目中用到react-native-echarts,在android打包后無法顯示圖表:
原因:release版本只能使用uri加載資源(???)
解決:
把node_modules/native-echarts/src/components/Echarts/tpl.html文件復(fù)制一份到android/app/src/main/assets文件里
修改node_modules/native-echarts/src/components/Echarts/index.js:
source={require('./tpl.html')}
改為source={{uri:'file:///android_asset/tpl.html'}}
打包后記得改回來,不然ios無法正常顯示圖表
-
修改版本信息:
android在android/app/build.gradle文件下修改
其中versionCode一般是整數(shù),上傳appstore時(shí),每次都需比上次數(shù)字要大,否則不予覆蓋上一版本
versionName用于在app上顯示版本信息,供自己或用戶查看
defaultConfig{
versionCode 1
versionName "1.0"
}
- ?
IOS打包
在Xcode中選擇Product -> Scheme -> Edit Scheme (cmd + <),然后選擇Run選項(xiàng)卡,將Build Configuration設(shè)置為release
在ios中用http請(qǐng)求需做配置,參照讓iOS項(xiàng)目允許使用http協(xié)議請(qǐng)求
run,若想調(diào)試,將Build Configuration重新設(shè)置為debug
設(shè)置應(yīng)用圖標(biāo)和閃屏圖片react native ios打包到真機(jī)
若出現(xiàn)其他手機(jī)無法run release版本,報(bào)錯(cuò):
can't link with a main executable file '/Users/liujinling/Library/Developer/Xcode/DerivedData/gngcApp-glzeunbnyelbpmcrehcygunmtjfq/Build/Products/Release-iphoneos/gngcApp.app/gngcApp' for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
解決:
product ->schema-> edit ->schema-> run
選擇release build
中xxxTests
只勾選Test
, build
中xxx 勾選全部
-
賬號(hào)下手機(jī)連接數(shù)量達(dá)上限,無法使用其他手機(jī)調(diào)試或安裝:
原因:免費(fèi)的賬號(hào)連接設(shè)備數(shù)應(yīng)該是3個(gè)左右,想連接更多的測(cè)試機(jī),升級(jí)到收費(fèi)賬號(hào),可連100個(gè)設(shè)備
解決:1. 申請(qǐng)企業(yè)收費(fèi)開發(fā)者賬號(hào)
? 2. General/signing/Team:添加一個(gè)新的account
-
安裝release版時(shí)報(bào)錯(cuò):
Could not write to the device
,或A valid provisioning profile for this executable was not found.
:原因:我這里因?yàn)榍袚Qteam(開發(fā)者賬號(hào))導(dǎo)致
解決:Xcode上方導(dǎo)航欄product下clean操作,重新run
?
Mac 下gradle配置
android studio 下載gradle極慢,所以下載到本地自己配置
下載所需版本:http://services.gradle.org/distributions/ (例:gradle-4.1-all)
命令open .gradle 打開finder,
進(jìn)入wrapper/dists/gradle-4.1-all/(njsjdscn),刪掉目錄下所有
將下載的gradle-4.1-all.zip拉進(jìn)來,重啟android studio
記一次重大填坑現(xiàn)場(chǎng)
在android和ios真機(jī)+模擬器run成功n次,雙機(jī)打包均跑成功后,再次android真機(jī)調(diào)試時(shí),突然的gradle構(gòu)建失敗!!!WTF
詭異1:android打包時(shí)按照react-native官網(wǎng)配置了一些文件,今天打開代碼,發(fā)現(xiàn)一會(huì)這里多了個(gè)‘g’,一會(huì)那里classpath被刪掉,還有其他的屬性名缺了一半,連gradle.zip后面緊跟了個(gè)’android‘……細(xì)思極恐
詭異2:react-native-linear-gradient庫突然無法正確引入?錯(cuò)誤提示:com.facebook.react:react-native:+
詭異3:android/app/build.gradle文件找不到com.facebook.react:react-native:+
解決:
- 在android studio 報(bào)錯(cuò)處跟蹤進(jìn)react-native-linear-gradient,添加一塊代碼,既然gradle找不到
com.facebook.react:react-native:+
,我們就告訴他怎么找
repositories {
jcenter()
}
- 在android/app/build.gradle添加如下代碼
allprojects {
repositories {
jcenter()
mavenCentral()
mavenLocal()
maven {
// All of React Native (JS, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
}
}
若url "$rootDir/../node_modules/react-native/android"
報(bào)錯(cuò),將其改為url "$rootDir/node_modules/react-native/android"
。應(yīng)該是通過yarn安裝的react-native使用前者,通過npm安裝的使用后者
莫名其妙的坑,踩了一下午,燥
又一次重重大填坑現(xiàn)場(chǎng)
RN Android 文件預(yù)覽
-
利用
react-native-doc-viewer
*注意注釋部分
const handlePress = (name,id) => {
const nameArr = name.split('.');
const type = nameArr[nameArr.length - 1];
//Interface.downloadUrl + id是文件的下載地址
const downloadUrl = Interface.downloadUrl + id + '.' + type;
if (Platform.OS === 'ios') {
//IOS(成功預(yù)覽)
OpenFile.openDoc([{
url: downloadUrl,
//此處url后綴必須帶文件type(例:.doc)
//原因:ios配置沒有fileType,需靠url后綴識(shí)別文件類型
fileNameOptional: name
//ios的fileNameOptional取值中文是ok的
}], (error, url) => {
if (error) {
console.error(error);
} else {
console.log(url, '成功')
}
})
} else {
//Android(除圖片外,其他無效,打不開文件)
OpenFile.openDoc([{
url: Interface.downloadUrl + id,
//此處url直接為下載地址,無需特意加類型后綴
fileName: name,
//Android的fileName取值中文報(bào)錯(cuò)
cache:false,
fileType:type
}], (error, url) => {
if (error) {
console.error(error);
} else {
console.log(url, '成功')
}
})
}
}
- 輔助
react-native-fs
//Android
const SavePath = RNFS.DocumentDirectoryPath;
//const SavePath = RNFS.ExternalDirectoryPath;
//const SavePath = RNFS.ExternalStorageDirectoryPath;
//當(dāng)配合react-native-doc-viewer,以上三個(gè)路徑均測(cè)試,無法打開文件
//當(dāng)配合原生模塊,使用第二個(gè)
//const SavePath = RNFS.MainBundlePath //ios的存儲(chǔ)路徑
const options = {
fromUrl: downloadUrl,
//加不加類型后綴都o(jì)k
toFile: `${SavePath}/${name}`,
};
RNFS.downloadFile(options).promise.then(res => {
console.log(res, 'res')
//配合react-native-doc-viewer(無效)
OpenFile.openDoc([{
url: `file://${SavePath}/${name}`,
//此處url為系統(tǒng)內(nèi)部路徑,前面需加‘file://’
fileName: name,
//Android的fileName取值中文報(bào)錯(cuò)
cache:false,
fileType:type
}], (error, url) => {
if (error) {
console.error(error);
} else {
console.log(url, '成功')
}
})
//配合原生模塊(成功)
NativeModules.OpenFileModule.show(`${SavePath}/${name}`)
}).catch(err => {
console.log(err, 'err')
})
-
react-native-fs
加原生模塊實(shí)現(xiàn)
//任意位置新建一個(gè)類(java文件)
package com.reactNativeModules;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.webkit.MimeTypeMap;
import android.widget.Toast;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.io.File;
import java.util.Locale;
public OpenFileModule(ReactApplicationContext reactContext){
super(reactContext);
}
@Override
public String getName(){
return "OpenFileModule";
}
//getName為必需
@ReactMethod
private void show(final String filePath)
{
String ext = filePath.substring(filePath.lastIndexOf('.')).toLowerCase(Locale.US);
try
{
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
String temp = ext.substring(1);
String mime = mimeTypeMap.getMimeTypeFromExtension(temp);
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
File file = new File(filePath);
intent.setDataAndType(Uri.fromFile(file), mime);
//這里原本:startActivity(intent);
//但由于react調(diào)原生方法,不存在原生activity,報(bào)錯(cuò),使用下面兩句代替
Activity currentActivity = getCurrentActivity(); currentActivity.startActivity(intent);
}
catch (Exception e)
{
e.printStackTrace();
Toast.makeText(getReactApplicationContext(), "無法打開后綴名為." + ext + "的文件!",
Toast.LENGTH_LONG).show();
}
}
//任意位置定義一個(gè)包(java文件)
package com.reactNativeModules;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by liujinling on 2018/1/23.
*/
public class OpenFilePackage implements ReactPackage{
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
//OpenFileModule為上文新建的類名
modules.add(new OpenFileModule(reactContext));
return modules;
}
//此處為必需
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
}
//在mainactivity.java內(nèi)注冊(cè)模塊(必需)
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
//OpenFilePackage為上文新建的包名
new MainReactPackage(),new OpenFilePackage());
}
//js中使用
import {NativeModules} from 'react-native';
//注意這里的path需帶文件類型后綴
//且前面不要加‘file://’
//直接取RNFS.ExternalDirectoryPath存儲(chǔ)的地址
const path = '/data/file/test.doc'
NativeModules.OpenFileModule.show(path)
android中TextInput頂起TabBar問題
目錄:android/app/src/main/AndroidManifest.xml
中的<activity>標(biāo)簽中,添加android:windowSoftInputMode="stateAlwaysHidden|adjustPan|adjustResize"
gngcApp極光推送
蘋果開發(fā)者平臺(tái):蘋果開發(fā)者平臺(tái)
證書配置:iOS 證書申請(qǐng)和使用詳解
官方描述證書配置:iOS 證書設(shè)置指南
-
若報(bào)錯(cuò):
The provisioning profile specified in your build settings ("test") has an AppID of "com.baidu.test" which does not match your bundle identifier "com.apple.test"
原因:info.plist文件中的bundle ID與創(chuàng)建證書時(shí)的不一致
解決:
修改info.plist文件中的bundle ID保持一致
把Build Settings中Package分欄下的Product Bundle Identifier改成新的bundle ID
?
App設(shè)置應(yīng)用名字、圖標(biāo)、啟動(dòng)頁
生成應(yīng)用圖標(biāo):圖標(biāo)工廠
只需上傳一張1024*1024的應(yīng)用圖標(biāo),該網(wǎng)站會(huì)自動(dòng)為你生成各種適配版本的icon,包括ios和android
ios
應(yīng)用名稱:Xcode內(nèi)target/info/Custom iOS Target Propperties下的Bundle display name修改為應(yīng)用名稱
應(yīng)用圖標(biāo):項(xiàng)目目錄下Images.xcassets/AppIcon內(nèi),將需要適配的圖標(biāo)拖進(jìn)去,注意:若要上傳到App Store,1024*1024的圖標(biāo)一定要上傳
啟動(dòng)頁:關(guān)于iOS APP設(shè)置啟動(dòng)圖片
推送通知圖標(biāo):極光推送默認(rèn)選取應(yīng)用圖標(biāo)
android
應(yīng)用名稱:android/app/src/main/res/values/strings.xml內(nèi),修改應(yīng)用名稱
應(yīng)用圖標(biāo):android/app/src/main/res/文件夾下圖標(biāo)文件替換為圖標(biāo)工場(chǎng)下載下來的文件們
啟動(dòng)頁:
推送通知圖標(biāo):極光推送默認(rèn)選取應(yīng)用圖標(biāo),但在anfroid上可能行不通,android/app/src/main/res目錄下說明:若沒有res/drawable-xxxx/jpush_notification_icon這個(gè)資源默認(rèn)使用應(yīng)用圖標(biāo)作為通知icon,在5.0以上系統(tǒng)將應(yīng)用圖標(biāo)作為默認(rèn)推送圖標(biāo)
,官網(wǎng)如是說。沒有可以新建一個(gè),把圖標(biāo)命名為相應(yīng)名稱。項(xiàng)目中res下圖標(biāo)用的是mipmap,不是drawable,所以新建相應(yīng)路徑嘗試。不行的話,重啟手機(jī),此為坑。再不行,換個(gè)手機(jī)試試,可能當(dāng)前手機(jī)有緩存。