iOS音頻掌柜-- AVAudioSession

音頻輸出作為硬件資源晦溪,對于iOS系統(tǒng)來說是唯一的答恶,那么要如何協(xié)調(diào)和各個App之間對這個稀缺的硬件持有關(guān)系呢囊榜?

iOS給出的解決方案是"AVAudioSession" ,通過它可以實現(xiàn)對App當(dāng)前上下文音頻資源的控制亥宿,比如
插拔耳機(jī)、接電話砂沛、是否和其他音頻數(shù)據(jù)混音等烫扼。當(dāng)你遇到:

  • 是進(jìn)行錄音還是播放?
  • 當(dāng)系統(tǒng)靜音鍵按下時該如何表現(xiàn)碍庵?
  • 是從揚聲器還是從聽筒里面播放聲音映企?
  • 插拔耳機(jī)后如何表現(xiàn)悟狱?
  • 來電話/鬧鐘響了后如何表現(xiàn)?
  • 其他音頻App啟動后如何表現(xiàn)堰氓?
  • ...

這些場景的時候挤渐,就可以考慮一下“AVAudioSession”了。
??????
在很久以前(其實也是不是太久--iOS7以前)還有個AudioSession的存在双絮,其功能與AVAudioSession類似浴麻,但是在iOS7 以后就已經(jīng)被標(biāo)記為
“Not Applicable”,所以如果Google到了說AudioSession的內(nèi)容而不是用的AVAudioSession,那么就可以直接PASS了囤攀,當(dāng)然如果要兼容iOS6
就另當(dāng)別論了软免,不過現(xiàn)在QQ/微信都是要求iOS7的情況下沸毁,是否需要兼容iOS6就看老板們的意思吧磅氨。

Session默認(rèn)行為

  • 可以進(jìn)行播放,但是不能進(jìn)行錄制饮怯。
  • 當(dāng)用戶將手機(jī)上的靜音撥片撥到“靜音”狀態(tài)時蝌衔,此時如果正在播放音頻榛泛,那么播放內(nèi)容會被靜音。
  • 當(dāng)用戶按了手機(jī)的鎖屏鍵或者手機(jī)自動鎖屏了噩斟,此時如果正在播放音頻曹锨,那么播放會靜音并被暫停。
  • 如果你的App在開始播放的時候亩冬,此時QQ音樂等其他App正在播放艘希,那么其他播放器會被靜音并暫停。

默認(rèn)的行為相當(dāng)于設(shè)置了Category為“AVAudioSessionCategorySoloAmbient”

來看Demo硅急。

demo_player

通過這播放器demo可以驗證上面的默認(rèn)Session行為覆享。

AVAudioSession

AVAudioSession以一個單例實體的形式存在,通過類方法:

+ (AVAudioSession *)sharedInstance;

獲得單例营袜。

雖然系統(tǒng)會在App啟動的時候撒顿,激活這個唯一的AVAudioSession,但是最好還是在自己ViewController的viewDidLoad里面再次進(jìn)行激活:

- (BOOL)setActive:(BOOL)active 
        error:(NSError * _Nullable *)outError;

通過設(shè)置active為"YES"激活Session荚板,設(shè)置為“?NO”解除Session的激活狀態(tài)凤壁。BOOL返回值表示是否成功,如果失敗的話可以通過NSError的error.localizedDescription查看出錯原因跪另。

因為AVAudioSession會影響其他App的表現(xiàn)拧抖,當(dāng)自己App的Session被激活,其他App的就會被解除激活免绿,如何要讓自己的Session解除激活后恢復(fù)其他App Session的激活狀態(tài)呢唧席?

此時可以使用:

  • (BOOL)setActive:(BOOL)active
    withOptions:(AVAudioSessionSetActiveOptions)options
    error:(NSError * _Nullable *)outError;

這里的options傳入AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation 即可。

當(dāng)然,也可以通過otherAudioPlaying變量來提前判斷當(dāng)前是否有其他App在播放音頻淌哟。

