天天看點

安卓學習日記——媒體播放

  • 簡介

    Android的多媒體架構包括支援播放多種常見的媒體類型,使您可以輕松地把音頻、視訊和圖像內建到你的應用。你可以播放音頻或視訊媒體檔案,這些檔案是存儲在你的應用程式的資源檔案中的。應用程式的資源檔案可以是檔案系統中獨立的檔案,或通過網絡連接配接擷取的一個資料流,所有使用MediaPlayer APIS的資源檔案。

    注意:你隻能在标準輸出裝置上播放音頻資料。目前,标準輸出裝置是移動裝置的揚聲器或耳機。你不能在談話音頻調用期間播放聲音檔案。

三種播放方式

播放本地資源檔案

public void playFromRes(View v){
        MediaPlayer mp=MediaPlayer.create(this,R.raw.zhh);
        mp.start();
    }
           

播放系統檔案

public void playFromSys(View v){
        MediaPlayer mp=new MediaPlayer();
        String path= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getPath()+"/zhh.mp3";
        try {
            mp.setDataSource(this, Uri.parse(path));//設定資料源
            mp.prepare();//同步執行
            mp.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
           

播放網絡檔案

public void playFromInternet(View v){
        String path="http://fs.w.kugou.com/201904231441/48036033298fec2f60d6a81a8aeaca63/G137/M06/08/17/yQ0DAFuGdOCABiECAE4jb57rgmY473.mp3";//這個連結不可用了
        MediaPlayer mp=new MediaPlayer();
        try {
            mp.setDataSource(this,Uri.parse(path));
            mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mp.start();
                }
            });
            mp.prepareAsync();//異步緩沖

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
           

權限設定

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
           

狀态轉換圖

安卓學習日記——媒體播放

簡單的播放器實作

import android.media.MediaPlayer;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

/**
 * 簡單的播放器實作
 */
public class Main2Activity extends AppCompatActivity implements View.OnClickListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener {
    private MediaPlayer mp;
    private int index=0;//表示目前要播放音樂的索引
    private ArrayList<String> musicList=new ArrayList<>();
    private Button button_play,button_pause,button_next,button_prev;
    private boolean isPause=false;//true表示暫停狀态
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        initView();
        initMusic();
        mp=new MediaPlayer();
        mp.setOnPreparedListener(this);
        mp.setOnErrorListener(this);
        mp.setOnCompletionListener(this);


    }
    private void initView(){
        button_play=findViewById(R.id.button6_play);
        button_pause=findViewById(R.id.button7_pause);
        button_next=findViewById(R.id.button5_next);
        button_prev=findViewById(R.id.button4_prev);
        button_play.setOnClickListener(this);
        button_pause.setOnClickListener(this);
        button_next.setOnClickListener(this);
        button_prev.setOnClickListener(this);
    }
    public void initMusic(){
        String root= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getPath();
        musicList.add(root+ File.separator+"/zhh.mp3");
        musicList.add(root+ File.separator+"/qjtx.mp3");
        musicList.add(root+ File.separator+"/myhs.mp3");
        musicList.add(root+ File.separator+"/cl.mp3");
    }

    @Override
    public void onClick(View v) {
switch (v.getId()){
    case R.id.button6_play:
        play();
        break;
    case R.id.button7_pause:
        pause();
        break;
    case R.id.button5_next:
        next();
        break;
    case R.id.button4_prev:
        prev();
        break;
        default:
            break;
}
    }
//上一首
    private void prev() {
        if (index-1>=0){
            index--;
        }else {
            index=musicList.size()-1;
        }
        start();

    }
//下一首
    private void next() {
        if (index+1<musicList.size()){
            index++;
        }else {
            index=0;
        }
        start();
    }

    //暫停
    private void pause() {
        if (mp.isPlaying()){
            mp.pause();
            isPause=true;
        }
    }

    //播放
    private void play() {
            if (isPause){
                mp.start();
                isPause=false;
            }else {
                start();
            }
    }
    //重頭開始播放音樂
private void start(){
        if(index<musicList.size()){
           if (mp.isPlaying())mp.stop();
           mp.reset();//重置
           String musicPath= musicList.get(index);
            try {
                mp.setDataSource(musicPath);
                mp.prepareAsync();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
}
    @Override
    public void onPrepared(MediaPlayer mp) {
            mp.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mp!=null){
            if (mp.isPlaying())mp.stop();
            mp.release();
        }
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        mp.reset();
        return true;
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        next();
    }
}
           

權限

安卓學習日記——媒體播放
安卓學習日記——媒體播放
安卓學習日記——媒體播放

以服務的形式背景運作

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.IBinder;
import android.os.PowerManager;

import java.io.File;
import java.io.IOException;

public class MusicService extends Service implements MediaPlayer.OnPreparedListener {
    public static final String ACTION_PLAY="com.my.ACTION_PLAY";
    public static final String ACTION_PAUSE="com.my.ACTION_PAUSE";
    public static final String ACTION_EXIT="com.my.ACTION_EXIT";
    private WifiManager.WifiLock lock;
    private MediaPlayer mediaPlayer;
    public MusicService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mediaPlayer=new MediaPlayer();
        mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
        //保持WIFI正常工作
        WifiManager wifiManager= (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        lock=  wifiManager.createWifiLock("mylock");
        lock.acquire();
        mediaPlayer.setOnPreparedListener(this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        lock.release();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        String action=intent.getAction();
        if (ACTION_PLAY.equals(action)){
            mediaPlayer.reset();
            try {
                mediaPlayer.setDataSource(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)+ File.separator+"qjtx.mp3");
                mediaPlayer.prepareAsync();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else if (ACTION_PAUSE.equals(action)){
          if (mediaPlayer.isPlaying()) mediaPlayer.pause();


        }else if (ACTION_EXIT.equals(action)){
            if (mediaPlayer.isPlaying())mediaPlayer.stop();
            mediaPlayer.release();
        }
        return super.onStartCommand(intent, flags, startId);

    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        mp.start();
    }
}
           
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class Main3Activity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
    }
public void play(View v){
    Intent intent=new Intent(this,MusicService.class);
    intent.setAction(MusicService.ACTION_PLAY);
    startService(intent);
}
    public void pause(View v){
        Intent intent=new Intent(this,MusicService.class);
        intent.setAction(MusicService.ACTION_PAUSE);
        startService(intent);
    }
    public void exit(View v){
        Intent intent=new Intent(this,MusicService.class);
        intent.setAction(MusicService.ACTION_EXIT);
        startService(intent);
    }
}
           
安卓學習日記——媒體播放
安卓學習日記——媒體播放

作為前台服務運作

@TargetApi(Build.VERSION_CODES.O)
    private void notification() {
        String id ="channel_1";//channel的id
        String description = "123";//channel的描述資訊
        int importance = NotificationManager.IMPORTANCE_LOW;//channel的重要性
        NotificationChannel channel = new NotificationChannel(id, "123", importance);//生成channel

        Notification.Builder builder=new Notification.Builder(this,id);
        builder.setTicker("我的第一個音樂播放器");
        builder.setSmallIcon(R.mipmap.ic_launcher);
        builder.setContentTitle("我的音樂播放器");
        builder.setContentInfo("正在播放");
        PendingIntent pi=PendingIntent.getActivity(this,0,new Intent(this,Main3Activity.class),PendingIntent.FLAG_UPDATE_CURRENT);
        builder.setContentIntent(pi);
        NotificationManager nm= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        nm.createNotificationChannel(channel);
        Notification notification=builder.build();
        startForeground(0,notification);
        nm.notify(0,notification);
    }
           
安卓學習日記——媒體播放
安卓學習日記——媒體播放

注意,在sdk版本為25或25之前想在notification中添加一個點選事件 隻要通過setContentIntent()傳入一個PendingIntent就可以實作通知點選事件。但是26之後引入了一個叫NotificationChannel的類 在sdk版本為26的時候 我們不加這個東西 就設定用不了點選事件啦

具體分析參考部落格:解決Fail to post notification on channel "null"的方法

從ContentResolver擷取媒體内容

查詢音樂清單

public void queryMusic(View v){
        ContentResolver cr=getContentResolver();
        Cursor c= cr.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,null,null,null,null);
        if(c!=null){
            while (c.moveToNext()){
               String url= c.getString(c.getColumnIndex(MediaStore.Audio.Media.DATA));
               String songName= c.getString(c.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
               String artist= c.getString(c.getColumnIndex(MediaStore.Audio.Media.ARTIST));
                System.out.println("路徑:"+url);
                System.out.println("歌名:"+songName);
                System.out.println("歌手:"+artist);
                System.out.println("---------------------");

            }
        }
           
安卓學習日記——媒體播放

繼續閱讀