Gradle for Android(四) 創(chuàng)建構(gòu)建變體

開發(fā)應(yīng)用時(shí)抹估, 通常會(huì)有幾個(gè)不同的版本溉潭。最常見的是有一個(gè)測(cè)試用的臨時(shí)版本和一個(gè)生產(chǎn)版本。這些版本通常有不同的設(shè)置揍瑟,比如不同的URL地址等白翻。除此之外,你可能有一個(gè)免費(fèi)版和一個(gè)包含更多功能的付費(fèi)版绢片。這種情況下滤馍,你已經(jīng)有了四個(gè)不同的版本:臨時(shí)免費(fèi)版,臨時(shí)付費(fèi)版底循,生產(chǎn)免費(fèi)版巢株,生產(chǎn)付費(fèi)版。不同的版本有不同的配置是非常復(fù)雜的事情此叠。

Gradle有一些規(guī)則和可擴(kuò)展的概念來解決這一問題纯续。我們已經(jīng)提及Android Studio為每個(gè)新建工程創(chuàng)建的debugrelease兩種build types。這是另一個(gè)稱為product flavors的概念灭袁,它可以管理一個(gè)app或者library的不同版本猬错。build typesproduct flavors是結(jié)合起來使用的,這就使管理免費(fèi)和付費(fèi)版的臨時(shí)和生產(chǎn)應(yīng)用變得簡單茸歧。build typeproduct flavor的結(jié)合稱為build variant(構(gòu)建變體)倦炒。

本章我們首先學(xué)習(xí)build types,看看它如何使開發(fā)者的工作更加簡單软瞎。接下來我們會(huì)討論build typesproduct flavors的不同以及如何使用它們逢唤。我們還會(huì)學(xué)習(xí)發(fā)布app所必需的signing configurations(簽名配置)拉讯,以及如何為每個(gè)構(gòu)建變體設(shè)置不同的簽名配置。

本章我們學(xué)習(xí)如下內(nèi)容:

  • build types
  • product flavors
  • build variants
  • signing configurations

Build types(構(gòu)建類型)

在Gradle Android插件中鳖藕,構(gòu)建類型用來定義一個(gè)app或者library應(yīng)該如何構(gòu)建魔慷。每個(gè)構(gòu)建類型可以指定是否包含調(diào)試符號(hào),applicationId是什么著恩,無用的資源是否應(yīng)該移除等等院尔。你可以使用buildTypes塊來定義構(gòu)建類型。下面是Android Studio創(chuàng)建的標(biāo)準(zhǔn)buildTypes塊:

android {
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

新模塊默認(rèn)的build.gradle文件配置了一個(gè)名為release的構(gòu)建類型喉誊。它只是禁用了移除無用的資源(通過設(shè)置minifyEnabledfalse)邀摆,并且定義了ProGuard配置文件的位置。這是為了讓開發(fā)人員可以直接使用ProGuard進(jìn)行生產(chǎn)構(gòu)建伍茄。

release構(gòu)建類型不是唯一一個(gè)自動(dòng)為你的工程創(chuàng)建好的構(gòu)建類型栋盹。每個(gè)模塊默認(rèn)還有一個(gè)debug構(gòu)建類型。它設(shè)置有合理的默認(rèn)值敷矫,你也可以在buildTypes塊中配置它例获,覆寫屬性值。

debug構(gòu)建類型擁有它自己的默認(rèn)設(shè)置沪饺,以使它方便調(diào)試躏敢。當(dāng)你創(chuàng)建自己的構(gòu)建類型時(shí),會(huì)有不同的默認(rèn)值整葡。比如件余,debug構(gòu)建類型的debuggable屬性設(shè)置為true,而你自己創(chuàng)建的其他類型為false

創(chuàng)建構(gòu)建類型

當(dāng)默認(rèn)設(shè)置不滿足需求時(shí)遭居,你也可以很容易地創(chuàng)建自定義構(gòu)建類型啼器。你需要做的只是在buildTypes塊中添加一個(gè)新的構(gòu)建類型的對(duì)象。下面創(chuàng)建一個(gè)staging的構(gòu)建類型:

android {
    buildTypes {
        staging {
            applicationIdSuffix ".staging"
            versionNameSuffix "-staging"
            buildConfigField "String", "API_URL","\"http://staging.example.com/api\""
        }
    }
}

staging構(gòu)建類型定義了一個(gè)新的applicationId的后綴俱萍,這樣就和debug端壳、release版本區(qū)分開來。假設(shè)其他配置使用默認(rèn)值枪蘑,這樣每個(gè)構(gòu)建類型的applicationId如下:

  • Debug:com.package
  • Release:com.package
  • Staging:com.package.staging

這意味著你可以在設(shè)備上同時(shí)安裝release版本和staging版本损谦,而不會(huì)引起沖突。staging構(gòu)建類型也有一個(gè)版本名稱的后綴岳颇,用于區(qū)分同一設(shè)備不同版本的app照捡。buildConfigField屬性定義了一個(gè)URL地址,我們?cè)诘诙乱呀?jīng)見過话侧。

