当前位置: 移动技术网 > IT编程>开发语言>Java > java音乐播放器实现代码

java音乐播放器实现代码

2019年07月22日  | 移动技术网IT编程  | 我要评论

武林异史,枪手传奇王牌后卫,快乐大本营2010814

本文实例为大家分享了java音乐播放器的具体代码,供大家参考,具体内容如下

这个是源码结构介绍

这个是界面,有点简陋,见笑了,但是基本上的东西都有了,没办法,没有美工的程序写的界面

直接上源代码player.java

package com.service;
 
import java.io.file;
import java.io.ioexception;
import java.util.arraylist;
import java.util.random;
 
import javax.sound.sampled.*;
import javax.swing.jslider;
import javax.swing.jtable;

import com.list.musiclist;
import com.list.threadlist;
import com.list.viewlist;
import com.model.model;
import com.model.music;
import com.view.view;
 


/*"duration" 
"author" 
"title" 
"copyright" 
"date" 
"comment"*/
public class player extends thread{
 


 private player p;
 private long time = 0;
 
 object lock = new object();//一个空的对象,没什么意义
 
 private boolean paused = false;// 暂停 继续
 
 
 public boolean ispaused() {
 return paused;
 }

 public void setpaused(boolean paused) {
 this.paused = paused;
 }
 
 private jslider jsliderplayprogress;//播放进度条


 private boolean over = false;//开始 结束
 
 //是否自动播放下一曲
 private boolean isnext=true;
 
 
 private music music;//音乐
 
 
 audioinputstream din = null;
 sourcedataline line=null;
 
 private floatcontrol volume = null;

 private jslider jslidervolume; 
 
 public jslider getjslidervolume() {
 return jslidervolume;
 }

 public void setjslidervolume(jslider jslidervolume) {
 this.jslidervolume = jslidervolume;
 
 
 }
 public player(jslider jslidervolume,jslider jsliderplayprogress) {
 super();
 this.jslidervolume = jslidervolume;
 this.jsliderplayprogress=jsliderplayprogress;
 }


 public music getmusic() {
 return music;
 }

 public void setmusic(music music) {
 this.music = music;
 }
 
 public floatcontrol getvolume(){
  return volume;
 }

 
 
 //播放音乐
 public void run(){
 
 audioinputstream in=null;
 
 try {
  
  file file = new file(music.getpath());
 
  //播放不了的歌曲,直接下一首,并且在音乐列表中删除
  try {
   in = audiosystem.getaudioinputstream(file);
  } catch (exception e) {
  //删除有点小问题
  musiclist.getlist().remove(music.getid());
  
  viewlist.getlist().get(0).getjt().setmodel(new model());
  
  
  nextmusic();
  }
  
  audioformat baseformat = in.getformat();
  audioformat decodedformat = new audioformat(
   audioformat.encoding.pcm_signed,
   baseformat.getsamplerate(), 16, baseformat.getchannels(),
   baseformat.getchannels() * 2, baseformat.getsamplerate(),
   false);
  if(baseformat.getencoding()==audioformat.encoding.pcm_unsigned || baseformat.getencoding()==audioformat.encoding.ulaw ||
   baseformat.getencoding()==audioformat.encoding.alaw || baseformat.getencoding()==audioformat.encoding.pcm_signed){
    time=(file.length()*8000000)/((int)(decodedformat.getsamplerate()*baseformat.getsamplesizeinbits()));
  }else{
   int bitrate=0;
   if(baseformat.properties().get("bitrate")!=null){
    //取得播放速度(单位位每秒)
    bitrate=(int)((integer)(baseformat.properties().get("bitrate")));
    if(bitrate!=0)
    time=(file.length()*8000000)/bitrate;
   }
   
  }
  
  
  din = audiosystem.getaudioinputstream(decodedformat, in);
  dataline.info info = new dataline.info(sourcedataline.class, decodedformat);
  line = (sourcedataline) audiosystem.getline(info);
  line.open();
  setvolume();
  jsliderplayprogress.setmaximum((int)time);
  jsliderplayprogress.setvalue(0);
  if(line!=null){
  line.open(decodedformat);
  byte[] data = new byte[4096];
  int nbytesread;
  
  synchronized (lock) {
  while ((nbytesread = din.read(data, 0, data.length)) != -1) {
   while (paused) {
   if(line.isrunning()) {
    line.stop();
    system.out.println("暂停");
   }
   try {
    lock.wait();
    system.out.println("等待");
   }
   catch(interruptedexception e) {
   }
   }
   if(!line.isrunning()&&!over) {
   system.out.println("开始播放");
   line.start();
   
   }
   
   if (over&&line.isrunning()) {
   system.out.println("停止播放");
   jsliderplayprogress.setvalue(0);
   isnext=false;
   line.drain();
   line.stop();
   line.close();
   }
   
   jsliderplayprogress.setvalue((int)line.getmicrosecondposition());
   line.write(data, 0, nbytesread);
  }
  
 //根据播放模式选择下一首歌
  nextmusic();
  }
  
 }
 
 }
 catch(exception e) {
  e.printstacktrace();
 }
 finally {
  if(din != null) {
  try { din.close(); } catch(ioexception e) { }
  }
 }
 }
 