可以通過:

@property(readonly) NSString *category;

屬性迹卢,獲取當(dāng)前的Category,比如上面的播放其徒仓,默認(rèn)是

 NSLog(@"Current Category:%@", [AVAudioSession sharedInstance].category);

輸出:

Current Category:AVAudioSessionCategorySoloAmbien

七大Category

AVAudioSession主要能控制App的哪些表現(xiàn)以及如何控制的呢腐碱?首先AVAudioSession將使用音頻的場景分成七大類,通過設(shè)置Session為不同的類別掉弛,可以控制:

  • 當(dāng)App激活Session的時候症见,是否會打斷其他不支持混音的App聲音
  • 當(dāng)用戶觸發(fā)手機(jī)上的“靜音”鍵時或者鎖屏?xí)r,是否相應(yīng)靜音
  • 當(dāng)前狀態(tài)是否支持錄音
  • 當(dāng)前狀態(tài)是否支持播放
    每個App啟動時都會設(shè)置成上面說的默認(rèn)狀態(tài)狰晚,即其他App會被中斷同時相應(yīng)“靜音”鍵的播放模式筒饰。通過下表可以細(xì)分每個類別的支持情況:
類別 當(dāng)按“靜音”或者鎖屏是是否靜音 是否引起不支持混音的App中斷 是否支持錄音和播放
AVAudioSessionCategoryAmbient 只支持播放
AVAudioSessionCategoryAudioProcessing - 都不支持
AVAudioSessionCategoryMultiRoute 既可以錄音也可以播放
AVAudioSessionCategoryPlayAndRecord 默認(rèn)不引起 既可以錄音也可以播放
AVAudioSessionCategoryPlayback 默認(rèn)引起 只用于播放
AVAudioSessionCategoryRecord 只用于錄音
AVAudioSessionCategorySoloAmbient 只用于播放

可以看到,其實默認(rèn)的就是“AVAudioSessionCategorySoloAmbient”類別壁晒。從表中我們可以總結(jié)如下:

  • AVAudioSessionCategoryAmbient : 只用于播放音樂時瓷们,并且可以和QQ音樂同時播放,比如玩游戲的時候還想聽QQ音樂的歌秒咐,那么把游戲播放背景音就設(shè)置成這種類別谬晕。同時,當(dāng)用戶鎖屏或者靜音時也會隨著靜音携取,這種類別基本使用所有App的背景場景攒钳。
  • AVAudioSessionCategorySoloAmbient: 也是只用于播放,但是和"AVAudioSessionCategoryAmbient"不同的是,用了它就別想聽QQ音樂了雷滋,比如不希望QQ音樂干擾的App不撑,類似節(jié)奏大師。同樣當(dāng)用戶鎖屏或者靜音時也會隨著靜音晤斩,鎖屏了就玩不了節(jié)奏大師了焕檬。
  • AVAudioSessionCategoryPlayback: 如果鎖屏了還想聽聲音怎么辦?用這個類別澳泵,比如App本身就是播放器实愚,同時當(dāng)App播放時,其他類似QQ音樂就不能播放了兔辅。所以這種類別一般用于播放器類App
  • AVAudioSessionCategoryRecord: 有了播放器腊敲,肯定要錄音機(jī),比如微信語音的錄制维苔,就要用到這個類別碰辅,既然要安靜的錄音,肯定不希望有QQ音樂了介时,所以其他播放聲音會中斷乎赴。想想微信語音的場景忍法,就知道什么時候用他了。
  • AVAudioSessionCategoryPlayAndRecord: 如果既想播放又想錄制該用什么模式呢榕吼?比如VoIP,打電話這種場景勉失,PlayAndRecord就是專門為這樣的場景設(shè)計的 羹蚣。
  • AVAudioSessionCategoryMultiRoute: 想象一個DJ用的App,手機(jī)連著HDMI到揚聲器播放當(dāng)前的音樂乱凿,然后耳機(jī)里面播放下一曲顽素,這種常人不理解的場景,這個類別可以支持多個設(shè)備輸入輸出徒蟆。
  • AVAudioSessionCategoryAudioProcessing: 主要用于音頻格式處理胁出,一般可以配合AudioUnit進(jìn)行使用

