前端知識(shí) | React-Native如何自己擼第三方庫(kù)之a(chǎn)ndroid篇

在使用 ReactNative 開發(fā)過程中氏淑,由于開發(fā)中用到的語(yǔ)言是 JS,而如果需要實(shí)現(xiàn)百度定位或者微博分享等第三方 SDK 時(shí),往往會(huì)先去找有沒有支持 React Native 的三方庫(kù)翠拣。

盡管大部分常用功能已經(jīng)被民間藝人或官方團(tuán)隊(duì)實(shí)現(xiàn)按摘,但是一旦遇到未被 RN 開發(fā)的就只能擼起袖子自己干了朗徊。ReactNative 官方文檔也介紹了 Native Modules(下稱‘原生模塊’)的使用方法,它能用于訪問原生平臺(tái)的 API娜庇。


本文主要提供 Android 平臺(tái)的原生模塊打包教程拇泛。


原生模塊的使用方法:

以官網(wǎng)文檔列舉的 Toast 模塊使用方法為例滨巴,其主要步驟為:

第一步:

使用 Android Studio 打開 RN 項(xiàng)目的?android?文件,新建?Android Library?命名為 react-native-toast


圖1 新建Android Library

第二步:

在 react-native-toast 的build.gradlew?中添加RN依賴


dependencies {

....

compile

"com.facebook.react:react-native:+"?????? ? //here

}



在 app 的?build.gradlew?中引入這個(gè)庫(kù)


dependencies {

....

compile project(

':react-native-toast')//here

}




第三步:

前面的環(huán)境都配置好后就開始新建2個(gè) java 文件:

繼承 ReactContextBaseJavaModule 的 java 類Module.java?

和注冊(cè)模塊用的Package.java俺叭。

具體代碼在官網(wǎng)有詳細(xì)提供恭取,本文不重點(diǎn)闡述


思考:

如果按照 RN 文檔方法,在項(xiàng)目的 android 根文件夾下添加原生模塊熄守,會(huì)出現(xiàn)兩個(gè)問題:一是蜈垮,如果要實(shí)現(xiàn)的原生模塊多了,Android Library 也會(huì)遞增裕照,目錄容易混亂難以管理攒发;二是,這樣的原生模塊不容易復(fù)用晋南,其它項(xiàng)目沒法直接使用這個(gè)原生模塊惠猿。

通行的做法是,將實(shí)現(xiàn)后原生模塊打包好负间,然后存放在項(xiàng)目的 node_modules 的文件內(nèi)偶妖,供 APP 調(diào)用。


本文重點(diǎn):

本文將以百度定位的 Android SDK 為例政溃,介紹如何將其打包為一個(gè)名為 “react-native-baidu-location” 的原生模塊庫(kù)(library)趾访,供 RN APP 調(diào)用。

這個(gè)例子相比一般的原生模塊開發(fā)(RN文檔示例)會(huì)多一項(xiàng)工作董虱,即引入 SDK扼鞋,流程大致如下:

·創(chuàng)建一個(gè) RN 項(xiàng)目 Demo,用于調(diào)試愤诱。

·初始化 react-native-baidu-location 包云头。

·根據(jù)官網(wǎng)文檔對(duì) Android 平臺(tái)配置、引入 SDK淫半、寫代碼溃槐。


?初始化原生模塊庫(kù)

先創(chuàng)建一個(gè) RN 項(xiàng)目 Demo

安裝?react-native-create-library(類似的工具還有react-native-create-bridge)


?npm install -g ?react-native-create-library


在 node_modules 文件夾下創(chuàng)建你的三方庫(kù)

?react-native-create-library ?react-native-baidu-location


之后進(jìn)行本文之前的第三步,第一步和第二步已經(jīng)幫我們實(shí)現(xiàn)撮慨,只需要根據(jù)自己需求修改構(gòu)建工具的版本 ?.grandle?和?buildToolsVersion竿痰。

打包 Android 部分(重難點(diǎn))

因?yàn)橐园俣榷ㄎ粸槔嘀啵孕枰暾?qǐng)為百度開發(fā)者砌溺,下載基礎(chǔ)定位 SDK,具體步驟請(qǐng)使用 baidu变隔,本文不必闡述规伐,主要使用下載后解壓包內(nèi)叫?libs?的文件夾。

使用 Android Studio 打開 react-native-baidu-location 內(nèi)的 android 文件和 RN 項(xiàng)目Demo 下的 android 文件匣缘,因?yàn)檫@里是 android 打包教程猖闪,所以其他平臺(tái)教程請(qǐng)期待下篇《React-Native 如何自己擼第三方庫(kù)之 ios 篇》

?1.React-native-baidu-location - android

將?libs?文件復(fù)制到 android 文件下

?build.gradle?加入如下代碼

