Android学习_Mars老师之Mp3视频开发

这篇具有很好参考价值的文章主要介绍了Android学习_Mars老师之Mp3视频开发。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

实现的功能:开发一个可以播放音乐并同步显示歌词文件的APP.

成果展示:

Android学习_Mars老师之Mp3视频开发,android,android,学习,音视频

总体设计图:

Android学习_Mars老师之Mp3视频开发,android,android,学习,音视频

实现流程图

Android学习_Mars老师之Mp3视频开发,android,android,学习,音视频

代码展示:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.mp3player">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Mp3Player"
        tools:targetApi="31">

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".Mp3ListActivity"
            tools:ignore="Instantiatable"
            android:label="@string/app_name" />

        <activity
            android:name=".PlayerActivity"
            tools:ignore="DuplicateActivity,Instantiatable"
            android:label="@string/app_name" />

        <activity
            android:name=".LocalMp3ListActivity"
            tools:ignore="DuplicateActivity,Instantiatable"
            android:label="@string/app_name" />

        <service android:name="com.example.service.DownloadService" />

    </application>

    <uses-permission android:name="android.permission.INTERNET"
        tools:ignore="ManifestOrder" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />

</manifest>

MainActivity:

监听到用户点击Menu---->弹出选项框“Update”、“About”按钮---->onOptionsItemSelected()监听到用户点击更新按钮后调用updateListView()下载Mp3文件,采用SAX解析器解析文件生成一个Mp3Info对象,通过buildSimpleAdapter()将mp3文件的名字和大小返回给TextView显示。onListItemClick()监听用户点击哪个mp3文件,开启下载文件服务DownloadService。

package com.example.mp3player;

import androidx.appcompat.app.AppCompatActivity;

