入職三個月,遊戲SDK開發總結

藍師傅最近幾個月很是忙,好久沒更新文章了,慚愧慚愧,距離上一篇技術文章已是半年前了~java

前幾個月負責遊戲SDK的開發、維護、對接工做,項目結束了一段時間了,梳理一下游戲SDK開發涉及到的知識點。android

有些朋友可能對遊戲SDK開發有點陌生,但願本文對你有一些幫助。git

前言

記得17年畢業那會兒找工做的時候,去一家公司面試,面的是遊戲SDK崗位,面試官一開口就問我以前有沒有作過SDK開發,我說沒作過,結果聊了幾句就回去等通知了~github

HR在篩選簡歷的時候可能出了點問題,可是,從技術角度講,沒作過SDK開發就不能勝任這個崗位了嗎?面試

1、什麼是SDK

SDK(Software Development Kit)是軟件開發工具包的意思,通常咱們將一部分功能單獨封裝成一個library進行開發和維護,而後將編譯產物(jar包或者aar)提供給多個項目使用,這就屬於SDK開發。 常見的如短視頻SDK、推送SDK,分享SDK,以及這篇文章的重點:遊戲SDK。算法

2、 遊戲SDK

2.1 遊戲SDK是啥

image.png

小紅是作社交App的娛樂公司,日活幾千萬,想讓本身平臺多元化,好比作個遊戲下載的功能,給用戶下載,用戶以爲好玩,可能就會付費買裝備,可是有個問題,小紅並不會作遊戲,若是單開一個產品線去研發遊戲,投入是至關巨大的,因此想到能不能去外面接遊戲進來。數據庫

image.png

最終小紅和小綠確認合做關係:編程

一、小紅提供遊戲SDK,須要包含核心的登陸功能、支付功能;
二、小綠開發完的遊戲,不接入其它平臺的登陸和支付系統,直接接入小紅的遊戲SDK,用小紅的登錄和支付系統
三、小紅每月都要跟小綠對帳,按比例分紅給小綠緩存

小結: 遊戲SDK跟普通SDK的區別在於,它提供一個遊戲帳號體系和支付體系,核心就是登陸和支付功能。安全

2.2 遊戲SDK的流程圖

遊戲SDK最核心的是登陸和支付功能,其它的都是運營相關的,例如埋點、數據統計等等~

登陸和支付的流程大概以下圖:

image.png

圖畫的比較簡陋,解釋一下,上半部分是登陸流程、下半部分是支付流程

流程還算比較簡單的~

接下來講說遊戲SDK開發的一些須要注意的點:

3、遊戲SDK開發注意事項

3.1 少依賴

不少開發者都知道,做爲SDK,應該儘可能少使用開源庫,或者說不用開源庫,
而是經過手寫網絡框架,手寫數據庫等等,主要是考慮兩個方面:

  • 減少SDK體積 ;
  • 避免第三方接入的時候發生依賴衝突

固然,依賴庫並非說不能用,有時候一些數據統計的庫須要依賴第三方,那這種狀況是沒有辦法避免的,能夠在對接文檔中提供一個解決依賴衝突的辦法

3.2 解決依賴衝突

方式一

在app的build.gradle中添加相似配置以下:

configurations.all {
    resolutionStrategy {
        //解決v4包衝突,強制使用這個版本的v4包
        force 'com.android.support:support-v4:26.1.0'
    }
}

複製代碼

方式二

exclude

implementation("com.xxx.xxx:xx") {
     exclude group: 'com.android.support'
}
複製代碼

exclude是最經常使用的解決依賴衝突的方式,但若是多個依賴庫引入不一樣版本的其它庫,須要分別寫好多個exclude,顯然第一種方式比較簡單粗暴。

3.3 對外暴露的接口儘可能少

面向接口編程,以遊戲SDK爲例,對外暴露的接口通常有SDK初始化、登陸、支付等,參考設計以下:

定義接口:

interface IGame {

    // 一、在Application中調用,
    fun registerApp(context: ApplicationContext, appId: String)

    // 二、在activity中初始化
    fun init(activity: Activity)

    // 三、業務接口,登陸、支付等等
    fun login(loginCallBack: LoginCallBack)
    
    fun pay(product: Product, payCallBack: PayCallBack)
    ...
}
複製代碼

實現類

/**
 * 實現類
 */
class GameImpl : IGame{

