weex插件開(kāi)發(fā)與發(fā)布(以個(gè)推推送為例)浑吟,看完少踩幾天的坑

吐槽:weex 文檔真心太少旱幼,特別是自定義插件查描,幾乎為零,希望這篇文檔對(duì)你有幫助

1.修改plugin模板文件

找到 weex plugin 命令執(zhí)行代碼
~/.xtoolkit/node_modules/weexpack/bin/weexpack-plugin.js
會(huì)發(fā)現(xiàn)最終模板文件在 generator-weex-plugin 里面

  1. node_modules/generator-weex-plugin/../templates 下面js upperCamelCaseName 都改為 lowerCamelCaseName

  2. package.json里面的copy:examples 改為

"rm -rf ./playground/android/app/src/main/assets/* && cp -vrf ./examples/build/* ./playground/android/app/src/main/assets/ &&rm -rf ./playground/ios/bundlejs/* && cp -vrf ./examples/build/* ./playground/ios/bundlejs/"

  1. playground/android/gradle-wrapper.properties 改為4.1.

  2. android/libary下面的build.gradle defaultConfig 新增

     defaultConfig {
         ...
         javaCompileOptions {
             annotationProcessorOptions {
                 includeCompileClasspath true
             }
         }
         ...
     }
    
  3. playground/android/setting.gradle 將libary改成module名稱

    include ":getuipush"
    project (':getuipush').projectDir = new File("../../android/library")
    

    app/build.gradle文件中修改為:

    compile project(path: ':getuipush')
    
這么多坑柏卤,燃根煙消消愁~ ????

2. weex plugin create getui-push

  • 生成的目錄結(jié)構(gòu)如下

     ├── android(Android插件工程)
     │    ├── buid.gradle(android發(fā)布文件)
     ├── ios(ios插件工程)
     ├── js(h5插件工程)
     ├── examples(例子,開(kāi)發(fā)者用來(lái)測(cè)試問(wèn)題)
     │    ├── build
     │    └── index.we
     ├── playground(測(cè)試實(shí)例,寫(xiě)好的module在各端做測(cè)試使用)
     │    ├── android(demo)
     │    ├── ios(demo)
     │    └── browser(demo)          
     ├── ****.podspec(ios發(fā)布文件)
     ├── package.json(js發(fā)布文件)
     ├── README.md
    
    最終js代碼 (幾行js代碼 ios和android的推送就輕輕松松搞定)
    const plugin = weex.requireModule('getuiPush');
    
    plugin.initPush({
        appId:'appId',
        appKey:'appKey',
        appSecret:'appSecret',
    });
    
    plugin.onRegisterClient(function (clientId) {
        console.log('js 收到' + clientId);
    });
    
    plugin.onReceivePayloadData(function (payloadData) {
        console.log('js 收到' + JSON.stringify(payloadData));
    });
    

3.編寫(xiě)ios插件 代碼 (以weex-getui-push 為例)

