http://blog.youkuaiyun.com/toni001/article/details/6724785
暑假在家学习Android,通过编写一个Mp3播放器学习MediaPalyer。在这里和大家分享一下代码。
1、ID3V2 标签解析
只解析些常见的。{歌名、艺术家、专辑、头像}
新建一个Id3v2Info类
- package com.aws.mp3;
- public class Id3v2Info {
- // 歌名
- private String tit2 = null;
- // 艺术家
- private String tpe1 = null;
- // 专辑
- private String talb = null;
- // 头像
- private byte[] apic = null;
- public Id3v2Info(String tit2, String tpe1, String talb, byte[] apic) {
- setTit2(tit2);
- setTpe1(tpe1);
- setTalb(talb);
- setApic(apic);
- }
- public void setTit2(String tit2) {
- this.tit2 = tit2;
- }
- public String getTit2() {
- return tit2;
- }
- public void setTpe1(String tpe1) {
- this.tpe1 = tpe1;
- }
- public String getTpe1() {
- return tpe1;
- }
- public void setTalb(String talb) {
- this.talb = talb;
- }
- public String getTalb() {
- return talb;
- }
- public void setApic(byte[] apic) {
- this.apic = apic;
- }
- public byte[] getApic() {
- return apic;
- }
- }
再建立一个Mp3ReadId3v2类,用来提取Mp3中的信息。
- package com.aws.mp3;
- import java.io.IOException;
- import java.io.InputStream;
- /**
- * <b>MP3的ID3V2信息解析类</b>
- *
- * @QQ QQ:951868171
- * @version 1.0
- * @email xi_yf_001@126.com
- * */
- public class Mp3ReadId3v2 {
- private InputStream mp3ips;
- public String charset = "GBK"; // 预设编码为GBK
- private Id3v2Info info;
- public Mp3ReadId3v2(InputStream in) {
- this.mp3ips = in;
- info = new Id3v2Info("未知", "未知", "未知", null);
- }
- public void readId3v2() throws Exception {
- try {
- readId3v2(1024*100); //读取前100KB
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /**
- *
- * */
- public void readId3v2(int buffSize) throws Exception {
- try {
- if(buffSize > mp3ips.available()){
- buffSize = mp3ips.available();
- }
- byte[] buff = new byte[buffSize];
- mp3ips.read(buff, 0, buffSize);
- if (ByteUtil.indexOf("ID3".getBytes(), buff, 1, 512) == -1)
- throw new Exception("未发现ID3V2");
- //获取头像
- if (ByteUtil.indexOf("APIC".getBytes(), buff, 1, 512) != -1) {
- int searLen = ByteUtil.indexOf(new byte[] { (byte) 0xFF,
- (byte) 0xFB }, buff);
- int imgStart = ByteUtil.indexOf(new byte[] { (byte) 0xFF,
- (byte) 0xD8 }, buff);
- int imgEnd = ByteUtil.lastIndexOf(new byte[] { (byte) 0xFF,
- (byte) 0xD9 }, buff, 1, searLen) + 2;
- byte[] imgb = ByteUtil.cutBytes(imgStart, imgEnd, buff);
- info.setApic(imgb);
- }
- if (ByteUtil.indexOf("TIT2".getBytes(), buff, 1, 512) != -1) {
- info.setTit2(new String(readInfo(buff, "TIT2"), charset));
- System.out.println("info:" + info.getTit2());
- }
- if (ByteUtil.indexOf("TPE1".getBytes(), buff, 1, 512) != -1) {
- info.setTpe1(new String(readInfo(buff, "TPE1"), charset));
- System.out.println("info:" + info.getTpe1());
- }
- if (ByteUtil.indexOf("TALB".getBytes(), buff, 1, 512) != -1) {
- info.setTalb(new String(readInfo(buff, "TALB"), charset));
- System.out.println("info:" + info.getTalb());
- }
- } catch (IOException e) {
- e.printStackTrace();
- }finally{
- mp3ips.close();
- }
- }
- /**
- *读取文本标签
- **/
- private byte[] readInfo(byte[] buff, String tag) {
- int len = 0;
- int offset = ByteUtil.indexOf(tag.getBytes(), buff);
- len = buff[offset + 4] & 0xFF;
- len = (len << 8) + (buff[offset + 5] & 0xFF);
- len = (len << 8) + (buff[offset + 6] & 0xFF);
- len = (len << 8) + (buff[offset + 7] & 0xFF);
- len = len - 1;
- return ByteUtil.cutBytes(ByteUtil.indexOf(tag.getBytes(), buff) + 11,
- ByteUtil.indexOf(tag.getBytes(), buff) + 11 + len, buff);
- }
- public void setInfo(Id3v2Info info) {
- this.info = info;
- }
- public Id3v2Info getInfo() {
- return info;
- }
- public String getName() {
- return getInfo().getTit2();
- }
- public String getAuthor() {
- return getInfo().getTpe1();
- }
- public String getSpecial() {
- return getInfo().getTalb();
- }
- public byte[] getImg() {
- return getInfo().getApic();
- }
- }
- package com.aws.mp3;
- /**
- * 字节操作类
- * */
- public class ByteUtil {
- /**
- * 正向索引
- * */
- public static int indexOf(byte[] tag, byte[] src) {
- return indexOf(tag, src, 1);
- }
- /**
- * 获取第index个的位置<br />
- * index从1开始
- * */
- public static int indexOf(byte[] tag, byte[] src, int index) {
- return indexOf(tag, src, 1, src.length);
- }
- /**
- * 获取第index个的位置<br />
- * index从1开始
- *
- * */
- public static int indexOf(byte[] tag, byte[] src, int index, int len) {
- if (len > src.length) {
- try {
- throw new Exception("大于总个数");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- int size = 0;
- int tagLen = tag.length;
- byte[] tmp = new byte[tagLen];
- for (int j = 0; j < len - tagLen + 1; j++) {
- for (int i = 0; i < tagLen; i++) {
- tmp[i] = src[j + i];
- }
- // 判断是否相等
- for (int i = 0; i < tagLen; i++) {
- if (tmp[i] != tag[i])
- break;
- if (i == tagLen - 1) {
- size++;
- return j;
- }
- }
- }
- return -1;
- }
- /**
- * 倒序索引<br />
- *
- * */
- public static int lastIndexOf(byte[] tag, byte[] src) {
- return lastIndexOf(tag, src, 1);
- }
- /**
- * 倒序获取第index个的位置<br />
- * index从1开始
- * */
- public static int lastIndexOf(byte[] tag, byte[] src, int index) {
- return lastIndexOf(tag, src, src.length);
- }
- /**
- * 倒序获取第index个的位置<br />
- * index从1开始
- * */
- public static int lastIndexOf(byte[] tag, byte[] src, int index, int len) {
- if (len > src.length) {
- try {
- throw new Exception("大于总个数");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- int size = 0;
- int tagLen = tag.length;
- byte[] tmp = new byte[tagLen];
- for (int j = len - tagLen; j >= 0; j--) {
- for (int i = 0; i < tagLen; i++) {
- tmp[i] = src[j + i];
- }
- for (int i = 0; i < tagLen; i++) {
- if (tmp[i] != tag[i])
- break;
- if (i == tagLen - 1) {
- size++;
- return j;
- }
- }
- }
- return -1;
- }
- /**
- * 统计个数
- * */
- public static int size(byte[] tag, byte[] src) {
- int size = 0;
- int tagLen = tag.length;
- int srcLen = src.length;
- byte[] tmp = new byte[tagLen];
- for (int j = 0; j < srcLen - tagLen + 1; j++) {
- for (int i = 0; i < tagLen; i++) {
- tmp[i] = src[j + i];
- }
- for (int i = 0; i < tagLen; i++) {
- if (tmp[i] != tag[i])
- break;
- if (i == tagLen - 1) {
- size++;
- }
- }
- // 速度较慢
- // if (Arrays.equals(tmp, tag)) {
- // size++;
- // }
- }
- return size;
- }
- /**
- * 截取byte[]
- * */
- public static byte[] cutBytes(int start, int end, byte[] src) {
- if (end <= start || start < 0 || end > src.length) {
- try {
- throw new Exception("参数错误");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- byte[] tmp = new byte[end - start];
- for (int i = 0; i < end - start; i++) {
- tmp[i] = src[start + i];
- }
- return tmp;
- }
- }
2、ID3V1 标签解析
v1标签解析比较简单,就是操作mp3后128个字节。懒得贴代码。3、资源下载地址
播放器源码下载http://download.youkuaiyun.com/source/3553639