在創(chuàng)建構(gòu)建類型時(shí)栗精,你不必完全自定義,你也可以從由其他構(gòu)建類型來初始化。

android {
    buildTypes {
        staging.initWith(buildTypes.debug)
        staging {
            applicationIdSuffix ".staging"
            versionNameSuffix "-staging"
            debuggable = false
        }
    }
}

initWith()方法會(huì)根據(jù)傳入的構(gòu)建類型來初始化當(dāng)前構(gòu)建類型悲立。你可以在新的構(gòu)建類型對(duì)象中覆寫屬性鹿寨,或者定義新的屬性。

Source sets(源碼集)

在你創(chuàng)建一個(gè)新構(gòu)建類型時(shí)薪夕,Gradle也會(huì)創(chuàng)建一個(gè)新的源碼集脚草。源碼集目錄默認(rèn)和構(gòu)建類型同名,但并不會(huì)自動(dòng)創(chuàng)建寥殖。你需要手動(dòng)創(chuàng)建該目錄才能為該構(gòu)建類型自定義源代碼和資源文件玩讳。

下面是標(biāo)準(zhǔn)的debugrelease構(gòu)建類型嚼贡,外加自定義的staging構(gòu)建類型的源碼集目錄結(jié)構(gòu):

app
└── src
    ├── debug
    │    ├── java
    │    │   └── com.package
    │    │         └── Constants.java
    │    ├── res
    │    │  └── layout
    │    │         └── activity_main.xml
    │    └── AndroidManifest.xml
    ├── main
    │    ├── java
    │    │    └── com.package
    │    │            └── MainActivity.java
    │    ├── res
    │    │    ├── drawable
    │    │    └── layout
    │    │            └── activity_main.xml
    │    └── AndroidManifest.xml
    ├── staging
    │    ├── java
    │    │    └── com.package
    │    │            └── Constants.java
    │    ├── res
    │    │    └── layout
    │    │            └── activity_main.xml
    │    └── AndroidManifest.xml
    └── release
         ├── java
         │     └── com.package
         │          └── Constants.java
         └── AndroidManifest.xml

這些源碼集帶來巨大的便利,比如你可以為某個(gè)構(gòu)建類型覆蓋特定屬性同诫,添加特定的代碼粤策,添加特殊的布局文件或者字符串資源等。

在你為每個(gè)構(gòu)建類型添加Java類的時(shí)候误窖,需要知道這是互斥的叮盘。這意味著如果你在staging的源碼集中添加了CustomLogic.java文件,你可以在debug或者release源碼集中添加同一個(gè)文件霹俺,但是不可以在main中添加柔吼,否則該文件會(huì)被定義兩次,從而在構(gòu)建時(shí)引發(fā)異常丙唧。

