Android从本地服务器获取Mp3实现边下边播(JavaEE+Tomcat+SQLServer)

项目实例:https://download.csdn.net/download/qq_37437983/10484636

实现环境:

    1)Lenovo G50-80 Ubuntu16.04笔记本

    2)Android Studio

    3)Eclipse J2EE

    4)Tomcat 8.5

    5)sqlServer

    6)jdk1.8

 

概要设计

基于Android平台的MP3在线播放器的设计与实现的目标为:

    (l)采用布局和组件绘制系统界面。

    (2)完成系统中登录界面和播放界面之间的跳转。

    (3)实现界面上端的歌曲信息展示。

    (4)实现在线播放功能。

    (4)实现歌曲的上一首和下一首切换。

 

数据库表设计

(1) 用户表Userlogin,管理员信息表用于存放管理员的相关信息,结构如表1所示。

 

(2) 题目表Mp3Info,题目表用于存放用户答错的题目,结构如表2所示。

 

登录模块

运行在线Mp3播放系统,首先进入系统的登录界面。如图所示:

图8 登陆界面

  登陆时需要判断用户名和密码是否正确,首先Android端提出登录请求并将请求帐号和密码通过Get形式传送出去,代码如下:

public class UserLogin extends AsyncTask<Void,Void,String> {

    private String account;
    private String password;


    UserLogin(String account,String password){
        this.account = account;
        this.password = password;
    }


