Android 華為集成消息推送sdk

本來是想吐槽的戴陡,寫到最好發(fā)現(xiàn)官網(wǎng)好清晰

不容易發(fā)現(xiàn)的官方API

image.png

集成步驟:開發(fā)準(zhǔn)備官方鏈接地址

創(chuàng)建應(yīng)用梯投,添加簽名證書
    1. 打開命令行工具(使用CMD命令)命辖,執(zhí)行cd命令進(jìn)入keytool.exe所在的目錄
    1. 執(zhí)行命令keytool -list -v -keystore <keystore-file>,按命令行提示進(jìn)行操作分蓖。<keystore-file>為應(yīng)用簽名文件的完整路徑尔艇。填寫SHA256,然后等十幾分鐘后下載對應(yīng)的agcibbetct0services.json文件么鹤。
keytool -list -v -keystore I:\yhxx\releasexxxxx.keystore
image.png
image.png

image.png
添加應(yīng)用的AppGallery Connect配置文件

a. 登錄 AppGallery Connect 網(wǎng)站终娃,選擇“我的項(xiàng)目”。
b. 在項(xiàng)目列表中找到您的項(xiàng)目午磁,在項(xiàng)目中點(diǎn)擊需要集成HMS SDK的應(yīng)用尝抖。
c. 在“項(xiàng)目設(shè)置”頁面中,單擊“應(yīng)用”欄下的agconnect-services.json下載配置文件迅皇。
d. 將agconnect-services.json文件拷貝到應(yīng)用級根目錄下昧辽。

image.png

配置HMS SDK的maven倉地址

a. 打開AndroidStudio項(xiàng)目級project下的build.gradle文件。

image.png

b. 在allprojects ->repositories里面配置HMS SDK的maven倉地址登颓。

allprojects {
    repositories {
        google()
        jcenter()
        maven {url 'https://developer.huawei.com/repo/'}
    }
}

c. 在buildscript ->repositories里面配置HMS SDK的maven倉地址搅荞。

buildscript {
    repositories {
        google()
        jcenter()
        maven {url 'https://developer.huawei.com/repo/'}
    }
}

d. 在buildscript -> dependencies里面增加配置。

buildscript {
    dependencies {
        classpath 'com.huawei.agconnect:agcp:1.2.1.301'
    }
}
添加編譯依賴

a. 打開應(yīng)用級modulebuild.gradle文件。

image.png

b. 在dependencies中添加如下編譯依賴咕痛。
說明:{version}替換為實(shí)際的·SDK·版本號:implementation 'com.huawei.hms:push:4.0.3.301'

根據(jù)文檔來填寫痢甘,版本號好像更新

dependencies {
     //其它已存在的依賴不要刪除 implementation 'com.huawei.hms:push:4.0.3.301
     implementation 'com.huawei.hms:push:{version}'
}

c. 在應(yīng)用級build.gradle文件尾添加配置。

apply plugin: 'com.huawei.agconnect'

配置簽名(不可少茉贡,否則會獲取不到token塞栅,6003錯誤)

android {
     signingConfigs {
         config {
             keyAlias 'yalun'
             keyPassword '123456'
             storeFile file('I:/yhxx/release1.keystore')
             storePassword '123456'
         }
     }
     buildTypes {
         debug {
             signingConfig signingConfigs.config
         }
         release {
             signingConfig signingConfigs.config
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
         }
     }
 }
同步工程

修改完的build.gradle文件,點(diǎn)擊右上方出現(xiàn)Sync Now等待同步完成腔丧。

注冊HWPushReceiverService:

配置完成后放椰,可以通過兩種方式獲取token,一種是清單文件直接加入配置愉粤,可以再onNewToken方法里面直接獲取砾医,推薦。再一種是設(shè)置一下衣厘,也是在onNewToken方法中獲取token如蚜。參考本項(xiàng)目中的類HWPushReceiverService

HWPushReceiverService類需要開發(fā)者自己定義,繼承于com.huawei.hms.push.HmsMessageService類并實(shí)現(xiàn)其中的方法影暴。
exported屬性需要設(shè)置為false错邦。

image.png

package com.cc.pushallsdk;

import android.text.TextUtils;
import android.util.Log;

import com.huawei.hms.push.HmsMessageService;
import com.huawei.hms.push.RemoteMessage;

import java.util.Arrays;