資源文件的處理方式和代碼文件不同愈魏。圖片和布局文件會(huì)覆蓋main中的同名文件,但是values目錄下的文件(比如strings.xml)不會(huì)想际。Gradle會(huì)將該構(gòu)建類型和main中的values目錄下的文件進(jìn)行合并培漏。

舉個(gè)例子,假如main中的strings.xml文件如下:

<resources>
    <string name="app_name">TypesAndFlavors</string>
    <string name="hello_world">Hello world!</string>
</resources>

staging中的strings.xml如下:

<resources>
    <string name="app_name">TypesAndFlavors STAGING</string>
</resources>

合并后的strings.xml文件為:

<resources>
    <string name="app_name">TypesAndFlavors STAGING</string>
    <string name="hello_world">Hello world!</string>
</resources>

以上規(guī)則同樣適用于manifest文件胡本。當(dāng)你為一個(gè)構(gòu)建類型創(chuàng)建manifest文件時(shí)牌柄,你不必從main中將整個(gè)manifest文件拷貝過來,你只需要添加你需要的標(biāo)簽就可以了侧甫。Android插件會(huì)將它們合并到一起珊佣。

本章的后續(xù)內(nèi)容我們會(huì)詳細(xì)討論文件合并。

Product flavors

構(gòu)建類型用來為同一個(gè)app或者library配置不同的構(gòu)建披粟,與之相反咒锻,product flavors用來為同一個(gè)app創(chuàng)建不同的版本。典型的例子是一個(gè)app有一個(gè)免費(fèi)版本和一個(gè)付費(fèi)版本僻爽。另一個(gè)常見的場(chǎng)景是一個(gè)代理程序虫碉,它為幾個(gè)客戶構(gòu)建具有相同功能的應(yīng)用程序,只是品牌發(fā)生改變胸梆。一個(gè)公司制作的應(yīng)用可以被同類型的客戶重復(fù)使用敦捧,這在出租車行業(yè)和銀行領(lǐng)域是很常見的须板。改變的僅僅是顏色,logo兢卵,后臺(tái)地址习瑰。Product flavors極大簡化了創(chuàng)建基于同樣代碼的不同版本的應(yīng)用的過程。

如果你不確定自己需要新的build type還是新的product flavor秽荤,你應(yīng)該問問自己是想要為了內(nèi)部使用為應(yīng)用創(chuàng)建一個(gè)新的構(gòu)建甜奄,還是想要向Google Play發(fā)布一個(gè)新的APK。如果你想要在原有的基礎(chǔ)上創(chuàng)建一個(gè)全新的可單獨(dú)發(fā)布的應(yīng)用窃款,你應(yīng)該選擇product flavors课兄,否則,你應(yīng)該使用build types晨继。

創(chuàng)建product flavors

創(chuàng)建product flavors和創(chuàng)建build types十分相似烟阐。你可以通過添加productFlavor塊來實(shí)現(xiàn):

android {
    productFlavors {
        red {
            applicationId 'com.gradleforandroid.red'
            versionCode 3
        }
        blue {
            applicationId 'com.gradleforandroid.blue'
            minSdkVersion 14
            versionCode 4
        }
    }
}

Product flavors和build types相比有不同的屬性。這是因?yàn)閜roduct flavors是ProductFlavor類的對(duì)象紊扬,就像所有構(gòu)建腳本中的defaultConfig對(duì)象一樣蜒茄。這意味著defaultConfig和你所有的product flavors擁有同樣的屬性。

Source sets

和構(gòu)建類型一樣餐屎,product flavors也可以有自己的源碼集目錄檀葛。你只需要?jiǎng)?chuàng)建一個(gè)和flavor同名的文件夾即可。你甚至可以更進(jìn)一步腹缩,創(chuàng)建一個(gè)build type和flavor名稱結(jié)合起來的目錄屿聋。名稱結(jié)合時(shí),flavor在前庆聘,build type在后胜臊。比如,你想為release版本伙判,blueflavor的app設(shè)置一個(gè)不一樣的圖標(biāo)象对,則結(jié)合后的源碼集目錄為blueRelease。該目錄優(yōu)先級(jí)高于單獨(dú)的release目錄或者blue目錄宴抚。

