1. 说明

本音乐播放器基于Android开发,原为我和另外两个小伙伴在上学期间一起做的一个小项目,近来有时间整理一下。之前我有文章已经介绍了播放界面的功能实现(Android音乐播放器开发),但介绍的比较粗糙,接下来会做更细致化的整理。源码已同步到Gitee仓库,GitHub仓库,觉得还不错的话帮忙点个“star”吧,非常感谢。

当初代码写的很随意,目的只为实现功能。现在更倾向于代码可读性和简洁性,因此会在原来的程序基础上做一些小修改。也有可能不会一步到位,计划慢慢修改,以增强自己的理解。

服务端使用的是比较传统的servlet和jdbc传递数据,整理完之后,新版本会修改为SSM框架,更加简洁高效。安卓端使用的也都是基础的工具,比如音乐播放功能的实现也是借助于入门级的MediaPlayer类,目前关于安卓端没有什么更改的想法。

服务端:Android音乐播放器开发–服务端

登录:Android音乐播放器开发–登录

(适用于平时做个小课设的小伙伴们)

2. 注册界面设计

在写登录功能时,注册按钮的点击事件是启动本界面。

分析一下需求:

相对于登录界面,注册界面并没有很大的区别,直接贴全部的代码了(activity_register.xml

<?xml version="1.0" encoding="utf-8"?>
<!--注册界面-->
<!--这里的布局放置是: 1 个 ImageView 控件,用于显示用户头像;3 个 EditText 控件,用于输入用户名、密码、再次输入密码;1 个 Button 控件为注册按钮-->
<!--修改 activity_register.xml 为 LinearLayout 布局-->
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/activity_register"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/c"android:orientation="vertical"><include layout="@layout/main_title_bar"></include><!--引入标题栏--><ImageViewandroid:layout_width="70dp"android:layout_height="70dp"android:layout_gravity="center_horizontal"android:layout_marginTop="25dp"android:src="@drawable/x"/><!--三个编辑框--><EditTextandroid:id="@+id/et_user_name"android:layout_width="fill_parent"android:layout_height="48dp"android:layout_gravity="center_horizontal"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:layout_marginTop="35dp"android:background="@drawable/register_user_name_bg"android:drawableLeft="@drawable/user_name_icon"android:drawablePadding="10dp"android:gravity="center_vertical"android:hint="请输入用户名"android:paddingLeft="8dp"android:singleLine="true"android:textColor="#000000"android:textColorHint="#a3a3a3"android:textSize="14sp"/><EditTextandroid:id="@+id/et_psw"android:layout_width="fill_parent"android:layout_gravity="center_horizontal"android:layout_height="48dp"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:background="@drawable/register_psw_bg"android:drawableLeft="@drawable/psw_icon"android:drawablePadding="10dp"android:hint="请输入密码"android:inputType="textPassword"android:paddingLeft="8dp"android:singleLine="true"android:textColor="#000000"android:textColorHint="#a3a3a3"android:textSize="14sp"/><EditTextandroid:id="@+id/et_psw_again"android:layout_width="fill_parent"android:layout_height="48dp"android:layout_gravity="center_horizontal"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:background="@drawable/register_psw_again_bg"android:drawableLeft="@drawable/psw_icon"android:drawablePadding="10dp"android:hint="请再次输入密码"android:inputType="textPassword"android:paddingLeft="8dp"android:singleLine="true"android:textColor="#000000"android:textColorHint="#a3a3a3"android:textSize="14sp"/><Buttonandroid:id="@+id/btn_register"android:layout_width="fill_parent"android:layout_height="40dp"android:layout_gravity="center_horizontal"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:layout_marginTop="15dp"android:background="@drawable/register_selector"android:text="注 册"android:textColor="@android:color/white"android:textSize="18sp"/>
</LinearLayout>

这里使用了与登录实现的同一个标题(main_title_bar.xml

3. 注册功能实现

先贴全部代码

package cn.sjcup.musicplayer;import androidx.appcompat.app.AppCompatActivity;import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;import org.json.JSONObject;import cn.sjcup.musicplayer.servlet.RequestServlet;public class RegisterActivity extends Activity {private TextView mTitle;    //标题private TextView mBack;     //返回按钮private Button mRegister;     //注册按钮private EditText mName, mPwd, mPwdAgain;     //用户名,密码,再次输入的密码控件private String userName, pwd, pwdAgain;    //用户名,密码,再次输入的密码的控件的值private JSONObject registerInfo;  //注册返回信息@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_register);initView();   //初始化界面initEvent();  //初始化事件}private void initView(){mTitle = this.findViewById(R.id.tv_main_title);mBack = this.findViewById(R.id.tv_back);mRegister = this.findViewById(R.id.btn_register);mName = this.findViewById(R.id.et_user_name);mPwd = this.findViewById(R.id.et_psw);mPwdAgain = this.findViewById(R.id.et_psw_again);mTitle.setText("注册");}private void initEvent(){//返回按钮mBack.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {RegisterActivity.this.finish();}});//注册按钮mRegister.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//获取输入框中的值userName = mName.getText().toString().trim();pwd = mPwd.getText().toString().trim();pwdAgain = mPwdAgain.getText().toString().trim();//先判断输入框是否有值if (TextUtils.isEmpty(userName)) {Toast.makeText(RegisterActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show();return;} else if (TextUtils.isEmpty(pwd)) {Toast.makeText(RegisterActivity.this, "请输入密码", Toast.LENGTH_SHORT).show();return;} else if (TextUtils.isEmpty(pwdAgain)) {Toast.makeText(RegisterActivity.this, "请再次输入密码", Toast.LENGTH_SHORT).show();return;}//判断两次输入的密码是否相同if (!pwd.equals(pwdAgain)) {Toast.makeText(RegisterActivity.this, "输入两次的密码不一样", Toast.LENGTH_SHORT).show();return;}isExistThread(userName, pwd);   //先检测用户名是否已经存在}});}private void isExistThread(final String account, final String password){new Thread(){public void run(){try {JSONObject result = RequestServlet.login(account, password);Message msg = new Message();msg.what=2;msg.obj = result;handler2.sendMessage(msg);}catch (Exception e){e.printStackTrace();}}}.start();}private Handler handler2 = new Handler() {public void handleMessage(android.os.Message msg) {if (msg.what == 2) {JSONObject result = (JSONObject) msg.obj;if(result == null || !result.optString("account").equals(userName)){//账户名未被注册registerThread(userName, pwd);    //注册新账户}else{//账户名已被注册Toast.makeText(RegisterActivity.this, "用户名已被占用!", Toast.LENGTH_SHORT).show();}}}};private void registerThread(final String account, final String password){new Thread(){public void run(){try {JSONObject result = RequestServlet.Register(account, password);Message msg = new Message();msg.what=1;msg.obj = result;handler.sendMessage(msg);}catch (Exception e){e.printStackTrace();}}}.start();}private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {if (msg.what == 1) {registerInfo = (JSONObject) msg.obj;String result = registerInfo.optString("result");if(result.equals("注册成功!")){Toast.makeText(RegisterActivity.this, "注册成功!", Toast.LENGTH_SHORT).show();RegisterActivity.this.finish();}else if(result.equals("注册失败!")){Toast.makeText(RegisterActivity.this, "注册失败,请重新注册", Toast.LENGTH_SHORT).show();}}}};
}

同登录一样,先声明一些必要的变量

private TextView mTitle;    //标题
private TextView mBack;     //返回按钮
private Button mRegister;     //注册按钮
private EditText mName, mPwd, mPwdAgain;     //用户名,密码,再次输入的密码控件
private String userName, pwd, pwdAgain;    //用户名,密码,再次输入的密码的控件的值
private JSONObject registerInfo;  //注册返回信息

在加载时就初始化界面和事件

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_register);initView();   //初始化界面initEvent();  //初始化事件
}

