Android音樂播放器的實(shí)現(xiàn)-Service 與 MediaPlayer學(xué)習(xí)后

Android學(xué)習(xí)整理 - 系列

Android學(xué)習(xí)整理 - 6 -Service

Android學(xué)習(xí)整理- 8 -MediaPlayer 放歌


為了實(shí)現(xiàn)后臺(tái)放歌觉鼻,可以轉(zhuǎn)移到Service中,具體的邏輯和在Activity中是差不多的


功能需求:

  • 播放邻遏,暫停,停止
  • 歌曲進(jìn)度條(SeekBar)
  • 后臺(tái)

實(shí)現(xiàn)過程

下載4首歌曲改名a1,a2,a3,a4放進(jìn)sd卡目錄下Sounds文件夾

新建服務(wù)MediaService

    private static final String TAG = "MediaService";
    private MyBinder mBinder = new MyBinder();
    //標(biāo)記當(dāng)前歌曲的序號(hào)
    private int i = 0;
    //歌曲路徑
    private String[] musicPath = new String[]{
            Environment.getExternalStorageDirectory() + "/Sounds/a1.mp3",
            Environment.getExternalStorageDirectory() + "/Sounds/a2.mp3",
            Environment.getExternalStorageDirectory() + "/Sounds/a3.mp3",
            Environment.getExternalStorageDirectory() + "/Sounds/a4.mp3"
    };
  //這里要是路徑有問題,就加上getAbsolutePath(),像下面這樣
  //Environment.getExternalStorageDirectory().getAbsolutePath() + "/Sounds/a1.mp3",

    //初始化MediaPlayer
    public MediaPlayer mMediaPlayer = new MediaPlayer();



    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    public class MyBinder extends Binder {
     
    }

在MyBinder類里面添加邏輯功能暫停捉腥,播放氓拼,下一首你画,上一首,等

 /**
         * 播放音樂
         */
        public void playMusic() {
            if (!mMediaPlayer.isPlaying()) {
                //如果還沒開始播放桃漾,就開始
                mMediaPlayer.start();
            }
        }

        /**
         * 暫停播放
         */
        public void pauseMusic() {
            if (mMediaPlayer.isPlaying()) {
                //如果還沒開始播放坏匪,就開始
                mMediaPlayer.pause();
            }
        }

         /**
         * 下一首
         */
        public void nextMusic() {
            if (mMediaPlayer != null && i < 4 && i >= 0) {
                //切換歌曲reset()很重要很重要很重要,沒有會(huì)報(bào)IllegalStateException
                mMediaPlayer.reset();
                iniMediaPlayerFile(i + 1);
                //這里的if只要是為了不讓歌曲的序號(hào)越界撬统,因?yàn)橹挥?首歌
                if (i == 2) {

                } else {
                    i = i + 1;
                }
                playMusic();
            }
        }

        /**
         * 上一首
         */
        public void preciousMusic() {
            if (mMediaPlayer != null && i < 4 && i > 0) {
                mMediaPlayer.reset();
                iniMediaPlayerFile(i - 1);
                if (i == 1) {

                } else {

                    i = i - 1;
                }
                playMusic();
            }
        }
  

        /**
         * 關(guān)閉播放器
         */
        public void closeMedia() {
            if (mMediaPlayer != null) {
                mMediaPlayer.stop();
                mMediaPlayer.release();
            }
        }

注意

在下一首和上一首的功能里重新調(diào)用 setDataSource時(shí)适滓,要先reset再重新加載資源,不然會(huì)爆java.lang.IllegalStateException錯(cuò)誤恋追,

下面這段有點(diǎn)多余凭迹,也是MyBinder里面的,因?yàn)榭梢栽贏ctivity中直接獲取到MediaPlayer的對(duì)象而不用像下面這樣拐彎苦囱,嗯嗅绸,暫時(shí)先這樣寫了

 /**
         * 獲取歌曲長度
         **/
        public int getProgress() {

            return mMediaPlayer.getDuration();
        }

        /**
         * 獲取播放位置
         */
        public int getPlayPosition() {

            return mMediaPlayer.getCurrentPosition();
        }
        /**
         * 播放指定位置
         */
        public void seekToPositon(int msec) {
            mMediaPlayer.seekTo(msec);
        }

