diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..639900d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..7252431
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/poem.iml b/.idea/poem.iml
new file mode 100644
index 0000000..d6ebd48
--- /dev/null
+++ b/.idea/poem.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/doc/实践模板-开源软件泛读、标注和维护报告文档.docx b/doc/实践模板-开源软件泛读、标注和维护报告文档.docx
new file mode 100644
index 0000000..46491d2
Binary files /dev/null and b/doc/实践模板-开源软件泛读、标注和维护报告文档.docx differ
diff --git a/doc/系统设计分析第一次作业.docx b/doc/系统设计分析第一次作业.docx
new file mode 100644
index 0000000..9f55070
Binary files /dev/null and b/doc/系统设计分析第一次作业.docx differ
diff --git a/src/MyApplication/.gitignore b/src/MyApplication/.gitignore
new file mode 100644
index 0000000..aa724b7
--- /dev/null
+++ b/src/MyApplication/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/src/MyApplication/.idea/.gitignore b/src/MyApplication/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/src/MyApplication/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/src/MyApplication/.idea/.name b/src/MyApplication/.idea/.name
new file mode 100644
index 0000000..e7cb646
--- /dev/null
+++ b/src/MyApplication/.idea/.name
@@ -0,0 +1 @@
+poem
\ No newline at end of file
diff --git a/src/MyApplication/.idea/compiler.xml b/src/MyApplication/.idea/compiler.xml
new file mode 100644
index 0000000..fb7f4a8
--- /dev/null
+++ b/src/MyApplication/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MyApplication/.idea/gradle.xml b/src/MyApplication/.idea/gradle.xml
new file mode 100644
index 0000000..7b46144
--- /dev/null
+++ b/src/MyApplication/.idea/gradle.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MyApplication/.idea/misc.xml b/src/MyApplication/.idea/misc.xml
new file mode 100644
index 0000000..bdd9278
--- /dev/null
+++ b/src/MyApplication/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MyApplication/.idea/vcs.xml b/src/MyApplication/.idea/vcs.xml
new file mode 100644
index 0000000..b2bdec2
--- /dev/null
+++ b/src/MyApplication/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MyApplication/app/.gitignore b/src/MyApplication/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/src/MyApplication/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/src/MyApplication/app/build.gradle b/src/MyApplication/app/build.gradle
new file mode 100644
index 0000000..a814057
--- /dev/null
+++ b/src/MyApplication/app/build.gradle
@@ -0,0 +1,88 @@
+plugins {
+ id 'com.android.application'
+ id "org.sonarqube" version "3.3"
+}
+
+android {
+ namespace 'com.example.myapplication'
+ compileSdk 32
+
+ defaultConfig {
+ applicationId "com.example.myapplication"
+ minSdk 26
+ targetSdk 32
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ buildFeatures {
+ viewBinding true
+ }
+}
+apply plugin: "org.sonarqube"
+sonarqube {
+ properties {
+ property "sonar.host.url", "http://localhost:9000" //sonar管理系统地址
+ property "sonar.login", "admin" // sonar管理系统账号
+ property "sonar.password", "YJL321432yjl" // sonar管理系统密码
+ property "sonar.sourceEncoding", "UTF-8"
+ property "sonar.projectKey", "poem" //sonar平台中相对应项目的key
+ property "sonar.projectName", "poem" //sonar平台中相对应项目的名字
+ property "sonar.sources", "src/main" //源码,sonar检测的源文件目录
+ property "sonar.projectVersion", project.version //版本,随意
+ property "sonar.java.binaries", "build/intermediates/javac/debug/classes"
+ }
+}
+dependencies {
+ implementation fileTree(dir: "libs", include: ["*.jar"])
+
+ implementation 'androidx.appcompat:appcompat:1.4.1'
+ implementation 'com.google.android.material:material:1.5.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
+ implementation 'androidx.navigation:navigation-fragment:2.4.1'
+ implementation 'androidx.navigation:navigation-ui:2.4.1'
+ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+
+ implementation 'com.github.xuexiangjys:XUI:1.2.1'
+ implementation 'androidx.recyclerview:recyclerview:1.2.1'
+ implementation 'com.github.bumptech.glide:glide:4.15.1'
+
+ /*步骤二:添加retrofit依赖库*/
+ implementation 'com.squareup.retrofit2:retrofit:2.9.0'
+ implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
+
+ implementation 'org.sufficientlysecure:html-textview:4.0'
+
+ // 下拉刷新,上拉加载
+ implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.3'
+ // 没有使用特殊Header,可以不加这一依赖
+ implementation 'com.scwang.smartrefresh:SmartRefreshHeader:1.1.3'
+ //tag
+ implementation 'com.hyman:flowlayout-lib:1.1.2'
+
+ //图表
+ // Charts
+ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
+
+ //腾讯接口
+ implementation 'com.tencent.edu:TAISDK:1.2.3.92'
+
+ //代码审查
+ implementation 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3'
+}
\ No newline at end of file
diff --git a/src/MyApplication/app/proguard-rules.pro b/src/MyApplication/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/src/MyApplication/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/src/MyApplication/app/src/androidTest/java/com/example/myapplication/ExampleInstrumentedTest.java b/src/MyApplication/app/src/androidTest/java/com/example/myapplication/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..982ba51
--- /dev/null
+++ b/src/MyApplication/app/src/androidTest/java/com/example/myapplication/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.example.myapplication;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("com.example.myapplication", appContext.getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/src/MyApplication/app/src/main/AndroidManifest.xml b/src/MyApplication/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..99713ef
--- /dev/null
+++ b/src/MyApplication/app/src/main/AndroidManifest.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/AdviceActivity.java b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/AdviceActivity.java
new file mode 100644
index 0000000..9566797
--- /dev/null
+++ b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/AdviceActivity.java
@@ -0,0 +1,36 @@
+package com.example.myapplication.Activity;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.TextView;
+
+import com.example.myapplication.R;
+import com.xuexiang.xui.widget.edittext.MultiLineEditText;
+
+public class AdviceActivity extends AppCompatActivity {
+
+ private TextView poetryTitle;
+ private MultiLineEditText advice;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_advice);
+
+ Intent intent = getIntent();
+ String poetryId = intent.getStringExtra("poemId");
+ String Title = intent.getStringExtra("poemTitle");
+ String username = intent.getStringExtra("username");
+
+ initView();
+
+ poetryTitle.setText(Title);
+ }
+
+ private void initView() {
+ poetryTitle = findViewById(R.id.poetryTitle);
+ advice = findViewById(R.id.advice);
+ }
+}
\ No newline at end of file
diff --git a/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/ChatActivity.java b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/ChatActivity.java
new file mode 100644
index 0000000..d534fff
--- /dev/null
+++ b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/ChatActivity.java
@@ -0,0 +1,244 @@
+package com.example.myapplication.Activity;
+
+import static android.widget.Toast.LENGTH_SHORT;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import android.content.Intent;
+import android.graphics.Color;
+import android.media.MediaPlayer;
+import android.media.MediaRecorder;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.Toast;
+
+import com.example.myapplication.Adapter.MsgAdapter;
+import com.example.myapplication.Modal.ClientMessageBean;
+import com.example.myapplication.Modal.SystemMessageBean;
+import com.example.myapplication.R;
+import com.example.myapplication.Util.FileUtils;
+import com.example.myapplication.Util.WebSocketUtil;
+import com.google.gson.Gson;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ChatActivity extends AppCompatActivity {
+ private List msgList = new ArrayList<>();
+ private String username;
+ private int rid;
+ static int numOfCaches= 1;
+ //此处待修改
+ private String url = "ws://101.33.242.218:8081/chat/";
+ private EditText inputText;
+ private Button send;
+ private Button sendVoiceButton;
+ private ImageButton changeToVoice;
+ private ImageButton changeToText;
+ private RecyclerView msgRecyclerView;
+ private MsgAdapter adapter;
+ LinearLayout sendVoice;
+ LinearLayout sendText;
+ private LinearLayoutManager layoutManager;
+ private WebSocketUtil webSocketUtil;
+ //语音操作对象
+ private MediaPlayer mPlayer = null;
+ private MediaRecorder mRecorder = null;
+ //语音文件保存路径
+ private String FileName = null;
+ //接受消息,更新界面
+ private Handler handler = new Handler(new Handler.Callback() {
+ @Override
+ public boolean handleMessage(@NonNull Message message) {
+ SystemMessageBean systemMessageBean = (SystemMessageBean) message.obj;
+ Gson gson = new Gson();
+ ClientMessageBean messageBean ;
+ if(systemMessageBean.getFrom() == null){
+ messageBean = new ClientMessageBean(0,null,systemMessageBean.getMessage(),null);
+ }else if (!systemMessageBean.getFrom().equals(username)){
+ messageBean = gson.fromJson(systemMessageBean.getMessage(),ClientMessageBean.class);
+ messageBean.setType(messageBean.getType()+1);
+ }else{
+ messageBean = gson.fromJson(systemMessageBean.getMessage(),ClientMessageBean.class);
+ }
+ if(messageBean.getRecord()!=null){
+ try {
+ byte[] bytes = messageBean.getRecord();
+ FileUtils.getFileByBytes(bytes, getCacheDir().getPath()+"/",numOfCaches+".amr");
+ messageBean.setMessage(getCacheDir().getPath()+"/"+numOfCaches+".amr");
+ numOfCaches++;
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+ msgList.add(messageBean);
+ //当有新消息,刷新RecyclerVeiw的显示
+ adapter.notifyItemInserted(msgList.size() - 1);
+ //将RecyclerView定位到最后一行
+ msgRecyclerView.scrollToPosition(msgList.size() - 1);
+ //清空输入框内容
+ inputText.setText("");
+ return false;
+ }
+ });
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.chat_view);
+ mPlayer = new MediaPlayer();
+ FileName = getCacheDir() + "/amrsend.amr";
+ //初始化控件
+ initView();
+ createConnection();
+ send.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ //点击发送后新建信息,发送给服务器
+ String content = inputText.getText().toString();
+ ClientMessageBean messageBean = new ClientMessageBean(
+ 1,
+ username,
+ content,
+ null
+ );
+ Gson gson = new Gson();
+ webSocketUtil.send(gson.toJson(messageBean));
+ }
+ });
+
+ //切换发送语音和文本
+ changeToVoice.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ sendText.setVisibility(View.GONE);
+ sendVoice.setVisibility(View.VISIBLE);
+ }
+ });
+ changeToText.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ sendVoice.setVisibility(View.GONE);
+ sendText.setVisibility(View.VISIBLE);
+ }
+ });
+ //设置发送语音监听
+ sendVoiceButton.setOnTouchListener(sendVoiceListener);
+
+ }
+
+ public void initView(){
+ sendText = findViewById(R.id.text_bottom);
+ sendVoice = findViewById(R.id.voice_bottom);
+
+ inputText = (EditText)findViewById(R.id.input_txet);
+ send = (Button) findViewById(R.id.send);
+ sendVoiceButton = findViewById(R.id.record_voice);
+ changeToVoice = findViewById(R.id.change_to_voice);
+ changeToText = findViewById(R.id.back_to_text);
+
+ //首先隐藏发送语音模块
+ sendVoice.setVisibility(View.GONE);
+
+ msgRecyclerView = (RecyclerView)findViewById(R.id.msg_recycle_view);
+ layoutManager = new LinearLayoutManager(this);
+ msgRecyclerView.setLayoutManager(layoutManager);
+ adapter = new MsgAdapter(msgList,mPlayer);
+ msgRecyclerView.setAdapter(adapter);
+ }
+
+ void createConnection(){
+ //获取进入房间号和用户名
+ Intent intent = getIntent();
+ username = intent.getStringExtra("username");
+ rid = intent.getIntExtra("rid",0);
+
+ webSocketUtil = new WebSocketUtil();
+ webSocketUtil.connect(url,rid,username,handler);
+ }
+
+
+ //这里记得断开连接
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ webSocketUtil.disconnect();
+ }
+ private OnTouchListener sendVoiceListener = new OnTouchListener() {
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ float beginX,beginY=0,finalX,finalY;
+ switch (motionEvent.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ sendVoiceButton.setText("正在录音");
+ sendVoiceButton.setBackgroundColor(Color.RED);
+ beginX = motionEvent.getX();
+ beginY = motionEvent.getY();
+ Log.e("MainActivity", "beginX:" + beginX);
+ Log.e("MainActivity", "beginY:" + beginY);
+ Log.e("MainActivity", "ACTION_DOWN");
+ mRecorder = new MediaRecorder();
+ mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+ mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+ mRecorder.setOutputFile(FileName);
+ mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+ try {
+ mRecorder.prepare();
+ } catch (IOException e) {
+ Log.e("MainActivity", "prepare() failed" + e);
+ }
+ mRecorder.start();
+ break;
+ case MotionEvent.ACTION_UP:
+ sendVoiceButton.setText("按住说话");
+ sendVoiceButton.setBackgroundColor(getColor(R.color.colorPrimaryDark));
+ finalX = motionEvent.getX();
+ finalY = motionEvent.getY();
+ Log.e("MainActivity", "finalX:" + finalX);
+ Log.e("MainActivity", "finalY:" + finalY);
+ Log.e("MainActivity", "ACTION_UP");
+ mRecorder.stop();
+ mRecorder.release();
+ mRecorder = null;
+ if ((beginY - finalY) > 50) {
+ Log.e("MainActivity", "执行删除");
+ new File(FileName).delete();
+ Toast.makeText( ChatActivity.this,"取消发送", LENGTH_SHORT).show();
+ Log.e("MainActivity", "执行删除后文件是否还存在:" + new File(FileName).exists());
+ }
+ if(new File(FileName).exists()){
+ ClientMessageBean messageBean = new ClientMessageBean(
+ 3,
+ username,
+ null,
+ FileUtils.getBytesByFile(new File(FileName))
+ );
+ Gson gson = new Gson();
+ webSocketUtil.send(gson.toJson(messageBean));
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
+ };
+}
\ No newline at end of file
diff --git a/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/DetailActivity.java b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/DetailActivity.java
new file mode 100644
index 0000000..49e3c90
--- /dev/null
+++ b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/DetailActivity.java
@@ -0,0 +1,260 @@
+package com.example.myapplication.Activity;
+
+import static com.xuexiang.xui.XUI.getContext;
+
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.StrictMode;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.myapplication.Api.Api;
+import com.example.myapplication.Constant.constant;
+import com.example.myapplication.Modal.PoetryDetail;
+import com.example.myapplication.R;
+import com.example.myapplication.Util.Spilt;
+import com.google.gson.Gson;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.sufficientlysecure.htmltextview.HtmlTextView;
+
+import java.io.IOException;
+import java.util.List;
+
+import okhttp3.ResponseBody;
+import retrofit2.Callback;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+public class DetailActivity extends AppCompatActivity {
+
+
+ private static final String TAG = "test";
+
+ private Retrofit PoetryDetailRetrofit;
+ private Context context;
+
+ private Toolbar toolbar;
+ private TextView titleText;
+ private String toolbarTitle;
+
+ private HtmlTextView htmlAnnotation;
+ private TextView translation;
+ private TextView appreciation;
+ private LinearLayout linearLayout;
+ private Button test_button;
+ private TextView menu_line;
+ private TextView poem_title;
+ private TextView poem_author;
+ private TextView poem_content;
+ private ImageView poem_menu_advice;
+
+// 标签
+// private TagFlowLayout tag_flow;
+
+ private ScrollView scrollView;
+ private ImageView author_img;
+ private ImageView icon_collect;
+ private TextView author_content;
+ private JSONObject responseObject;
+ private PoetryDetail poetryDetail;
+ private final int COMPLETED = 1;
+ private final int COLLECT = 2;
+ private final int STORAGE = 3;
+ private final int TO_WEBVIEW = 4;
+ private List tags;
+
+ private Handler handler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == COMPLETED) {
+ try {
+ poem_title.setText(poetryDetail.getTitle()); //诗词名
+ String author = poetryDetail.getDesty() + "." + poetryDetail.getAuthor();
+ poem_author.setText(author); //作者+朝代
+ String contentText = poetryDetail.getContent();
+ contentText = Spilt.spiltContentText(contentText);
+ poem_content.setText(contentText); //原文
+
+// 图片
+// Bitmap bitmap = getURLImage(poetryDetail.getImg()); //诗人图片
+// author_img.setImageBitmap(bitmap);
+
+// author_content.setText(poetryDetail.getAuthorDetail()); //诗人信息
+ String annotation = poetryDetail.getAnnotation();
+ htmlAnnotation.setHtml(annotation); //注释
+ appreciation.setText(poetryDetail.getAppreciation()); //赏析
+ translation.setText(poetryDetail.getTransContent()); //译文
+// tags = spiltBySpace(poetryDetail.getTag()); //标签
+
+// 标签
+// initTagFlowLayout();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }else {
+ Toast.makeText(DetailActivity.this, "显示失败", Toast.LENGTH_SHORT).show();
+ }
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_detail);
+
+ context = getContext();
+
+ //在主线程访问网络连接
+ if (android.os.Build.VERSION.SDK_INT > 9) {
+ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.setThreadPolicy(policy);
+ }
+
+ initView();
+
+ setSupportActionBar(toolbar);//设置toolbar
+ getSupportActionBar().setDisplayShowTitleEnabled(false);//屏蔽toolbar默认标题显示
+
+ toolbarTitle = getIntent().getStringExtra("toolbarTitle");
+ String content = getIntent().getStringExtra("content");
+
+ titleText.setText(toolbarTitle);
+
+// 获取诗词详情
+ getPoetryDetailByContent(content);
+
+// 监听器
+ //背诵
+ test_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent;
+ intent = new Intent(getContext(), TestActivity.class);
+ intent.putExtra("title", poetryDetail.getTitle());
+ intent.putExtra("desty", poetryDetail.getDesty());
+ intent.putExtra("author", poetryDetail.getAuthor());
+ intent.putExtra("content", poetryDetail.getContent());
+ startActivity(intent);
+ }
+ });
+
+ //意见反馈
+ poem_menu_advice.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(getContext(), AdviceActivity.class);
+ String poemId = String.valueOf(poetryDetail.getId());
+
+ intent.putExtra("poemId", poemId);
+ intent.putExtra("poemTitle", poetryDetail.getTitle());
+ startActivity(intent);
+ }
+ });
+ }
+
+ private void initView() {
+ toolbar = findViewById(R.id.poem_titleBar);
+ titleText = findViewById(R.id.poem_titleText);
+ menu_line = findViewById(R.id.menu_line);
+ htmlAnnotation = findViewById(R.id.annotation_text);
+ translation = findViewById(R.id.translation_text);
+ appreciation = findViewById(R.id.appreciation_text);
+ test_button = findViewById(R.id.poem_test_button);
+ poem_title = findViewById(R.id.detail_poem_title);
+ poem_author = findViewById(R.id.detail_poem_author);
+ poem_content = findViewById(R.id.detail_poem_content);
+ poem_menu_advice = findViewById(R.id.poem_menu_advice);
+
+ author_img = findViewById(R.id.author_img);
+ author_content = findViewById(R.id.author_detail);
+ scrollView = findViewById(R.id.detail_scroll);
+ linearLayout = findViewById(R.id.poem_linnear);
+ icon_collect = findViewById(R.id.poem_menu_icon);
+
+ }
+
+ //根据首句获取诗词详情
+ public void getPoetryDetailByContent(String content) {
+ String poetry_detail_url = constant.poetry_IP;
+
+ //步骤五:构建Retrofit实例
+ PoetryDetailRetrofit = new Retrofit.Builder()
+ //设置网络请求BaseUrl地址
+ .baseUrl(poetry_detail_url)
+ //设置数据解析器
+ .addConverterFactory(GsonConverterFactory.create())
+ .build();
+
+ //步骤六:创建网络请求接口对象实例
+ Api poetryDetailApi = PoetryDetailRetrofit.create(Api.class);
+
+ //步骤七:对发送请求进行封装,传入接口参数
+ retrofit2.Call poetryDetailDataCall = poetryDetailApi.getPoetryDetail(content);
+
+ //步骤八:发送网络请求(同步)
+ Log.e(TAG, "get == url:" + poetryDetailDataCall.request().url());
+ new Thread(new Runnable() { //Android主线程不能操作网络请求,所以new一个线程来操作
+ @Override
+ public void run() {
+ poetryDetailDataCall.enqueue(new Callback() {
+ @Override
+ public void onResponse(retrofit2.Call call, retrofit2.Response response) {
+ try {
+ String responseData = response.body().string();
+ parseJSONWithGSON(responseData);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onFailure(retrofit2.Call call, Throwable t) {
+ Toast.makeText(DetailActivity.this, "获取诗词详情失败", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }).start();
+ }
+
+ //解析返回数据
+ private void parseJSONWithGSON(String jsonData) {
+ Gson gson = new Gson();
+ JSONObject jsonObject = null;
+ try {
+ responseObject = new JSONObject(jsonData);
+ if (responseObject != null) {
+ jsonObject = responseObject;
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ PoetryDetail detail = null;
+ if (jsonObject != null) {//成功获取数据
+ detail = gson.fromJson(jsonObject.toString(), PoetryDetail.class);
+ poetryDetail = detail;
+ Message message = new Message();
+ message.what = COMPLETED;
+ handler.sendMessage(message);
+ } else//没有数据
+ {
+ Message message = new Message();
+ message.what = TO_WEBVIEW;
+ handler.sendMessage(message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/LoginActivity.java b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/LoginActivity.java
new file mode 100644
index 0000000..fe6e9d9
--- /dev/null
+++ b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/LoginActivity.java
@@ -0,0 +1,195 @@
+package com.example.myapplication.Activity;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.StrictMode;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.example.myapplication.Api.Api;
+import com.example.myapplication.Constant.constant;
+import com.example.myapplication.R;
+
+import java.io.IOException;
+
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+public class LoginActivity extends AppCompatActivity {
+
+ private static final String TAG = "test";
+ public static final int MSG_LOGIN_ERR = 1; //登录错误
+ public static final int MSG_CONNET_ERR = 2; //网络链接错误
+
+ private Context context;
+ private Retrofit LoginRetrofit;
+
+ private EditText et_number;
+ private EditText et_password;
+ private Button bt_login;
+ private Button bt_register;
+
+ private LoginHandler login_handler;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_login);
+
+ context = this;
+ InitView();
+ login_handler = new LoginHandler();
+ Init();
+
+// StrictMode是指严格模式
+ if (Build.VERSION.SDK_INT > 9){
+ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.setThreadPolicy(policy);//这两句设置禁止所有检查
+ }
+ }
+
+ private void InitView() {
+ et_number = (EditText)findViewById(R.id.et_number);
+ et_password = (EditText)findViewById(R.id.et_password);
+ bt_login = (Button)findViewById(R.id.bt_login);
+ bt_register = (Button) findViewById(R.id.bt_register);
+ }
+
+ private void Init() {
+ //设置提示的颜色
+ et_number.setHintTextColor(getResources().getColor(R.color.white));
+ et_password.setHintTextColor(getResources().getColor(R.color.white));
+
+
+ //登录
+ bt_login.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (judge()) {
+ loginInfo();
+ }
+ }
+ });
+
+ //注册
+ bt_register.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Toast.makeText(context, "注册", Toast.LENGTH_SHORT).show();
+ startActivity(new Intent(LoginActivity.this, RegisterActivity.class));
+ }
+ });
+
+ }
+
+ /**登录*/
+ private void loginInfo() {
+ String username = et_number.getText().toString();
+ String password = et_password.getText().toString();
+
+ String login_url = constant.poetry_IP;
+
+ //步骤五:构建Retrofit实例
+ LoginRetrofit = new Retrofit.Builder()
+ //设置网络请求BaseUrl地址
+ .baseUrl(login_url)
+ //设置数据解析器
+ .addConverterFactory(GsonConverterFactory.create())
+ .build();
+
+ //步骤六:创建网络请求接口对象实例
+ Api loginApi = LoginRetrofit.create(Api.class);
+
+ //步骤七:对发送请求进行封装,传入接口参数
+ Call loginDataCall = loginApi.getData(username, password);
+
+ //步骤八:发送网络请求(同步)
+ Log.e(TAG, "post == url:" + loginDataCall.request().url());
+ new Thread(new Runnable() { //Android主线程不能操作网络请求,所以new一个线程来操作
+ @Override
+ public void run() {
+ loginDataCall.enqueue(new Callback() {
+ @Override
+ public void onResponse(Call call, Response response) {
+ try {
+ String date = new String(response.body().bytes());
+ if(date.equals("success")){
+ Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
+ Intent intent = new Intent(LoginActivity.this, MainActivity.class);
+ startActivity(intent);
+ }else{
+ Toast.makeText(LoginActivity.this, "登录失败,请检查你的用户名和密码", Toast.LENGTH_SHORT).show();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+ Toast.makeText(LoginActivity.this, "get回调失败", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }).start();
+
+ }
+
+ /**判断登录信息是否合法*/
+ private boolean judge() {
+ if (TextUtils.isEmpty(et_number.getText().toString()) ) {
+ Toast.makeText(context, "用户名不能为空",Toast.LENGTH_SHORT).show();
+ return false;
+ } else if (TextUtils.isEmpty(et_password.getText().toString())) {
+ Toast.makeText(context, "用户ID不能为空",Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ return true;
+ }
+
+ /**事件捕获*/
+ class LoginHandler extends Handler {
+ @Override
+ public void dispatchMessage(Message msg) {
+ super.dispatchMessage(msg);
+ switch (msg.what) {
+ case MSG_LOGIN_ERR:
+ et_number.setText("");
+ et_password.setText("");
+ et_number.requestFocus();
+
+ new AlertDialog.Builder(LoginActivity.this)
+ .setTitle("注意")
+ .setMessage("用户名或密码输入不正确,请重新输入")
+ .setPositiveButton("确定",null)
+ .create()
+ .show();
+ bt_login.setEnabled(true);
+ break;
+ case MSG_CONNET_ERR:
+ new AlertDialog.Builder(LoginActivity.this)
+ .setTitle("注意")
+ .setMessage("网络连接错误,请检查网络")
+ .setPositiveButton("确定",null)
+ .create()
+ .show();
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/MainActivity.java b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/MainActivity.java
new file mode 100644
index 0000000..e67de41
--- /dev/null
+++ b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/MainActivity.java
@@ -0,0 +1,155 @@
+package com.example.myapplication.Activity;
+
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.view.MenuItem;
+import android.view.View;
+
+import com.example.myapplication.Fragment.AiPoetry.AiPoetryFragment;
+import com.example.myapplication.Fragment.My.MyFragment;
+import com.example.myapplication.Fragment.Search.SearchFragment;
+import com.example.myapplication.Fragment.association.AssociationFragment;
+import com.example.myapplication.Fragment.home.HomeFragment;
+import com.example.myapplication.R;
+import com.google.android.material.bottomnavigation.BottomNavigationView;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentStatePagerAdapter;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.navigation.NavController;
+import androidx.navigation.Navigation;
+import androidx.navigation.ui.AppBarConfiguration;
+import androidx.navigation.ui.NavigationUI;
+import androidx.viewpager.widget.ViewPager;
+
+import com.example.myapplication.databinding.ActivityMainBinding;
+
+public class MainActivity extends AppCompatActivity {
+
+ BottomNavigationView navView;
+ ViewPager viewPager;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ //状态栏文字自适应
+ getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+
+ initViewPage();
+ initBottomNav();
+
+ FragmentManager manager = this.getSupportFragmentManager();
+ FragmentTransaction fTransaction = manager.beginTransaction();
+ fTransaction.replace(R.id.fragment_search,new SearchFragment());
+ fTransaction.commit();
+
+ }
+
+ /**
+ * viewPage初始化
+ * 获取viewPager,并为其设置适配器
+ */
+ private void initViewPage() {
+ viewPager = findViewById(R.id.view_pager);
+ viewPager.setAdapter(new FragmentStatePagerAdapter(getSupportFragmentManager()) {
+ @NonNull
+ @Override
+ public Fragment getItem(int position) {
+ Fragment fragment = null;
+ /**
+ *页面选中判断,当到达指定position时,返回position对应的页面
+ */
+ switch ( position ){
+ case 0:
+ fragment = new HomeFragment();
+ break;
+ case 1:
+ fragment = new AiPoetryFragment();
+ break;
+ case 2:
+ requestPermission();
+ fragment = new AssociationFragment();
+ break;
+ case 3:
+ fragment = new MyFragment();
+ break;
+ }
+ assert fragment != null;
+ return fragment;
+ }
+
+ /**
+ *这里需要填写总的页面数量
+ */
+ @Override
+ public int getCount() {
+ return 4;
+ }
+ });
+
+ //viewPager滑动事件监听
+ viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ navView.getMenu().getItem(position).setChecked(true);
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+
+ }
+ });
+ }
+
+ /**
+ * 底部导航栏初始化
+ */
+ private void initBottomNav() {
+ navView = findViewById(R.id.nav_view);
+ navView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
+ @Override
+ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
+ /**
+ *当点击到菜单中的item时,调用viewPage中的setCurrentItem方法切换到对应界面
+ */
+ switch ( item.getItemId() ){
+ case R.id.navigation_home:
+ viewPager.setCurrentItem(0);
+ break;
+ case R.id.navigation_ai_poetry:
+ viewPager.setCurrentItem(1);
+ break;
+ case R.id.navigation_association:
+ viewPager.setCurrentItem(2);
+ break;
+ case R.id.navigation_my:
+ viewPager.setCurrentItem(3);
+ break;
+ }
+ return false;
+ }
+ });
+ }
+
+ private void requestPermission() {
+ if (ContextCompat.checkSelfPermission(this,
+ Manifest.permission.RECORD_AUDIO)
+ != PackageManager.PERMISSION_GRANTED) {
+ ActivityCompat.requestPermissions(this,
+ new String[]{Manifest.permission.RECORD_AUDIO},
+ 1234);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/PoetryListActivity.java b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/PoetryListActivity.java
new file mode 100644
index 0000000..a4bc5d4
--- /dev/null
+++ b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/PoetryListActivity.java
@@ -0,0 +1,311 @@
+package com.example.myapplication.Activity;
+
+import static com.xuexiang.xui.XUI.getContext;
+
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.myapplication.Adapter.PoemListAdapter;
+import com.example.myapplication.Api.Api;
+import com.example.myapplication.Constant.constant;
+import com.example.myapplication.Modal.Poetry;
+import com.example.myapplication.R;
+import com.example.myapplication.Util.Spilt;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.scwang.smartrefresh.layout.api.RefreshLayout;
+import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener;
+import com.scwang.smartrefresh.layout.listener.OnRefreshListener;
+
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+public class PoetryListActivity extends AppCompatActivity {
+
+ private Retrofit SearchRetrofit;
+ private Retrofit SearchByTagRetrofit;
+ private static final String TAG = "test";
+
+ private PoemListAdapter poemListAdapter;
+ private ListView poemListView;
+ private Toolbar toolbar;
+ private TextView titleText;
+ private String toolbarTitle;
+ private final int COMPLETED = 1;
+ private final int TO_WEBVIEW = 2;
+ private RefreshLayout refreshLayout;
+ // 每次20首
+ private Integer size = 20;
+ private Integer page = 0;
+ private List poetryList = new ArrayList<>();
+ private boolean isLoad = false;
+ private JSONObject responseObject;
+ private String from;
+
+ private Handler handler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == COMPLETED) { //绑定数据
+ try {
+ poemListAdapter = new PoemListAdapter(poetryList, getContext());
+ poemListView.setAdapter(poemListAdapter);
+ refreshLayout.finishRefresh();//结束刷新
+ refreshLayout.finishLoadMore(2000);//结束加载
+ isLoad = true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ if (message.what == TO_WEBVIEW)//跳转至网站
+ {
+ Toast.makeText(getContext(), "暂时没有数据哦,请重新选择标签", Toast.LENGTH_LONG).show();
+ }
+ }
+
+ };
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ isLoad = false;
+ poetryList.clear();
+ break;
+ }
+ return true;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_poetry_list);
+
+ // 哪种搜索类型(搜索框/标签)
+ from = getIntent().getStringExtra("from");
+
+ toolbar = findViewById(R.id.titleBar);
+ poemListView = findViewById(R.id.poemList);
+ titleText = findViewById(R.id.titleText);
+ setSupportActionBar(findViewById(R.id.titleBar));//设置toolbar
+
+ refreshLayout = findViewById(R.id.refreshLayout);
+ refreshLayout.setEnableScrollContentWhenLoaded(true);
+
+
+ poemListAdapter = new PoemListAdapter(poetryList, getContext());
+ poemListView.setAdapter(poemListAdapter);
+// poemListView.setEmptyView(findViewById(R.id.empty_imageview_iv));
+
+ getSupportActionBar().setDisplayShowTitleEnabled(false);//屏蔽toolbar默认标题显示
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setHomeAsUpIndicator(R.drawable.ic_back);
+ }//设置返回图标显示
+
+ toolbarTitle = getIntent().getStringExtra("toolBarTitle");
+ titleText.setText(toolbarTitle);
+ refreshLayout.autoRefresh();
+
+ refreshLayout.setOnRefreshListener(new OnRefreshListener() {
+ @Override
+ public void onRefresh(RefreshLayout refreshlayout) {
+ if (from.equals("collect")) {
+ String temp = getIntent().getStringExtra("collect");
+ Log.d("TEMPPPPPPPPP", temp);
+ Gson gson = new Gson();
+ List poetries = gson.fromJson(temp, new TypeToken>() {
+ }.getType());
+ poetryList = poetries;
+ poemListAdapter = new PoemListAdapter(poetryList, getContext());
+ poemListView.setAdapter(poemListAdapter);
+ refreshlayout.finishRefresh();
+ } else if (from.equals("filter")) {
+ String tag = getIntent().getStringExtra("tag");
+ String dynasty = getIntent().getStringExtra("dynasty");
+ getPoemListByTag(tag, dynasty, page, size);
+ } else if (from.equals("search")) {
+ String key = getIntent().getStringExtra("key");
+ getPoemListBySearch(key, page, size);
+ } else if (from.equals("detail")) {
+ String tag = getIntent().getStringExtra("tag");
+ getPoemListByTag(tag, "null", page, size);
+ }
+ }
+ });
+
+ refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() {
+ @Override
+ public void onLoadMore(RefreshLayout refreshlayout) {
+ if (from.equals("collect")) {
+ String temp = getIntent().getStringExtra("collect");
+ Log.d("TEMPPPPPPPPP", temp);
+ Gson gson = new Gson();
+ List poetries = gson.fromJson(temp, new TypeToken>() {
+ }.getType());
+ poetryList = poetries;
+ poemListAdapter = new PoemListAdapter(poetryList, getContext());
+ poemListView.setAdapter(poemListAdapter);
+ refreshlayout.finishRefresh();
+ refreshlayout.finishLoadMore(2000);
+ } else if (from.equals("filter")) {
+ page++;
+ String tag = getIntent().getStringExtra("tag");
+ String dynasty = getIntent().getStringExtra("dynasty");
+ getPoemListByTag(tag, dynasty, page, size);
+ } else if (from.equals("search")) {
+ page++;
+ String key = getIntent().getStringExtra("key");
+ getPoemListBySearch(key, page, size);
+ } else if (from.equals("detail")) {
+ page++;
+ String tag = getIntent().getStringExtra("tag");
+ getPoemListByTag(tag, "null", page, size);
+ }
+
+ }
+ });
+
+ poemListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ Intent intent = new Intent(PoetryListActivity.this, DetailActivity.class);
+
+ String poemText = poetryList.get(position).getContent();
+ String sentence = Spilt.spiltPoemTextByEnter(poemText)[0];
+ intent.putExtra("content", sentence);
+ intent.putExtra("toolbarTitle", poetryList.get(position).getName());
+ startActivity(intent);
+ }
+ });
+ }
+
+ //根据标签获取诗词
+ private void getPoemListByTag(String tag, String dynasty, Integer page, Integer size) {
+ String searchByTag_url = constant.poetry_IP;
+
+ //步骤五:构建Retrofit实例
+ SearchByTagRetrofit = new Retrofit.Builder()
+ //设置网络请求BaseUrl地址
+ .baseUrl(searchByTag_url)
+ //设置数据解析器
+ .addConverterFactory(GsonConverterFactory.create())
+ .build();
+
+ //步骤六:创建网络请求接口对象实例
+ Api poetryApi = SearchByTagRetrofit.create(Api.class);
+
+ //步骤七:对发送请求进行封装,传入接口参数
+ retrofit2.Call poetryDataCall = poetryApi.getPoetrysByTag(dynasty, tag, page, size);
+
+ //步骤八:发送网络请求(同步)
+ Log.e(TAG, "post == url:" + poetryDataCall.request().url());
+ new Thread(new Runnable() { //Android主线程不能操作网络请求,所以new一个线程来操作
+ @Override
+ public void run() {
+ poetryDataCall.enqueue(new Callback() {
+ @Override
+ public void onResponse(retrofit2.Call call, Response response) {
+ String responseData = null;
+ try {
+ responseData = response.body().string();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ parseJSONWithGSON(responseData);
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+ Toast.makeText(PoetryListActivity.this, "get回调失败", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }).start();
+ }
+
+ //根据搜索关键字获取诗词
+ private void getPoemListBySearch(String key, Integer page, Integer size) {
+ String search_url = constant.poetry_IP;
+
+ //步骤五:构建Retrofit实例
+ SearchRetrofit = new Retrofit.Builder()
+ //设置网络请求BaseUrl地址
+ .baseUrl(search_url)
+ //设置数据解析器
+ .addConverterFactory(GsonConverterFactory.create())
+ .build();
+
+ //步骤六:创建网络请求接口对象实例
+ Api poetryApi = SearchRetrofit.create(Api.class);
+
+ //步骤七:对发送请求进行封装,传入接口参数
+ retrofit2.Call poetryDataCall = poetryApi.getPoetrys(key, page, size);
+
+ //步骤八:发送网络请求(同步)
+ Log.e(TAG, "post == url:" + poetryDataCall.request().url());
+ new Thread(new Runnable() { //Android主线程不能操作网络请求,所以new一个线程来操作
+ @Override
+ public void run() {
+ poetryDataCall.enqueue(new Callback() {
+ @Override
+ public void onResponse(retrofit2.Call call, Response response) {
+ String responseData = null;
+ try {
+ responseData = response.body().string();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ parseJSONWithGSON(responseData);
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+ Toast.makeText(PoetryListActivity.this, "get回调失败", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }).start();
+ }
+
+ private void parseJSONWithGSON(String jsonData) {
+ Gson gson = new Gson();
+ List list = gson.fromJson(jsonData, new TypeToken>(){}.getType());
+ if (list.size() != 0)//数据获取成功
+ {
+ poetryList.addAll(list);
+ Message message = new Message();
+ message.what = COMPLETED;
+ handler.sendMessage(message);
+ } else//没有数据
+ {
+ Message message = new Message();
+ message.what = TO_WEBVIEW;
+ handler.sendMessage(message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/RegisterActivity.java b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/RegisterActivity.java
new file mode 100644
index 0000000..11d26fe
--- /dev/null
+++ b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/RegisterActivity.java
@@ -0,0 +1,196 @@
+package com.example.myapplication.Activity;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.StrictMode;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.example.myapplication.Api.Api;
+import com.example.myapplication.Constant.constant;
+import com.example.myapplication.R;
+
+import java.io.IOException;
+
+import okhttp3.FormBody;
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+public class RegisterActivity extends AppCompatActivity {
+
+ private static final String TAG = "test";
+ public static final int MSG_LOGIN_ERR = 1; //登录错误
+ public static final int MSG_CONNET_ERR = 2; //网络链接错误
+
+ private Context context;
+ private Retrofit RegisterRetrofit;
+
+ private EditText r_number;
+ private EditText r_password;
+ private Button bt_register;
+
+ private RegisterHandler register_handler;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_register);
+
+ context = this;
+ InitView();
+ register_handler = new RegisterHandler();
+ Init();
+
+// StrictMode是指严格模式
+ if (Build.VERSION.SDK_INT > 9){
+ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.setThreadPolicy(policy);//这两句设置禁止所有检查
+ }
+ }
+
+ private void InitView() {
+ r_number = (EditText)findViewById(R.id.r_number);
+ r_password = (EditText)findViewById(R.id.r_password);
+ bt_register = (Button)findViewById(R.id.bt_register);
+ }
+
+ private void Init() {
+ //设置提示的颜色
+ r_number.setHintTextColor(getResources().getColor(R.color.white));
+ r_password.setHintTextColor(getResources().getColor(R.color.white));
+
+
+ //注册
+ bt_register.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (judge()) {
+// postData();
+ registerInfo();
+ }
+ }
+ });
+ }
+
+ /**注册*/
+ private void registerInfo(){
+ String username = r_number.getText().toString();
+ String password = r_password.getText().toString();
+
+ String register_url = constant.poetry_IP;
+
+ //步骤五:创建Retrofit对象
+ RegisterRetrofit = new Retrofit.Builder()
+ .baseUrl(register_url) // 设置网络请求baseUrl
+ .addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析
+ .build();
+
+ // 步骤六:创建网络请求接口的实例
+ Api registerApi = RegisterRetrofit.create(Api.class);
+
+ //步骤七:对发送请求进行封装:传入参数
+ Call registerCall = registerApi.getRegisterData(username, password);
+
+ //步骤八:发送网络请求(异步)
+ Log.e(TAG, "post == url:" + registerCall.request().url());
+ //请求参数
+ StringBuilder sb = new StringBuilder();
+ if (registerCall.request().body() instanceof FormBody) {
+ FormBody body = (FormBody) registerCall.request().body();
+ for (int i = 0; i < body.size(); i++) {
+ sb.append(body.encodedName(i))
+ .append(" = ")
+ .append(body.encodedValue(i))
+ .append(",");
+ }
+ sb.delete(sb.length() - 1, sb.length());
+ Log.e(TAG, "RequestParams:{" + sb.toString() + "}");
+ }
+
+ registerCall.enqueue(new Callback() {
+ //请求成功时回调
+ @Override
+ public void onResponse(Call call, Response response) {
+ //步骤九:请求处理,输出结果
+ String date = null;
+ try {
+ date = response.body().string();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ if(date.equals("success")){
+ Toast.makeText(RegisterActivity.this, "注册成功", Toast.LENGTH_SHORT).show();
+ startActivity(new Intent(RegisterActivity.this, LoginActivity.class));
+ }else {
+ Toast.makeText(RegisterActivity.this, "注册失败,该用户名已被使用", Toast.LENGTH_SHORT).show();
+ }
+
+ }
+
+ //请求失败时回调
+ @Override
+ public void onFailure(Call call, Throwable throwable) {
+ Log.e(TAG, "post回调失败:" + throwable.getMessage() + "," + throwable.toString());
+ Toast.makeText(RegisterActivity.this, "post回调失败", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+
+ //判断登录信息是否合法
+ private boolean judge() {
+ if (TextUtils.isEmpty(r_number.getText().toString()) ) {
+ Toast.makeText(context, "用户名不能为空",Toast.LENGTH_SHORT).show();
+ return false;
+ } else if (TextUtils.isEmpty(r_password.getText().toString())) {
+ Toast.makeText(context, "用户ID不能为空",Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ return true;
+ }
+
+ /**事件捕获*/
+ class RegisterHandler extends Handler {
+ @Override
+ public void dispatchMessage(Message msg) {
+ super.dispatchMessage(msg);
+ switch (msg.what) {
+ case MSG_LOGIN_ERR:
+ r_number.setText("");
+ r_password.setText("");
+ r_number.requestFocus();
+
+ new AlertDialog.Builder(RegisterActivity.this)
+ .setTitle("注意")
+ .setMessage("用户名或密码输入不正确,请重新输入")
+ .setPositiveButton("确定",null)
+ .create()
+ .show();
+ bt_register.setEnabled(true);
+ break;
+ case MSG_CONNET_ERR:
+ new AlertDialog.Builder(RegisterActivity.this)
+ .setTitle("注意")
+ .setMessage("网络连接错误,请检查网络")
+ .setPositiveButton("确定",null)
+ .create()
+ .show();
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/TestActivity.java b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/TestActivity.java
new file mode 100644
index 0000000..275c76d
--- /dev/null
+++ b/src/MyApplication/app/src/main/java/com/example/myapplication/Activity/TestActivity.java
@@ -0,0 +1,398 @@
+package com.example.myapplication.Activity;
+
+
+import android.Manifest;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
+import com.example.myapplication.Api.ToTrans;
+import com.example.myapplication.Modal.EmotionResBean;
+import com.example.myapplication.Modal.PrivateInfo;
+import com.example.myapplication.R;
+import com.example.myapplication.Util.Spilt;
+import com.github.mikephil.charting.charts.HorizontalBarChart;
+import com.github.mikephil.charting.components.XAxis;
+import com.github.mikephil.charting.components.YAxis;
+import com.github.mikephil.charting.data.BarData;
+import com.github.mikephil.charting.data.BarDataSet;
+import com.github.mikephil.charting.data.BarEntry;
+import com.github.mikephil.charting.formatter.IndexAxisValueFormatter;
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.tencent.taisdk.TAIError;
+import com.tencent.taisdk.TAIOralEvaluation;
+import com.tencent.taisdk.TAIOralEvaluationData;
+import com.tencent.taisdk.TAIOralEvaluationEvalMode;
+import com.tencent.taisdk.TAIOralEvaluationFileType;
+import com.tencent.taisdk.TAIOralEvaluationListener;
+import com.tencent.taisdk.TAIOralEvaluationParam;
+import com.tencent.taisdk.TAIOralEvaluationRet;
+import com.tencent.taisdk.TAIOralEvaluationServerType;
+import com.tencent.taisdk.TAIOralEvaluationStorageMode;
+import com.tencent.taisdk.TAIOralEvaluationTextMode;
+import com.tencent.taisdk.TAIOralEvaluationWord;
+import com.tencent.taisdk.TAIOralEvaluationWorkMode;
+import com.tencent.taisdk.TAIRecorderParam;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import okhttp3.MediaType;
+import okhttp3.MultipartBody;
+import okhttp3.RequestBody;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+public class TestActivity extends AppCompatActivity {
+
+ TAIOralEvaluation oralEvaluation ;
+ TextView content;
+ TextView author;
+ TextView title;
+ TextView oralResult;
+ Button viewAns ;
+ TAIOralEvaluationParam param;
+ String[] criterion = {"评分标准","发音标准","流利度","发音完整度"};
+ HorizontalBarChart ratings ;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_test);
+
+ requestPermission();
+ initView();
+ settingsOfChat();
+ setPoem();
+ ratings.setVisibility(View.INVISIBLE);
+ //点击查看答案,显示诗句内容
+ viewAns.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ content.setVisibility(View.VISIBLE);
+ }
+ });
+ }
+
+
+ public void onRecord(View view){
+ Button button = (Button) view;
+ oralResult.setText("");
+ if(oralEvaluation == null){
+ oralEvaluation = new TAIOralEvaluation();
+ }
+ if (oralEvaluation.isRecording()){
+ button.setText("开始测试");
+ oralEvaluation.stopRecordAndEvaluation();
+ }else {
+ button.setText("停止录制");
+ oralEvaluation.setListener(new TAIOralEvaluationListener() {
+ @Override
+ public void onEvaluationData(TAIOralEvaluationData data, TAIOralEvaluationRet result) {
+ /**
+ * 中间结果
+ * 解析result中的评估结果
+ */
+ System.out.println("middle");
+ }
+
+ @Override
+ public void onEvaluationError(TAIOralEvaluationData data, TAIError error) {
+ //调用接口失败,提升信号不好或账号已欠费
+ System.out.println("error");
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Gson gson = new Gson();
+ String retString = gson.toJson(error);
+ String errorStr = "onEvaluationE rror: " + retString + " seqId: " + data.seqId;
+ }
+ });
+ }
+
+ @Override
+ public void onFinalEvaluationData(TAIOralEvaluationData data, TAIOralEvaluationRet result) {
+ //提交服务端,情感分析
+ submitMp3(param.audioPath);
+ /**
+ * 最终结果
+ * 处理每个字是否有念或读音正确
+ */
+ List list = result.words;
+ String text = String.valueOf(content.getText());
+ //部分文字改变颜色
+ //这里注意一定要先给textview赋值
+ SpannableStringBuilder builder = new SpannableStringBuilder(text);
+ int curr = 0,size = text.length();
+ for (TAIOralEvaluationWord word : list) {
+ /**
+ * 处理没有读 -1
+ * 处理念错字 <0.5 || 0.7
+ */
+ ForegroundColorSpan miss = new ForegroundColorSpan(getResources().getColor(R.color.toast_error_color));
+ ForegroundColorSpan worry = new ForegroundColorSpan(getResources().getColor(R.color.toast_error_color));
+ ForegroundColorSpan right = new ForegroundColorSpan(getResources().getColor(R.color.black));
+ if(word.pronAccuracy <= -1){
+ builder.setSpan(miss,curr,curr+1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
+ }else if(word.pronAccuracy <= 0.5){
+ builder.setSpan(worry,curr,curr+1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
+ }else {
+ builder.setSpan(right,curr,curr+1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
+ }
+ curr++;
+ while(curr < text.length() && isChinesePunctuation(text.charAt(curr))){
+ curr++;
+ }
+ }
+ /**
+ * 解析口语分数
+ */
+ Gson gson = new Gson();
+ String retString = gson.toJson(result);
+ String ans = "";
+ JsonParser parser = new JsonParser();
+ JsonElement JsonTree = parser.parse(retString);
+ double SuggestedScore,PronAccuracy = 0,PronFluency = 0,PronCompletion = 0;
+ if(JsonTree.isJsonObject()){
+ JsonObject jsonObject = JsonTree.getAsJsonObject();
+ SuggestedScore = jsonObject.get("SuggestedScore").getAsDouble();
+ ans += "评分: "+SuggestedScore+"\n";
+ PronAccuracy = jsonObject.get("PronAccuracy").getAsDouble();
+// ans += "PronAccuracy: "+PronAccuracy+"\n";
+ PronFluency = jsonObject.get("PronFluency").getAsDouble();
+// ans += "PronFluency: "+PronFluency+"\n";
+ PronCompletion = jsonObject.get("PronCompletion").getAsDouble();
+// ans += "PronCompletion: "+PronCompletion+"\n";
+ }
+
+ String finalAns = ans;
+ int finalPronAccuracy = (int) (PronAccuracy);
+ int finalPronFluency = (int) (PronFluency*100);
+ int finalPronCompletion = (int) (PronCompletion*100);
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ //图表设置
+ Listlist=new ArrayList<>();
+ list.add(new BarEntry(1, finalPronAccuracy));
+ list.add(new BarEntry(2, finalPronFluency));
+ list.add(new BarEntry(3, finalPronCompletion));
+
+ BarDataSet barDataSet=new BarDataSet(list,"口语分析");
+ BarData barData=new BarData(barDataSet);
+ barData.setDrawValues(true);
+ ratings.setVisibility(View.VISIBLE);
+ ratings.setData(barData);
+ ratings.animateY(3000);
+
+ content.setText(builder);
+ content.setVisibility(View.VISIBLE);
+ oralResult.append(finalAns);
+// oralResult.append(retString);
+ }
+ });
+ }
+
+ @Override
+ public void onEndOfSpeech(boolean isSpeak) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ onRecord(null);
+ }
+ });
+ }
+
+ @Override
+ public void onVolumeChanged(int volume) {
+ ;
+ }
+ });
+ param = new TAIOralEvaluationParam();
+ param.context = this;
+ param.sessionId = UUID.randomUUID().toString();
+ param.appId = PrivateInfo.appId;
+ param.soeAppId = PrivateInfo.soeAppId;
+ param.secretId = PrivateInfo.secretId;
+ param.secretKey = PrivateInfo.secretKey;
+ param.token = PrivateInfo.token;
+
+ int evalMode = TAIOralEvaluationEvalMode.PARAGRAPH;
+ param.workMode = TAIOralEvaluationWorkMode.ONCE ;
+ param.evalMode = evalMode;
+ param.storageMode = TAIOralEvaluationStorageMode.DISABLE;
+ param.fileType = TAIOralEvaluationFileType.MP3;
+ param.serverType = TAIOralEvaluationServerType.CHINESE ;
+ param.textMode = TAIOralEvaluationTextMode.NORMAL ;
+ param.scoreCoeff = 2.0;
+ param.refText = content.getText().toString();
+ param.audioPath = this.getFilesDir() + "/" + param.sessionId + ".mp3";
+ if (param.workMode == TAIOralEvaluationWorkMode.STREAM) {
+ param.timeout = 5;
+ param.retryTimes = 5;
+ } else {
+ param.timeout = 30;
+ param.retryTimes = 0;
+ }
+ TAIRecorderParam recordParam = new TAIRecorderParam();
+ recordParam.fragSize = (int) (1.0 * 1024);
+ recordParam.fragEnable = false;
+ recordParam.vadEnable = true;
+ recordParam.vadInterval = Integer.parseInt("5000");
+ oralEvaluation.setRecorderParam(recordParam);
+ oralEvaluation.startRecordAndEvaluation(param);
+ }
+ }
+
+ private void requestPermission() {
+ if (ContextCompat.checkSelfPermission(this,
+ Manifest.permission.RECORD_AUDIO)
+ != PackageManager.PERMISSION_GRANTED) {
+ ActivityCompat.requestPermissions(this,
+ new String[]{Manifest.permission.RECORD_AUDIO},
+ 1234);
+ }
+ }
+
+ public boolean isChinesePunctuation(char c) {
+ Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
+ if (ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
+ || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
+ || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
+ || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS
+ || ub == Character.UnicodeBlock.VERTICAL_FORMS) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ void submitMp3(String filePath){
+ File file = new File(filePath);
+ Retrofit retrofit = new Retrofit.Builder()
+ .baseUrl("http://101.33.242.218:8081")
+ .addConverterFactory(GsonConverterFactory.create())
+ .build();
+ ToTrans request = retrofit.create(ToTrans.class);
+ //请求体
+ MultipartBody.Builder builder = new MultipartBody.Builder()
+ .setType(MultipartBody.FORM);
+ RequestBody requestBody = RequestBody.create(MediaType.parse("audio/mpeg"),file);
+ builder.addFormDataPart("file", file.getName(), requestBody);
+ List parts = builder.build().parts();
+ //对 发送请求 进行封装
+ Call call = request.getCall(parts);
+ call.enqueue(new Callback() {
+ //请求成功时回调
+ @Override
+ public void onResponse(Call call, Response response) {
+ //请求处理,输出结果
+ System.out.println(response.body());
+ Gson gson = new Gson();
+ EmotionResBean resBean = response.body();
+ String emotion = resBean.getEmotion();
+ if(emotion.equals("neutral")||emotion.equals("calm")) {
+ oralResult.append("看看赏析,再体会诗中的情感");
+ }else {
+ oralResult.append("声情并茂呢");
+ }
+ }
+ //请求失败时候的回调
+ @Override
+ public void onFailure(Call call, Throwable throwable) {
+ System.out.println((call.request().body()));
+ System.out.println("连接失败");
+ }
+ });
+ }
+
+ void initView(){
+ content = findViewById(R.id.content);
+ oralResult = findViewById(R.id.result);
+ ratings = findViewById(R.id.ratings);
+ viewAns = findViewById(R.id.viewAns);
+ title = findViewById(R.id.title);
+ author = findViewById(R.id.author);
+ //设置内容不可见
+ content.setVisibility(View.INVISIBLE);
+ }
+
+ void settingsOfChat(){
+ //X轴
+ XAxis xAxis=ratings.getXAxis();
+ xAxis.setDrawGridLines(false); //是否绘制X轴上的网格线(背景里面的竖线)
+ xAxis.setAxisLineColor(Color.BLACK); //X轴颜色
+ xAxis.setAxisLineWidth(2); //X轴粗细
+ xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); //X轴所在位置 默认为上面
+ xAxis.setValueFormatter(new IndexAxisValueFormatter(criterion));
+ xAxis.setAxisMaximum(4); //X轴最大数值
+ xAxis.setAxisMinimum(0); //X轴最小数值
+ //X轴坐标的个数 第二个参数一般填false true表示强制设置标签数 可能会导致X轴坐标显示不全等问题
+ xAxis.setLabelCount(4,false);
+ xAxis.setAvoidFirstLastClipping(true);
+
+ //Y轴
+ YAxis AxisLeft=ratings.getAxisRight();
+ AxisLeft.setDrawGridLines(false); //是否绘制Y轴上的网格线(背景里面的横线)
+ AxisLeft.setAxisLineColor(Color.BLACK); //Y轴颜色
+ AxisLeft.setAxisLineWidth(2); //Y轴粗细
+// AxisLeft.setValueFormatter(new DefaultAxisValueFormatter(100));
+ AxisLeft.setAxisMaximum(105f); //Y轴最大数值
+ AxisLeft.setAxisMinimum(0f); //Y轴最小数值
+ //Y轴坐标的个数 第二个参数一般填false true表示强制设置标签数 可能会导致X轴坐标显示不全等问题
+ AxisLeft.setLabelCount(5,false);
+
+ AxisLeft=ratings.getAxisLeft();
+ AxisLeft.setDrawGridLines(false); //是否绘制Y轴上的网格线(背景里面的横线)
+ AxisLeft.setAxisLineColor(Color.BLACK); //Y轴颜色
+ AxisLeft.setAxisLineWidth(2); //Y轴粗细
+// AxisLeft.setValueFormatter(new DefaultAxisValueFormatter(100));
+ AxisLeft.setAxisMaximum(105f); //Y轴最大数值
+ AxisLeft.setAxisMinimum(0f); //Y轴最小数值
+ //Y轴坐标的个数 第二个参数一般填false true表示强制设置标签数 可能会导致X轴坐标显示不全等问题
+ AxisLeft.setLabelCount(5,false);
+
+
+
+ //是否隐藏右边的Y轴(不设置的话有两条Y轴 同理可以隐藏左边的Y轴)
+ ratings.getDescription().setEnabled(false);//隐藏右下角英文
+ ratings.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);//X轴的位置 默认为右边
+ ratings.getAxisLeft().setEnabled(false);//隐藏上侧Y轴 默认是上下两侧都有Y轴
+ ratings.setTouchEnabled(false);//不可调整大小
+ }
+
+ void setPoem(){
+ //获取活动跳转传过来的诗,并显示在界面(诗内容不显示)
+ Intent intent = getIntent();
+ title.setText(intent.getStringExtra("title"));
+
+ String dynasty_author = intent.getStringExtra("desty") + " . "
+ + intent.getStringExtra("author");
+ author.setText(dynasty_author);
+
+ String contentText = intent.getStringExtra("content");
+
+ contentText = Spilt.spiltContentText(contentText);
+ content.setText(contentText);
+ }
+
+}
\ No newline at end of file
diff --git a/src/MyApplication/app/src/main/java/com/example/myapplication/Adapter/MsgAdapter.java b/src/MyApplication/app/src/main/java/com/example/myapplication/Adapter/MsgAdapter.java
new file mode 100644
index 0000000..7596301
--- /dev/null
+++ b/src/MyApplication/app/src/main/java/com/example/myapplication/Adapter/MsgAdapter.java
@@ -0,0 +1,151 @@
+package com.example.myapplication.Adapter;
+
+import android.media.MediaPlayer;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.example.myapplication.Modal.ClientMessageBean;
+import com.example.myapplication.Modal.SystemMessageBean;
+import com.example.myapplication.R;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+public class MsgAdapter extends RecyclerView.Adapter {
+ private List mMsgList;
+ private MediaPlayer mPlayer;
+ static class ViewHolder extends RecyclerView.ViewHolder{
+
+ LinearLayout leftLayout;
+ LinearLayout rightLayout;
+ LinearLayout centerLayout;
+ LinearLayout voiceRightLayout;
+ LinearLayout voiceLeftLayout;
+ TextView leftMsg;
+ TextView rightMsg;
+ TextView centerMsg;
+ ImageButton broadcastRight;
+ ImageButton broadcastLeft;
+ public ViewHolder(View view){
+ super(view);
+ leftLayout = view.findViewById(R.id.left_layout);
+ rightLayout = view.findViewById(R.id.right_layout);
+ centerLayout = view.findViewById(R.id.center_layout);
+ leftMsg = view.findViewById(R.id.left_msg);
+ rightMsg = view.findViewById(R.id.right_msg);
+ centerMsg = view.findViewById(R.id.center_msg);
+ voiceLeftLayout = view.findViewById(R.id.voice_order);
+ voiceRightLayout = view.findViewById(R.id.voice_self);
+ broadcastLeft = view.findViewById(R.id.record_order);
+ broadcastRight = view.findViewById(R.id.record_self);
+ }
+ }
+
+ public MsgAdapter(List msgList, MediaPlayer mPlayer){
+ mMsgList = msgList;
+ this.mPlayer = mPlayer;
+ }
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
+ View view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.message_view,parent,false);
+ return new ViewHolder(view);
+ }
+ @Override
+ public void onBindViewHolder(ViewHolder holder,int position){
+ ClientMessageBean msg = mMsgList.get(position);
+ if (msg.getType() == 2){
+ //如果收到消息,则显示在左边,将右边,中间布局隐藏
+ holder.leftLayout.setVisibility(View.VISIBLE);
+ holder.centerLayout.setVisibility(View.GONE);
+ holder.rightLayout.setVisibility(View.GONE);
+ //语音隐藏
+ holder.voiceRightLayout.setVisibility(View.GONE);
+ holder.voiceLeftLayout.setVisibility(View.GONE);
+ holder.leftMsg.setText(msg.getMessage());
+ }else if(msg.getType() == 1){
+ //将左,中布局隐藏
+ holder.rightLayout.setVisibility(View.VISIBLE);
+ holder.centerLayout.setVisibility(View.GONE);
+ holder.leftLayout.setVisibility(View.GONE);
+ holder.voiceRightLayout.setVisibility(View.GONE);
+ holder.voiceLeftLayout.setVisibility(View.GONE);
+ holder.rightMsg.setText(msg.getMessage());
+ }else if(msg.getType() == 0){
+ //隐藏左右布局
+ holder.centerLayout.setVisibility(View.VISIBLE);
+ holder.leftLayout.setVisibility(View.GONE);
+ holder.rightLayout.setVisibility(View.GONE);
+ holder.voiceRightLayout.setVisibility(View.GONE);
+ holder.voiceLeftLayout.setVisibility(View.GONE);
+ holder.centerMsg.setText(msg.getMessage());
+ } else if (msg.getType() == 3) {
+ holder.leftLayout.setVisibility(View.GONE);
+ holder.rightLayout.setVisibility(View.GONE);
+ holder.centerLayout.setVisibility(View.GONE);
+ holder.voiceRightLayout.setVisibility(View.VISIBLE);
+ holder.voiceLeftLayout.setVisibility(View.GONE);
+ try {
+ holder.broadcastRight.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mPlayer.reset();
+ mPlayer.setDataSource(msg.getMessage());
+ mPlayer.prepare();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ mPlayer.start();
+ }
+ }).start();
+ }
+ });
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ } else if (msg.getType() == 4) {
+ holder.leftLayout.setVisibility(View.GONE);
+ holder.rightLayout.setVisibility(View.GONE);
+ holder.centerLayout.setVisibility(View.GONE);
+ holder.voiceRightLayout.setVisibility(View.GONE);
+ holder.voiceLeftLayout.setVisibility(View.VISIBLE);
+ try {
+ holder.broadcastRight.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mPlayer.reset();
+ mPlayer.setDataSource(msg.getMessage());
+ mPlayer.prepare();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ mPlayer.start();
+ }
+ }).start();
+ }
+ });
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ @Override
+ public int getItemCount(){
+ return mMsgList.size();
+ }
+
+}
diff --git a/src/MyApplication/app/src/main/java/com/example/myapplication/Adapter/PoemListAdapter.java b/src/MyApplication/app/src/main/java/com/example/myapplication/Adapter/PoemListAdapter.java
new file mode 100644
index 0000000..3d19281
--- /dev/null
+++ b/src/MyApplication/app/src/main/java/com/example/myapplication/Adapter/PoemListAdapter.java
@@ -0,0 +1,75 @@
+package com.example.myapplication.Adapter;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import com.example.myapplication.R;
+import com.example.myapplication.Modal.Poetry;
+import com.example.myapplication.Util.Spilt;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PoemListAdapter extends BaseAdapter {
+ private List poetryList = new ArrayList();
+ private Context context;
+
+ public PoemListAdapter(List poetryList, Context context) {
+
+ this.poetryList = poetryList;
+ this.context = context;
+ }
+
+ @Override
+ public int getCount() {
+ return poetryList.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return poetryList.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ViewHolder viewHolder = null;
+ Log.d("ListViewLoading", "--------------------------------------------");
+ if (convertView == null) {
+ viewHolder = new ViewHolder();
+ convertView = View.inflate(context, R.layout.poem_item, null);
+ viewHolder.author = convertView.findViewById(R.id.poem_author);
+ viewHolder.title = convertView.findViewById(R.id.poem_title);
+ viewHolder.contentView = convertView.findViewById(R.id.poem_content);
+ viewHolder.spiltLine = convertView.findViewById(R.id.spilt_line);
+ convertView.setTag(viewHolder);
+ } else
+ viewHolder = (ViewHolder) convertView.getTag();
+
+ viewHolder.title.setText(poetryList.get(position).getName());
+ String author = poetryList.get(position).getDynasty() + "." + poetryList.get(position).getAuthor();
+ viewHolder.author.setText(author);
+
+ String content = poetryList.get(position).getContent();
+ content = Spilt.spiltContentText(content);
+ viewHolder.contentView.setText(content);
+
+ return convertView;
+ }
+
+ public class ViewHolder {
+ public TextView title;
+ public TextView author;
+ public TextView contentView;
+ public TextView spiltLine;
+ }
+
+}
diff --git a/src/MyApplication/app/src/main/java/com/example/myapplication/Adapter/RoomAdapter.java b/src/MyApplication/app/src/main/java/com/example/myapplication/Adapter/RoomAdapter.java
new file mode 100644
index 0000000..c02d960
--- /dev/null
+++ b/src/MyApplication/app/src/main/java/com/example/myapplication/Adapter/RoomAdapter.java
@@ -0,0 +1,67 @@
+package com.example.myapplication.Adapter;
+
+import android.content.Context;
+import android.content.Intent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.example.myapplication.Activity.ChatActivity;
+import com.example.myapplication.Modal.RoomBean;
+import com.example.myapplication.R;
+
+import java.util.List;
+
+public class RoomAdapter extends RecyclerView.Adapter{
+ List mRoomList ;
+ Context mContext;
+ static class ViewHolder extends RecyclerView.ViewHolder{
+ TextView rname;
+ TextView description;
+ public ViewHolder(View view){
+ super(view);
+ rname = view.findViewById(R.id.rname);
+ description = view.findViewById(R.id.description);
+ }
+ }
+ public RoomAdapter(List list,Context context){
+ this.mRoomList = list;
+ this.mContext = context;
+ }
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.room_view,parent,false);
+ return new ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ RoomBean roomBean = mRoomList.get(position);
+ holder.rname.setText(roomBean.getRname());
+ holder.description.setText(roomBean.getDescription());
+ View.OnClickListener listener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(mContext, ChatActivity.class);
+ //用户名还需要调整
+ intent.putExtra("username", String.valueOf(Math.random()));
+ intent.putExtra("rid", roomBean.getRid());
+ mContext.startActivity(intent);
+ }
+ };
+ holder.description.setOnClickListener(listener);
+ holder.rname.setOnClickListener(listener);
+ }
+
+ @Override
+ public int getItemCount() {
+ return mRoomList.size();
+ }
+}
diff --git a/src/MyApplication/app/src/main/java/com/example/myapplication/Api/Api.java b/src/MyApplication/app/src/main/java/com/example/myapplication/Api/Api.java
new file mode 100644
index 0000000..84856c8
--- /dev/null
+++ b/src/MyApplication/app/src/main/java/com/example/myapplication/Api/Api.java
@@ -0,0 +1,53 @@
+package com.example.myapplication.Api;
+
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.http.Field;
+import retrofit2.http.FormUrlEncoded;
+import retrofit2.http.GET;
+import retrofit2.http.POST;
+import retrofit2.http.Query;
+
+/**
+ * @创建者 晏嘉琳
+ * @创建时间 2023/5/31 17:44
+ * @类描述 ${TODO}步骤四:创建网络接口类(封装Url地址和网络数据请求)
+ */
+public interface Api {
+ //这里特别说明Url的组成,retrofit把网络请求的Url分成两部分设置:第一部分在创建Retrofit实例时通过.baseUrl()设置,
+ //第二部分在网络接口注解中设置,如下面的"/user",网络请求的完整地址Url = Retrofit实例.baseUrl()+网络请求接口注解()
+
+ @GET("user/loginIn")
+ Call getData(@Query("username") String username, @Query("password") String password);
+
+ @GET("user/register")
+ Call getRegisterData(@Query("username") String username, @Query("password") String password);
+
+ @GET("poetry/getOnePoem")
+ Call getPoetry();
+
+ @GET("poetry/getByContentDetail")
+ Call getPoetryDetail(@Query("content") String content);
+
+ @GET("poetry/getBySearch")
+ Call getPoetrys(@Query("key") String key, @Query("page") Integer page, @Query("size") Integer size);
+
+ @GET("poetry/getAllDynasty")
+ Call getDynastyList();
+
+ @GET("poetry/getByTag")
+ Call getPoetrysByTag(@Query("dynasty") String dynasty, @Query("tag") String tag, @Query("page") Integer page, @Query("size") Integer size);
+
+ @GET("poetry/generate")
+ Call createPoetry(@Query("form") String form, @Query("head") String head);
+
+ //post请求
+ @FormUrlEncoded
+ @POST("api/comments.163")
+ Call