Android手機拍照或從本地相冊選取圖片設(shè)置頭像剂陡。適配小米、華為狐胎、7.0

新版-Android手機拍照或從本地相冊選取圖片設(shè)置頭像高版本適配

傳送門
https://github.com/jiaweizeng/BalaPortrait
設(shè)置頭像通常有兩種方式:

1鸭栖,讓用戶通過選擇本地相冊之類的圖片庫中已有的圖像,裁剪后作為頭像握巢。

2晕鹊,讓用戶啟動手機的相機拍照,拍完照片后裁剪,然后作為頭像溅话。

代碼如下
MainActivity.Java文件:

package portrait.bala.portrait;

import android.Manifest;
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;

public class MainActivity extends AppCompatActivity {

    /* 頭像文件 */
    private static final String IMAGE_FILE_NAME = "temp_head_image.jpg";
    private static final String CROP_IMAGE_FILE_NAME = "bala_crop.jpg";
    /* 請求識別碼 */
    private static final int CODE_GALLERY_REQUEST = 0xa0;
    private static final int CODE_CAMERA_REQUEST = 0xa1;
    private static final int CODE_RESULT_REQUEST = 0xa2;

    // 裁剪后圖片的寬(X)和高(Y),480 X 480的正方形。
    private static int output_X = 480;
    private static int output_Y = 480;
    //改變頭像的標記位
    private int new_icon=0xa3;
    private ImageView headImage = null;
    private String mExtStorDir;
    private Uri mUriPath;

    private final int PERMISSION_READ_AND_CAMERA =0;//讀和相機權(quán)限
    private final int PERMISSION_READ =1;//讀取權(quán)限
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mExtStorDir = Environment.getExternalStorageDirectory().toString();
        headImage = (ImageView) findViewById(R.id.imageView);

        Button buttonLocal = (Button) findViewById(R.id.buttonLocal);
        buttonLocal.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
//                choseHeadImageFromGallery();
                checkReadPermission();

            }
        });

        Button buttonCamera = (Button) findViewById(R.id.buttonCamera);
        buttonCamera.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
