Google Play 下架 App 以後的替身製做

前段時間升級 qq sdk 實現第三方登陸功能。在用戶手機未安裝QQ時,會引導用戶下載安裝。Google Play 商店以它的規則爲由下架了咱們的App。這個問題不少開發者都遇到過,畢竟咱們都得聽 Google 的,規則制定者不是開玩笑的。通過溝通,堅定不讓從新上架,提議換個包名拷貝代碼,從新上傳一個新的應用。咱們當時按照這個簡單的方法上架了緊急修復的App,可是考慮到後續功能迭代以及兩個項目的維護成本,須要尋求一個新的方式來完成這些操做。android

背景

公司有個老版本的讀書軟件一直在線上,可是好久沒維護了。此次事故正好能夠把老的軟件做爲殼子,替換成目前維護的新的App。這樣能夠避免用戶流失(Google Play 渠道用戶量自己就不是很大)。git

修改應用ID

每一個 Android 應用均有一個惟一的應用 ID,像 Java 軟件包名稱同樣,如 com.example.myapp。 此 ID 能夠在設備上和 Google Play 商店中對您的應用進行惟一標識。 若是您想要上傳新版本的應用,應用 ID(以及使用它簽署的證書)必須與原始 APK 相同 - 若是您更改應用 ID,Google Play 商店會將 APK 視爲徹底不一樣的應用。因此您發佈應用後,毫不應更改應用 ID。github

基於這個原則,咱們實現的方式很簡單,配置編譯變體,指定特定的 applicationIdapi

應用是基於 Walle 進行多渠道打包的,那麼咱們須要配置兩個 productFlavors ,其中一個是對 Google Play 商店的定製版,另外一個是使用 Wally 進行多渠道打包的基礎apk。固然若是你沒有作多渠道打包,那麼也至少須要配置兩個,畢竟你須要一個 未變體的 Apk 供其餘渠道使用。服務器

flavorDimensions "default" // 當只有一個時,不須要在 Flavors 中重複指定
productFlavors {
    google { // Google Play 商店的定製版
        applicationId "com.yun.reader"
    }

    yun { // 基礎版本 apk
        applicationId "com.yun.news"
    }
}
複製代碼

好了,sync以後,如今咱們就能夠在 Gradle->:app->Tasks->build 中編譯兩個不一樣的 apk 了。微信

指定不一樣的簽名

老版本的 Apk 簽名和新開發 Apk 並非用的同一個簽名文件,因此,在productFlavors中須要指定簽名文件。cookie

首先咱們須要定義簽名文件:app

android {
    signingConfigs {
        yun {
            if (System.getenv("YUN_NEWS_KEYSTORE_FILE") != null) {
                storeFile file(System.getenv("YUN_NEWS_KEYSTORE_FILE"))
                storePassword System.getenv("YUN_NEWS_KEYSTORE_PASSWORD")
                keyAlias System.getenv("YUN_NEWS_KEY_ALIAS")
                keyPassword System.getenv("YUN_NEWS_KEY_PASSWORD")
            }
        }

        google {
            if (System.getenv("YUN_READER_KEYSTORE_FILE") != null) {
                storeFile file(System.getenv("YUN_READER_KEYSTORE_FILE"))
                storePassword System.getenv("YUN_READER_KEYSTORE_PASSWORD")
                keyAlias System.getenv("YUN_READER_KEY_ALIAS")
                keyPassword System.getenv("YUN_READER_KEY_PASSWORD")
            }
        }
    }
}
複製代碼

看上面的代碼你會發現,咱們的路徑都是放在遠程編譯服務器的環境變量中的,你也能夠存放在本地的 local.properties 中,具體的操做能夠自行Google。微信支付

兩個簽名定義完成,使用起來很簡單:gradle

flavorDimensions "default" // 當只有一個時,不須要在 Flavors 中重複指定
productFlavors {
    google { // Google Play 商店的定製版
        applicationId "com.yun.reader"
        signingConfig signingConfigs.google
    }

    yun { // 基礎版本 apk
        applicationId "com.yun.news"
        signingConfig signingConfigs.yun
    }
}
複製代碼

這裏有幾點須要注意

  1. signingConfigs 聲明須要放在 productFlavors 以前,不然找不到對應的自定義簽名
  2. productFlavors 中已指定簽名,須要把 buildTypes -> release 下面指定的簽名刪除,不然在編譯 Release 版本時會覆蓋掉 productFlavors 中指定的簽名。

微信支付相關報錯

咱們替換掉 applicationId 以後,其實 Context.getPackageName() 方法返回的值也跟着變化了,那麼,微信支付根據這個包名去查找相關的配置確定是找不到的,因此,咱們須要將 WXEntryActivityWXPayEntryActivity 拷貝一份到 com.yun.reader.wxapi 包名下面。記得在 manifests 中用絕對路徑聲明這兩個 Activity。

有的同窗就算這樣配置以後,微信支付仍然會報錯,由於咱們改了 applicationId 致使之前默認是 news 的相關配置對 reader 是不適用的。因此咱們須要爲之前的代碼背鍋,將全部寫死的地方改成配置型。

例如: 在微信支付時,須要傳遞 app_code 字段,讓服務器在生成訂單時,知曉當前的應用是哪個,方便後續的校對。若是服務器直接寫死了是 news, 那麼在後續匹配中,news 申請的 支付碼和 packageName 不能匹配,那麼支付失敗是必然的。

相似的問題還有 cookie , 與Web端交互的時候,對方會根據cookie來判別應用,因此Web端也須要作兼容。RN 端相似。

AndroidManifest 中根據 productFlavors 指定特定變量

例如:QQ 登陸,每一個 App 有不一樣的 scheme,本文中用 applicationId 來假裝成兩個不一樣的 App, scheme 須要配置不一樣的 tencent_id。這裏能夠利用manifestPlaceholders來實現這個需求。

首先須要在 gradle 中聲明:

defaultConfig {
    manifestPlaceholders = [tencent_id: "1000000000", package_name: "com.yun.news"]
}
複製代碼

若是 manifestPlaceholders 包含多個值,須要用 , 隔開。

productFlavors中配置很簡單

productFlavors {
    google {
        applicationId "com.yun.reader"
        signingConfig signingConfigs.google
        manifestPlaceholders.tencent_id = "1000000000"
        manifestPlaceholders.package_name = "com.yun.reader"
    }

    yun {
        applicationId "com.yun.news"
        signingConfig signingConfigs.yun
        manifestPlaceholders.tencent_id = "1000000001"
        manifestPlaceholders.package_name = "com.yun.news"
    }
}
複製代碼

manifest 中使用方式以下:

<activity android:name="com.tencent.tauth.AuthActivity" ...>
    <intent-filter>
        ...
        <data android:scheme="tencent${tencent_id}" />
    </intent-filter>
</activity>

複製代碼

這樣咱們就能夠根據不一樣的 productFlavors 來配置特性字段了。 相似的有:MIPush(若是寫死包名,手機不能同時安裝兩個變體),

參考:developer.android.com/studio/buil…

相關文章
相關標籤/搜索