 //设置播放器滚动条
 public void setvolume()
 {
 if(line!=null)
 {
  if(line.iscontrolsupported(floatcontrol.type.master_gain))
  {
  jslidervolume.setenabled(true);
  volume= (floatcontrol)line.getcontrol( floatcontrol.type.master_gain );
  jslidervolume.setminimum((int)volume.getminimum());
  jslidervolume.setmaximum((int)volume.getmaximum());
  //jslidervolume.setvalue((int)(volume.getminimum()+(4*(volume.getmaximum()-volume.getminimum()))/5));
  volume.setvalue((float)(volume.getminimum()+(4*(volume.getmaximum()-volume.getminimum()))/5));
  }
 }
 else
 {
  volume=null;
  jslidervolume.setenabled(false);
 } 
 }
 private void nextmusic() {
 string mode=setting.getmode();
 if (isnext&&!mode.equals("one")) {//单曲播放就不执行
  int nextid=0;//将要播放的id
  int currentid=integer.parseint(this.music.getid());
  system.out.println(mode);
  if (mode.equals("default")&&(currentid==musiclist.getlist().size()-1)){
  return;
  }
  
  if (mode.equals("rand")) {
   random random = new random();
   nextid=math.abs(random.nextint())%musiclist.getlist().size();
  }else if (mode.equals("onecircle")) {
  nextid=currentid;
  }else if (mode.equals("default")&&!(currentid==musiclist.getlist().size()-1)) {
   nextid=currentid+1;
  }else if (mode.equals("morecircle")) {
  
  nextid=(currentid==musiclist.getlist().size()-1)?0:currentid+1;
  }
  jtable jtable=viewlist.getlist().get(0).getjt();
  if(nextid==0){//第一个
  
  jtable.setrowselectioninterval(0,0);
  
  }else {
   jtable.setrowselectioninterval(nextid-1,nextid); 
  }
   this.stopplay();
   threadlist.getlist().clear();
   p=new player(jslidervolume,jsliderplayprogress);
   p.setmusic(musiclist.getlist().get(nextid));
   threadlist.getlist().add(p);
   p.start();
 }
 }
 


 //开始
 public void startplay(){
 over=false;
 }
 
 
 //停止
 
 public void stopplay(){
 over=true;
 }
 
 
 // 暂停
 public void userpressedpause() {
 paused = true;
 }
 
 //继续
 public void userpressedplay() {
  synchronized(lock) {
   paused = false;
   lock.notifyall();
 }

 }
 
 public void pause(){
 if (paused) {
  synchronized(lock) {
   paused = false;
   lock.notifyall();
   }
 }else{
  paused = true;
 }
 
 }
 

 
 
}

这个主要是播放音乐的类,播放,暂停,停止,上一首,下一首都有了 

 view.java

package com.view;

import java.awt.borderlayout;
import java.awt.color;
import java.awt.component;
import java.awt.container;
import java.awt.dimension;
import java.awt.gridlayout;
import java.awt.image;
import java.awt.event.actionevent;
import java.awt.event.actionlistener;
import java.awt.event.mouseevent;
import java.awt.event.mouselistener;
import java.awt.event.windowevent;
import java.awt.event.windowlistener;
import java.io.file;
import java.io.ioexception;
import java.net.uri;
import java.net.url;
import java.util.arraylist;