android ?{

???? ....

?? sourceSets {

??????? main {

??????????? jniLibs.srcDirs = ['libs']

??????? }

??? }

}

2.Demo - android

根據(jù)百度文檔鲜棠,配置相關(guān)服務(wù),ak 秘鑰和權(quán)限

AndroidManifest.xml?加入如下代碼

??????????? ?android:name="com.baidu.location.f"

??????????? android:enabled="true"

??????????? ?android:process=":remote">


??????????? ?android:name="com.baidu.lbsapi.API_KEY"

??????????? ?android:value="GN1lCG*************4I&&s" />

添加權(quán)限

```

```

3.?編寫 Native 模塊

和前文的第三步一樣使用固定寫法:

1.?????建一個(gè)中間訪問對(duì)象,

2.?????建一個(gè) ReactPackage 對(duì)象.

3.? ? ?將 ReactPackage 對(duì)象加載到 MainApplication 中.

LocationActivity

package ?com.location;


import ?android.util.Log;


import ?com.baidu.location.BDLocation;

import ?com.baidu.location.BDLocationListener;

import ?com.baidu.location.LocationClient;

import ?com.baidu.location.LocationClientOption;

import ?com.baidu.location.Poi;

import ?com.facebook.react.bridge.Callback;

import ?com.facebook.react.bridge.ReactApplicationContext;

import ?com.facebook.react.bridge.ReactContextBaseJavaModule;

import ?com.facebook.react.bridge.ReactMethod;


import ?java.util.List;


/**

?* Created by luokun on 2018/1/31.

?*/


public ?class LocationActivity extends ReactContextBaseJavaModule {

??? public LocationClient mLocationClient = ?null;

??? private Callback locationCallback;


??? public ?LocationActivity(ReactApplicationContext reactContext) {

??????? super(reactContext);

??? }

??? @ReactMethod

??? public void startLocation( Callback ?locationCallback) {

??????? this.locationCallback = ?locationCallback;

??????? mLocationClient = new ?LocationClient(getReactApplicationContext());???? //聲明LocationClient類

??????? ?mLocationClient.registerLocationListener(myListener);??? //注冊(cè)監(jiān)聽函數(shù)

??????? LocationClientOption option = new ?LocationClientOption();

??????? option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy

??????? );//可選培慌,默認(rèn)高精度豁陆,設(shè)置定位模式,高精度吵护,低功耗盒音,僅設(shè)備

??????? ?option.setCoorType("bd09ll");//可選,默認(rèn)gcj02馅而,設(shè)置返回的定位結(jié)果坐標(biāo)系

??????? int span = 0;

??????? option.setScanSpan(span);//可選祥诽,默認(rèn)0,即僅定位一次瓮恭,設(shè)置發(fā)起定位請(qǐng)求的間隔需要大于等于1000ms才是有效的

??????? option.setIsNeedAddress(true);//可選雄坪,設(shè)置是否需要地址信息,默認(rèn)不需要

??????? option.setOpenGps(true);//可選屯蹦,默認(rèn)false,設(shè)置是否使用gps

??????? option.setLocationNotify(true);//可選维哈,默認(rèn)false,設(shè)置是否當(dāng)gps有效時(shí)按照1S1次頻率輸出GPS結(jié)果

??????? ?option.setIsNeedLocationDescribe(true);//可選颇玷,默認(rèn)false笨农,設(shè)置是否需要位置語(yǔ)義化結(jié)果,可以在BDLocation.getLocationDescribe里得到帖渠,結(jié)果類似于“在北京天安門附近”

??????? ?option.setIsNeedLocationPoiList(true);//可選谒亦,默認(rèn)false,設(shè)置是否需要POI結(jié)果空郊,可以在BDLocation.getPoiList里得到

??????? option.setIgnoreKillProcess(false);//可選份招,默認(rèn)true,定位SDK內(nèi)部是一個(gè)SERVICE狞甚,并放到了獨(dú)立進(jìn)程锁摔,設(shè)置是否在stop的時(shí)候殺死這個(gè)進(jìn)程,默認(rèn)不殺死

??????? ?option.SetIgnoreCacheException(false);//可選哼审,默認(rèn)false谐腰,設(shè)置是否收集CRASH信息,默認(rèn)收集

??????? option.setEnableSimulateGps(false);//可選涩盾,默認(rèn)false十气,設(shè)置是否需要過濾gps仿真結(jié)果,默認(rèn)需要

??????? mLocationClient.setLocOption(option);

??????? mLocationClient.start();

??????? ?Log.e("tag","ok");

??? }


??? /**

???? * 定位回掉

???? */

