上一个版本只完成了音乐播放的功能,此次编写实现了歌单搜索,歌曲选择以及歌曲下载的功能,一些基本功能已经大体完成了,后续也只是一些BUG处理,脚本逻辑完善等等。app及代码下载在我的公众号:For My Future。


ui.layout(
    <vertical>
        <SearchView id="search" w="*" h="50" marginTop="15"/>
        <ListView id="list" bg="#B0E0E6"/>
        <ListView id="namelist" w="*" h="*"/>
    </vertical>
);

  上方搜索框是searchview控件,下方是两个listview。

  searchview比input使用起来更麻烦一点,选择它是因为手机用键盘输入时会出现搜索的按钮,如下图红圈标识。第一个listview的功能是根据输入自动推荐相关歌曲名称,类似我们百度输入某些文字后输入框下面出现的一些推荐词条,如下图蓝框。第二个listview就是点击搜索按钮后相关歌曲信息的展示了。

 1.1搜索框功能编写

     搜索框样式设置:


ui.search.setIconified( false );
ui.search.setSubmitButtonEnabled(true);
ui.search.setQueryHint( "请输入音乐..." );//搜索的hint

  在功能编写之前,首先要声明一个storage,存储获得的音乐rid以及相关信息,方便脚本之间数据的传递。


var storage = storages.create("1216951671");

  搜索框事件监听,具体详解见代码注释。

