176
社区成员




EmoGenius Crew —— Sprint Essay 5
Which course does this assignment belong to | 2301-MUSE Community |
---|---|
Assignment Requirement | Teamwork——Alpha Sprint |
Team name | EmoGenius Crew |
The goal of this assignment | Sprint Essay 5. |
Topical Collection Essay | EmoGenius Crew - Alpha SprintTopical Collection of Essays |
Complete the final test of the project, including functional test, user experience test, stress test, smoke test and regression test, etc., modify and improve the test cases and test flow during the test process to improve the test efficiency and test quality
The test results show that there are still many problems in our software in many aspects, and more time is needed to modify and perfect it. For example, the profile picture is displayed incorrectly, and the voice cannot be transmitted correctly.
The next stage still needs to be worked on.
Test, debug and modify the code of the emotional diary part of the emotional function area. The facial recognition code of the emotional function area is realized.
Partial code :
Part of the code display:
@RestController
public class UserController {
public static final String SESSION_NAME = "userInfo";
@Autowired
private UserService userService;
private BindingResult errors ;
/**
* 用户注册
*
* @param user 传入注册用户信息
* @param errors Validation的校验错误存放对象
* @param request 请求对象,用于操作session
* @return 注册结果
**/
@PostMapping("register")
public Result<User> register(@RequestBody @Valid User user, BindingResult errors, HttpServletRequest request) {
LOGGER.info("收到一条注册");
Result<User> result;
// 如果校验有错,返回注册失败以及错误信息
if (errors.hasErrors()) {
result = new Result<>();
result.setResultFailed(errors.getFieldError().getDefaultMessage());
return result;
}
// 调用注册服务
result = userService.register(user);
return result;
}
@PostMapping("/login")
public Result<User> login(@RequestBody @Valid User user, BindingResult errors) {
LOGGER.info("收到一条登录");
Result<User> result;
// 如果校验有错,返回登录失败以及错误信息
if (errors.hasErrors()) {
result = new Result<>();
result.setResultFailed(errors.getFieldError().getDefaultMessage());
return result;
}
// 调用登录服务
result = userService.login(user);
return result;
}
/**
* 判断用户是否登录
*
* @param request 请求对象,从中获取session里面的用户信息以判断用户是否登录
* @return 结果对象,已经登录则结果为成功,且数据体为用户信息;否则结果为失败,数据体为空
*/
@GetMapping("/is-login")
public Result<User> isLogin(HttpServletRequest request) {
// 传入session到用户服务层
return userService.isLogin(request.getSession());
}
/**
* 用户信息修改
*
* @param user 修改后用户信息对象
* @param request 请求对象,用于操作session
* @return 修改结果
*/
@PutMapping("/PersonalInfo")
public Result<User> update(@RequestBody User user, HttpServletRequest request) throws Exception {
LOGGER.info("收到一条更新信息");
Result<User> result = new Result<>();
String Base64Code= user.getHeadPortraitBase64Code();
String Path="E:/Head/"+user.getAccount()+".png";
byte[] imageBytes = Base64.decodeBase64(Base64Code);
File imageFile = new File(Path);
try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(imageFile))) {
outputStream.write(imageBytes);
} catch (IOException e) {
e.printStackTrace();
result.setResultFailed("Failed");
return result;
}
user.setHeadPortraitBase64Code(Path);
HttpSession session = request.getSession();
result = userService.update(user);
// 修改成功则刷新session信息
if (result.isSuccess()) {
session.setAttribute(SESSION_NAME, result.getData());
}
user.setHeadPortraitBase64Code(Base64Code);
return result;
}
@SneakyThrows
@PostMapping("/updateFace")
public Result<User> updateHeadPortrait(@RequestBody User user) {
LOGGER.info("收到一条面部信息");
Result<User> result=new Result<>();
String Path="E:/Head/face/"+user.getAccount()+".png";
String Base64Code= user.getHeadPortraitBase64Code();
byte[] imageBytes = Base64.decodeBase64(Base64Code);
File imageFile = new File(Path);
try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(imageFile))) {
outputStream.write(imageBytes);
result.setResultSuccess("保存成功");
return result;
} catch (IOException e) {
e.printStackTrace();
result.setResultFailed("保存失败");
return result;
}
}
@SneakyThrows
@PostMapping("/loginByFace")
public Result<User> compareFace(@RequestBody User user) {
LOGGER.info("收到一条面部登录");
return userService.LoginByFace(user);
}
@PostMapping("/Diary")
public String PredictEmo(@RequestBody Diary diary){
LOGGER.info("收到一条待测日记");
return userService.TestEmotion(diary);
}
/**
* 用户登出
*
* @param request 请求,用于操作session
* @return 结果对象
*/
@GetMapping("/logout")
public Result<Void> logout(HttpServletRequest request) {
Result<Void> result = new Result<>();
// 用户登出很简单,就是把session里面的用户信息设为null即可
request.getSession().setAttribute(SESSION_NAME, null);
result.setResultSuccess("用户退出登录成功!");
return result;
}
}
@Mapper
public interface UserDAO {
@Insert("INSERT INTO user (account, password) VALUES (#{account}, #{password})")
int add(User user);
@Update("UPDATE user SET password = #{password}, username = #{username} ,userIdiograph=#{userIdiograph}, age =#{age}, gender=#{gender},headPortraitBase64Code = #{headPortraitBase64Code}WHERE account = #{account}")
int update(User user);
@Update("UPDATE user SET headPortraitBase64Code = #{headPortraitBase64Code} WHERE account = #{account}")
int updateImg(User user);
@Select("SELECT * FROM user WHERE id = #{id}")
User getById(Integer id);
@Select("SELECT * FROM user WHERE account = #{account}")
User getByUserAccount(String account);
}
Database and server load is low.
The code of the emotional robot in the emotional function area is written.
From local storage to cloud server storage can be a good solution to the problem of insufficient database memory.
The code of facial recognition in the emotional function area was tested, debugged, modified and standardized. The code of the emotional diary part of the emotional function area is improved.
@PostMapping("/Post")
public Result<Post> update(@RequestBody Post post) throws Exception{
LOGGER.info("收到一条帖子上传");
Result<Post> result = new Result<>();
Timestamp time=new Timestamp(System.currentTimeMillis());
post.setLike(0);
post.setRemark(0);
Diary diary=new Diary();
diary.setContent(post.getContent());
post.setPolarity(userService.TestEmotion(diary));
post.setTimestamp(time);
result = forumsService.posting(post);
return result;
}
/*
@SneakyThrows
@PostMapping("/Post")
public void Post(String topic) throws MqttException {
mqttServer.init("pub_forum",1);
mqttMessage=mqttServer.getMessage();
String message = new String(mqttMessage.getPayload());
ObjectMapper objectMapper = new ObjectMapper();
Post post = objectMapper.readValue(message, Post.class);
Result<Post> result = new Result<>();
if(error.hasErrors()) {
result.setResultFailed(error.getFieldError().getDefaultMessage());
mqttServer.sendMQTTMessage("pub_account", result.getMessage(), 0);
}
result = forumsService.posting(post);
mqttServer.sendMQTTMessage("pub_forum",result.getMessage(),0);
}*/
@PostMapping ("/getPostsInfo")
public String getHistory(@RequestBody Post post) {
MappingModelCreationLogger.LOGGER.info("发送帖子信息");
List<Map<String, Object>> results = jdbcTemplate.queryForList(
"SELECT id, user_account, content, `like`, remark, created_at, polarity FROM posts ORDER BY id ASC");
return results.toString();
}
@PostMapping("/getPostsInfoByPolarity")
public String getPostsInfoByPolarity(@RequestBody Post post) {
MappingModelCreationLogger.LOGGER.info("根据情感极性发送帖子信息");
List<Map<String, Object>> results;
if (post.getPolarity().equals("positive")) {
// 查询帖子信息,仅获取 polarity 为 "positive" 的帖子
results = jdbcTemplate.queryForList(
"SELECT id, user_account, content, `like`, remark, created_at,Polarity FROM posts WHERE Polarity = 'positive'");
} else {
// 查询所有帖子信息
results = jdbcTemplate.queryForList(
"SELECT id, user_account, content, `like`, remark, created_at,Polarity FROM posts WHERE Polarity = 'negative' ");
}
return results.toString();
}
@PostMapping("/like")
public Result<Post> like(@RequestBody Post post){
MappingModelCreationLogger.LOGGER.info("收到一条 点赞或取消点赞");
Result<Post>result=new Result<>();
result=forumsService.Like(post);
return result;
}
Some codes still have problems with irregular writing.
Modify and improve the emotional diary part of the emotional function area to store the diary information code, as well as all database and server-related document writing.
Standard code writing helps debug, sometimes writing is not standard does not affect the operation of the code, but will affect the code migration, or in the process of code migration may cause problems
To achieve the music player playback page function, can display the song picture and lyrics and other music information.
package com.example.x_music.music_api;
import android.annotation.SuppressLint;
import android.net.Uri;
import com.example.x_music.callback.VoidCallBack;
import com.example.x_music.entity.MusicInfo;
import com.example.x_music.util.HttpUtil;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class WuSunMusicApi {
private static final String search = "http://www.qeecc.com/so/%s/%d.html";
private static final String meataUrl = "http://www.qeecc.com/templets/2t58/js/play.php";
private static final String refererUrl = " http://www.qeecc.com/song/%s.html";
private static final String lrcUrl = "http://api.44h4.com/lc.php?cid=%s";
/**
* 设置播放链接,歌词id,图片链接
* @param info 音乐信息
* @param callBack 回调
*/
public static void setPicAndLrcAndPlayUrl(MusicInfo info, VoidCallBack<MusicInfo> callBack){
//设置请求头参数
HashMap<String, String> params = new HashMap<>(), header = new HashMap<>();
params.put("id", info.getMusicId());
params.put("type", "ilingku");
header.put("Referer", String.format(refererUrl, info.getMusicId()));
//u异步调用
HttpUtil.post(meataUrl, params, header, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
callBack.onFail();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String s = response.body().string();
if (s.length() == 0) return;
//封面
int fi = s.indexOf("pic") + 6, efi = fi;
while (s.charAt(efi) != '"') efi++;
String cpic = s.substring(fi, efi).replaceAll("\\\\", "");
//歌词id
fi = s.indexOf("lkid") + 6; efi = fi;
while (s.charAt(efi) != '"') efi++;
String clrc = s.substring(fi, efi - 1).replaceAll("\\\\", "");
//播放链接
fi = s.indexOf("url") + 6; efi = fi;
while (s.charAt(efi) != '"') efi++;
String playUrl = s.substring(fi, efi).replaceAll("\\\\", "");
info.setPlayerUrl(playUrl);
info.setPic(cpic);
info.setLrc(String.format(lrcUrl, clrc));
response.close();
callBack.onSucceed(info);
}
});
}
/**
* 搜索
* @param key 关键词
* @param page 页数
* @param callBack 结果回调
*/
@SuppressLint("DefaultLocale")
public static void search(String key, int page, VoidCallBack<List<MusicInfo>> callBack) {
HttpUtil.get(String.format(search, Uri.encode(key), page), new Callback() {
@Override
public void onFailure(Call call, IOException e) {
callBack.onFail();
}
//<a href="/song/c3hpZGs.html" target="_mp3">周杰伦《外婆》[Mp3]</a>
@Override
public void onResponse(Call call, Response response) throws IOException {
String s = response.body().string().replaceAll("\n", "").replaceAll("\r", "").replaceAll(" ", "&");
List<MusicInfo> list = new ArrayList<>();
for (int ai = 0; ai < s.length(); ai++) {
//<a
if (s.charAt(ai) == '<' && s.charAt(ai + 1) == 'a') {
//href
int hi = ai + 9, ehi = hi;
while (s.charAt(ehi) != '"') ehi++;
String href = s.substring(hi, ehi);
//target
int ti = ehi + 10, eti = ti;
while (s.charAt(eti) != '"') eti++;
String target = s.substring(ti, eti);
//只要target为_mp3的
if (!target.equals("_mp3")) continue;
//周杰伦
int fi = eti + 2, efi = fi;
while (s.charAt(efi) != '《') efi++;
String author = s.substring(fi, efi);
//外婆
int ki = efi + 1, eki = ki;
while (s.charAt(eki) != '》') eki++;
String musicName = s.substring(ki, eki);
//music_id c3hpZGs
String musicId = href.substring(href.lastIndexOf('/') + 1, href.length() - 5);
MusicInfo info = MusicInfo.builder()
.title(musicName)
.author(author)
.musicId(musicId)
.build();
list.add(info);
ai = eki;
}
}
callBack.onSucceed(list);
response.close();
}
});
}
}
No.
Continue testing the contents of this section to make sure there are no bugs.
Working with good teammates can achieve twice the results with half the effort.
Since the emotion forum page has not been tested on the virtual machine, the final effect may not be perfect.
Beautify the page.
Patient learning will always yield results.
1.forum
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/emotion_forum_background"
android:orientation="vertical">
<Button
android:id="@+id/activeSection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/negativeSection"
android:layout_marginBottom="110dp"
android:background="@drawable/emotion_forum_positive"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:paddingRight="150dp"
android:paddingTop="80dp"
android:text="Active Section"
/>
<ImageView
android:id="@+id/rabbitHappy"
android:layout_width="80dp"
android:layout_height="100dp"
android:layout_above="@+id/negativeSection"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:background="@drawable/emotion_forum_rabbit_happy">
</ImageView>
<Button
android:id="@+id/negativeSection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/writingPosts"
android:layout_marginBottom="40dp"
android:background="@drawable/emotion_forum_negative"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:paddingRight="150dp"
android:paddingTop="80dp"
android:text="Negative Section" />
<Button
android:id="@+id/writingPosts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:layout_marginBottom="20dp"
android:layout_toStartOf="@+id/rabbitSad"
android:background="@drawable/emotion_forum_post"
android:text="make a post" />
<ImageView
android:id="@+id/rabbitSad"
android:layout_width="60dp"
android:layout_height="100dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="12dp"
android:layout_marginBottom="6dp"
android:background="@drawable/emotion_forum_rabbit_sad">
</ImageView>
</RelativeLayout>
2.home page
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#D0E3E4"
android:orientation="vertical">
<Button
android:id="@+id/ProfilePhoto"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginStart="25dp"
android:layout_marginTop="10dp"
android:background="@drawable/user_avatar_circle" />
<TextView
android:id="@+id/UserInfo"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="25dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="25dp"
android:layout_toRightOf="@+id/ProfilePhoto"
android:background="@drawable/home_circle_text"
android:paddingLeft="50dp"
android:text="Personal Infomation" />
<TextView
android:id="@+id/EmoCalendar"
android:layout_width="338dp"
android:layout_height="106dp"
android:layout_below="@+id/UserInfo"
android:layout_marginStart="30dp"
android:layout_marginTop="33dp"
android:layout_marginEnd="30dp"
android:background="@drawable/home_circle_text"
android:gravity="center_horizontal"
android:text="预留情绪日历部分">
</TextView>
<TextView
android:id="@+id/DailySentence"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/EmotionDiary"
android:background="@drawable/daily_sentence_background_4"
android:layout_marginStart="50dp"
android:layout_marginBottom="25dp"
android:layout_marginEnd="50dp"
android:gravity="center"
android:text="Daily Sentence">
</TextView>
<Button
android:id="@+id/EmotionDiary"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_above="@+id/Player"
android:background="@drawable/home_diary_4"
android:layout_alignParentStart="true"
android:layout_marginStart="50dp"
android:layout_marginBottom="25dp"
android:paddingTop="100dp"
android:text="Emotion Diary" />
<Button
android:id="@+id/EmotionForum"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_above="@+id/ChattingRobot"
android:background="@drawable/home_forum_4"
android:layout_alignParentEnd="true"
android:layout_marginEnd="50dp"
android:layout_marginBottom="25dp"
android:paddingTop="100dp"
android:text="Emotion Forum" />
<Button
android:id="@+id/Player"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="@drawable/home_player_3"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="50dp"
android:layout_marginBottom="10dp"
android:paddingTop="100dp"
android:text="Player" />
<Button
android:id="@+id/ChattingRobot"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="@drawable/home_robot_4"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="50dp"
android:layout_marginBottom="10dp"
android:paddingTop="100dp"
android:text="Chatting Robot" />
</RelativeLayout>
Continued to improve the functionality of the forum and classified the sentiment polarity for each post.
package com.example.fourm;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.example.feelingtogethertestone.HomeActivity;
import com.example.feelingtogethertestone.R;
public class CentralActivity extends AppCompatActivity {
private Button postive;
private Button negative;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_central);
postive=findViewById(R.id.POSITIVE);
negative=findViewById(R.id.NEGATIVE);
postive.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
//前一个(MainActivity.this)是目前页面,后面一个是要跳转的下一个页面
intent.setClass(CentralActivity.this, FourmmainActivity.class);
intent.putExtra("emo", "positive");
startActivity(intent);
}
});
negative.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
//前一个(MainActivity.this)是目前页面,后面一个是要跳转的下一个页面
intent.setClass(CentralActivity.this, FourmmainActivity.class);
intent.putExtra("emo", "negative");
startActivity(intent);
}
});
}
}
The posts have been divided into positive and negative categories, and they have been integrated with the server.
The integration was very successful.
Improve the functionality of the emotion calendar, allowing users to record emotions on different dates.
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.CalendarView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
private CalendarView calendarView;
private Map<String, String> moodMap; // 用于存储日期和对的心情选择
private SharedPreferences preferences;
private String initialMood; // 用于跟踪初始心情选择
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
calendarView = findViewById(R.id.calendarView);
moodMap = new HashMap<>(); // 初始化心情选择映射
preferences = getPreferences(Context.MODE_PRIVATE);
// 从SharedPreferences中恢复历史选择
restoreHistorySelection();
// 设置日历选择监听器
calendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
@Override
public void onSelectedDayChange(@NonNull CalendarView view, int year, int month, int dayOfMonth) {
String selectedDate = year + "-" + (month + 1) + "-" + dayOfMonth;
String memo = selectedDate;
initialMood = moodMap.get(selectedDate); // 获取历史选择
showToast(memo);
showMoodSelectDialog(selectedDate); // 弹出心情选择对话框
}
});
}
private void restoreHistorySelection() {
Map<String, ?> allEntries = preferences.getAll();
for (Map.Entry<String, ?> entry : allEntries.entrySet()) {
moodMap.put(entry.getKey(), entry.getValue().toString());
}
}
// 显示 Toast 的方法
private void showToast(String message) {
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
}
// 弹出心情选择对话框
private void showMoodSelectDialog(final String selectedDate) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
View dialogView = inflater.inflate(R.layout.mood_select, null);
builder.setView(dialogView);
// 获取心情选择按钮
final Button btnMoodA = dialogView.findViewById(R.id.btnMoodA);
final Button btnMoodB = dialogView.findViewById(R.id.btnMoodB);
final Button btnMoodC = dialogView.findViewById(R.id.btnMoodC);
// 设置按钮点击事件
btnMoodA.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onMoodSelected(selectedDate, "A");
}
});
btnMoodB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onMoodSelected(selectedDate, "B");
}
});
btnMoodC.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onMoodSelected(selectedDate, "C");
}
});
// 设置初始心情选择
if (initialMood != null && !initialMood.isEmpty()) {
switch (initialMood) {
case "A":
btnMoodA.setSelected(true);
break;
case "B":
btnMoodB.setSelected(true);
break;
case "C":
btnMoodC.setSelected(true);
break;
}
}
AlertDialog dialog = builder.create();
dialog.show();
}
// 处理心情选择的方法
private void onMoodSelected(String date, String mood) {
moodMap.put(date, mood); // 将日期和心情选择关联起来
showToast("你的心情:" + mood);
Log.d("MoodMap", moodMap.toString());
// 保存历史选择到SharedPreferences
SharedPreferences.Editor editor = preferences.edit();
editor.putString(date, mood);
editor.apply();
// 根据心情选择设置 CalendarView 的背景图案
int drawableResId;
switch (mood) {
case "A":
drawableResId = R.drawable.logo_a; // 替换成你的logo_A.xml资源
break;
case "B":
drawableResId = R.drawable.logo_b; // 替换成你的logo_B.xml资源
break;
case "C":
drawableResId = R.drawable.logo_c; // 替换成你的logo_C.xml资源
break;
default:
drawableResId = 0; // 如果没有匹配的心情选择,设置为0
break;
}
if (drawableResId != 0) {
calendarView.setBackgroundResource(drawableResId);
}
}
}
The functionality of recording emotions for users on different dates still needs improvement.
Improve the functionality of recording emotions for users on different dates, and continue writing code related to frontend-backend communication.
There are certain differences between the design model of the code and the virtual model, so it is important to frequently check the interface of the virtual model.
Adjusted some details of the UI interface, aligned various components, and made it more beautiful.
Need to pay attention to the display situation on different devices. The preview and actual screens may be different.
Continue learning and modifying UI.
In the process of redesigning the interface, I learned more knowledge.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#D0E4E3"
android:scaleType="centerInside">>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="150dp"
android:layout_height="80dp"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="Sign up"
android:textSize="40sp"
android:textStyle="bold"
android:textColor="@color/black"
></TextView>
<ImageView
android:id="@+id/facialPicture"
android:layout_width="110dp"
android:layout_height="120dp"
android:layout_gravity="right"
android:layout_marginLeft="100dp"
android:layout_marginRight="50dp"
android:background="@drawable/rabbit_sign_in" />
></LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginTop="0dp"
android:layout_marginLeft="30dp"
android:layout_gravity="left"
android:text="Acccount"
android:textColor="#6081A5"
></TextView>
<EditText
android:id="@+id/id_edit"
android:layout_width="360dp"
android:layout_height="45dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:background="@drawable/rectangular1_shape"
android:textColor="#141212"></EditText>
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginTop="30dp"
android:layout_marginLeft="30dp"
android:layout_gravity="left"
android:text="Password"
android:textColor="#6081A5"
></TextView>
<EditText
android:id="@+id/passward_edit"
android:layout_width="360dp"
android:layout_height="45dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:background="@drawable/rectangular1_shape"
android:textColor="#141212"></EditText>
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginTop="30dp"
android:layout_marginLeft="30dp"
android:layout_gravity="left"
android:text="Reconfirm your Password"
android:textColor="#6081A5"
></TextView>
<EditText
android:id="@+id/pass_edit_1"
android:layout_width="360dp"
android:layout_height="45dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:background="@drawable/rectangular1_shape"
android:textColor="#141212"></EditText>
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginTop="30dp"
android:layout_marginLeft="30dp"
android:layout_gravity="left"
android:text="Email Address"
android:textColor="#6081A5"
></TextView>
<EditText
android:id="@+id/email_edit"
android:layout_width="360dp"
android:layout_height="45dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:background="@drawable/rectangular1_shape"
android:textColor="#141212"></EditText>
<Button
android:id="@+id/regester2"
android:layout_width="360dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="register!"
android:layout_marginTop="45dp"
android:background="@drawable/rectangular2_shape"
android:textColor="@color/white"
/>
</LinearLayout>
Completed the production of the emotion diary.
Need to create buttons for each day's date and add emotion tags.
Resolve remaining issues.
The plugin functionality of Android Studio is very powerful.
The music player has been completed, which can play music, search music and other functions.
package com.example.x_music.activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.x_music.R;
import com.example.x_music.callback.VoidCallBack;
import com.example.x_music.adpter.PlayListDetailAdapter;
import com.example.x_music.datasource.MusicInfoDB;
import com.example.x_music.datasource.PlaylistDB;
import com.example.x_music.entity.MusicInfo;
import com.example.x_music.entity.PlayList;
import com.example.x_music.util.DownloadPool;
import com.example.x_music.util.ToastUtil;
import com.example.x_music.util.XMusicPlayer;
import com.xuexiang.xui.XUI;
import com.xuexiang.xui.widget.actionbar.TitleBar;
import com.xuexiang.xui.widget.button.ButtonView;
import java.util.ArrayList;
public class PlayListDetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
XUI.initTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play_list_detail);
//设置回退行为
TitleBar bar = findViewById(R.id.pld_titleBar);
bar.getLeftText().setOnClickListener(v -> finish());
//获取歌单id
Intent intent = getIntent();
int id = intent.getIntExtra("id", -1);
if (id == -1) return;
//用歌单id查询歌单
PlayList playList = PlaylistDB.getById(id);
String[] musicIds = PlaylistDB.getMusicInfoIdsArray(playList);
RecyclerView recyclerView = findViewById(R.id.pld_list);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplication());
recyclerView.setLayoutManager(linearLayoutManager);
//设置adpater
PlayListDetailAdapter adapter = new PlayListDetailAdapter(playList, musicIds);
recyclerView.setAdapter(adapter);
//下载所有
ButtonView downAll = findViewById(R.id.fragment_down_btn);
//下载所有歌曲
downAll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for (String musicId : musicIds) {
//查询音乐信息
MusicInfo mfo = MusicInfoDB.getById(Integer.parseInt(musicId));
if (mfo != null) {
//异步下载
DownloadPool.download(mfo, new VoidCallBack<MusicInfo>() {
@Override
public void onSucceed(MusicInfo musicInfo) {
//下载成功回调
runOnUiThread(new Runnable() {
@Override
public void run() {
ToastUtil.toast(musicInfo.getTitle() + "下载成功");
}
});
}
@Override
public void onFail() {
//下载失败回调
runOnUiThread(new Runnable() {
@Override
public void run() {
ToastUtil.toast(mfo.getTitle() + "下载失败");
}
});
}
});
}
}
}
});
//播放所有
ButtonView playAll = findViewById(R.id.fragment_play_btn);
playAll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
XMusicPlayer player = ContextApp.getPlayer();
//清空播放列表
player.clearPlayerList();
//获取播放列表
ArrayList<MusicInfo> list = new ArrayList<>();
for (String musicId : musicIds) {
//查询播放信息
MusicInfo info = MusicInfoDB.getById(Integer.parseInt(musicId));
list.add(info);
}
//设置播放列表
player.setPlayList(list);
//播放第一首
player.play(0);
}
});
}
}
package com.example.x_music;
import android.app.Application;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;
import com.example.x_music.adpter.ViewPagerAdapter;
import com.example.x_music.datasource.CacheDataSource;
import com.google.android.material.tabs.TabLayout;
import com.xuexiang.xui.XUI;
import com.xuexiang.xui.widget.textview.MarqueeTextView;
import com.xuexiang.xui.widget.textview.marqueen.DisplayEntity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
XUI.initTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initTabLayout();
}
private void initTabLayout(){
ViewPager viewPager = findViewById(R.id.viewPager);
TabLayout tabLayout = findViewById(R.id.tabLayout);
viewPager.setAdapter(new ViewPagerAdapter(this, getSupportFragmentManager()));
tabLayout.setupWithViewPager(viewPager);
int[] icons = new int[]{
R.drawable.play,
R.drawable.my_playlist,
R.drawable.search,
R.drawable.setting
};
for (int i = 0; i < icons.length; i++) {
tabLayout.getTabAt(i).setIcon(icons[i]);
}
}
}
No.
Continue to improve the music player to ensure there are no bugs.
Further improvement of content and layout is needed.
Added recording functionality to the diary.
The Gradle of the project implementing the recording feature is not consistent with the Gradle of the main project, resulting in import failure.
Improve the recording history feature in the diary.
Pay attention to whether different versions of API methods are compatible.