import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import com.example.download.HttpDownloader;
import com.example.model.Mp3Info;
import com.example.service.DownloadService;
import com.example.xml.Mp3ListContentHandler;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class MainActivity extends ListActivity {
    private static final int UPDATE = 1;
    private static final int ABOUT = 2;
    private List<Mp3Info> mp3Infos = null;
    //after user click Menu button ,the function is called,so wo can monitor in this function
    @Override
    public boolean onCreateOptionsMenu(Menu menu){
        //Distinguish Button of Update and About
        menu.add(0,UPDATE,1,"update list");
        menu.add(0,ABOUT,2,"about");
        return super.onCreateOptionsMenu(menu);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item){
        //user click Update button
        if(item.getItemId() == UPDATE){
            updateListView();
        }else if(item.getItemId() == ABOUT){
            //user click button about
        }
        System.out.println("itemId----->"+item.getItemId());
        return super.onOptionsItemSelected(item);
    }
    //The smaller the function,the better!  because Strongly Reusability
    //function of downloading xml
    private String downloadXml(String urlStr){
        HttpDownloader httpDownloader = new HttpDownloader();
        String result = httpDownloader.download(urlStr);
        return result;
    }
    //Convert an xml file into an array of object
    private List<Mp3Info> parse(String xmlStr){
        /*
            use SAX parser to parse xml document
            SAXParserFactory.newInstance():get an SAXParserFactory new instance。
         */
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        //define an arraylist of mp3Info
        List<Mp3Info> infos = new ArrayList<Mp3Info>();
        try{
            /*
                saxParserFactory是一个SAX解析器,用于解析xml文档
                newSAXParser将解析器工厂实例化
                getXMLReader()生成一个解析器实例
             */
            XMLReader xmlReader = saxParserFactory.newSAXParser().getXMLReader();
            //定义一个将xml转换成Mp3Info对象数组的生成器
            Mp3ListContentHandler mp3ListContentHandler = new Mp3ListContentHandler(infos);
            //解析器实例捆绑生成器
            xmlReader.setContentHandler(mp3ListContentHandler);
            //将xml文件转换成一个Java可以处理的InputStream流
            xmlReader.parse(new InputSource(new StringReader(xmlStr)));
            //Iterator跌倒infos的数据
            for(Iterator iterator = infos.iterator();iterator.hasNext();){
                Mp3Info mp3Info = (Mp3Info) iterator.next();
                System.out.println(mp3Info);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return infos;
    }

    private SimpleAdapter buildSimpleAdapter(List<Mp3Info> mp3Infos){
        List<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
        //iterate mp3Infos and assign to TextView to show to user
        for(Iterator iterator= mp3Infos.iterator();iterator.hasNext();){
            Mp3Info mp3Info = (Mp3Info) iterator.next();
            HashMap<String ,String> map = new HashMap<String,String>();
            map.put("mp3_name",mp3Info.getMp3Name());
            map.put("mp3_size",mp3Info.getMp3Size());
            list.add(map);
        }

        //create an simpleAdapter object
        SimpleAdapter simpleAdapter = new SimpleAdapter(this,list,R.layout.mp3info_item,new String[]{"mp3_name","mp3_size"},new int[]{R.id.mp3_name,R.id.mp3_size});
        return simpleAdapter;
    }

    private void updateListView(){
        //download mp3 information xml file
        String xml = downloadXml("http://192.168.1.34:8081/MP3/resources.xml");
        //analysis xml file ane put the consequence in the Object mp3Info,last add Object in the List
        List<Mp3Info> mp3Infos = parse(xml);
        //generate Object of List ,put mp3Info Object in the List according to standard "SimpleAdapter"
        SimpleAdapter simpleAdapter = buildSimpleAdapter(mp3Infos);
        //set simpleAdapter into ListActivity
        setListAdapter(simpleAdapter);
    }

    //after you click the activity file button ,the function is called ,you can know which textview is clicked and then you can download it.
    protected void onListItemClick(ListView l, View v, int position, long id){
        //position specifies which mp3Info object is called
        Mp3Info mp3Info = mp3Infos.get(position);

        //use service to download file in network
        Intent intent = new Intent();
        intent.putExtra("mp3Info",mp3Info);
        intent.setClass(MainActivity.this, DownloadService.class);
        startService(intent);

        super.onListItemClick(l,v,position,id);
    }

}

DownloadService

创建一个Mp3Info实体对象,接受从MainActivity中传来的数据,DownloadThread 方法开启新线程调用HttpDownloader 下载文件。并根据HttpDownloader.download()返回结果采用Notification方式提示用户文件下载情况

package com.example.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

import androidx.annotation.Nullable;

import com.example.download.HttpDownloader;
import com.example.model.Mp3Info;


public class DownloadService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //acquire which file or mp3Info Object is clicked ,then we can call DownloadThread function.
        Mp3Info mp3Info = (Mp3Info) intent.getSerializableExtra("mp3Info");
        DownloadThread downloadThread = new DownloadThread(mp3Info);
        Thread thread = new Thread(downloadThread);
        thread.start();
        return super.onStartCommand(intent, flags, startId);
    }

    //download specified(mp3Info appointed) files in a thread over the network
    //create a new thread.
    class DownloadThread implements Runnable{
        private Mp3Info mp3Info = null;
        public DownloadThread(Mp3Info mp3Info) {
            this.mp3Info = mp3Info;
        }
        public void run(){
            String mp3Url = "http://192.168.1.34:8081/MP3"+mp3Info.getMp3Name();
            HttpDownloader httpDownloader = new HttpDownloader();
            String result = httpDownloader.download(mp3Url);
            int resultInt = Integer.parseInt(result);
            //notify user the consequence of downloading file
            String resultMessage = null;
            if(resultInt == -1){
                resultMessage = "download file failed";
            }else if(resultInt == 0){
                resultMessage = "file existed,can't download repeatly";
            }else if(resultInt == 1){
                resultMessage = "file download successsfully";
            }
        }
    }
}

Mp3Info

package com.example.model;

import java.io.Serializable;

public class Mp3Info implements Serializable {
    private String id;
    private String mp3Name;
    private String mp3Size;
    private String lrcName;
    private String lrcSize;

    public Mp3Info() {
        super();
    }

