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

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

1.修改plugin模板文件

找到 weex plugin 命令執(zhí)行代碼
~/.xtoolkit/node_modules/weexpack/bin/weexpack-plugin.js
會發(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(例子,開發(fā)者用來測試問題)
     │    ├── build
     │    └── index.we
     ├── playground(測試實(shí)例,寫好的module在各端做測試使用)
     │    ├── 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.編寫ios插件 代碼 (以weex-getui-push 為例)

weex 會自動在ios/Sources目錄下生成兩個GetuiPushModule.h(頭文件) GetuiPushModule.m(源文件)

  1. 配置個推sdk

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

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

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

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

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

    • 聲明變量來接收callback

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

        - (void)onRegisterClient:(WXModuleKeepAliveCallback)callback
        {
            self.onRegisterClientCallBack = callback;
        }
        - (void)onReceivePayloadData:(WXModuleKeepAliveCallback)callback
        {
            self.onReceivePayloadDataCallBack = callback;
        }
      
    • 當(dāng)個推推送消息到客戶端,ios會執(zhí)行GeTuiSdkDidReceivePayloadData,我們可以在該方法里通過以下代碼回調(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.編寫android插件 代碼

weex 會自動生成GetuiPushModule.java

  1. 配置個推sdk

    1. 添加Maven庫地址,在以項目名為命名的頂層build.gradle文件中,添加個推maven庫地址

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

    2.在libary/build.gradle文件中引用個推SDK依賴庫

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

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

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

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

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

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

     @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 使用了一個靜態(tài)變量存儲,方便在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);
     }
    

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

    invoke適用于一次回調(diào),invokeAndKeepAlive會保持連接,多次回調(diào)js

4.調(diào)試

npm run build & npm run copy:examples

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

android 使用 android studio 打開 playground/android

weex 打包 module

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

weex plugin login

weex plugin publish

2. 發(fā)布iOS pod包

將源代碼上傳到github,并tag版本號
    添加到本地倉庫                  git add ./*
    提交commit到目的倉庫            git commit -m "first commit"
    提交到github                   git push -u origin master
    給本地倉庫打標(biāo)簽                 git tag -a 0.0.1 -m "Relase version 0.0.1"
    提交標(biāo)簽到遠(yuǎn)程倉庫                git push origin --tags
    注解:就像git push origin master 把本地修改提交到遠(yuǎn)程倉庫一樣,-tags可以把本地的打的標(biāo)簽全部提交到遠(yuǎn)程倉庫。
驗(yàn)證.podspec
pod spec lint GetuiPush.podspec --verbose --use-libraries --allow-warnings
發(fā)布到CocoaPods
  1. 注冊trunk,首先需要使用如下命令注冊自己的電腦。這很簡單,只要你指明你的郵箱地址(spec文件中的)和名稱即可。CocoaPods 會給你填寫的郵箱發(fā)送驗(yàn)證郵件,點(diǎn)擊郵件中的鏈接就可通過驗(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)隊審核(貌似1~2小時,還是npm好,不需要審核,這也是為什么npm一大堆的第三方包????),審核成功后就可以使用pod search GetuiPush搜索到你的 Pod 了!如果沒有找到 可以使用 pod setup 更新本地pod依賴庫后再執(zhí)行 pod search
版本升級

當(dāng)需要更新 Pod 版本的時候,修改 .podspec 中的 s.version 為更高的版本號,并修改 s.source 中對應(yīng)的 Git 版本。提交到Git,并打上對應(yīng)tag。然后再次執(zhí)行pod trunk push GetuiPush.podspec將新的 .podspec 發(fā)布到 CocoaPods。

為了更新更加方便,版本控制更加清晰,s.source 建議采用如下寫法:
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

貼出我修改的重要幾個地方:

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'      // 項目的主頁
     def gitUrl = 'https://github.com/scholar-ink/weex-plugin-getui-push.git'   // Git倉庫的url
     version = "0.0.1"       //這個是版本號,必須填寫
     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'   //項目描述
                     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'         //填寫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") //賬號和apiKey
         key = properties.getProperty("bintray.apikey")
         configurations = ['archives']
         pkg {
             repo = "maven" //倉庫名,注意不是項目名
             name = "getuipush"  //發(fā)布到JCenter上的項目名字
             websiteUrl = siteUrl
             vcsUrl = gitUrl
             licenses = ["Apache-2.0"]
             publish = true
         }
    }    
    

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容