public class HWPushReceiverService extends HmsMessageService {
    private static String TAG=HWPushReceiverService.class.getSimpleName();
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        Log.i(TAG, "getCollapseKey: " + remoteMessage.getCollapseKey()
                + "\n getData: " + remoteMessage.getData()
                + "\n getFrom: " + remoteMessage.getFrom()
                + "\n getTo: " + remoteMessage.getTo()
                + "\n getMessageId: " + remoteMessage.getMessageId()
                + "\n getOriginalUrgency: " + remoteMessage.getOriginalUrgency()
                + "\n getUrgency: " + remoteMessage.getUrgency()
                + "\n getSendTime: " + remoteMessage.getSentTime()
                + "\n getMessageType: " + remoteMessage.getMessageType()
                + "\n getTtl: " + remoteMessage.getTtl());
        RemoteMessage.Notification notification = remoteMessage.getNotification();
        if (notification != null) {
            Log.i(TAG, "\n getImageUrl: " + notification.getImageUrl()
                    + "\n getTitle: " + notification.getTitle()
                    + "\n getTitleLocalizationKey: " + notification.getTitleLocalizationKey()
                    + "\n getTitleLocalizationArgs: " + Arrays.toString(notification.getTitleLocalizationArgs())
                    + "\n getBody: " + notification.getBody()
                    + "\n getBodyLocalizationKey: " + notification.getBodyLocalizationKey()
                    + "\n getBodyLocalizationArgs: " + Arrays.toString(notification.getBodyLocalizationArgs())
                    + "\n getIcon: " + notification.getIcon()
                    + "\n getSound: " + notification.getSound()
                    + "\n getTag: " + notification.getTag()
                    + "\n getColor: " + notification.getColor()
                    + "\n getClickAction: " + notification.getClickAction()
                    + "\n getChannelId: " + notification.getChannelId()
                    + "\n getLink: " + notification.getLink()
                    + "\n getNotifyId: " + notification.getNotifyId());

        }
    }
    @Override
    public void onDeletedMessages() {
        super.onDeletedMessages();

    }
    /**
    *
    *清單文件設(shè)置了自動初始化能力的應(yīng)用,不需要顯式的調(diào)用getToken申請token坤检,
    * Push SDK會自動申請token兴猩,并通過onNewToken回調(diào)方法返回。
    */
    @Override
    public void onNewToken(String token) {
        super.onNewToken(token);
        if (!TextUtils.isEmpty(token)) {
//            refreshedTokenToServer(token);
        }
    }

    @Override
    public void onTokenError(Exception e) {
        super.onTokenError(e);
    }
}

清單文件AndroidManifest.xml集成的所有的可能用得到的
<application>
        <!--華為-->
        <provider
            android:name="com.huawei.agconnect.core.provider.AGConnectInitializeProvider"
            android:authorities="${applicationId}.AGCInitializeProvider"
            android:exported="false" />

        <service
            android:name="com.huawei.agconnect.core.ServiceDiscovery"
            android:exported="false" />

        <service
            android:name="com.huawei.hms.support.api.push.service.HmsMsgService"
            android:enabled="true"
            android:exported="true"
            android:process=":pushservice">
            <intent-filter>
                <action android:name="com.huawei.push.msg.NOTIFY_MSG" />
                <action android:name="com.huawei.push.msg.PASSBY_MSG" />
            </intent-filter>
        </service>
        <!-- 自定義的HWPushReceiverService extends HmsMessageService-->
        <service
            android:name="com.cc.pushallsdk.HWPushReceiverService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.huawei.push.action.MESSAGING_EVENT" />
            </intent-filter>
        </service>
        <!-- 通知消息:點(diǎn)擊不需要程序內(nèi)容做處理早歇,需要自定義跳轉(zhuǎn)就要定義協(xié)議-->
        <!-- 透傳消息:繼承HmsMessageService里面復(fù)寫onMessageReceived該方法,接收透傳參數(shù)-->
        <activity android:name="com.cc.pushallsdk.TargetActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data
                    android:host="com.cc.pushallsdk"
                    android:path="/wandanotify"
                    android:scheme="wandapushscheme" />
            </intent-filter>
        </activity>

</application>

配置工程project.properties文件(不知是否必要讨勤,官方寫了反正我添加了)

打開您的工程的project.properties文件箭跳,添加如下代碼,用于合并子工程中的Manifest文件潭千。

manifestmerger.enabled=true

集成步驟:[基礎(chǔ)能力官方鏈接地址]

https://developer.huawei.com/consumer/cn/doc/development/HMS-Guides/push-basic-capability