復(fù)合的flavor變體

有些時(shí)候勒魔,你想要更進(jìn)一步創(chuàng)建product flavor的組合。舉個(gè)例子菇曲,客戶A和客戶B想同時(shí)擁有免費(fèi)和付費(fèi)版本的應(yīng)用冠绢,并且兩個(gè)客戶的商標(biāo)不同。創(chuàng)建四個(gè)不同的flavors會(huì)導(dǎo)致重復(fù)的設(shè)置常潮。這時(shí)弟胀,組合flvors是一個(gè)高效的方式,只需要為flavor設(shè)置不同的維度就可以了:

android {
    flavorDimensions "color", "price"

    productFlavors {
        red {
            flavorDimension "color"
        }
        blue {
            flavorDimension "color"
        }
        free {
            flavorDimension "price"
        }
        paid {
            flavorDimension "price"
        }
    }
}

一旦使用了flavorDimensions,你需要為每個(gè)flavor指定一個(gè)維度孵户,否則會(huì)產(chǎn)生編譯錯(cuò)誤萧朝。flavorDimensions定義了一組維度,它們的順序很重要夏哭。在組合兩個(gè)flavors時(shí)检柬,它們可能定義了相同的屬性或者資源。這種情況下竖配,維度的順序決定了優(yōu)先使用哪個(gè)flavor的配置何址。在上面的例子中,color維度會(huì)覆蓋price維度进胯。維度的順序也決定了構(gòu)建變體的名稱用爪。上例產(chǎn)生的構(gòu)建變體如下:

  • blueFreeDebugblueFreeRelease
  • bluePaidDebugbluePaidRelease
  • redFreeDebugredFreeRelease
  • redPaidDebugredPaidRelease

Build variants(構(gòu)建變體)

構(gòu)建變體是build types和product flavors簡單組合的結(jié)果。每當(dāng)你創(chuàng)建一個(gè)新的build type或者product flavor胁镐,一個(gè)新的變體也會(huì)被創(chuàng)建项钮。比如,你有標(biāo)準(zhǔn)的debugrelease構(gòu)建變量希停,你又創(chuàng)建了redblue兩個(gè)product flavors,這時(shí)將會(huì)創(chuàng)建下面的構(gòu)建變體:

<center>
圖1 Android Studio構(gòu)建變體窗口

圖1 Android Studio構(gòu)建變體窗口</center>

這是Android Studio的Build Variants窗口的截圖署隘。該窗口列出了所有的構(gòu)建變體宠能,并允許你切換它們。點(diǎn)擊Run按鈕將會(huì)運(yùn)行你所選擇的構(gòu)建變體磁餐。

如果你沒有product flavors违崇,構(gòu)建變體將只包含構(gòu)建類型。你不可以沒有任何構(gòu)建類型诊霹。即使你沒有定義自己的構(gòu)建類型羞延,Android插件也會(huì)為app或者library創(chuàng)建debug構(gòu)建類型。

依賴

每個(gè)構(gòu)建類型有它自己的依賴脾还。Gradle自動(dòng)為每個(gè)構(gòu)建類型創(chuàng)建一個(gè)新的依賴配置伴箩。如果你只想為debug版本添加一個(gè)日志框架,可以這樣做:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.0'
    debugCompile 'de.mindpipe.android:android-logging-log4j:1.0.3'
}

你可以用這種方式將構(gòu)建類型和依賴配置組合起來使用鄙漏,比如stagingProvided嗤谚、releaseApk等。這使你可以得到非常具體的依賴項(xiàng)怔蚌。

