安卓MediaPlayer实现自定义音乐播放器

项目中用到了MediaPlayer播放音频,趁这两天比较闲,试着写了一个音频播放器,还有很多不完善,仅当练手。实现了播放、暂停、退出,上下切歌,扫描音频文件并展示,点击音频列表可播放,打开指定音频文件播放的功能,不过功能之间并没有做特殊处理,所以多个功能之间使用会出现崩溃(笑哭)。下面是效果图:

这里写图片描述

这里写图片描述

已知问题:
1. 目前打开目录查找文件功能在PAD(安卓5.1)上可以,手机上(安卓8.0)上会崩溃。
2. 这个布局主要是针对手头上的PAD,对手机布局没有优化,同时布局也比较丑,但是这次Demo主要以功能练习为主,所以布局上也不再优化。
3. 因此Demo仅用于MediaPlayer学习,目前所做内容已超过预期。加之下周需要述职,没有精力花费在此,故代码逻辑并不严谨,封装也不好, 留待后期优化。

可优化:
后期打算增加播放时当前播放歌曲左侧列表高亮。
UI布局优化(不可能的,就是如此粗犷的人)

下面贴代码:

MainActivity.java,基本功能都是在此完成。

package com.example.qxb_810.audioplaydemo;

import android.Manifest;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.example.qxb_810.bean.ScanFile;
import com.example.qxb_810.utils.GetPathFromUri4kitkat;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import butterknife.BindView;
import butterknife.ButterKnife;