了解了這七大類別,我們就可以根據(jù)自己的需要進(jìn)行對應(yīng)類別的設(shè)置了:

- (BOOL)setCategory:(NSString *)category error:(NSError **)outError;

傳入對應(yīng)的列表枚舉即可段审。如果返回"NO"可以通過NSError的error.localizedDescription查看原因全蝶。

可以通過:

@property(readonly) NSArray<NSString *> *availableCategories;

屬性,查看當(dāng)前設(shè)備支持哪些類別寺枉,然后再進(jìn)行設(shè)置抑淫,從而保證傳入?yún)?shù)的合法,減少錯誤的可能姥闪。

比如修改上面的Demo例子:

    NSLog(@"Current Category:%@", [AVAudioSession sharedInstance].category);
    NSError *error = nil;
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
    if (nil != error) {
        NSLog(@"set Option error %@", error.localizedDescription);
    }
    NSLog(@"Current Category:%@", [AVAudioSession sharedInstance].category);

此時在播放音樂的時候始苇,再去按下靜音鍵,會發(fā)現(xiàn)筐喳,音樂還在繼續(xù)播放催式,不會被靜音。

類別的選項

上面介紹的這個七大類別避归,可以認(rèn)為是設(shè)定了七種主場景荣月,而這七類肯定是不能滿足開發(fā)者所有的需求的。CoreAudio提供的方法是槐脏,首先定下七種的一種基調(diào)喉童,然后在進(jìn)行微調(diào)。CoreAudio為每種Category都提供了些許選項來進(jìn)行微調(diào)顿天。
在設(shè)置完類別后堂氯,可以通過

@property(readonly) AVAudioSessionCategoryOptions categoryOptions;

屬性,查看當(dāng)前類別設(shè)置了哪些選項牌废,注意這里的返回值是AVAudioSessionCategoryOptions咽白,實際是多個options的“|”運算。默認(rèn)情況下是0鸟缕。

選項 適用類別 作用
AVAudioSessionCategoryOptionMixWithOthers AVAudioSessionCategoryPlayAndRecord, AVAudioSessionCategoryPlayback, and AVAudioSessionCategoryMultiRoute 是否可以和其他后臺App進(jìn)行混音
AVAudioSessionCategoryOptionDuckOthers AVAudioSessionCategoryAmbient, AVAudioSessionCategoryPlayAndRecord, AVAudioSessionCategoryPlayback, and AVAudioSessionCategoryMultiRoute 是否壓低其他App聲音
AVAudioSessionCategoryOptionAllowBluetooth AVAudioSessionCategoryRecord and AVAudioSessionCategoryPlayAndRecord 是否支持藍(lán)牙耳機(jī)
AVAudioSessionCategoryOptionDefaultToSpeaker AVAudioSessionCategoryPlayAndRecord 是否默認(rèn)用免提聲音

目前主要的選項有這幾種晶框,都有對應(yīng)的使用場景排抬,除此之外,在iOS9還提供了AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers最新的iOS10又新加了兩個AVAudioSessionCategoryOptionAllowBluetoothA2DP 授段、AVAudioSessionCategoryOptionAllowAirPlay用來支持藍(lán)牙A2DP耳機(jī)和AirPlay蹲蒲。

