ShareSDK实现第三方登录和分享(Android)

第三方登录和分享是很常见的功能,现在开发的每个APP基本上都会用到,所以有一套快速集成方案能提高开发效率,我们公司使用的是 ShareSDK,下面记录集成 ShareSDK 和实现最常见的微信、微博、QQ的登录和分享。

注册

首先我们需要注册 ShareSDK 账号并添加一个新应用。

Paste_Image.png

集成SDK

申请 ShareSDK 的 appkey 成功之后,我们就可以把SDK集成到项目中: ShareSDK for Android 快速集成

第一步:下载SDK

目前最新的是 2017-03-27 更新的 v2.8.2 ,选中自己需要的平台点击下载就可以了,右上角可以下载DEMO源码。


Paste_Image.png

使用 ShareSDK 提供的工具可以快速生成我们需要的资源文件:

Paste_Image.png
Paste_Image.png

第二步:集成到项目中

把工具生成的文件都放到我们自己的项目中:

Paste_Image.png
① 添加依赖包,把 res 里面的文件拷贝到项目中
Paste_Image.png
② 在 assets 下添加ShareSDK.xml
Paste_Image.png

这里以微信、微博和QQ第三方登录和分享为例,在 ShareSDK.xml 里面分别改成自己申请的第三方平台 key。ShareSDK 的 AppKey 也可以在这里配置,这样在代码中初始化时就不需要传参数。

<ShareSDK
    AppKey="你的ShareSDK AppKey"/> <!-- 修改成你在sharesdk后台注册的应用的appkey"-->

<!-- ShareByAppClient标识是否使用微博客户端分享,默认是false -->
<SinaWeibo
    Id="1"
    SortId="1"
    AppKey="你的新浪微博 AppKey"
    AppSecret="你的新浪微博 AppSecret"
    RedirectUrl="https://api.weibo.com/oauth2/default.html"
    ShareByAppClient="true"
    Enable="true" />

<QZone
    Id="3"
    SortId="3"
    AppId="你的腾讯 AppId"
    AppKey="你的腾讯 AppKey"
    Enable="true" />

<!-- 
    Wechat微信和WechatMoments微信朋友圈的appid是一样的;

                   注意:开发者不能用我们这两个平台的appid,否则分享不了

      微信测试的时候,微信测试需要先签名打包出apk,
    sample测试微信,要先签名打包,keystore在sample项目中,密码123456
    
    BypassApproval是绕过审核的标记,设置为true后AppId将被忽略,故不经过
    审核的应用也可以执行分享,但是仅限于分享文字和图片,不能分享其他类型,
    默认值为false。此外,微信收藏不支持此字段。
-->
<Wechat
    Id="4"
    SortId="4"
    AppId="你的微信 AppId"
    AppSecret="你的微信 AppSecret"
    BypassApproval="false"
    Enable="true" />

<!-- ShareByAppClient标识是否使用微博客户端分享,默认是false -->
<QQ
    Id="7"
    SortId="7"
    AppId="你的腾讯 AppId"
    AppKey="你的腾讯 AppKey"
    ShareByAppClient="true"
    Enable="true" />
③ 配置AndroidManifest

添加权限:

<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<!-- 蓝牙分享所需的权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

添加 ShareSDK 必要的 activity :

<!-- 微信 -->
<activity
    android:name=".wxapi.WXEntryActivity"
    android:configChanges="keyboardHidden|orientation|screenSize"
    android:exported="true"
    android:screenOrientation="portrait"
    android:theme="@android:style/Theme.Translucent.NoTitleBar" />

<activity
    android:name="com.mob.tools.MobUIShell"
    android:theme="@android:style/Theme.Translucent.NoTitleBar"
    android:configChanges="keyboardHidden|orientation|screenSize"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateHidden|adjustResize" >
    <!-- QQ和QQ空间分享 QQ登录的回调必须要配置的 -->
    <intent-filter>
        <data android:scheme="tencent100371282" />
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.BROWSABLE" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>

    <!-- 新浪微博客户端分享回调必须配置 -->
    <intent-filter>
        <action android:name="com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