    @Override
    public String toString() {
        return "Mp3Info{" +
                "id='" + id + '\'' +
                ", mp3Name='" + mp3Name + '\'' +
                ", mp3Size='" + mp3Size + '\'' +
                ", lrcName='" + lrcName + '\'' +
                ", lrcSize='" + lrcSize + '\'' +
                '}';
    }

    public Mp3Info(String id, String mp3Name, String mp3Size, String lrcName, String lrcSize) {
        super();
        this.id = id;
        this.mp3Name = mp3Name;
        this.mp3Size = mp3Size;
        this.lrcName = lrcName;
        this.lrcSize = lrcSize;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setMp3Name(String mp3Name) {
        this.mp3Name = mp3Name;
    }

    public void setMp3Size(String mp3Size) {
        this.mp3Size = mp3Size;
    }

    public void setLrcName(String lrcName) {
        this.lrcName = lrcName;
    }

    public void setLrcSize(String lrcSize) {
        this.lrcSize = lrcSize;
    }


    public String getId() {
        return id;
    }

    public String getMp3Name() {
        return mp3Name;
    }

    public String getMp3Size() {
        return mp3Size;
    }

    public String getLrcName() {
        return lrcName;
    }

    public String getLrcSize() {
        return lrcSize;
    }
}

HttpDownloader

package com.example.download;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class HttpDownloader {
    public String download(String urlStr){
        StringBuffer sb = new StringBuffer();
        String line = null;
        BufferedReader buffer = null;
        try{
            //创建一个url对象
            URL url = new URL(urlStr);
            //创建一个http连接
            HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
            //使用io流读取数据
            buffer = new BufferedReader(new InputStreamReader((urlConn.getInputStream())));
            while((line = buffer.readLine()) != null){
                sb.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try{
                buffer.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
}

Mp3ListActivity

采用tabHost布局显示远程文件和本地文件,点击“remote”按钮,选择文件下载,即可在“local”按钮下的页面中查看到下载的文件。页面布局采用layout.mp3_list_activity。

package com.example.mp3player;

import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.TabHost;

public class Mp3ListActivity extends TabActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mp3_list_activity);
        //obtain a TabHost object
        TabHost tabHost = getTabHost();
        //generate a Intent object and point to MainActivity
        Intent remoteIntent = new Intent();
        remoteIntent.setClass(this,MainActivity.class);
        //generate TabSpec object ,it assign a page includes Remote button and file list
        TabHost.TabSpec remoteSpec = tabHost.newTabSpec("Reomte");
        //define the remote button text and image form android library
        Resources res = getResources();
        remoteSpec.setIndicator("Remote",res.getDrawable(android.R.drawable.stat_sys_download));
        //set remoteSpec object text and picture
        remoteSpec.setContent(remoteIntent);
        //add remoteSpec in tabHost
        tabHost.addTab(remoteSpec);

        Intent localIntent = new Intent();
        localIntent.setClass(this,LocalMp3ListActivity.class);
        TabHost.TabSpec localSpec = tabHost.newTabSpec("Local");
        localSpec.setIndicator("Local",res.getDrawable(android.R.drawable.stat_sys_download));
        localSpec.setContent(localIntent);
        tabHost.addTab(localSpec);
    }
}

LocalMp3ListActivity

读取到下载的文件的名字和尺寸,显示在页面上,监听点击事件。如果监听到用户点击某文件,调用PlayerActivity播放音乐。

package com.example.mp3player;

import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import com.example.model.Mp3Info;
import com.example.utils.FileUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

public class LocalMp3ListActivity extends ListActivity {
    private List<Mp3Info> mp3Infos = null;
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.local_mp3_list_activity);
    }
    @Override
    protected void onResume() {
        FileUtils fileUtils = new FileUtils();
        List<Mp3Info> mp3Infos = fileUtils.getMp3File("mp3/");
        List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
        for (Iterator iterator = mp3Infos.iterator(); iterator.hasNext(); ) {
            Mp3Info mp3Info = (Mp3Info) iterator.next();
            HashMap<String, String> map = new HashMap<String, String>();
            map.put("mp3_name", mp3Info.getMp3Name());
            map.put("mp3_size", mp3Info.getMp3Size());
            list.add(map);
        }

        SimpleAdapter simpleAdapter = new SimpleAdapter(this, list, R.layout.mp3info_item, new String[]{"mp3_name", "mp3_size"}, new int[]{R.id.mp3_name, R.id.mp3_size});
        setListAdapter(simpleAdapter);
        super.onResume();
    }