weex 會(huì)自動(dòng)在ios/Sources目錄下生成兩個(gè)GetuiPushModule.h(頭文件) GetuiPushModule.m(源文件)

  1. 配置個(gè)推sdk

    • 在 根目錄下的 GetuiPush.podspec 加入
      s.dependency "GTSDK"
    • 在 ios目錄下的 Podfile 加入
      pod 'GTSDK', '2.0.0.0-noidfa'
    • 切入到playground/ios 目錄 執(zhí)行
      pod update
  2. 初始化個(gè)推

    • js結(jié)構(gòu)為:initPush(options)

      我們需要現(xiàn)在 GetuiPushModule.h 頭文件里面聲明 initGeTui這個(gè)方法

         //添加宏WX_EXPORT_METHOD, 它可以被weex識(shí)別
         WX_EXPORT_METHOD(@selector(initPush:))
      
        //js 初始化個(gè)推
        - (void)initPush:(NSDictionary *)options
        {
            [self startSdkWith:options[@"appId"] appKey:options[@"appKey"] appSecret:options[@"appSecret"]];
            
            //[2]:注冊(cè)APNS
            [self registerRemoteNotification];
            
            //打開(kāi)app時(shí)候,消除掉badge
            [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
            
            if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
                
                // iOS8以后 本地通知必須注冊(cè)(獲取權(quán)限)
                UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];
                
                [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
            }
            //[2-EXT]: 獲取啟動(dòng)時(shí)收到的APN數(shù)據(jù)
        }
      
  3. 當(dāng)個(gè)推推送消息到客戶端的時(shí)候需要告訴到j(luò)s代碼

    • js結(jié)構(gòu)為:
      plugin.onReceivePayloadData(callback)

    • 聲明變量來(lái)接收callback

        @interface GetuiPushModule()
            @property(nonatomic,copy)WXModuleKeepAliveCallback onRegisterClientCallBack;
      
            @property(nonatomic,copy)WXModuleKeepAliveCallback onReceivePayloadDataCallBack;
        
        @end
      
    • 同樣在 GetuiPushModule.h聲明 onReceivePayloadData這個(gè)方法

        - (void)onRegisterClient:(WXModuleKeepAliveCallback)callback
        {
            self.onRegisterClientCallBack = callback;
        }
        - (void)onReceivePayloadData:(WXModuleKeepAliveCallback)callback
        {
            self.onReceivePayloadDataCallBack = callback;
        }
      
    • 當(dāng)個(gè)推推送消息到客戶端,ios會(huì)執(zhí)行GeTuiSdkDidReceivePayloadData,我們可以在該方法里通過(guò)以下代碼回調(diào)js代碼

        -(void)GeTuiSdkDidReceivePayloadData:(NSData *)payloadData andTaskId:(NSString *)taskId andMsgId:(NSString *)msgId andOffLine:(BOOL)offLine fromGtAppId:(NSString *)appId {
            NSDictionary *msgDict = [NSJSONSerialization JSONObjectWithData:payloadData options:NSJSONReadingAllowFragments error:nil];
            self.onReceivePayloadDataCallBack(msgDict,true);
        }
      

如此螺句,我們就能親切的在看到j(luò)s代碼console.log(推送的消息)了

3.編寫(xiě)android插件 代碼

weex 會(huì)自動(dòng)生成GetuiPushModule.java

  1. 配置個(gè)推sdk

    1. 添加Maven庫(kù)地址阿宅,在以項(xiàng)目名為命名的頂層build.gradle文件中,添加個(gè)推maven庫(kù)地址

      allprojects {
          repositories {
              jcenter()
              mavenCentral()
      
              //個(gè)推Maven URL地址
              maven {
                  url "http://mvn.gt.igexin.com/nexus/content/repositories/releases/"
              }
          }
      }
      

    2.在libary/build.gradle文件中引用個(gè)推SDK依賴庫(kù)

     dependencies {
         compile 'com.getui:sdk:2.11.1.0'
     }   
    

    3.配置個(gè)推應(yīng)用參數(shù)

    在app/build.gradle文件中的android.defaultConfig下添加manifestPlaceholders桥滨,配置個(gè)推相關(guān)的應(yīng)用參數(shù)

     android {
       ...
       defaultConfig {
         ...
         manifestPlaceholders = [
             GETUI_APP_ID : "APP_ID",
             GETUI_APP_KEY : "APP_KEY",
             GETUI_APP_SECRET : "APP_SECRET"
         ]
       }
     }
    

    4.按照個(gè)推文檔配置自定義推送服務(wù)窝爪、接收推送服務(wù)事件的service

    5.在GetuiPushModule.java 里面添加initPush方法(正式開(kāi)始了~)

     @JSMethod
     public void initPush(Map param) {
     
         Log.d("param",param.toString());
         PushManager.getInstance().initialize(this.mWXSDKInstance.getContext(), DemoPushService.class);
         PushManager.getInstance().registerPushIntentService(this.mWXSDKInstance.getContext(), PushIntentService.class);
     }
    

    6.添加 clientId回調(diào)和消息回調(diào)方法

     @JSMethod(uiThread = true)
     public void onRegisterClient(JSCallback callback){
    
     GetuiPushModule.onRegisterClientCallBack = callback;
    
     }
    
     @JSMethod(uiThread = true)
     public void onReceivePayloadData(JSCallback callback){
    
         GetuiPushModule.onReceivePayloadDataCallBack = callback;
    
     }
    

    上面的callback 使用了一個(gè)靜態(tài)變量存儲(chǔ),方便在PushIntentService 服務(wù)里面 執(zhí)行回調(diào)方法給js

    7.在PushIntentService 服務(wù)里回調(diào)js

     @Override
     public void onReceiveClientId(Context context, String clientid) {
    
         GetuiPushModule.onRegisterClientCallBack.invoke(clientid);
    
         Log.e(TAG, "onReceiveClientId -> " + "clientid = " + clientid);
     }
    
     @Override
     public void onReceiveMessageData(Context context, GTTransmitMessage msg) {
    
         Log.e("onReceiveMessageData", "onReceiveMessageData");
    
         byte[] payload = msg.getPayload();
    
         Map json = (Map) JSON.parse(new String(payload));
    
         GetuiPushModule.onReceivePayloadDataCallBack.invokeAndKeepAlive(json);
     }
    

    可以看到 上面使用兩個(gè)回調(diào)的方式 invoke 和 invokeAndKeepAlive

    invoke適用于一次回調(diào)齐媒,invokeAndKeepAlive會(huì)保持連接蒲每,多次回調(diào)js