初始化界面,首先需要绑定界面中的控件,如果需要在加载界面时操作界面变化,都是在这里设置

private void initView(){mTitle = this.findViewById(R.id.tv_main_title);mBack = this.findViewById(R.id.tv_back);mRegister = this.findViewById(R.id.btn_register);mName = this.findViewById(R.id.et_user_name);mPwd = this.findViewById(R.id.et_psw);mPwdAgain = this.findViewById(R.id.et_psw_again);mTitle.setText("注册");
}

初始化事件,主要是监听各个按钮,按钮被点击是做出事件响应

private void initEvent(){//返回按钮mBack.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {RegisterActivity.this.finish();}});//注册按钮mRegister.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//获取输入框中的值userName = mName.getText().toString().trim();pwd = mPwd.getText().toString().trim();pwdAgain = mPwdAgain.getText().toString().trim();//先判断输入框是否有值if (TextUtils.isEmpty(userName)) {Toast.makeText(RegisterActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show();return;} else if (TextUtils.isEmpty(pwd)) {Toast.makeText(RegisterActivity.this, "请输入密码", Toast.LENGTH_SHORT).show();return;} else if (TextUtils.isEmpty(pwdAgain)) {Toast.makeText(RegisterActivity.this, "请再次输入密码", Toast.LENGTH_SHORT).show();return;}//判断两次输入的密码是否相同if (!pwd.equals(pwdAgain)) {Toast.makeText(RegisterActivity.this, "输入两次的密码不一样", Toast.LENGTH_SHORT).show();return;}isExistThread(userName, pwd);   //先检测用户名是否已经存在}});
}

