Gradle 打包

參考資料:
http://gold.xitu.io/post/580c85768ac247005b5472f9
http://www.reibang.com/p/9df3c3b6067a
http://mp.weixin.qq.com/s?__biz=MzA4NTQwNDcyMA==&mid=2650661971&idx=1&sn=3fb69537bbc5fbb14d152ba6381c3b83#rd
https://segmentfault.com/a/1190000004229002
http://wiki.jikexueyuan.com/project/deep-android-gradle/

dex 打包
http://blog.csdn.net/mynameishuangshuai/article/details/52703029

For Android 準備的基礎

構建工具
Gradle是一種構建工具肄梨,Android Studio默認采用Gradle來構建灸拍,Eclipse中使用的ant來構建Android;
構建工具指的是對項目進行編譯、運行鼻吮、簽名像街、打包、依賴管理等一系列功能的合集抖僵,另外一個非常重要的功能是管理依賴(第三方庫管理)鲤看;

Google 開發(fā)了Andriod Studio 插件 Android Gradle Plugin 用來構建 Android App;

新增內(nèi)容(基礎知識)##

Gradle是一個框架耍群,定義了自己一些規(guī)則义桂,我們需要遵循她的設計規(guī)則:

  1. 在Gradle中,每一個待編譯的工程都叫做一個Project世吨,如:Android Project目錄下的各種lib引入庫澡刹,都是一個Project。
  2. 在每個Project在構建時耘婚,又包含了一系列Task罢浇,比如:Android APK的編譯包含:java源代碼編譯Task、Android資源編譯Task沐祷、簽名Task等等嚷闭;
  3. 一個Project有多少個task,由其編譯腳本指定的插件決定赖临,什么是插件胞锰?插件就是用來定義Task,并執(zhí)行這些Task的東西兢榨;

Gradle負責定義流程和規(guī)則嗅榕,而具體的編譯工作則是通過插件的方式來完成,
如:編譯Java的有java插件吵聪,編譯Android lib 的有Android lib 的插件凌那;

總之:Gradle中每一個待編譯的工程,都是一個Project吟逝,而Project的編譯的工作帽蝶,是由其定義的一個一個Task來定義與執(zhí)行的;

在Android工程中块攒,每一個Library励稳、每一個App都是單獨的Project佃乘,同時在每一個Project的根目錄下,都有一個build.gradle文件驹尼,表示Project的編譯腳本趣避;

settings.gradle文件
在Android工程中,我們一般都有多個Project扶欣,如上鹅巍,每個project都有一個build.gradle文件與此對應;在工程的根目錄料祠,有一個build.gradle文件骆捧,她負責配置其他子Project的,與settings.gradle文件髓绽,settings.gradle文件指出該工程包含多少個 子 Project敛苇;

image.png

有了這2個文件,在項目的根目錄進行編譯時顺呕,可以把項目中的所有project都編譯好枫攀;

Gradle 相關命令

  1. gradle projects 查看工程信息;
  2. gradle tasks 查看任務信息株茶;
  3. gradle task-name 執(zhí)行任務来涨,如:gralde clean,gradle properties

task 的依賴關系
task和task之間可能有關系启盛,如:某task的執(zhí)行蹦掐,需要其他task先執(zhí)行完成,這就是依賴關系僵闯;如:assemble task就依賴其他task先執(zhí)行卧抗,assemble 才能執(zhí)行;
可以指定 assemble 依賴于 自己定義的 task鳖粟,這樣社裆,自定義的task會優(yōu)先執(zhí)行;

gradle工作流程

  1. 初始化階段:對于多project build而言向图,就是執(zhí)行 settings.gradle;
  2. Configuration階段:解析每個project中的build.gradle文件泳秀,在這2個階段之間,可加入一些定制化的hook榄攀;
  3. 預執(zhí)行階段:現(xiàn)整個 build的 project及內(nèi)部的task關系已確定晶默;
  4. 執(zhí)行任務階段;

