快速自定義Cordova外掛(-配置檔案)

xiaoyu_zheng發表於2018-07-02

之前寫過兩篇cordova自定義外掛的文章,都是沒使用到第三方庫,也沒有提供使用者自定義配置變數,這篇文章主要就來處理這些問題。

例子是用的cordova-plugin-wechat這個外掛

一、動態改變外掛引數變數

在正式開始之前先補充個知識點:

1,在安卓gradle裡面有很多個控制變數,比如cdvBuildMultipleApks之類的,怎麼來的呢

首先建立一個.build檔案比如:config.build檔案,

然後在裡面定義變數如:

ext {
    minSdkVersion = 14
    targetSdkVersion = 23
    compileSdkVersion = 23
  }

也可以直接寫為ext.cdvBuildMultipleApks,ext.cdvVersionCodeForceAbiDigit,ext.cdvMinSdkVersion

ext的意思是對外提供變數

我們在build.gradle(app)在中使用的cdvBuildMultipleApks可能來自於build.gradle(project)中定義,也可能來自於其他的.gradle檔案,在build.gradle(app)中使用時需要引入(build.gradle(project)的除外)如:apply from "../config.gradle"


2,安卓中config.xml檔案中外掛的配置舉例(cordova-plugin-crosswalk-webview外掛):

<plugin name="cordova-plugin-crosswalk-webview" spec="^2.4.0">
        <variable name="XWALK_VERSION" value="23+" />
        <variable name="XWALK_LITEVERSION" value="xwalk_core_library_canary:17+" />
        <variable name="XWALK_COMMANDLINE" value="--disable-pull-to-refresh-effect" />
        <variable name="XWALK_MODE" value="embedded" />
        <variable name="XWALK_MULTIPLEAPK" value="false" />
    </plugin>

variable中name對應於外掛裡面的plugin.xml中$XWALK_VERSION",$XWALK_LITEVERSION,$XWALK_COMMANDLINE,$XWALK_MODE,$XWALK_MULTIPLEAPK:

在外掛的plugin.xml中通過上面的方法可以獲取到config.xml中外掛的配置value

3,安卓中config.xml裡面可以寫preference開頭的標籤檔案,如:

    <preference name="StatusBarStyle" value="default" />
然後在android中的.java檔案和ios中的.m檔案裡面可以獲取到並且配置。


現在我們正式開始,以cordova-plugin-wechat這個外掛舉例:

plugin.xml配置檔案如下:

<?xml version="1.0" encoding="UTF-8"?>

<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
    xmlns:rim="http://www.blackberry.com/ns/widgets"
    xmlns:android="http://schemas.android.com/apk/res/android"
    id="cordova-plugin-wechat"
    version="2.1.0">

    <name>Wechat</name>
    <description>A cordova plugin, a JS version of Wechat SDK</description>
    <license>MIT</license>
    <keywords>cordova,wechat,weixin,share</keywords>
    <repo>https://github.com/xu-li/cordova-plugin-wechat.git</repo>
    <issue>https://github.com/xu-li/cordova-plugin-wechat/issues</issue>

    <!-- add this to your config.xml -->
    <!-- <preference name="WECHATAPPID" value="YOUR_WECHAT_APP_ID_HERE" /> -->
    <preference name="WECHATAPPID" />

    <!-- js module-->
    <js-module src="www/wechat.js" name="Wechat">
        <clobbers target="Wechat" />
    </js-module>

    <!-- ios -->
    <platform name="ios">
        <config-file target="config.xml" parent="/*">
            <feature name="Wechat">
                <param name="ios-package" value="CDVWechat"/>
                <param name="onload" value="true" />
            </feature>
            <preference name="WECHATAPPID" value="$WECHATAPPID"/>
        </config-file>

        <config-file target="*-Info.plist" parent="LSApplicationQueriesSchemes">
            <array>
                <string>weixin</string>
                <string>wechat</string>
            </array>
        </config-file>

        <config-file target="*-Info.plist" parent="NSAppTransportSecurity">
            <dict>
                <key>NSAllowsArbitraryLoads</key>
                <true/>
            </dict>
        </config-file>


        <config-file target="*-Info.plist" parent="CFBundleURLTypes">
            <array>
                <dict>
                    <key>CFBundleURLName</key>
                    <string>weixin</string>
                    <key>CFBundleURLSchemes</key>
                    <array>
                        <string>$WECHATAPPID</string>
                    </array>
                </dict>
            </array>
        </config-file>

        <!-- Plugin source code -->
        <header-file src="src/ios/CDVWechat.h" />
        <source-file src="src/ios/CDVWechat.m" />

        <!-- Wechat Official -->
        <header-file src="src/ios/libs/OpenSDK1.8.0/WXApi.h" />
        <header-file src="src/ios/libs/OpenSDK1.8.0/WXApiObject.h" />
        <source-file src="src/ios/libs/OpenSDK1.8.0/libWeChatSDK.a" framework="true" />

        <!-- Other required frameworks -->
        <framework src="libz.tbd" />
        <framework src="libsqlite3.0.tbd" />
        <framework src="CoreTelephony.framework" />
        <framework src="SystemConfiguration.framework" />
        <framework src="Security.framework" />
        <framework src="CFNetwork.framework" />
        <framework src="libstdc++.6.tbd" />
    </platform>

    <!-- android -->
    <platform name="android">
        <hook type="after_plugin_add" src="scripts/android-install.js" />
        <hook type="after_plugin_install" src="scripts/android-install.js" />
        <hook type="before_plugin_rm" src="scripts/android-install.js" />
        <hook type="before_plugin_uninstall" src="scripts/android-install.js" />

        <config-file target="res/xml/config.xml" parent="/*">
            <feature name="Wechat">
                <param name="android-package" value="xu.li.cordova.wechat.Wechat"/>
            </feature>
            <preference name="WECHATAPPID" value="$WECHATAPPID"/>
        </config-file>

        <config-file target="AndroidManifest.xml" parent="/*">
            <uses-permission android:name="android.permission.INTERNET"/>
            <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
            <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
            <uses-permission android:name="android.permission.READ_PHONE_STATE" />
            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        </config-file>

        <config-file target="AndroidManifest.xml" parent="/manifest/application">
            <activity
                android:name=".wxapi.WXEntryActivity"
                android:label="@string/launcher_name"
                android:exported="true">
                <intent-filter>
                    <action android:name="android.intent.action.VIEW"/>
                    <category android:name="android.intent.category.DEFAULT"/>
                    <data android:scheme="$WECHATAPPID"/>
                </intent-filter>
            </activity>
            <activity
                android:name=".wxapi.WXPayEntryActivity"
                android:label="@string/launcher_name"
                android:exported="true"
                android:launchMode="singleTop">
                <intent-filter>
                    <action android:name="android.intent.action.VIEW"/>
                    <category android:name="android.intent.category.DEFAULT"/>
                    <data android:scheme="$WECHATAPPID"/>
                </intent-filter>
            </activity>
        </config-file>

        <source-file src="src/android/Wechat.java" target-dir="src/xu/li/cordova/wechat" />
        <source-file src="src/android/Util.java" target-dir="src/xu/li/cordova/wechat" />
        <framework src="android-build.gradle" custom="true" type="gradleReference" />
    </platform>
