Android系统apn介绍

快速入口: Apn_change完整时序图

apn_change.png

1. APN概念

APN全称是Access Point Name,中文即接入点,是通过手机上网时必须配置的一个参数,它决定了手机通过哪种接入方式来访问网络。

2. Apn参数及初始化

Apn的创建在ContentProvider里面,他所在的Process启动了,ContentProvider就会在ActivityThread中启动,流程如下:

注:统一使用@类.方法表示流程中的方法

@SQLiteOpenHelper.getDatabaseLocked

@TelephonyProvider.DatabaseHelper.onCreate

createCarriersTable(db, CARRIERS_TABLE);//创建数据库(carriers)

initDatabase(db);//初始化apn数据

Carriers内的字段都定义在Telephony.java文件的子类Carriers中,各个字段详情见附件1([Carriers参数定义]。

Android的网络配置作为资源文件写入了XML(/frameworks/base/core/res/res/xml/apns.xml),这个资源文件作为Android的默认Apns配置,不建议修改该文件,且一般为空。因为Apn的配置是根据不同的硬件产品而不同,所以为不同的硬件产品建立各自的配置文件(system/etc/apns-conf.xml) ,而不去改动默认的配置文件(apns.xml)。

在apn数据库的初始化中,会先加载系统apn然后加载厂商apn。以下为部分代码:

// Read internal APNS data  

XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns)

loadApns(db, parser);

// Read external APNS data (partner-provided)     

File confFile = new File(Environment.getRootDirectory(), "etc/apns-conf.xml");

loadApns(db, confparser);

3. Apn数据库的增删改查

(1)首先创建URI连接:

public Uri createUri = Uri.parse("content://telephony/carriers");

(2)然后根据前后文获取ContentResolver访问数据库:

ContentResolver contentResolver =context.getContentResolver();

(3)写一个要修改的参数对,contentValues 里面使用HashMap保存:

ContentValues contentValues =new ContentValues();

contentValues.put("name", apn.getName());

(4)增删改查语句:

contentResolver.insert(createUri, contentValues); 

contentResolver.delete(createUri,"_id=?",new String[] { id });

contentResolver.update(createUri, contentValues, null,null);

contentResolver.query(createUri,projection,selection,selectionArgs,sortOrder)

4. 上层设置默认apn

用户通过设置界面进入apn选项界面,当更换当前的apn选项时,会更新当前的apn数据库,然后就会触发重建数据连接流程,时序图如下:

ui重置apn.png

4.1上层UI进入apn界面流程

在设置界面中点击“移动网络”选项,进入手机移动网络设置界面。然后点击“接入点名称”时会触发点击事件,然后通过intent又返回到设置里面开启apn界面,显示当前apn项,逻辑如下:

@leui_settings_headers//设置界面布局文件

android:targetClass="com.android.phone.MobileNetworkSettings">

@MobileNetworkSettings//移动网络界面创建Options

mGsmUmtsOptions = new GsmUmtsOptions(this, prefSet, mPhone.getPhoneId());

@GsmUmtsOptions//options界面就是“接入点名称”选项菜单

intent.setAction(Settings.ACTION_APN_SETTINGS);//开启ApnSettings

@ApnSettings.fillList//打开apn界面后遍历当前apn列表并显示

@ApnPreference//承载一个apn显示列

 this(context, attrs, R.attr.apnPreferenceStyle);//引入apn的xml文件

@res/values/themes.xml:129:

<item name="apnPreferenceStyle">@style/ApnPreference</item>

@res/values/styles.xml:351://apn的界面有几次跳转,最后在styles中

    <style name="ApnPreference">

        <item name="android:layout">@layout/apn_preference_layout</item>

    </style>

@apn_preference_layout//apn布局文件

4.2 UI重选apn

在apn界面点击更换一个apn后,会通过uri更新当前的apn数据库。接着Dctracker监听到了数据库的变化,从而开始重新创建数据连接:

