編輯:關於Android編程
一丶本地音樂加載相當於就是listVIew應用
扣丁音樂1.0前部分(gif圖大小限制)演示:
實體類Mp3Info(歌曲相關數據及get和set方法)
public class Mp3Info { private long id; private String title;//歌名 private String artist;//藝術家 private String album;//專輯 private long albumId; private long duration;//時長 private long size;//大小 private String url;//路徑 private int isMusic;//是否為音樂 public long getId() { return id; } public void setId(long 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 long getAlbumId() { return albumId; } public void setAlbumId(long albumId) { this.albumId = albumId; } public long getDuration() { return duration; } public void setDuration(long duration) { this.duration = duration; } 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; } public int getIsMusic() { return isMusic; } public void setIsMusic(int isMusic) { this.isMusic = isMusic; } @Override public String toString() { return "Mp3Info{" + "id=" + id + ", title='" + title + '\'' + ", artist='" + artist + '\'' + ", album='" + album + '\'' + ", albumId=" + albumId + ", duration=" + duration + ", size=" + size + ", url='" + url + '\'' + ", isMusic=" + isMusic + '}'; } }工具類MediaUtils(實現例如篩選歌曲長度,時間格式化,圖片處理等)
public class MediaUtils { //獲取專輯封面的Uri private static final Uri albumArtUri = Uri.parse("content://media/external/audio/albumart"); /** * 獲取默認專輯圖片 */ public static Bitmap getDefaultArtwork(Context context,boolean small){ BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inPreferredConfig = Bitmap.Config.RGB_565; if(small){ return BitmapFactory.decodeStream(context.getResources().openRawResource(R.drawable.music_play),null,opts); } return BitmapFactory.decodeStream(context.getResources().openRawResource(R.drawable.music_play),null,opts); } /** * 從文件當中獲取專輯封面位圖 */ private static Bitmap getArtworkFromFile(Context context,long songid,long albumid){ Bitmap bm = null; if(albumid<0 && songid<0){ throw new IllegalArgumentException("Must specify an album or a song id"); } try { BitmapFactory.Options options = new BitmapFactory.Options(); FileDescriptor fd = null; if(albumid<0){ Uri uri = Uri.parse("content://media/external/audio/media" +songid+"albumart"); ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri,"r"); if(pfd!=null){ fd = pfd.getFileDescriptor(); } }else{ Uri uri = ContentUris.withAppendedId(albumArtUri,albumid); ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r"); if(pfd!=null){ fd = pfd.getFileDescriptor(); } } options.inSampleSize=1; //只進行大小判斷 options.inJustDecodeBounds = true; //調用此方法得到options得到圖片大小 BitmapFactory.decodeFileDescriptor(fd,null,options); //我們的目標是在800pixel的畫面上顯示 //所以需要調用computeSampleSize得到圖片縮放的比例 options.inSampleSize = 100; //我們得到了縮放的比例,現在開始正式讀入Bitmap數據 options.inJustDecodeBounds = false; options.inDither = false; options.inPreferredConfig = Bitmap.Config.ARGB_8888; //根據options參數,減少所需要的內存 bm = BitmapFactory.decodeFileDescriptor(fd,null,options); }catch (FileNotFoundException e){ e.printStackTrace(); } return bm; } /** * 獲取專輯封面位圖對象 */ public static Bitmap getArtwork(Context context,long song_id,long album_id,boolean allowdefault,boolean small){ if(album_id<0){ if(song_id<0){ Bitmap bm = getArtworkFromFile(context,song_id,-1); if(bm!=null){ return bm; } } if(allowdefault){ return getDefaultArtwork(context,small); } return null; } ContentResolver res = context.getContentResolver(); Uri uri = ContentUris.withAppendedId(albumArtUri,album_id); if(uri !=null){ InputStream in = null; try { in = res.openInputStream(uri); BitmapFactory.Options options = new BitmapFactory.Options(); //先指定原始大小 options.inSampleSize = 1; //只進行大小判斷 options.inJustDecodeBounds = true; //調用此方法得到options得到圖片的大小 BitmapFactory.decodeStream(in,null,options); //我們的目標是在你N pixel的畫面上顯示。所以需要調用computeSampleSize得到圖片縮放的比例 //這裡的target為800是根據默認專輯圖片代傲決定的,800只是測試數字但是試驗後發現完美的結合 if(small){ options.inSampleSize = computeSampleSize(options,40); }else { options.inSampleSize = computeSampleSize(options,600); } //我們得到了縮放比例,現在開始正式讀入Bitmap數據 options.inJustDecodeBounds = false; options.inDither = false; options.inPreferredConfig = Bitmap.Config.ARGB_8888; in = res.openInputStream(uri); return BitmapFactory.decodeStream(in,null,options); }catch (FileNotFoundException e){ Bitmap bm = getArtworkFromFile(context,song_id,album_id); if(bm!=null){ if(bm.getConfig()==null){ bm = bm.copy(Bitmap.Config.RGB_565,false); if(bm == null && allowdefault){ return getDefaultArtwork(context,small); } }else if(allowdefault){ bm = getDefaultArtwork(context,small); } return bm; } }finally { try { if(in != null){ in.close(); } }catch (IOException e){ e.printStackTrace(); } } } return null; } /** * 對圖片進行合適的縮放 */ public static int computeSampleSize(BitmapFactory.Options options,int target){ int w = options.outWidth; int h = options.outHeight; int candidateW = w / target; int candidateH = h / target; int candidate = Math.max(candidateW,candidateH); if(candidate == 0){ return 1; } if (candidate>1){ if((w>target)&&(w/candidate)activity_local_songs.xml(後面貼出)1){ if((h>target)&&(h/candidate) /** * 用於從數據庫中查詢歌曲的信息,保存在List當中 */ public static ArrayList getMp3Infos(Context context){ Cursor cursor = context.getContentResolver().query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, //最小音樂長度 MediaStore.Audio.Media.DURATION + ">=180000", null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER); ArrayList mp3Infos = new ArrayList (); for(int i=0;i _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));//專輯 long albumId = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));//專輯id 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));//路徑 int isMusic = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));//是否為音樂 if(isMusic!=0){ mp3Info.setId(id); mp3Info.setTitle(title); mp3Info.setArtist(artist); mp3Info.setAlbum(album); mp3Info.setAlbumId(albumId); mp3Info.setDuration(duration); mp3Info.setSize(size); mp3Info.setUrl(url); mp3Infos.add(mp3Info); } } cursor.close(); return mp3Infos; } /** * 格式化時間,將毫秒轉換為分:秒格式 */ public static String formatTime(long time){ String min = time / (1000 * 60)+""; String sec = time % (1000 * 60)+""; if(min.length()<2){ min = "0"+time / (1000 * 60)+""; }else{ min = time / (1000 * 60)+""; } if(sec.length()==4){ sec = "0"+(time % (1000 * 60))+""; }else if(sec.length()==3){ sec = "00"+(time % (1000 * 60))+""; }else if(sec.length()==2){ sec = "000"+(time % (1000 * 60))+""; }else if(sec.length()==1){ sec = "0000"+(time % (1000 * 60))+""; } return min + ":" +sec.trim().substring(0,2); }}
item_music_fragment.xml(略)
很明顯這裡我和視頻顯示得不一樣,歌曲圖片不好找顯示出來也不是很美觀,於是我顯示的是歌名,歌手,專輯,時間這個xml應個人喜好可調整
LocalSongsListAdapter.java
public class LocalSongsListAdapter extends BaseAdapter{ private Context context; private ArrayListLocalSongsActivity.javamp3Infos; public LocalSongsListAdapter(Context context,ArrayList mp3Infos){ this.context = context; this.mp3Infos = mp3Infos; } public void setMp3Infos(ArrayList mp3Infos){ this.mp3Infos = mp3Infos; } @Override public int getCount() { return mp3Infos.size(); } @Override public Object getItem(int position) { return mp3Infos.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder vh; if(convertView==null){ convertView = LayoutInflater.from(context).inflate(R.layout.item_music_list,null); vh = new ViewHolder(); vh.tv_song_name = (TextView)convertView.findViewById(R.id.tv_song_name); vh.tv_song_artist = (TextView)convertView.findViewById(R.id.tv_song_artist); vh.tv_song_album = (TextView)convertView.findViewById(R.id.tv_song_album); vh.tv_song_duration = (TextView)convertView.findViewById(R.id.tv_song_duration); convertView.setTag(vh); }else{ vh = (ViewHolder)convertView.getTag(); } //給控件賦值要寫在if語句外面,否則第一次加載數據失敗 Mp3Info mp3Info = mp3Infos.get(position); vh.tv_song_name.setText(mp3Info.getTitle()); vh.tv_song_artist.setText(mp3Info.getArtist()); vh.tv_song_album.setText(mp3Info.getAlbum()); vh.tv_song_duration.setText(MediaUtils.formatTime(mp3Info.getDuration())); return convertView; } static class ViewHolder{ TextView tv_song_name; TextView tv_song_artist; TextView tv_song_album; TextView tv_song_duration; } }
寫到這裡LocalSongsActivity.java裡面只需要初始化控件,後面再貼出
/** * 初始化本地音樂列表 */ private void initDate() { mp3Infos = MediaUtils.getMp3Infos(this); System.out.println(mp3Infos.size()); localSongsListAdapter = new LocalSongsListAdapter(this,mp3Infos); localSongsListAdapter.notifyDataSetChanged(); lv_local_songs_list.setAdapter(localSongsListAdapter); }
SD卡讀取權限,網絡權限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> <uses-permission android:name="android.permission.INTERNET"></uses-permission>
到這裡就能完成歌曲的加載了
由於項目需要,要修改已經開發好的應用包名,這本身很簡單,但是如果你沒找到門道,可能會白白浪費許多時間。修改包名有三個地方要改,這三個地方的修改一定要按順序來,否則你可能會
概述:一般情況下,我們知道View類有個View.OnTouchListener內部接口,通過重寫他的onTouch(View v, MotionEvent event)
貝塞爾曲線開發的藝術一句話概括貝塞爾曲線:將任意一條曲線轉化為精確的數學公式。很多繪圖工具中的鋼筆工具,就是典型的貝塞爾曲線的應用貝塞爾曲線中有一些比較關鍵的名詞,解釋如
1:自己最近在做了支付,遇到了一下問題先總結如下 第一條: Android快捷支付SDK Demo resultStatus={4001};memo={參數錯誤};