ui.search.setOnQueryTextListener( {
    onQueryTextChange ( text ) { //监听搜索框内容改变来推荐词条
        if ( text.length > 0 ) {
            ui.list.setVisibility( 0 );
            // ui.list.setFilterText( text );//设置过滤器
            adapter.getFilter().filter( text );//过滤器与list绑定,具体介绍在后面
        } else {
            ui.list.setVisibility( 8 );//不可见
            ui.list.clearTextFilter();
        }
        return true;
    },
    onQueryTextSubmit(text){ //点击搜索按键后所触发的事件
        ui.list.setVisibility( 8 );
        if(text!=null){
            threads.start(function(){ //线程访问网络,搜索歌曲
                let res =http.get("http://search.kuwo.cn/r.s?all="+text+"&ft=music& itemset=web_2021&client=kt&pn=0&rn=30&rformat=json&encoding=utf8")
                let html=res.body.string().replace(/'/g,'"');//双引号替换单引号
                let json=JSON.parse(html);
                for(i=0;i<20;i++){//搜索20首歌,歌曲名字,时间,id,歌手分别放在对应的列表中
                    songnamelists[i]=json.abslist[i].SONGNAME;
                    durationlists[i]=formatSeconds(json.abslist[i].DURATION);//fomatsecond时间戳转化函数,下文会具体介绍
                    musicridlists[i]=json.abslist[i].MUSICRID;
                    artistlists[i]=json.abslist[i].ARTIST; 
                    totallists[i]= songnamelists[i].toString()+"\t"+"\t"+ artistlists[i].toString()+"\t"+"\t"+durationlists[i].toString();//相关信息汇总在一个列表中 }
            })
            
             let adapter2 = new ArrayAdapter(context, android.R.layout.simple_expandable_list_item_1, totallists)
             ui.namelist.setAdapter(adapter2);//listview控件要与adapter绑定
             ui.namelist.setOnItemClickListener({
            onItemClick( parent,  view, position,  id){//position为 点击歌曲时的位置
                media.stopMusic();
    //let s = adapter.getItem(position);
            musicrid = musicridlists[position];
            total = totallists[position];
            storage.put("musicrid", musicrid);//根据位置取列表中歌曲id及相关信息,storage可存储所选歌曲信息,并发送给音乐播放歌曲界面,实现两个脚本之间传递数据
            storage.put("total", total);
            log(storage.get("musicrid"));
            engines.execScriptFile("界面.js")//启动音乐播放器界面
             }

})
         }
         
        // log(totallists);
         
       return true;}
} );

  1.2推荐词条功能编写

      首先adapter与一个list进行绑定,后续对列表数据的改动就是通过adapter进行操作的。


strArr = [ "许嵩", "如果当时", "庐州月", "昨夜书", "最伟大的作品", "超市" ,"周杰伦" ];//本地推荐的词条,当然也可以通过网上的词条api进行添加
let adapter = new ArrayAdapter( context, android.R.layout.simple_expandable_list_item_1, strArr );
ui.list.setAdapter( adapter );
ui.list.setTextFilterEnabled( true );//启动过滤v
ui.list.setVisibility( 8 );//一开始不显示ListView

ui.list.setOnItemClickListener({//监听list点击
    onItemClick( parent,  view, position,  id){
    let s = adapter.getItem(position);
    ui.search.setQuery(s.toString(),true)}//点击时将词条内容设置到搜索框中
})

    1.3时间戳转化

      通过api得到的音乐时长是秒数,所以还要设计函数转化为分秒的格式。


function formatSeconds(value) {
    let secondTime = parseInt(value);// 秒
    let minuteTime = 0;// 分
    let hourTime = 0;// 小时
    if(secondTime > 60) {//如果秒数大于60,将秒数转换成整数
        //获取分钟,除以60取整数,得到整数分钟
        minuteTime = parseInt(secondTime / 60);
        //获取秒数,秒数取余,得到整数秒数
        secondTime = parseInt(secondTime % 60);
        //如果分钟大于60,将分钟转换成小时
        if(minuteTime > 60) {
            //获取小时,获取分钟除以60,得到整数小时
            hourTime = parseInt(minuteTime / 60);
            //获取小时后取余的分,获取分钟除以60取余的分
            minuteTime = parseInt(minuteTime % 60);
        }
    }
    let result = "" + parseInt(secondTime) + "秒";

    if(minuteTime > 0) {
      result = "" + parseInt(minuteTime) + "分" + result;
    }
    if(hourTime > 0) {
      result = "" + parseInt(hourTime) + "小时" + result;
    }
    return result;
}

二.歌曲下载功能musicv2.js文件编写

  这个文件就是上一个教程的,再做一些修改即可。播放功能在上一个教程讲解过,故不再赘述。下文详细介绍如何进行下载。

  首先创建存储的文件夹,


var dirpath = "/sdcard/下载的音乐/";
files.ensureDir(dirpath);

  在这个脚本用storage的功能得到search.js脚本传递过来的音乐的rid和相关信息。

var storage = storages.create("1216951671");
var musicrid = storage.get("musicrid");
var total = storage.get("total")

  然后取音乐直链进行播放,


let songurl ="http://antiserver.kuwo.cn/anti.s?type=convert_url&rid="+musicrid+"&format=aac|mp3&response=url";
  let songurl1 = http.get(songurl);
  musicurl= songurl1.body.string()
  PlayMusic();

 当点击下载按钮时,根据这个直链进行下载及保存。


ui.down.click(function(){
    threads.start(function(){
        let res = http.get(musicurl);
        files.writeBytes(dirpath+total+".mp3", res.body.bytes());
        toast("下载成功,打开手机自带音乐播放器即可聆听");
        media.scanFile(dirpath);//扫描,自动添加到媒体库
    })
  
})

 最后,在手机自带的音乐播放器即可找到下载的文件。

  其实app还存在很多问题,比如说音乐重音问题,如果正在听音乐,这时返回重新搜索播放新歌曲,就会有二重音,所以在听音乐界面返回搜索音乐界面的时候一定要去点暂停或者停止按钮,这样才不会造成重音。能用但有缺陷,所以这版的音乐app起名为音乐BUG版。

视频演示地址:
https://b23.tv/CnGOyTU

app下载地址:

https://jianglaishi.lanzout.com/ipLGz08fy4qd
密码:c1bv

代码及更多教程在我的微信公众号For My Future上,欢迎关注!

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