來看每個選項的基本作用:

  • AVAudioSessionCategoryOptionMixWithOthers : 如果確實用的AVAudioSessionCategoryPlayback實現(xiàn)的一個背景音,但是呢侵贵,又想和QQ音樂并存届搁,那么可以在AVAudioSessionCategoryPlayback類別下在設(shè)置這個選項,就可以實現(xiàn)共存了窍育。
  • AVAudioSessionCategoryOptionDuckOthers:在實時通話的場景卡睦,比如QQ音樂,當(dāng)進(jìn)行視頻通話的時候漱抓,會發(fā)現(xiàn)QQ音樂自動聲音降低了表锻,此時就是通過設(shè)置這個選項來對其他音樂App進(jìn)行了壓制。
  • AVAudioSessionCategoryOptionAllowBluetooth:如果要支持藍(lán)牙耳機(jī)電話乞娄,則需要設(shè)置這個選項
  • AVAudioSessionCategoryOptionDefaultToSpeaker: 如果在VoIP模式下瞬逊,希望默認(rèn)打開免提功能,需要設(shè)置這個選項

通過接口:
- (BOOL)setCategory:(NSString *)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError
來對當(dāng)前的類別進(jìn)行選項的設(shè)置补胚。

比如Demo中:

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];
    if (nil != error) {
        NSLog(@"set Option error %@", error.localizedDescription);
    }
    options = [[AVAudioSession sharedInstance] categoryOptions];
    NSLog(@"Category[%@] has %lu options",  [AVAudioSession sharedInstance].category, options);

此時码耐,先打開QQ音樂播放器,然后再開始進(jìn)行播放溶其,會發(fā)現(xiàn)骚腥,QQ和我們的播放器都在播放,并且進(jìn)行了自動混音瓶逃。

不過這個過程束铭,感覺CoreAudio缺少一個setOption的接口,既然已經(jīng)是當(dāng)前處于的Category厢绝,干嘛還要再設(shè)置選項的時候再指定Category呢契沫??疑惑昔汉。懈万。。

七大模式

剛講完七大類別靶病,現(xiàn)在再來七大模式会通。通過上面的七大類別,我們基本覆蓋了常用的主場景娄周,在每個主場景中可以通過Option進(jìn)行微調(diào)涕侈。為此CoreAudio提供了七大比較常見微調(diào)后的子場景。叫做各個類別的模式煤辨。

模式 適用的類別 場景
AVAudioSessionModeDefault 所有類別 默認(rèn)的模式
AVAudioSessionModeVoiceChat AVAudioSessionCategoryPlayAndRecord VoIP
AVAudioSessionModeGameChat AVAudioSessionCategoryPlayAndRecord 游戲錄制裳涛,由GKVoiceChat自動設(shè)置木张,無需手動調(diào)用
AVAudioSessionModeVideoRecording AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord 錄制視頻時
AVAudioSessionModeMoviePlayback AVAudioSessionCategoryPlayback 視頻播放
AVAudioSessionModeMeasurement AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayback 最小系統(tǒng)
AVAudioSessionModeVideoChat AVAudioSessionCategoryPlayAndRecord 視頻通話

每個模式有其適用的類別,所以端三,并不是有“七七 四十九”種組合舷礼。如果當(dāng)前處于的類別下沒有這個模式,那么是設(shè)置不成功的郊闯。設(shè)置完Category后可以通過:

@property(readonly) NSArray<NSString *> *availableModes;

屬性且轨,查看其支持哪些屬性,做合法性校驗虚婿。

來看具體應(yīng)用:

  • AVAudioSessionModeDefault: 每種類別默認(rèn)的就是這個模式,所有要想還原的話泳挥,就設(shè)置成這個模式然痊。
  • AVAudioSessionModeVoiceChat:主要用于VoIP場景,此時系統(tǒng)會選擇最佳的輸入設(shè)備屉符,比如插上耳機(jī)就使用耳機(jī)上的麥克風(fēng)進(jìn)行采集剧浸。此時有個副作用,他會設(shè)置類別的選項為"AVAudioSessionCategoryOptionAllowBluetooth"從而支持藍(lán)牙耳機(jī)矗钟。
  • AVAudioSessionModeVideoChat : 主要用于視頻通話唆香,比如QQ視頻、FaceTime吨艇。時系統(tǒng)也會選擇最佳的輸入設(shè)備躬它,比如插上耳機(jī)就使用耳機(jī)上的麥克風(fēng)進(jìn)行采集并且會設(shè)置類別的選項為"AVAudioSessionCategoryOptionAllowBluetooth" 和 "AVAudioSessionCategoryOptionDefaultToSpeaker"。
  • AVAudioSessionModeGameChat : 適用于游戲App的采集和播放东涡,比如“GKVoiceChat”對象冯吓,一般不需要手動設(shè)置