gradle編程模型
Gradle執(zhí)行的時候航攒,會把腳本轉化成Java對象,Gradle主要3種對象趴梢,并與三種不同的腳本文件對應:

  1. Gradle對象:執(zhí)行gradle xxx漠畜,gradle會從默認配置腳本中構造出一個Gradle對象币他,整個執(zhí)行過程中,只有這么一個對象憔狞,類型是Gradle蝴悉;
  2. Project對象:由build.gralde轉;
  3. Settings對象:settings.gradle轉瘾敢;

Project對象
Project包含若干個Tasks拍冠,Project對應具體工程,需要為Project加載所需要的插件簇抵,如:為java工程加入Java插件庆杜;

  • 加載插件 :調(diào)用apply方法, https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html
    apply plugin: 'com.android.library'
    apply plugin: 'com.android.application'
    Groovy支持函數(shù)調(diào)用時碟摆,通過 參數(shù)名1:參數(shù)值1,晃财,參數(shù)名2:參數(shù)值2來傳遞參數(shù);
    // 加載自定義的插件(這里為一個工具文件)
    apply from: rootProject.getRootDir().getAbsolutePath() + "/utils.gradle"
  • 設置屬性
    gradle可能包含不止一個build.gradle文件典蜕,考慮在多個腳本中設置屬性:
    gradle提供名為 extra property的方法断盛,表示額外屬性,在第一次定義該屬性時需通過ext前綴來標示他是一個額外的屬性愉舔,后面的存在钢猛,就不需要ext前綴了,ext屬性支持Project和Gradle對象轩缤,意思是為Project和Gradle對象設置ext屬性命迈;
 ext {
     local = 'Hello groovy'
 }
 task printProperties {
     println local        // Local extra property
     if (project.hasProperty('cmd')) {
         println cmd        // Command line property
     }
}

如果在 utils.gradle 中定義了一些函數(shù),然后想在其他 build.gradle 中調(diào)用這些函數(shù)典奉。那該怎么做呢躺翻?

[utils.gradle]
//utils.gradle 中定義了一個獲取 AndroidManifests.xml versionName 的函數(shù)
def getVersionNameAdvanced(){
     // 下面這行代碼中的 project 是誰?
      def xmlFile = project.file("AndroidManifest.xml")
      def rootManifest = new XmlSlurper().parse(xmlFile)
      return rootManifest['@android:versionName']
}
//現(xiàn)在卫玖,想把這個 API 輸出到各個 Project公你。由于這個 utils.gradle 會被每一個 Project Apply,所以
//我可以把 getVersionNameAdvanced 定義成一個 closure假瞬,然后賦值到一個外部屬性
// 下面的 ext 是誰的 ext陕靠?
ext{ //此段花括號中代碼是閉包
    //除了 ext.xxx=value 這種定義方法外,還可以使用 ext{}這種書寫方法脱茉。
    //ext{}不是 ext(Closure)對應的函數(shù)調(diào)用剪芥。但是 ext{}中的{}確實是閉包。
    getVersionNameAdvanced = this.&getVersionNameAdvanced
}

問題

  1. project是誰琴许?
    當一個project apply 一個gradle文件時税肪,這個gradle文件會轉化成一個script對象;
    script中有一個delegate對象,這個delegate益兄,默認加載(即調(diào)用apply)它的project對象锻梳;
    在 apply函數(shù)中,除了 from參數(shù)净捅,還有個to參數(shù)疑枯,通過to參數(shù),可改變delegate對象為其他蛔六;
    delegate就是當在script中荆永,操作一些不是script自己定義的變量,或者函數(shù)時国章,gradle會到script的delegate對象中去找具钥,看有沒有定義這些變量or函數(shù);
    ==》這樣project就是加載utils.gradle的Project捉腥;
  2. ext是誰的ext氓拼?
    ==》 project對應的ext了;此處為 Project 添加了一些 closure抵碟。那么桃漾,在 Project 中
    就可以調(diào)用 getVersionNameAdvanced 函數(shù)了

