精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Gradle實(shí)現(xiàn)Android多渠道定制化打包

移動開發(fā) Android
最近在項(xiàng)目中遇到需要實(shí)現(xiàn) Apk 多渠道、定制化打包, Google 、百度查找了一些資料,成功實(shí)現(xiàn)了上述功能,在此記錄以備不時(shí)之需,溫故而知新,可以為師矣~

最近在項(xiàng)目中遇到需要實(shí)現(xiàn) Apk 多渠道、定制化打包, Google 、百度查找了一些資料,成功實(shí)現(xiàn)了上述功能,在此記錄以備不時(shí)之需,溫故而知新,可以為師矣~

需求可以總結(jié)如下: 

 

 

 

如何實(shí)現(xiàn)多個(gè) Apk 安裝在同一設(shè)備

在之前的印象中,同一個(gè)應(yīng)用在同一設(shè)備上只能安裝一個(gè),除非手動修改 AndroidManifest.xml 文件中的包名( package ),但這么做的后果就是新的應(yīng)用真的是新的應(yīng)用,舊版應(yīng)用再也收不到更新。而現(xiàn)在你通過 Gradle,你可以輕松構(gòu)建多個(gè)不同版本的應(yīng)用,并且在同一設(shè)備上安裝使用。

這里要用到 productFlavors ,productFlavors 可以用來自定義應(yīng)用構(gòu)建版本,我們可以用其 applicationId 屬性來實(shí)現(xiàn)多個(gè) Apk 安裝在同一設(shè)備上。