import javax.swing.imageicon;
import javax.swing.jbutton;
import javax.swing.jcombobox;
import javax.swing.jcomponent;
import javax.swing.jframe;
import javax.swing.jlabel;
import javax.swing.jmenu;
import javax.swing.jmenubar;
import javax.swing.jmenuitem;
import javax.swing.joptionpane;
import javax.swing.jpanel;
import javax.swing.jrootpane;
import javax.swing.jscrollpane;
import javax.swing.jslider;
import javax.swing.jtable;
import javax.swing.listselectionmodel;
import javax.swing.scrollpaneconstants;
import javax.swing.swingconstants;
import javax.swing.event.changeevent;
import javax.swing.event.changelistener;
import javax.swing.table.tablecellrenderer;



import com.list.musiclist;
import com.list.threadlist;
import com.list.viewlist;
import com.model.model;
import com.model.music;
import com.service.player;
import com.service.setting;
import com.util.dirinput;
import com.util.fileinput;
import com.util.filelist;
import com.util.list_file;


public class view extends jframe implements mouselistener,actionlistener,windowlistener {
 
 private jbutton stop, open,del,next,pre;
 private player p;
 private jpanel[] jpanels;
 private musiclist list;
 //private long clicktime=0l;
 private jscrollpane jsp;
 private jtable jt;
 private jrootpane j;
 private model model;
 private jslider jslidervolume;
 private jslider jsliderplayprogress;
 private fileinput fileinput;
 private dirinput dirinput;
 private jmenubar jb;
 private jmenu jm;
 private jmenuitem fm,dm;
 private jcombobox jbox;
 
 
 public view(){
 system.out.println(viewlist.getlist().size());
 if (viewlist.getlist().size()==0) {
  open();
 }
 }

 
 