另外幾種和音頻APP關(guān)系不大,一般我們只需要關(guān)注VoIP或者視頻通話即可疮跑。

通過調(diào)用:

- (BOOL)setMode:(NSString *)mode error:(NSError **)outError

可以在設(shè)置Category之后再設(shè)置模式组贺。

當(dāng)然,這些模式只是CoreAduio總結(jié)的祖娘,不一定完全滿足要求失尖,對于具體的模式,在iOS10中還是可以微調(diào)的渐苏。通過接口:

  • (BOOL)setCategory:(NSString *)category mode:(NSString *)mode options:(AVAudioSessionCategoryOptions)options error:(NSError **)outError

但是在iOS9及以下就只能在Category上調(diào)了掀潮,其實本質(zhì)是一樣的,可以認(rèn)為是個API糖整以,接口封裝胧辽。

系統(tǒng)中斷響應(yīng)

上面說的這些Category啊、Option啊以及Mode都是對自己作為播放主體時的表現(xiàn)公黑,但是假設(shè)邑商,現(xiàn)在正在播放著摄咆,突然來電話了、鬧鐘響了或者你在后臺放歌但是用戶啟動其他App用上面的方法影響的時候人断,我們的App該如何表現(xiàn)呢吭从?最常用的場景當(dāng)然是先暫停,待恢復(fù)的時候再繼續(xù)恶迈。那我們的App要如何感知到這個終端以及何時恢復(fù)呢涩金?

AVAudioSession提供了多種Notifications來進(jìn)行此類狀況的通知。其中將來電話暇仲、鬧鈴響等都?xì)w結(jié)為一般性的中斷步做,用
AVAudioSessionInterruptionNotification來通知。其回調(diào)回來的userInfo主要包含兩個鍵:

  • AVAudioSessionInterruptionTypeKey: 取值為AVAudioSessionInterruptionTypeBegan表示中斷開始奈附,我們應(yīng)該暫停播放和采集全度,取值為AVAudioSessionInterruptionTypeEnded表示中斷結(jié)束,我們可以繼續(xù)播放和采集斥滤。
  • AVAudioSessionInterruptionOptionKey: 當(dāng)前只有一種值AVAudioSessionInterruptionOptionShouldResume表示此時也應(yīng)該恢復(fù)繼續(xù)播放和采集将鸵。

而將其他App占據(jù)AudioSession的時候用AVAudioSessionSilenceSecondaryAudioHintNotification來進(jìn)行通知。其回調(diào)回來的userInfo鍵為:

AVAudioSessionSilenceSecondaryAudioHintTypeKey

可能包含的值:

  • AVAudioSessionSilenceSecondaryAudioHintTypeBegin: 表示其他App開始占據(jù)Session
  • AVAudioSessionSilenceSecondaryAudioHintTypeEnd: 表示其他App開始釋放Session

外設(shè)改變

除了其他App和系統(tǒng)服務(wù)佑颇,會對我們的App產(chǎn)生影響以外顶掉,用戶的手也會對我們產(chǎn)生影響。默認(rèn)情況下挑胸,AudioSession會在App啟動時選擇一個最優(yōu)的輸出方案痒筒,比如插入耳機(jī)的時候,就用耳機(jī)嗜暴。但是這個過程中凸克,用戶可能拔出耳機(jī),我們App要如何感知這樣的情況呢闷沥?

同樣AVAudioSession也是通過Notifications來進(jìn)行此類狀況的通知萎战。

