音乐播放器
1 package com.tan.lyc; 2 3 import java.io.BufferedInputStream; 4 import java.io.BufferedReader; 5 import java.io.ByteArrayOutputStream; 6 import java.io.File; 7 import java.io.FileInputStream; 8 import java.io.FileNotFoundException; 9 import java.io.FileOutputStream; 10 import java.io.FileWriter; 11 import java.io.IOException; 12 import java.io.InputStream; 13 import java.io.InputStreamReader; 14 import java.io.Reader; 15 import java.io.UnsupportedEncodingException; 16 import java.net.HttpURLConnection; 17 import java.net.MalformedURLException; 18 import java.net.ProtocolException; 19 import java.net.URL; 20 import java.util.ArrayList; 21 import java.util.List; 22 import java.net.HttpURLConnection; 23 import java.net.MalformedURLException; 24 import java.net.URLEncoder; 25 26 import org.json.JSONArray; 27 import org.json.JSONException; 28 import org.json.JSONObject; 29 30 import com.tan.myplay.MyApplication; 31 import com.tan.service.MusicPlayService; 32 33 import android.content.IntentSender.SendIntentException; 34 import android.util.Log; 35 36 public class LrcProcess { 37 private String url = "http://geci.me/api/lyric/"; 38 private List<LrcContent> lrcList; // List集合存放歌词内容对象 39 private LrcContent mLrcContent; // 声明一个歌词内容对象 40 private String lrc; 41 private ByteArrayOutputStream out; 42 private String songname, singer; 43 44 /** 45 * 无参构造函数用来实例化对象 46 */ 47 public LrcProcess() { 48 mLrcContent = new LrcContent(); 49 lrcList = new ArrayList<LrcContent>(); 50 } 51 52 /** 53 * 读取歌词 54 * 55 * @param path 56 * @param songname 57 * @param singer 58 * @return 59 */ 60 public String readLRC(String path, String singer, String songname) { 61 // 定义一个StringBuilder对象,用来存放歌词内容 62 StringBuilder stringBuilder = new StringBuilder(); 63 String s1 = path.substring(0, path.length() - 4); 64 s1 += ".lrc"; 65 Log.d("test", s1 + " path"); 66 Log.d("test","please tell me ok"); 67 File f = new File(s1); 68 // System.out.println(path); 69 try { 70 FileInputStream fis = new FileInputStream(f); 71 InputStreamReader isr = new InputStreamReader(fis, "utf-8"); 72 BufferedReader br = new BufferedReader(isr); 73 String s = ""; 74 while ((s = br.readLine()) != null) { 75 s = s.replace("[", ""); 76 s = s.replace("]", "@"); // 每一句话的分隔符 77 78 s = s.replaceAll("<[0-9]{3,5}>", ""); // 去掉每个字的时间标签,这里用到了正则表达式 79 80 String spiltLrcData[] = s.split("@"); 81 82 if (spiltLrcData.length > 1) { 83 84 mLrcContent.setLrcStr(spiltLrcData[1]); // 将每句话创建一个类的实例,歌词和对应时间赋值 85 int lycTime = time2Str(spiltLrcData[0]); 86 mLrcContent.setLrcTime(lycTime); 87 lrcList.add(mLrcContent); 88 89 mLrcContent = new LrcContent(); 90 } 91 } 92 } catch (FileNotFoundException e) { 93 e.printStackTrace(); 94 // Log.d("test", "findlrc"); 95 // findLrc(path, songname, singer); 96 // Log.d("test", "why not"); 97 test(path,songname, singer); 98 // readLRC(path, songname, singer); 99 stringBuilder.append("一丁点儿歌词都没找到,下载后再来找我把......."); 100 } catch (Exception e) { 101 e.printStackTrace(); 102 stringBuilder.append("没有读取到歌词....."); 103 } 104 return stringBuilder.toString(); 105 } 106 107 private void test(final String path,final String songname, final String singer) { 108 out = new ByteArrayOutputStream(); 109 new Thread() { 110 public void run() { 111 String url = null; 112 try { 113 url = setParams(songname, singer); 114 } catch (UnsupportedEncodingException e1) { 115 116 e1.printStackTrace(); 117 } 118 try { 119 URL url1 = new URL(url); 120 HttpURLConnection conn = (HttpURLConnection) url1 121 .openConnection(); 122 InputStream in = conn.getInputStream(); 123 byte[] data = new byte[1024]; 124 int len = 0; 125 126 while ((len = in.read(data)) != -1) { 127 Log.d("test", data + "data"); 128 out.write(data, 0, len); 129 } 130 out.flush(); 131 132 String json=new String(out.toByteArray()); 133 Log.d("test", new String(out.toByteArray())); 134 135 JSONObject jsonObject = null; 136 try { 137 jsonObject = new JSONObject(json); 138 } catch (JSONException e1) { 139 // TODO Auto-generated catch block 140 e1.printStackTrace(); 141 } 142 int count = 0; 143 try { 144 count = jsonObject.getInt("count"); 145 } catch (JSONException e) { 146 // TODO Auto-generated catch block 147 e.printStackTrace(); 148 } 149 Log.d("count", count + ""); 150 JSONArray array = null; 151 try { 152 array = jsonObject.getJSONArray("result"); 153 } catch (JSONException e) { 154 // TODO Auto-generated catch block 155 e.printStackTrace(); 156 } 157 try { 158 lrc = array.getJSONObject(0).getString("lrc"); 159 } catch (JSONException e) { 160 // TODO Auto-generated catch block 161 e.printStackTrace(); 162 } 163 164 URL url2 = new URL(lrc); 165 InputStream in1 = url2.openStream(); 166 BufferedReader reader = new BufferedReader( 167 new InputStreamReader(in1)); 168 String s1 = path.substring(0, path.length() - 4); 169 s1 += ".lrc"; 170 171 Log.d("test",s1+"file path"); 172 File file = new File(s1); 173 // FileOutputStream fout=new FileOutputStream(file); 174 FileWriter fw = new FileWriter(file); 175 String s = ""; 176 while ((s = reader.readLine()) != null) { 177 fw.write(s+"\n"); 178 Log.d("test", s); 179 } 180 fw.close(); 181 182 } catch (MalformedURLException e) { 183 // TODO Auto-generated catch block 184 e.printStackTrace(); 185 } catch (IOException e) { 186 // TODO Auto-generated catch block 187 e.printStackTrace(); 188 } 189 } 190 }.start(); 191 192 } 193 194 private void findLrc(final String path, String songname, String singer) { 195 196 String json = getJson(songname, singer); 197 198 Log.d("test", json + "json"); 199 String lrc = analysis(json); 200 Log.d("test", lrc + "lrc"); 201 makeFile(lrc, path); 202 203 } 204 205 protected void makeFile(final String lrc, final String path) { 206 new Thread() { 207 public void run() { 208 try { 209 URL url1 = new URL(lrc); 210 InputStream in = url1.openStream(); 211 BufferedReader reader = new BufferedReader( 212 new InputStreamReader(in)); 213 String s1 = path.substring(0, path.length() - 4); 214 s1 += ".lrc"; 215 int len = -1; 216 File file = new File(s1); 217 // FileOutputStream fout=new FileOutputStream(file); 218 FileWriter fw = new FileWriter(file); 219 String s = ""; 220 while ((s = reader.readLine()) != null) { 221 fw.write(s); 222 Log.d("test", s); 223 } 224 fw.close(); 225 } catch (Exception e) { 226 // TODO Auto-generated catch block 227 e.printStackTrace(); 228 } 229 }; 230 }.start(); 231 } 232 233 protected String analysis(final String json) { 234 new Thread() { 235 public void run() { 236 try { 237 JSONObject jsonObject = new JSONObject(json); 238 int count = jsonObject.getInt("count"); 239 Log.d("count", count + ""); 240 JSONArray array = jsonObject.getJSONArray("result"); 241 lrc = array.getJSONObject(0).getString("lrc"); 242 Log.d("test", "lrc dhajdjhaj" + lrc); 243 // 获取到lrc地址 244 } catch (Exception e) { 245 // TODO Auto-generated catch block 246 e.printStackTrace(); 247 } 248 } 249 }.start(); 250 return lrc; 251 } 252 253 private String getJson(final String songname,final String singer) { 254 out = new ByteArrayOutputStream(); 255 new Thread() { 256 public void run() { 257 InputStream inStream = null; 258 String url = null; 259 URL urlLrc = null; 260 try { 261 url = setParams(songname, singer); 262 } catch (UnsupportedEncodingException e1) { 263 // TODO Auto-generated catch block 264 e1.printStackTrace(); 265 } 266 try { 267 urlLrc = new URL(url); 268 } catch (MalformedURLException e) { 269 // TODO Auto-generated catch block 270 e.printStackTrace(); 271 } 272 Log.d("test", urlLrc + ""); 273 byte[] data = new byte[1024]; 274 int len = 0; 275 HttpURLConnection conn = null; 276 try { 277 conn = (HttpURLConnection) urlLrc.openConnection(); 278 } catch (IOException e) { 279 // TODO Auto-generated catch block 280 e.printStackTrace(); 281 } 282 try { 283 conn.setRequestMethod("GET"); 284 } catch (ProtocolException e) { 285 // TODO Auto-generated catch block 286 e.printStackTrace(); 287 }// 使用GET方法获取 288 conn.setConnectTimeout(5000); 289 Log.d("test", "conn" + conn); 290 try { 291 conn.connect(); 292 } catch (IOException e) { 293 // TODO Auto-generated catch block 294 e.printStackTrace(); 295 } 296 297 try { 298 inStream = conn.getInputStream(); 299 } catch (IOException e) { 300 // TODO Auto-generated catch block 301 e.printStackTrace(); 302 } 303 304 Log.d("test", inStream + "instream"); 305 try { 306 while ((len = inStream.read(data)) != -1) { 307 Log.d("test", data + "data"); 308 out.write(data, 0, len); 309 } 310 } catch (IOException e) { 311 // TODO Auto-generated catch block 312 e.printStackTrace(); 313 } 314 try { 315 out.flush(); 316 } catch (IOException e) { 317 // TODO Auto-generated catch block 318 e.printStackTrace(); 319 } 320 Log.d("test", data.toString()); 321 try { 322 inStream.close(); 323 } catch (IOException e) { 324 // TODO Auto-generated catch block 325 e.printStackTrace(); 326 } 327 try { 328 out.close(); 329 } catch (IOException e) { 330 // TODO Auto-generated catch block 331 e.printStackTrace(); 332 } 333 // 334 } 335 }.start(); 336 return new String(out.toByteArray()); 337 } 338 339 private String setParams(String songname, String singer) 340 throws UnsupportedEncodingException { 341 String song = URLEncoder.encode(songname, "UTF-8"); 342 String sing = URLEncoder.encode(singer, "UTF-8"); 343 return url + song + "/" + sing; 344 } 345 346 private void createFile(String path, String songname, String singer) { 347 348 } 349 350 public int TimeStr(String timeStr) { 351 352 timeStr = timeStr.replace(":", "."); 353 timeStr = timeStr.replace(".", "@"); 354 355 String timeData[] = timeStr.split("@"); 356 357 // 分离出分、秒并转换为整型 358 int minute = Integer.parseInt(timeData[0]); 359 int second = Integer.parseInt(timeData[1]); 360 int millisecond = Integer.parseInt(timeData[2]); 361 362 // 计算上一行与下一行的时间转换为毫秒数 363 int currentTime = (minute * 60 + second) * 1000 + millisecond * 10; 364 365 return currentTime; 366 } 367 368 /** 369 * 解析歌词时间 歌词内容格式如下: [00:02.32]陈奕迅 [00:03.43]好久不见 [00:05.22]歌词制作 王涛 370 * 371 * @param timeStr 372 * @return 373 */ 374 public int time2Str(String timeStr) { // 将分:秒:毫秒转化为长整型的数 375 timeStr = timeStr.replace(":", "."); 376 timeStr = timeStr.replace(".", "@"); 377 378 String timeData[] = timeStr.split("@"); 379 380 int min = Integer.parseInt(timeData[0]); 381 int sec = Integer.parseInt(timeData[1]); 382 int millSec = Integer.parseInt(timeData[2]); 383 384 int currentTime = (min * 60 + sec) * 1000 + millSec * 10; 385 return currentTime; 386 } 387 388 public List<LrcContent> getLrcList() { 389 return lrcList; 390 } 391 392 }
url需要utf-8转换
否则得不到的对应的数据,既找不到对应的url
其中如果找不到歌词会在歌词迷上搜索并下载
1 package com.tan.sortadapter; 2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 import com.tan.bean.Music; 8 import com.tan.myplay.R; 9 10 import android.content.ContentResolver; 11 import android.content.ContentUris; 12 import android.content.Context; 13 import android.database.Cursor; 14 import android.database.sqlite.SQLiteDatabase; 15 import android.graphics.Bitmap; 16 import android.graphics.BitmapFactory; 17 import android.net.Uri; 18 import android.provider.MediaStore; 19 import android.provider.MediaStore.Audio; 20 import android.provider.MediaStore.Images; 21 import android.util.Log; 22 23 public class ReadDataFromContentProvider { 24 25 /* 26 * 读取所有图片 27 */ 28 public static void readImage(Context context) { 29 ContentResolver resolver = context.getContentResolver(); 30 Uri imgUri = Images.Media.EXTERNAL_CONTENT_URI; 31 String[] columns = new String[] { Images.Media.TITLE, 32 Images.Media.DATA, Images.Media.SIZE, Images.Media.MIME_TYPE // 类型 33 }; 34 Cursor cursor = resolver.query(imgUri, columns, null, null, null); 35 36 if (null != cursor && cursor.getCount() > 0) { 37 while (cursor.moveToNext()) { 38 Log.e("imgs", cursor.getString(0) + "\t" + cursor.getString(3)); 39 } 40 } 41 if (null != cursor) { 42 cursor.close(); 43 } 44 } 45 46 public static List<Music> readAudio(Context context) { 47 ContentResolver resolver = context.getContentResolver(); 48 System.out.println("recovetsk mkahn i"); 49 Uri audioUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 50 String[] columns = { Audio.Media.TITLE, // 歌名 51 MediaStore.Audio.Media.DATA, // 路径 52 MediaStore.Audio.Media.ARTIST, // 演唱者 53 MediaStore.Audio.Media.ALBUM, // 专辑名 54 MediaStore.Audio.Media.DURATION, // 音频文件长度,毫秒 55 MediaStore.Audio.Media.ALBUM_KEY// 用来读取专辑图片时使用 56 }; 57 List<Music> data = null; 58 Cursor cursor = resolver.query(audioUri, columns, null,null, null); 59 // System.out.println("query mkahn i"); 60 // System.out.println(cursor.getCount()+"nbdajbvdjha"); 61 if (null != cursor && cursor.getCount() > 0) { 62 data = new ArrayList<Music>(); 63 // System.out.println("cursor is nou null"); 64 CharacterParser characterParser = CharacterParser.getInstance(); 65 while (cursor.moveToNext()) { 66 // 读到一个音频 67 // 读取该音频的专辑图片信息 68 // System.out.println("find data"); 69 70 // Uri albumUri = Audio.Albums.EXTERNAL_CONTENT_URI; 71 // Cursor albumCursor = resolver.query(albumUri, new 72 // String[]{Audio.Albums.ALBUM_ART}, Audio.Albums.ALBUM_KEY 73 // +"=?", new String[]{albumKey}, null) ; 74 // if(albumCursor != null && albumCursor.getCount() > 0) { 75 // albumCursor.moveToNext() ; 76 // String albumPath = albumCursor.getString(0); 77 // bmp = BitmapFactory.decodeFile(albumPath) ; 78 // albumCursor.close() ; 79 // } 80 long albumKey=cursor.getLong(5); 81 String album_uri = "content://media/external/audio/albumart"; // 专辑Uri对应的字符串 82 Uri albumUri = ContentUris.withAppendedId(Uri.parse(album_uri), 83 albumKey); 84 // 取图片 ==> 得到一个输入流 85 Bitmap bim = null; 86 try { 87 InputStream is = context.getContentResolver() 88 .openInputStream(albumUri); 89 System.out.println("is inputstream"); 90 if (null != is) { 91 System.out.println("is not null inputstream"); 92 bim = BitmapFactory.decodeStream(is); 93 } 94 else{ 95 bim=BitmapFactory.decodeResource(context.getResources(), R.drawable.bc1); 96 } 97 } catch (Exception e) { 98 e.printStackTrace(); 99 } 100 101 102 String songname = cursor.getString(0); 103 String url = cursor.getString(1); 104 String singer = cursor.getString(2); 105 String belongto = cursor.getString(3); 106 Long duration = cursor.getLong(4); 107 108 // Bitmap bitmap=bmp; 109 String pinyin = characterParser.getSelling(songname); 110 String sortString = pinyin.substring(0, 1).toUpperCase(); 111 String sortLetter; 112 // 正则表达式,判断首字母是否是英文字母 113 if (sortString.matches("[A-Z]")) { 114 sortLetter = sortString.toUpperCase(); 115 } else { 116 sortLetter = "#"; 117 } 118 Music music = new Music(url, songname, singer, sortLetter, 119 belongto, duration,bim); 120 data.add(music); 121 // System.out.println(music); 122 123 // data.add(new Music(cursor.getString(0), cursor.getString(1), 124 // cursor.getString(2), cursor.getString(3) , cursor.getLong(4) 125 // , bmp)) ; 126 } 127 } 128 if (null != cursor) { 129 cursor.close(); 130 } 131 return data; 132 } 133 134 // private static String getAlbumArt(Context context,int album_id) { 135 // String mUriAlbums = "content://media/external/audio/albums"; 136 // String[] projection = new String[] { "album_art" }; 137 // Cursor cur = context.getContentResolver().query( 138 // Uri.parse(mUriAlbums + "/" + Integer.toString(album_id)), 139 // projection, null, null, null); 140 // String album_art = null; 141 // if (cur.getCount() > 0 && cur.getColumnCount() > 0) { 142 // cur.moveToNext(); 143 // album_art = cur.getString(0); 144 // } 145 // cur.close(); 146 // cur = null; 147 // return album_art; 148 // } 149 }
从contentprovider中读取本机音乐信息并用music封装
1 package com.tan.bean; 2 3 import android.graphics.Bitmap; 4 5 public class Music { 6 private String url; 7 private String songName; 8 private String singer; 9 private String sortLetters; 10 private String belongto; 11 private Long duration; 12 private Bitmap bitmap; 13 /* 14 * sortLetters 与 songName 相匹配 15 * 也可扩展成能跟singer匹配 16 */ 17 18 public Music() { 19 super(); 20 } 21 22 23 public Music( String url, String songName, String singer, 24 String sortLetters, String belongto, Long duration) { 25 super(); 26 this.url = url; 27 this.songName = songName; 28 this.singer = singer; 29 this.sortLetters = sortLetters; 30 this.belongto = belongto; 31 this.duration = duration; 32 } 33 34 35 36 37 38 public Music(String url, String songName, String singer, 39 String sortLetters, String belongto, Long duration, Bitmap bitmap) { 40 super(); 41 this.url = url; 42 this.songName = songName; 43 this.singer = singer; 44 this.sortLetters = sortLetters; 45 this.belongto = belongto; 46 this.duration = duration; 47 this.bitmap = bitmap; 48 } 49 50 51 @Override 52 public String toString() { 53 return "Music [url=" + url + ", songName=" + songName + ", singer=" 54 + singer + ", sortLetters=" + sortLetters + ", belongto=" 55 + belongto + ", duration=" + duration 56 + "]"; 57 } 58 59 60 public String getBelongto() { 61 return belongto; 62 } 63 64 65 public void setBelongto(String belongto) { 66 this.belongto = belongto; 67 } 68 69 70 public Long getDuration() { 71 return duration; 72 } 73 74 public void setDuration(Long duration) { 75 this.duration = duration; 76 } 77 78 public Bitmap getBitmap() { 79 return bitmap; 80 } 81 82 public void setBitmap(Bitmap bitmap) { 83 this.bitmap = bitmap; 84 } 85 86 public String getSortLetters() { 87 return sortLetters; 88 } 89 90 public void setSortLetters(String sortLetters) { 91 this.sortLetters = sortLetters; 92 } 93 94 95 96 public String getUrl() { 97 return url; 98 } 99 100 public void setUrl(String url) { 101 this.url = url; 102 } 103 104 public String getSongName() { 105 return songName; 106 } 107 108 public void setSongName(String songName) { 109 this.songName = songName; 110 } 111 112 public String getSinger() { 113 return singer; 114 } 115 116 public void setSinger(String singer) { 117 this.singer = singer; 118 } 119 120 }
音乐的存放
实现Parcelable就是为了进行序列化
永久性保存对象,保存对象的字节序列到本地文件中;
通过序列化对象在网络中传递对象;
通过序列化在进程间传递对象。
1 package com.tan.lyc; 2 3 public class LrcContent { 4 private String lrcStr; //歌词内容 5 private long lrcTime; //歌词当前时间 6 public String getLrcStr() { 7 return lrcStr; 8 } 9 public void setLrcStr(String lrcStr) { 10 this.lrcStr = lrcStr; 11 } 12 public long getLrcTime() { 13 return lrcTime; 14 } 15 public void setLrcTime(long lrcTime) { 16 this.lrcTime = lrcTime; 17 } 18 19 }
存放歌词信息 即时间加字段
1 package com.tan.lyc; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.content.Context; 7 import android.graphics.Canvas; 8 import android.graphics.Color; 9 import android.graphics.Paint; 10 import android.graphics.Typeface; 11 import android.util.AttributeSet; 12 import android.widget.TextView; 13 14 15 /** 16 * 类说明:自定义绘画歌词,产生滚动效果 17 */ 18 19 public class LrcView extends TextView { 20 21 private float width; 22 private float high; 23 private Paint CurrentPaint; 24 private Paint NotCurrentPaint; 25 private float TextHigh = 60; 26 private float TextSize = 30; 27 private int Index = 0; 28 29 private List<LrcContent> mSentenceEntities = new ArrayList<LrcContent>(); 30 31 public void setSentenceEntities(List<LrcContent> mSentenceEntities) { 32 this.mSentenceEntities = mSentenceEntities; 33 } 34 35 public LrcView(Context context) { 36 super(context); 37 init(); 38 } 39 40 public LrcView(Context context, AttributeSet attrs, int defStyle) { 41 super(context, attrs, defStyle); 42 init(); 43 } 44 45 public LrcView(Context context, AttributeSet attrs) { 46 super(context, attrs); 47 init(); 48 } 49 50 private void init() { 51 setFocusable(true); 52 53 // 高亮部分 54 CurrentPaint = new Paint(); 55 CurrentPaint.setAntiAlias(true); 56 CurrentPaint.setTextAlign(Paint.Align.CENTER); 57 58 // 非高亮部分 59 NotCurrentPaint = new Paint(); 60 NotCurrentPaint.setAntiAlias(true); 61 NotCurrentPaint.setTextAlign(Paint.Align.CENTER); 62 } 63 64 @Override 65 public void onDraw(Canvas canvas) { 66 super.onDraw(canvas); 67 if (canvas == null) { 68 return; 69 } 70 71 CurrentPaint.setColor(Color.argb(210, 251, 248, 29)); 72 NotCurrentPaint.setColor(Color.argb(140, 255, 255, 255)); 73 74 CurrentPaint.setTextSize(45); 75 CurrentPaint.setTypeface(Typeface.SERIF); 76 77 NotCurrentPaint.setTextSize(TextSize); 78 NotCurrentPaint.setTypeface(Typeface.DEFAULT); 79 80 try { 81 setText(""); 82 canvas.drawText(mSentenceEntities.get(Index).getLrcStr(), width / 2, 83 high / 2, CurrentPaint); 84 85 float tempY = high / 2; 86 // 画出本句之前的句子 87 for (int i = Index - 1; i >= 0; i--) { 88 // 向上推移 89 tempY = tempY - TextHigh; 90 91 canvas.drawText(mSentenceEntities.get(i).getLrcStr(), width / 2, 92 tempY, NotCurrentPaint); 93 } 94 tempY = high / 2; 95 // 画出本句之后的句子 96 for (int i = Index + 1; i < mSentenceEntities.size(); i++) { 97 // 往下推移 98 tempY = tempY + TextHigh; 99 canvas.drawText(mSentenceEntities.get(i).getLrcStr(), width / 2, 100 tempY, NotCurrentPaint); 101 } 102 } catch (Exception e) { 103 setText("木有歌词文件,赶紧去下载吧..."); 104 } 105 } 106 107 @Override 108 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 109 super.onSizeChanged(w, h, oldw, oldh); 110 111 this.width = w; 112 this.high = h; 113 } 114 115 public void SetIndex(int index) { 116 this.Index = index; 117 } 118 }
ondraw方法用来实现歌词的滚动
1 package com.tan.service; 2 3 import com.tan.myplay.MainActivity; 4 import com.tan.myplay.MusicPlayActivity; 5 import com.tan.myplay.MyApplication; 6 import com.tan.myplay.NotiReceiver; 7 import com.tan.myplay.R; 8 import com.tan.service.MusicPlayService.LocalBinder; 9 10 import android.app.Notification; 11 import android.app.NotificationManager; 12 import android.app.PendingIntent; 13 import android.app.Service; 14 import android.content.ComponentName; 15 import android.content.Context; 16 import android.content.Intent; 17 import android.content.IntentFilter; 18 import android.os.Binder; 19 import android.os.Bundle; 20 import android.os.Handler; 21 import android.os.IBinder; 22 import android.os.Message; 23 import android.util.Log; 24 import android.widget.RemoteViews; 25 26 public class NotiService extends Service { 27 28 private NotificationManager notificationManager; 29 private Notification notification; 30 private MusicPlayService service; 31 private Handler handler; 32 private Context context; 33 private final IBinder mBinder = new LocalBinder1(); 34 35 public NotiService() { 36 } 37 38 @Override 39 public IBinder onBind(Intent intent) { 40 return mBinder; 41 } 42 43 public class LocalBinder1 extends Binder { 44 public NotiService getService() { 45 return NotiService.this; 46 } 47 } 48 @Override 49 public void onCreate() { 50 MyApplication application = (MyApplication) getApplication(); 51 service = application.getmService(); 52 handler = new Handler() { 53 @Override 54 public void handleMessage(Message msg) { 55 Bundle bundle = msg.getData(); 56 String action = bundle.getString("action"); 57 if (action.equals(MainActivity.lastAction)) { 58 service.setCurrentTime(0); 59 service.frontMusic(); 60 61 } else if (action.equals(MainActivity.nextAction)) { 62 service.setCurrentTime(0); 63 service.nextMusic(); 64 65 } else if (action.equals(MainActivity.playAction)) { 66 service.pausePlay(); 67 }else if(action.equals(MainActivity.startAction)){ 68 service.playMusic(); 69 } 70 71 initNotification(); 72 } 73 }; 74 // System.out.println("handler ok"); 75 76 NotiReceiver notiReceiver = new NotiReceiver(handler); 77 IntentFilter fil = new IntentFilter(); 78 fil.addAction(MainActivity.nextAction); 79 fil.addAction(MainActivity.playAction); 80 fil.addAction(MainActivity.lastAction); 81 fil.addAction(MainActivity.startAction); 82 registerReceiver(notiReceiver, fil); 83 // System.out.println("register ok"); 84 initNotification(); 85 // System.out.println("error here"); 86 } 87 88 @Override 89 public int onStartCommand(Intent intent, int flags, int startId) { 90 // TODO Auto-generated method stub 91 initNotification(); 92 return super.onStartCommand(intent, flags, startId); 93 } 94 95 96 97 private void initNotification() { 98 Log.d("test", "start hkahkfhkahfkhajfkjafahn"); 99 notification = new Notification(R.drawable.ic_launcher, "lose音乐", 100 System.currentTimeMillis()); 101 notificationManager = (NotificationManager) getSystemService(getApplicationContext().NOTIFICATION_SERVICE); 102 // 设置不消失(应用没退出的话) 103 notification.flags = Notification.FLAG_ONGOING_EVENT; 104 RemoteViews contentViews = new RemoteViews(getPackageName(), 105 R.layout.notification); 106 107 contentViews.setImageViewResource(R.id.noti_showlyric, 108 R.drawable.ic_launcher); 109 110 contentViews.setTextViewText(R.id.noti_songname, service.getSongName()); 111 contentViews.setTextViewText(R.id.noti_songsinger, service.getSingerName()); 112 113 contentViews.setImageViewResource(R.id.noti_lastsong, 114 R.drawable.latest1); 115 contentViews.setImageViewResource(R.id.noti_nextsong, R.drawable.next1); 116 117 Log.d("test", "start dadljalhdkahk initno"); 118 if(service.isPlay()){ 119 contentViews.setImageViewResource(R.id.noti_playbt, 120 R.drawable.pause1); 121 }else{ 122 contentViews.setImageViewResource(R.id.noti_playbt, 123 R.drawable.play1); 124 } 125 126 Log.d("test","servieces error"); 127 notification.contentView = contentViews; 128 129 Intent previousButtonIntent = new Intent(MainActivity.lastAction); 130 PendingIntent pendPreviousButtonIntent = PendingIntent.getBroadcast( 131 this, 0, previousButtonIntent, 0); 132 contentViews.setOnClickPendingIntent(R.id.noti_lastsong, 133 pendPreviousButtonIntent); 134 135 Intent nextButtonIntent = new Intent(MainActivity.nextAction); 136 PendingIntent pendNextButtonIntent = PendingIntent.getBroadcast(this, 137 0, nextButtonIntent, 0); 138 contentViews.setOnClickPendingIntent(R.id.noti_nextsong, 139 pendNextButtonIntent); 140 141 Intent playButtonIntent = new Intent(MainActivity.playAction); 142 PendingIntent pendPlayButtonIntent = PendingIntent.getBroadcast(this, 143 0, playButtonIntent, 0); 144 contentViews.setOnClickPendingIntent(R.id.noti_playbt, 145 pendPlayButtonIntent); 146 147 Intent notificationIntent = new Intent(this, MainActivity.class); 148 PendingIntent contentIntent = PendingIntent.getActivity(this, 0, 149 notificationIntent, 0); 150 notification.contentIntent = contentIntent; 151 notificationManager.notify(0, notification); 152 Log.d("test", "adadad.la initno"); 153 } 154 155 public void setContext(Context context) { 156 this.context = context; 157 } 158 159 160 }
应用退出后,能够继续响应通知点击事件
/* * Filename CharacterParser.java * Company 上海乐问-浦东分公司。 * @author LuRuihui * @version 0.1 */ package com.tan.sortadapter; /** * Java汉字转换为拼音 * */ public class CharacterParser { private static int[] pyvalue = new int[] {-20319, -20317, -20304, -20295, -20292, -20283, -20265, -20257, -20242, -20230, -20051, -20036, -20032, -20026, -20002, -19990, -19986, -19982, -19976, -19805, -19784, -19775, -19774, -19763, -19756, -19751, -19746, -19741, -19739, -19728, -19725, -19715, -19540, -19531, -19525, -19515, -19500, -19484, -19479, -19467, -19289, -19288, -19281, -19275, -19270, -19263, -19261, -19249, -19243, -19242, -19238, -19235, -19227, -19224, -19218, -19212, -19038, -19023, -19018, -19006, -19003, -18996, -18977, -18961, -18952, -18783, -18774, -18773, -18763, -18756, -18741, -18735, -18731, -18722, -18710, -18697, -18696, -18526, -18518, -18501, -18490, -18478, -18463, -18448, -18447, -18446, -18239, -18237, -18231, -18220, -18211, -18201, -18184, -18183, -18181, -18012, -17997, -17988, -17970, -17964, -17961, -17950, -17947, -17931, -17928, -17922, -17759, -17752, -17733, -17730, -17721, -17703, -17701, -17697, -17692, -17683, -17676, -17496, -17487, -17482, -17468, -17454, -17433, -17427, -17417, -17202, -17185, -16983, -16970, -16942, -16915, -16733, -16708, -16706, -16689, -16664, -16657, -16647, -16474, -16470, -16465, -16459, -16452, -16448, -16433, -16429, -16427, -16423, -16419, -16412, -16407, -16403, -16401, -16393, -16220, -16216, -16212, -16205, -16202, -16187, -16180, -16171, -16169, -16158, -16155, -15959, -15958, -15944, -15933, -15920, -15915, -15903, -15889, -15878, -15707, -15701, -15681, -15667, -15661, -15659, -15652, -15640, -15631, -15625, -15454, -15448, -15436, -15435, -15419, -15416, -15408, -15394, -15385, -15377, -15375, -15369, -15363, -15362, -15183, -15180, -15165, -15158, -15153, -15150, -15149, -15144, -15143, -15141, -15140, -15139, -15128, -15121, -15119, -15117, -15110, -15109, -14941, -14937, -14933, -14930, -14929, -14928, -14926, -14922, -14921, -14914, -14908, -14902, -14894, -14889, -14882, -14873, -14871, -14857, -14678, -14674, -14670, -14668, -14663, -14654, -14645, -14630, -14594, -14429, -14407, -14399, -14384, -14379, -14368, -14355, -14353, -14345, -14170, -14159, -14151, -14149, -14145, -14140, -14137, -14135, -14125, -14123, -14122, -14112, -14109, -14099, -14097, -14094, -14092, -14090, -14087, -14083, -13917, -13914, -13910, -13907, -13906, -13905, -13896, -13894, -13878, -13870, -13859, -13847, -13831, -13658, -13611, -13601, -13406, -13404, -13400, -13398, -13395, -13391, -13387, -13383, -13367, -13359, -13356, -13343, -13340, -13329, -13326, -13318, -13147, -13138, -13120, -13107, -13096, -13095, -13091, -13076, -13068, -13063, -13060, -12888, -12875, -12871, -12860, -12858, -12852, -12849, -12838, -12831, -12829, -12812, -12802, -12607, -12597, -12594, -12585, -12556, -12359, -12346, -12320, -12300, -12120, -12099, -12089, -12074, -12067, -12058, -12039, -11867, -11861, -11847, -11831, -11798, -11781, -11604, -11589, -11536, -11358, -11340, -11339, -11324, -11303, -11097, -11077, -11067, -11055, -11052, -11045, -11041, -11038, -11024, -11020, -11019, -11018, -11014, -10838, -10832, -10815, -10800, -10790, -10780, -10764, -10587, -10544, -10533, -10519, -10331, -10329, -10328, -10322, -10315, -10309, -10307, -10296, -10281, -10274, -10270, -10262, -10260, -10256, -10254}; public static String[] pystr = new String[] {"a", "ai", "an", "ang", "ao", "ba", "bai", "ban", "bang", "bao", "bei", "ben", "beng", "bi", "bian", "biao", "bie", "bin", "bing", "bo", "bu", "ca", "cai", "can", "cang", "cao", "ce", "ceng", "cha", "chai", "chan", "chang", "chao", "che", "chen", "cheng", "chi", "chong", "chou", "chu", "chuai", "chuan", "chuang", "chui", "chun", "chuo", "ci", "cong", "cou", "cu", "cuan", "cui", "cun", "cuo", "da", "dai", "dan", "dang", "dao", "de", "deng", "di", "dian", "diao", "die", "ding", "diu", "dong", "dou", "du", "duan", "dui", "dun", "duo", "e", "en", "er", "fa", "fan", "fang", "fei", "fen", "feng", "fo", "fou", "fu", "ga", "gai", "gan", "gang", "gao", "ge", "gei", "gen", "geng", "gong", "gou", "gu", "gua", "guai", "guan", "guang", "gui", "gun", "guo", "ha", "hai", "han", "hang", "hao", "he", "hei", "hen", "heng", "hong", "hou", "hu", "hua", "huai", "huan", "huang", "hui", "hun", "huo", "ji", "jia", "jian", "jiang", "jiao", "jie", "jin", "jing", "jiong", "jiu", "ju", "juan", "jue", "jun", "ka", "kai", "kan", "kang", "kao", "ke", "ken", "keng", "kong", "kou", "ku", "kua", "kuai", "kuan", "kuang", "kui", "kun", "kuo", "la", "lai", "lan", "lang", "lao", "le", "lei", "leng", "li", "lia", "lian", "liang", "liao", "lie", "lin", "ling", "liu", "long", "lou", "lu", "lv", "luan", "lue", "lun", "luo", "ma", "mai", "man", "mang", "mao", "me", "mei", "men", "meng", "mi", "mian", "miao", "mie", "min", "ming", "miu", "mo", "mou", "mu", "na", "nai", "nan", "nang", "nao", "ne", "nei", "nen", "neng", "ni", "nian", "niang", "niao", "nie", "nin", "ning", "niu", "nong", "nu", "nv", "nuan", "nue", "nuo", "o", "ou", "pa", "pai", "pan", "pang", "pao", "pei", "pen", "peng", "pi", "pian", "piao", "pie", "pin", "ping", "po", "pu", "qi", "qia", "qian", "qiang", "qiao", "qie", "qin", "qing", "qiong", "qiu", "qu", "quan", "que", "qun", "ran", "rang", "rao", "re", "ren", "reng", "ri", "rong", "rou", "ru", "ruan", "rui", "run", "ruo", "sa", "sai", "san", "sang", "sao", "se", "sen", "seng", "sha", "shai", "shan", "shang", "shao", "she", "shen", "sheng", "shi", "shou", "shu", "shua", "shuai", "shuan", "shuang", "shui", "shun", "shuo", "si", "song", "sou", "su", "suan", "sui", "sun", "suo", "ta", "tai", "tan", "tang", "tao", "te", "teng", "ti", "tian", "tiao", "tie", "ting", "tong", "tou", "tu", "tuan", "tui", "tun", "tuo", "wa", "wai", "wan", "wang", "wei", "wen", "weng", "wo", "wu", "xi", "xia", "xian", "xiang", "xiao", "xie", "xin", "xing", "xiong", "xiu", "xu", "xuan", "xue", "xun", "ya", "yan", "yang", "yao", "ye", "yi", "yin", "ying", "yo", "yong", "you", "yu", "yuan", "yue", "yun", "za", "zai", "zan", "zang", "zao", "ze", "zei", "zen", "zeng", "zha", "zhai", "zhan", "zhang", "zhao", "zhe", "zhen", "zheng", "zhi", "zhong", "zhou", "zhu", "zhua", "zhuai", "zhuan", "zhuang", "zhui", "zhun", "zhuo", "zi", "zong", "zou", "zu", "zuan", "zui", "zun", "zuo"}; private StringBuilder buffer; private String resource; private static CharacterParser characterParser = new CharacterParser(); public static CharacterParser getInstance() { return characterParser; } public String getResource() { return resource; } public void setResource(String resource) { this.resource = resource; } /** * 汉字转成ASCII码 * * @param chs * @return */ private int getChsAscii(String chs) { int asc = 0; try { byte[] bytes = chs.getBytes("gb2312"); if (bytes == null || bytes.length > 2 || bytes.length <= 0) { throw new RuntimeException("illegal resource string"); } if (bytes.length == 1) { asc = bytes[0]; } if (bytes.length == 2) { int hightByte = 256 + bytes[0]; int lowByte = 256 + bytes[1]; asc = (256 * hightByte + lowByte) - 256 * 256; } } catch (Exception e) { System.out.println("ERROR:ChineseSpelling.class-getChsAscii(String chs)" + e); } return asc; } /** * 单字解析 * * @param str * @return */ public String convert(String str) { String result = null; int ascii = getChsAscii(str); if (ascii > 0 && ascii < 160) { result = String.valueOf((char) ascii); } else { for (int i = (pyvalue.length - 1); i >= 0; i--) { if (pyvalue[i] <= ascii) { result = pystr[i]; break; } } } return result; } /** * 词组解析 * * @param chs * @return */ public String getSelling(String chs) { String key, value; buffer = new StringBuilder(); for (int i = 0; i < chs.length(); i++) { key = chs.substring(i, i + 1); if (key.getBytes().length >= 2) { value = (String) convert(key); if (value == null) { value = "unknown"; } } else { value = key; } buffer.append(value); } return buffer.toString(); } public String getSpelling() { return this.getSelling(this.getResource()); } }
汉字编码与拼音的对应
1 package com.tan.sortadapter; 2 3 import java.util.Comparator; 4 5 import com.tan.bean.Music; 6 7 /** 8 * 9 * @author tannian 10 * 11 */ 12 public class PinyinComparator implements Comparator<Music> { 13 14 @Override 15 public int compare(Music o1, Music o2) { 16 // TODO Auto-generated method stub 17 if (o1.getSortLetters().equals("@") 18 || o2.getSortLetters().equals("#")) { 19 return -1; 20 } else if (o1.getSortLetters().equals("#") 21 || o2.getSortLetters().equals("@")) { 22 return 1; 23 } else { 24 return o1.getSortLetters().compareTo(o2.getSortLetters()); 25 } 26 } 27 28 }
实现Comparator接口
1 package com.tan.sortadapter; 2 3 import java.util.List; 4 5 import com.tan.bean.Music; 6 import com.tan.myplay.R; 7 8 9 import android.content.Context; 10 import android.view.LayoutInflater; 11 import android.view.View; 12 import android.view.ViewGroup; 13 import android.widget.BaseAdapter; 14 import android.widget.SectionIndexer; 15 import android.widget.TextView; 16 17 public class MusicAdapter extends BaseAdapter implements SectionIndexer{ 18 private List<Music> list = null; 19 private Context mContext; 20 21 public MusicAdapter(Context mContext, List<Music> list) { 22 this.mContext = mContext; 23 this.list = list; 24 } 25 26 /** 27 * 当ListView数据发生变化时,调用此方法来更新ListView 28 * @param list 29 */ 30 public void updateListView(List<Music> list){ 31 this.list = list; 32 notifyDataSetChanged(); 33 } 34 35 public int getCount() { 36 return this.list.size(); 37 } 38 39 public Object getItem(int position) { 40 return list.get(position); 41 } 42 43 public long getItemId(int position) { 44 return position; 45 } 46 47 public View getView(final int position, View view, ViewGroup arg2) { 48 ViewHolder viewHolder = null; 49 final Music mContent = list.get(position); 50 if (view == null) { 51 viewHolder = new ViewHolder(); 52 view = LayoutInflater.from(mContext).inflate(R.layout.song_item, null); 53 viewHolder.songname = (TextView) view.findViewById(R.id.song_songname); 54 viewHolder.singer=(TextView) view.findViewById(R.id.song_singer); 55 viewHolder.sortLetter = (TextView) view.findViewById(R.id.catalog); 56 view.setTag(viewHolder); 57 } else { 58 viewHolder = (ViewHolder) view.getTag(); 59 } 60 61 //根据position获取分类的首字母的Char ascii值 62 int section = getSectionForPosition(position); 63 64 //如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现 65 if(position == getPositionForSection(section)){ 66 viewHolder.sortLetter.setVisibility(View.VISIBLE); 67 viewHolder.sortLetter.setText(mContent.getSortLetters()); 68 }else{ 69 viewHolder.sortLetter.setVisibility(View.GONE); 70 } 71 72 viewHolder.songname.setText(this.list.get(position).getSongName()); 73 viewHolder.singer.setText(this.list.get(position).getSinger()); 74 75 return view; 76 77 } 78 79 80 81 final static class ViewHolder { 82 TextView sortLetter; 83 TextView songname; 84 TextView singer; 85 } 86 87 88 /** 89 * 根据ListView的当前位置获取分类的首字母的Char ascii值 90 */ 91 public int getSectionForPosition(int position) { 92 return list.get(position).getSortLetters().charAt(0); 93 } 94 95 /** 96 * 根据分类的首字母的Char ascii值获取其第一次出现该首字母的位置 97 */ 98 public int getPositionForSection(int section) { 99 for (int i = 0; i < getCount(); i++) { 100 String sortStr = list.get(i).getSortLetters(); 101 char firstChar = sortStr.toUpperCase().charAt(0); 102 if (firstChar == section) { 103 return i; 104 } 105 } 106 107 return -1; 108 } 109 110 /** 111 * 提取英文的首字母,非英文字母用#代替。 112 * 113 * @param str 114 * @return 115 */ 116 private String getAlpha(String str) { 117 String sortStr = str.trim().substring(0, 1).toUpperCase(); 118 // 正则表达式,判断首字母是否是英文字母 119 if (sortStr.matches("[A-Z]")) { 120 return sortStr; 121 } else { 122 return "#"; 123 } 124 } 125 126 @Override 127 public Object[] getSections() { 128 return null; 129 } 130 }
用来对数据进行显示(排序)
1 package com.tan.view; 2 3 import com.tan.myplay.R; 4 5 import android.content.Context; 6 import android.graphics.Canvas; 7 import android.graphics.Color; 8 import android.graphics.Paint; 9 import android.graphics.Typeface; 10 import android.graphics.drawable.ColorDrawable; 11 import android.util.AttributeSet; 12 import android.view.MotionEvent; 13 import android.view.View; 14 import android.widget.TextView; 15 16 public class SideBar extends View { 17 // 触摸事件 18 private OnTouchingLetterChangedListener onTouchingLetterChangedListener; 19 // 26个字母 20 public static String[] b = { "A", "B", "C", "D", "E", "F", "G", "H", "I", 21 "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", 22 "W", "X", "Y", "Z", "#" }; 23 private int choose = -1;// 选中 24 private Paint paint = new Paint(); 25 26 private TextView mTextDialog; 27 28 public void setTextView(TextView mTextDialog) { 29 this.mTextDialog = mTextDialog; 30 } 31 32 33 public SideBar(Context context, AttributeSet attrs, int defStyle) { 34 super(context, attrs, defStyle); 35 } 36 37 public SideBar(Context context, AttributeSet attrs) { 38 super(context, attrs); 39 } 40 41 public SideBar(Context context) { 42 super(context); 43 } 44 45 /** 46 * 重写这个方法 47 */ 48 protected void onDraw(Canvas canvas) { 49 super.onDraw(canvas); 50 // 获取焦点改变背景颜色. 51 int height = getHeight();// 获取对应高度 52 int width = getWidth(); // 获取对应宽度 53 int singleHeight = height / b.length;// 获取每一个字母的高度 54 55 for (int i = 0; i < b.length; i++) { 56 paint.setColor(Color.rgb(33, 65, 98)); 57 // paint.setColor(Color.WHITE); 58 paint.setTypeface(Typeface.DEFAULT_BOLD); 59 paint.setAntiAlias(true); 60 paint.setTextSize(16); 61 // 选中的状态 62 if (i == choose) { 63 paint.setColor(Color.parseColor("#3399ff")); 64 paint.setFakeBoldText(true); 65 } 66 // x坐标等于中间-字符串宽度的一半. 67 float xPos = width / 2 - paint.measureText(b[i]) / 2; 68 float yPos = singleHeight * i + singleHeight; 69 canvas.drawText(b[i], xPos, yPos, paint); 70 paint.reset();// 重置画笔 71 } 72 73 } 74 75 @Override 76 public boolean dispatchTouchEvent(MotionEvent event) { 77 final int action = event.getAction(); 78 final float y = event.getY();// 点击y坐标 79 final int oldChoose = choose; 80 final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener; 81 final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数. 82 83 switch (action) { 84 case MotionEvent.ACTION_UP: 85 setBackgroundDrawable(new ColorDrawable(0x00000000)); 86 choose = -1;// 87 invalidate(); 88 if (mTextDialog != null) { 89 mTextDialog.setVisibility(View.INVISIBLE); 90 } 91 break; 92 93 default: 94 setBackgroundResource(R.drawable.sidebar_background); 95 if (oldChoose != c) { 96 if (c >= 0 && c < b.length) { 97 if (listener != null) { 98 listener.onTouchingLetterChanged(b[c]); 99 } 100 if (mTextDialog != null) { 101 mTextDialog.setText(b[c]); 102 mTextDialog.setVisibility(View.VISIBLE); 103 } 104 105 choose = c; 106 invalidate(); 107 } 108 } 109 110 break; 111 } 112 return true; 113 } 114 115 /** 116 * 向外公开的方法 117 * 118 * @param onTouchingLetterChangedListener 119 */ 120 public void setOnTouchingLetterChangedListener( 121 OnTouchingLetterChangedListener onTouchingLetterChangedListener) { 122 this.onTouchingLetterChangedListener = onTouchingLetterChangedListener; 123 } 124 125 /** 126 * 接口 127 * 128 * @author coder 129 * 130 */ 131 public interface OnTouchingLetterChangedListener { 132 public void onTouchingLetterChanged(String s); 133 } 134 135 }
侧栏的实现
浙公网安备 33010602011771号