 private void open() {
 
 //this.getrootpane().setwindowdecorationstyle(jrootpane.none);
 
 
 //this.setundecorated(true);
 //菜单选项
 
 jb=new jmenubar();
 jm=new jmenu("打开");
 
 fm=new jmenuitem("文件");
 
 dm=new jmenuitem("文件夹");
 
 fm.addactionlistener(this);
 dm.addactionlistener(this);
 jb.add(jm);
 
 jm.add(fm);
 jm.add(dm);
 
 
 
 //this.setjmenubar(jb);
 
 
 
 jpanel p1=new jpanel();
 jpanel p2=new jpanel();
 jpanel p3=new jpanel();
 
 //增加菜单选项
 j=new jrootpane();
 
 j.setjmenubar(jb);
 
 
 p2.add(j);
 
 
  open=new jbutton("播放");
  stop=new jbutton("停止");
  open.addmouselistener(this);
  stop.addmouselistener(this);
  pre=new jbutton("上一首");
  next=new jbutton("下一首");
  pre.addmouselistener(this);
  next.addmouselistener(this);
 p1.setlayout(new gridlayout(2,1));
 
 jpanel jpanel2=new jpanel();
 
 jpanel2.add(open);
 jpanel2.add(stop);
 jpanel2.add(pre);
 jpanel2.add(next);
 
 p1.add(jpanel2);
 /*p1.add(open);
 p1.add(stop);
 p1.add(pre);
 p1.add(next);*/
 
 
 
 
 
 del=new jbutton("删除");
 del.addmouselistener(this);
 
  jsliderplayprogress = new jslider(); //播放进度条
  jsliderplayprogress.setvalue(0);
  jsliderplayprogress.setenabled(false);
  jsliderplayprogress.setpreferredsize(new dimension(200, 20));
  
  
  p1.add(jsliderplayprogress);
  
 
 jslidervolume = new jslider(); //音量进度条
 jslidervolume.setvalue(0);
  //jsliderplayprogress.setenabled(false);
 jslidervolume.setpreferredsize(new dimension(100, 20));//设置滚动条长度
  
  
  
 jslidervolume.addchangelistener(new changelistener()
  {
  public void statechanged(changeevent evt) 
  {
   system.out.println(jslidervolume.getvalue());
   if (threadlist.getlist().size()!=0) {
   threadlist.getlist().get(0).getvolume().setvalue((float)jslidervolume.getvalue());
   }
   
   
  }
  });
 string[] v={"顺序播放","随机播放","单曲循环","列表循环","单曲播放"};
 
 jbox=new jcombobox(v);
 
 jbox.addactionlistener(this);
  
 p2.add(jbox); 
 p2.add(del);
 
 
  p2.add(jslidervolume);
 
 jpanels=new jpanel[list.getlist().size()];
 
 for (int i = 0; i < list.getlist().size(); i++) {
  
  music music=list.getlist().get(i);
  
  jpanel jpanel=new myjpanel(music);
  
  
  jlabel jlabel=new jlabel(music.getname(),swingconstants.center);
  jlabel.setsize(300, 10);
  jlabel.sethorizontaltextposition(jlabel.center);
  
  jpanel.setbackground(color.white);
  
  jpanels[i]=jpanel;
  
  jpanel.addmouselistener(this);
  
  jpanel.add(jlabel);
  
  
  
  p3.add(jpanel);
  
  
 }
 
 
 p3.setbackground(color.white);
 
 p3.setlayout(new gridlayout(10, 1));
 
 p3.setsize(320, 500);
 
 
 this.add(p1,borderlayout.north);
 this.add(p2,borderlayout.south);
 
 
  
  
 
 
 model=new model();  //添加表
 
 jt=new jtable(model){ // 设置jtable的单元格为透明的
  public component preparerenderer(tablecellrenderer renderer,
    int row, int column) {
   component c = super.preparerenderer(renderer, row, column);
   if (c instanceof jcomponent) {
    ((jcomponent) c).setopaque(false);
   }
   return c;
   }
   };;
   
 jt.setopaque(false);
 
 jt.setrowheight(30);
 jt.setselectionmode(listselectionmodel.single_selection );
 jt.setshowhorizontallines(false);
 jt.setselectionbackground(new color(189,215,238));
 jt.addmouselistener(this);
 
 jsp = new jscrollpane(jt);
 
 jsp.setopaque(false);
 jsp.getviewport().setopaque(false);
 
 
 //addmusic();
 
 //this.add(p3,borderlayout.center);
 
 this.add(jsp,borderlayout.center);
 
 
 this.setdefaultcloseoperation(exit_on_close);
 
 this.addwindowlistener(this);
 
 image image=this.gettoolkit().getimage("img/icon.jpg");
 
 this.seticonimage(image);
 
 this.settitle("音乐播放器");
 
  imageicon icon = new imageicon("img/bg.jpg"); 
  jlabel lab = new jlabel(icon); // 将图片放入到label中
  lab.setbounds(0, 0, icon.geticonwidth(), icon.geticonheight()); // 设置放有图片的label的位置
  
  this.getcontentpane().add(lab, -1); // jthis本身是窗体,不能放置任何组件,用getcontentpane()方法得到this的默认内容面板,将lab放入其中,-1表示放入面板的下层
  this.getcontentpane().add(jsp, 0); // 0表示放在面板的最顶层
  container con = this.getcontentpane();
  ((jpanel)con).setopaque(false); // 设置面板为透明的
  p2.setopaque(false);
  jslidervolume.setopaque(false);
  jpanel2.setopaque(false);
  p1.setopaque(false);
  p3.setopaque(false);
  jsliderplayprogress.setopaque(false);
 this.setlocation(400, 200);
 this.setsize(337, 525);
 this.setresizable(false);
 this.setvisible(true);
 }
 
 @override
 public void mouseclicked(mouseevent e) {
 
 system.out.println("开始播放");
 
 if (e.getsource()==open) {
  
  if (p==null) {//开始
  p=new player(jslidervolume,jsliderplayprogress);
  p.setmusic(musiclist.getlist().get(0));
  jt.setrowselectioninterval(0,0);
  threadlist.add(p);
  open.settext("暂停");
  p.start();
  }else{//继续
  if (threadlist.getlist().size()!=0) {
   p=threadlist.getlist().get(0);
  }
  
  string s=p.ispaused()?"暂停":"播放";
  open.settext(s);
  p.pause();
  }
  
 }else if (e.getsource()==stop) {
  if (threadlist.getlist().size()!=0) {
  p=threadlist.getlist().get(0);
  }
  if (p!=null) {
  p.stopplay();
  p=null;
  open.settext("播放");
  }
 
  
 }else if (e.getsource()==pre) {//上一首
  premusic();

 }else if (e.getsource()==next) {//下一首
  nextmusic();
 }else if (e.getsource()==del) {
  
  delmusic();
   
 }else if (e.getsource()==jt&&e.getclickcount()==2) {//双击
  
  clickmusic();
  
  
  
 }

 
 }