AndroidManifest 里面的内容都不要改,直接复制就可以,特别是 微信 ,之前就在这里吃过亏。

④ 微信需要注意的地方

要正常使用微信功能,我们还要添加微信的回调 activity,直接把工具生成的文件拷贝进去就可以,WXEntryActivity.java 的路径必须是
包名.wxapi.WXEntryActivity
这里的包名指的是 Application Id 而不是 package。

Paste_Image.png

代码中使用 ShareSDK

第三方登录的代码:

package com.simple.activity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;

import java.util.HashMap;

import butterknife.BindView;
import butterknife.OnClick;
import cn.simple.R;
import cn.sharesdk.framework.Platform;
import cn.sharesdk.framework.PlatformActionListener;
import cn.sharesdk.framework.PlatformDb;
import cn.sharesdk.framework.ShareSDK;
import cn.sharesdk.sina.weibo.SinaWeibo;
import cn.sharesdk.tencent.qq.QQ;
import cn.sharesdk.wechat.friends.Wechat;


/**
 * 登录界面
 * 作者: JairusTse
 * 日期: 17/2/24 14:53
 */
public class LoginActivity extends AppCompatActivity implements PlatformActionListener {

    @BindView(R.id.img_qq)
    ImageView imgQq;
    @BindView(R.id.img_weixin)
    ImageView imgWeixin;
    @BindView(R.id.img_weibo)
    ImageView imgWeibo;

    private PlatformDb platDB; //平台授权数据DB

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_login);
        //初始化shareSDK,如果没有在ShareSDK.xml中设置appkey,需要在这里传参数
        ShareSDK.initSDK(this);
    }

    //第三方授权登录
    private void authorize(Platform plat) {

        if (plat == null) {
            return;
        }

        //判断指定平台是否已经完成授权
        if(plat.isAuthValid()) {
            String token = plat.getDb().getToken();
            String userId = plat.getDb().getUserId();
            String name = plat.getDb().getUserName();
            String gender = plat.getDb().getUserGender();
            String headImageUrl = plat.getDb().getUserIcon();
            String platformNname = plat.getDb().getPlatformNname();
            if (userId != null) {

                //已经授权过,直接下一步操作
                if(platformNname.equals(SinaWeibo.NAME)) {
                    //微博授权
                } else if(platformNname.equals(QQ.NAME)) {
                    //QQ授权
                } else if(platformNname.equals(Wechat.NAME)) {
                    //微信授权
                }
                return;
            }
        }

        // true不使用SSO授权,false使用SSO授权
        plat.SSOSetting(false);
        plat.setPlatformActionListener(this);
        plat.authorize();

        //获取用户资料
        plat.showUser(null);
    }

    //授权成功回调
    @Override
    public void onComplete(Platform platform, int i, HashMap<String, Object> hashMap) {
        String headImageUrl = null;//头像
        String userId;//userId
        String token;//token
        String gender;//性别
        String name = null;//用户名

        if (i == Platform.ACTION_USER_INFOR) {

            platDB = platform.getDb(); // 获取平台数据DB

            if (platform.getName().equals(Wechat.NAME)) {
                //微信登录

                // 通过DB获取各种数据
                token = platDB.getToken();
                userId = platDB.getUserId();
                name = platDB.getUserName();
                gender = platDB.getUserGender();
                headImageUrl = platDB.getUserIcon();
                if ("m".equals(gender)) {
                    gender = "1";
                } else {
                    gender = "2";
                }

            } else if (platform.getName().equals(SinaWeibo.NAME)) {
                // 微博登录

                token = platDB.getToken();
                userId = platDB.getUserId();
                name = hashMap.get("nickname").toString(); // 名字
                gender = hashMap.get("gender").toString(); // 年龄
                headImageUrl = hashMap.get("figureurl_qq_2").toString(); // 头像figureurl_qq_2 中等图,figureurl_qq_1缩略图

            } else if (platform.getName().equals(QQ.NAME)) {
                // QQ登录

                token = platDB.getToken();
                userId = platDB.getUserId();
                name = hashMap.get("nickname").toString(); // 名字
                gender = hashMap.get("gender").toString(); // 年龄
                headImageUrl = hashMap.get("figureurl_qq_2").toString(); // 头像figureurl_qq_2 中等图,figureurl_qq_1缩略图

            }
        }
    }

    //授权出错回调
    @Override
    public void onError(Platform platform, int i, Throwable throwable) {

    }

    //取消授权回调
    @Override
    public void onCancel(Platform platform, int i) {

    }

    @Override
    protected void onDestroy() {
        ShareSDK.stopSDK(this);
        super.onDestroy();
    }

    @OnClick({R.id.img_qq, R.id.img_weixin, R.id.img_weibo})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.img_qq: {
                // qq登录
                Platform qq = ShareSDK.getPlatform(QQ.NAME);
                authorize(qq);
                break;
            }
            case R.id.img_weixin: {
                // 微信登录
                Platform wechat = ShareSDK.getPlatform(Wechat.NAME);
                authorize(wechat);
                break;
            }
            case R.id.img_weibo: {
                // 微博登录
                Platform weibo = ShareSDK.getPlatform(SinaWeibo.NAME);
                authorize(weibo);
                break;
            }
        }
    }
}