在Java和Groovy中:可能會把常用的函數(shù)放到一個輔助類中,通過import他們拟逮,并調(diào)用撬统;
但在Gradle中,更正規(guī)的方式在 xxx.gradle中定義插件敦迄,然后通過Task的方式來完成工作恋追;

Task介紹
task是Gradle中的一種數(shù)據(jù)類型,表示一些要執(zhí)行的工作罚屋,不同的插件可添加不同task苦囱,每一個task需要和一個project關聯(lián);
Task 的 API 文檔位于 https://docs.gradle.org/current/dsl/org.gradle.api.Task.html

[build.gradle]
// Task 是和Project關聯(lián)的脾猛,所以撕彤,需要利用Project的task函數(shù)來創(chuàng)建一個Task
task myTask  // 新建task名字
task myTask {}  // 閉包
task myType << { task action }  // << 符號是 doLast縮寫
task myTask(type:SomeType)
task myTask(type:SomeType) { }

上面都用到了Project的一個函數(shù),task猛拴,注意:

  1. 一個Task包含若干action羹铅,所以 Task有doFirst和doLast二個函數(shù),用于添加需要最先執(zhí)行的Action和最后需要執(zhí)行的Action愉昆,action是一個閉包职员;
    2.Task創(chuàng)建的時候可指定Type,通過 type:名字表達跛溉,就是告訴gradle焊切,這個新建的Task對象會從哪個基類Task派生扮授,如:Copy是Gradle中的一個類,當 task myTask(type:Copy)的時候蛛蒙,創(chuàng)建的Task是一個Copy Task糙箍;
    3.當使用task myTask {XXX}的時候,花括號是一個閉包牵祟,這會導致gradle在創(chuàng)建此task之后,返回給用戶之前抖格,會先執(zhí)行了 閉包內(nèi)容诺苹;
    4.當使用task myTask << {XXX}的時候,創(chuàng)建task對象雹拄,并把closure作為一個action加到此task的action隊列中收奔,并且告訴他“最后才執(zhí)行這個closure”;

Script Block
gradle文件中包含一些 Script Block滓玖,她的作用是讓我們來配置相關信息的坪哄,不同的SB有不同的配置;
如:

