android示例:简单的播放MP3并显示歌词的应用(待更新)

闲来无事,写了个小应用,能够播放固定的MP3,并显示歌词,待改进地方有:
1 可播放目录内所有歌曲文件,并同时显示歌词
2 有进度条
3 可快进,回退,停止等

待弄明白的是:判断何时是唱歌的的起始点。
以下为示例:
布局文件main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res/com.android.test"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <Button
        android:id="@+id/startbt"            
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_gravity="center"
        android:text="@string/start">
    </Button>

    <com.android.test.view.LyricView
        android:id="@+id/mylrc"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center"
        android:layout_gravity="center"
        android:layout_marginTop="0dp"
        android:layout_marginBottom="0dp"
        android:background="@drawable/bg"  
        android:visibility="gone"      
    />

</FrameLayout>

歌词view:

package com.android.test.view;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Currency;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.regex.Pattern;

import android.R.integer;
import android.app.ActionBar.Tab;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.Layout.Alignment;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.RelativeLayout;

public class LyricView extends RelativeLayout {

    private static String TAG = "qjy";
    private TextPaint mPaint; 
    private int currentIndex = 0;
    private String currentLrc = null;
    private static TreeMap<Integer, LyricObject> lrc_map;

    public LyricView(Context context)
    {
        super(context);
        init();
    }

    public LyricView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init();
    }

    private void init()
    {
        lrc_map = new TreeMap<Integer, LyricView.LyricObject>();

        mPaint = new TextPaint();
        mPaint.setColor(Color.RED);
        mPaint.setTextSize(20);
//      mPaint.setTextAlign(Paint.Align.CENTER);
        Thread myThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    read("/data/app/test.lrc");
                } catch (Exception e) {
                    Log.e(TAG, "ERROR: can not read test.lrc");
                }

            }
        });

        myThread.start();       
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);

        Log.e(TAG, "LyricView onDraw start");

//      LyricObject ones = lrc_map.get(5);
        if (currentIndex < 6) {
            StringBuilder  testString = new StringBuilder();

            for (int j = 0; j < 6; j++) {
                if (testString.toString() != null) {
                    testString.append("\n\r");
                }           
                testString.append(lrc_map.get(j).lrc);
            }

            StaticLayout layout = new StaticLayout(testString.toString(), mPaint, getMeasuredWidth()-getPaddingLeft()-getPaddingRight(), Alignment.ALIGN_CENTER, 1, 0, true);
            canvas.save();
            layout.draw(canvas);
            canvas.restore();
            return;
        }

        currentLrc = lrc_map.get(currentIndex).lrc;

        Rect boundRect = new Rect();
        mPaint.getTextBounds(currentLrc, 0,currentLrc.length(), boundRect);
        canvas.drawText(currentLrc, getMeasuredWidth()/2 - boundRect.width()/2 , getMeasuredHeight()/2 + boundRect.height()/2, mPaint);
    }

    public void setTime(int time){
        int c;
        if (currentIndex == (lrc_map.size()-1)) {
            return;
        }

        for (c = currentIndex; c < lrc_map.size()-1; c++) {
            if (time > lrc_map.get(c).begintime && time < lrc_map.get(c+1).begintime) {
                currentIndex = c;
                break;
            }else if (time > lrc_map.get(lrc_map.size()-1).begintime) {
                currentIndex = lrc_map.size()-1;
                break;
            }           
        }       
        Log.e(TAG, "current index is "+currentIndex);
    }

    public static void read(String file)
    {
        String data;
        String mTime;
        int min;
        int sec;
        int ms;
        int i = 0;
        LyricObject item;

        Log.e(TAG, "start to read ! ");
        lrc_map.clear();

        try {
            File f = new File(file);
            FileInputStream fis = new FileInputStream(f);

            BufferedReader br = new BufferedReader(new InputStreamReader(fis, "GB2312"));
            Pattern pattern = Pattern.compile("[0-9]*");

            while ((data = br.readLine()) != null) {
                item = new LyricObject();               
                mTime = data.substring(data.indexOf("[") + 1, data.indexOf("]"));
                if (pattern.matcher(mTime.substring(0, mTime.indexOf(":"))).matches()) {
                    min = Integer.parseInt(mTime.substring(0, mTime.indexOf(":")));
                    sec = Integer.parseInt(mTime.substring(mTime.indexOf(":")+1, mTime.indexOf(".")));
                    ms = Integer.parseInt(mTime.substring(mTime.indexOf(".")+1));
                    item.begintime = (min*60 + sec)*1000 + ms;
                    item.lrc = data.substring(data.indexOf("]")+1);
                } else {
                    item.begintime = 0;
                    item.lrc = mTime;
                }

                Log.e(TAG, "i IS " + i);
                lrc_map.put(new Integer(i), item);              
                Log.e(TAG, "begintime IS " + lrc_map.get(i).begintime);
                Log.e(TAG, "LRC IS " + lrc_map.get(i).lrc);
                i++;
            }
            fis.close();            
        } catch (Exception e) {
            Log.e(TAG, "ERROR can not read! ");
            e.printStackTrace();
        }
    }

    protected static class LyricObject {
        protected int begintime;
        protected int endtime;
        protected int consume;
        protected String lrc;
    }
}