@ApnSettings.onPreferenceChange//ui改动preferapn

        setSelectedApnKey((String) newValue);

@ApnSettings.setSelectedApnKey//更新apn数据库

resolver.update(getUri(PREFERAPN_URI), values, null, null);

@DcTracker//mApnObserver监听apn数据库变化

p.getContext().getContentResolver().registerContentObserver(Telephony.Carriers.CONTENT_URI, true, mApnObserver);

@DcTracker.ApnChangeObserver.onChange

sendMessage(obtainMessage(DctConstants.EVENT_APN_CHANGED));

@DcTracker.handleMessage//消息id为270355

case DctConstants.EVENT_APN_CHANGED//(270355)

@DcTracker.onApnChanged//创建数据连接的方法

tryRestartDataConnections(true, Phone.REASON_APN_CHANGED);

5. DcTracker创建数据连接

这里面,我们首先说一下会触发Dctraker创建数据连接的几个消息:

 EVENT_APN_CHANGED//(270335)监听apn数据库变化
 EVENT_RECORDS_LOADED//(270338)卡加载
 EVENT_VOICE_CALL_ENDED//(270344)
 EVENT_ROAMING_ON//(270347)
 EVENT_ROAMING_OFF//(270348)
 EVENT_DATA_CONNECTION_ATTACHED//(270352)
 EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED//(270357)
 EVENT_DATA_RAT_CHANGED//(270377)监听底层主动上报的     RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED
 EVENT_MODEM_DATA_PROFILE_READY//(270379)

在重选apn引起的创建数据连接流程中,首先通过网络类型获取卡信息,读取其中的mcc mnc值,再通过该值查找apn数据库创建apn列表,这些逻辑都在方法createAllApnList里面;有了apn列表之后,会先找一个初始的apn下发到modem,这一步的作用目前不是很明确,像创建数据连接的一个预处理。它在以下几种情况下被调用:

EVENT_RECORDS_LOADED

EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED

EVENT_DATA_RAT_CHANGED

EVENT_APN_CHANGED

然后依据当前情况清空原有数据连接,重新创建。

@DcTracker.tryRestartDataConnections//开始创建连接

createAllApnList//创建apn列表

getPreferredApn//有优选apn则获取

setPreferredApn(-1);//没有则设为-1

setInitialAttachApn//设置初始apn(ia->Preferred->default->first)会通过RIL下发RIL_REQUEST_SET_INITIAL_ATTACH_APN命令,预绑定

cleanUpAllConnections

setupDataOnConnectableApns

接着setupDataOnConnectableApns方法选用apn列表中合适的apn开始创建数据连接。trySetupData里面的buildWaitingApns方法会对apn列表进行进一步过滤,有PreferredApn则加入列表并直接返回,使用该apn;如没有preferredApn会把apn表中满足条件的apn都加入列表并返回,再使用第一个apn创建连接。

@DcTracker.setupDataOnConnectableApns

trySetupData

@DcTracker.trySetupData

buildWaitingApns

setupData

@DcTracker.setupData

apnSetting = apnContext.getNextWaitingApn();//使用第一个

dcac.bringUp(apnContext...);

经过一系列的验证,各个参数准备完毕,发出创建连接请求。走到状态机,StateMachine的子类接受消息,能继续创建连接的有DcInactiveState/DcRetryingState,这里我们用的是DcInactiveState。

@DcAsyncChannel.bringUp

         sendMessage(DataConnection.EVENT_CONNECT...)