    override fun registerApp(context: ApplicationContext, appId: String) {
		//appid相關
    }

    override fun init(activity: Activity) {
		//初始化邏輯,例如顯示懸浮窗
    }

    override fun login(loginCallBack: LoginCallBack) {
		//登陸邏輯
    }

    override fun pay(product: Product, payCallBack: PayCallBack) {
		//支付邏輯
    }
    ...

}

複製代碼

實現類是咱們的內部邏輯,咱們不但願被外部訪問到,外部只須要知道有 IGame這個接口中的方法就行,咱們能夠再寫個單例的管理類來給外部使用

/**
 * 單例的SDK管理類
 */
object GameSDKManager :IGame{

    //實現類私有化
    private val gameImpl: IGame  by lazy { GameImpl() }

    override fun registerApp(application: Application, appId: String) {
        gameImpl.registerApp(application,appId)
    }

    override fun init(activity: Activity) {
        gameImpl.init(activity)
    }

    override fun login(loginCallBack: LoginCallBack) {
        gameImpl.login(loginCallBack)
    }

    override fun pay(product: Product, payCallBack: PayCallBack) {
        gameImpl.pay(product,payCallBack)
    }

}

複製代碼

kotlinobject關鍵字表示單例,

外部經過GameSDKManager.xxx來調用SDK中的方法,
之後要提供其它方法,只要修改 IGame接口,而後在 GameSDKManagerGameImpl 中分別實現便可。

固然,不是說必定要這樣拆分三個類,這只是一個面向接口編程的例子。

4、遊戲SDK的坑

遊戲SDK前期開發自測多是很順利的,難度不大,可是在跟遊戲對接的時候可能會出現一些問題, 什麼ClassNotFound、Resource not found、依賴衝突、崩潰等等,至於爲何這樣,下面會介紹~

4.1 SDK要支持Eclipse

SDK 1.0 測試經過,正式上線,高高興興地把文檔甩給對接方,內心想,這個我測過的沒問題,demo也給了,只要按照文檔和demo來,問題不大。

編程5分鐘,扯淡2小時.png

然而,對方回覆了一句:「有Eclipse接入文檔嗎?」

我一臉懵逼,這都什麼年代了,真還有人用Eclipse開發App?

我想試圖說服對方用Android Studio,而後獲得的回覆是:其它的遊戲SDK都提供了Eclipse的接入方式~

想起我上一次用Eclipse應該是大三的時候...

就這樣,次日下載了Eclipse以後,按照教程安裝APT插件,然而編譯一直報錯,忘記具體的錯誤信息了,最終的解決辦法是下載了一份Eclipse版本的SDK,Eclipse 不能使用Android Studio版本的SDK

好了,Eclipse環境弄好了,hello world也跑起來了,開始寫demo~

因爲SDK的產物是aar,而Eclipse只能依賴jar包和library,通常都用jar包依賴,先將aar解壓出來,把裏面的classes.jar拷貝出來重命名,而後在Eclipse中依賴這個jar包,同時,SDK的資源文件、libs目錄下的jar包也須要拷貝到Eclipse項目中。

終於,編譯成功,安裝,打開,閃退了~

啪.jpg

奔潰信息指向:setContentView(xxx),錯誤信息是 Resources$NotFoundException: Resource ID #0x13d6b6

4.2 setContentView(xxx) 憑什麼奔潰?

看如下這段代碼

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    //簡單的一段代碼
    setContentView(R.layout.activity_test)
    
}
複製代碼

這段代碼在打包aar的時候,Android Studio接入沒問題,可是打成jar包,Eclipse接入的時候會奔潰,奔潰信息以下,

Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x13d6b6
        at android.content.res.ResourcesImpl.getValue(ResourcesImpl.java:246)
        at android.content.res.Resources.loadXmlResourceParser(Resources.java:2256)
        at android.content.res.Resources.getLayout(Resources.java:1228)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:427)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:380)
        at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:555)
        at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:161)
        at luyao.util.ktx.base.BaseVMActivity.onCreate(BaseVMActivity.kt:25)
複製代碼

按下command 鍵,鼠標放到R.layout.activity_test 上去

image.png

這是一個常量,這個常量定義在R文件中,在AAPT階段生成,