    @Override
    protected String doInBackground(Void... voids) {
        String PATH = "http://192.168.43.102:8080/Mp3Manager/login?account="+account+"&password="+password;
        String result = "";
        try {
            HttpGet get = new HttpGet(new URI(PATH));
            HttpClient client = new DefaultHttpClient();
            HttpResponse response = client.execute(get);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                result = EntityUtils.toString(response.getEntity());
                Log.v("+++++++++++++++++++", result);
            }else {
                Log.v("-------------------", result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    protected void onPostExecute(String result){
        if(result.equals("yes")){
            Intent intent = new Intent(mactivity,PlayArea.class);
            mactivity.startActivity(intent);
        //    Toast.makeText(mactivity, "登录成功", Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(mactivity, "登录失败,请输入正确的帐号和密码", Toast.LENGTH_SHORT).show();
        }
    }
}

  JavaEE后台收到请求后,通过web.xml筛选后执行UserLogin.java文件,代码如下:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// TODO Auto-generated method stub

String account = request.getParameter("account");

String password = request.getParameter("password");

String sql = "select password from UserCollection where account = '"+account+"'";

DBOper db = new DBOper();

ResultSet rs = db.exeQuery(sql);

try {

if(rs.next()&&rs.getString(1).equals(password)) {

response.getWriter().append("yes");

// System.out.println("yes");

}else {

response.getWriter().append("no");

// System.out.println("no");

}

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

图9,用户名后台

 

5.2  播放音乐模块

登录成功之后进入主界面,如图所示:

图10 主界面

此界面分为两部分,上面的部分是歌曲列表,可以根据歌曲多少自适应调整高度,并且点击之后会显示出歌曲的详细信息;下面部分是播放模块,可进行音乐的播放和暂停,并且还可进行上一曲和下一曲的音乐切换.Android端实现的代码如下:

public class myAsyncTask extends AsyncTask<Void, Void, String> {
    /**
     * 用于异步下载数据
     */
    @Override
    protected String doInBackground(Void... arg0) {
        // TODO Auto-generated method stub
        String result = "";
        String PATH = "http://192.168.43.102:8080/Mp3Manager/getMp3Info?";
        try {
            HttpGet get = new HttpGet(new URI(PATH));
            HttpClient client = new DefaultHttpClient();
            HttpResponse response = client.execute(get);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                result = EntityUtils.toString(response.getEntity());
                // 从后台获得的数据去掉空格
                result = result.trim();
                Log.v("++++++++++", result);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 解析result(json格式的字符串)并将之存入到lists中
     */
    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        try {
            JSONArray array = new JSONObject(result).getJSONArray("MP3INFO");
            for (int i = 0; i < array.length(); i++) {

                Mp3Info mp3 = new Mp3Info();
                JSONObject object = array.getJSONObject(i);
            //    Log.v("+++++++++++++++++++++", i+"+++++++++++++++++++");
                String id = object.getString("id").toString();
                String song = object.getString("song").toString();
                String Zsong = object.getString("Zsong").toString();
                String singer = object.getString("singer").toString();
                String album = object.getString("album").toString();
                String notes = object.getString("notes").toString();
                mp3.setAlbum(album);
                mp3.setId(id);
                mp3.setNotes(notes);
                mp3.setSong(song);
                mp3.setZsong(Zsong);
                mp3.setSinger(singer);
                lists.add(mp3);
                listSong.add(Zsong);
            }
            lenMp3 = lists.size();
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(PlayArea.this,android.R.layout.simple_list_item_1,listSong);
            listView.setAdapter(adapter);


            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {


                    curMp3 = i;
                    Mp3Info mp3Info = (Mp3Info)lists.get(i);
                    String id = mp3Info.getId().toString();
                    final String song = mp3Info.getSong().toString();
                    final String Zsong = mp3Info.getZsong().toString();
                    final String singer = mp3Info.getSinger().toString();
                    String album = mp3Info.getAlbum().toString();
                    String notes = mp3Info.getNotes().toString();
                    new AlertDialog.Builder(PlayArea.this)
                            .setIcon(R.drawable.title)
                            .setTitle("歌曲简介")
                            .setMessage("歌曲:  "+Zsong+"\n\ni d:  "+id+"\n\n歌 手:  "+singer+"\n\n专 辑:  "+album+"\n\n备 注:  "+notes)
                            .setPositiveButton("播放",new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    PlayMp3 playMp3 = new PlayMp3();
                                    playMp3.init(song,Zsong,singer);
                                //    Toast.makeText(PlayArea.this, "点击播放 ", Toast.LENGTH_SHORT).show();
                                }
                            })
                            .setNegativeButton("关闭",null)
                            .show();
                }
            });


            ivMusicPlay.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    PlayMp3 playMp3 = new PlayMp3();
                    playMp3.init();
                }
            });
            ivMusicPre.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    curMp3--;
                    if(curMp3<0) curMp3 = lenMp3-1;
                    Mp3Info mp3Info = (Mp3Info) lists.get(curMp3);
                    final String song = mp3Info.getSong().toString();
                    final String Zsong = mp3Info.getZsong().toString();
                    final String singer = mp3Info.getSinger().toString();
                    PlayMp3 playMp3 = new PlayMp3();
                    playMp3.init(song,Zsong,singer);
                }
            });
            ivMusicNext.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    curMp3++;
                    if(curMp3>=lenMp3) curMp3 = 0;
                    Mp3Info mp3Info = (Mp3Info) lists.get(curMp3);
                    final String song = mp3Info.getSong().toString();
                    final String Zsong = mp3Info.getZsong().toString();
                    final String singer = mp3Info.getSinger().toString();
                    PlayMp3 playMp3 = new PlayMp3();
                    playMp3.init(song,Zsong,singer);
                }
            });
        } catch (Exception e) {


            // TODO Auto-generated catch block
            Log.v("+++++++++++++++++++++", e.getMessage());
            e.printStackTrace();
        }
        super.onPostExecute(result);
    }
}

 

图11 点击列表显示详情信息

 

 

  Android端显示的信息是后台Gson将封装好的list转换为String对象传给Android端解析.代码如下:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 

// TODO Auto-generated method stub

//获取gson

Gson gson = new Gson();

List<Mp3Info> infos = new ArrayList<>();

//获取数据库信息

DBOper db = new DBOper();

String sql = "select * from Mp3Info";

ResultSet rs = db.exeQuery(sql);