@StateMachine.SmHandler.processMsg

 while (!curStateInfo.state.processMessage(msg)) {

@DataConnection.DcInactiveState.processMessage//当前的子类状态处理

onConnect(mConnectionParams);//EVENT_CONNECT//(关键字)

transitionTo(mActivatingState);//状态由断开变为正在连接

@DataConnection.onConnect

mPhone.mCi.setupDataCall(Integer.toString(cp.mRilRat + 2)...);//rillrat代表网络类型,其值+2传到ril。[部分log](#_部分log:)及[网络类型](#_网络类型:)详情参见附件2。

@RIL.setupDataCall

RIL_REQUEST_SETUP_DATA_CALL//SETUP_DATA_CALL(关键字)

时序图如下:

dctracker处理数据连接.png

6. 底层网络状态变化触发创建apn连接的流程

底层网络状态发生变化,会发出UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED消息通知上层。

@RIL.processUnsolicited

case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED:

mVoiceNetworkStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null));//mVoiceNetworkStateRegistrants发出通知

@GsmServiceStateTracker//ServiceStateTracker//监听该通知

mCi.registerForVoiceNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null);

mVoiceNetworkStateRegistrants.add(r);

上层收到通知,会向底层重新请求新的数据连接的各个参数,具体下发的消息如下(以GsmServiceStateTracker为例):

EVENT_POLL_STATE_OPERATOR//spn

EVENT_POLL_STATE_GPRS//RilData

EVENT_POLL_STATE_REGISTRATION//服务状态,RilVoice

EVENT_POLL_STATE_NETWORK_SELECTION_MODE//网络模式

代码逻辑如下:

@GsmServiceStateTracker.handleMessage

case EVENT_NETWORK_STATE_CHANGED

@GsmServiceStateTracker.pollState//下发四个命令

       mPollingContext[0]++;

   mCi.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR, mPollingContext));

   mPollingContext[0]++;

   mCi.getDataRegistrationState(obtainMessage(EVENT_POLL_STATE_GPRS, mPollingContext));

   mPollingContext[0]++;

   mCi.getVoiceRegistrationState(obtainMessage(EVENT_POLL_STATE_REGISTRATION, mPollingContext));

   mPollingContext[0]++;

   mCi.getNetworkSelectionMode(obtainMessage(EVENT_POLL_STATE_NETWORK_SELECTION_MODE, mPollingContext));

各个请求连续发送完毕后,底层会一一回复。然后上层收到新的参数,重新配置各个参数:运营商名称,数据类型,voice类型,网络模式。配置完后,开始创建数据连接。

@GsmServiceStateTracker.handleMessage

        ...

handlePollStateResult(msg.what, ar);

@GsmServiceStateTracker.handlePollStateResult//负责配置各个参数

        mPollingContext[0]//;//当mPollingContext[0]为0时才会走pollStateDone

@GsmServiceStateTracker.pollStateDone

notifyDataRegStateRilRadioTechnologyChanged();

@ServiceStateTracker.notifyDataRegStateRilRadioTechnologyChanged

mDataRegStateOrRatChangedRegistrants.notifyResult(new Pair<Integer, Integer>(drs, rat));

@DcTracker.handleMessage//DCTracker注册mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged

case DctConstants.EVENT_DATA_RAT_CHANGED(270377)(this,DctConstants.EVENT_DATA_RAT_CHANGED, null);

onUpdateIcc//更据当前网络类型更新sim信息

tryRestartDataConnections//创建数据连接

底层网络状态变化后,触发重新创建数据连接的整个时序图如下:

data_rat_changed.png

7. 底层成功创建数据连接后的处理

当底层成功创建数据连接后,会向上层发出RIL_REQUEST_SETUP_DATA_CALL消息。RIL层接受该消息后,通知状态机。状态机根据底层上报的参数,判断出重新创建连接成功,将状态由DcActivatingState改为ActiveState。ActiveState又会发出通知告诉DcTrackerBase,而后续处理操作onDataSetupComplete由DcTrackerBase的子类DcTracker完成。

@RIL.run

case RIL_REQUEST_SETUP_DATA_CALL

@RIL.processResponse

@RIL.processSolicited

transitionTo(mActiveState);

@DcActivatingState.handleMessage()

case EVENT_SETUP_DATA_CONNECTION_DONE:

onSetupConnectionCompleted

transitionTo(mActiveState);

@DcActiveState.enter()

notifyAllOfConnected(Phone.REASON_CONNECTED);

@DataConnection.notifyAllOfConnected

notifyAllWithEvent(null, DctConstants.EVENT_DATA_SETUP_COMPLETE, reason);

@DcTrackerBase.handleMessage

case EVENT_DATA_SETUP_COMPLETE

onDataSetupComplete():

@DcTracker.onDataSetupComplete

时序图如下:

data_setup_complete.png

附件1_

创建carriers表语句:

db.execSQL("CREATE TABLE " + tableName +

                    "(_id INTEGER PRIMARY KEY," +

                    "name TEXT DEFAULT ''," +

                    "numeric TEXT DEFAULT ''," +

                    "mcc TEXT DEFAULT ''," +

                    "mnc TEXT DEFAULT ''," +

                    "apn TEXT DEFAULT ''," +

                    "user TEXT DEFAULT ''," +

                    "server TEXT DEFAULT ''," +

                    "password TEXT DEFAULT ''," +

                    "proxy TEXT DEFAULT ''," +

                    "port TEXT DEFAULT ''," +

                    "mmsproxy TEXT DEFAULT ''," +

                    "mmsport TEXT DEFAULT ''," +

                    "mmsc TEXT DEFAULT ''," +

                    "authtype INTEGER DEFAULT -1," +

                    "type TEXT DEFAULT ''," +

                    "current INTEGER," +

                    "protocol TEXT DEFAULT 'IP'," +

                    "roaming_protocol TEXT DEFAULT 'IP'," +

                    "carrier_enabled BOOLEAN DEFAULT 1," +

                    "bearer INTEGER DEFAULT 0," +

                    "bearer_bitmask INTEGER DEFAULT 0," +

                    "mvno_type TEXT DEFAULT ''," +

                    "mvno_match_data TEXT DEFAULT ''," +

                    "sub_id INTEGER DEFAULT " + 

                    SubscriptionManager.INVALID_SUBSCRIPTION_ID + 

                    "," +

                    "profile_id INTEGER DEFAULT 0," +

                    "modem_cognitive BOOLEAN DEFAULT 0," +

                    "max_conns INTEGER DEFAULT 0," +

                    "wait_time INTEGER DEFAULT 0," +

                    "max_conns_time INTEGER DEFAULT 0," +

                    "mtu INTEGER DEFAULT 0," +

                    "edited INTEGER DEFAULT " + 

                     Telephony.Carriers.UNEDITED + 

                    "," +

                    "read_only BOOLEAN DEFAULT 0," +

                    "UNIQUE (numeric, mcc, mnc, apn, proxy, port, 

                     mmsproxy, mmsport, mmsc," +

                    "carrier_enabled, bearer, mvno_type, mvno_match_data,                    profile_id));");

carriers参数定义

定义在Telephony.Carriers中,

_id//key

name//Entry name

numeric//Numeric operator ID (as String). Usually MCC + MNC.

mcc//Mobile Country Code (MCC).

mnc//Mobile Network Code (MNC).

apn//APN name.

user//APN username.

server//Server address.

password//APN password.

proxy//Proxy address.

port//Proxy port.

mmsproxy//MMS proxy address.

mmsport//MMS proxy port.

mmsc//MMSC URL.

authtype//Authentication type.

(1:PAP/2:CHAP/3:PAP|CHAP)需要跟user password联合使用。

type//Comma-delimited list of APN types.(default,mms,supl,dun,ims,ia...)

current// Is this the current APN?

Protocol

//The protocol to use to connect to this APN. One of the PDP_type values in TS 27.007 section 10.1.1. For example: IP, IPV6, IPV4V6, or PPP.

roaming_protocol

//The protocol to use to connect to this APN when roaming. The syntax is the same as protocol.

carrier_enabled//Is this APN enabled?

Bearer