有小夥伴應該已經看出問題所在了,先假設你們都不知道,咱們來回顧一下apk打包的主要流程

  1. AAPT(或者AAPT2)工具打包資源文件,生成R.class文件,resources.arsc資源索引表
  2. AIDL 轉換成Jave代碼(有AIDL的話)
  3. Java代碼編譯成.class文件
  4. 經過dex工具將.class文件轉換成Dalvik 字節碼,也就是.dex文件
  5. 經過ApkBuilde工具將.dex文件和其它資源文件打包成未簽名的apk
  6. 經過簽名工具給apk簽名,v1簽名使用jarsigner、v2簽名使用apksigner(sdk 25版本開始提供)

apk編譯的第一個階段,AAPT會打包資源文件,生成R.class文件和resources.arsc資源索引表

library項目在打包aar的時候,上面123這幾個流程必定會走的,可是aar中並無生成 resources.arsc 這個資源索引表,資源的id跟資源文件的映射關係記錄在R.txt中,以下圖:

aar結構

而Eclipse由於只能接入jar包,也就是解壓aar後取出裏面的classes.jar,當咱們把資源文件拷貝到Eclipse,再編譯apk的時候,資源文件會對應一個新的資源id,而aar中classes.jar裏引用的資源id是不變的

classes.jar裏面的
setContentView(R.layout.activity_test)
至關於
setContentView(-1300150)

而當咱們將 activity_test.xml 拷貝到Eclipse項目後編譯,AAPT從新給它生成一個資源id, R.layout.activity_test 對應的資源id已經不是 -1300150 了,

這就是爲何classes.jar裏面的setContentView(-1300150) 會報錯找不到資源。

知道了問題的緣由以後, 要解決這個問題,那麼SDK裏面使用資源id須要動態去獲取,不能使用R文件裏面的常量~

4.1.2 動態獲取資源id

谷歌提供了相關的API,能夠經過資源名稱獲取資源id

Resources#getIdentifier(String name, String defType, String defPackage)

/**
     * Return a resource identifier for the given resource name.  A fully
     * qualified resource name is of the form "package:type/entry".  The first
     * two components (package and type) are optional if defType and
     * defPackage, respectively, are specified here.
     * 
     * <p>Note: use of this function is discouraged.  It is much more
     * efficient to retrieve resources by identifier than by name.
     * 
     * @param name The name of the desired resource.
     * @param defType Optional default resource type to find, if "type/" is
     *                not included in the name.  Can be null to require an
     *                explicit type.
     * @param defPackage Optional default package to find, if "package:" is
     *                   not included in the name.  Can be null to require an
     *                   explicit package.
     * 
     * @return int The associated resource identifier.  Returns 0 if no such
     *         resource was found.  (0 is not a valid resource ID.)
     */
    public int getIdentifier(String name, String defType, String defPackage) {
        return mResourcesImpl.getIdentifier(name, defType, defPackage);
    }

複製代碼

第一個參數是資源名稱,例如一個TextView定義的id叫tv_title;
第二個參數是類型,例如 string、xml、style、layout 等等,跟R.class文件裏面的內部類是對應的

image.png

若是想獲取佈局文件id,傳layout,若是是獲取字符串id,傳string,以此類推。

第三個參數是包名。

最後封裝成工具類以下

object ResourceUtil {

    //緩存資源id
    private val idMap: HashMap<String, Int> = HashMap()

    private fun getIdByName(context: Context, defType: String, name: String): Int {
        
        //緩存
        val key = defType + "_" + name
        val value: Int? = idMap.get(key)
        value?.let {
            return it
        }

        //獲取資源id
        val identifier = context.resources.getIdentifier(name, defType, context.packageName)
        identifier?.let {
            idMap.put(key, identifier)
        }
        return identifier
    }
    
    /**
     * 獲取佈局文件的資源ID,defType傳 layout
     */
    fun getIdFromLayout(context: Context, name: String): Int {
        return getIdByName(context, "layout", name)
    }
    ...
    
複製代碼

而後setContentView(R.layout.test) 須要修改爲

setContentView(ResourceUtil.getIdFromLayout(context, "test"))
複製代碼

問題是解決了,可是仍是須要了解一下底層原理,例如,AAPT打包資源文件,會生成資源id,資源id跟資源是如何關聯起來的呢?經過資源名稱去讀資源id,又是如何讀取的呢?

3.1.3 AAPT打包產物

編譯的第一個階段,使用AAPT打包資源文件,產物以下