基礎(chǔ)能力概覽

image.png
  • Step1與Step2谱姓,開發(fā)者的App集成HMS SDK,再調(diào)用HmsInstanceId.getToken接口獲取到Push Token刨晴,請參考申請Push Token章節(jié)屉来。

  • Step3,開發(fā)者的App將獲取到的Push Token上報到開發(fā)者服務(wù)器App Provider Server上狈癞。

  • Step4茄靠,開發(fā)者使用服務(wù)器保存的Push Token調(diào)用Push服務(wù)端提供的API推送Push消息,請參考服務(wù)端開發(fā)指導(dǎo)章節(jié)蝶桶。

  • Step5慨绳,Push服務(wù)器將開發(fā)者推送的Push消息發(fā)送給Push Token對應(yīng)的用戶設(shè)備,設(shè)備接收Push消息,請參考接收透傳消息章節(jié)脐雪。

  • Step6與Step7厌小,Push服務(wù)器檢測到設(shè)備回復(fù)消息響應(yīng)時,將響應(yīng)狀態(tài)回執(zhí)給開發(fā)者战秋,開發(fā)者需實(shí)現(xiàn)消息回執(zhí)接收能力璧亚,請參考服務(wù)端開發(fā)指導(dǎo)章節(jié)。

2. 客戶端開發(fā)指導(dǎo)

本章節(jié)指導(dǎo)開發(fā)者完成Push基礎(chǔ)能力開發(fā)中的客戶端開發(fā)脂信,通過本開發(fā)指導(dǎo)的學(xué)習(xí)能夠幫助開發(fā)者快速掌握客戶端開發(fā)所需的知識技能涨岁,快速體驗(yàn)華為Push服務(wù)〖基礎(chǔ)能力客戶端開發(fā)主要包括如下4個功能點(diǎn):

1梢薪、開發(fā)者集成Push SDK后申請Push Token,請參考申請Push Token章節(jié)尝哆,同時Push SDK 4.0版本我們提供了自動初始化獲取token的能力秉撇,請參考自動初始化章節(jié)

2、開發(fā)者App客戶端接收服務(wù)端推送的Push透傳消息秋泄,請參考接收透傳消息章節(jié)

3琐馆、是否允許NC(Notification Center)顯示通知欄消息,請參考設(shè)置是否顯示通知欄消息章節(jié)

4恒序、自定義點(diǎn)擊消息的動作以及向App傳遞數(shù)據(jù)可以參考點(diǎn)擊通知消息章節(jié)

1瘦麸、調(diào)用getToken方法獲取Token
private void getToken() {
    new Thread() {
        @Override
        public void run() {
            try {
                // read from agconnect-services.json
                String appId = AGConnectServicesConfig.fromContext(this).getString("client/app_id");
                String token = HmsInstanceId.getInstance(this).getToken(appId, "HCM");
                Log.i(TAG, "get token:" + token);
                if(!TextUtils.isEmpty(token)) {
                    sendRegTokenToServer(token);
                }
            } catch (ApiException e) {
                Log.e(TAG, "get token failed, " + e);
            }
        }
    }.start();
}
private void sendRegTokenToServer(String token) {
    Log.i(TAG, "sending token to server. token:" + token);
}

2.3 接收透傳消息

2.3.1 場景介紹

App如果訂閱了主題消息或者服務(wù)器主動推送的透傳消息(包括通知消息前臺展示功能中設(shè)置通知消息由應(yīng)用自己處理,區(qū)別于NC (Notification Center)通知欄消息)歧胁,都需要App通過實(shí)現(xiàn)onMessageReceived回調(diào)方法來接收消息滋饲,收到消息的后續(xù)行為由應(yīng)用自己處理
重寫onMessageReceived 繼承于HmsMessageService所復(fù)寫的方法獲取透傳消息數(shù)據(jù)喊巍。