Product flavor也可以有自己的依賴配置巩步,定義方式同構(gòu)建類型,如freeCompile等桦踊。

然而如果你想為一個(gè)包含構(gòu)建類型和Product flavor的構(gòu)建變體添加依賴配置椅野,你需要在configurations塊中初始化這個(gè)配置。下面為freeDebug變體添加apk依賴:

configurations {
    // Initializes a placeholder for the freeDebugApk dependency configuration.
    freeDebugApk {}
}

dependencies {
    freeDebugApk fileTree(dir: 'libs', include: ['*.jar'])
}

任務(wù)

Gradle Android插件會(huì)為每個(gè)構(gòu)建變體創(chuàng)建任務(wù)。新建的Android應(yīng)用默認(rèn)有debugrelease構(gòu)建類型竟闪,所以你可以使用assembleDebugassembleRelease任務(wù)來創(chuàng)建對(duì)應(yīng)的APK离福,或者使用assemble任務(wù)同時(shí)創(chuàng)建兩個(gè)。當(dāng)你添加新的構(gòu)建類型時(shí)瘫怜,新的任務(wù)也會(huì)被創(chuàng)建术徊。一旦你添加了flavors,一系列新的任務(wù)也會(huì)被創(chuàng)建鲸湃。因?yàn)闃?gòu)建類型的任務(wù)需要和product flavor的任務(wù)結(jié)合起來赠涮。這意味著對(duì)于只有一個(gè)構(gòu)建類型和一個(gè)flavor的簡單配置,你已經(jīng)有了三個(gè)任務(wù)來構(gòu)建所有的構(gòu)建變體:

  • assembleBlue使用blue flavor的配置暗挑,同時(shí)assemble BlueReleaseBlueDebug
  • assembleDebug使用debug構(gòu)建類型的配置笋除,為每個(gè)product flavor assemble一個(gè)debug版本。
  • assembleBlueDebug結(jié)合了blue flavor和debug構(gòu)建類型的配置炸裆,并且flavor設(shè)置會(huì)覆蓋構(gòu)建類型的設(shè)置垃它。

Source sets

由一個(gè)構(gòu)建類型和一個(gè)或多個(gè)product flavor組成的構(gòu)建變體也可以有自己的源碼集目錄。比如由debug構(gòu)建類型烹看,blue flavor和free flavor組成的構(gòu)建變體国拇,源碼集目錄為src/blueFreeDebug/java/。你也可以在sourceSets塊中修改目錄位置惯殊,這在第一章出現(xiàn)過酱吝。

合并資源和manifest文件

源碼集的引入增加了構(gòu)建過程的復(fù)雜度。Gradle Android插件在打包app前需要合并main源碼集和構(gòu)建類型的源碼集土思。除此之外务热,庫工程也可能提供額外資源,它們也需要合并進(jìn)來己儒。這同樣適用于manifest文件崎岂。比如,你在debug變體的app中可能需要額外的Android權(quán)限來保存日志文件闪湾,而你并不想在main源碼集中聲明這些權(quán)限冲甘,因?yàn)檫@可能引起潛在用戶的抵觸。作為替代方案响谓,你需要在debug構(gòu)建類型的源碼集中添加manifest文件來聲明這些權(quán)限损合。

資源和manifest文件的優(yōu)先級(jí)順序如下:

Build type > Flavor > Main > Dependencies

如果一個(gè)資源同時(shí)在flavor和main的源碼集中聲明,那么flavor中的資源有更高的優(yōu)先級(jí)娘纷。這種情況下嫁审,flavor源碼集中的資源會(huì)被打包,main源碼集中的不會(huì)赖晶。庫工程中聲明的資源優(yōu)先級(jí)最低律适。

合并資源和manifest文件還有許多需要學(xué)習(xí)的地方辐烂。如果你想學(xué)習(xí)更多細(xì)節(jié),可以閱讀官方文檔:http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger

創(chuàng)建構(gòu)建變體

Gradle可以很容易地處理復(fù)雜的構(gòu)建變體捂贿。即使是創(chuàng)建并配置兩個(gè)構(gòu)建類型和兩個(gè)product flavors纠修,構(gòu)建文件依然很簡潔:

android {
    buildTypes {
        debug {
            buildConfigField "String", "API_URL","\"http://test.example.com/api\""
        }

        staging.initWith(android.buildTypes.debug)
        staging {
            buildConfigField "String", "API_URL","\"http://staging.example.com/api\""
            applicationIdSuffix ".staging"
        }
    }

    productFlavors {
        red {
            applicationId "com.gradleforandroid.red"
            resValue "color", "flavor_color", "#ff0000"
        }

        blue {
            applicationId "com.gradleforandroid.blue"
            resValue "color", "flavor_color", "#0000ff"
        }
    }
}

本例我們創(chuàng)建了四個(gè)構(gòu)建變體:blueDebug,blueStaging,redDebugredStaging

變體過濾器

你也可以在構(gòu)建中完全忽略某個(gè)變體厂僧。這樣扣草,你就可以加快assemble命令構(gòu)建所有變體的速度,并且去掉不用執(zhí)行的任務(wù)颜屠。這也可以保證在Android Studio的構(gòu)建變體窗口(見圖1)中不會(huì)出現(xiàn)這個(gè)變體的選項(xiàng)辰妙。

你可以在build.gradle文件中添加如下代碼來過濾掉構(gòu)建變體:

android.variantFilter { variant ->
    if(variant.buildType.name.equals('release')) {
        variant.getFlavors().each() { flavor ->
            if (flavor.name.equals('blue')) {
                variant.setIgnore(true);
            }
        }
    }
}

本例中,我們首先檢查變體的構(gòu)建類型是不是release甫窟,然后我們檢查該構(gòu)建類型的所有flavors密浑。getFlavors()方法返回一個(gè)flavor數(shù)組,數(shù)組的長度等于flavor的維度數(shù)粗井。比如尔破,對(duì)于blueFreeDebug變體而言,flavor數(shù)組包含bluefree兩個(gè)flavor浇衬。本例過濾掉了blueFreeReleasebluePaidRelease兩個(gè)變體懒构。運(yùn)行gradlew tasks命令,將不會(huì)看到這兩個(gè)變體相關(guān)的任務(wù)耘擂。

簽名配置

在你將應(yīng)用發(fā)布到Google Play或其他應(yīng)用市場(chǎng)之前痴脾,你需要用私鑰進(jìn)行簽名。如果你有多個(gè)不同的版本梳星,你需要為每個(gè)flavor使用不同的私鑰進(jìn)行簽名。這就需要使用簽名配置了滚朵。

android {
    signingConfigs {
        staging.initWith(signingConfigs.debug)

        release {
            storeFile file("release.keystore")
            storePassword"secretpassword"
            keyAlias "gradleforandroid"
            keyPassword "secretpassword"
        }
    }
}

本例我們創(chuàng)建了兩個(gè)不同的簽名配置冤灾。

Android插件會(huì)默認(rèn)配置一個(gè)名為debug的簽名配置,使用一個(gè)通用的公開密碼的keystore文件辕近,所以沒有必要再為debug構(gòu)建類型創(chuàng)建一個(gè)簽名配置韵吨。

staging配置調(diào)用了initWith()函數(shù),該函數(shù)通過傳入的配置初始化當(dāng)前配置移宅。這就表示staging使用了和debug相同的簽名配置归粉。

release配置使用storeFile來指定keystore文件的路徑,同時(shí)定義了key別名和用到的密碼漏峰。

就像前面提到的糠悼,在構(gòu)建文件中保存證書不是很好的設(shè)計(jì)。推薦保存在Gradle properties文件中浅乔。第七章會(huì)用一大塊去講解處理簽名配置密碼的一個(gè)任務(wù)倔喂。