try {

while(rs.next()) {

Mp3Info info = new Mp3Info();

String id = rs.getString(1);

String song = rs.getString(2);

String Zsong = rs.getString(3);

String singer = rs.getString(4);

String album = rs.getString(5);

String notes = rs.getString(6);

info.setId(id);

info.setSong(song);

info.setAlbum(album);

info.setNotes(notes);

info.setZsong(Zsong);

info.setSinger(singer);

infos.add(info);

}

//将infos转换为json格式的字符串

String str = gson.toJson(infos);

request.setAttribute("MP3INFO", "{\"MP3INFO\":"+str+"}");

request.getRequestDispatcher("index.jsp").forward(request, response);

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

response.getWriter().append("Served at: ").append(request.getContextPath());

}

 

图12 后台歌曲信息界面

5.3  播放器数据源获取

本系统的最关键之处就是从后台Mp3库中获取数据源交给MediaPlayer.主要想法就是定义两个Socket:远程Socket和本地Socket.其中远程Socket用于请求服务器资源,本地Socket负责监听mediaplayer请求,并将远程Socket获得数据写入mediaPlayer中进行播放.

(1)首先初始化本地Socket,代码如下:

public MediaPlayerProxy(String writeFileName, boolean writeFile) throws Exception {

    currPlayDegree = 0;//当前音乐播放进度
    proxyFail = false;//代理播放失败了
    cachedFileLength = 0;//已缓存的文件长度
    fileTotalLength = 0;//要缓存的文件总长度
    currMusicCachedProgress = 0;//当前的音乐缓冲值(seekbar上的缓冲值)


    proxyIdle = false;  //代理忙
    this.writeFile = writeFile;
    this.writeFileName = writeFileName;

    try {
        if (localServer == null || localServer.isClosed()) {
            //创建本地socket服务器,用来监听mediaplayer请求和给mediaplayer提供数据
            localServer = new ServerSocket();
            localServer.setReuseAddress(true);
            //创建IP地址为192.168.43.1,端口号为9090的本地端口地址
            InetSocketAddress socketAddress = new InetSocketAddress(InetAddress.getByName(LOCAL_IP_ADDRESS), local_ip_port);
            //本地socket绑定本地端口地址
            localServer.bind(socketAddress);
        }
    } catch (Exception e) {
        Log.e("1111111111111111+++++++",e.getMessage());
        try {
            local_ip_port--;  //端口号非空闲,自减
            localServer = new ServerSocket();
            localServer.setReuseAddress(true);
            //创建IP地址为192.168.43.1,端口号为9090的本地端口地址
            InetSocketAddress socketAddress = new InetSocketAddress(InetAddress.getByName(LOCAL_IP_ADDRESS), local_ip_port);
            //本地socket绑定本地端口地址
            localServer.bind(socketAddress);
        } catch (Exception e2) {
            Log.e("22222222222222++++++",e2.getMessage());
            throw new Exception();
        }
    }
}

(2)根据真实的请求音源文件地址,得到本地音源文件地址将本地音源地址通过setDataSource的方式传递给mediaplayer. 前面创建的本地socket对象监听这个地址,用于获取mediaplayer的请求数据。代码如下:

public String getLocalURLAndSetRemotSocketAddr(String url) {
    try {
        remotUrl = url;
        if (writeFile) {  //正在缓存的音乐地址
            bufferingMusicUrlList.add(remotUrl);
        }

        String localProxyUrl = "";

        final URI originalURI = URI.create(url);
        final String remoteHost = originalURI.getHost();  //服务器主机
        if (!TextUtils.isEmpty(remoteHost)) {  //存在主机
            if (originalURI.getPort() != -1) {//URL带Port
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //服务器的主机号和端口
                        remoteAddress = new InetSocketAddress(remoteHost, originalURI.getPort());
                    }
                }).start();
                //替换
                localProxyUrl = url.replace(remoteHost + ":" + originalURI.getPort(), LOCAL_IP_ADDRESS + ":" + local_ip_port);
                remoteHostAndPort = remoteHost + ":" + originalURI.getPort();
            } else {//URL不带Port,使用80端口
                if (!TextUtils.isEmpty(remoteHost)) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            remoteAddress = new InetSocketAddress(remoteHost, HTTP_PORT);//使用80端口
                        }
                    }).start();
                    localProxyUrl = url.replace(remoteHost, LOCAL_IP_ADDRESS + ":" + local_ip_port);
                    remoteHostAndPort = remoteHost;
                }
            }
        }
        return localProxyUrl;
    } catch (Exception e) {
        Log.e("+333333333333++++++++++",e.getMessage());
        return "";
    }
}

  (3)本地socket监听mediaplayer,通过getInputStream方法可以获取到mediaplayer传递过来的请求信息数据,由于我们是通过本地代理地址的方式获取到的,所以我们需要根据这个本地的请求信息替换成真实的远程socket请求信息,向服务器获取真实请求数据。代码如下:

public void getTrueSocketRequestInfo(Socket localSocket) throws Exception {
    InputStream in_localSocket = localSocket.getInputStream();
    String trueSocketRequestInfoStr = "";//保存MediaPlayer的真实HTTP请求

    byte[] local_request = new byte[1024];
    while (in_localSocket.read(local_request) != -1) {
        String str = new String(local_request);
        trueSocketRequestInfoStr = trueSocketRequestInfoStr + str;

        if (trueSocketRequestInfoStr.contains("GET") && trueSocketRequestInfoStr.contains("\r\n\r\n")) {
            //把request中的本地ip改为远程ip
            trueSocketRequestInfoStr = trueSocketRequestInfoStr.replace(LOCAL_IP_ADDRESS + ":" + local_ip_port, remoteHostAndPort);
            this.trueSocketRequestInfoStr = trueSocketRequestInfoStr;
            //如果用户拖动了进度条,因为拖动了滚动条还有Range则表示本地歌曲还未缓存完,不再保存
            if (trueSocketRequestInfoStr.contains("Range")) {
                Log.e("+44444++++Range++++++","");
                writeFile = false;
            }
            break;
        }
    }
}

 

(4)上一步我们获取到了真实的请求数据信息,此时通过远程socket连接远程请求,代码如下:

 

public Socket sendRemoteRequest() throws Exception {
    //创建远程socket用来请求网络数据
    Socket remoteSocket = new Socket();
    remoteSocket.connect(remoteAddress, socketTimeoutTime);
    remoteSocket.getOutputStream().write(trueSocketRequestInfoStr.getBytes());
    remoteSocket.getOutputStream().flush();
    return remoteSocket;
}

(5)将远程socket的数据,通过本地socket写入mediaplayer进行播放

(6)最后在PlayMp3.java文件中调用,代码如下:

private void playMusic() {
    if(Zsong!=""&&singer!=""){
        tv_Name.setText(Zsong);
        tv_author.setText(singer);
    }


    ivMusicPlay.setImageResource(R.mipmap.music_button_pause);
    currentState = STATE_PLAY;


    * 第一次执行加载数据,之后执行暂停,开始
    * */


    if (!firstPlay && mediaPlayer.getCurrentPosition() > 0) {

        mediaPlayerHttpProxy = null;
        mediaPlayer.start();
    } else {


        try {
         //   Toast.makeText(playArea, Zsong+"加载"+mediaPlayer.getCurrentPosition(), Toast.LENGTH_SHORT).show();
            mediaPlayerHttpProxy = new MediaPlayerProxy(Zsong, false);
            //setProgress是文件写入本地进度,setSecondaryProgress就是文件加载进度
            mediaPlayerHttpProxy.setOnCaChedProgressUpdateListener(new MediaPlayerProxy.OnCaChedProgressUpdateListener() {
                @Override
                public void updateCachedProgress(int progress) {
                    sb_music.setSecondaryProgress(progress);
                }
            });


            //得到从服务器得到的数据源
            String localProxyUrl = mediaPlayerHttpProxy.getLocalURLAndSetRemotSocketAddr(TEST_URL);
            mediaPlayerHttpProxy.startProxy();
            mediaPlayer.setDataSource(localProxyUrl);
            mediaPlayer.prepareAsync();
            firstPlay = false;


        } catch (Exception e) {
            Log.e("++++++++++++++++++++",e.getMessage());
        }
    }
}

 

项目实例:https://download.csdn.net/download/qq_37437983/10484636

下载积分不够的,留言中有百度云下载链接。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 23
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我要出家当道士

打赏是不可能,这辈子都不可能

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值