1. 程式人生 > >android 音樂播放器小案例

android 音樂播放器小案例

案例主目的是為了複習一下Service服務 Handler訊息機制 學習一下mediaplayer類 和了解自定義控制元件

MainAcitivity.java

package com.alleged.musicPlay;

import android.support.v7.app.ActionBarActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import
android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; public class MainActivity extends ActionBarActivity { private
musicPlayer player;//介面 private Context context; private Myconn conn; private static SeekBar seekbar; public static Handler handler = new Handler(){ //當接受到訊息時 public void handleMessage(android.os.Message msg){ Bundle data = msg.getData(); //獲取當前進度和總進度
int drua = data.getInt("drua"); int currentposition = data.getInt("currentposition"); //設定進度條 seekbar.setMax(drua); seekbar.setProgress(currentposition); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 開啟服務,暴露出播放 暫停 繼續播放三個方法 使用handler訊息機制把當前位置和總的位置返回回來 // 先呼叫startservice 方法開啟服務 保證服務在後臺長期執行 Intent intent = new Intent(this, musicService.class); //開啟服務執行oncreate方法 startService(intent); //自定義類實現serviceconnection介面 conn = new Myconn(); //繫結服務 bindService(intent, conn, BIND_AUTO_CREATE); seekbar = (SeekBar) findViewById(R.id.palySeekbar); //對進度條設定拖拽變化事件監聽 seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } //停止拖拽 @Override public void onStopTrackingTouch(SeekBar seekBar) { //設定播放的位置 player.SeekBar(seekBar.getProgress()); } }); } public void musicplay(View v) { player.musicPlay(); } public void musicpause(View v) { player.musicpause(); } public void musiccontinue(View v) { player.musicContinue(); } // 當Activity銷燬的時候呼叫 @Override protected void onDestroy() { // 在Activity銷燬的時候 取消繫結服務 unbindService(conn); super.onDestroy(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } public class Myconn implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 獲取我們定義的中間人物件 player = (musicPlayer) service; } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } } }

musicPlay介面(主要是為了暴露出服務中的方法)

package com.alleged.musicPlay;

public interface musicPlayer {
    public void musicPlay();
    public void musicpause();
    public void musicContinue();
    public void SeekBar(int position);
}

musicService服務

package com.alleged.musicPlay;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;

public class musicService extends Service {
    // 服務中建立mediaplayer類物件,對多媒體播放進行控制和設定
    private MediaPlayer mediaPlayer;

    @Override
    public IBinder onBind(Intent intent) {
        return new myBinder();
    }

    // 服務第一次開啟的是呼叫
    @Override
    public void onCreate() {

        // [1]初始化mediaplayer
        mediaPlayer = new MediaPlayer();
        super.onCreate();
    }

    //設定音樂的播放位置
    public void SeekToPosition(int position){
        mediaPlayer.seekTo(position);
    }
    // 當服務銷燬的時候呼叫
    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    public void mplay() {
        System.out.println("音樂開始播放");

        try{
            mediaPlayer.reset();
            //設定播放的歌曲的位置 
            mediaPlayer.setDataSource("/mnt/sdcard/Denitia and Sene - Casanova.mp3");
            //準備播放
            mediaPlayer.prepare();
            //開始播放
            mediaPlayer.start();
            updateSeekBar();
        }catch(Exception e){
            e.printStackTrace();
        }

    }
    private void updateSeekBar() {
        //獲取當前歌曲的長度
        final int drua = mediaPlayer.getDuration();
        //定時器每一秒更新一次當前位置
        final Timer time = new Timer();
        final TimerTask task = new TimerTask(){

            //次執行緒複寫run方法
            @Override
            public void run() {
                //獲取當前歌曲的進度
                int currentposition = mediaPlayer.getCurrentPosition();

                //使用訊息佇列更新位置資訊
                Message msg = new Message();
                Bundle bundle = new Bundle();
                bundle.putInt("drua", drua);
                bundle.putInt("currentposition", currentposition);
                msg.setData(bundle);
                MainActivity.handler.sendMessage(msg);
            }

        };
        //300毫秒後 每隔1秒鐘獲取一次當前歌曲的進度
        time.schedule(task, 300, 1000);
        //當歌曲播放完成的時候 把timer 和task 取消 
        mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

            @Override
            public void onCompletion(MediaPlayer mp) {
                System.out.println("歌曲播放完畢");
                task.cancel();
                time.cancel();

            }
        });
    }

    public void mpause() {
        System.out.println("音樂暫停了");
        mediaPlayer.pause();

    }

    public void mcontinue() {
        System.out.println("音樂繼續播放了");
        mediaPlayer.start();
    }

    public void mseekbar(int position) {
        //滾動條拖拽
        mediaPlayer.seekTo(position);

    }
    public class myBinder extends Binder implements musicPlayer{

        @Override
        public void musicPlay() {
            mplay();
        }

        @Override
        public void musicpause() {
            mpause();

        }

        @Override
        public void musicContinue() {
            mcontinue();

        }

        @Override
        public void SeekBar(int position) {
            mseekbar(position);

        }

    }

}
package com.alleged.musicPlay;

