实验主题
本次课程设计计划实现一个低配版的仿网易云音乐的音乐播放器,主要实现功能如下:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25dp"
android:text="用户名:"
android:textColor="#000000"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_goneMarginLeft="20dp" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20dp"
android:id="@+id/name"
android:hint="请输入用户名">
</EditText>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密码:"
android:textSize="25dp"
android:textColor="#000000"
android:layout_marginTop="10dp" />
<com.example.musicplayer.Showpwd
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20dp"
android:id="@+id/pwd"
android:hint="请输入密码">
</com.example.musicplayer.Showpwd>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight="1">
<Button
android:id="@+id/register"
android:layout_marginTop="20dp"
android:layout_marginLeft="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="注册"
android:textSize="20dp"
android:background="#FFFFFF"/>
<Button
android:id="@+id/login"
android:layout_marginTop="20dp"
android:layout_marginLeft="100dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="已有账号,去登录"
android:textSize="20dp"
android:background="#FFFFFF"/>
</LinearLayout>
</LinearLayout>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init(){
mContext = getApplicationContext();
sh = new Sharehelp(mContext);
//创建表
dh=new Databasehelp(mContext,"mydb.db",null,1);
db=dh.getWritableDatabase();
final ContentValues values=new ContentValues();
name=(EditText)findViewById(R.id.name);
pwd=(Showpwd)findViewById(R.id.pwd);
register=(Button)findViewById(R.id.register);
login=(Button)findViewById(R.id.login);
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
已有账号跳转至登录界面
Intent intent=new Intent(MainActivity.this,Login.class);
startActivity(intent);
}
});
register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
进行注册
uname=String.valueOf(name.getText());
upwd=String.valueOf(pwd.getText());
values.put("name",uname);
values.put("pwd",upwd);
sh.save(uname,upwd);
用户名和密码不能为空
if(uname.equals("")||upwd.equals("")){
Toast.makeText(MainActivity.this, "信息不全,请补充", Toast.LENGTH_SHORT).show();
}
else{
信息存入数据库
db.insert("mydb",null,values);
values.clear();
Toast.makeText(MainActivity.this, "保存成功", Toast.LENGTH_SHORT).show();
name.setText("");//保存成功清空信息
pwd.setText("");
//跳转至登录页面
Intent intent=new Intent(MainActivity.this,Login.class);
startActivity(intent);
}
}
});
}
public static final String CREATE_LIST="create table mydb("
+"id integer primary key autoincrement,"
+"name text,"
+"pwd text)";
Showpwd:
实现密码的隐藏与显示:
private void init() {
cl = mContext.getResources().getDrawable(R.drawable.close);//眼睛关闭图片
op=mContext.getResources().getDrawable(R.drawable.open);//眼睛打开图片
setInputType(129);
setCompoundDrawablesWithIntrinsicBounds(null, null, cl, null);
addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable editable) {
setDrawable();
}
});
}
private void setDrawable(){
if (length() < 1)
setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
else
setCompoundDrawablesWithIntrinsicBounds(null, null, cl, null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(cl != null && event.getAction() == MotionEvent.ACTION_UP)
{
int eventX = (int) event.getRawX();
int eventY = (int) event.getRawY();
Rect rect = new Rect();
getGlobalVisibleRect(rect);
rect.left = rect.right - 100;
if (rect.contains(eventX, eventY)) {
if(flag==0){
setInputType(128);
setCompoundDrawablesWithIntrinsicBounds(null, null, op, null);
flag=1;
}else{
setInputType(129);
setCompoundDrawablesWithIntrinsicBounds(null, null, cl, null);
flag=0;
}
}
}
return super.onTouchEvent(event);
}
}
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25dp"
android:text="用户名:"
android:textColor="#000000"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_goneMarginLeft="20dp" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20dp"
android:id="@+id/name"
android:hint="请输入用户名">
</EditText>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密码:"
android:textSize="25dp"
android:textColor="#000000"
android:layout_marginTop="10dp" />
<com.example.musicplayer.Showpwd
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20dp"
android:id="@+id/pwd"
android:hint="请输入密码">
</com.example.musicplayer.Showpwd>
<Button
android:id="@+id/login"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录"
android:textSize="20dp"
android:background="#FFFFFF"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="
android:textSize="25dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/menu1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="本地歌曲"
android:textSize="25dp"/>
<TextView
android:id="@+id/menu2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="在线音乐"
android:textSize="25dp"/>
</LinearLayout>
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="9">
</FrameLayout>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
content=(FrameLayout)findViewById(R.id.content);
tv1=(TextView)findViewById(R.id.menu1);
tv2=(TextView)findViewById(R.id.menu2);
tv1.setOnClickListener(this);
tv2.setOnClickListener(this);
fm=getSupportFragmentManager();//若是继承FragmentActivity,fm=getFragmentManger();
ft=fm.beginTransaction();
ft.replace(R.id.content,new Play1());//默认情况下Fragment1
ft.commit();
}
@Override
public void onClick(View v){
ft=fm.beginTransaction();
switch (v.getId()){
case R.id.menu1:
ft.replace(R.id.content,new Play1());
break;
case R.id.menu2:
ft.replace(R.id.content,new Play2());
break;
default:
break;
}
ft.commit();
}
private View view;
//本地歌曲歌名及歌手
public String[] name={"告五人——爱人错过","告五人——你要不要吃哈密瓜","告五人——温蒂公主的侍卫"};
//歌曲图片读取
public static int[] icons={R.drawable.music0,R.drawable.music1,R.drawable.music2};
@Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
//将上图布局加载进来
view=inflater.inflate(R.layout.music_list,null);
ListView listView=view.findViewById(R.id.lv);
MyBaseAdapter adapter=new MyBaseAdapter();
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent=new Intent(Play1.this.getContext(),Music_Activity.class);//创建Intent对象,启动check
//将数据存入Intent对象
intent.putExtra("name",name[position]);
intent.putExtra("position",String.valueOf(position));
startActivity(intent);
}
});
return view;
}
class MyBaseAdapter extends BaseAdapter {//数据显示到list view中
@Override
public int getCount(){return name.length;}
@Override
public Object getItem(int i){return name[i];}
@Override
public long getItemId(int i){return i;}
@Override
public View getView(int i ,View convertView, ViewGroup parent) {
View view=View.inflate(Play1.this.getContext(),R.layout.item_list,null);
TextView tv_name=view.findViewById(R.id.item_name);
ImageView iv=view.findViewById(R.id.iv);
tv_name.setText(name[i]);
iv.setImageResource(icons[i]);
return view;
}
}
//为进度条添加事件监听
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//进度条改变时,会调用此方法
if (progress==seekBar.getMax()){//当进度条到末端时,结束动画
animator.pause();//停止播放动画
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {//进度条开始滑动时调用
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {//进度条停止滑动时调用
//根据拖动的进度改变音乐播放进度
int progress=seekBar.getProgress();//获取seekBar的进度
musicControl.seekTo(progress);//改变播放进度
}
});
public static Handler handler=new Handler(){
@Override
public void handleMessage(Message msg){
Bundle bundle=msg.getData();//获取从子线程发送过来的音乐播放进度
int duration=bundle.getInt("duration");
int currentPosition=bundle.getInt("currentPosition");
sb.setMax(duration);
sb.setProgress(currentPosition);
//歌曲总时长
int minute=duration/1000/60;
int second=duration/1000%60;
String strMinute=null;
String strSecond=null;
if(minute<10){//如果歌曲的时间中的分钟小于10
strMinute="0"+minute;//在分钟的前面加一个0
}else{
strMinute=minute+"";
}
if (second<10){//如果歌曲中的秒钟小于10
strSecond="0"+second;//在秒钟前面加一个0
}else{
strSecond=second+"";
}
tv_total.setText(strMinute+":"+strSecond);
//歌曲当前播放时长
minute=currentPosition/1000/60;
second=currentPosition/1000%60;
if(minute<10){//如果歌曲的时间中的分钟小于10
strMinute="0"+minute;//在分钟的前面加一个0
}else{
strMinute=minute+" ";
}
if (second<10){//如果歌曲中的秒钟小于10
strSecond="0"+second;//在秒钟前面加一个0
}else{
strSecond=second+" ";
}
tv_progress.setText(strMinute+":"+strSecond);
}
};
上一首,下一首歌曲切换
private void preplay(){
String position= intent1.getStringExtra("position");
int i=parseInt(position);
if(i==0)
i=2;
else
i=(i-1)%3;
musicControl.play(i);
ImageView iv_music=(ImageView)findViewById(R.id.iv_music);
iv_music.setImageResource(Play1.icons[i]);
name_song=(TextView)findViewById(R.id.song_name);
name_song.setText(names[i]);
//animator.start();
}
private void nxtplay(){
String position= intent1.getStringExtra("position");
int i=parseInt(position);
i=(i+1)%3;
musicControl.play(i);
ImageView iv_music=(ImageView)findViewById(R.id.iv_music);
iv_music.setImageResource(Play1.icons[i]);
name_song=(TextView)findViewById(R.id.song_name);
name_song.setText(names[i]);
// animator.start();
}
各个button功能实现:
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_play://播放
String position=intent1.getStringExtra("position");
int i=parseInt(position);
musicControl.play(i);
animator.start();
break;
case R.id.btn_pause://暂停
musicControl.pausePlay();
animator.pause();
break;
case R.id.btn_continue_play://继续播放
musicControl.continuePlay();
animator.start();
break;
case R.id.btn_exit://退出
unbind(isUnbind);
isUnbind=true;
finish();
break;
case R.id.btn_pre://上一首
preplay();
break;
case R.id.btn_nxt://下一首
nxtplay();
break;
}
}
Musicservice:
进度条方法:
public void addTimer(){ //添加计时器用于设置音乐播放器中的播放进度条
if(timer==null){
timer=new Timer();//创建计时器对象
TimerTask task=new TimerTask() {
@Override
public void run() {
if (player==null) return;
int duration=player.getDuration();//获取歌曲总时长
int currentPosition=player.getCurrentPosition();//获取播放进度
Message msg=Music_Activity.handler.obtainMessage();//创建消息对象
//将音乐的总时长和播放进度封装至消息对象中
Bundle bundle=new Bundle();
bundle.putInt("duration",duration);
bundle.putInt("currentPosition",currentPosition);
msg.setData(bundle);
//将消息发送到主线程的消息队列
Music_Activity.handler.sendMessage(msg);
}
};
//开始计时任务后的5毫秒,第一次执行task任务,以后每500毫秒执行一次
timer.schedule(task,5,500);
}
}
设置播放器:
class MusicControl extends Binder {//Binder是一种跨进程的通信方式
public void play(int i){//String path
Uri url=Uri.parse("android.resource://"+getPackageName()+"/raw/"+"music"+i);
try{
player.reset();//重置音乐播放器
//加载多媒体文件
player=MediaPlayer.create(getApplicationContext(),url);
player.start();//播放音乐
addTimer();//添加计时器
}catch(Exception e){
e.printStackTrace();
}
}
public void pausePlay(){
if(player.isPlaying()){
player.pause();//暂停播放音乐
}
}
public void continuePlay(){
player.start();//继续播放音乐
}
public void seekTo(int progress){
player.seekTo(progress);//设置音乐的播放位置
}
}
public class Play2 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_play2, null);
Button btn=view.findViewById(R.id.wyy);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri = Uri.parse("https://music.163.com");//要跳转的网址
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});
return view;
}
}