主文件:

package com.android.test;

import com.android.test.view.LyricView;
import com.android.test.view.TitleView;

import android.app.Activity;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.view.View.OnClickListener;
import android.content.res.Configuration;
import android.media.MediaPlayer;
import android.os.Handler;

public class MActivity extends Activity {
    String TAG = "qjy";
    Button myButton;
    LyricView mv;
    TitleView mtv;
    Thread spThread;
    Thread lrcT;

    private String mp3 = "file:///data/app/test.mp3";
    MediaPlayer myMP;

    Handler mHandler = new Handler(){

        public void handleMessage(Message msg){
            Log.e(TAG, "handlerMessage");
            switch (msg.what) {
            case 0:
                mv.setTime(msg.arg1);
                mv.invalidate();
                break;

            default:
                break;
            }
            super.handleMessage(msg);
        }
    };

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  WindowManager.LayoutParams.FLAG_FULLSCREEN);  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  

        setContentView(R.layout.main);
        Log.d(TAG, "onCreate");    

        myButton =(Button) findViewById(R.id.startbt);
        mv = (LyricView) findViewById(R.id.mylrc);
        mtv = (TitleView) findViewById(R.id.mytv);
        myButton.setOnClickListener(mListener);

        myMP = new MediaPlayer();

    }

    OnClickListener mListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            myButton.setVisibility(View.GONE);
            mtv.setVisibility(View.GONE);
            mv.setVisibility(View.VISIBLE);
            mv.invalidate();

            try {
                myMP.setDataSource(mp3);
                myMP.prepare();
            } catch (Exception e) {
                Log.e(TAG, "ERROR: can not start mediaplayer");
                e.printStackTrace();
            }

            startPlayer();

        }
    };

    private void startPlayer() {
        spThread = new Thread(new Runnable() {

            @Override
            public void run() {
                myMP.start();               
            }
        });

        lrcT = new Thread(new Runnable() {
            Message msg; 

            @Override
            public void run() {
                try {
                    while (true) {
                        Thread.sleep(1000);
                        Log.e(TAG, "current position is " + myMP.getCurrentPosition());
                        msg = mHandler.obtainMessage();
                        msg.arg1 = myMP.getCurrentPosition();
                        msg.what = 0;
                        mHandler.sendMessage(msg);
                    }                   
                } catch (Exception e) {
                    Log.e(TAG, "ERROR: set current position!");
                    e.printStackTrace();
                }
            }
        });

        spThread.start();
        lrcT.start();
    }

    @Override
    public void onStart()
    {
        super.onStart();
        Log.d(TAG, "onStart");
    }

    @Override
    public void onRestart()
    {   
        super.onRestart();
        Log.d(TAG, "onRestart");
    } 

    @Override
    public void onPause()
    {   
        super.onPause();
        Log.d(TAG, "onPause");
    }

    @Override
    public void onResume()
    {   
        super.onResume();
        Log.d(TAG, "onResume");
    }

    @Override
    public void onStop()
    {   
        super.onStop();
        Log.d(TAG, "onStop");
    }

    @Override
    public void onDestroy()
    {   
        super.onDestroy();
        Log.d(TAG, "onDestroy");

        spThread.interrupt();
        lrcT.interrupt();
    }

    @Override
    public void onSaveInstanceState(Bundle outState)
    {
        super.onSaveInstanceState(outState);
        Log.d(TAG, "onSaveInstanceState");
    }

    @Override
    public void onRestoreInstanceState(Bundle outState)
    {
        super.onRestoreInstanceState(outState);
        Log.d(TAG, "onRestoreInstanceState");
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig)
    {
        super.onConfigurationChanged(newConfig);
        Log.d(TAG, "onConfigurationChanged");
    }

}

manifest文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.android.test"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
        <activity android:name="MActivity"

                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值