@Override
public void onMessageReceived(RemoteMessage message) {
    Log.i(TAG, "onMessageReceived is called");
    if (message == null) {
        Log.e(TAG, "Received message entity is null!");
        return;
    }
    Log.i(TAG, "getCollapseKey: " + message.getCollapseKey()
            + "\n getData: " + message.getData()
            + "\n getFrom: " + message.getFrom()
            + "\n getTo: " + message.getTo()
            + "\n getMessageId: " + message.getMessageId()
            + "\n getOriginalUrgency: " + message.getOriginalUrgency()
            + "\n getUrgency: " + message.getUrgency()
            + "\n getSendTime: " + message.getSentTime()
            + "\n getMessageType: " + message.getMessageType()
            + "\n getTtl: " + message.getTtl());
    RemoteMessage.Notification notification = message.getNotification();
    if (notification != null) {
        Log.i(TAG, "\n getImageUrl: " + notification.getImageUrl()
                + "\n getTitle: " + notification.getTitle()
                + "\n getTitleLocalizationKey: " + notification.getTitleLocalizationKey()
                + "\n getTitleLocalizationArgs: " + Arrays.toString(notification.getTitleLocalizationArgs())
                + "\n getBody: " + notification.getBody()
                + "\n getBodyLocalizationKey: " + notification.getBodyLocalizationKey()
                + "\n getBodyLocalizationArgs: " + Arrays.toString(notification.getBodyLocalizationArgs())
                + "\n getIcon: " + notification.getIcon()
                + "\n getSound: " + notification.getSound()
                + "\n getTag: " + notification.getTag()
                + "\n getColor: " + notification.getColor()
                + "\n getClickAction: " + notification.getClickAction()
                + "\n getChannelId: " + notification.getChannelId()
                + "\n getLink: " + notification.getLink()
                + "\n getNotifyId: " + notification.getNotifyId());
    }
    Boolean judgeWhetherIn10s = false;
    // If the messages are not processed in 10 seconds, the app needs to use WorkManager for processing.
    if (judgeWhetherIn10s) {
        startWorkManagerJob(message);
    } else {
        // Process message within 10s
        processWithin10s(message);
    }
}
private void startWorkManagerJob(RemoteMessage message) {
    Log.d(TAG, "Start new job processing.");
}
private void processWithin10s(RemoteMessage message) {
    Log.d(TAG, "Processing now.");
}

2.4 設(shè)置是否顯示通知欄消息

2.4.1 場景介紹

通知消息是由系統(tǒng)直接在通知中心下拉列表呈現(xiàn)的即時消息屠缭。開發(fā)者如果想控制應(yīng)用是否允許顯示通知欄消息,可以調(diào)用HmsMessaging.turnOnPush或者HmsMessaging.turnOffPush接口崭参。如果開發(fā)者不調(diào)用此接口呵曹,系統(tǒng)默認(rèn)是允許顯示通知欄消息。

HmsMessaging.getInstance(context).turnOnPush().addOnCompleteListener(new OnCompleteListener<Void>() {
    @Override
    public void onComplete(Task<Void> task) {
        if (task.isSuccessful()) {
            Log.i(TAG, "turnOnPush Complete");
        } else {
            Log.e(TAG, "turnOnPush failed: ret=" + task.getException().getMessage());
        }
    }
});

2.5 點(diǎn)擊通知消息

關(guān)于通知消息何暮,開發(fā)者可以自定義點(diǎn)擊消息的動作奄喂,包括:打開App首頁、打開特定URL海洼、打開自定義富媒體消息跨新、打開自定義App頁面。其中打開App首頁與自定義App頁面需要開發(fā)者端云協(xié)同開發(fā)來完成贰军,下面我們講下如何實(shí)現(xiàn)這兩種動作并從服務(wù)端接收數(shù)據(jù)玻蝌。

注意:
1蟹肘、點(diǎn)擊動作觸發(fā)打開應(yīng)用首頁或者自定義App頁面,都是通過跨應(yīng)用啟動Activity的方式來實(shí)現(xiàn)俯树,需要保證要拉起的目標(biāo)Activity的exported屬性為true帘腹,即目標(biāo)Activity要對外界公開,并且無權(quán)限保護(hù)许饿,這樣才能啟動成功阳欲。
2、通過通知消息傳遞數(shù)據(jù)給應(yīng)用需要推送服務(wù)App版本為10.0.0及以上陋率。

2.5.1 打開自定義App頁面

打開自定義App頁面有兩種方式球化,一種是通過服務(wù)端REST API指定intent參數(shù),另一種是指定action參數(shù)瓦糟。如果同時指定了兩個參數(shù)筒愚,會優(yōu)先選取使用intent參數(shù)。

指定intent參數(shù)

跨應(yīng)用啟動Activity必須使用顯式intent方式菩浙,通過intent可以攜帶額外的數(shù)據(jù)給客戶端App
1巢掺、intent參數(shù)生成
在AndroidStudio工程中參照如下代碼生成intent。