第三方分享的代码:

package com.simple.activity;

import android.Manifest;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import com.tbruyelle.rxpermissions.Permission;
import com.tbruyelle.rxpermissions.RxPermissions;
import com.example.util.ShareSDKUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import butterknife.BindView;
import butterknife.OnClick;
import cn.simple.R;
import cn.sharesdk.framework.ShareSDK;
import rx.functions.Action1;

/**
 * ShareSDK第三方分享界面
 * 作者: JairusTse
 * 日期: 17/2/28 15:16
 */
public class AuthShareActivity extends AppCompatActivity {

    @BindView(R.id.title)
    TextView title;
    @BindView(R.id.img_title)
    ImageView imgTitle;
    @BindView(R.id.tv_left)
    TextView tvLeft;
    @BindView(R.id.right_btn)
    ImageButton rightBtn;

    /** 微信 **/
    public static final String AUTH_WECHAT = "wechat";
    /** QQ **/
    public static final String AUTH_QQ = "qq";
    /** QQ空间 **/
    public static final String AUTH_QQ_ZONE = "qq_zone";
    /** 朋友圈 **/
    public static final String AUTH_MOMENT = "moment";

    private String share_title = "分享标题";
    private String share_text = "分享内容";
    private String share_url = "https://http://www.jianshu.com/p/36aca90d588d"; //分享链接
    private String share_icon = Environment.getDataDirectory().getAbsolutePath() +
            File.separator + "myapp" + File.separator + "icon.png"; //分享缩略图在SD卡的路径

    private RxPermissions rxPermissions; //检测权限

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        setContentView(R.layout.activity_account_center);