//Radio Access Technology info. To check what values are allowed, refer to android.telephony.ServiceState. This should be spread to other technologies, but is currently only used for LTE (14) and eHRPD (13).

bearer_bitmask

//Radio Access Technology bitmask. To check what values can be contained, refer to android.telephony.ServiceState. 0 indicates all techs otherwise first bit refers to RAT/bearer 1, second bit refers to RAT/bearer 2 and so on. Bitmask for a radio tech R is (1 << (R - 1))

mvno_type

//MVNO type: SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1).

mvno_match_data

//MVNO data. Use the following examples.

SPN: A MOBILE, BEN NL, ...

IMSI: 302720x94, 2060188, ...

GID: 4E, 33, ...

sub_id//The subscription to which the APN belongs to

profile_id//The profile_id to which the APN saved in modem

modem_cognitive//Is the apn setting to be set in modem

max_conns//The max connections of this apn

wait_time//The wait time for retry of the apn

max_conns_time//The time to limit max connection for the apn

mtu//The MTU size of the mobile interface to which the APN connected

edited//Is this APN added/edited/deleted by a user or carrier?

read_only//default?

附件2

网络类型:

ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN

RIL_RADIO_TECHNOLOGY_UNKNOWN = 0;

RIL_RADIO_TECHNOLOGY_GPRS = 1;

RIL_RADIO_TECHNOLOGY_EDGE = 2;

RIL_RADIO_TECHNOLOGY_UMTS = 3;

RIL_RADIO_TECHNOLOGY_IS95A = 4;

RIL_RADIO_TECHNOLOGY_IS95B = 5;

RIL_RADIO_TECHNOLOGY_1xRTT = 6;

RIL_RADIO_TECHNOLOGY_EVDO_0 = 7;

RIL_RADIO_TECHNOLOGY_EVDO_A = 8;

RIL_RADIO_TECHNOLOGY_HSDPA = 9;

RIL_RADIO_TECHNOLOGY_HSUPA = 10;

RIL_RADIO_TECHNOLOGY_HSPA = 11;

RIL_RADIO_TECHNOLOGY_EVDO_B = 12;

RIL_RADIO_TECHNOLOGY_EHRPD = 13;

RIL_RADIO_TECHNOLOGY_LTE = 14;

RIL_RADIO_TECHNOLOGY_HSPAP = 15;

RIL_RADIO_TECHNOLOGY_GSM = 16;

RIL_RADIO_TECHNOLOGY_TD_SCDMA = 17;

SIM//RUIM//ISIM

SIMRecords(APPTYPE_USIM,APPTYPE_SIM)

RuimRecords(APPTYPE_RUIM,APPTYPE_CSIM)

IsimUiccRecords(APPTYPE_ISIM)

附件3

apn文件的替换

MTK平台

@device/mediatek/common/device.mk
PRODUCT_COPY_FILES += device/mediatek/common/apns-conf.xml:system/etc/apns-conf.xml 
修改为:
#PRODUCT_COPY_FILES += device/mediatek/common/apns-conf.xml:system/etc/apns-conf.xml 
 APN_PATH := device/mediatek/common
       XXX_APN_CONFIG_FILE := $(if $(wildcard vendor/xxx/frameworks/etc/apnsconfig/apns-conf.xml),yes,no) 
       ifeq ($(XXX_APN_CONFIG_FILE),yes)
          APN_PATH := vendor/xxx/frameworks/etc/apnsconfig
       endif
 PRODUCT_COPY_FILES := $(APN_PATH)/apns-conf.xml:system/etc/apns-conf.xml $(PRODUCT_COPY_FILES)

高通平台

@xx/device/qcom/msm8994/msm8994.mk:69:
ifeq ($(wildcard $(QC_PROP_ROOT)/common-noship/etc/device-vendor-noship.mk),)
    ifneq ($(call is-android-codename-in-list,GINGERBREAD HONEYCOMB),true)
        APN_PATH := vendor/xxx/frameworks/etc/apnsconfig
        PRODUCT_COPY_FILES := $(APN_PATH)/apns-conf.xml:system/etc/apns-conf.xml $(PRODUCT_COPY_FILES)
    endif