Intent intent = new Intent(Intent.ACTION_VIEW);
// Scheme協(xié)議(pushscheme://com.huawei.codelabpush/deeplink?)需要開發(fā)者自定義比如:`"wandapushscheme://com.cc.pushallsdk/wandanotify?`content=thisistest")
intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?"));
// 往intent中添加參數(shù)劲蜻,用戶可以根據(jù)自己的需求進(jìn)行添加參數(shù)
intent.putExtra("name", "abc");
intent.putExtra("age", 180);
// 必須帶上該Flag
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME);
// 打印出的intentUri值就是設(shè)置到推送消息中intent字段的值
Log.d("intentUri", intentUri);

intentUri

開發(fā)者傳參有兩種方法:這些通過本地寫獲取得到intentUri給到服務(wù)端或者網(wǎng)頁端進(jìn)行傳輸
方法1:參數(shù)之間用“&”相連陆淀,其中參數(shù)name=abc與age=180兩個參數(shù)之間用“&”相連。例如:

intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?name=abc&age=180"));

方法2:intent直接添加參數(shù):

intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?"));
intent.putExtra("name", "abc");
intent.putExtra("age", 180);

2先嬉、App服務(wù)端消息體中指定intent值

服務(wù)端如何發(fā)送消息請參考服務(wù)端開發(fā)指導(dǎo)轧苫。消息體樣例:

{
    "message": {
        "data": "{'score':'7','time': '16:42'}",
        "notification": {
            "title": "message title",
            "body": "message body"
        },
        "android": {
            "data":"{'androidData':'7','time':'16:42'}",
            "notification": {
                "click_action": {
                    "type": 1,
                    "intent": "intent://com.huawei.codelabpush/deeplink?#Intent;scheme=pushscheme;launchFlags=0x4000000;i.age=180;S.name=abc;end"
                }
            }
        },
        "token": [
            "pushtoken1"
        ]
    }
}

3、客戶端AndroidManifest.xml文件注冊待啟動的Activity類
參照如下配置注冊自定義的Activity疫蔓,其中host含懊、path、scheme需與步驟1中協(xié)議的配置相對應(yīng)鳄袍,否則不能跳轉(zhuǎn)到指定的界面绢要。

<activity android:name=".DeeplinkActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:host="com.huawei.codelabpush"
            android:path="/deeplink"
            android:scheme="pushscheme" />
    </intent-filter>
</activity>

自動初始化1

<application    
    <meta-data       
        android:name="push_kit_auto_init_enabled"        
        android:value="true" />
</application>

自動初始化2

方式2
應(yīng)用顯式調(diào)用HmsMessaging.setAutoInitEnabled(boolean enable)方法,設(shè)置為true即為啟用了自動初始化拗小,反之為未啟用樱哼。設(shè)置后值會保存在應(yīng)用本地的shared_prefs目錄下的文件中。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末阅束,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子茄唐,更是在濱河造成了極大的恐慌息裸,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件年扩,死亡現(xiàn)場離奇詭異,居然都是意外死亡访圃,警方通過查閱死者的電腦和手機(jī)厨幻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來况脆,“玉大人批糟,你說我怎么就攤上這事∈⒛” “怎么了纬傲?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長算墨。 經(jīng)常有香客問我汁雷,道長,這世上最難降的妖魔是什么挖藏? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任厢漩,我火速辦了婚禮,結(jié)果婚禮上宵膨,老公的妹妹穿的比我還像新娘炸宵。我一直安慰自己,他們只是感情好土全,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著末秃,像睡著了一般拨黔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上篱蝇,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天零截,我揣著相機(jī)與錄音,去河邊找鬼哪工。 笑死弧哎,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的偎捎。 我是一名探鬼主播序攘,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼丈牢!你這毒婦竟也來了瞄沙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肮疗,沒想到半個月后扒接,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體们衙,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒙挑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年忆蚀,在試婚紗的時候發(fā)現(xiàn)自己被綠了姑裂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡欣鳖,死狀恐怖茴厉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情怀酷,我是刑警寧澤嗜闻,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布泞辐,位于F島的核電站,受9級特大地震影響咐吼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜厢塘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一晚碾、第九天 我趴在偏房一處隱蔽的房頂上張望格嘁。 院中可真熱鬧廊移,春花似錦探入、人聲如沸懂诗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽离唐。三九已至,卻和暖如春胖喳,著一層夾襖步出監(jiān)牢的瞬間贮竟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工技健, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惰拱,地道東北人。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像昔逗,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子婆排,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評論 2 349