??? public BDLocationListener myListener = ?new BDLocationListener() {

??????? @Override

??????? public void onReceiveLocation(final ?BDLocation bdLocation) {

??? ????????Log.e("TGA", "回掉+1");

??????????? //Receive Location

??????????? final StringBuffer sb = new ?StringBuffer(256);

??????????? sb.append("time : ");

??????????? sb.append(bdLocation.getTime());

??????????? sb.append("\nerror code : ?");

??????????? sb.append(bdLocation.getLocType());

??????????? sb.append("\nlatitude : ?");

??????????? ?sb.append(bdLocation.getLatitude());

??????????? sb.append("\nlontitude : ?");

??????????? ?sb.append(bdLocation.getLongitude());

??????????? sb.append("\nradius : ?");

???? ???????sb.append(bdLocation.getRadius());

??????????? if (bdLocation.getLocType() == ?BDLocation.TypeGpsLocation) {// GPS定位結(jié)果

??????????????? sb.append("\nspeed : ?");

??????????????? ?sb.append(bdLocation.getSpeed());// 單位:公里每小時(shí)

??????????????? sb.append("\nsatellite : ?");

??????????????? ?sb.append(bdLocation.getSatelliteNumber());

??????????????? sb.append("\nheight : ?");

??????????????? ?sb.append(bdLocation.getAltitude());// 單位:米

??????????????? sb.append("\ndirection : ?");

??????????????? ?sb.append(bdLocation.getDirection());// 單位度

??????????????? sb.append("\naddr : ?");

??????????????? ?sb.append(bdLocation.getAddrStr());

??????????????? sb.append("\ndescribe : ?");

??????????????? sb.append("gps定位成功");


??????????? } else if ?(bdLocation.getLocType() == BDLocation.TypeNetWorkLocation) {// 網(wǎng)絡(luò)定位結(jié)果

??????????????? sb.append("\naddr : ?");

??????????????? ?sb.append(bdLocation.getAddrStr());

??????????????? //運(yùn)營(yíng)商信息

??????????????? ?sb.append("\noperationers : ");

??????????????? sb.append(bdLocation.getOperators());

??????????????? sb.append("\ndescribe : ?");

??????????????? sb.append("網(wǎng)絡(luò)定位成功");

??????????? } else if ?(bdLocation.getLocType() == BDLocation.TypeOffLineLocation) {// 離線定位結(jié)果

??????????????? sb.append("\ndescribe : ?");

??? ????????????sb.append("離線定位成功春霍,離線定位結(jié)果也是有效的");

??????????? } else if ?(bdLocation.getLocType() == BDLocation.TypeServerError) {

??????????????? sb.append("\ndescribe : ?");

??????????????? sb.append("服務(wù)端網(wǎng)絡(luò)定位失敗砸西,可以反饋IMEI號(hào)和大體定位時(shí)間到loc-bugs@baidu.com,會(huì)有人追查原因");

?? ?????????} else if (bdLocation.getLocType() ?== BDLocation.TypeNetWorkException) {

??????????????? sb.append("\ndescribe : ?");

??????????????? sb.append("網(wǎng)絡(luò)不同導(dǎo)致定位失敗,請(qǐng)檢查網(wǎng)絡(luò)是否通暢");

??????????? } else if ?(bdLocation.getLocType() == BDLocation.TypeCriteriaException) {

??????????????? sb.append("\ndescribe : ?");

??????????????? sb.append("無法獲取有效定位依據(jù)導(dǎo)致定位失敗芹枷,一般是由于手機(jī)的原因衅疙,處于飛行模式下一般會(huì)造成這種結(jié)果,可以試著重啟手機(jī)");

??????????? }

??????????? ?sb.append("\nlocationdescribe : ");

??????????? ?sb.append(bdLocation.getLocationDescribe());// 位置語(yǔ)義化信息

??????????? List list = ?bdLocation.getPoiList();// POI數(shù)據(jù)

??????????? if (list != null) {

??????????????? sb.append("\npoilist ?size = : ");

??????????????? sb.append(list.size());

???? ???????????for (Poi p : list) {

??????????????????? sb.append("\npoi= : ?");

??????????????????? sb.append(p.getId() + ?" " + p.getName() + " " + p.getRank());

??????????????? }

??????????? }

??????????? ?locationCallback.invoke(sb.toString());

??????? }

??? };


??? @Override

??? public String getName() {

??????? return "Location";

??? }

}


LocationPackage

package ?com.location;


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 luokun on 2018/1/31.

?*/


public ?class LocationPackage implements ReactPackage {


??? @Override

??? public List ?createViewManagers(ReactApplicationContext reactContext) {

??????? return Collections.emptyList();

??? }


??? @Override

??? public List ?createNativeModules(

??????????? ReactApplicationContext ?reactContext) {

??????? List modules = ?new ArrayList<>();


??????? modules.add(new ?LocationActivity(reactContext));??? //


??????? return modules;

??? }

}


Index.js文件