返回按钮如果被点击,销毁当前界面,返回登录界面。注册按钮被点击,需要向数据库请求数据,因为在Android操作中,所有网络操作必须放在子线程中,所以这里单独写了一个方法。

注册时,首先判断一下输入框内是否都有值。如果都有值,判断两次输入的密码是否相同。在注册前,这里将账户名与数据库内的数据进行了比对,如果存在该用户名,不能再次进行注册。

这里的判断用户名是否已存在与前面介绍的登录在功能实现上是一样的,请求login方法,获取到用户数据。

private void isExistThread(final String account, final String password){new Thread(){public void run(){try {JSONObject result = RequestServlet.login(account, password);Message msg = new Message();msg.what=2;msg.obj = result;handler2.sendMessage(msg);}catch (Exception e){e.printStackTrace();}}}.start();
}

使用Message把信息传递到主线程,主线程在接收到数据后,对数据进行比对。

private Handler handler2 = new Handler() {public void handleMessage(android.os.Message msg) {if (msg.what == 2) {JSONObject result = (JSONObject) msg.obj;if(result == null || !result.optString("account").equals(userName)){//账户名未被注册registerThread(userName, pwd);    //注册新账户}else{//账户名已被注册Toast.makeText(RegisterActivity.this, "用户名已被占用!", Toast.LENGTH_SHORT).show();}}}
};

在判断出账户名未被注册时,启动注册线程。这里调用了RequestServlet类中的Register方法(稍后介绍)

private void registerThread(final String account, final String password){new Thread(){public void run(){try {JSONObject result = RequestServlet.Register(account, password);Message msg = new Message();msg.what=1;msg.obj = result;handler.sendMessage(msg);}catch (Exception e){e.printStackTrace();}}}.start();
}

子线程将服务端返回的数据传递到主线程上,主线程解析数据后显示是否注册成功。

private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {if (msg.what == 1) {registerInfo = (JSONObject) msg.obj;String result = registerInfo.optString("result");System.out.println(result);if(result.equals("注册成功!")){Toast.makeText(RegisterActivity.this, "注册成功!", Toast.LENGTH_SHORT).show();RegisterActivity.this.finish();}else if(result.equals("注册失败!")){Toast.makeText(RegisterActivity.this, "注册失败,请重新注册", Toast.LENGTH_SHORT).show();}}}
};

值得注意的是,服务端返回的信息是符合json规范的键值对形式的数据,因此在解析时,取出的也是result关键词对应的值。

RequestServlet

在登录时,调用了这里的login方法,注册调用Register方法,程序与登录程序并无明显区别。

private static final String REGISTER_SERVLET ="http://192.168.43.xxx:8080/musicplayer/SignUp";//注册
public static JSONObject Register(String account, String password){JSONObject result = null;String path = REGISTER_SERVLET+"?account="+account+"&password="+password;HttpURLConnection conn;try {conn = getConn(path);int code = conn.getResponseCode();    //http相应状态吗,200代表相应成功if (code == 200){InputStream stream = conn.getInputStream();String str = streamToString(stream);result = getJSON(str);conn.disconnect();}}catch (Exception e){e.printStackTrace();}return result;
}

如果使用虚拟机测试,连接servlet一般使用"http://localhost:8080"或"http://127.0.0.1:8080"。这里我使用了一个局域网做测试,需要将url修改为服务端的ip。windows系统查询本地ip的方法为:cmd–>ipconfig

login方法中,首先需要根据url获取网络连接HttpURLConnection,根据连接获取文件流,再将文件流转为string型数据,最后转为json型数据,返回用户信息。

4. 测试

测试使用真机测试。环境:Android 10

这里需要启动手机开发者模式,打开手机调试,连接Android studio 服务端启动Tomcat

测试两次密码不同

测试使用已存在的账户名再次注册

使用’qwe’注册

注册成功后,返回登录界面,并提示“注册成功!”

使用’qwe’账户登录

显示登录成功,并跳转到了音乐播放界面

服务端数据库

查看服务端的数据库,可以找到有关账户“qwe”的注册信息

5.

近来发现一些小伙伴不看开头啊。

程序已经放到两个仓库了,觉得有帮助到你的话,就请给本文点个赞,给仓库点个star吧!万分感谢!

Gitee仓库

GitHub仓库

Android音乐播放器开发(3)—注册相关推荐

  1. Android音乐播放器开发(4)—修改密码

    1. 说明 本音乐播放器基于Android开发,原为我和另外两个小伙伴在上学期间一起做的一个小项目,近来有时间整理一下.之前我有文章已经介绍了播放界面的功能实现(Android音乐播放器开发),但介绍 ...

  2. Android音乐播放器开发(6)—ListView组件创建歌曲播放列表(内含原理分析)

    1. 说明 源码已同步到Gitee仓库,GitHub仓库,觉得还不错的话帮忙点个"star"吧,非常感谢. 以往的文章 服务端:Android音乐播放器开发–服务端 登录:Andr ...

  3. Android音乐播放器开发(5)—播放界面(播放、暂停、上一首、下一首,顺序播放、随机播放、拖拽进度条…)

    1. 说明 源码已同步到Gitee仓库,Github仓库,觉得还不错的话帮忙点个"star"吧,非常感谢. Android播放器专栏其它文章: 服务端:Android音乐播放器开发 ...

  4. Android音乐播放器开发(2)—登录

    1. 说明 本音乐播放器基于Android开发,原为我和另外两个小伙伴在上学期间一起做的一个小项目,近来有时间整理一下.之前我有文章已经介绍了播放界面的功能实现(Android音乐播放器开发),但介绍 ...

  5. android 播放音乐 自定义控件,Android音乐播放器开发小记——项目简介

    项目源码: 前言 之前做的App多半是巡检,点检类的,一直想开发不同类型的APP来练习.所以选择做一款音乐播放器,基本可以涵盖android所有的基础知识,比如四大组件,自定义控件,网络请求,跨进程通 ...

  6. android音乐播放器底部,android音乐播放器开发中所遇到的bug及解决方法

    这几天在写一个android版的音乐播放器,在开发过程中遇到了一些小问题 小bug,最后经过一番调试与查找 终于发现问题所在.现在将开发中的问题与解决方法分享给大家... 一,音乐播放器的界面我采用的 ...

  7. android音乐播放器开发 SweetMusicPlayer 播放本地音乐

    代码地址:https://github.com/huweigoodboy/SweetMusicPlayer 上一篇写了加载歌曲列表,http://blog.csdn.net/huweigoodboy/ ...

  8. android音乐播放器开发 SweetMusicPlayer 实现思路

    代码地址:https://github.com/huweigoodboy/SweetMusicPlayer 一,实现效果 目前还不是特别完善,主要有以下几个功能, 1,加载歌曲列表(实现a-z字母检索 ...

  9. android音乐播放器开发 SweetMusicPlayer 载入歌曲列表

    上一篇写了播放器的总体实现思路,http://blog.csdn.net/huweigoodboy/article/details/39855653,如今来总结下载入歌曲列表. 代码地址:https: ...

最新文章

  1. SharePoint 2007图文开发教程(3)---实现简单的WebPart
  2. Shell+Linux命令实现日志分析
  3. Stumpwm的编译安装
  4. docker进阶-搭建私有企业级镜像仓库Harbor
  5. Core Data 编程指南
  6. 前端学习(3020):vue+element今日头条管理--创建路由和配置路由
  7. matlab中size(A 2),MATLAB中size(A,2)什么意思
  8. 小鹏汽车回应“侵犯消费者权益被罚3000元”:已于3月8日对购车协议内容进行调整...
  9. Java父类与子类中静态代码块 实例代码块 静态变量 实例变量 构造函数执行顺序...
  10. as安装过程中gradle_电磁阀在安装过程中需注意的一些细节
  11. 汇编学习--7.16--直接定址表
  12. 达观杯文本智能处理(4)
  13. Zepto:基础学习
  14. OPPO Monitor Platform:从应用请求到后端处理,自研解决服务化架构系统监控难题...
  15. 电脑远程连接已停止工作 解决方案
  16. 使用pystaller打包qy图形界面遇到的问题:This application failed to start...
  17. 【web素材】11—15套免费网站后台管理模板
  18. winAUTOPWN2.8更新下载
  19. 三种交换技术及其比较
  20. 数据防泄密(DLP)系统

热门文章

  1. 上学易 APP - 小学信息平台,学区查询,幼升小,小学,学区,学校基础信息平台
  2. as使用git@oschina
  3. 程序员平时都喜欢逛什么论坛呢?
  4. Java架构师成长直通车:LVS+Nginx实现高可用集群
  5. 送5本刚刚出版的《大数据时代生存法则》
  6. 利用随机森林算法实现Bank风险预测
  7. 倒计时H5页面源码(2018年除夕)
  8. 生活中的一些常用理论
  9. python将中文转换成utf8_如何在python中从unicode转换成utf8?
  10. mac 备份文件 太大 时间机器_如何在Mac OS X中设置时间机器备份 | MOS86