buildscript {   // 這是一個Script Block
    repositories {
        jcenter()
    }

script block

每個SB后面都需要跟一個花括號势篡,閉包翩肌;
https://docs.gradle.org/current/javadoc/ ,可輸入SB名字禁悠,進行查找念祭;
解釋幾個SB:

  1. subprojects:它會遍歷 工程 中的 每個子 Project,在其closure中碍侦,默認參數(shù)是子project對應的Project對象粱坤,由于其他SB都在subprojects中,所以相當于對每個Project都配置了一些信息瓷产;
  2. buildscript::它的 closure 是在一個類型為 ScriptHandler 的對象上執(zhí)行的站玄。主意用來所依賴的 classpa
    th 等信息。通過查看 ScriptHandler API 可知濒旦,在 buildscript SB 中株旷,你可以調(diào)用 ScriptHandler 提供
    的 repositories(Closure )、dependencies(Closure)函數(shù)疤估。這也是為什么 repositories 和 dependencies
    兩個 SB 為什么要放在 buildscript 的花括號中的原因灾常。這就是所謂的行話,得知道規(guī)矩铃拇。不知道
    規(guī)矩你就亂了钞瀑。記不住規(guī)矩,又不知道查 SDK慷荔,那么就徹底抓瞎雕什,只能到網(wǎng)上到處找答案了!
buildscript

Android 自己定義了好多 ScriptBlock。Android 定義的 DSL 參考文檔在
https://developer.android.com/tools/building/plugin-for-gradle.html








其他一些:##


Gradle Wrapper
參考:
http://mp.weixin.qq.com/s?__biz=MzA4NTQwNDcyMA==&mid=2650661971&idx=1&sn=3fb69537bbc5fbb14d152ba6381c3b83#rd
我們可以在項目的根目錄贷岸,輸入 gradlew -v 可查看 gradle 版本壹士;
gradlew 為 gradle wapper 的縮寫

注意:如果沒有配置 全局的 gralde 環(huán)境變量,在Android studio 的 命令框中偿警,需要輸入./ 再加 graldew來使用相關命令躏救,如下:

常用命令
./gradlew -v 查看版本號 (win 下 輸入 gradlew -v)
./gradlew clean 清除/app目錄下的build文件夾
./gradlew build 檢查依賴并編譯打包
./gradlew build 命令把 debug、release 環(huán)境的包都打出來螟蒸;
./gradlew assembleDebug 編譯并打Debug包
./gradlew assembleRelease 編譯并打Release的包

基本的Gradle
構建Android程序盒使,需要構建腳本, gradle默認提供了一些配置與默認值七嫌,簡化了我們的構建工作少办;

Project與Tasks
Gradle中有2個非常重要的對象,Project 和 Tasks诵原;
注意: Android Studio 中的project和Gradle中的project不是同一個概念英妓。
這里的project指的是 gradle中的project;
每個project有至少一個tasks绍赛,每個build.gradle文件代表一個project蔓纠,tasks在build.gradle中定義,一個tasks包含了多個動作惹资,然后按順序一個一個執(zhí)行贺纲,類似java中的方法;

構建生命周期
一旦一個tasks被執(zhí)行褪测,后面將不再執(zhí)行猴誊,不包含依賴的tasks總是優(yōu)先執(zhí)行,一個構建會經(jīng)歷以下3個階段:

  1. 初始化階段:project實例在這兒創(chuàng)建侮措,如果有多個模塊懈叹,即有多個build.gradle文件,多個project將會被創(chuàng)建分扎;
  2. 配置階段:在該階段澄成,build.gradle腳本將會執(zhí)行,為每個project創(chuàng)建和配置所有的tasks畏吓;
  3. 執(zhí)行階段:這一階段墨状,gradle會決定哪一個tasks會被執(zhí)行,哪一個tasks會被執(zhí)行完全依賴開始構建時傳入的參數(shù)和當前所在的文件夾位置有關

build.gradle的配置文件
基于gradle構建的項目菲饼,至少有一個 build.gradle文件肾砂,下面的是Android的build.gradle:
這個 就是 實際構建開始的地方

// 定義全局的相關屬性,使用 jcenter作為倉庫
buildscript {
    repositories {
        jcenter()
    }
   // 定義構建過程
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.3'
    }
}
// 用來定義各個模塊的默認屬性宏悦,在所有模塊中的可見
allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

構建腳本定義了Android構建工具镐确,還有Android的依賴庫

// 每個app都需要這個插件包吝,Android plugin 提供了所有需要去構建和測試的應用
apply plugin: 'com.android.application'    

// 表示的是一個 依賴庫
apply plugin: 'com.android.library'

基本的Tasks
android插件依賴于Java插件,java依賴于base插件源葫,
base插件有基本的tasks生命周期和一些通用的屬性诗越;
base插件定義了例如assemble和clean任務,Java插件定義了check和build任務息堂,這兩個任務不在base插件中定義嚷狞。

這些tasks的約定含義:

assemble: 集合所有的output
clean: 清除所有的output
check: 執(zhí)行所有的checks檢查,通常是unit測試和instrumentation測試
build: 執(zhí)行所有的assemble和check
Java插件同時也添加了source sets的概念储矩。

Android Tasks
Android插件繼承了基本tasks感耙,并實現(xiàn)了自己的行為:

  1. assemble 針對每個版本創(chuàng)建一個apk
  2. clean 刪除所有的構建任務,包含apk文件
  3. check 執(zhí)行Lint檢查并且能夠在Lint檢測到錯誤后停止執(zhí)行腳本
  4. build 執(zhí)行assemble和check