endif

feature 控制_telephony.ct.apn

vendor/xxx/frameworks/featureslist/
手机目录: system/etc/permissions/

附件4_部分log:

//////////////-DcTracker创建数据连接流程log//////////////////-

09-09 16:53:33.053 D/GsmDCT  ( 3057): [1]handleMessage msg={ when=-546ms what=270352 obj=android.os.AsyncResult@3651063e target=com.android.internal.telephony.dataconnection.DcTracker }

09-09 16:53:33.358 D/GsmDCT  ( 3057): [1]setupDataOnConnectableApns: dataAttached

09-09 16:53:33.360 D/GsmDCT  ( 3057): [1]buildWaitingApns: usePreferred=true canSetPreferApn=true mPreferredApn=null operator=310410 radioTech=11

09-09 16:53:33.374 D/GsmDCT  ( 3057): [1]createDataConnection() X id=0 dc={DC-1: State=DcInactiveState mApnSetting=null RefCount=0 mCid=-1 mCreateTime=-1 mLastastFailTime=-1 mLastFailCause=NONE mTag=1 mRetryManager=RetryManager: { forever=false maxRetry=0 curMaxRetry=0 retry=0 config={null} retryArray={}} mLinkProperties={LinkAddresses: []  Routes: [] DnsAddresses: [] Domains: null MTU: 0} linkCapabilities=[ Transports: CELLULAR Capabilities: NOT_RESTRICTED&TRUSTED&NOT_VPN LinkUpBandwidth>=5898Kbps LinkDnBandwidth>=14336Kbps Specifier: <1>] mApnContexts=[]}

09-09 16:53:33.374 D/GsmDCT  ( 3057): [1]setupData: dcac=DC-1 apnSetting=[ApnSettingV3] Cingular 410, 446, 310410, wap.cingular, , http://mmsc.cingular.com/, wireless.cingular.com, , , -1, default | supl | mms, IP, IP, true, 0, 0, false, 0, 0, 0, 0, , 

09-09 16:53:33.385 D/DC-1    ( 3057): DcInactiveState: mag.what=EVENT_CONNECT

09-09 16:53:33.389 D/DC-1    ( 3057): onConnect: carrier='Cingular 410' APN='wap.cingular' proxy='' port=''

09-09 16:53:33.390 D/RILJ    ( 3057): [3952]> SETUP_DATA_CALL 13 0 wap.cingular WAP@CINGULARGPRS.COM CINGULAR1 3 IP [SUB1]

//////////////-DcTracker创建数据连接流程log//////////////////-

//////////-底层网络状态变化log//////////-

09-10 07:53:32.374 D/GsmSST  ( 3057): [GsmSST1] Poll ServiceState done:  oldSS=[1 1 home null null null  Unknown Unknown CSS not supported -1 -1 RoamInd=-1 DefRoamInd=-1 EmergOnly=false] newSS=[0 0 home AT&T AT&T 310410  UMTS HSPA CSS not supported -1 -1 RoamInd=-1 DefRoamInd=-1 EmergOnly=false] oldMaxDataCalls=20 mNewMaxDataCalls=20 oldReasonDataDenied=-1 mNewReasonDataDenied=-1

09-09 16:53:32.500 D/GsmSST  ( 3057): [GsmSST1] notifyDataRegStateRilRadioTechnologyChanged: drs=0 rat=11

09-09 16:53:32.655 D/GsmDCT  ( 3057): [1]handleMessage msg={ when=-150ms what=270377 obj=android.os.AsyncResult@29a9f9c0 target=com.android.internal.telephony.dataconnection.DcTracker }

//////////-底层网络状态变化log//////////-
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容