在定義了簽名配置之后铝条,你需要將其應(yīng)用到構(gòu)建類型或者flavor中。構(gòu)建類型和flavor都有一個(gè)名為signingConfig的屬性:

android {
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

本例使用了構(gòu)建類型席噩。如果你想為每個(gè)flavor使用不同的證書班缰,你需要?jiǎng)?chuàng)建不同的簽名配置。你可以用同樣的方式定義它們:

android {
    productFlavors {
        blue {
            signingConfig signingConfigs.release
        }
    }
}

通過這種方式使用簽名配置會(huì)出現(xiàn)問題悼枢。為flavor設(shè)置簽名配置時(shí)埠忘,會(huì)覆蓋構(gòu)建類型的簽名配置。更好的方式是為每個(gè)構(gòu)建類型每個(gè)flavor設(shè)置不同的配置:

android {
    buildTypes {
        release {
            productFlavors.red.signingConfig signingConfigs.red
            productFlavors.blue.signingConfig signingConfigs.blue
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末馒索,一起剝皮案震驚了整個(gè)濱河市莹妒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌双揪,老刑警劉巖动羽,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異渔期,居然都是意外死亡运吓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門疯趟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拘哨,“玉大人,你說我怎么就攤上這事信峻【肭啵” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我绘搞,道長重挑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘述雾。我一直安慰自己,他們只是感情好兼丰,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布玻孟。 她就那樣靜靜地躺著,像睡著了一般鳍征。 火紅的嫁衣襯著肌膚如雪黍翎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天艳丛,我揣著相機(jī)與錄音玩敏,去河邊找鬼斗忌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛旺聚,可吹牛的內(nèi)容都是我干的织阳。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼砰粹,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼唧躲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碱璃,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤弄痹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后嵌器,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肛真,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年爽航,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蚓让。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡讥珍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出衷佃,到底是詐尸還是另有隱情趟卸,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布氏义,位于F島的核電站锄列,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏惯悠。R本人自食惡果不足惜右蕊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吮螺。 院中可真熱鬧,春花似錦帕翻、人聲如沸鸠补。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽紫岩。三九已至,卻和暖如春睬塌,著一層夾襖步出監(jiān)牢的瞬間泉蝌,已是汗流浹背歇万。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留勋陪,地道東北人贪磺。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像诅愚,于是被迫代替她去往敵國和親寒锚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 當(dāng)你在開發(fā)一個(gè)app,通常你會(huì)有幾個(gè)版本违孝。大多數(shù)情況是你需要一個(gè)開發(fā)版本刹前,用來測(cè)試app和弄清它的質(zhì)量,然后還需要...
    justCode_閱讀 421評(píng)論 0 2
  • 第四篇( 構(gòu)建變體 ) 當(dāng)你在開發(fā)一個(gè)app,通常你會(huì)有幾個(gè)版本雌桑。大多數(shù)情況是你需要一個(gè)開發(fā)版本喇喉,用來測(cè)試app和...
    一劍飛鴻閱讀 667評(píng)論 0 0
  • 轉(zhuǎn)載注明出處:http://www.reibang.com/p/5255b100930e 0. 前言 完全由個(gè)人翻...
    王三的貓阿德閱讀 2,501評(píng)論 0 4
  • 1.介紹 如果你正在查閱build.gradle文件的所有可選項(xiàng),請(qǐng)點(diǎn)擊這里進(jìn)行查閱:DSL參考 1.1新構(gòu)建系統(tǒng)...
    Chuckiefan閱讀 12,118評(píng)論 8 72
  • 當(dāng)你在開發(fā)一個(gè)app,通常你會(huì)有幾個(gè)版本校坑。大多數(shù)情況是你需要一個(gè)開發(fā)版本拣技,用來測(cè)試app和弄清它的質(zhì)量,然后還需要...
    雪殘閱讀 407評(píng)論 0 0