假設(shè)有這樣的App:

route_change
route_change

最開始在錄音時,用戶插入和拔出耳機(jī)我們都停止錄音舆逃,這里通過Notification來通知有新設(shè)備了蚂维,或者設(shè)備被退出了,然后我們控制停止錄音路狮〕嫔叮或者在播放時,當(dāng)耳機(jī)被拔出出時奄妨,Notification給了通知涂籽,我們先暫停音樂播放,待耳機(jī)插回時砸抛,在繼續(xù)播放评雌。

在NSNotificationCenter中對AVAudioSessionRouteChangeNotification進(jìn)行注冊树枫。在其userInfo中有鍵:

  • AVAudioSessionRouteChangeReasonKey : 表示改變的原因
枚舉值 意義
AVAudioSessionRouteChangeReasonUnknown 未知原因
AVAudioSessionRouteChangeReasonNewDeviceAvailable 有新設(shè)備可用
AVAudioSessionRouteChangeReasonOldDeviceUnavailable 老設(shè)備不可用
AVAudioSessionRouteChangeReasonCategoryChange 類別改變了
AVAudioSessionRouteChangeReasonOverride App重置了輸出設(shè)置
AVAudioSessionRouteChangeReasonWakeFromSleep 從睡眠狀態(tài)呼醒
AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory 當(dāng)前Category下沒有合適的設(shè)備
AVAudioSessionRouteChangeReasonRouteConfigurationChange Rotuer的配置改變了
  • AVAudioSessionSilenceSecondaryAudioHintTypeKey: 和上面的中斷意義意義。

總結(jié):

AVAudioSession構(gòu)建了一個音頻使用生命周期的上下文景东。當(dāng)前狀態(tài)是否可以錄音砂轻、對其他App有怎樣的影響、是否響應(yīng)系統(tǒng)的靜音鍵斤吐、如何感知來電話了等都可以通過它來實現(xiàn)搔涝。尤為重要的是AVAudioSession不僅可以和AVFoundation中的AVAudioPlyaer/AVAudioRecorder配合,其他錄音/播放工具比如AudioUnit和措、AudioQueueService也都需要他進(jìn)行錄音庄呈、靜音等上下文配合。

文中Demo參見GitHub

參考文檔

  1. Audio Session Programming Guide
  2. AVAudioSession Class Reference
  3. Audio Session Services Reference
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末派阱,一起剝皮案震驚了整個濱河市抒痒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌颁褂,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件傀广,死亡現(xiàn)場離奇詭異颁独,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)伪冰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門誓酒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人贮聂,你說我怎么就攤上這事靠柑。” “怎么了吓懈?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵歼冰,是天一觀的道長。 經(jīng)常有香客問我耻警,道長隔嫡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任甘穿,我火速辦了婚禮腮恩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘温兼。我一直安慰自己秸滴,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布募判。 她就那樣靜靜地躺著荡含,像睡著了一般咒唆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上内颗,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天钧排,我揣著相機(jī)與錄音,去河邊找鬼均澳。 笑死恨溜,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的找前。 我是一名探鬼主播糟袁,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼躺盛!你這毒婦竟也來了项戴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤槽惫,失蹤者是張志新(化名)和其女友劉穎周叮,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體界斜,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡仿耽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了各薇。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片项贺。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖峭判,靈堂內(nèi)的尸體忽然破棺而出开缎,到底是詐尸還是另有隱情,我是刑警寧澤林螃,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布奕删,位于F島的核電站,受9級特大地震影響疗认,放射性物質(zhì)發(fā)生泄漏急侥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一侮邀、第九天 我趴在偏房一處隱蔽的房頂上張望坏怪。 院中可真熱鬧,春花似錦绊茧、人聲如沸铝宵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鹏秋。三九已至尊蚁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間侣夷,已是汗流浹背横朋。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留百拓,地道東北人琴锭。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像衙传,于是被迫代替她去往敵國和親决帖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

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