//                choseHeadImageFromCameraCapture();
                checkStoragePermission();//檢查是否有權(quán)限
            }
        });
    }



    // 從本地相冊選取圖片作為頭像
    private void choseHeadImageFromGallery() {
        // 設(shè)置文件類型    (在華為手機中不能獲取圖片飞几,要替換代碼)
        /*Intent intentFromGallery = new Intent();
        intentFromGallery.setType("image*//*");
        intentFromGallery.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(intentFromGallery, CODE_GALLERY_REQUEST);*/

        Intent intentFromGallery = new Intent(Intent.ACTION_PICK, null);
        intentFromGallery.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
        startActivityForResult(intentFromGallery, CODE_GALLERY_REQUEST);

    }

    // 啟動手機相機拍攝照片作為頭像
    private void choseHeadImageFromCameraCapture() {
        String savePath = mExtStorDir;

        Intent intent = null;
        // 判斷存儲卡是否可以用砚哆,可用進行存儲

        if (hasSdcard()) {
            //設(shè)定拍照存放到自己指定的目錄,可以先建好
            File file = new File(savePath);
            if (!file.exists()) {
                file.mkdirs();
            }
            Uri pictureUri;
            File pictureFile = new File(savePath, IMAGE_FILE_NAME);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                pictureUri = FileProvider.getUriForFile(this, getPackageName()+".fileProvider", pictureFile);
    /*ContentValues contentValues = new ContentValues(1);
    contentValues.put(MediaStore.Images.Media.DATA, pictureFile.getAbsolutePath());
    pictureUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);*/
            } else {
                intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                pictureUri = Uri.fromFile(pictureFile);
            }
            /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                ContentValues contentValues = new ContentValues(1);
                contentValues.put(MediaStore.Images.Media.DATA, pictureFile.getAbsolutePath());
                pictureUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
            } else {
                intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                pictureUri = Uri.fromFile(pictureFile);
            }*/
            if (intent != null) {
                intent.putExtra(MediaStore.EXTRA_OUTPUT,
                        pictureUri);
                startActivityForResult(intent, CODE_CAMERA_REQUEST);
            }
        }
    }

    public Uri getImageContentUri(File imageFile) {
        String filePath = imageFile.getAbsolutePath();
        Cursor cursor = getContentResolver().query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                new String[] { MediaStore.Images.Media._ID },
                MediaStore.Images.Media.DATA + "=? ",
                new String[] { filePath }, null);

        if (cursor != null && cursor.moveToFirst()) {
            int id = cursor.getInt(cursor
                    .getColumnIndex(MediaStore.MediaColumns._ID));
            Uri baseUri = Uri.parse("content://media/external/images/media");
            return Uri.withAppendedPath(baseUri, "" + id);
        } else {
            if (imageFile.exists()) {
                ContentValues values = new ContentValues();
                values.put(MediaStore.Images.Media.DATA, filePath);
                return getContentResolver().insert(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            } else {
                return null;
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode,
                                    Intent intent) {

        // 用戶沒有進行有效的設(shè)置操作,返回
        if (resultCode == RESULT_CANCELED) {
            Toast.makeText(getApplication(), "取消", Toast.LENGTH_LONG).show();
            return;
        }

        switch (requestCode) {
            case CODE_GALLERY_REQUEST:
                cropRawPhoto(intent.getData());
                break;

            case CODE_CAMERA_REQUEST:
                if (hasSdcard()) {
                    File tempFile = new File(
                            Environment.getExternalStorageDirectory(),
                            IMAGE_FILE_NAME);
//                    cropRawPhoto(Uri.fromFile(tempFile));
                    cropRawPhoto(getImageContentUri(tempFile));
                } else {
                    Toast.makeText(getApplication(), "沒有SDCard!", Toast.LENGTH_LONG)
                            .show();
                }

                break;

            case CODE_RESULT_REQUEST:
                /*if (intent != null) {
                    setImageToHeadView(intent);    //此代碼在小米有異常屑墨,換以下代碼
                }*/
                try {
                    Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(mUriPath));
                    setImageToHeadView(intent,bitmap);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }

                break;
        }

        super.onActivityResult(requestCode, resultCode, intent);
    }

    private void checkStoragePermission() {
        int result = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        int resultCAMERA = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
        if (result == PackageManager.PERMISSION_DENIED||resultCAMERA == PackageManager.PERMISSION_DENIED) {
            String[] permissions = {/*Manifest.permission.WRITE_EXTERNAL_STORAGE
                    ,*/Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE};
            ActivityCompat.requestPermissions(this, permissions, PERMISSION_READ_AND_CAMERA);
        } else {
            choseHeadImageFromCameraCapture();
        }
    }


    private void checkReadPermission() {
        int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
        if (permission==PackageManager.PERMISSION_DENIED){
            String[] permissions ={Manifest.permission.READ_EXTERNAL_STORAGE};
            ActivityCompat.requestPermissions(this,permissions, PERMISSION_READ);
        }else {
            choseHeadImageFromGallery();
        }

    }

    //權(quán)限申請回調(diào)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        switch (requestCode){
            case PERMISSION_READ_AND_CAMERA:
                for (int i=0;i<grantResults.length;i++){
                    if (grantResults[i]==PackageManager.PERMISSION_DENIED){
                        Toast.makeText(this, "why ??????", Toast.LENGTH_SHORT).show();
                        return;
                    }
                }
                choseHeadImageFromCameraCapture();
                break;
            case PERMISSION_READ:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    choseHeadImageFromGallery();
                }
                break;
        }

    }
    /**
     * 裁剪原始的圖片
     */
    public void cropRawPhoto(Uri uri) {

        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");

        // 設(shè)置裁剪
        intent.putExtra("crop", "true");

        // aspectX , aspectY :寬高的比例
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);

        // outputX , outputY : 裁剪圖片寬高
        intent.putExtra("outputX", output_X);
        intent.putExtra("outputY", output_Y);
        intent.putExtra("return-data", true);

        //startActivityForResult(intent, CODE_RESULT_REQUEST); //直接調(diào)用此代碼在小米手機有異常躁锁,換以下代碼
        String mLinshi = System.currentTimeMillis() + CROP_IMAGE_FILE_NAME;
        File mFile = new File(mExtStorDir, mLinshi);
//        mHeadCachePath = mHeadCacheFile.getAbsolutePath();

        mUriPath = Uri.parse("file://" + mFile.getAbsolutePath());
        //將裁剪好的圖輸出到所建文件中
        intent.putExtra(MediaStore.EXTRA_OUTPUT, mUriPath);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        //注意:此處應(yīng)設(shè)置return-data為false,如果設(shè)置為true卵史,是直接返回bitmap格式的數(shù)據(jù)战转,耗費內(nèi)存。設(shè)置為false以躯,然后槐秧,設(shè)置裁剪完之后保存的路徑,即:intent.putExtra(MediaStore.EXTRA_OUTPUT, uriPath);