/**
 * author XXX
 * email XXX@XXXXXX.com
 * create 2018/9/5 19:08
 * desc  音乐播放  -- mediaPlayer的使用
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    @BindView(R.id.tv_play)
    TextView tvPlay;
    @BindView(R.id.tv_resume)
    TextView tvResume;
    @BindView(R.id.tv_stop)
    TextView tvStop;
    @BindView(R.id.sb_progress)
    SeekBar sbProgress;
    @BindView(R.id.tv_currprogress)
    TextView tvCurrprogress;
    @BindView(R.id.tv_maxprogress)
    TextView tvMaxprogress;
    @BindView(R.id.iv_pic)
    ImageView ivPic;
    @BindView(R.id.tv_find_file)
    TextView tvFindFile;
    @BindView(R.id.tv_scan_file)
    TextView tvScanFile;
    @BindView(R.id.tv_last)
    TextView tvLast;
    @BindView(R.id.tv_next)
    TextView tvNext;
    @BindView(R.id.tv_title)
    TextView tvTitle;
    @BindView(R.id.tv_artist)
    TextView tvArtist;
    @BindView(R.id.rv_file_list)
    RecyclerView rvFileList;

    private MediaPlayer mMediaPlayer;
    private int mDuration = 0;
    private boolean isMusicLoadSuccess = false;
    private boolean isPlayPause = false;
    private String mPath;
    private int mCurrPostion = 0;

    private MyAdapter myAdapter;
    private ObjectAnimator animator;
    private List<ScanFile> fileList = new ArrayList<ScanFile>();
    private Set<String> filePathSet = new HashSet<String>();
    private List<String> fileNameList = new ArrayList<String>();

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 123) {
                sbProgress.setProgress(mMediaPlayer.getCurrentPosition());
                tvCurrprogress.setText(formatDuring(mMediaPlayer.getCurrentPosition()));
                mHandler.sendEmptyMessage(123);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        mPath = null;
        try {
            requestPermissions();
            initMediaPlayer();
            initRecyclerView();
            initEvent();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 动态申请权限  ----  API23后需要动态申请权限
     */
    private void requestPermissions() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            // 读写存储权限 和联网权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.INTERNET}, 1);
        }
    }

    /**
     * 初始化RecyclerView
     */
    private void initRecyclerView() {
        rvFileList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        myAdapter = new MyAdapter(fileList, this);
        rvFileList.setAdapter(myAdapter);
    }

    /**
     * 初始化MediaPlayer
     *
     * @throws IOException
     */
    private void initMediaPlayer() throws IOException {
        mMediaPlayer = new MediaPlayer();
        if (mPath != null && !mPath.equals("")) {
            mMediaPlayer.setLooping(false);  // 设置单曲循环
            mMediaPlayer.setDataSource(mPath);
            mMediaPlayer.prepareAsync();    // 异步加载音频
            mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    // 异步加载结束后再回调
                    isMusicLoadSuccess = true;
                    mDuration = mMediaPlayer.getDuration();
                    tvMaxprogress.setText(formatDuring(mDuration));
                    sbProgress.setMax(mDuration);   // 设置进度条最大值
                }
            });
        }


        animator = ObjectAnimator.ofFloat(ivPic, "rotation", 360.0f);
        animator.setDuration(10000);    // 设置转速,越大越慢
        animator.setInterpolator(new LinearInterpolator());
        animator.setRepeatCount(-1);
        ivPic.setImageBitmap(null);
        if (getAudioPic() != null) {
            ivPic.setImageBitmap(getAudioPic());
        }

        ivPic.setBackgroundResource(R.drawable.shape_default_pic);
    }

    /**
     * 初始化事件
     */
    private void initEvent() {
        tvPlay.setOnClickListener(this);
        tvResume.setOnClickListener(this);
        tvStop.setOnClickListener(this);
        tvFindFile.setOnClickListener(this);
        tvScanFile.setOnClickListener(this);
        tvLast.setOnClickListener(this);
        tvNext.setOnClickListener(this);

        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                changeMusic(++mCurrPostion);
            }
        });

        sbProgress.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                tvCurrprogress.setText(formatDuring(seekBar.getProgress()));
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                mMediaPlayer.seekTo(seekBar.getProgress());
            }
        });
    }

    /**
     * 获取音乐文件图片
     *
     * @return
     */
    public Bitmap getAudioPic() {
        try {
            Uri selectedAudio = Uri.parse(mPath);
            MediaMetadataRetriever myRetriever = new MediaMetadataRetriever();
            myRetriever.setDataSource(this, selectedAudio); // the URI of audio file
            byte[] artwork;
            artwork = myRetriever.getEmbeddedPicture();
            if (artwork != null) {
                return getCircleBitmap(BitmapFactory.decodeByteArray(artwork, 0, artwork.length));
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取圆形图片
     *
     * @param bitmap
     * @return
     */
    private Bitmap getCircleBitmap(Bitmap bitmap) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getHeight() / 2, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);//将图片画出来
        return output;
    }

    /**
     * 扫描音乐文件信息
     *
     * @return
     */
    public void scanAudioFile() {
        fileList.clear();
        filePathSet.clear();
        fileNameList.clear();
        Cursor cursor = this.getContentResolver().query(
                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
                MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
        for (int i = 0; i < cursor.getCount(); i++) {
            cursor.moveToNext();
            int id = (int) cursor.getLong(cursor
                    .getColumnIndex(MediaStore.Audio.Media._ID));   //音乐id
            String title = cursor.getString((cursor
                    .getColumnIndex(MediaStore.Audio.Media.TITLE))); // 音乐标题
            String artist = cursor.getString(cursor
                    .getColumnIndex(MediaStore.Audio.Media.ARTIST)); // 艺术家
            String album = cursor.getString(cursor
                    .getColumnIndex(MediaStore.Audio.Media.ALBUM)); //专辑
            String displayName = cursor.getString(cursor
                    .getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
            int albumId = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
            int duration = (int) cursor.getLong(cursor
                    .getColumnIndex(MediaStore.Audio.Media.DURATION)); // 时长
            long size = cursor.getLong(cursor
                    .getColumnIndex(MediaStore.Audio.Media.SIZE)); // 文件大小
            String url = cursor.getString(cursor
                    .getColumnIndex(MediaStore.Audio.Media.DATA)); // 文件路径
            int isMusic = cursor.getInt(cursor
                    .getColumnIndex(MediaStore.Audio.Media.IS_MUSIC)); // 是否为音乐


            if (1 == isMusic && duration > 1000 * 60 && !filePathSet.contains(url)) {    // 大于1min的音乐文件且未添加过
                ScanFile file = new ScanFile(id, title, artist, album, displayName, url, albumId, duration, size, isMusic);
                filePathSet.add(file.getUrl());
                fileNameList.add(file.getTitle());
                fileList.add(file);
            }
        }
        myAdapter.notifyDataSetChanged();
        Log.e("list", fileList.toString());
    }


    /**
     * 切换歌曲
     *
     * @param postion
     */
    private void changeMusic(int postion) {
        if (fileList.size() > 0) {
            mCurrPostion = 0;
            sbProgress.setProgress(0);
            mHandler.removeMessages(123);
            // 播放结束
            mMediaPlayer.stop();
            if (postion >= fileList.size()) {
                postion = 0;
            } else if (postion <= 0) {
                postion = fileList.size() - 1;
            }
            tvArtist.setText("演唱者: " + fileList.get(postion).getArtist());
            tvTitle.setText("歌曲名: " + fileList.get(postion).getTitle());
            ScanFile scanFile = fileList.get(mCurrPostion = postion);
            mPath = scanFile.getUrl();
            try {
                initMediaPlayer();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Toast.makeText(getApplicationContext(), "暂无音乐,请扫描...", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_play:
                if (isMusicLoadSuccess) {
                    if (mMediaPlayer.isPlaying()) {
                        Toast.makeText(getApplicationContext(), "播放中...", Toast.LENGTH_SHORT).show();
                    } else {
                        if (fileList.size() == 0) {
                            Toast.makeText(getApplicationContext(), "暂无音乐,请扫描...", Toast.LENGTH_SHORT).show();
                        } else {
                            mMediaPlayer.start();
                            animator.start();
                            mHandler.sendEmptyMessage(123);
                        }
                    }
                } else {
                    Toast.makeText(getApplicationContext(), fileList.size() > 0 ? "加载中..." : "暂无音乐,请扫描...", Toast.LENGTH_SHORT).show();
                }

                break;
            case R.id.tv_resume:
                if (!isPlayPause) {
                    if (mMediaPlayer.isPlaying()) {
                        isPlayPause = true;
                        mDuration = mMediaPlayer.getCurrentPosition();
                        mMediaPlayer.pause();
                        animator.pause();
                        tvResume.setText("继续");
                    } else {
                        Toast.makeText(getApplicationContext(), "还未播放...", Toast.LENGTH_SHORT).show();
                    }
                } else {
                    isPlayPause = false;
                    mMediaPlayer.start();
                    animator.resume();
                    tvResume.setText("暂停");
                }
                break;
            case R.id.tv_stop:
                mDuration = 0;
                sbProgress.setProgress(0);
                mMediaPlayer.reset();
                mMediaPlayer.stop();
                animator.cancel();
                mHandler.removeMessages(123);
                break;
            case R.id.tv_find_file:
                File parentFlie = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
                Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                intent.setDataAndType(Uri.fromFile(parentFlie), "*/*");
             //   intent.setDataAndType(FileProvider.getUriForFile(getApplicationContext(), "com.example.qxb_810.fileprovider", parentFlie), "*/*");     // 设置打开文件类型,这么没设置类型
                //      intent.setType(“image/*”);
                //intent.setType(“audio/*”); //选择音频
                //intent.setType(“video/*”); //选择视频 (mp4 3gp 是android支持的视频格式)
                //intent.setType(“video/*;image/*”);//同时选择视频和图片
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                startActivityForResult(intent, 111);
                break;
            case R.id.tv_scan_file:
                Toast.makeText(getApplicationContext(), "扫描中...", Toast.LENGTH_SHORT).show();
                scanAudioFile();
                Toast.makeText(getApplicationContext(), "扫描结束,共扫描到" + fileList.size() + "个音频...", Toast.LENGTH_SHORT).show();
                break;
            case R.id.tv_last:
                changeMusic(--mCurrPostion);
                break;
            case R.id.tv_next:
                changeMusic(++mCurrPostion);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {//是否选择,没选择就不会继续
            Uri uri = data.getData();//得到uri,后面就是将uri转化成file的过程。
            mPath = GetPathFromUri4kitkat.getPath(this, uri);
            try {
                if (mMediaPlayer != null) {
                    mMediaPlayer.stop();
                    mMediaPlayer.release();
                    animator.cancel();
                    isMusicLoadSuccess = false;
                    initMediaPlayer();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 换算时间
     *
     * @param time 时间
     * @return
     */
    public static String formatDuring(long time) {
        long minutes = (time % (1000 * 60 * 60)) / (1000 * 60);
        long seconds = (time % (1000 * 60)) / 1000;
        String min = minutes < 10 ? "0" + minutes : minutes + "";
        String sec = seconds < 10 ? "0" + seconds : seconds + "";
        return min + ":" + sec;
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeMessages(123);
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.release();
        }
    }

    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
        private List<ScanFile> list = new ArrayList<>();
        private Context context;

        public MyAdapter(List<ScanFile> list, Context context) {
            this.list = list;
            this.context = context;
        }

        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(context).inflate(R.layout.simple_adapter_item, parent, false);
            MyViewHolder viewHolder = new MyViewHolder(view);
            return viewHolder;
        }

        @Override
        public void onBindViewHolder(final MyViewHolder holder, final int position) {
            holder.tvTitle.setText(list.get(position).getTitle());
            holder.llContent.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    changeMusic(position);
                    mHandler.sendEmptyMessage(123);
                    mMediaPlayer.start();
                }
            });
        }

        @Override
        public int getItemCount() {
            return list.size();
        }

        class MyViewHolder extends RecyclerView.ViewHolder {
            @BindView(R.id.tv_title)
            TextView tvTitle;
            @BindView(R.id.ll_content)
            LinearLayout llContent;

            public MyViewHolder(View itemView) {
                super(itemView);
                ButterKnife.bind(this, itemView);
            }
        }
    }
}

MainActivity布局,没错,如此丑陋的布局就是下面这个文件:

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

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"
        android:visibility="visible">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_file_list"
            android:layout_width="wrap_content"
            android:layout_height="300dp"></android.support.v7.widget.RecyclerView>
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/iv_pic"
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:layout_marginBottom="20dp" />

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="暂无标题" />

        <TextView
            android:id="@+id/tv_artist"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:layout_marginTop="20dp"
            android:text="演唱人" />

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

            <TextView
                android:id="@+id/tv_currprogress"
                android:layout_width="80dp"
                android:layout_height="wrap_content"
                android:layout_alignLeft="@+id/sb_progress"
                android:gravity="center"
                android:text="00:00" />

            <SeekBar
                android:id="@+id/sb_progress"
                android:layout_width="500dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical" />

            <TextView
                android:id="@+id/tv_maxprogress"
                android:layout_width="80dp"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="00:00" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:gravity="center">

            <TextView
                android:id="@+id/tv_last"
                android:layout_width="80dp"
                android:layout_height="35dp"
                android:layout_margin="5dp"
                android:background="@color/colorAccent"
                android:gravity="center"
                android:text="上一首" />

            <TextView
                android:id="@+id/tv_play"
                android:layout_width="80dp"
                android:layout_height="35dp"
                android:layout_margin="5dp"
                android:background="@color/colorAccent"
                android:gravity="center"
                android:text="播放" />

            <TextView
                android:id="@+id/tv_resume"
                android:layout_width="80dp"
                android:layout_height="35dp"
                android:layout_margin="5dp"
                android:background="@color/colorAccent"
                android:gravity="center"
                android:text="暂停" />

            <TextView
                android:id="@+id/tv_stop"
                android:layout_width="80dp"
                android:layout_height="35dp"
                android:layout_margin="5dp"
                android:background="@color/colorAccent"
                android:gravity="center"
                android:text="退出" />

            <TextView
                android:id="@+id/tv_find_file"
                android:layout_width="80dp"
                android:layout_height="35dp"
                android:layout_margin="5dp"
                android:background="@color/colorAccent"
                android:gravity="center"
                android:text="打开目录" />

            <TextView
                android:id="@+id/tv_scan_file"
                android:layout_width="80dp"
                android:layout_height="35dp"
                android:layout_margin="5dp"
                android:background="@color/colorAccent"
                android:gravity="center"
                android:text="文件扫描" />

            <TextView
                android:id="@+id/tv_next"
                android:layout_width="80dp"
                android:layout_height="35dp"
                android:layout_margin="5dp"
                android:background="@color/colorAccent"
                android:gravity="center"
                android:text="下一首" />
        </LinearLayout>
    </LinearLayout>
</FrameLayout>

GetPathFromUri4kitkat类,这个是从网上找的,因为需要转相应路径

package com.example.qxb_810.utils;

import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;

public class GetPathFromUri4kitkat {

    /**
     * 专为Android4.4设计的从Uri获取文件绝对路径,以前的方法已不好使
     */
    @SuppressLint("NewApi")
    public static String getPath(final Context context, final Uri uri) {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{split[1]};

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {column};

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }
}

ScanFile — bean类

package com.example.qxb_810.bean;

/**
* author XXX
* email XXX@XXXXXX.com
* create 2018/9/6 14:23
* desc 音乐bean
*/

public class ScanFile {

    private int id;
    private String title;
    private String artist;
    private String album;
    private String displayName;
    private String url;
    private int albumId;
    private int duration;
    private long size;
    private int isMusic;


    public ScanFile() {
    }

    public ScanFile(int id, String title, String artist, String album, String displayName, String url, int albumId, int duration, long size, int isMusic) {
        this.id = id;
        this.title = title;
        this.artist = artist;
        this.album = album;
        this.displayName = displayName;
        this.url = url;
        this.albumId = albumId;
        this.duration = duration;
        this.size = size;
        this.isMusic = isMusic;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public String getAlbum() {
        return album;
    }

    public void setAlbum(String album) {
        this.album = album;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public int getAlbumId() {
        return albumId;
    }

    public void setAlbumId(int albumId) {
        this.albumId = albumId;
    }

    public int getDuration() {
        return duration;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

    public long getSize() {
        return size;
    }

    public void setSize(long size) {
        this.size = size;
    }

    public int getIsMusic() {
        return isMusic;
    }

    public void setIsMusic(int isMusic) {
        this.isMusic = isMusic;
    }

    @Override
    public String toString() {
        return "ScanFile{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", artist='" + artist + '\'' +
                ", album='" + album + '\'' +
                ", displayName='" + displayName + '\'' +
                ", url='" + url + '\'' +
                ", albumId=" + albumId +
                ", duration=" + duration +
                ", size=" + size +
                ", isMusic=" + isMusic +
                '}';
    }
}

接下来就是一些简单的布局文件

shape_default_pic

<?xml version="1.0" encoding="UTF-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    android:useLevel="false" >
    <solid android:color="@color/colorAccent" />
    <padding
        android:left="2dp"
        android:top="1dp"
        android:right="2dp"
        android:bottom="1dp" />
    <solid
        android:color="@color/colorAccent" />
    <stroke
        android:width="10dp"
        android:color="@color/colorPrimary"/>
    <size android:width="15dp"
        android:height="15dp" />
</shape>

simple_adapter_item

<?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="wrap_content"
    android:orientation="vertical"
    android:id="@+id/ll_content">
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:text="标题"
        android:singleLine="true"
        android:textSize="25dp"/>
    <View
        android:background="@color/colorPrimary"
        android:layout_width="match_parent"
        android:layout_height="1dp"/>
</LinearLayout>

OK,项目大致就是这些文件。作为第一个做出来的稍微像样点的小Demo,代码里面仍有很多不足需要改进,等下周述职结束后再进行优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫吻鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值