4.調(diào)試

npm run build & npm run copy:examples

ios 使用 xcode 打開(kāi) playground/ios (沒(méi)有pod install 的話 先 pod update 下載依賴文件)

android 使用 android studio 打開(kāi) playground/android

weex 打包 module

1. 打包上傳到weex market 和 js npm

weex plugin login

weex plugin publish

2. 發(fā)布iOS pod包

將源代碼上傳到github,并tag版本號(hào)
    添加到本地倉(cāng)庫(kù)                  git add ./*
    提交commit到目的倉(cāng)庫(kù)            git commit -m "first commit"
    提交到github                   git push -u origin master
    給本地倉(cāng)庫(kù)打標(biāo)簽                 git tag -a 0.0.1 -m "Relase version 0.0.1"
    提交標(biāo)簽到遠(yuǎn)程倉(cāng)庫(kù)                git push origin --tags
    注解:就像git push origin master 把本地修改提交到遠(yuǎn)程倉(cāng)庫(kù)一樣喻括,-tags可以把本地的打的標(biāo)簽全部提交到遠(yuǎn)程倉(cāng)庫(kù)邀杏。
驗(yàn)證.podspec
pod spec lint GetuiPush.podspec --verbose --use-libraries --allow-warnings
發(fā)布到CocoaPods
  1. 注冊(cè)trunk,首先需要使用如下命令注冊(cè)自己的電腦唬血。這很簡(jiǎn)單望蜡,只要你指明你的郵箱地址(spec文件中的)和名稱即可。CocoaPods 會(huì)給你填寫(xiě)的郵箱發(fā)送驗(yàn)證郵件刁品,點(diǎn)擊郵件中的鏈接就可通過(guò)驗(yàn)證泣特。
    pod trunk register scholar-ink@163.com "scholar-ink"
  2. 然后就可以發(fā)布你的 Pod 了。
    pod trunk push GetuiPush.podspec --use-libraries --allow-warnings
    發(fā)布成功后挑随,需要等待pod團(tuán)隊(duì)審核(貌似1~2小時(shí)状您,還是npm好,不需要審核兜挨,這也是為什么npm一大堆的第三方包????)膏孟,審核成功后就可以使用pod search GetuiPush搜索到你的 Pod 了!如果沒(méi)有找到 可以使用 pod setup 更新本地pod依賴庫(kù)后再執(zhí)行 pod search
版本升級(jí)

當(dāng)需要更新 Pod 版本的時(shí)候拌汇,修改 .podspec 中的 s.version 為更高的版本號(hào)柒桑,并修改 s.source 中對(duì)應(yīng)的 Git 版本。提交到Git噪舀,并打上對(duì)應(yīng)tag魁淳。然后再次執(zhí)行pod trunk push GetuiPush.podspec將新的 .podspec 發(fā)布到 CocoaPods飘诗。

為了更新更加方便,版本控制更加清晰界逛,s.source 建議采用如下寫(xiě)法:
s.source = { :git => "https://github.com/scholar-ink/weex-plugin-getui-push.git", :tag => s.version}

3.打包android代碼

可參考http://blog.csdn.net/jiankeufo/article/details/71191865

貼出我修改的重要幾個(gè)地方:

1.在你modul的build.gradle文件中配置插件

    apply plugin: 'com.github.dcendents.android-maven'
    apply plugin: 'com.jfrog.bintray'
  1. 在你Project的build.gradle文件中加入Maven和Jfrog Bintray的依賴插件:

     classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
     classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
    
  2. 重要配置 有注釋的配置特別關(guān)注

     def siteUrl = 'https://github.com/scholar-ink/weex-plugin-getui-push'      // 項(xiàng)目的主頁(yè)
     def gitUrl = 'https://github.com/scholar-ink/weex-plugin-getui-push.git'   // Git倉(cāng)庫(kù)的url
     version = "0.0.1"       //這個(gè)是版本號(hào)昆稿,必須填寫(xiě)
     group = "org.weex.plugin"                                        // Maven Group ID for the artifact,一般填你唯一的包名
     
     install{
         repositories.mavenInstaller {
             // This generates POM.xml with proper parameters
             pom {
                 project {
                     packaging 'aar'
                     // Add your description here
                     name 'getui-push extend for weex'   //項(xiàng)目描述
                     url siteUrl
                     // Set your license
                     licenses {
                         license {
                             name 'The Apache Software License, Version 2.0'
                             url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                         }
                     }
                     developers {
                         developer {
                             id 'zhouink'         //填寫(xiě)bintray或者github的用戶名
                             name 'zhouchao'     //姓名
                             email 'zhouc1120@gmail.com'//郵箱
                         }
                     }
                     scm {
                         connection gitUrl
                         developerConnection gitUrl
                         url siteUrl
                     }
                 }
             }
         }
     }
     
     task sourcesJar(type: Jar) {
         from android.sourceSets.main.java.srcDirs
         classifier = 'sources'
     }
     task javadoc(type: Javadoc) {
         source = android.sourceSets.main.java.srcDirs
         classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
     }
     task javadocJar(type: Jar, dependsOn: javadoc) {
         classifier = 'javadoc'
         from javadoc.destinationDir
     }
     artifacts {
         archives javadocJar
         archives sourcesJar
     }
     Properties properties = new Properties()
     properties.load(project.rootProject.file('local.properties').newDataInputStream())
     bintray {
         user = properties.getProperty("bintray.user") //賬號(hào)和apiKey
         key = properties.getProperty("bintray.apikey")
         configurations = ['archives']
         pkg {
             repo = "maven" //倉(cāng)庫(kù)名息拜,注意不是項(xiàng)目名
             name = "getuipush"  //發(fā)布到JCenter上的項(xiàng)目名字
             websiteUrl = siteUrl
             vcsUrl = gitUrl
             licenses = ["Apache-2.0"]
             publish = true
         }
    }    
    

值得提到的一點(diǎn)是 addPackageToJCenter 是需要審核的溉潭,而且審核時(shí)間還不短,郁悶中~完全沒(méi)有js 的npm php的composer來(lái)的實(shí)在~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末少欺,一起剝皮案震驚了整個(gè)濱河市喳瓣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赞别,老刑警劉巖畏陕,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異氯庆,居然都是意外死亡蹭秋,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)堤撵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)仁讨,“玉大人,你說(shuō)我怎么就攤上這事实昨《椿恚” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵荒给,是天一觀的道長(zhǎng)丈挟。 經(jīng)常有香客問(wèn)我,道長(zhǎng)志电,這世上最難降的妖魔是什么曙咽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮挑辆,結(jié)果婚禮上例朱,老公的妹妹穿的比我還像新娘。我一直安慰自己鱼蝉,他們只是感情好洒嗤,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著魁亦,像睡著了一般渔隶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上洁奈,一...
    開(kāi)封第一講書(shū)人閱讀 52,328評(píng)論 1 310
  • 那天间唉,我揣著相機(jī)與錄音绞灼,去河邊找鬼。 笑死呈野,一個(gè)胖子當(dāng)著我的面吹牛镀赌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播际跪,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼喉钢!你這毒婦竟也來(lái)了姆打?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤肠虽,失蹤者是張志新(化名)和其女友劉穎幔戏,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體税课,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡闲延,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了韩玩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垒玲。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖找颓,靈堂內(nèi)的尸體忽然破棺而出合愈,到底是詐尸還是另有隱情,我是刑警寧澤击狮,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布佛析,位于F島的核電站,受9級(jí)特大地震影響彪蓬,放射性物質(zhì)發(fā)生泄漏寸莫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一档冬、第九天 我趴在偏房一處隱蔽的房頂上張望膘茎。 院中可真熱鬧,春花似錦捣郊、人聲如沸辽狈。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)刮萌。三九已至,卻和暖如春娘扩,著一層夾襖步出監(jiān)牢的瞬間着茸,已是汗流浹背壮锻。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涮阔,地道東北人猜绣。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像敬特,于是被迫代替她去往敵國(guó)和親掰邢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

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