build.gradle 中部分配置代碼如下: 

  1. android { 
  2.     compileSdkVersion 24 
  3.     buildToolsVersion "24.0.1" 
  4.  
  5.     //默認(rèn)配置,所有 productFlavors 都會繼承 defaultConfig 中配置的屬性 
  6.     defaultConfig { 
  7.         //默認(rèn)的 applicationId,一般與 AndroidManifest.xml 文件 package屬性相同 
  8.         applicationId "com.littlejie.multichannel" 
  9.         minSdkVersion 15 
  10.         targetSdkVersion 24 
  11.         versionCode 1 
  12.         versionName "1.0" 
  13.     } 
  14.  
  15.     // productFlavors 定義了一個(gè)應(yīng)用的自定義構(gòu)建版本 
  16.     //一個(gè)單一的項(xiàng)目可以同時(shí)定義多個(gè)不同的 flavor 來改變應(yīng)用的輸出。 
  17.     // productFlavors 這個(gè)概念是為了解決不同的版本之間的差異非常小的情況,通常用于區(qū)分同一個(gè)應(yīng)用的不同渠道/客戶等,可包含少量業(yè)務(wù)功能差別。 
  18.     // productFlavors 中的 flavor 不能跟 buildType 中的一樣,否則會報(bào): "ProductFlavor names cannot collide with BuildType names" 
  19.     productFlavors { 
  20.  
  21.         //默認(rèn)版本,不設(shè)置 applicationId ,繼承 defaultConfig 中的配置 
  22.         flavors_default { 
  23.         } 
  24.  
  25.         //開發(fā)版本, applicationId 替換為 com.littlejie.multichannel.dev 
  26.         flavors_dev { 
  27.             applicationId "com.littlejie.multichannel.dev" 
  28.         } 
  29.  
  30.         //發(fā)布版本, applicationId 替換為 com.littlejie.multichannel.release 
  31.         flavors_release { 
  32.             applicationId "com.littlejie.multichannel.release" 
  33.         } 
  34.     } 
  35.  

MainActivity.java: 

  1. public class MainActivity extends Activity { 
  2.  
  3.     private static final String TAG = MainActivity.class.getSimpleName(); 
  4.  
  5.     @Override 
  6.     protected void onCreate(Bundle savedInstanceState) { 
  7.         super.onCreate(savedInstanceState); 
  8.         setContentView(R.layout.activity_main); 
  9.  
  10.         Log.d(TAG, "package name = " + this.getPackageName()); 
  11.     } 
  12.  

在 Android Studio 中執(zhí)行如下命令: 

  1. //打 debug 包,gradle 命令會在后面 `gradle task`中詳細(xì)講述 
  2. gradle clean assembleDebug  

打包完成后,將 Apk 安裝到模擬器(adb install name.apk),運(yùn)行,log 如下:

flavors_default: 

  1. 09-17 22:43:55.390 19747-19747/com.littlejie.multichannel D/MainActivity: package name = com.littlejie.multichannel 

flavors_dev: 

  1. 09-17 22:11:30.860 2638-2638/com.littlejie.multichannel.dev D/MainActivity: package name = com.littlejie.multichannel.dev 

flavors_release: 

  1. 09-17 22:44:55.610 20650-20650/com.littlejie.multichannel.release D/MainActivity: package name = com.littlejie.multichannel.release 

從這里可以看出,不同 flavor 的 package name 被 applicationId 替換掉了,而且同一個(gè)模擬器上可以同時(shí)安裝以上三個(gè)應(yīng)用。

下面我們再看看 AndroidManifest.xml 中發(fā)生了什么變化。這里需要用到 aapt 來查看 AndroidManifest.xml 的信息:

  1. //輸出 apk 的 AndroidManifest.xml 文件的信息aapt dump xmltree ***.apk AndroidManifest.xml 

下面是 flavors_dev 版本的信息,可以看出 Java 源文件的包名并沒有發(fā)生改變,而 package 屬性的值被替換為 applicationId了。

如果在申請第三方 SDK 接入,則對應(yīng)的包名應(yīng)該填 applicationId ,而不是 AndroidManifest.xml 中的默認(rèn)值 

  1. lishengjiedeMacBook-Pro:apk littlejie$ aapt dump xmltree multichannel-flavors_dev-debug.apk AndroidManifest.xml 
  2. N: android=http://schemas.android.com/apk/res/android 
  3.   E: manifest (line=2) 
  4.     A: android:versionCode(0x0101021b)=(type 0x10)0x1 
  5.     A: android:versionName(0x0101021c)="1.0" (Raw: "1.0"
  6.     //此處 package 的值已替換成 applicationId 的值 
  7.     A: package="com.littlejie.multichannel.dev" (Raw: "com.littlejie.multichannel.dev"
  8.     A: platformBuildVersionCode=(type 0x10)0x18 (Raw: "24"
  9.     A: platformBuildVersionName=(type 0x4)0x40e00000 (Raw: "7.0"
  10.     E: uses-sdk (line=7) 
  11.       A: android:minSdkVersion(0x0101020c)=(type 0x10)0xf 
  12.       A: android:targetSdkVersion(0x01010270)=(type 0x10)0x18 
  13.     E: application (line=11) 
  14.       A: android:theme(0x01010000)=@0x7f08008e 
  15.       A: android:label(0x01010001)=@0x7f060020 
  16.       A: android:icon(0x01010002)=@0x7f030000 
  17.       A: android:debuggable(0x0101000f)=(type 0x12)0xffffffff 
  18.       A: android:allowBackup(0x01010280)=(type 0x12)0xffffffff 
  19.       A: android:supportsRtl(0x010103af)=(type 0x12)0xffffffff 
  20.       // Activity 的包名還是原來 AndroidManifest.xml 中申明的 
  21.       E: activity (line=17) 
  22.         A: android:name(0x01010003)="com.littlejie.multichannel.MainActivity" (Raw: "com.littlejie.multichannel.MainActivity"
  23.         E: intent-filter (line=18) 
  24.           E: action (line=19) 
  25.             A: android:name(0x01010003)="android.intent.action.MAIN" (Raw: "android.intent.action.MAIN"
  26.           E: category (line=21) 
  27.             A: android:name(0x01010003)="android.intent.category.LAUNCHER" (Raw: "android.intent.category.LAUNCHER" 

applicationId 的原理可以理解為在 gradle 打包的時(shí),動態(tài)合并屬性,將 package 替換為 applicationId 指定的值,但并不會替換 Java 文件的包名,包括生成的 R 文件(可以去對應(yīng) module 下的 build/generated 目錄下查看對應(yīng) flavor 的 R 文件)。

另外,由于最終生成的包中 AndroidManifest.xml 文件中的 package 屬性被 applicationId 替換掉,故對于某些第三方 SDK ,如:微信、高德地圖等需要驗(yàn)證包名的,就會碰到相當(dāng)?shù)疤鄣氖拢總€(gè)包都需要重新去生成 APPID 和 APPKEY,如果渠道很多,那么像微信就會出現(xiàn)問題微信賬號申請的應(yīng)用數(shù)就會超出微信的限制。

Android 官方文檔原文如下:

Therefore, we have decoupled the two usages of package name:

The final package that is used in your built .apk's manifest, and is the package your app is known as on your device and in the Google Play store, is the "application id".

The package that is used in your source code to refer to your R class, and to resolve any relative activityrvice registrations, continues to be called the "package".

補(bǔ)充:ApplicationId versus PackageName

替換 AndroidManifest.xml 中的屬性

這里可以參考友盟統(tǒng)計(jì) SDK 中使用的方案。該方案通過在 AndroidManifest.xml 文件中 application 標(biāo)簽下指定 <mate-data> 設(shè)置占位符來實(shí)現(xiàn)動態(tài)替換屬性值。 

  1. <meta-data android:name="UMENG_CHANNEL" android:value="${UMENG_CHANNEL}" /> 

占位符形如${name},在最終執(zhí)行 AndroidManifest.xml 文件合并的時(shí)候,占位符會被

build.gradle 中對應(yīng)值取代。 build.gradle 的配置需要用到上節(jié)講到的 productFlavors 的 manifestPlaceholders 屬性, manifestPlaceholders 屬性直譯過來就是清單文件占位符。

下面是 build.gradle 的節(jié)選代碼: 

  1. productFlavors { 
  2.  
  3.    //將 AndroidManifest.xml 文件中的 ${UMENG_CHANNEL} 替換為 default 
  4.    flavors_default { 
  5.        manifestPlaceholders = [UMENG_CHANNEL: "defalut"
  6.    } 
  7.  
  8.    flavors_dev { 
  9.        applicationId "com.littlejie.multichannel.dev" 
  10.        manifestPlaceholders = [UMENG_CHANNEL: "dev"
  11.    } 
  12.  
  13.    flavors_release { 
  14.        applicationId "com.littlejie.multichannel.release" 
  15.        manifestPlaceholders = [UMENG_CHANNEL: "release"
  16.    } 
  17.  
  18.  

如果你要替換多個(gè)屬性,則只需要將 manifestPlaceholders 的寫法如下:

  1. manifestPlaceholders = [VALUE_NAME1 : "value" , VALUE_NAME2 : "value"

補(bǔ)充:關(guān)于 AndroidManifest 文件合并規(guī)則可以查看 官方文檔.

替換資源文件

多渠道打包的時(shí)候可能會碰到這種情況:每個(gè)應(yīng)用市場的啟動頁圖標(biāo)、應(yīng)用名稱可能會有點(diǎn)小出入,更有甚者,連布局都不一樣。這時(shí)候我們該怎么辦呢?

有一種解決辦法就是:在代碼里進(jìn)行判斷,根據(jù)渠道的不一樣,加載不同的圖片和布局,這是一種解決辦法。但是當(dāng)渠道有很多時(shí),代碼就會變得很難維護(hù),而且指定渠道用到的資源文件都會被打入所有 Apk 中。所以這個(gè)方法并不值得推薦。那么,有什么好的解決辦法呢?

辦法 Google 早就給我們想好了,而且相當(dāng)簡單,那就是:在 main 的同級目錄下創(chuàng)建以渠道名命名的文件夾,然后創(chuàng)建資源文件(路徑要與 main 中的一致),然后打包的時(shí)候 gradle 就會自己替換或者合并資源。

例如, App 的默認(rèn) icon 路徑為 main\res\mipmap-hdpi\ic_launcher.png ,那么 flavors_dev的路徑就為 flavors_dev\res\mipmap-hdpi\ic_launcher.png ,打包 flavors_dev 渠道的時(shí)候會自動替換圖片。

對于資源合并,如果在 main 下的 strings.xml 內(nèi)容為: 

  1. <resources> 
  2.     <string name="app_name">MultiChannel</string> 
  3.     <string name="string_merge">我是string,我暫時(shí)沒被合并</string> 
  4. </resources>  

在 flavors_dev 下的 strings.xml 內(nèi)容為:

  1. <resources> 
  2.     <string name="string_merge">我是dev_string,我會把string合并</string> 
  3. </resources>  

當(dāng)打 flavors_dev 渠道包時(shí),最終 strings.xml 會變成: 

  1. <resources> 
  2.     <string name="app_name">MultiChannel</string> 
  3.     <string name="string_merge">我是dev_string,我會把string合并</string> 
  4. </resources>  

以上特性可以用來替換 Apk 的應(yīng)用名稱和應(yīng)用圖標(biāo),這比使用前面講到的占位符方便很多。同理,替換圖片和合并顏色的原理也相似。

多渠道使用獨(dú)立簽名

多渠道打包的時(shí)候,可能每個(gè)渠道包的簽名都必須不一樣,真正做到定制化,那么,怎么實(shí)現(xiàn)每個(gè)渠道包使用指定的簽名呢?

平時(shí)我們打包的時(shí)候是這樣的: 

  1. signingConfigs { 
  2.    release { 
  3.        storeFile file("簽名文件路徑"
  4.        storePassword "storePassword" 
  5.        keyAlias "keyAlias" 
  6.        keyPassword "keyPassword" 
  7.    } 
  8.  
  9.  
  10. buildTypes { 
  11.    release { 
  12.        minifyEnabled true 
  13.        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 
  14.        shrinkResources true 
  15.        //指定打 release 包時(shí)使用的簽名文件 
  16.        signingConfig signingConfigs.release 
  17.    } 
  18.  
  19.    //如果 debug 包需要測試諸如微信、地圖等第三方 sdk ,則可以指定 debug 包使用 release 包的簽名 
  20.    //debug { 
  21.    //    signingConfig signingConfigs.release 
  22.    //} 
  23.  

而給每個(gè)渠道包指定簽名其實(shí)也差不多。

Google 官方原話:

This enables either having all release packages share the same SigningConfig, by setting android.buildTypes.release.signingConfig, or have each release package use their own SigningConfig by setting each android.productFlavors.*.signingConfig objects separately.

大意就是,在 buildType 下指定簽名的具體屬性,形如 android.productFlavors.*.signingConfig signingConfigs.* ,前一個(gè) * 指代在 productFlavors 中定義的 flavor ,后一個(gè) * 指代在 signingConfigs 定義的屬性。值得注意的是,signingConfigs 必須定義在 buildType 之前。

以下是 build.gradle 的配置節(jié)選: 

  1. //定義簽名屬性 
  2. signingConfigs { 
  3.    flavors_default { 
  4.        //如果簽名文件在項(xiàng)目的根目錄下,則可以這么寫 
  5.        storeFile file("../littlejie.jks"
  6.        storePassword "******" 
  7.        keyAlias "******" 
  8.        keyPassword "*****" 
  9.    } 
  10.  
  11.    flavors_dev { 
  12.        storeFile file("../littlejie_dev.jks"
  13.        storePassword "*****" 
  14.        keyAlias "*****" 
  15.        keyPassword "*****" 
  16.    } 
  17.  
  18. buildTypes { 
  19.    release { 
  20.        minifyEnabled true 
  21.        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 
  22.        shrinkResources true 
  23.  
  24.        //多個(gè) flavor ,指定 flavor 使用指定 簽名 
  25.        productFlavors.flavors_default.signingConfig signingConfigs.flavors_default 
  26.        productFlavors.flavors_dev.signingConfig signingConfigs.flavors_dev 
  27.    } 
  28.  
  29.    //如果 debug 包需要測試諸如微信、地圖等第三方 sdk ,則可以指定 debug 包使用 release 包的簽名 
  30.    //debug 并不能設(shè)置多個(gè)簽名 
  31.    //debug { 
  32.    //   productFlavors.flavors_default.signingConfig signingConfigs.flavors_default 
  33.    //   productFlavors.flavors_dev.signingConfig signingConfigs.flavors_dev 
  34.    //} 
  35.  

下面我們來驗(yàn)證下生成的包的簽名是否正確,查看簽名我們會用到如下兩個(gè)命令:

  1. //查看簽名文件的屬性 
  2. keytool -list -keystore 簽名文件 
  3.  
  4. //查看 apk 的簽名,需要提前解壓 apk ,獲取 CERT.RSA(位于解壓目錄下 /META-INF 下) 
  5. //以下命令行是在 apk 解壓目錄下執(zhí)行 
  6. keytool -printcert -file META-INF/CERT.RSA  

更多 keytool 命令使用可以查看 官方文檔

首先,我們來看下 littlejie.jks 的信息:

  1. lishengjiedeMacBook-Pro:AndroidDemo littlejie$ keytool -list -keystore littlejie.jks 
  2. 輸入密鑰庫口令: 
  3.  
  4. 密鑰庫類型: JKS 
  5. 密鑰庫提供方: SUN 
  6.  
  7. 您的密鑰庫包含 1 個(gè)條目 
  8.  
  9. littlejie, 2016-9-18, PrivateKeyEntry, 
  10. 證書指紋 (SHA1): A2:B1:BF:BF:F1:F3:26:F4:FD:0C:94:95:B5:32:90:69:24:F7:99:84  

解壓 multichannel-flavors_default-release.apk ,查看 CERT.RSA 信息 

  1. lishengjiedeMacBook-Pro:apk littlejie$ keytool -printcert -file multichannel-flavors_default-release/META-INF/CERT.RSA 
  2. 所有者: CN=littlejie 
  3. 發(fā)布者: CN=littlejie 
  4. 序列號: 71693e05 
  5. 有效期開始日期: Sun Sep 18 17:20:34 CST 2016, 截止日期: Thu Sep 12 17:20:34 CST 2041 
  6. 證書指紋: 
  7.      MD5: AC:12:83:51:44:FC:82:68:8B:23:7B:E9:12:24:AE:52 
  8.      SHA1: A2:B1:BF:BF:F1:F3:26:F4:FD:0C:94:95:B5:32:90:69:24:F7:99:84 
  9.      SHA256: AD:04:19:5F:92:00:0D:FA:7C:E5:8A:12:57:72:4C:1E:0E:2E:FC:0D:92:28:05:D0:CC:42:FC:93:95:44:88:88 
  10.      簽名算法名稱: SHA256withRSA 
  11.      版本: 3  

可以發(fā)現(xiàn)兩者的 SHA1 值是相等的。

同理,可以查看 littlejie_dev.jks 和 multichannel-flavors_dev-release.apk 的簽名信息

  1. //littlejie_dev.jks 的簽名信息 
  2. lishengjiedeMacBook-Pro:AndroidDemo littlejie$ keytool -list -keystore littlejie_dev.jks 
  3. 輸入密鑰庫口令: 
  4.  
  5. 密鑰庫類型: JKS 
  6. 密鑰庫提供方: SUN 
  7.  
  8. 您的密鑰庫包含 1 個(gè)條目 
  9.  
  10. littlejie, 2016-9-18, PrivateKeyEntry, 
  11. 證書指紋 (SHA1): B4:25:67:A5:9F:8C:1F:12:BD:85:6B:2D:FE:71:62:57:8A:CC:AE:E2 
  12.  
  13. //multichannel-flavors_dev-release.apk 的簽名信息 
  14. lishengjiedeMacBook-Pro:apk littlejie$ keytool -printcert -file multichannel-flavors_dev-release/META-INF/CERT.RSA 
  15. 所有者: CN=littlejie 
  16. 發(fā)布者: CN=littlejie 
  17. 序列號: 48346e15 
  18. 有效期開始日期: Sun Sep 18 17:21:23 CST 2016, 截止日期: Thu Sep 12 17:21:23 CST 2041 
  19. 證書指紋: 
  20.      MD5: 15:E9:E1:67:AB:33:8B:04:A4:C3:D0:05:8F:A6:35:37 
  21.      SHA1: B4:25:67:A5:9F:8C:1F:12:BD:85:6B:2D:FE:71:62:57:8A:CC:AE:E2 
  22.      SHA256: 96:A5:14:EC:28:25:32:0D:3E:D0:DB:D0:84:06:E7:9C:17:D7:91:83:A4:51:93:AB:34:3E:D9:FD:C5:FA:A1:8E 
  23.      簽名算法名稱: SHA256withRSA 
  24.      版本: 3  

但是這里有個(gè)問題,就是這種給某個(gè) flavor 指定簽名的方法對 debug 無效,有興趣的同學(xué)可以看上述注釋掉的 debug 簽名部分配置。簡單來說,debug 簽名只能指定一個(gè)或者使用默認(rèn)的 debug 簽名。

若哪位大神有解決方案,歡迎指出~

這里再做幾點(diǎn)補(bǔ)充:

1.多渠道使用獨(dú)立簽名,打包時(shí)千萬不要使用 Android Studio 中 Build 菜單下的 Generate Signed APK,因?yàn)楫?dāng)你使用這個(gè)打包的時(shí)候, Android Studio 會讓你指定使用的簽名文件, so 你就等著哭吧~樓主因?yàn)檫@個(gè)折騰了半天。解決方法就是使用 gradle tasks。傳送門:Android Gradle Build Tasks

2.鑒于第一點(diǎn)中的傳送門需要翻墻,所以在這里簡單介紹一下 Android Gradle Build Tasks 的使用。

  • 打全部包: gradle assemble
  • 打全部 Debug 包: gradle assembleDebug ,可以簡寫為 gradle aD ,前提是沒有相同縮寫的參數(shù)
  • 打全部 Release 包: gradle assembleRelease,可以簡寫為 gradle aR
  • 打指定 flavor 包: gradle assemble(flavor)(Debug|Release)
  • 打包完成后安裝(設(shè)備上沒有安裝該 apk ,否則會失敗,而且只能指定 flavor ,不然也會失敗): gradle install(flavor)(Debug|Release)
  • 打包前先 clean 一下(在測試的時(shí)候很必要,如果不 clean 的話,可能會導(dǎo)致某些小修改不會及時(shí)打入新包): gradle clean assembleDebug

利用 Gradle 修改構(gòu)建版本號

樓主表示對 Groovy 不是很熟,所以利用 Gradle 自動修改構(gòu)建版本這個(gè)就先留著,我先去研究幾天~

補(bǔ)充

有童鞋在評論中說:使用 productFlavors 打包效率太低,的確是這樣, gradle 好用是好用,就是打包效率低。如果只是單純生成渠道包,建議使用美團(tuán)多渠道打包方案,另外 360 加固也是一種不錯的選擇,效率都比使用 gradle 來的高。但如果需要替換 Apk 中的圖片、字符串、應(yīng)用的 applicationId 、給指定渠道的包使用指定的簽名,那么只能乖乖使用 gradle 打包了,慢你也得忍著~

之前剛開始調(diào)研的時(shí)候,發(fā)現(xiàn) Github 上有個(gè) ApkCustomizationTool 項(xiàng)目,它是通過對 Apk 解包,替換圖片、字符串,然后重新簽名,不過這畢竟是事后諸葛亮,控制在打包的源頭總是畢竟好的,有興趣的同學(xué)可以去研究下。

不知大家有沒有這種感受,每次發(fā)版上傳渠道的時(shí)候想死有沒有?o(╯□╰)o

總結(jié)

以上就是自己在使用 Gradle 實(shí)現(xiàn) Android 多渠道打包時(shí)碰到的問題, Android 官方關(guān)于使用 Gradle 的文檔已經(jīng)很詳細(xì)了,自己總結(jié)的只是一點(diǎn)皮毛,有時(shí)間要去自習(xí)研讀下。

責(zé)任編輯:龐桂玉 來源: 安卓巴士Android開發(fā)者門戶
相關(guān)推薦

2022-09-02 15:35:37

Android實(shí)踐

2019-05-21 14:22:28

Android渠道統(tǒng)計(jì)打包

2022-05-12 16:28:42

數(shù)據(jù)

2012-05-24 14:26:25

CNZZ統(tǒng)計(jì)移動開發(fā)

2009-08-24 15:24:34

IT運(yùn)維管理ITIL運(yùn)維流程摩卡軟件

2017-02-15 12:59:23

Android渠道打包技術(shù)小結(jié)

2009-10-20 11:22:10

Linux備份方式

2022-02-23 16:56:43

Python多渠道歸因模型數(shù)據(jù)驅(qū)動

2014-07-07 17:13:49

SAP華為

2019-01-28 13:55:58

2023-04-27 07:30:48

算法技術(shù)精準(zhǔn)投放

2019-11-12 11:07:04

Informatica

2013-04-23 13:23:56

Aspect聯(lián)絡(luò)中心呼叫中心

2025-03-18 12:23:25

2017-04-28 10:46:50

營銷

2014-08-26 17:12:31

聯(lián)絡(luò)中心Aspect

2017-04-24 13:47:30

互聯(lián)網(wǎng)

2018-05-10 15:54:39

2015-09-07 16:58:51

億瑪大數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

秋霞国产精品| 天堂av网在线| 你懂的国产精品| 欧美大片一区二区| www黄色日本| 丁香在线视频| 国产高清亚洲一区| 日本久久久久久久久| 国产大屁股喷水视频在线观看| 日韩亚洲精品在线观看| 狠狠躁夜夜躁人人爽天天天天97| 免费国产一区| 北条麻妃一二三区| 每日更新成人在线视频| 欧美猛男性生活免费| 国产免费看av| 久久综合给合| 在线看国产一区二区| 成人污网站在线观看| 超碰免费在线观看| 成人免费三级在线| 91老司机在线| 国产第一页在线观看| 欧美三级网页| www.日韩不卡电影av| 37p粉嫩大胆色噜噜噜| 国产精品视频首页| 欧美综合色免费| 日韩免费视频播放| av片在线观看网站| 国产精品久久福利| 欧美一进一出视频| 五十路在线视频| 国产高清精品久久久久| 国产精品美女久久久久久免费| 日韩手机在线观看| 欧美高清日韩| 久久精品久久久久| 亚洲 欧美 国产 另类| 久久91精品| 精品视频在线导航| 亚洲天堂美女视频| japanese色系久久精品| 日韩一二三区不卡| 三年中文在线观看免费大全中国| 成人黄色毛片| 欧美日韩综合在线免费观看| 99福利在线观看| 中文字幕在线官网| 欧美性极品xxxx做受| 男人日女人视频网站| 久久电影网站| 一区二区在线免费观看| 国产乱子伦精品视频| 成人影院在线看| 亚洲另类一区二区| 成人在线观看毛片| 久久免费电影| 天天色综合天天| 播放灌醉水嫩大学生国内精品| 成年男女免费视频网站不卡| 亚洲午夜国产一区99re久久| 无码熟妇人妻av在线电影| 四虎影视成人| 天天操天天色综合| 久久美女福利视频| 国精产品一区一区三区四川| 欧美午夜精品久久久久久孕妇| 三级在线视频观看| 久久伊人国产| 日韩午夜在线观看| www.17c.com喷水少妇| 久久资源综合| 亚洲男人第一网站| аⅴ天堂中文在线网| 久久在线视频| 久久国产天堂福利天堂| 国产一级片播放| 美女诱惑一区| 国产精品爽爽ⅴa在线观看| 在线视频1卡二卡三卡| 国产剧情在线观看一区二区| 国产不卡一区二区在线观看| 日韩电影网址| 国产精品久久久久aaaa| 久久成人福利视频| 二区三区不卡| 欧美高清视频在线高清观看mv色露露十八 | 日韩女优人人人人射在线视频| 少妇又紧又色又爽又刺激视频 | 一本大道久久a久久精品综合| 91在线视频观看免费| 国产精品久久久久久久久久辛辛 | 成人免费毛片xxx| 亚洲图片在线| 国产精品久久精品| 精品人妻久久久久一区二区三区| 99这里只有精品| 亚洲国产日韩欧美| av影视在线| 欧美午夜电影网| 成人啪啪18免费游戏链接| 久久av综合| 欧美福利视频在线| 91视频在线视频| 成人动漫一区二区在线| 色综合视频二区偷拍在线| 国内在线视频| 在线看日本不卡| 97精品人妻一区二区三区蜜桃| 欧美日中文字幕| 性欧美xxxx交| 国产喷水福利在线视频| 91视频国产观看| 国产欧美综合一区| 精品123区| 亚洲国产精品久久久久| 一本在线免费视频| 销魂美女一区二区三区视频在线| 91视频国产一区| 国产女人在线视频| 亚洲高清免费视频| www.五月天色| 99久久久久| 欧美综合在线观看| 蜜桃久久一区二区三区| 亚洲欧美日韩系列| 日本三级黄色网址| 国产伦一区二区三区| 国模极品一区二区三区| 一区二区三区亚洲视频| 国产亚洲精品精华液| 狠狠97人人婷婷五月| 99亚洲乱人伦aⅴ精品| 久久精品欧美视频| 亚洲天堂免费av| 日本一区二区综合亚洲| 人妻内射一区二区在线视频| 伊人久久大香线蕉av超碰| 久久视频在线直播| 国产永久免费视频| 国产精品久久久久9999吃药| 日本人视频jizz页码69| 欧洲毛片在线视频免费观看| 国产精品444| 日本私人网站在线观看| 狠狠做深爱婷婷久久综合一区 | 中文字幕成人av| 成年人黄色片视频| 女人丝袜激情亚洲| 自拍偷拍欧美一区| 亚洲黄色免费电影| 欧美视频国产视频| 999久久久免费精品国产| 国产精品女主播视频| 北岛玲日韩精品一区二区三区| 欧美性极品xxxx娇小| 91中文字幕永久在线| 国产精品五区| 日本成人看片网址| 日本肉肉一区| 色婷婷久久av| 国产女人爽到高潮a毛片| 亚洲日本在线视频观看| 在线观看一区二区三区视频| 国产一区二区中文| 99久久综合狠狠综合久久止| av丝袜在线| 亚洲精品网址在线观看| 中文字幕在线观看1| 最新久久zyz资源站| 妖精视频在线观看| 亚洲黄色在线| 秋霞在线观看一区二区三区| 国模私拍国内精品国内av| 日韩午夜在线视频| 性一交一乱一伧老太| 午夜激情久久久| xxx在线播放| 国产一区二区免费视频| www插插插无码视频网站| 亚洲精品国模| 91精品久久久久久久久| 久久www人成免费看片中文| 亚洲精品视频播放| 国产又粗又猛又爽又黄的视频一 | 日韩久久免费视频| 亚洲视频在线免费播放| 午夜伊人狠狠久久| 国产精品一二三区在线观看| 国产最新精品精品你懂的| www.xxx麻豆| 欧美一区二区性| 99超碰麻豆| 欧美亚洲大片| 欧美日韩成人免费| 大片免费播放在线视频| 欧美不卡一区二区三区四区| 国产成人无码av| 亚洲精品五月天| 波多野结衣片子| 国产电影一区在线| 不卡av免费在线| 亚洲成色精品| 制服诱惑一区| 日韩大尺度在线观看| 国产伊人精品在线| 色吧亚洲日本| 欧美日本高清一区| 1769在线观看| 亚洲奶大毛多的老太婆| 亚洲福利在线观看视频| 精品视频1区2区3区| 中国一级特黄毛片| 一区二区三区四区在线免费观看| 欧美做受xxxxxⅹ性视频| 国产成人啪免费观看软件 | 国产精品高潮久久| 98精品国产高清在线xxxx天堂| 国产一二区在线| 一本色道久久88综合亚洲精品ⅰ| 日韩性xxxx| 精品久久久三级丝袜| 国产精品久久免费| 欧美综合久久久| 欧美亚洲精品天堂| 亚洲国产一区二区视频| 一区二区三区四区五区| 国产精品国产三级国产| 久久久久久九九九九九| 91视视频在线观看入口直接观看www| www日本在线观看| 久久99国产精品久久99| 在线免费视频a| 鲁大师成人一区二区三区| 乱妇乱女熟妇熟女网站| 日韩视频二区| 2018国产在线| 一区视频在线| 国产一区二区三区小说| 欧美激情1区2区3区| 国产又粗又大又爽的视频| 99国内精品久久久久久久| 亚洲韩国在线| 久久一级电影| 亚洲欧美丝袜| 91高清一区| 影音先锋成人资源网站| 一区二区三区四区在线观看国产日韩| 日本黄色a视频| 91精品国产91久久久久久密臀| 亚洲一区bb| 久久精品亚洲欧美日韩精品中文字幕| 亚洲精品一区二区三区四区五区| 欧美综合视频| 一区二区三区不卡在线| 色天天久久综合婷婷女18| 一区二区三区四区不卡| 五月天久久久| www.一区二区.com| 亚洲日本激情| 农村妇女精品一二区| 日本伊人色综合网| 8x8x成人免费视频| 国产福利精品一区二区| 少妇激情一区二区三区视频| 91麻豆123| 人妻无码一区二区三区免费| 亚洲人妖av一区二区| 久草视频免费播放| 欧美日韩国产在线看| 国产尤物在线视频| 精品视频一区二区不卡| 成人h动漫精品一区二区无码| 精品成人在线观看| 免费黄色片在线观看| 日韩在线免费观看视频| 呦呦在线视频| 欧美一二三视频| 国产精品99久久久久久董美香| 91青青草免费在线看| 开心激情综合| 亚洲人成人77777线观看| 911久久香蕉国产线看观看| 日韩 欧美 视频| 日韩精品欧美精品| 日本黄色www| wwww国产精品欧美| 久久国产波多野结衣| 亚洲成人在线网站| 中国一级片黄色一级片黄| 精品欧美乱码久久久久久1区2区| 天堂а√在线8种子蜜桃视频| 色偷偷亚洲男人天堂| 黄色羞羞视频在线观看| 国产成人中文字幕| 999久久精品| 亚洲三区四区| 日韩香蕉视频| 日本网站在线看| 国产三级一区二区三区| 青春草免费视频| 欧美日韩一区二区三区高清| 日韩中文字幕观看| www.亚洲天堂| 搜成人激情视频| 国产手机精品在线| 一区二区电影| 欧美三级午夜理伦三级富婆| 91亚洲大成网污www| 久久久久久久久久久久久女过产乱| 一本色道久久综合亚洲91 | 国产91丝袜在线播放| 国产欧美一区二区三区在线观看视频| 亚洲午夜影视影院在线观看| 国产又粗又大又黄| 永久555www成人免费| 性国裸体高清亚洲| 国产精品一区二区三区不卡| 天天色天天射综合网| 日本xxxx黄色| 久久久蜜桃精品| 青青草av在线播放| 亚洲成人av中文字幕| 牛牛电影国产一区二区| 国产在线视频一区| 日韩国产欧美| 韩国中文字幕av| 久久久久久综合| 丰满少妇乱子伦精品看片| 精品黑人一区二区三区久久| 麻豆网在线观看| 国产精品永久免费在线| 欧洲杯什么时候开赛| 91蝌蚪视频在线观看| 26uuu国产日韩综合| 四虎精品永久在线| 亚洲精品aⅴ中文字幕乱码| www在线观看黄色| 精品一区二区三区视频日产| 亚洲精选成人| 日本一卡二卡在线| 欧美色xxxx| 天堂а√在线8种子蜜桃视频| 91精品国产91久久久久久吃药| youjizzjizz亚洲| 青春草国产视频| 成人午夜免费电影| 五月天婷婷丁香| 亚洲精品在线电影| 蜜桃视频m3u8在线观看| 九九九九精品| 欧美亚洲三区| 熟女高潮一区二区三区| 欧洲人成人精品| 91sp网站在线观看入口| 国产日韩欧美中文在线播放| 天天av综合| 亚洲一级Av无码毛片久久精品| 亚洲va中文字幕| 欧美视频综合| 国产伦精品免费视频| 亚洲乱码电影| 美女久久久久久久久| 欧美性生交xxxxxdddd| 成人在线二区| 91在线观看免费高清完整版在线观看| 国产精品99免费看| 丰满少妇高潮一区二区| 欧美亚洲丝袜传媒另类| 国产成人l区| 国产一区喷水| 热久久久久久久| 久久免费黄色网址| 亚洲欧美日韩精品久久| 国产精品传媒麻豆hd| 91黄色在线看| 久久久久久久性| 国产免费av电影| 8050国产精品久久久久久| 欧美美女一区| 美女伦理水蜜桃4| 色噜噜狠狠成人中文综合| 99热国产在线中文| 久久久com| 久久超碰97中文字幕| 国产乡下妇女做爰| 国产一区二区三区在线观看视频| 韩国三级成人在线| 国产成人精品视频免费看| 亚洲欧洲日韩一区二区三区| 欧美自拍偷拍一区二区| 国产精品直播网红| 亚洲激情专区| 国产精品一区二区亚洲| 亚洲第一福利网站| 亚洲老司机网| 成人免费无码av| 亚洲一区在线视频| 波多野结衣在线影院|