'use ?strict';


import ?{ NativeModules } from 'react-native';


export ?default NativeModules.Location;

恭喜完成鸳慈!

至于怎么使用饱溢,最好寫一個(gè) README.md,要‘裝逼’咱們就來全套走芋。寫個(gè)使用文檔理朋,讓我們搬運(yùn)工們用得順手。(笑笑就好:))

使用方法:

自動(dòng) link

React-native-baidu-location ?link

或者手動(dòng) link

/android/settings.gradle

include ?':react-native-baidu-location'

project(':react-native-baidu-location').projectDir ?= new File(rootProject.projectDir, ?'../node_modules/react-native-baidu-ocr/android')

/android/app/build.gradle

dependencies ?{

?? ...

??? compile ?project(':react-native-baidu-ocr'') // 加入

?? ...

}

js 使用方法

Import ?Location from ‘react-native-baidu-location’

...

...

?componentDidMount() {

??????? ?Location.startLocation((location)=> {

??????????? console.log(location)???????

});

??? }

當(dāng)你看到這里的時(shí)候并且自己照著寫了一遍绿聘,那么恭喜你成功開發(fā)出第三方 rn 庫(kù)了嗽上,甚至可以上傳到 npm 上開源。

上傳成功后熄攘,其它項(xiàng)目就可以通過 npminstall 來使用這個(gè)庫(kù)兽愤。

總結(jié):

要打包 React Native 的原生模塊,你最好有以下知識(shí)儲(chǔ)備:

有 RN 開發(fā)經(jīng)驗(yàn)挪圾。如 RN 文檔所說浅萧,原生模塊是該框架的高級(jí)特性,當(dāng)然是有一定的經(jīng)驗(yàn)更易理解哲思。

了解 Java 和 Objective-C洼畅, 至少能看懂這兩種代碼。和官網(wǎng)教程對(duì)比上述代碼雖然多但是很多都是固定寫法棚赔。

基本實(shí)現(xiàn)原理是通過回調(diào)使 JavaScript 能夠訪問到 java 返回值帝簇。

更多特性敬請(qǐng)期待。


-END-?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末靠益,一起剝皮案震驚了整個(gè)濱河市丧肴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌胧后,老刑警劉巖芋浮,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異壳快,居然都是意外死亡纸巷,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門眶痰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瘤旨,“玉大人,你說我怎么就攤上這事凛驮●烧荆” “怎么了条辟?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵黔夭,是天一觀的道長(zhǎng)宏胯。 經(jīng)常有香客問我,道長(zhǎng)本姥,這世上最難降的妖魔是什么肩袍? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮婚惫,結(jié)果婚禮上氛赐,老公的妹妹穿的比我還像新娘。我一直安慰自己先舷,他們只是感情好艰管,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蒋川,像睡著了一般牲芋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捺球,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天缸浦,我揣著相機(jī)與錄音,去河邊找鬼氮兵。 笑死裂逐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的泣栈。 我是一名探鬼主播卜高,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼南片!你這毒婦竟也來了篙悯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤铃绒,失蹤者是張志新(化名)和其女友劉穎鸽照,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體颠悬,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡矮燎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赔癌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诞外。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖灾票,靈堂內(nèi)的尸體忽然破棺而出峡谊,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布既们,位于F島的核電站濒析,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏啥纸。R本人自食惡果不足惜号杏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望斯棒。 院中可真熱鬧盾致,春花似錦、人聲如沸荣暮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)穗酥。三九已至蜈块,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間迷扇,已是汗流浹背百揭。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蜓席,地道東北人器一。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像厨内,于是被迫代替她去往敵國(guó)和親祈秕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,527評(píng)論 25 707
  • React Native開發(fā)中常用三方組件大全 作者整理的一套常用的React Native開發(fā)中使用到的三方組件...
    光強(qiáng)_上海閱讀 21,124評(píng)論 6 95
  • 我的花園中央是一座海 無所事事雏胃,她雕刻水 我的杏樹沒有姿勢(shì) 冬天結(jié)果夏天瘋 玫瑰一夜一枯萎 掉下委屈的刺 這春天的...
    我是不是蝎大人閱讀 201評(píng)論 0 1
  • 生活在小縣城的我请毛,覺得買了房有房住,工作穩(wěn)定已經(jīng)很不錯(cuò)瞭亮,所以一直沒有想過去投資買第二套房子方仿,已沒有想過要如何奮斗讓...
    學(xué)著努力8e8o閱讀 136評(píng)論 0 0
  • 1大約是在三年前開始,我做著美夢(mèng)统翩,寫著一些隨心之筆仙蚜,喝著苦茶,妄想成為那些隱士大師之中的一員厂汗。還未到二十的年紀(jì)委粉,我...
    木起心落閱讀 903評(píng)論 0 0