</plugin>

注:發現通過$WECHATAPPID去取到config.xml中外掛配置的value的,同時發現通過在plugin.xml裡面就可以把需要的資訊寫入到了ios中的info檔案和安卓中的mainfest.xml檔案中去了


安裝cordova-plugin-wechat這個外掛需要使用者指定變數的值,需要在外掛plugin.xml中新增<preference/>標籤,標籤有兩個引數設定:name和default。

1、name:變數名稱,如果需要引用name對應的value時使用$name,如 <preference name="KEY"> 引用使用 <data scheme="$KEY">;

2、default:預設值,如果使用者沒有指定值的時候。如果default引數未指定,則name屬性使用者必須填寫,這也是cordova的一個策略。

使用方式:cordova plugin cordova_plugin_xxx --variable key=123456789

安卓剛剛實現了在外掛裡面的plugin.xml中可以去配置mainfest.xml,發現還有一個需求:就是怎麼通過外掛去控制gradle中的配置呢?

思路就是:在外掛的src/android中建立一個.gradle檔案,然後在裡面寫配置,同時可以根據外掛裡面的plugin.xml中的變數做不同的處理,還以開頭講的第二個知識點為例,

外掛中的plugin.xml中其中有一個配置檔案如下:

<config-file target="res/xml/config.xml" parent="/*">
            <preference name="webView" value="org.crosswalk.engine.XWalkWebViewEngine"/>
            <preference name="xwalkVersion" value="$XWALK_VERSION"/>
            <preference name="xwalkLiteVersion" value="$XWALK_LITEVERSION"/>
            <preference name="xwalkCommandLine" value="$XWALK_COMMANDLINE"/>
            <preference name="xwalkMode" value="$XWALK_MODE" />
            <preference name="xwalkMultipleApk" value="$XWALK_MULTIPLEAPK" />
            <preference name="android-minSdkVersion" value="16" />
        </config-file>

    在xwalk.gradle檔案中    ext.xwalkMode = getConfigPreference("xwalkMode");,

這裡getConfigPreference("xwalkMode");裡面的“xwalkMode”紅字部分是對應的。


二、自定義外掛中需要引入第三方庫

   1, 安卓中自定義外掛需要引入jar包,這個問題搞了一天才搞好,被網上的貼子和老的demo給坑了,有個demo是拿jpush舉例子的

如下:

<!--需要引入jar包時新增此處程式碼-->
<source-file src="src/android/jpush-sdk-release1.7.5.jar" target-dir="libs"/>  

實踐證明上面是錯誤的,看cordova官方有兩種做法:

The preferred way is to use the <framework /> tag (see the Plugin Specification for more details). Specifying libraries in this manner allows them to be resolved via Gradle's Dependency Management logic. This allows commonly used libraries such as gsonandroid-support-v4, and google-play-services to be used by multiple plugins without conflict.

The second option is to use the <lib-file /> tag to specify the location of a jar file (see the Plugin Specification for more details). This approach should only be used if you are sure that no other plugin will be depending on the library you are referencing (e.g. if the library is specific to your plugin). Otherwise, you risk causing build errors for users of your plugin if another plugin adds the same library. It is worth noting that Cordova app developers are not necessarily native developers, so native platform build errors can be especially frustrating.

意思是說一種通過<framework>另一種是通過<lib-file>,第一種方式試了很多遍就是不成功,無奈試了第二種方式成功了。

過程如下:src/android/libs中放入需要引用的jar包


如上我是自定義友盟統計的外掛,然後在plugin.xml中寫入:

<lib-file src="src/android/libs/umeng-analytics-7.4.0.jar" />
<lib-file src="src/android/libs/umeng-common-1.4.0.jar" />
<lib-file src="src/android/libs/utdid4all-1.1.5.3_proguard.jar" /> 

2,ios中新增framework(依然拿友盟framework舉例)

        <framework src="src/ios/UMAnalytics.framework" custom="true" />
        <framework src="src/ios/UMCommon.framework" custom="true" />

注意的地方是framework有可能會依賴系統的庫,比如友盟這裡就需要新增:

        <framework src="libz.tbd" weak="true" />
        <framework src="libsqlite3.0.tbd" weak="true" />



相關文章