        rxPermissions = new RxPermissions(this);
        ShareSDK.initSDK(this);
    }

    /**
     * 检查分享的缩略图是否存在SD卡中,没有就保存到SD卡
     * @param img_id 图片资源id
     */
    private void checkImage(int img_id) {
        File icon = new File(share_icon);
        if(!icon.exists()) {
            saveBitmap(share_icon, BitmapFactory.decodeResource(getResources(), img_id));
        }
    }

    /**
     * 保存Bitmap到本地
     * @param path 保存文件路径
     * @param mBitmap 图片Bitmap
     */
    public static void saveBitmap(String path, Bitmap mBitmap) {

        File f = new File(path);
        try {
            f.createNewFile();
        } catch (Exception e) {
            e.printStackTrace();
        }
        FileOutputStream fOut = null;
        try {
            fOut = new FileOutputStream(f);
            mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
            fOut.flush();
            fOut.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 第三方分享
     * @param share_type 分享类型
     */
    private void auth_share(final String share_type) {
        //保存图片需要访问SD卡权限,分享到QQ和QQ空间也需要访问SD卡权限
        rxPermissions.requestEach(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .subscribe(new Action1<Permission>() {
                    @Override
                    public void call(Permission permission) {
                        if(permission.granted) {

                            //分享的图片要先保存到sd卡
                            checkImage(R.drawable.ic_launcher);

                            switch (share_type) {
                                case AUTH_WECHAT:
                                    //分享到微信
                                    ShareSDKUtil.shareWX(share_title, URL_SHARE, share_text, share_icon);
                                    break;
                                case AUTH_QQ:
                                    //分享到QQ好友
                                    ShareSDKUtil.shareQQ(share_title, URL_SHARE, share_text, share_icon);
                                    break;
                                case AUTH_QQ_ZONE:
                                    //分享到QQ空间
                                    ShareSDKUtil.shareQzone(share_title, URL_SHARE, share_text, share_icon);
                                    break;
                                case AUTH_MOMENT:
                                    //分享到朋友圈
                                    ShareSDKUtil.shareWXM(share_title, URL_SHARE, share_text, share_icon);
                                    break;
                            }

                        } else if(permission.shouldShowRequestPermissionRationale == true){
                            //禁止授权
                        } else if(permission.shouldShowRequestPermissionRationale == false){
                            //禁止授权且不再询问
                        }
                    }
                });
    }

    @OnClick({R.id.btn_moment, R.id.btn_qq, R.id.btn_qq_zone, R.id.btn_wechat})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_moment:
                auth_share(AUTH_MOMENT);
                break;
            case R.id.btn_qq:
                auth_share(AUTH_QQ);
                break;
            case R.id.btn_qq_zone:
                auth_share(AUTH_QQ_ZONE);
                break;
            case R.id.btn_wechat:
                auth_share(AUTH_WECHAT);
                break;
        }
    }
}


工具类ShareSDKUtil :

package com.example.util;

import android.util.Log;

import java.util.HashMap;

import cn.sharesdk.framework.Platform;
import cn.sharesdk.framework.PlatformActionListener;
import cn.sharesdk.framework.ShareSDK;
import cn.sharesdk.tencent.qq.QQ;
import cn.sharesdk.tencent.qzone.QZone;
import cn.sharesdk.wechat.friends.Wechat;
import cn.sharesdk.wechat.moments.WechatMoments;

/**
 * 作者:JairusTse
 * 日期: 17/4/11
 */

public class ShareSDKUtil {
    private static String type="";
   
    /**
     *
     * @param title 标题
     * @param titleUrl title链接
     * @param text 内容
     * @param imagePath 图片本地路径
     */
    public static void shareQzone(String title, String titleUrl, String text, String imagePath){
        type="share";

        Platform.ShareParams sp = new Platform.ShareParams();
        sp.setTitle(title);
        sp.setTitleUrl(titleUrl); // 标题的超链接
        sp.setText(text);
        sp.setImagePath(imagePath);

        Platform qzone = ShareSDK.getPlatform (QZone.NAME);
        // 设置分享事件回调(注:回调放在不能保证在主线程调用,不可以在里面直接处理UI操作)
        qzone.setPlatformActionListener(mPlatformActionListener);
        // 执行图文分享
        qzone.share(sp);

    }

    /**
     * QQ
     * @param title
     * @param titleUrl
     * @param text
     * @param imagePath
     */
    public static void shareQQ(String title, String titleUrl, String text, String imagePath){
        type="share";
        QQ.ShareParams sp=new QQ.ShareParams();
        sp.setTitle(title);
        sp.setText(text);
        if(titleUrl!=null){
            sp.setTitleUrl(titleUrl); // 标题的超链接
        }
        if(imagePath!=null){
            sp.setImageUrl(imagePath);
        }
        Platform qq = ShareSDK.getPlatform(QQ.NAME);
        qq. setPlatformActionListener (mPlatformActionListener); // 设置分享事件回调
        // 执行图文分享
        qq.share(sp);
    }