  1. res文件夾內的圖片及xml資源(xml被編譯成二進制)
  2. assets文件夾(不會生成資源id)
  3. 二進制AndroidManifest.xml
  4. 資源索引表 resources.arsc
  5. R.class文件

重點關注資源索引表 resources.arsc,

resources.arsc 文件的數據格式比較複雜,Android Studio能夠幫咱們解析出來

經過Android Studio的 Build -> Analyze APK,打開apk後選擇 resources.arsc打開

image.png

id(資源id)、name(資源名稱)、value(資源路徑)均可以經過這個索引表來互相轉換,
前面說過 Resources#getIdentifier(String name, String defType, String defPackage),之因此能夠經過資源名稱獲取到資源id,固然仍是要藉助 resources.arsc 這個資源索引表。

3.1.4 經過資源名稱讀取資源id的原理

Resources#getIdentifier源碼我大概跟了一下,調用流程是

Resources#getIdentifier

ResourcesImpl#getIdentifier

AssetManager#getResourceIdentifier

AssetManager2.cpp#GetResourceId

不貼太多源碼,你們有興趣能夠看 AssetManager2.cpp 這個類,裏面關聯了 ApkAssets, frameworks/base/libs/androidfw/ApkAssets.cpp

ApkAssets.cpp 裏面有 resources.arsc 的定義和使用

image.png

得出結論是resources.arsc是在native層加載和解析的,經過resources.arsc這個資源索引表,能夠將資源id和資源名稱、資源路徑相互轉換。

上面講的這些太枯燥了,遊戲SDK就這些內容?能不能來點實用的呢?

5、遊戲SDK開發,後期的一些操做

若是是普通的遊戲SDK,那麼只要保證接入方可以成功接入SDK就完事了,然而,

小紅除了提供遊戲SDK以外,還須要對 接入遊戲SDK的遊戲進行驗收,確保遊戲SDK的功能正常。

image.png

畢竟遊戲是要在小紅的平臺上運營,小紅有責任和義務對每個遊戲進行測試驗收,確保基本功能正常,總不能用戶一打開就奔潰吧~

隨着SDK的版本升級,功能會增長,須要驗收的功能會愈來愈多,例如:驗證簽名,SDK有檢查更新的功能,token過時,遊戲須要作退出登陸邏輯等等...

下面將介紹我是如何處理一些問題的。

5.1 日誌開關

SDK接入出現問題,release版本若關閉了日誌,咱們須要將日誌打開復現問題,經常使用的有兩種方式:

  1. 能夠參考開發者模式的開關,設置某個控件的點擊事件,例如在連續點擊5次的時候打開日誌開關。 日誌開關須要持久化,例如保存到sp,在SDK初始化的時候去讀這個開關。