接著載服務(wù)中MediaService中

/**
     * 添加file文件到MediaPlayer對(duì)象并且準(zhǔn)備播放音頻
     */
    private void iniMediaPlayerFile(int dex) {
        //獲取文件路徑
        try {
            //此處的兩個(gè)方法需要捕獲IO異常
            //設(shè)置音頻文件到MediaPlayer對(duì)象中
            mMediaPlayer.setDataSource(musicPath[dex]);
            //讓MediaPlayer對(duì)象準(zhǔn)備
            mMediaPlayer.prepare();
        } catch (IOException e) {
            Log.d(TAG, "設(shè)置資源,準(zhǔn)備階段出錯(cuò)");
            e.printStackTrace();
        }
    }

加入權(quán)限

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

注冊(cè)服務(wù)

<service android:name=".service.MediaService"/>

布局文件如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.minminaya.mediaservice.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/play"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:text="paly"/>

        <Button
            android:id="@+id/pause"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:text="pause"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">


        <Button
            android:id="@+id/precious"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:text="precious"/>

        <Button
            android:id="@+id/next"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:text="next"/>


    </LinearLayout>

    <SeekBar
        android:layout_marginTop="20dp"
        android:id="@+id/seekbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <TextView
        android:text="當(dāng)前進(jìn)度:"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

預(yù)覽

Activity中撕彤,首先先實(shí)現(xiàn)播放的4大功能鱼鸠,聲明

    private MediaService.MyBinder mMyBinder;
    private Button playButton;
    private Button pauseButton;
    private Button nextButton;
    private Button preciousButton;
    //“綁定”服務(wù)的intent
    Intent MediaServiceIntent;

服務(wù)與活動(dòng)的紐帶ServiceConnection

 private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mMyBinder = (MediaService.MyBinder) service;
             Log.d(TAG, "Service與Activity已連接");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
  
        }
    };

綁定id,這里所有view都綁了,button事件

private void iniView() {
        playButton = (Button) findViewById(R.id.play);
        pauseButton = (Button) findViewById(R.id.pause);
        nextButton = (Button) findViewById(R.id.next);
        preciousButton = (Button) findViewById(R.id.precious);
        mSeekBar = (SeekBar) findViewById(R.id.seekbar);
        mTextView = (TextView) findViewById(R.id.text1);
        playButton.setOnClickListener(this);
        pauseButton.setOnClickListener(this);
        nextButton.setOnClickListener(this);
        preciousButton.setOnClickListener(this);
    }

button事件詳細(xì)

 @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.play:
                mMyBinder.playMusic();
                break;
            case R.id.pause:
                mMyBinder.pauseMusic();
                break;
            case R.id.next:
                mMyBinder.nextMusic();
                break;
            case R.id.precious:
                mMyBinder.preciousMusic();
                break;
        }
    }

接下來是onCreate方法蚀狰,針對(duì)Android6.0以上的運(yùn)行時(shí)權(quán)限愉昆,動(dòng)態(tài)申請(qǐng)權(quán)限

      iniView();
        MediaServiceIntent = new Intent(this, MediaService.class);


        //判斷權(quán)限夠不夠,不夠就給
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
            }, 1);
        } else {
            //夠了綁定播放音樂的服務(wù)
            bindService(MediaServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
        }

運(yùn)行時(shí)權(quán)限的回調(diào)麻蹋,在Activity中的

//獲取到權(quán)限回調(diào)方法
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull  String[]permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    bindService(MediaServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
                } else {
                    Toast.makeText(this, "權(quán)限不夠獲取不到音樂跛溉,程序?qū)⑼顺?, Toast.LENGTH_SHORT).show();
                    finish();
                }
                break;
            default:
                break;
        }
    }

onDestroy方法種添加

        mMyBinder.closeMedia();
        unbindService(mServiceConnection);

這個(gè)時(shí)候可以播放了,進(jìn)度條當(dāng)然沒有動(dòng)

效果圖

接下來實(shí)現(xiàn)進(jìn)度條的功能

在Activity中實(shí)例化handler

    private Handler mHandler = new Handler();

    private SeekBar mSeekBar;
    private TextView mTextView;
    //進(jìn)度條下面的當(dāng)前進(jìn)度文字扮授,將毫秒化為m:ss格式
    private SimpleDateFormat time = new SimpleDateFormat("m:ss");