import com.alleged.musicPlay.*;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.widget.ImageView;

public class CircleImageView extends ImageView {

    private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;

    private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
    private static final int COLORDRAWABLE_DIMENSION = 2;

    private static final int DEFAULT_BORDER_WIDTH = 0;
    private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
    private static final boolean DEFAULT_BORDER_OVERLAY = false;

    private final RectF mDrawableRect = new RectF();
    private final RectF mBorderRect = new RectF();

    private final Matrix mShaderMatrix = new Matrix();
    private final Paint mBitmapPaint = new Paint();
    private final Paint mBorderPaint = new Paint();

    private int mBorderColor = DEFAULT_BORDER_COLOR;
    private int mBorderWidth = DEFAULT_BORDER_WIDTH;

    private Bitmap mBitmap;
    private BitmapShader mBitmapShader;
    private int mBitmapWidth;
    private int mBitmapHeight;

    private float mDrawableRadius;
    private float mBorderRadius;

    private ColorFilter mColorFilter;

    private boolean mReady;
    private boolean mSetupPending;
    private boolean mBorderOverlay;

    public CircleImageView(Context context) {
        super(context);

        init();
    }

    public CircleImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);

        a.recycle();

        init();
    }

    private void init() {
        super.setScaleType(SCALE_TYPE);
        mReady = true;

        if (mSetupPending) {
            setup();
            mSetupPending = false;
        }
    }

    @Override
    public ScaleType getScaleType() {
        return SCALE_TYPE;
    }

    @Override
    public void setScaleType(ScaleType scaleType) {
        if (scaleType != SCALE_TYPE) {
            throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
        }
    }

    @Override
    public void setAdjustViewBounds(boolean adjustViewBounds) {
        if (adjustViewBounds) {
            throw new IllegalArgumentException("adjustViewBounds not supported.");
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (getDrawable() == null) {
            return;
        }

        canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);
        if (mBorderWidth != 0) {
            canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        setup();
    }

    public int getBorderColor() {
        return mBorderColor;
    }

    public void setBorderColor(int borderColor) {
        if (borderColor == mBorderColor) {
            return;
        }

        mBorderColor = borderColor;
        mBorderPaint.setColor(mBorderColor);
        invalidate();
    }

    public void setBorderColorResource(@ColorRes int borderColorRes) {
        setBorderColor(getContext().getResources().getColor(borderColorRes));
    }

    public int getBorderWidth() {
        return mBorderWidth;
    }

    public void setBorderWidth(int borderWidth) {
        if (borderWidth == mBorderWidth) {
            return;
        }

        mBorderWidth = borderWidth;
        setup();
    }

    public boolean isBorderOverlay() {
        return mBorderOverlay;
    }

    public void setBorderOverlay(boolean borderOverlay) {
        if (borderOverlay == mBorderOverlay) {
            return;
        }

        mBorderOverlay = borderOverlay;
        setup();
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        super.setImageBitmap(bm);
        mBitmap = bm;
        setup();
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        super.setImageDrawable(drawable);
        mBitmap = getBitmapFromDrawable(drawable);
        setup();
    }

    @Override
    public void setImageResource(@DrawableRes int resId) {
        super.setImageResource(resId);
        mBitmap = getBitmapFromDrawable(getDrawable());
        setup();
    }

    @Override
    public void setImageURI(Uri uri) {
        super.setImageURI(uri);
        mBitmap = getBitmapFromDrawable(getDrawable());
        setup();
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        if (cf == mColorFilter) {
            return;
        }

        mColorFilter = cf;
        mBitmapPaint.setColorFilter(mColorFilter);
        invalidate();
    }

    private Bitmap getBitmapFromDrawable(Drawable drawable) {
        if (drawable == null) {
            return null;
        }

        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        try {
            Bitmap bitmap;

            if (drawable instanceof ColorDrawable) {
                bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
            } else {
                bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
            }

            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
            return bitmap;
        } catch (OutOfMemoryError e) {
            return null;
        }
    }

    private void setup() {
        if (!mReady) {
            mSetupPending = true;
            return;
        }

        if (mBitmap == null) {
            return;
        }

        mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

        mBitmapPaint.setAntiAlias(true);
        mBitmapPaint.setShader(mBitmapShader);

        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setColor(mBorderColor);
        mBorderPaint.setStrokeWidth(mBorderWidth);

        mBitmapHeight = mBitmap.getHeight();
        mBitmapWidth = mBitmap.getWidth();

        mBorderRect.set(0, 0, getWidth(), getHeight());
        mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2);

        mDrawableRect.set(mBorderRect);
        if (!mBorderOverlay) {
            mDrawableRect.inset(mBorderWidth, mBorderWidth);
        }
        mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2);

        updateShaderMatrix();
        invalidate();
    }

    private void updateShaderMatrix() {
        float scale;
        float dx = 0;
        float dy = 0;

        mShaderMatrix.set(null);

        if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
            scale = mDrawableRect.height() / (float) mBitmapHeight;
            dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
        } else {
            scale = mDrawableRect.width() / (float) mBitmapWidth;
            dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
        }

        mShaderMatrix.setScale(scale, scale);
        mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);

        mBitmapShader.setLocalMatrix(mShaderMatrix);
    }

}