//        intent.putExtra("return-data", true);
        intent.putExtra("return-data", false);
//        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        startActivityForResult(intent, CODE_RESULT_REQUEST);
    }

    /**
     * 提取保存裁剪之后的圖片數(shù)據(jù)寸潦,并設(shè)置頭像部分的View
     */
    private void setImageToHeadView(Intent intent,Bitmap b) {
        /*Bundle extras = intent.getExtras();
        if (extras != null) {
            Bitmap photo = extras.getParcelable("data");
            headImage.setImageBitmap(photo);
        }*/
        try {
            if (intent != null) {

//                Bitmap bitmap = imageZoom(b);//看個人需求,可以不壓縮
                headImage.setImageBitmap(b);
//                long millis = System.currentTimeMillis();
                /*File file = FileUtil.saveFile(mExtStorDir, millis+CROP_IMAGE_FILE_NAME, bitmap);
                if (file!=null){
                    //傳遞新的頭像信息給我的界面
                    Intent ii = new Intent();
                    setResult(new_icon,ii);
                    Glide.with(this).load(file).apply(RequestOptions.circleCropTransform())
//                                .apply(RequestOptions.fitCenterTransform())
                            .apply(RequestOptions.placeholderOf(R.mipmap.user_logo)).apply(RequestOptions.errorOf(R.mipmap.user_logo))
                            .into(mIvTouxiangPersonal);
//                uploadImg(mExtStorDir,millis+CROP_IMAGE_FILE_NAME);
                    uploadImg(mExtStorDir,millis+CROP_IMAGE_FILE_NAME);
                }*/

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 檢查設(shè)備是否存在SDCard的工具方法
     */
    public static boolean hasSdcard() {
        String state = Environment.getExternalStorageState();
        if (state.equals(Environment.MEDIA_MOUNTED)) {
            // 有存儲的SDCard
            return true;
        } else {
            return false;
        }
    }

    private Bitmap imageZoom(Bitmap bitMap) {
        //圖片允許最大空間   單位:KB
        double maxSize =1000.00;
        //將bitmap放至數(shù)組中社痛,意在bitmap的大屑(與實際讀取的原文件要大)
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitMap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] b = baos.toByteArray();
        //將字節(jié)換成KB
        double mid = b.length/1024;
        //判斷bitmap占用空間是否大于允許最大空間  如果大于則壓縮 小于則不壓縮
        if (mid > maxSize) {
            //獲取bitmap大小 是允許最大大小的多少倍
            double i = mid / maxSize;
            //開始壓縮  此處用到平方根 將寬帶和高度壓縮掉對應(yīng)的平方根倍 (1.保持刻度和高度和原bitmap比率一致,壓縮后也達到了最大大小占用空間的大兴獍А)
            bitMap = zoomImage(bitMap, bitMap.getWidth() / Math.sqrt(i),
                    bitMap.getHeight() / Math.sqrt(i));
        }
        return bitMap;
    }

    /***
     * 圖片的縮放方法
     *
     * @param bgimage
     *            :源圖片資源
     * @param newWidth
     *            :縮放后寬度
     * @param newHeight
     *            :縮放后高度
     * @return
     */
    public static Bitmap zoomImage(Bitmap bgimage, double newWidth,
                                   double newHeight) {
        // 獲取這個圖片的寬和高
        float width = bgimage.getWidth();
        float height = bgimage.getHeight();
        // 創(chuàng)建操作圖片用的matrix對象
        Matrix matrix = new Matrix();
        // 計算寬高縮放率
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 縮放圖片動作
        matrix.postScale(scaleWidth, scaleHeight);
        Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width,
                (int) height, matrix, true);
        return bitmap;
    }
}


布局文件有三個組件:放置頭像的ImageView斩箫,兩個Button,其中一個Button觸發(fā)從本地相冊選取圖片作為頭像的操作時間撵儿;另外一個Button觸發(fā)手機拍攝照片作為頭像的操作事件乘客。activity_main.xml:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher" />

    <Button
        android:id="@+id/buttonLocal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="本地相冊選取頭像" />

    <Button
        android:id="@+id/buttonCamera"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="手機拍照選取頭像" />

</LinearLayout>

還要權(quán)限動態(tài)申請 WRITE_EXTERNAL_STORAGE

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

解決7.0 不能直接暴露獲取SD卡路徑的方法
在清單文件中添加provider,

FileUriExposedException