 private void clickmusic() {
 //双击jtable
 system.out.println("点击了");
 
 int rownum = this.jt.getselectedrow();
 system.out.println(rownum);
 if(rownum == -1) {
  joptionpane.showmessagedialog(this, "你没有选择一项");
  return;
 }
 arraylist<player> list=threadlist.getlist();
 
 
 system.out.println(list.size()+"音乐文件数目");
 
  if (list.size()==0) {
  
  p=new player(jslidervolume,jsliderplayprogress);
  p.setmusic(musiclist.getlist().get(rownum));
  threadlist.add(p);
  open.settext("暂停");
  p.start();
 }else{
  system.out.println("停止");
 list.get(0).stopplay();
 list.clear();
 p=new player(jslidervolume,jsliderplayprogress);
  p.setmusic(musiclist.getlist().get(rownum));
  open.settext("暂停");
  list.add(p);
  p.start();
 }
 }

 private void delmusic() {
 int rownum = this.jt.getselectedrow();
 
 
 musiclist.getlist().remove(rownum);
 
 system.out.println(musiclist.getlist().size());
 
 jt.setmodel(new model());

 
  arraylist<player> list=threadlist.getlist();
  p=new player(jslidervolume,jsliderplayprogress);
  system.out.println(list.size()+"大小");
  if (list.size()!=0) {
  list.get(0).stopplay();
  list.clear();
  open.settext("暂停");
  if(rownum==0){//第一个
   system.out.println("第一个");
    jt.setrowselectioninterval(0,0);
    p.setmusic(musiclist.getlist().get(rownum));
    
    
  }else if(rownum==musiclist.getlist().size()){//最后一个
   system.out.println("最后一个");
    
    jt.setrowselectioninterval(rownum-2,rownum-1);
    p.setmusic(musiclist.getlist().get(rownum-1));
    
  }else {
   system.out.println("中间");
   
    jt.setrowselectioninterval(rownum-1,rownum);
   p.setmusic(musiclist.getlist().get(rownum));
    
  }
   list.add(p);
   p.start();
  }
 }

 public jtable getjt() {
 return jt;
 }

 private void premusic() {
 system.out.println("上一首");
 
 arraylist<player> list=threadlist.getlist();
 
 int id=integer.parseint(list.get(0).getmusic().getid());
 
 if(id!=0){
 if (id==1) {
  jt.setrowselectioninterval(0,0);
 }else{
  jt.setrowselectioninterval(id-2,id-1);
 }
 system.out.println(id);
 
 list.get(0).stopplay();
 list.clear();
 
  p=new player(jslidervolume,jsliderplayprogress);

  p.setmusic(musiclist.getlist().get(id-1));
  system.out.println(id-1);
  
  open.settext("暂停");
  list.add(p);
  p.start();
 }
 }

 private void nextmusic() {
 system.out.println("下一首");
 arraylist<player> list=threadlist.getlist();
 int id=integer.parseint(list.get(0).getmusic().getid());
 
 system.out.println(id);
 if(id!=musiclist.getlist().size()-1){ //122
  
 jt.setrowselectioninterval(id,id+1); //123条
 
 list.get(0).stopplay();
 list.clear();
 
 p=new player(jslidervolume,jsliderplayprogress);
 
  p.setmusic(musiclist.getlist().get(id+1));
  system.out.println(id+1);
  
  open.settext("暂停");
  list.add(p);
  p.start();
}
 }
 //判断双击
/* private boolean checkclicktime() {
 long nowtime = (new date()).gettime();
 if ((nowtime - clicktime) < 300) {
 clicktime = nowtime;
 return true;
 }
 clicktime = nowtime;
 return false;
 }*/
 