在ServiceConnection中添加

 mSeekBar.setMax(mMyBinder.getProgress());

            mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                    //這里很重要倒谷,如果不判斷是否來自用戶操作進(jìn)度條,會(huì)不斷執(zhí)行下面語句塊里面的邏輯糙箍,然后就會(huì)卡頓卡頓
                    if(fromUser){
                        mMyBinder.seekToPositon(seekBar.getProgress());
//                    mMediaService.mMediaPlayer.seekTo(seekBar.getProgress());
                    }
                }

                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {

                }

                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {

                }
            });

            mHandler.post(mRunnable);

注意

  • 這里的seekbar回調(diào)里渤愁,如果不判斷fromUser,播放會(huì)一直卡頓

還有一個(gè)runnable

 /**
     * 更新ui的runnable
     */
    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            mSeekBar.setProgress(mMyBinder.getPlayPosition());
            mTextView.setText(time.format(mMyBinder.getPlayPosition()) + "s");
            mHandler.postDelayed(mRunnable, 1000);
        }
    };

onDestroy中 mMyBinder.closeMedia();前添加

//我們的handler發(fā)送是定時(shí)1000s發(fā)送的深夯,如果不關(guān)閉抖格,MediaPlayer release掉了還在獲取getCurrentPosition就會(huì)爆IllegalStateException錯(cuò)誤
        mHandler.removeCallbacks(mRunnable);

注意關(guān)閉handle的隊(duì)列,不然咕晋,轉(zhuǎn)入后臺(tái)播放時(shí)程序崩潰


1.gif

貼全部代碼環(huán)節(jié)

全部Activity代碼如下

package com.minminaya.mediaservice;

import android.Manifest;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.format.Time;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.minminaya.mediaservice.service.MediaService;

import java.text.SimpleDateFormat;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Handler mHandler = new Handler();

    private static final String TAG = "MainActivity";
    private MediaService.MyBinder mMyBinder;
//    private MediaService mMediaService;

    private Button playButton;
    private Button pauseButton;
    private Button nextButton;
    private Button preciousButton;
    private SeekBar mSeekBar;
    private TextView mTextView;
    //進(jìn)度條下面的當(dāng)前進(jìn)度文字雹拄,將毫秒化為m:ss格式
    private SimpleDateFormat time = new SimpleDateFormat("m:ss");
    //“綁定”服務(wù)的intent
    Intent MediaServiceIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iniView();
        MediaServiceIntent = new Intent(this, MediaService.class);


        //判斷權(quán)限夠不夠,不夠就給
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
            }, 1);
        } else {
            //夠了就設(shè)置路徑等掌呜,準(zhǔn)備播放
            bindService(MediaServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
        }
    }

    //獲取到權(quán)限回調(diào)方法
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull  String[]permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    bindService(MediaServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
                } else {
                    Toast.makeText(this, "權(quán)限不夠獲取不到音樂滓玖,程序?qū)⑼顺?, Toast.LENGTH_SHORT).show();
                    finish();
                }
                break;
            default:
                break;
        }
    }


    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mMyBinder = (MediaService.MyBinder) service;