https://developer.android.google.cn/reference/android/os/FileUriExposedException.html

FileProvider

https://developer.android.google.cn/reference/android/support/v4/content/FileProvider.html

創(chuàng)建XML文件夾

file_paths.xml


<paths>
    <external-path path="Android/data/portrait.bala.portrait/" name="files_root" />
    <external-path path="." name="external_storage_root" />
  <external-path name="external_files" path="."/>
</paths>

或者

<paths>
  <external-path name="external_files" path="."/>
</paths>
要修改包名
<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="portrait.bala.portrait.fileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"/>
        </provider>

在application類中添加如下代碼

StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
if (Build.VERSION.SDK_INT >= 18){

    builder.detectFileUriExposure();
}
StrictMode.setVmPolicy(builder.build());

FileUtil

public class FileUtil {
    /**
     * 獲取目錄文件大小
     *
     * @param dir
     * @return
     */
    public static long getDirSize(File dir) {
        if (dir == null) {
            return 0;
        }
        if (!dir.isDirectory()) {
            return 0;
        }
        long dirSize = 0;
        File[] files = dir.listFiles();
        for (File file : files) {
            if (file.isFile()) {
                dirSize += file.length();
            } else if (file.isDirectory()) {
                dirSize += file.length();
                dirSize += getDirSize(file); // 遞歸調(diào)用繼續(xù)統(tǒng)計
            }
        }
        return dirSize;
    }

    /**
     * 轉(zhuǎn)換文件大小
     *
     * @param fileS
     * @return B/KB/MB/GB
     */
    public static String formatFileSize(long fileS) {
        java.text.DecimalFormat df = new java.text.DecimalFormat("#.00");
        String fileSizeString = "";
        if (fileS < 1024) {
            fileSizeString = df.format((double) fileS) + "B";
        } else if (fileS < 1048576) {
            fileSizeString = df.format((double) fileS / 1024) + "KB";
        } else if (fileS < 1073741824) {
            fileSizeString = df.format((double) fileS / 1048576) + "MB";
        } else {
            fileSizeString = df.format((double) fileS / 1073741824) + "G";
        }
        return fileSizeString;
    }

    public static File saveFile(String filePath,String fileName, Bitmap bitmap){
        ByteArrayOutputStream baos =new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG,100,baos);
        byte[] bytes = baos.toByteArray();
        try {
            File file = new File(filePath, fileName);
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(bytes);
            fos.close();
            return file;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }
}
URI轉(zhuǎn)成圖片路徑
if (data != null) {
    // 獲取圖片URI
    val uri = data.data
    // 將URI轉(zhuǎn)換為路徑:
    val proj = arrayOf(MediaStore.Images.Media.DATA)
    val cursor = managedQuery(uri, proj, null, null, null)
    //  這個是獲得用戶選擇的圖片的索引值
    val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
    cursor.moveToFirst()
    // 最后根據(jù)索引值獲取圖片路徑
    val photoPath = cursor.getString(columnIndex)
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末淀歇,一起剝皮案震驚了整個濱河市易核,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌浪默,老刑警劉巖牡直,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異纳决,居然都是意外死亡碰逸,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門阔加,熙熙樓的掌柜王于貴愁眉苦臉地迎上來饵史,“玉大人,你說我怎么就攤上這事「炫纾” “怎么了湃番?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長厌蔽。 經(jīng)常有香客問我牵辣,道長,這世上最難降的妖魔是什么奴饮? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任纬向,我火速辦了婚禮,結(jié)果婚禮上戴卜,老公的妹妹穿的比我還像新娘逾条。我一直安慰自己,他們只是感情好投剥,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布师脂。 她就那樣靜靜地躺著,像睡著了一般江锨。 火紅的嫁衣襯著肌膚如雪吃警。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天啄育,我揣著相機與錄音酌心,去河邊找鬼。 笑死挑豌,一個胖子當(dāng)著我的面吹牛安券,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播氓英,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼侯勉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了铝阐?” 一聲冷哼從身側(cè)響起址貌,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎徘键,沒想到半個月后芳誓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡啊鸭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年锹淌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赠制。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡赂摆,死狀恐怖挟憔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情烟号,我是刑警寧澤绊谭,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站汪拥,受9級特大地震影響达传,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜迫筑,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一宪赶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脯燃,春花似錦搂妻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至逝嚎,卻和暖如春扁瓢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背补君。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工引几, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人赚哗。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓她紫,卻偏偏與公主長得像硅堆,于是被迫代替她去往敵國和親屿储。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351

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