Android学习之如何读取本地音乐以及图片

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36391075/article/details/75144100

最近做音乐播放器读取本地音乐这一块。简单模仿网易云音乐的界面。
首先我建议了一个music类

public class music {

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

    public String getAlbum() {
        return album;
    }

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

    public long getDuration() {
        return duration;
    }

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

    public long getId() {
        return id;
    }

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

    public int getIsMusic() {
        return isMusic;
    }

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

    public long getAlbum_id() {
        return album_id;
    }

    public void setAlbum_id(long album_id) {
        this.album_id = album_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 long getSize() {
        return size;
    }

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

    public String getUrl() {
        return url;
    }

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

想要读取本地的东西,肯定是用contentresolver了,得到cursor,进行查询。
核心代码:

 public List<music> getMusic(){
        ContentResolver contentResolver = getContentResolver();
        Cursor cursor = contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,null,null,null,MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
        List<music> musicList = new ArrayList<>();
        if(cursor.moveToFirst()){
        for(int i = 0; i <cursor.getCount();i++) {
            music m = new music();
            long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID));
            String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
            String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
            long duration = 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));
            String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));
            long album_id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
            int ismusic = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));

            if (ismusic != 0 && duration / (500 * 60) >= 1) {
                m.setId(id);
                m.setTitle(title);
                m.setArtist(artist);
                m.setDuration(duration);
                m.setSize(size);
                m.setUrl(url);
                m.setAlbum(album);
                m.setAlbum_id(album_id);
                musicList.add(m);
            }
            cursor.moveToNext();

        }


        }
        return musicList;


    }
}

然后通过ListView展示出来。

ublic class bendiyinyueAdapter extends ArrayAdapter<music> {

    Context context;
    int res;

    public bendiyinyueAdapter(Context context, int resource, List<music> objects) {
        super(context, resource, objects);
        this.context = context;
        this.res = resource;
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        music item = getItem(position);
        ViewHold viewHold;
        View view;
        if(convertView == null){
             view= LayoutInflater.from(context).inflate(res,parent,false);
            viewHold = new ViewHold();
            viewHold.name = (TextView) view.findViewById(R.id.music_name);
            viewHold.artist = (TextView)view.findViewById(R.id.artist);
            view.setTag(viewHold);
        }else {
            view = convertView;
            viewHold = (ViewHold)view.getTag();
        }

        viewHold.name.setText(item.getTitle());
        viewHold.artist.setText(item.getArtist());

        return view;

    }

    class  ViewHold{
        TextView name ;
        TextView artist;


    }
}






 listView = (ListView)findViewById(R.id.bendiyinyue_list);
        musics =getMusic();
        adapter = new bendiyinyueAdapter(this,R.layout.bendi_item,musics);
        listView.setAdapter(adapter);

效果:这里写图片描述

接下来是得到专辑的图片:

private static final Uri albumArtUri=Uri.parse(“content://media/external/audio/albumart”);

我一直在思考,我怎么知道图片的uri,然后我试着打印了一下:
Log.d(“aaaaa”,MediaStore.Audio.Media.EXTERNAL_CONTENT_URI.toString();
得到的结果是:
content://media/external/audio/media
这是音频媒体表的uri
然后我查询API,发现了
MediaStore.Audio.Artists.Albums
打印它的所有的列:发现了album_art,它缓存专辑封面。所以现在我们知道需要找album_art

所以当我们不知道albumid的时候,就通过歌曲来找:
Uri.parse(“content://media/external/audio/media/”+songid+”/albumart”);
接着通过uri来打开这个文件:
文件描述符是进程用于读取或写入打开文件并打开网络套接字的对象。

FileDescriptor可以编写代表原始Linux文件描述符标识符的对象,并ParcelFileDescriptor返回对对原始文件描述符操作的对象。返回的文件描述符是原始文件描述符的dup:对象和fd不同,但在相同的底层文件流上操作,具有相同的位置。
然后获取Bitmap

    public static Bitmap getArtWorkFormFile(ContentResolver resolver,int songid,int album){
        Bitmap bitmap = null;
        if(album <0 &&songid <0){
            throw new IllegalArgumentException("Must specify an album or song");
        }

        try{
            BitmapFactory.Options options = new BitmapFactory.Options();
            FileDescriptor fileDescriptor = null;
            if(album <0){
                Uri uri = Uri.parse("content://media/external/audio/media/"+songid+"/albumart");
                ParcelFileDescriptor parcelFileDescriptor = resolver.openFileDescriptor(uri,"r");
                if(parcelFileDescriptor !=null){
                    fileDescriptor = parcelFileDescriptor.getFileDescriptor();
                }
            }else {
                Uri uri = ContentUris.withAppendedId(albumArtUri,album);
                ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri,"r");
                if(pfd != null){
                    fileDescriptor = pfd.getFileDescriptor();
                }
            }

            options.inSampleSize = 1;
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFileDescriptor(fileDescriptor,null,options);
            options.inSampleSize = calculateInSampleSize(options,50,50);
            options.inJustDecodeBounds =false;
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;

            bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor,null,options);

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

        return  bitmap;
    }  

当我知道albumid的时候,直接用流来进行读取:

public static Bitmap getArtwork(ContentResolver resolver,int songid,int albumid ,boolean allowdefalut,boolean samll){
        if(albumid <0 ){
            if(songid <0){
                Bitmap bitmap = getArtWorkFormFile(resolver,songid,albumid);
                if(bitmap !=null){
                    return bitmap;
                }
            }
            return null;
        }
        Uri uri = ContentUris.withAppendedId(albumArtUri,albumid);
        if(uri != null){
            InputStream inputStream = null;
            try{
                inputStream = resolver.openInputStream(uri);
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 1;
                options.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(inputStream,null,options);
                if(samll){
                    options.inSampleSize = calculateInSampleSize(options,50,50);
                }else {
                    options.inSampleSize = calculateInSampleSize(options,600,600);
                }
                options.inJustDecodeBounds= false;
                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                inputStream = resolver.openInputStream(uri);
                return BitmapFactory.decodeStream(inputStream,null,options);


            }catch (FileNotFoundException e){
                Bitmap bitmap = getArtWorkFormFile(resolver,songid,albumid);
                if(bitmap != null){
                    if(bitmap.getConfig() == null){
                        bitmap = bitmap.copy(Bitmap.Config.RGB_565,false);
                        if(bitmap == null && allowdefalut){
                            return  null;
                        }
                    }
                }

                return bitmap;

            }
        }
        return null;
    }

   public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

public Bitmap.Config inPreferredConfig

在API级别1中添加
如果这是非空的,解码器将尝试将其解码为该内部配置。如果它为空,或者不能满足请求,则解码器将尝试根据系统的屏幕深度和原始图像的特征来选择最佳匹配配置,例如,如果它具有每像素alpha(需要一个配置也可以一样)。ARGB_8888默认情况下,图像加载了配置。

Bitmap.Config:
可能的位图配置。位图配置描述像素的存储方式。这会影响质量(颜色深度)以及显示透明/半透明颜色的能力。

Bitmap.Config .ALPHA_8 每个像素存储为单透明(alpha)通道。
Bitmap.Config .ARGB_4444 这个字段在API级别13中已被弃用。由于此配置的质量差,建议使用ARGB_8888。
Bitmap.Config .ARGB_8888 每个像素存储在4个字节上。每个通道(用于半透明的RGB和alpha)以8位精度存储(256个可能的值)。该配置非常灵活,提供最好的质量。应尽可能使用。
Bitmap.Config .RGB_565 每个像素存储在2个字节上,只有RGB通道被编码:红色存储有5位精度(32个可能值),绿色以6位精度存储(64个可能值),蓝色存储5位精确。 此配置可能会根据源的配置产生轻微的视觉伪影。例如,没有抖动,结果可能会显示绿色的色调。为了获得更好的效果,应该应用抖动。当使用不需要高色彩保真度的不透明位图时,此配置可能很有用。

展开阅读全文

没有更多推荐了,返回首页