    /**
     * 朋友圈
     * @param title
     * @param titleUrl
     * @param text
     * @param imagePath
     */
    public static void shareWXM(String title, String titleUrl, String text, String imagePath){
        type="share";
        WechatMoments.ShareParams sp = new WechatMoments.ShareParams();
        sp.setTitle(title);
        sp.setText(text);
        if(titleUrl!=null){
            sp.setTitleUrl(titleUrl); // 标题的超链接
        }
        if(imagePath!=null){
            sp.setImagePath(imagePath);
        }
        sp.setShareType(Platform.SHARE_WEBPAGE);
        sp.setUrl(titleUrl);
        Platform moments = ShareSDK.getPlatform(WechatMoments.NAME);
        moments. setPlatformActionListener (mPlatformActionListener); // 设置分享事件回调
        // 执行图文分享
        moments.share(sp);
    }
    /**
     * 微信
     * @param title
     * @param titleUrl
     * @param text
     * @param imagePath
        Platform.SHARE_TEXT(分享文本),
        Platform.SHARE_IMAGE(分享图片),
        Platform.SHARE_WEBPAGE(分享网页,既图文分享),
        Platform.SHARE_MUSIC(分享音频),
        Platform.SHARE_VIDEO(分享视频),
        Platform.SHARE_APPS(分享应用,仅微信支持),
        Platform.SHARE_FILE(分享文件,仅微信支持)
        Platform.SHARE_EMOJI(分享表情,仅微信支持)
     */
    public static void shareWX(String title, String titleUrl, String text, String imagePath){
        type="share";
        Wechat.ShareParams sp=new Wechat.ShareParams();
        sp.setTitle(title);
        sp.setText(text);
        if(titleUrl!=null){
            sp.setTitleUrl(titleUrl); // 标题的超链接
        }
        if(imagePath!=null){
            sp.setImagePath(imagePath);
        }
        sp.setShareType(Platform.SHARE_WEBPAGE);
        sp.setUrl(titleUrl);
        Platform wx = ShareSDK.getPlatform (Wechat.NAME);
        wx. setPlatformActionListener (mPlatformActionListener); // 设置分享事件回调
        // 执行图文分享
        wx.share(sp);
    }

    public static PlatformActionListener mPlatformActionListener = new PlatformActionListener() {
        @Override
        public void onComplete(Platform platform, int i, HashMap<String, Object> hashMap) {
            if(type.equals("login")){
                Log.e("onComplete","登录成功");
                Log.e("openid",platform.getDb().getUserId());//拿到登录后的openid
                Log.e("username",platform.getDb().getUserName());//拿到登录用户的昵称
            }else{
                Log.e("onComplete","分享成功");
            }
        }
        @Override
        public void onError(Platform platform, int i, Throwable throwable) {
            Log.e("onError",throwable.toString()+"");
            if(type.equals("login")){
                Log.e("onError","登录失败"+throwable.toString());
            }else{
                Log.e("onError","分享失败"+throwable.toString());
            }
        }
        @Override
        public void onCancel(Platform platform, int i) {
            if(type.equals("login")){
                Log.e("onCancel","登录取消");
            }else{
                Log.e("onCancel","分享取消");
            }
        }
    };
}


有两个需要注意的地方:

  • 分享到QQ好友和QQ空间需要访问存储权限,我用的是RxPermissions,具体用法可以看下我另外一篇博客:Android 6.0 运行时权限
  • 设置分享的缩略图要用本地SD卡的图片,如果用图片url分享出去是不能正常显示的,但是我们经常会使用项目里面的资源图片,所以需要先把资源图片保存到SD卡中,上面的例子也提供了把资源图片保存到SD卡的方法,同样要注意权限的判断。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容