//            mMediaService = ((MediaService.MyBinder) service).getInstance();
            mSeekBar.setMax(mMyBinder.getProgress());

            mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                    //這里很重要,如果不判斷是否來自用戶操作進(jìn)度條质蕉,會(huì)不斷執(zhí)行下面語句塊里面的邏輯势篡,然后就會(huì)卡頓卡頓
                    if(fromUser){
                        mMyBinder.seekToPositon(seekBar.getProgress());
//                    mMediaService.mMediaPlayer.seekTo(seekBar.getProgress());
                    }
                }

                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {

                }

                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {

                }
            });

            mHandler.post(mRunnable);

            Log.d(TAG, "Service與Activity已連接");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };


    private void iniView() {
        playButton = (Button) findViewById(R.id.play);
        pauseButton = (Button) findViewById(R.id.pause);
        nextButton = (Button) findViewById(R.id.next);
        preciousButton = (Button) findViewById(R.id.precious);
        mSeekBar = (SeekBar) findViewById(R.id.seekbar);
        mTextView = (TextView) findViewById(R.id.text1);
        playButton.setOnClickListener(this);
        pauseButton.setOnClickListener(this);
        nextButton.setOnClickListener(this);
        preciousButton.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.play:
                mMyBinder.playMusic();
                break;
            case R.id.pause:
                mMyBinder.pauseMusic();
                break;
            case R.id.next:
                mMyBinder.nextMusic();
                break;
            case R.id.precious:
                mMyBinder.preciousMusic();
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //我們的handler發(fā)送是定時(shí)1000s發(fā)送的,如果不關(guān)閉模暗,MediaPlayer release掉了還在獲取getCurrentPosition就會(huì)爆IllegalStateException錯(cuò)誤
        mHandler.removeCallbacks(mRunnable);

        mMyBinder.closeMedia();
        unbindService(mServiceConnection);
    }

    /**
     * 更新ui的runnable
     */
    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            mSeekBar.setProgress(mMyBinder.getPlayPosition());
            mTextView.setText(time.format(mMyBinder.getPlayPosition()) + "s");
            mHandler.postDelayed(mRunnable, 1000);
        }
    };

}

服務(wù)的

package com.minminaya.mediaservice.service;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Environment;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import java.io.IOException;

/**
 * Created by NIWA on 2017/3/17.
 */

public class MediaService extends Service {

    private static final String TAG = "MediaService";
    private MyBinder mBinder = new MyBinder();
    //標(biāo)記當(dāng)前歌曲的序號(hào)
    private int i = 0;
    //歌曲路徑
    private String[] musicPath = new String[]{
            Environment.getExternalStorageDirectory() + "/Sounds/a1.mp3",
            Environment.getExternalStorageDirectory() + "/Sounds/a2.mp3",
            Environment.getExternalStorageDirectory() + "/Sounds/a3.mp3",
            Environment.getExternalStorageDirectory() + "/Sounds/a4.mp3"
    };
    //初始化MediaPlayer
    public MediaPlayer mMediaPlayer = new MediaPlayer();


    public MediaService() {
        iniMediaPlayerFile(i);
    }


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    public class MyBinder extends Binder {

//        /**
//         *  獲取MediaService.this(方便在ServiceConnection中)
//         *
//         * *//*
//        public MediaService getInstance() {
//            return MediaService.this;
//        }*/
        /**
         * 播放音樂
         */
        public void playMusic() {
            if (!mMediaPlayer.isPlaying()) {
                //如果還沒開始播放禁悠,就開始
                mMediaPlayer.start();
            }
        }

        /**
         * 暫停播放
         */
        public void pauseMusic() {
            if (mMediaPlayer.isPlaying()) {
                //如果還沒開始播放,就開始
                mMediaPlayer.pause();
            }
        }

        /**
         * reset
         */
        public void resetMusic() {
            if (!mMediaPlayer.isPlaying()) {
                //如果還沒開始播放兑宇,就開始
                mMediaPlayer.reset();
                iniMediaPlayerFile(i);
            }
        }

        /**
         * 關(guān)閉播放器
         */
        public void closeMedia() {
            if (mMediaPlayer != null) {
                mMediaPlayer.stop();
                mMediaPlayer.release();
            }
        }

        /**
         * 下一首
         */
        public void nextMusic() {
            if (mMediaPlayer != null && i < 4 && i >= 0) {
                //切換歌曲reset()很重要很重要很重要碍侦,沒有會(huì)報(bào)IllegalStateException
                mMediaPlayer.reset();
                iniMediaPlayerFile(i + 1);
                //這里的if只要是為了不讓歌曲的序號(hào)越界,因?yàn)橹挥?首歌
                if (i == 2) {

                } else {
                    i = i + 1;
                }
                playMusic();
            }
        }

        /**
         * 上一首
         */
        public void preciousMusic() {
            if (mMediaPlayer != null && i < 4 && i > 0) {
                mMediaPlayer.reset();
                iniMediaPlayerFile(i - 1);
                if (i == 1) {

                } else {

                    i = i - 1;
                }
                playMusic();
            }
        }

        /**
         * 獲取歌曲長度
         **/
        public int getProgress() {

            return mMediaPlayer.getDuration();
        }

        /**
         * 獲取播放位置
         */
        public int getPlayPosition() {

            return mMediaPlayer.getCurrentPosition();
        }
        /**
         * 播放指定位置
         */
        public void seekToPositon(int msec) {
            mMediaPlayer.seekTo(msec);
        }




    }