默認情況下assemble tasks定義了assembleDebug和assembleRelease持隧,當然你還可以定義更多構建版本。除了這些tasks,android 插件也提供了一些新的tasks:

  1. connectedCheck 在測試機上執(zhí)行所有測試任務
  2. deviceCheck 執(zhí)行所有的測試在遠程設備上
  3. installDebug和installRelease 在設備上安裝一個特殊的版本
  4. 所有的install task對應有uninstall 任務

Android Studio中的tasks

![A$PZHC}F`6YTR30Q~JH]{NM.png](http://upload-images.jianshu.io/upload_images/2003670-088f7832be095f82.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

依賴管理
gradle自動為android程序添加了倉庫逃片,默認是jcenter屡拨,我們添加的某個第三方jar,稱為一個依賴褥实,比如:support v7包呀狼,gson 等;
一個依賴需要定義3個元素:group,name和version损离,添加依賴使用的是 groovy 語法哥艇,如下:

// 依賴
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'
}

依賴的配置
有些時候,你可能需要和sdk協(xié)調(diào)工作僻澎。為了能順利編譯你的代碼貌踏,你需要添加SDK到你的編譯環(huán)境。你不需要將sdk包含在你的APK中窟勃,因為它早已經(jīng)存在于設備中祖乳,所以配置來啦,我們會有5個不同的配置:

  1. compile
  2. apk
  3. provided
  4. testCompile
  5. androidTestCompile

compile 默認秉氧,其含義是包含所有的依賴包眷昆,即在APK里,compile的依賴會存在汁咏。
apk 的意思是apk中存在亚斋,但是不會加入編譯中,這個貌似用的比較少攘滩。
provided 的意思是提供編譯支持帅刊,但是不會寫入apk。
testCompile 和androidTestCompile 會添加額外的library支持針對測試轰驳。

這些配置將會被用在測試相關的tasks中厚掷,這會對添加測試框架例如JUnit或者Espresso非常有用弟灼,因為你只是想讓這些框架們能夠出現(xiàn)在測試apk中,而不是生產(chǎn)apk中冒黑。

構建版本
一個app如果有多個版本田绑,比如 release,debug抡爹,不同渠道不同版本等掩驱,使用 gralde 可以方便管理這些;

  1. Build types冬竟;
  2. Product flavors欧穴;
  3. Build variants
  4. Signing configurations;

buildTypes
gradle 的android插件中,一個版本構建意味著一個app或者依賴庫如何被構建泵殴,每個構建版本可能有一些特殊面涮帘,比如 是否 debug,application id笑诅,應用名稱调缨,哪些資源是否需要刪掉等,可以定義一個構建版本 buildTypes 方法吆你,如:

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

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

product flavors
product flavors 用來為一個app創(chuàng)建不同的版本弦叶,比如:app的付費與免費; 如果 app 需要對內(nèi)對外 完全隔離妇多,就可以使用 product flavors伤哺,

      // 多渠道打包
    productFlavors {
        // 個性化定制
        xiaomi {
            applicationId "groovy.better.com.groovytest.xiaomi"
            minSdkVersion 11
        }
        huawei {
            applicationId "groovy.better.com.groovytest.huawei"
            minSdkVersion 14
        }
        baidu {
            applicationId "groovy.better.com.groovytest.baidu"
            minSdkVersion 16
        }
    }

    // apk名稱修改
    applicationVariants.all { variant ->
        if (variant.buildType.name.equals('release')) {
            variant.outputs.each { output ->
                def appName = 'demo'
                def oldFile = output.outputFile
                def buildName
                def releaseApkName

                variant.productFlavors.each { product ->
                    buildName = product.name
                }

                releaseApkName = appName + getVersionByMainfest() + '_' + buildName + '_' + getNowTime() + '.apk'
                output.outputFile = new File(oldFile.parent, releaseApkName)
            }
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'
}

// ----->  自定義的方法
//獲取時間戳
def getNowTime() {
    def date = new Date()
    def now = date.format('yyyyMMddHHmm')
    return now
}

//從androidManifest.xml中獲取版本號
def getVersionByMainfest() {
    def parser = new com.android.builder.core.DefaultManifestParser()
    return parser.getVersionName(android.sourceSets.main.manifest.srcFile)
}


BuildConfig配置
BuildConfig.java文件,無法進行動態(tài)配置者祖,她是通過 module 相應的gradle文件生成的立莉,可通過 module的 gralde文件,進行一些全局的開關控制:

添加配置代碼:

buildTypes {

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

            buildConfigField 'String', 'TEST_NAME', '"test_debug"' // ildConfigField
            resValue "string", "test_name", "test_debug"   //resValue
        }

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

            buildConfigField 'String', 'TEST_NAME', '"test_release"' // ildConfigField
            resValue "string", "test_name", "test_release"   //resValue
        }
    }

生成的 BuildConfig.java 文件:

Paste_Image.png
  1. buildConfigField: 會根據(jù)gradle的配置咸包,在原來默認的BuildConfig.java基礎上桃序,動態(tài)添加一個指定數(shù)據(jù)類型的value。
    buildConfigField 一共有3個參數(shù)烂瘫,具體參考上面的參考資料媒熊;
  2. resValue: buildConfigField主要改變了java常量,Gradle組件提供了resValue字段坟比,用于動態(tài)生成value資源芦鳍,在程序中也可以訪問到,其中生成的目標存在generated.xml中葛账,使用的規(guī)則與buildConfigField 類似柠衅,即類型+常量名+常量值,如上代碼 resValue 部分籍琳,生成generated.xml截圖:
Paste_Image.png

** 使用占位符動態(tài)配置 清單文件中 :meta-data **
請注意:占位符須與 gradle中的 名稱一致;
清單文件代碼:

Paste_Image.png

配置不同渠道上的值:

Paste_Image.png

構建的生命周期
初始化階段:gralde尋找 settings.gradle文件,如果項目有多個模塊狈醉,settings.gralde文件定義了模塊的位置,如果這些子目錄包含其自己的 build.gradle文件势誊,gradle將運行其,并將它們合并到構建任務中谣蠢;

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末粟耻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子眉踱,更是在濱河造成了極大的恐慌挤忙,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谈喳,死亡現(xiàn)場離奇詭異册烈,居然都是意外死亡,警方通過查閱死者的電腦和手機婿禽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門茄厘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谈宛,你說我怎么就攤上這事√ナ穑” “怎么了吆录?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長琼牧。 經(jīng)常有香客問我恢筝,道長,這世上最難降的妖魔是什么巨坊? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任撬槽,我火速辦了婚禮,結果婚禮上趾撵,老公的妹妹穿的比我還像新娘侄柔。我一直安慰自己,他們只是感情好占调,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布暂题。 她就那樣靜靜地躺著,像睡著了一般究珊。 火紅的嫁衣襯著肌膚如雪薪者。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天剿涮,我揣著相機與錄音言津,去河邊找鬼攻人。 笑死,一個胖子當著我的面吹牛悬槽,可吹牛的內(nèi)容都是我干的怀吻。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼陷谱,長吁一口氣:“原來是場噩夢啊……” “哼烙博!你這毒婦竟也來了?” 一聲冷哼從身側響起烟逊,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤渣窜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后宪躯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乔宿,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年访雪,在試婚紗的時候發(fā)現(xiàn)自己被綠了详瑞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡臣缀,死狀恐怖坝橡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情精置,我是刑警寧澤计寇,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站脂倦,受9級特大地震影響番宁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赖阻,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一蝶押、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧火欧,春花似錦棋电、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至衅檀,卻和暖如春招刨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哀军。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工沉眶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留打却,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓谎倔,卻偏偏與公主長得像柳击,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子片习,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

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