1. 程式人生 > >13、最新安卓Xamarin繫結相關填坑之旅

13、最新安卓Xamarin繫結相關填坑之旅

今天群裡面有兄弟夥說第三方庫用不起。說實話在我覺得第三方庫能成功的機率大於90% 除了極少數噁心的庫以外。

絕大部分第三方庫都還是可以繫結好的

這個是官方的也有對應的demo

首先遇到繫結庫 我會第一時間nuget查詢下 雖然這種庫很少有人會用。但是萬一有人綁定了呢?

然後 我會在github搜尋下有木有好心的人綁定了

這2個方法後都沒得人繫結 好吧 那就我自己開擼

首先安卓的繫結絕對比ios繫結容易得多 耐心細心慢慢來肯定可以解決

先下載官方的 用as開啟跑起來  沒問題 好的 官方無坑。 (一定記得這一步 不然萬一官方的有坑你自己又在擼會哭的)

接下來 準備一個2個工具  ILSpy.exe     Jd-gui.exe

然後先看下官方依賴的庫有那些 這一步很重要

用相關的gradlew 去檢視相關依賴 具體百度 Android Studio 依賴檢視

目前我查出來依賴了

systemweb-2.0.9

sdk-analytics-0.4.7
youzansdk-6.3.5
anko-commons-0.10.0
anko-sqlite-0.10.0
gson-2.8.0
okhttp-3.8.1
okio-1.13.0
basic-6.3.5

webcache-2.2.0

jsbridge-2.0.2

這裡面如果是aar 記得要單獨建一個繫結類庫

開始繫結

第一步繫結basic-6.3.5 .aar 的時候就發現有個YouzanBrowser類無法生成 這個時候 開啟

檢視所有檔案

開啟這個資料夾 然後檢視 裡面有個 classs.jar  用jd-gui.exe 工具反編譯檢視下類的結構

然後用xml語法進行編輯修改  請記住 官方的自動生成只是簡化這個步驟而已. 對寫得很好的庫完全沒問題  但是有些國內廠商寫得並不好 一堆亂 意味著你就放棄掉這些好了 直接自己來寫

首先remove-node 移除掉編譯出錯的節點

<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='CursorLoader']/method[@name='loadInBackground']" />
語法是 xpath 語法 操作的物件是什麼物件呢?  是一個xml檔案

 api.xml  是工具幫你生成的 有時候你記不住語法 可以參考下

api.xml.fixed  是經過修改後生成的(經過你的xpath處理 也就是一直在說的Metadata.xml 檔案)

好了 其他都不重要 記住 如果你發現編譯一堆語法錯誤 首先 直接remove掉這些節點和錯誤的類

然後根據專案需要那些api方法和類 直接自己生成

我們需要YouzanBrowser 這個物件 用jd-gui開啟對應的class.jar

這不是我們需要的類嗎?為什麼生成不了? 大部分都是因為依賴的第三方庫 第三方的類和物件無法解析 介面實現等 都會有這個問題。我們不管先看下

塗抹的內容不重要

只看一個Package  class名字 繼承關係

<add-node path="/api/package[@name='com.youzan.androidsdk.basic']">
    <class abstract="false" deprecated="not deprecated" extends="android.webkit.WebView" extends-generic-aware="java.lang.Object" final="false" name="YouzanBrowser" static="false" visibility="public">
      
    </class>
  </add-node>

 這裡面的名字 大家英文好 看看就行  需要注意的是2個東西

 extends 如果沒有特殊的需要可以不用繼承特定的型別 直接繼承Object 即可   但是我們這裡由於需要一個特定型別的 在程式碼裡面 所以設定他繼承 android.webkit.WebView  具體的型別大家可以看他jd-gui 的原始碼

然後就是新增需要的方法

  <constructor deprecated="not deprecated" final="false" name="YouzanBrowser" static="false"  visibility="public">
        <parameter name="context" type="android.content.Context">
        </parameter>
      </constructor>
      <method abstract="false" deprecated="not deprecated" final="false" name="pageGoBack" native="false" return="boolean" static="false" synchronized="false" visibility="public">
        
      </method>
      <method abstract="false" deprecated="not deprecated" final="false" name="reload" native="false" return="void" static="false" synchronized="false" visibility="public">

      </method>
      <method abstract="false" deprecated="not deprecated" final="false" name="onPause" native="false" return="void" static="false" synchronized="false" visibility="public">

      </method>

      <method abstract="false" deprecated="not deprecated" final="false" name="destroy" native="false" return="void" static="false" synchronized="false" visibility="public">

      </method>
      <method abstract="false" deprecated="not deprecated" final="false" name="onResume" native="false" return="void" static="false" synchronized="false" visibility="public">

      </method>
      <!--boolean receiveFile(int paramInt, Intent paramIntent);-->
      <method abstract="false" deprecated="not deprecated" final="false" name="receiveFile" native="false" return="void"
             static="false" synchronized="false" visibility="public">
        <parameter name="paramInt" type="int">
        </parameter>
        <parameter name="paramIntent" type="android.content.Intent">
        </parameter>
      </method>
      <method abstract="false" deprecated="not deprecated" final="false" name="loadUrl" native="false" return="void"
              static="false" synchronized="false" visibility="public">
        <parameter name="paramString" type="java.lang.String">
        </parameter>
      </method>

 這樣非常簡單根據反編譯出來的物件 型別進行調整和命名即可 也不用扣破頭的想生成的咋不對呢 等等問題.  介面也是類似的處理邏輯

如果編譯不通過 可以檢視輸出 裡面會有詳細的提示

把所有的繫結編譯通過後  記得 加入相關依賴庫 就是你最初查找出來的

有時候智慧提示會出現卡殼  那怎麼知道我要的類是否生成出來? 可以藉助IlSpy 看下 如果出來了 即使 demo裡面有波浪號也不管他 只管編譯即可

開始寫個demo跑跑看

開始遇到第一個深坑。

  java.lang.NoClassDefFoundError: Failed resolution of: Lkotlin/jvm/internal/Intrinsics;

第一個崩潰的異常出現 。查詢任何資料都沒有Xamarin相關的介紹。你會覺得神經病啊 啥垃圾Xamarin。。。 其實不是 如果你做安卓原生開發就會知道 使用kotlin的庫的時候 java這邊需要引入一個stblib

我們Xamarin早就提供了 nuget 搜尋下 

加入這個庫再執行 就不會報錯了

至此整個流程完畢

如果執行過程出現

Java.Lang.NoClassDefFoundError: Failed resolution of: Lorg/jetbrains/anko/db/ManagedSQLiteOpenHelper; NoClassDefFoundError  請檢查下依賴的第三方jar 是否已經打在你繫結庫裡面   記得 一定要先清理 再編譯 否則 會讓你覺得崩潰 明明添加了 結果還是 沒找到 記得清空 跑下吧  我 已經放在github上了

https://github.com/jsonsugar/XamainAndroidBindLibary