    /**
     * 添加file文件到MediaPlayer對(duì)象并且準(zhǔn)備播放音頻
     */
    private void iniMediaPlayerFile(int dex) {
        //獲取文件路徑
        try {
            //此處的兩個(gè)方法需要捕獲IO異常
            //設(shè)置音頻文件到MediaPlayer對(duì)象中
            mMediaPlayer.setDataSource(musicPath[dex]);
            //讓MediaPlayer對(duì)象準(zhǔn)備
            mMediaPlayer.prepare();
        } catch (IOException e) {
            Log.d(TAG, "設(shè)置資源隶糕,準(zhǔn)備階段出錯(cuò)");
            e.printStackTrace();
        }
    }
}

Github源代碼:MediaService

高級(jí)播放器瓷产。。枚驻。人類用的

上面的播放是固有的幾個(gè)文件(連音頻文件名都訂好了濒旦,真坑)

有個(gè)博主,做的畢業(yè)項(xiàng)目测秸,是一系列文章疤估,感覺不錯(cuò)灾常,
Android開源音樂播放器之播放器基本功能

注意事項(xiàng),

幾個(gè)注意點(diǎn)在上面了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末铃拇,一起剝皮案震驚了整個(gè)濱河市钞瀑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌慷荔,老刑警劉巖雕什,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異显晶,居然都是意外死亡贷岸,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門磷雇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來偿警,“玉大人,你說我怎么就攤上這事唯笙∶簦” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵崩掘,是天一觀的道長七嫌。 經(jīng)常有香客問我,道長苞慢,這世上最難降的妖魔是什么诵原? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮挽放,結(jié)果婚禮上绍赛,老公的妹妹穿的比我還像新娘。我一直安慰自己骂维,他們只是感情好惹资,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著航闺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪猴誊。 梳的紋絲不亂的頭發(fā)上潦刃,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音懈叹,去河邊找鬼乖杠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛澄成,可吹牛的內(nèi)容都是我干的胧洒。 我是一名探鬼主播畏吓,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼卫漫!你這毒婦竟也來了菲饼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤列赎,失蹤者是張志新(化名)和其女友劉穎宏悦,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體包吝,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡饼煞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诗越。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片砖瞧。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖嚷狞,靈堂內(nèi)的尸體忽然破棺而出芭届,到底是詐尸還是另有隱情,我是刑警寧澤感耙,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布褂乍,位于F島的核電站,受9級(jí)特大地震影響即硼,放射性物質(zhì)發(fā)生泄漏逃片。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一只酥、第九天 我趴在偏房一處隱蔽的房頂上張望褥实。 院中可真熱鬧,春花似錦裂允、人聲如沸损离。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽僻澎。三九已至,卻和暖如春十饥,著一層夾襖步出監(jiān)牢的瞬間窟勃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工逗堵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留秉氧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓蜒秤,卻偏偏與公主長得像汁咏,于是被迫代替她去往敵國和親亚斋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,506評(píng)論 25 707
  • 本人初學(xué)Android攘滩,最近做了一個(gè)實(shí)現(xiàn)安卓簡單音樂播放功能的播放器帅刊,收獲不少,于是便記錄下來自己的思路與知識(shí)總結(jié)...
    落日柳風(fēng)閱讀 19,082評(píng)論 2 41
  • 在Android中播放音頻文件一般都是使用MediaPlayer類來實(shí)現(xiàn)的 MediaPlayer使用步驟簡介: ...
    大話程序閱讀 1,633評(píng)論 0 12
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程轰驳,因...
    小菜c閱讀 6,358評(píng)論 0 17
  • 一直懷揣著一個(gè)有關(guān)文學(xué)级解,系于創(chuàng)作的夢(mèng)想冒黑,卻一直沒有專心地寫點(diǎn)什么,總以為自己的積淀還不夠厚實(shí)勤哗,文筆還不夠瑰麗抡爹,思想...
    _起點(diǎn)_閱讀 497評(píng)論 1 4