 private void addmusic(string path) {//增加mp3文件夹
 
 system.out.println("增加mp3文件夹");
 arraylist<music> musiclist=musiclist.getlist();
  
  list_file fm = new list_file();
  arraylist<string[]> filelist = fm.serachfiles(path);
  
  for (int i = 0; i < filelist.size(); i++) {
  music music= new music();
   music.setid(musiclist.size()+"");
   string[] s=(string[]) filelist.get(i);
   
   music.setname(s[0]);
   music.setpath(s[1]);
  musiclist.add(music);
  }
  
  jt.setmodel(new model());
 
 }

 @override
 public void mouseentered(mouseevent e) {
 // todo auto-generated method stub
 
 }

 @override
 public void mouseexited(mouseevent e) {
 // todo auto-generated method stub
 
 }

 @override
 public void mousepressed(mouseevent e) {
 // todo auto-generated method stub
 
 }

 @override
 public void mousereleased(mouseevent e) {
 // todo auto-generated method stub
 
 }



 @override
 public void actionperformed(actionevent e) {
 if (e.getsource()==fm) {//添加mp3文件
 if(fileinput==null) fileinput = new fileinput(this);
  fileinput.open();
  file[] s=fileinput.getfiles();
  arraylist<music> musiclist=musiclist.getlist();
  
  
  if(s!=null){
  for(int i=0;i<s.length;i++){
  music music= new music();
  music.setid(musiclist.size()+"");
  music.setname(s[i].getname());
  music.setpath(s[i].getabsolutepath());
  musiclist.add(music);
  jt.setmodel(new model());
  }
  }
 }else if (e.getsource()==dm) {
  
  
  if(dirinput==null) dirinput = new dirinput(this);
  
  dirinput.open();
  
  file s=dirinput.getfile();
  
  
  if(s!=null){
   
   addmusic(s.getabsolutepath());
  }
  
  
  
 }else if (e.getsource()==jbox) {
  //顺序播放 (默认)default 随机rand 单曲循环 onecircle 列表循环 morecircle 单曲播放 one 
  
 
 if (threadlist.getlist().size()!=0) {
 p=threadlist.getlist().get(0);
 }else {
  p=new player(jslidervolume,jsliderplayprogress);
  threadlist.getlist().add(p);
 }
 
 string[] s={"default","rand","onecircle","morecircle","one"};
 
 setting.setmode(s[jbox.getselectedindex()]);
 
 
 }
 }



 @override
 public void windowactivated(windowevent e) {
 // todo auto-generated method stub
 
 }



 @override
 public void windowclosed(windowevent e) {
 // todo auto-generated method stub
 system.out.println("关闭kk");
 }



 @override
 public void windowclosing(windowevent e) {
 // todo auto-generated method stub
 system.out.println("close");
 
 if (musiclist.getlist().size()!=0) {
  system.out.println("写入文件");
  //清空之前的内容
  filelist.clear("file/musiclist.txt");
  arraylist<music> list=musiclist.getlist();
  for (int i = 0; i < list.size(); i++) {
  filelist.writefile("file/musiclist.txt",list.get(i).getid()+","+list.get(i).getname()+","
   +list.get(i).getpath()+"\n");
  }
  
 }
 
 
 
 
 
 }



 @override
 public void windowdeactivated(windowevent e) {
 // todo auto-generated method stub
 
 }



 @override
 public void windowdeiconified(windowevent e) {
 // todo auto-generated method stub
 
 }



 @override
 public void windowiconified(windowevent e) {
 // todo auto-generated method stub
 
 }



 @override
 public void windowopened(windowevent e) {
 // todo auto-generated method stub
 system.out.println("open");
 
 file file=new file("file/musiclist.txt");
 
 if (file.exists()==false) {
  try {
  file.createnewfile();
  } catch (ioexception e1) {
  // todo auto-generated catch block
  e1.printstacktrace();
  }
 }else {


  filelist.readfilebylines("file/musiclist.txt");
  jt.setmodel(new model());
 }
 
 
 
 }

}

剩下的代码在后面附件上有,现在主要是有几个小问题,第一,我还没有找到获取音乐文件具体信息比较好的办法,所以每一首暂时还没有歌手,作曲的信息,第二界面有点难看,见谅了,第三个是打包成jar文件会有路径问题,暂时还没办法解决,我是直接在myeclipse上运行,一切正常,就是打包有点小问题

暂时先说这些了,这个是我业余时间的项目,有什么不足的,大家都可以提出来。

下载地址:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网