使用了服務一定要在xml檔案中配置一下

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.alleged.musicPlay"
    android:versionCode="1"
    android:versionName="1.0" >


    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="com.alleged.musicPlay.musicService"></service>
    </application>

</manifest>

佈局檔案

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.alleged.musicPlay"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical|center_horizontal"
    android:orientation="vertical"
    tools:context="com.alleged.musicPlay.MainActivity" >

    <com.alleged.musicPlay.CircleImageView
        android:id="@+id/roundImageView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:src="@drawable/pre19"
         />

    <LinearLayout
        android:id="@+id/button_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/play"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_weight="1"
            android:gravity="center_horizontal|center_vertical"
            android:text="播放"
            android:textSize="15sp"
            android:onClick="musicplay" >
        </Button>

        <Button
            android:id="@+id/wait"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_weight="1"
            android:gravity="center_horizontal|center_vertical"
            android:text="暫停"
            android:textSize="15sp"
            android:onClick="musicpause" >
        </Button>

        <Button
            android:id="@+id/replay"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_weight="1"
            android:gravity="center_horizontal|center_vertical"
            android:text="繼續播放"
            android:textSize="15sp"
            android:onClick="musiccontinue" >
        </Button>
    </LinearLayout>
    <LinearLayout 
        android:id="@+id/seekbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:orientation="horizontal"
        >

        <SeekBar
            android:id="@+id/palySeekbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>

</LinearLayout>

結果如下這裡寫圖片描述