  2. 還有一種作法是相似友盟,初始化的方法提供debug參數,讓接入方能夠傳true來查看日誌,可是考慮到SDK內部信息安全,我沒有這麼作。

5.2 配置檢查

我提供的demo運行是正常的,可是第三方他們接入的時候常常會出現一些問題,多是他們的Android SDK版本不同,或者一些配置沒有嚴格按照文檔來寫,做爲SDK的開發者,我但願這些配置的問題接入方能夠本身發現和處理,這就須要在遊戲SDK中增長檢測的邏輯。

5.2.1 一個檢查更新的功能

Android 8.0 開始,調起應用安裝頁面,須要用戶顯式打開未知來源開關,因而有以下代碼

image.png

有一次發如今接入方的apk中,context.packageManager.canRequestPackageInstalls(),一直返回false,無法調起安裝頁面,首先想到的是,接入方沒有聲明安裝權限

<!--安裝apk須要的權限-->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
複製代碼

而後本身去掉權限聲明驗證一下,發現會拋異常,說明不是這個緣由。

最後發現 targetSdkVersion 小於26的話, packageManager.canRequestPackageInstalls()一直會返回false,目前各大應用市場已經陸續要求targetSdkVersion必須26或以上,爲了保證SDK的更新功能正常,在SDK初始化的時候,添加以下檢測代碼

image.png

這樣接入方targetSdkVersion就必定要26或以上,不然拋異常,從異常日誌中就能夠發現問題。

4.2.2 FileProvider 須要增長配置檢查

因爲 7.0以後安裝apk須要經過FileProvider來獲取url,因此manifest有了這樣的代碼

image.png

若是是Android Studio打包,通常會自動讀取build.gradle中的applicationId來替換佔位符${applicationId},

若是是Eclipse打包,佔位符${applicationId}則原封不動,不會被替換,那麼下面的代碼就會報空指針了

FileProvider.getUriForFile(context,
                    context.packageName + ".fileprovider", file)
複製代碼

如何保證接入方必定有配置FileProvider,而且配置正確呢?增長配置檢測代碼以下

image.png

在sdk初始化的時候去私有目錄建立一個空文件,而後經過 getUriFormFile 方法觸發FileProvider獲取url的邏輯,若是有異常,說明FileProvider配置不對。

以後在驗收apk的時候,只要能正常安裝打開,就說明FileProvider配置是正確的。

5.2.3 簽名驗證

遊戲方接入遊戲SDK以後打包成apk,這個apk要在咱們平臺上線,咱們但願統一apk簽名, 因此在驗收apk的時候,須要確認apk的簽名。

查看apk簽名主要用兩種方式:

針對v2簽名

keytool -printcert -jarfile xxx.apk

or

apksigner verify -v --print-certs xxx.apk

image.png

這個命令雖然簡單粗暴,可是要求apk使用v2簽名,

針對v1簽名

若是apk是使用v1簽名,那麼比較麻煩,須要解壓apk,找到META-INFO目錄下的 CERT.RSA,而後執行命令

keytool -printcert -file CERT.RSA

image.png

針對v1簽名可能有更好的辦法,我沒找到~

代碼簽名檢查

若是是使用v2簽名還好,直接一個命令就能查看簽名,可是大部分遊戲發行商都是使用v1簽名,手動驗證簽名仍是比較麻煩的,仍是代碼裏驗證下比較香啊~

fun checkSign(context: Context) {
    val signCheck = SignCheck(context, "A3:E1:5E:BA:...")
    if (signCheck.check()) {
        Log.i(TAG, "簽名正確")
    } else {
        toast("應用簽名不匹配,請檢查簽名")
    }
}
複製代碼

SignCheck 類的邏輯主要是獲取應用簽名,check方法是將應用簽名跟正確的簽名作對比,相同就返回true。

若是簽名不正確,遊戲方接入SDK過程會彈toast提示

若是有其它必選配置,相似的方式處理一下,一勞永逸~

六 遊戲SDK的渠道包概念

渠道包你們都不陌生,通常是爲了統計app在不一樣應用市場的數據,例如新增、日活、留存等。

遊戲SDK的渠道包概念稍微有點不一樣:

平臺上線了遊戲以後,依賴用戶本身來下載遊戲,起量是很慢的,因此須要推廣,若是使用推送讓用戶去下載,那麼用戶體驗會不好。因此須要讓那些有影響力的人來作有償推廣。SDK中每個請求接口都會傳渠道標識,好比A用戶去推廣遊戲,咱們會給他一個打了A渠道標識的apk,經過這個apk註冊的用戶,就歸屬A用戶。

6.1 選擇打渠道包的方式

按照簽名方式的不一樣,目前有兩個比較熱門的打渠道包的開源庫

下一代Android打包工具:https://github.com/mcxiaoke/packer-ng-plugin
有兩個版本,支持v1簽名和v2簽名。

Walle(瓦力):https://github.com/Meituan-Dianping/walle
目測只支持v2簽名。

對於遊戲SDK來講,單純使用Walle並不適合,由於大部分遊戲發行商,默認的apk簽名方式都是v1簽名。

成年人不喜歡作選擇,兩個都要

fun getChannel(context: Context): String {

    //針對v1簽名
    var channel = PackerNg.getMarket(context)

    if (TextUtils.isEmpty(channel)) {
        //針對v2簽名
        channel = WalleChannelReader.getChannel(context, Utils.getDefaultChannel())
    }
    return channel

}
複製代碼

可使用 PackerNg-v1 + PackerNg-v2,也可使用 PackerNg-v1 + Walle。

6.2 渠道包原理

6.2.1 針對v1簽名

PackerNg-v1 的原理:

APK文件實際上是一個帶簽名信息的ZIP文件,根據 ZIP文件格式規範,ZIP文件末尾有一部分元數據表明ZIP文件註釋,正確修改這一部分數據不會對ZIP文件形成破壞

image.png

針對v1簽名,還有其它渠道包方案,可是大部分都存在效率問題,例如利用gradle的productFlavors屬性打渠道包,速度慢;或者利用META-INF目錄不被簽名校驗的特色,加入文件名爲渠道名的空文件,可是讀取渠道的時候比較慢,由於須要解壓apk讀取。

6.2.2 針對v2簽名

使用v2簽名的apk,上面針對v1簽名的方案所有失效。

Walle 的原理是:

V2簽名塊中有個區塊能夠添加一些附屬信息,而且不會被簽名校驗,將自定義渠道信息寫入這個區塊,生成渠道包。

七 反編譯

前期,遊戲發行商出的apk可能沒有使用咱們的簽名,讓他們從新打包有時候耗時比較長,因此必須掌握apktool的相關命令,來進行解包和打包,以及簽名。

7.1 apktool下載

apktool github

須要配置下環境,比較簡單,mac:下載apktool.jar、apktool可執行腳本,放到 /usr/local/bin/ 目錄下,而後 command + x 設置權限就能夠了。

7.2 反編譯

apktool d demo.apk

image.png

會將demo.apk反編譯以後輸出到demo目錄,-o 參數能夠指定輸出目錄。

反編譯以後就能夠修改資源文件或者字節碼

7.3 回編譯

apktool b demo -o unsign.apk

image.png

輸出的是未簽名的apk,須要簽名才能安裝到手機上

7.4 apk簽名

通常咱們用Android Studio打一個簽名的apk很簡單

image.png

可是單獨給一個未簽名的apk簽名,就須要藉助簽名工具,v1簽名是使用jarsigner,v2簽名是使用apksigner,

7.4.1 v1簽名

jarsigner -verbose
-keystore [簽名文件路徑]
-keypass [密碼]
-storepass [密碼]
-signedjar [輸出apk路徑] [須要簽名的apk路徑]
-digestalg [摘要算法的名稱如SHA1]
-sigalg [簽名算法的名稱如MD5withRSA]
[證書別名]

例如個人簽名文件叫 lizhigame.keystore,別名密碼都是 lizhigame,那麼簽名命令以下

jarsigner -verbose -keystore lizhigame.keystore -keypass lizhigame -storepass lizhigame -signedjar sign.apk unsign.apk -digestalg SHA1 -sigalg MD5withRSA lizhigame

執行命令後能夠看到控制檯日誌

image.png

7.4.2 v2簽名

V2 簽名使用apkSigner,在SDK build-tools下,注意在版本25以上纔有

image.png

apkSigner簽名命令:

apksigner sign
--ks [簽名文件]
--ks-pass pass:[密碼]
--out [輸出apk路徑]
[須要簽名的apk]

例如個人簽名文件叫 lizhigame.keystore,別名密碼都是 lizhigame,那麼簽名命令以下

apksigner sign --ks lizhigame.keystore --ks-pass pass:lizhigame --out sign_v2.apk unsign.apk

image.png

apksigner 簽名過程沒有任何提示,能夠結合驗證簽名命令一塊兒使用

驗證簽名

apksigner verify -v --print-certs sign_v2.apk

總結

這篇文章是我對遊戲SDK開發三個多月工做的總結和分享,遊戲SDK開發,更多的是業務問題處理和對接問題處理。將重複性的工做作成自動化,經過代碼檢查配置的方式,強制讓接入方按照咱們的要求來接入SDK,能夠減小沒必要要的溝通成本。

本文知識點總結:

  1. 介紹遊戲SDK的概念,流程
  2. 介紹遊戲SDK開發的注意事項
  3. Eclipse接入SDK奔潰緣由分析,須要動態獲取資源id
  4. 介紹AAPT打包資源文件過程,源索引表resources.arsc的做用
  5. 遊戲SDK的一些細節的操做
  6. 渠道包方案和原理
  7. apktool反編譯和回編譯
  8. 使用jarsigner和apksigner對apk進行簽名

若是你正在找工做,招聘網站上多多少少有一些遊戲SDK開發的崗位,薪資通常不會過低,但願這篇文章能帶給你一些幫助。

其它

最近幾個月很是忙,沒有太多精力寫文章(主要仍是懶)~

接下來我仍是會抽時間堅持寫的,主要方向是:高質量開發高效開發架構等方面,這是通往高級Android工程師必須跨越的檻,我會結合實際項目,來完成這個系列的文章。

敬請期待~

相關文章
相關標籤/搜索