    protected void onListItemClick(ListView l, View v, int position, long id){
        if(mp3Infos != null){
            Mp3Info mp3Info = mp3Infos.get(position);
            Intent intent = new Intent();
            intent.putExtra("mp3Info",mp3Info);
            intent.setClass(this,PlayerActivity.class);
            startActivity(intent);
        }
    }
}

FileUtils

package com.example.utils;

import android.os.Environment;

import com.example.model.Mp3Info;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class FileUtils {
    private String SDCardRoot;

    //get Directory of external device
    public FileUtils(){
        SDCardRoot = Environment.getExternalStorageDirectory().getAbsolutePath();
    }

    //create document in SDCard
    //function file.seperator is equal to '/'
    public File createFileInSDCard(String fileName, String dir) throws IOException {
        File file = new File(SDCardRoot+dir+File.separator+fileName);
        file.createNewFile();
        return file;
    }

    //create folder in SDCard
    public File createSDDir(String dir){
        File dirFile = new File(SDCardRoot+dir+File.separator);
        dirFile.mkdir();
        return dirFile;
    }
    //check whether the file exists on the sd card
    public boolean isFileExist(String fileName,String dir){
        File file = new File(SDCardRoot+dir+File.separator+fileName);
        return file.exists();
    }
    //write datas from InputStream in sd card
    public File write2SDFromInput(String path, String fileName, InputStream input){
        File file = null;
        OutputStream output = null;
        try{
            createSDDir(path);
            file = createFileInSDCard(fileName,path);
            output = new FileOutputStream(file);
            byte buffer[] = new byte[4*1024];
            int temp;
            while((temp = input.read(buffer)) != -1){
                output.write(buffer,0,temp);
            }
            output.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                output.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return file;
    }
    //read files name and size
    public List<Mp3Info> getMp3File(String path){
        List<Mp3Info> mp3InfoList = new ArrayList<Mp3Info>();
        File file = new File(SDCardRoot+File.separator+path);
        //traverse directory
        File[] files = file.listFiles();
        for(int i=0;i<files.length;i++){
            if(files[i].getName().endsWith("mp3")){
                Mp3Info mp3Info = new Mp3Info();
                mp3Info.setMp3Name(files[i].getName());
                mp3Info.setMp3Size(files[i].length()+"");
                mp3InfoList.add(mp3Info);
            }
        }
        return mp3InfoList;
    }
}

PlayerActivity

创建播放、暂停、停止三个按钮;如果监听到调用PlayService 服务,并开启线程更新歌词文件。文章来源地址https://www.toymoban.com/news/detail-526894.html

package com.example.mp3player;

import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;

import com.example.lrc.LrcProcess;
import com.example.model.AppConstant;
import com.example.model.Mp3Info;
import com.example.service.PlayService;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Queue;

public class PlayerActivity extends Activity {
    private ImageButton beginButton = null;
    private ImageButton pauseButton = null;
    private ImageButton stopButton = null;
    private MediaPlayer mediaPlayer = null;
    private boolean isPlaying = false;
    private boolean isPause = false;
    private  boolean isReleased = false;
    private Mp3Info mp3Info = null;

    private Handler handler = new Handler();
    private UpdateTimeCallback updateTimeCallback = null;
    private long begin = 0;
    private long nextTimeMill = 0;
    private long currentTimeMill = 0;
    private String message = null;
    private long pauseTimeMills = 0;
    private ArrayList<Queue> queues = null;
    private TextView lrcTextView = null;
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.player);
        Intent intent = new Intent();
        mp3Info = (Mp3Info) intent.getSerializableExtra("mp3Info");

        beginButton = (ImageButton) findViewById(R.id.begin);
        pauseButton = (ImageButton) findViewById(R.id.pause);
        stopButton = (ImageButton) findViewById(R.id.stop);
        lrcTextView = (TextView) findViewById(R.id.lrcText);

        beginButton.setOnClickListener(new beginButtonListener());
        pauseButton.setOnClickListener(new pauseButtonListener());
        stopButton.setOnClickListener(new stopButtonListener());

    }
    class beginButtonListener implements View.OnClickListener{
        @Override
        public void onClick(View v){
            //用于使用Service播放Mp3音乐
            Intent intent = new Intent();
            intent.setClass(PlayerActivity.this,PlayService.class);
            intent.putExtra("mp3Info",mp3Info);
            intent.putExtra("MSG",AppConstant.PlayMsg.PLAY_MSG);
            //读取lrc文件
            prepareLrc(mp3Info.getLrcName());
            //启动service
            startService(intent);
            //begin当前毫秒数
            begin = System.currentTimeMillis();
            //延后5s执行updateTimeCallback函数
            handler.postDelayed(updateTimeCallback,5);
            isPlaying = true;
        }
    }
    class pauseButtonListener implements View.OnClickListener{
        @Override
        public void onClick(View v){
            Intent intent = new Intent();
            intent.setClass(PlayerActivity.this, PlayService.class);
            intent.putExtra("MSG", AppConstant.PlayMsg.PAUSE_MSG);
            startService(intent);
            if(isPlaying){
                handler.removeCallbacks(updateTimeCallback);
                pauseTimeMills = System.currentTimeMillis();
            }else {
                handler.postDelayed(updateTimeCallback,5);
                begin = System.currentTimeMillis() - pauseTimeMills+begin;
            }
            isPlaying = isPlaying ? false : true;
        }
    }
    class stopButtonListener implements View.OnClickListener{
        @Override
        public void onClick(View v){
            //通知Service停止播放Mp3文件
            Intent intent = new Intent();
            intent.setClass(PlayerActivity.this,PlayService.class);
            intent.putExtra("MSG",AppConstant.PlayMsg.STOP_MSG);
            startService(intent);
            //从handler中移除updateTimeCallback--->更新lyric函数。
            handler.removeCallbacks(updateTimeCallback);
        }
    }

    //更新歌词文件
    class UpdateTimeCallback implements Runnable{
        ArrayList<Queue> queues = null;
        Queue times = null;
        Queue messages = null;
        public UpdateTimeCallback(ArrayList<Queue> queues){
            this.queues = queues;
            times = queues.get(0);
            messages = queues.get(1);
        }

        @Override
        public void run() {
            //计算开始播放到现在的时长,以毫秒为单位。
            long offset = System.currentTimeMillis()-begin;
            System.out.println(offset);
            //currentTimeMill == 0---->第一次调用UpdateTimeCallback函数
            if(currentTimeMill == 0){
                nextTimeMill = (Long)times.poll();
                message = (String) messages.poll();
            }
            //现在时间已经大于下一次要播放音乐的时间了,把下一次要重新的时间点和歌词信息保存起来
            if(offset >= nextTimeMill){
                lrcTextView.setText(message);
                message = (String)messages.poll();
                nextTimeMill = (Long)times.poll();
            }
            currentTimeMill = currentTimeMill + 10;
            //每隔10ms检查当前时间是否超过要重现加载歌词的时间
            handler.postDelayed(updateTimeCallback,10);
        }
    }
    //acquire lyric file information by lyric file name.
    private void prepareLrc(String lrcName){
        try{
            InputStream inputStream = new FileInputStream(Environment.getExternalStorageDirectory().getAbsolutePath());
            LrcProcess lrcProcess = new LrcProcess();
            //obtain lyric by inputStream.
            //得到事件队列和歌词队列  
            queues = lrcProcess.process(inputStream);
            updateTimeCallback = new UpdateTimeCallback(queues);
            begin = 0;
            currentTimeMill = 0;
            nextTimeMill = 0;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

PlayService

package com.example.service;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Environment;
import android.os.IBinder;

import androidx.annotation.Nullable;

import com.example.model.AppConstant;
import com.example.model.Mp3Info;
import com.example.mp3player.PlayerActivity;

import java.io.File;

public class PlayService extends Service {
    private MediaPlayer mediaPlayer = null;
    private boolean isPlaying = false;
    private boolean isPause = false;
    private  boolean isReleased = false;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    public int onStartCommand(Intent intent,int flags,int startId){
        Mp3Info mp3Info = (Mp3Info) intent.getSerializableExtra("mp3Info");
        int MSG = intent.getIntExtra("MSG",0);
        if(mp3Info != null){
            if(MSG == AppConstant.PlayMsg.PLAY_MSG){
                play(mp3Info);
            }
        }else{
            if(MSG == AppConstant.PlayMsg.PAUSE_MSG){
                pause();
            }else if(MSG == AppConstant.PlayMsg.STOP_MSG){
                stop();
            }
        }
        return super.onStartCommand(intent,flags,startId);
    }

    private void play(Mp3Info mp3Info){
        String path = getMp3Path(mp3Info);
        //function uri.parese compulsive require having prefix "file://"
        mediaPlayer = MediaPlayer.create(this, Uri.parse("file://"+path));
        //turn off looply playing music
        mediaPlayer.setLooping(false);
        //begin playing music
        mediaPlayer.start();
        isPlaying = true;
        isPause = false;
    }
    private void pause(){
        //if we don't know whether mediaPlayer equals to null,we will meet problem of null pointer exception after we directly used it.
        if(mediaPlayer != null){
            if(!isReleased){
                if(!isPause){
                    //state is playing music,click the pause button,we will pause the music.
                    mediaPlayer.pause();
                    isPause = true;
                    isPlaying = false;
                }else{
                    //state is pausing,click the pause button,we will play the music.
                    mediaPlayer.start();
                    isPause = false;
                    isPlaying = true;
                }
            }
        }
    }
    private void stop(){
        if(mediaPlayer != null){
            if(isPlaying){
                if(!isReleased){
                    mediaPlayer.stop();
                    //release all resources mediaPlayer used
                    mediaPlayer.release();
                    isReleased = true;
                }
                isPlaying = false;
            }
        }
    }
    //acquire mp3Path
    private String getMp3Path(Mp3Info mp3Info){
        String SDCardRoot  = Environment.getExternalStorageDirectory().getAbsolutePath();
        String path = SDCardRoot+ File.separator+"mp3/"+File.separator+mp3Info.getMp3Name();
        return path;
    }
}

LrcProcess

package com.example.lrc;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LrcProcess {
    public ArrayList<Queue> process(InputStream inputStream){
        //time list
        Queue<Long> timeMills = new LinkedList<Long>();
        //message list
        Queue<String> messages = new LinkedList<>();
        ArrayList<Queue> queues = new ArrayList<Queue>();
        try{
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String temp = null;
            int i = 0;
            Pattern p = Pattern.compile("\\[([^\\]]+)\\]");
            String result = null;
            boolean b = true;
            while((temp = bufferedReader.readLine()) != null){
                i++;
                Matcher m = p.matcher(temp);
                if(m.find()){
                    if(result != null){
                        messages.add(result);
                    }
                    String timeStr = m.group();
                    Long timeMill = time2Long(timeStr.substring(1,timeStr.length()-1));
                    if(b){
                        timeMills.offer(timeMill);
                    }
                    String msg = temp.substring(10);
                    result = ""+msg+"\n";
                }else{
                    result = result+temp+"\n";
                }
                messages.add(result);
                queues.add(timeMills);
                queues.add(messages);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return queues;
    }
    //turn time to millisecond
    public Long time2Long(String timeStr){
        String s[]= timeStr.split(":");
        int min = Integer.parseInt(s[0]);
        String ss[] = s[1].split("\\.");
        int sec = Integer.parseInt(ss[0]);
        int mill = Integer.parseInt(ss[1]);
        return min * 60 * 100 + sec * 1000 + mill * 10L;
    }
}

AppConstant

package com.example.model;

public interface AppConstant {
    public class PlayMsg{
        public static final int PLAY_MSG = 1;
        public static final int PAUSE_MSG = 2;
        public static final int STOP_MSG = 3;
    }
    public class URL{
        public static final String BASE_URL = "http://192.168.1.34:8081/MP3/";
    }
}

Mp3ListContentHandler

package com.example.xml;

import com.example.model.Mp3Info;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.util.List;
//读取xml文件并生成一个对象数组
public class Mp3ListContentHandler extends DefaultHandler {
    private List<Mp3Info> infos = null;

    public Mp3ListContentHandler(List<Mp3Info> infos) {
        this.infos = infos;
    }

    private Mp3Info mp3Info = null;
    private String tagName = null;
    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
            this.tagName = localName;
            //以resource为节点设置成一个Mp3Info对象
            if(tagName.equals("resource")){
                mp3Info = new Mp3Info();
            }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if(qName.equals("resource")){
            infos.add(mp3Info);
        }
        tagName = "";
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        String temp = new String(ch,start,length);
        if(tagName.equals("id")){
            mp3Info.setId(temp);
        }else if(tagName.equals("mp3.name")){
            mp3Info.setMp3Name(temp);
        }else if(tagName.equals("mp3.size")){
            mp3Info.setMp3Size(temp);
        }else if(tagName.equals("lrc.name")){
            mp3Info.setLrcName(temp);
        }else if(tagName.equals("lrc.size")){
            mp3Info.setLrcSize(temp);
        }
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:id="@+id/listLinearLayout"
        android:orientation="vertical"
        android:width="fill_parent"
        android:height="wrap_content">
        <!--suppress AndroidDomInspection -->
        <ListView android:id="@id/android:list"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:drawSelectorOnTop="false"
            android:scrollbars="vertical"/>
    </LinearLayout>
</LinearLayout>

local_mp3_list_activity.xml

<TabHost
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/tabhost">
    <LinearLayout android:orientation="vertical"
        android:layout_width="fill_parent"
        android:lauout_height="wrap_content"
        android:padding="5dip">
        <TabWidget
            android:id="@+id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>
        <FrameLayout
            android:id="@+id/tabContent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:padding="5dip"/>
    </LinearLayout>
</TabHost>

mp3_list_activity.xml

<TabHost
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/tabhost">
    <LinearLayout android:orientation="vertical"
        android:layout_width="fill_parent"
        android:lauout_height="wrap_content"
        android:padding="5dip">
        <TabWidget
            android:id="@+id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>
        <FrameLayout
            android:id="@+id/tabContent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:padding="5dip"/>
    </LinearLayout>
</TabHost>

mp3info_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal"
    android:paddingLeft="10dip"
    android:paddingRight="10dip"
    android:paddingTop="1dip"
    android:paddingBottom="1dip">

    <TextView
        android:id="@+id/mp3_name"
        android:layout_height="30dip"
        android:layout_width="180dip"
        android:textSize="10pt"/>
    <TextView
        android:id="@+id/mp3_size"
        android:layout_height="30dip"
        android:layout_width="180dip"
        android:textSize="10pt"/>
</LinearLayout>

player.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:padding="10dip">
    <ImageButton
        android:id="@+id/begin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/begin"/>
    <ImageButton
        android:id="@+id/pause"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/pause"/>
    <ImageButton
        android:id="@+id/stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/stop"/>
    <TextView
        android:id="@+id/lrcText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

到了这里,关于Android学习_Mars老师之Mp3视频开发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【学习】从零开始的Android音视频开发(3)——MediaPlayer的prepare/prepareAsync流程和start流程

    在之前的流程中我们没有从MediaPlayer生态上认识各类库之间的依赖调用关系 MediaPlayer部分头文件在frameworks/base/include/media/目录中,这个目录和libmedia.so库源文件的目录frameworks/av/media/libmedia/相对应。主要头文件有 IMediaPlayerClient.h、mediaplayer.h、IMediaPlayer.h、IMediaPlayerService.h、Med

    2024年02月03日
    浏览(30)
  • 5G到来未来五年,做纯应用的Android开发者如何学习通过音视频破局?附《578页NDK七大模块学习宝典》(1)

    “只懂应用层,目前越来越多的企业要求音视频技术,我该怎么办?” “到底该不该学习音视频,怎么抉择?\\\" “想从事音视频开发,该怎么入门?如何进阶 ?” 如果你有这样的问题,从侧面反映了你是一个积极向上,想不断努力来提升自己的人。 先从一个简单的问题聊起

    2024年04月23日
    浏览(43)
  • Android 播放mp3文件

    1,在res/raw中加入mp3文件 2,实现播放类 3,初始化声音播放类,一般在onCreate中调用 4,调用播放,初始化后可以多次调用 5,播放速度与音量等参数调节

    2024年02月09日
    浏览(26)
  • Android 音视频开发 - VideoView

    本篇文章主要介绍下Android 中的VideoView. VideoView是一个用于播放视频的视图组件,可以方便地在应用程序中播放本地或网络上的视频文件。 VideoView可以直接在布局文件中使用,也可以在代码中动态创建。 它封装了MediaPlayer和SurfaceView,提供了简单的接口来控制视频的播放和显示

    2024年04月08日
    浏览(80)
  • Android音视频开发 - MediaMetadataRetriever 相关

    MediaMetadataRetriever 是android中用于从媒体文件中提取元数据新的类. 可以获取音频,视频和图像文件的各种信息,如时长,标题,封面等. 需要申请 读写权限 . 这里我使用的是本地路径, 需要注意的是如果路径文件不存在,会抛出 IllegalArgumentException,具体的源码如下: 根据keyCode返回keyC

    2024年04月08日
    浏览(39)
  • android开发教程视频孙老师,flutter中文网

    1.网络 2.Java 基础容器同步设计模式 3.Java 虚拟机内存结构GC类加载四种引用动态代理 4.Android 基础性能优化Framwork 5.Android 模块化热修复热更新打包混淆压缩 6.音视频FFmpeg播放器 网络协议模型 应用层 :负责处理特定的应用程序细节 HTTP、FTP、DNS 传输层 :为两台主机提供端到端

    2024年03月15日
    浏览(35)
  • Android 音视频开发—MediaPlayer音频与视频的播放介绍

    Android多媒体中的——MediaPlayer,我们可以通过这个API来播放音频和视频该类是Androd多媒体框架中的一个重要组件,通过该类,我们可以以最小的步骤来获取,解码和播放音视频。 它支持三种不同的媒体来源: 本地资源 内部的URI,比如你可以通过ContentResolver来获取 外部URL(流

    2024年02月10日
    浏览(45)
  • Android音视频开发实战01-环境搭建

    FFmpeg 是一款流行的开源多媒体处理工具,它可以用于转换、编辑、录制和流式传输音视频文件。FFmpeg 具有广泛的应用场景,包括视频编解码、格式转换、裁剪、合并、滤镜等等。官网:https://ffmpeg.org/ FFmpeg 支持各种常见的音视频格式,例如 MP4、AVI、FLV、MOV、AAC、MP3、M4A 等等

    2024年02月10日
    浏览(37)
  • Android音视频开发实战02-Jni

    JNI是Java Native Interface的缩写,是Java提供的一种机制,用于在Java代码中调用本地(C/C++)代码。它允许Java代码与本地代码进行交互,通过JNI,Java应用程序可以调用一些原生库或者操作系统API,以获取更好的性能和更强的功能支持。 使用JNI需要编写一些Native方法,并将其实现在

    2024年02月11日
    浏览(38)
  • Android-音视频学习系列-(九)Android-端实现-rtmp-推流

    视频画面的采集主要是使用各个平台提供的摄像头 API 来实现的,在为摄像头设置了合适的参数之后,将摄像头实时采集的视频帧渲染到屏幕上提供给用户预览,然后将该视频帧传递给编码通道,进行编码。 1. 权限配置 2. 打开摄像头 2.1 检查摄像头 public static void checkCameraSe

    2024年04月12日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包