diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
new file mode 100644
index 0000000..197174c
--- /dev/null
+++ b/.idea/deploymentTargetDropDown.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index a9f4e52..a2d7c21 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -1,5 +1,6 @@
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 0d601bb..5925165 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,16 @@
-# NewBody
\ No newline at end of file
+# NewBody
+Google MLkit를 이용한 자세인식 홈트레이닝 어플(Android)
+
+# 기술 스택
+
+
+# 앱 화면
+- 시작 화면
+
+
+- 로그인 & 회원가입
+
+
+- 메뉴
+
+
diff --git a/app/build.gradle b/app/build.gradle
index 1cf2ea5..6d27cfe 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,5 +1,6 @@
plugins {
id 'com.android.application'
+ id 'com.google.gms.google-services'
}
android {
@@ -29,11 +30,54 @@ android {
}
dependencies {
-
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation 'com.google.firebase:firebase-auth-ktx:22.1.1'
+ implementation 'com.google.firebase:firebase-auth:22.1.1'
+ implementation 'com.google.firebase:firebase-firestore:24.7.1'
+ implementation 'com.google.android.gms:play-services-auth:20.6.0'
+ implementation(platform("com.google.firebase:firebase-bom:32.2.2"))
+ implementation 'com.google.firebase:firebase-analytics'
+ implementation 'com.google.firebase:firebase-database-ktx:20.2.2'
+ implementation 'com.google.firebase:firebase-storage-ktx:20.2.1'
+ implementation 'com.google.firebase:firebase-firestore-ktx:24.7.1'
+ implementation 'de.hdodenhof:circleimageview:3.1.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ implementation 'com.google.firebase:firebase-messaging:23.0.3'
+ implementation 'com.google.firebase:firebase-dynamic-links'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
+ implementation 'jp.wasabeef:glide-transformations:4.3.0'
+ implementation 'com.google.firebase:firebase-storage:20.2.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
-}
\ No newline at end of file
+ implementation 'com.google.mlkit:pose-detection-accurate:17.0.1-beta2'
+ implementation 'com.squareup.picasso:picasso:2.71828'
+ implementation 'com.google.code.gson:gson:2.10.1'
+ annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
+ implementation 'com.jakewharton:butterknife:10.2.3'
+ implementation 'com.google.guava:guava:27.0.1-android'
+
+ implementation 'com.github.bumptech.glide:glide:4.11.0'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
+ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
+
+ implementation 'com.android.volley:volley:1.2.1'
+ implementation 'com.google.code.gson:gson:2.10.1'
+
+ implementation 'io.github.bootpay:android:+'
+ implementation 'com.google.android.gms:play-services-ads:22.3.0'
+
+ def camerax_version = "1.0.0-beta07"
+ // CameraX core library using camera2 implementation
+ implementation "androidx.camera:camera-camera2:$camerax_version"
+ // CameraX Lifecycle Library
+ implementation "androidx.camera:camera-lifecycle:$camerax_version"
+ // CameraX View class
+ implementation "androidx.camera:camera-view:1.0.0-alpha14"
+}
+
+
+apply plugin: 'com.google.gms.google-services'
\ No newline at end of file
diff --git a/app/google-services.json b/app/google-services.json
new file mode 100644
index 0000000..86037a2
--- /dev/null
+++ b/app/google-services.json
@@ -0,0 +1,40 @@
+{
+ "project_info": {
+ "project_number": "1055116036920",
+ "firebase_url": "https://newbody-68ce0-default-rtdb.firebaseio.com",
+ "project_id": "newbody-68ce0",
+ "storage_bucket": "newbody-68ce0.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:1055116036920:android:1b4466be83eff432a10fcd",
+ "android_client_info": {
+ "package_name": "com.example.newbody"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "1055116036920-5s68ogbrje2iruknd5bodeifobimfek2.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyDCc8RJ5hJ1Xj_xXbYeEYeD_CzKTJmQ8-U"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "1055116036920-5s68ogbrje2iruknd5bodeifobimfek2.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2e684a3..fd2b9b9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,15 +2,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -20,6 +40,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/Calendar.java b/app/src/main/java/com/example/newbody/Calendar.java
new file mode 100644
index 0000000..f4a3be1
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Calendar.java
@@ -0,0 +1,240 @@
+package com.example.newbody;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CalendarView;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.database.DataSnapshot;
+import com.google.firebase.database.DatabaseError;
+import com.google.firebase.database.DatabaseReference;
+import com.google.firebase.database.FirebaseDatabase;
+import com.google.firebase.database.ValueEventListener;
+
+import java.util.ArrayList;
+
+
+public class Calendar extends Fragment {
+ private View view, mic_button;
+ private String readDay = null;
+ private String str = null;
+ private CalendarView calendarView;
+ private Button cha_Btn, del_Btn, save_Btn;
+ private TextView diaryTextView, textView2, textView3;
+ private EditText contextEditText;
+
+ private FirebaseAuth auth;
+
+ private FirebaseUser user;
+ private DatabaseReference databaseReference;
+
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ view = inflater.inflate(R.layout.activity_calendar, container, false);
+
+ calendarView = view.findViewById(R.id.calendarView);
+ diaryTextView = view.findViewById(R.id.diaryTextView);
+ save_Btn = view.findViewById(R.id.save_Btn);
+ del_Btn = view.findViewById(R.id.del_Btn);
+ cha_Btn = view.findViewById(R.id.cha_Btn);
+ textView2 = view.findViewById(R.id.textView2);
+ contextEditText = view.findViewById(R.id.contextEditText);
+ mic_button = view.findViewById(R.id.mic_button);
+ auth = FirebaseAuth.getInstance();
+ user = auth.getCurrentUser();
+ // Firebase 데이터베이스 참조를 초기화합니다.
+ databaseReference = FirebaseDatabase.getInstance().getReference("Calender").child(user.getUid());
+
+ // Firebase에 접근하기위한 객체 초기화
+ calendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
+ @Override
+ public void onSelectedDayChange(@NonNull CalendarView view, int year, int month, int dayOfMonth) {
+ diaryTextView.setVisibility(View.VISIBLE);
+ save_Btn.setVisibility(View.VISIBLE);
+ contextEditText.setVisibility(View.VISIBLE);
+ textView2.setVisibility(View.INVISIBLE);
+ cha_Btn.setVisibility(View.INVISIBLE);
+ del_Btn.setVisibility(View.INVISIBLE);
+ mic_button.setVisibility(View.VISIBLE);
+ diaryTextView.setText(String.format("%d / %d / %d", year, month + 1, dayOfMonth));
+ contextEditText.setText("");
+ checkDay(year, month, dayOfMonth);
+ }
+ });
+
+ mic_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ });
+
+ save_Btn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ saveDiary(readDay);
+ str = contextEditText.getText().toString();
+ textView2.setText(str);
+ save_Btn.setVisibility(View.INVISIBLE);
+ cha_Btn.setVisibility(View.VISIBLE);
+ del_Btn.setVisibility(View.VISIBLE);
+ mic_button.setVisibility(View.INVISIBLE);
+ contextEditText.setVisibility(View.INVISIBLE);
+ textView2.setVisibility(View.VISIBLE);
+ }
+ });
+ return view;
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 10000); // 10초
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 5000); // 5초
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ contextEditText.setText(str);
+ }
+ }
+ public void checkDay(int cYear, int cMonth, int cDay) {
+ readDay = "" + cYear + "-" + (cMonth + 1) + "" + "-" + cDay;
+ DatabaseReference dateRef = databaseReference.child(readDay);
+
+ dateRef.addValueEventListener(new ValueEventListener() {
+ @Override
+ public void onDataChange(@NonNull DataSnapshot snapshot) {
+ if (snapshot.exists()) {
+ // Diary entry exists for the selected date
+ String content = snapshot.getValue(String.class);
+ textView2.setText(content);
+
+ // 데이터가 있으므로 textView2를 보여주고 contextEditText를 숨깁니다.
+ textView2.setVisibility(View.VISIBLE);
+ contextEditText.setVisibility(View.INVISIBLE);
+ mic_button.setVisibility(View.INVISIBLE);
+
+ // 저장 버튼을 보여주고 수정, 삭제 버튼을 숨깁니다.
+ save_Btn.setVisibility(View.INVISIBLE);
+ cha_Btn.setVisibility(View.VISIBLE);
+ del_Btn.setVisibility(View.VISIBLE);
+ } else {
+ // Diary entry does not exist for the selected date
+ textView2.setVisibility(View.INVISIBLE);
+
+ diaryTextView.setVisibility(View.VISIBLE);
+ mic_button.setVisibility(View.VISIBLE);
+ save_Btn.setVisibility(View.VISIBLE);
+ cha_Btn.setVisibility(View.INVISIBLE);
+ del_Btn.setVisibility(View.INVISIBLE);
+ contextEditText.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public void onCancelled(@NonNull DatabaseError error) {
+ // Error occurred while fetching diary entry
+ error.toException().printStackTrace();
+ }
+ });
+
+
+
+ cha_Btn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ contextEditText.setVisibility(View.VISIBLE);
+ textView2.setVisibility(View.INVISIBLE);
+ contextEditText.setText(str);
+
+ save_Btn.setVisibility(View.VISIBLE);
+ cha_Btn.setVisibility(View.INVISIBLE);
+ del_Btn.setVisibility(View.INVISIBLE);
+ textView2.setText(contextEditText.getText());
+ }
+ });
+
+ del_Btn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ textView2.setVisibility(View.INVISIBLE);
+ contextEditText.setText("");
+ contextEditText.setVisibility(View.VISIBLE);
+ save_Btn.setVisibility(View.VISIBLE);
+ cha_Btn.setVisibility(View.INVISIBLE);
+ del_Btn.setVisibility(View.INVISIBLE);
+
+ // Remove the diary entry from Firebase Realtime Database
+ dateRef.removeValue()
+ .addOnSuccessListener(aVoid -> {
+ // Diary entry removed successfully
+ })
+ .addOnFailureListener(e -> {
+ // Error occurred while removing diary entry
+ e.printStackTrace();
+ });
+ }
+ });
+ }
+
+ @SuppressLint("WrongConstant")
+ public void saveDiary(String readDay) {
+ // Get the content from the EditText
+ String content = contextEditText.getText().toString();
+
+ DatabaseReference dateRef = databaseReference.child(readDay);
+
+ // Save the diary entry to Firebase Realtime Database
+ dateRef.setValue(content)
+ .addOnSuccessListener(aVoid -> {
+ // Diary entry saved successfully
+ })
+ .addOnFailureListener(e -> {
+ // Error occurred while saving diary entry
+ e.printStackTrace();
+ });
+ }
+
+}
+
diff --git a/app/src/main/java/com/example/newbody/CustomDialog.java b/app/src/main/java/com/example/newbody/CustomDialog.java
new file mode 100644
index 0000000..d06b224
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/CustomDialog.java
@@ -0,0 +1,44 @@
+package com.example.newbody;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.example.newbody.mainInfo.MainActivityA;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+public class CustomDialog extends Dialog {
+ private TextView txt_contents;
+ private Button shutdownClick;
+ private Context mContext;
+
+ public CustomDialog(@NonNull Context context, String contents) {
+ super(context);
+ mContext = context;
+ setContentView(R.layout.activity_custom_dialog);
+
+ txt_contents = findViewById(R.id.txt_contents);
+ txt_contents.setText(contents);
+ shutdownClick = findViewById(R.id.btn_shutdown);
+ shutdownClick.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(mContext, Record.class);
+ mContext.startActivity(intent);
+ dismiss(); // Dialog를 닫습니다.
+
+ // 해당 Dialog를 호출한 Activity를 종료합니다.
+ if (mContext instanceof Activity) {
+ ((Activity) mContext).finish();
+ }
+ }
+ });
+
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/CustomDialogNotice.java b/app/src/main/java/com/example/newbody/CustomDialogNotice.java
new file mode 100644
index 0000000..1758691
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/CustomDialogNotice.java
@@ -0,0 +1,37 @@
+package com.example.newbody;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+public class CustomDialogNotice extends Dialog {
+ private TextView txt_contents;
+ private Button shutdownClick;
+ private Context mContext;
+
+ public CustomDialogNotice(@NonNull Context context, String contents) {
+ super(context);
+ mContext = context;
+ setContentView(R.layout.activity_custom_dialog_notice);
+
+ txt_contents = findViewById(R.id.txt_contents);
+ txt_contents.setText(contents);
+ shutdownClick = findViewById(R.id.btn_shutdown);
+ shutdownClick.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+// Intent intent = new Intent(mContext, Home.class);
+// mContext.startActivity(intent);
+ dismiss(); // Dialog를 닫습니다.
+ }
+ });
+
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/FirebaseMessagingService.java b/app/src/main/java/com/example/newbody/FirebaseMessagingService.java
new file mode 100644
index 0000000..384c28e
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/FirebaseMessagingService.java
@@ -0,0 +1,46 @@
+package com.example.newbody;
+
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.core.app.NotificationCompat;
+
+import com.google.firebase.messaging.RemoteMessage;
+
+public class FirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
+
+ @Override
+ public void onMessageReceived(RemoteMessage remoteMessage) {
+ super.onMessageReceived(remoteMessage);
+
+ // 알림의 제목 및 본문을 가져옵니다.
+ String title = remoteMessage.getData().get("title_key");
+ String body = remoteMessage.getData().get("body_key");
+
+ // 가져온 제목 및 본문으로 알림을 전송합니다.
+ sendNotification(title, body);
+ }
+
+
+ private void sendNotification(String title, String body) {
+ Intent intent = new Intent(this, Notice.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ intent.putExtra("title", title);
+ intent.putExtra("body", body);
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
+
+ NotificationCompat.Builder notificationBuilder =
+ new NotificationCompat.Builder(this, "channel_id")
+ .setSmallIcon(R.mipmap.newbody_logo) // 앱 아이콘
+ .setContentTitle(title)
+ .setContentText(body)
+ .setAutoCancel(true)
+ .setContentIntent(pendingIntent);
+
+ NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+
+ notificationManager.notify(0, notificationBuilder.build());
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/FriendData.java b/app/src/main/java/com/example/newbody/FriendData.java
new file mode 100644
index 0000000..2d5b085
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/FriendData.java
@@ -0,0 +1,101 @@
+package com.example.newbody;
+
+public class FriendData {
+ private String name;
+ private String birth;
+ private String gender;
+ private String weight;
+
+ private String height;
+ private String fcmToken;
+
+ public String getFcmToken() {
+ return fcmToken;
+ }
+
+ public void setFcmToken(String fcmToken) {
+ this.fcmToken = fcmToken;
+ }
+
+ private String imageUrl;
+ public String getUid() {
+ return uid;
+ }
+
+ public void setUid(String uid) {
+ this.uid = uid;
+ }
+
+ private String uid;
+
+ public String getStatus() {
+ return status;
+ }
+
+ public String getImageUrl() {
+ return imageUrl;
+ }
+
+ public void setImageUrl(String imageUrl) {
+ this.imageUrl = imageUrl;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ private String status;
+
+ public FriendData() {
+
+ }
+
+ public FriendData(String name, String birth, String uid) {
+ this.name = name;
+ this.birth = birth;
+ this.uid = uid;
+ }
+
+ public String getGender() {
+ return gender;
+ }
+
+ public void setGender(String gender) {
+ this.gender = gender;
+ }
+
+ public String getWeight() {
+ return weight;
+ }
+
+ public void setWeight(String weight) {
+ this.weight = weight;
+ }
+
+ public String getHeight() {
+ return height;
+ }
+
+ public void setHeight(String height) {
+ this.height = height;
+ }
+
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getBirth() {
+ return birth;
+ }
+
+ public void setBirth(String birth) {
+ this.birth = birth;
+ }
+
+}
diff --git a/app/src/main/java/com/example/newbody/FriendInvite.java b/app/src/main/java/com/example/newbody/FriendInvite.java
new file mode 100644
index 0000000..52e7852
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/FriendInvite.java
@@ -0,0 +1,115 @@
+package com.example.newbody;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.Manifest;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.example.newbody.FriendInviteContact;
+import com.example.newbody.R;
+import com.example.newbody.RecyclerViewAdapterInvite;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FriendInvite extends AppCompatActivity {
+ private Button prev;
+ private Button searchBtn;
+
+ String searchOption = "name";
+ private RecyclerView recyclerView;
+ TextView textView;
+ private EditText searchEditText;
+ private RecyclerViewAdapter recyclerViewAdapter;
+ private RecyclerViewAdapterInvite adapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_friend_invite);
+
+ prev = findViewById(R.id.prevButtonFriendInvite2);
+ recyclerView = findViewById(R.id.recyclerView2);
+ searchBtn = findViewById(R.id.searchBtn2);
+ textView = findViewById(R.id.textView2);
+ searchEditText = findViewById(R.id.searchWord2);
+ recyclerViewAdapter = new RecyclerViewAdapter();
+ // 연락처 데이터를 읽어와서 contactList에 저장
+ List contactList = getContactList();
+
+ // RecyclerViewAdapterInvite 어댑터를 초기화하고 리사이클러뷰에 설정
+ adapter = new RecyclerViewAdapterInvite(this, contactList);
+ recyclerView.setAdapter(adapter);
+
+ // 리사이클러뷰에 LinearLayoutManager 설정 (세로 방향)
+ LinearLayoutManager layoutManager = new LinearLayoutManager(this);
+ recyclerView.setLayoutManager(layoutManager);
+
+ // (옵션) 리사이클러뷰에 구분선 추가
+ DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
+ layoutManager.getOrientation());
+ recyclerView.addItemDecoration(dividerItemDecoration);
+
+ textView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ searchOption = "name";
+ }
+ });
+ searchBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String searchWord = searchEditText.getText().toString();
+ String searchOption = "name";
+ adapter.performSearch(searchWord, searchOption); // 수정된 부분
+ if (adapter.getItemCount() == 0) {
+ Toast.makeText(FriendInvite.this, "존재하지 않는 이름입니다.", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ }
+ });
+ }
+
+ private List getContactList() {
+ List contactList = new ArrayList<>();
+
+ // 연락처 데이터를 읽어오는 코드
+ Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
+ null, null, null, null);
+
+ if (cursor != null) {
+ while (cursor.moveToNext()) {
+ String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
+ String phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
+ FriendInviteContact contact = new FriendInviteContact(name, phoneNumber);
+ contactList.add(contact);
+ }
+ cursor.close();
+ }
+
+ return contactList;
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/FriendInviteContact.java b/app/src/main/java/com/example/newbody/FriendInviteContact.java
new file mode 100644
index 0000000..9a202fe
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/FriendInviteContact.java
@@ -0,0 +1,20 @@
+package com.example.newbody;
+
+//연락처 가져오기
+public class FriendInviteContact {
+ private String name;
+ private String phoneNumber;
+
+ public FriendInviteContact(String name, String phoneNumber) {
+ this.name = name;
+ this.phoneNumber = phoneNumber;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPhoneNumber() {
+ return phoneNumber;
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/FriendList.java b/app/src/main/java/com/example/newbody/FriendList.java
new file mode 100644
index 0000000..d2ead5a
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/FriendList.java
@@ -0,0 +1,164 @@
+package com.example.newbody;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.util.Base64;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.example.newbody.FriendData;
+import com.google.firebase.firestore.FirebaseFirestore;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+
+public class FriendList extends AppCompatActivity {
+
+ TextView textView;
+ private FirebaseFirestore firestore;
+ String searchOption = "name";
+
+ private Button searchBtn;
+ private EditText searchEditText;
+
+ private RecyclerViewAdapter recyclerViewAdapter;
+ private Button prev;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_friend_list);
+
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+
+ searchBtn = findViewById(R.id.searchBtn);
+ searchEditText = findViewById(R.id.searchWord);
+ textView = findViewById(R.id.textView);
+ prev = findViewById(R.id.prevButtonFriendAdd);
+
+ // 파이어스토어 인스턴스 초기화
+ firestore = FirebaseFirestore.getInstance();
+
+ recyclerViewAdapter = new RecyclerViewAdapter();
+ RecyclerView recyclerView = findViewById(R.id.recyclerview);
+ recyclerView.setLayoutManager(new LinearLayoutManager(this));
+ recyclerView.setAdapter(recyclerViewAdapter);
+
+ textView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ searchOption = "name";
+ }
+ });
+
+ searchBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String searchWord = searchEditText.getText().toString();
+ String searchOption = "name";
+ recyclerViewAdapter.performSearch(searchWord, searchOption);
+ if (recyclerViewAdapter.getItemCount() == 0) {
+ Toast.makeText(FriendList.this, "존재하지 않는 이름입니다.", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ }
+ });
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("이전")){
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 10000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 3000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/FriendListPlus.java b/app/src/main/java/com/example/newbody/FriendListPlus.java
new file mode 100644
index 0000000..370f550
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/FriendListPlus.java
@@ -0,0 +1,163 @@
+package com.example.newbody;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+
+import com.example.newbody.FriendData;
+import com.example.newbody.R;
+import com.example.newbody.RecyclerViewAdapterPlus;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.Query;
+import com.google.firebase.firestore.QueryDocumentSnapshot;
+
+import java.util.ArrayList;
+
+public class FriendListPlus extends AppCompatActivity {
+
+ private RecyclerView mRecyclerView;
+ private RecyclerViewAdapterPlus mRecyclerAdapter;
+ private FirebaseFirestore db;
+
+ private Button FriendRequestBt;
+ private Button prev;
+
+ private Button DeleteBtn;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_friend_list11);
+
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+
+ mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
+
+ mRecyclerAdapter = new RecyclerViewAdapterPlus();
+
+ prev = findViewById(R.id.prevButtonFriendList);
+ DeleteBtn = findViewById(R.id.deleteBtn);
+ mRecyclerView.setAdapter(mRecyclerAdapter);
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+
+ db = FirebaseFirestore.getInstance();
+ String currentUid = FirebaseAuth.getInstance().getCurrentUser().getUid();
+ db.collection("users").document(currentUid)
+ .collection("friends")
+ .get()
+ .addOnSuccessListener(queryDocumentSnapshots -> {
+ ArrayList friendList = new ArrayList<>();
+ for (QueryDocumentSnapshot document : queryDocumentSnapshots) {
+ FriendData friend = document.toObject(FriendData.class);
+ friendList.add(friend);
+ }
+ mRecyclerAdapter.setFriendList(friendList);
+ })
+ .addOnFailureListener(e -> {
+ // 실패 처리
+ });
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ }
+ });
+ DeleteBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ // 삭제 버튼이 눌렸을 때의 동작
+ String currentUserUid = FirebaseAuth.getInstance().getCurrentUser().getUid();
+ mRecyclerAdapter.deleteSelectedItems(currentUserUid);
+ }
+ });
+
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("이전")){
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 10000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 3000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/Graph.java b/app/src/main/java/com/example/newbody/Graph.java
new file mode 100644
index 0000000..277e954
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Graph.java
@@ -0,0 +1,537 @@
+package com.example.newbody;
+
+import android.app.Activity;
+import android.app.DatePickerDialog;
+import android.app.Dialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Color;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.DatePicker;
+import android.widget.NumberPicker;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.DialogFragment;
+
+import com.github.mikephil.charting.charts.Chart;
+import com.github.mikephil.charting.charts.LineChart;
+import com.github.mikephil.charting.data.Entry;
+import com.github.mikephil.charting.data.LineData;
+import com.github.mikephil.charting.data.LineDataSet;
+import com.github.mikephil.charting.formatter.ValueFormatter;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+public class Graph extends AppCompatActivity implements OnDateSetListener {
+
+ private Button exerciseGraph, exerciseRange, graphView, prev, selectCalendar;
+ private Chart chartView, chartView2;
+ private String select_ex, select_range;
+ private FirebaseFirestore db;
+ private FirebaseUser user;
+ private LineChart chart, chart2;
+ private TextView dateSelect;
+ private View dateView;
+ SimpleDateFormat yy, mm;
+ Date date;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_graph);
+
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+
+ chart = findViewById(R.id.chart);
+ chart2 = findViewById(R.id.chart2);
+ exerciseGraph = findViewById(R.id.exerciseGraph);
+ exerciseRange = findViewById(R.id.graphRange);
+ selectCalendar = findViewById(R.id.selectDate);
+ dateSelect = findViewById(R.id.calendarText);
+ dateView = findViewById(R.id.calendarSelect);
+ graphView = findViewById(R.id.graph_info_button);
+ chartView = findViewById(R.id.chart);
+ prev = findViewById(R.id.prevButtonGraph);
+ db = FirebaseFirestore.getInstance();
+ user = FirebaseAuth.getInstance().getCurrentUser();
+
+ date = new Date();
+ yy = new SimpleDateFormat("yyyy");
+ mm = new SimpleDateFormat("MM");
+
+ exerciseRange.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ showRangeDialog();
+ }
+ });
+
+ exerciseGraph.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {showExerciseDialog();}
+ });
+
+ graphView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(exerciseRange.getText().equals("범위")){
+ Toast.makeText(Graph.this, "범위를 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(exerciseGraph.getText().equals("운동")){
+ Toast.makeText(Graph.this, "운동을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(exerciseRange.getText().equals("월별 통계")){
+ int yearNum = Integer.parseInt(yy.format(date));
+ int mmNum = Integer.parseInt(mm.format(date));
+ dateView.setVisibility(View.VISIBLE);
+ chart.setVisibility(View.GONE);
+ chart2.setVisibility(View.VISIBLE);
+ dateSelect.setText(yearNum + "년 " + mmNum + "월 ");
+ loadMonthlyData(yearNum, mmNum);
+ }else if(exerciseRange.getText().equals("최근 7일")){
+ chart.setVisibility(View.VISIBLE);
+ chart2.setVisibility(View.GONE);
+ dateView.setVisibility(View.INVISIBLE);
+ loadLast7DaysSquatData();
+ }
+ }
+ });
+
+ selectCalendar.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ showDatePickerDialog(view);
+ }
+ });
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ }
+ });
+ }
+
+ @Override
+ public void onDateSet(int year, int month) {
+ dateSelect.setText(year + "년 " + (month + 1) + "월");
+ }
+
+ private void showRangeDialog() {
+ final String[] exOptions = {"월별 통계", "최근 7일"};
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("범위 선택");
+ builder.setItems(exOptions, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ select_range = exOptions[which];
+ exerciseRange.setText(select_range);
+ }
+ });
+ builder.show();
+ }
+
+ private void showExerciseDialog() {
+ final String[] exOptions = {"스쿼트", "푸쉬업", "덤벨 숄더 프레스", "사이드 레터럴 레이즈", "레그 레이즈", "덤벨 컬", "덤벨 플라이", "덤벨 트라이셉스 익스텐션"};
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("운동 선택");
+ builder.setItems(exOptions, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ select_ex = exOptions[which];
+ exerciseGraph.setText(select_ex);
+ }
+ });
+ builder.show();
+ }
+
+ private void loadLast7DaysSquatData() {
+ final List last7Days = new ArrayList<>();
+ DateFormat dateFormat = new SimpleDateFormat("MMdd");
+ Calendar cal = Calendar.getInstance();
+ for (int i = 0; i < 7; i++) {
+ last7Days.add(dateFormat.format(cal.getTime()));
+ cal.add(Calendar.DAY_OF_MONTH, -1);
+ }
+
+ Collections.reverse(last7Days);
+
+ String collectionName = null;
+ String exercise = null;
+
+ if (exerciseGraph.getText().equals("스쿼트")) {
+ collectionName = "dailySquatRecords";
+ exercise = "squatCount";
+ } else if (exerciseGraph.getText().equals("푸쉬업")) {
+ collectionName = "dailyPushupRecords";
+ exercise = "pushupCount";
+ } else if (exerciseGraph.getText().equals("덤벨 숄더 프레스")) {
+ collectionName = "dailyDumbbellRecords";
+ exercise = "dumbbellCount";
+ } else if (exerciseGraph.getText().equals("사이드 레터럴 레이즈")) {
+ collectionName = "dailySideRecords";
+ exercise = "sideCount";
+ } else if (exerciseGraph.getText().equals("레그 레이즈")) {
+ collectionName = "dailyLegRecords";
+ exercise = "legCount";
+ }else if(exerciseGraph.getText().equals("덤벨 컬")){
+ collectionName = "dailyCurlRecords";
+ exercise = "CurlCount";
+ }else if(exerciseGraph.getText().equals("덤벨 플라이")){
+ collectionName = "dailyFlyRecords";
+ exercise = "flyCount";
+ }else if(exerciseGraph.getText().equals("덤벨 트라이셉스 익스텐션")){
+ collectionName = "dailyTricepsRecords";
+ exercise = "tricepsCount";
+ }
+
+ DocumentReference userRecordRef = db.collection(collectionName).document(user.getUid());
+
+ List entries = new ArrayList<>();
+ for (int i = 0; i < last7Days.size(); i++) {
+ final int index = i;
+ final String date = last7Days.get(i);
+
+ String finalExercise = exercise;
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ Long exerciseCount = document.getLong("2023"+date + finalExercise);
+ if (exerciseCount == null) {
+ exerciseCount = 0L;
+ }
+ entries.add(new Entry(index, exerciseCount));
+ if (index == last7Days.size() - 1) {
+ drawGraph(entries, last7Days);
+ }
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+ }
+ }
+
+ private void loadMonthlyData(int year, int month) {
+ String collectionName = null;
+ String exercise = null;
+
+ if (exerciseGraph.getText().equals("스쿼트")) {
+ collectionName = "dailySquatRecords";
+ exercise = "squatCount";
+ } else if (exerciseGraph.getText().equals("푸쉬업")) {
+ collectionName = "dailyPushupRecords";
+ exercise = "pushupCount";
+ } else if (exerciseGraph.getText().equals("덤벨 숄더 프레스")) {
+ collectionName = "dailyDumbbellRecords";
+ exercise = "dumbbellCount";
+ } else if (exerciseGraph.getText().equals("사이드 레터럴 레이즈")) {
+ collectionName = "dailySideRecords";
+ exercise = "sideCount";
+ } else if (exerciseGraph.getText().equals("레그 레이즈")) {
+ collectionName = "dailyLegRecords";
+ exercise = "legCount";
+ } else if(exerciseGraph.getText().equals("덤벨 컬")){
+ collectionName = "dailyCurlRecords";
+ exercise = "CurlCount";
+ } else if(exerciseGraph.getText().equals("덤벨 플라이")){
+ collectionName = "dailyFlyRecords";
+ exercise = "flyCount";
+ } else if(exerciseGraph.getText().equals("덤벨 트라이셉스 익스텐션")){
+ collectionName = "dailyTricepsRecords";
+ exercise = "tricepsCount";
+ }
+
+ DocumentReference userRecordRef = db.collection(collectionName).document(user.getUid());
+
+ // 해당 연도와 달에 해당하는 날짜 범위를 설정합니다.
+ int lastDay = Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_MONTH);
+ List entries = new ArrayList<>();
+ for (int day = 1; day <= lastDay; day++) {
+ final int index = day - 1;
+ final String date = String.format("%04d%02d%02d", year, month, day);
+
+ String finalExercise = exercise;
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ Long exerciseCount = document.getLong(date + finalExercise);
+ if (exerciseCount == null) {
+ exerciseCount = 0L;
+ }
+ entries.add(new Entry(index, exerciseCount));
+ if (index == lastDay - 1) {
+ drawMonthGraph(entries, year, month, lastDay);
+ }
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+ }
+ }
+
+ private void drawGraph(List entries, final List last7Days) {
+ LineDataSet dataSet = new LineDataSet(entries, exerciseGraph.getText() + " 그래프");
+
+ dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
+ dataSet.setLineWidth(2f);
+ dataSet.setColor(Color.parseColor("#9DCEFF"));
+ dataSet.setCircleColor(Color.parseColor("#9DCEFF"));
+
+ LineData lineData = new LineData(dataSet);
+
+ chart.getXAxis().setValueFormatter(new ValueFormatter() {
+ @Override
+ public String getFormattedValue(float value) {
+ if (value >= 0 && value < last7Days.size()) {
+ return last7Days.get((int) value);
+ }
+ return "";
+ }
+ });
+
+ chart.getAxisRight().setEnabled(false);
+
+ chart.setData(lineData);
+ chart.invalidate();
+ }
+
+ private void drawMonthGraph(List entries, int year, int month, int lastDay) {
+ LineDataSet dataSet = new LineDataSet(entries, exerciseGraph.getText() + " 그래프");
+
+ dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
+ dataSet.setLineWidth(2f);
+ dataSet.setColor(Color.parseColor("#9DCEFF"));
+ dataSet.setCircleColor(Color.parseColor("#9DCEFF"));
+
+ LineData lineData = new LineData(dataSet);
+
+ chart2.getXAxis().setValueFormatter(new ValueFormatter() {
+ @Override
+ public String getFormattedValue(float value) {
+ if (value >= 0 && value < lastDay) {
+ return String.format("%02d", (int)value + 1);
+ }
+ return "";
+ }
+ });
+
+ chart2.getAxisRight().setEnabled(false);
+
+ chart2.setData(lineData);
+ chart2.invalidate();
+
+ // 한 화면에 7개의 데이터 포인트만 보이도록 설정
+ chart2.setVisibleXRangeMaximum(7);
+ // 최초로 마지막 7개의 데이터 포인트를 보여줌
+ chart2.moveViewToX(0);
+ }
+
+
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("스쿼트") || str.equals("푸쉬업") || str.equals("푸시업") || str.equals("덤벨 숄더 프레스") || str.equals("덤벨 숄더") || str.equals("덤벨숄더프레스") ||
+ str.equals("사이드 레터럴 레이즈") || str.equals("사레레") || str.equals("사이드레터럴레이즈") || str.equals("레그 레이즈") || str.equals("레그레이즈") ||
+ str.equals("덤벨컬") || str.equals("덤벨 컬") || str.equals("덤벨 플라이") || str.equals("덤벨플라이") || str.equals("덤벨 트라이셉스 익스텐션") || str.equals("덤벨 트라이")){
+ if(str.equals("스쿼트")){
+ select_ex = "스쿼트";
+ exerciseGraph.setText(select_ex);
+ }else if(str.equals("푸쉬업") || str.equals("푸시업")){
+ select_ex = "푸쉬업";
+ exerciseGraph.setText(select_ex);
+ }else if(str.equals("덤벨 숄더 프레스") || str.equals("덤벨 숄더") || str.equals("덤벨숄더프레스")){
+ select_ex = "덤벨 숄더 프레스";
+ exerciseGraph.setText(select_ex);
+ }else if(str.equals("사이드 레터럴 레이즈") || str.equals("사레레") || str.equals("사이드레터럴레이즈")){
+ select_ex = "사이드 레터럴 레이즈";
+ exerciseGraph.setText(select_ex);
+ }else if(str.equals("레그 레이즈") || str.equals("레그레이즈")){
+ select_ex = "레그 레이즈";
+ exerciseGraph.setText(select_ex);
+ }else if(str.equals("덤벨컬") || str.equals("덤벨 컬")){
+ select_ex = "덤벨 컬";
+ exerciseGraph.setText(select_ex);
+ }else if(str.equals("덤벨 플라이") || str.equals("덤벨플라이")){
+ select_ex = "덤벨 플라이";
+ exerciseGraph.setText(select_ex);
+ }else if(str.equals("덤벨 트라이셉스 익스텐션") || str.equals("덤벨 트라이")){
+ select_ex = "덤벨 트라이셉스 익스텐션";
+ exerciseGraph.setText(select_ex);
+ }
+ } else if(str.equals("이전")){
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ } else if(str.equals("조회") || str.equals("그래프 조회") || str.equals("그래프")){
+ if(exerciseGraph.getText().equals("운동")){
+ Toast.makeText(Graph.this, "운동을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ chart.setVisibility(View.VISIBLE);
+ loadLast7DaysSquatData();
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 10000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 3000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+
+ public void showDatePickerDialog(View v) {
+ YearMonthPickerDialog dialog = new YearMonthPickerDialog();
+ dialog.setListener(new OnDateSetListener() {
+ @Override
+ public void onDateSet(int year, int month) {
+ // 여기에 로직 추가
+ dateSelect.setText(year + "년 " + month + "월");
+ loadMonthlyData(year, month);
+ }
+ });
+ dialog.show(getSupportFragmentManager(), "YearMonthPickerDialog");
+
+ }
+
+
+ public static class YearMonthPickerDialog extends DialogFragment {
+ private static final int MAX_YEAR = 2099;
+ private static final int MIN_YEAR = 2000;
+
+ private OnDateSetListener listener;
+
+ public void setListener(OnDateSetListener listener) {
+ this.listener = listener;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+
+ View dialog = inflater.inflate(R.layout.year_month_picker, null);
+ final NumberPicker monthPicker = dialog.findViewById(R.id.monthPicker);
+ final NumberPicker yearPicker = dialog.findViewById(R.id.yearPicker);
+
+ monthPicker.setMinValue(1);
+ monthPicker.setMaxValue(12);
+ monthPicker.setValue(1);
+
+ int year = Calendar.getInstance().get(Calendar.YEAR);
+ yearPicker.setMinValue(MIN_YEAR);
+ yearPicker.setMaxValue(MAX_YEAR);
+ yearPicker.setValue(year);
+
+ builder.setView(dialog)
+ .setPositiveButton("확인", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ if (listener != null) {
+ listener.onDateSet(yearPicker.getValue(), monthPicker.getValue());
+ }
+ }
+ })
+ .setNegativeButton("취소", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ YearMonthPickerDialog.this.getDialog().cancel();
+ }
+ });
+ return builder.create();
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/Home.java b/app/src/main/java/com/example/newbody/Home.java
new file mode 100644
index 0000000..5886728
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Home.java
@@ -0,0 +1,228 @@
+package com.example.newbody;
+
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
+import com.example.newbody.record.RecordSquatMain;
+import com.github.mikephil.charting.charts.PieChart;
+import com.github.mikephil.charting.data.PieData;
+import com.github.mikephil.charting.data.PieDataSet;
+import com.github.mikephil.charting.data.PieEntry;
+import com.github.mikephil.charting.formatter.PercentFormatter;
+import com.google.android.gms.ads.AdRequest;
+import com.google.android.gms.ads.AdView;
+import com.google.android.gms.ads.MobileAds;
+import com.google.android.gms.ads.initialization.InitializationStatus;
+import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Home extends Fragment {
+ private View view, yoga, yoga_lock;
+ private View posture_button, video_button, record_button, ranking_button, yoga_button, yoga_lock_button;
+ private PieChart pieChart;
+ private Button notice;
+ private CustomDialogNotice customDialog;
+ private ImageView premium;
+ private AdView mAdView;
+
+ FirebaseAuth auth;
+ FirebaseUser user;
+ FirebaseFirestore db;
+ TextView name, bmiResult;
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ view = inflater.inflate(R.layout.activity_home, container, false);
+
+ yoga = view.findViewById(R.id.yoga_layout);
+ yoga_lock = view.findViewById(R.id.yoga_lock_layout);
+
+ db = FirebaseFirestore.getInstance();
+ auth = FirebaseAuth.getInstance();
+ user = auth.getCurrentUser();
+ posture_button = view.findViewById(R.id.posture_button);
+ video_button = view.findViewById(R.id.video_button);
+ record_button = view.findViewById(R.id.record_button);
+ ranking_button = view.findViewById(R.id.ranking_button);
+ yoga_button = view.findViewById(R.id.yoga_button);
+ yoga_lock_button = view.findViewById(R.id.yoga_lock_button);
+ pieChart = view.findViewById(R.id.pieChart);
+ notice = view.findViewById(R.id.noticeDialog);
+ premium = view.findViewById(R.id.premium_badge);
+
+ name = view.findViewById(R.id.name_info);
+ bmiResult = view.findViewById(R.id.bmi_result);
+ mAdView = view.findViewById(R.id.adView);
+
+ AdRequest adRequest = new AdRequest.Builder().build();
+ mAdView.loadAd(adRequest);
+
+ premiumCheck();
+
+ if(user == null){
+ Intent intent = new Intent(getActivity(), LoginActivity.class);
+ startActivity(intent);
+ }else{
+ db.collection("users").document(user.getUid())
+ .get()
+ .addOnCompleteListener(new OnCompleteListener() {
+
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ int weight = Integer.parseInt(document.getString("weight"));
+ int height = Integer.parseInt(document.getString("height"));
+
+ double bmiNum = (double)weight/(((double)height/100)*((double)height/100));
+ if(bmiNum < 18.5){
+ bmiResult.setText("당신의 BMI수치는 저체중에 해당합니다. ");
+ }else if(bmiNum >= 18.5 && bmiNum < 25){
+ bmiResult.setText("당신의 BMI수치는 정상입니다. ");
+ }else if(bmiNum >= 25 && bmiNum < 30){
+ bmiResult.setText("당신의 BMI수치는 과체중에 해당합니다. ");
+ }else if(bmiNum >= 30){
+ bmiResult.setText("당신의 BMI수치는 비만에 해당합니다. ");
+ }
+ name.setText(document.getString("name"));
+
+ String bmi = String.valueOf(bmiNum);
+
+ List entries = new ArrayList<>();
+ entries.add(new PieEntry((float) bmiNum, ""));
+ entries.add(new PieEntry(100-(float)bmiNum, ""));
+
+// Log.d("BmiChart", "BMI: " + bmi);
+
+ PieDataSet dataSet = new PieDataSet(entries, "");
+ dataSet.setColors(Color.parseColor("#C58BF2"), Color.WHITE);
+// dataSet.setDrawValues(false);
+ dataSet.setValueTextColor(Color.WHITE);
+ dataSet.setValueTextSize(14f);
+
+ PieData pieData = new PieData(dataSet);
+ pieData.setValueFormatter(new PercentFormatter(pieChart));
+ pieChart.setData(pieData);
+ pieChart.getDescription().setEnabled(false);
+ pieChart.setDrawHoleEnabled(false);
+ pieChart.getLegend().setEnabled(false);
+ pieChart.invalidate();
+ pieChart.highlightValue(0, 0);
+ } else {
+ }
+ } else {
+ // handle the failure case
+ }
+ }
+ });
+ }
+
+ notice.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ customDialog = new CustomDialogNotice(getContext(),
+ "본 앱은 음성 인식을 지원합니다. \n\n앱 내에서 '바디'를 불러보세요 ! \n\n'바디야' 또는 '뉴바디'라고 말하면 \n\n바디가 대답해주고 \n\n" +
+ "명령을 실행해줍니다. " + "\n\n\n" + "예시) 자세 교정, 기록 측정 등");
+ customDialog.show();
+ }
+ });
+
+ posture_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), Posture.class);
+ startActivity(intent);
+ }
+ });
+ video_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), Video.class);
+ startActivity(intent);
+ }
+ });
+ record_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), Record.class);
+ startActivity(intent);
+ }
+ });
+ ranking_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), Ranking.class);
+ startActivity(intent);
+ }
+ });
+
+ yoga_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), YogaPosture.class);
+ startActivity(intent);
+ }
+ });
+
+ yoga_lock_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Toast.makeText(getActivity(), "프리미엄 회원 전용 메뉴입니다", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ return view;
+ }
+
+ public void premiumCheck(){
+ if(user == null){
+ Intent intent = new Intent(getActivity(), LoginActivity.class);
+ startActivity(intent);
+ }else{
+ db.collection("users").document(user.getUid())
+ .get()
+ .addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@androidx.annotation.NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ String grade = document.getString("grade");
+ if (grade == null) grade = "일반";
+
+ if(grade.equals("프리미엄")){
+ premium.setVisibility(View.VISIBLE);
+ yoga.setVisibility(View.VISIBLE);
+ yoga_lock.setVisibility(View.GONE);
+ }
+ }
+ } else {
+ }
+ }
+ });
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/example/newbody/ImageAdapterGridView.java b/app/src/main/java/com/example/newbody/ImageAdapterGridView.java
new file mode 100644
index 0000000..3de6111
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/ImageAdapterGridView.java
@@ -0,0 +1,85 @@
+package com.example.newbody;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ImageView;
+
+import java.util.ArrayList;
+
+public class ImageAdapterGridView extends BaseAdapter {
+ private Context mContext;
+ ArrayList itemList = new ArrayList();
+
+ public ImageAdapterGridView(Context c, ArrayList itemList) {
+ mContext = c;
+ this.itemList = itemList;
+ }
+
+ @Override
+ public int getCount() {
+ return itemList.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return itemList.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return 0;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ImageView imageView;
+ if (convertView == null) { // if it's not recycled, initialize some attributes
+ imageView = new ImageView(mContext);
+ imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
+ imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
+ imageView.setPadding(8, 8, 8, 8);
+ } else {
+ imageView = (ImageView) convertView;
+ }
+
+ Bitmap bm = decodeSampledBitmapFromUri(itemList.get(position), 220, 220);
+
+ imageView.setImageBitmap(bm);
+ return imageView;
+ }
+
+ public Bitmap decodeSampledBitmapFromUri(String path, int reqWidth, int reqHeight) {
+
+ Bitmap bm = null;
+ final BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(path, options);
+ options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
+ options.inJustDecodeBounds = false;
+ bm = BitmapFactory.decodeFile(path, options);
+
+ return bm;
+ }
+
+ public int calculateInSampleSize(
+ BitmapFactory.Options options, int reqWidth, int reqHeight) {
+ final int height = options.outHeight;
+ final int width = options.outWidth;
+ int inSampleSize = 1;
+
+ if (height > reqHeight || width > reqWidth) {
+ if (width > height) {
+ inSampleSize = Math.round((float)height / (float)reqHeight);
+ } else {
+ inSampleSize = Math.round((float)width / (float)reqWidth);
+ }
+ }
+
+ return inSampleSize;
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/LandmarkTriple.java b/app/src/main/java/com/example/newbody/LandmarkTriple.java
new file mode 100644
index 0000000..f04cb0b
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/LandmarkTriple.java
@@ -0,0 +1,44 @@
+package com.example.newbody;
+
+import com.google.mlkit.vision.pose.Pose;
+import com.google.mlkit.vision.pose.PoseLandmark;
+
+public class LandmarkTriple {
+ private final PoseLandmark firstLandmark;
+ private final PoseLandmark middleLandmark;
+ private final PoseLandmark lastLandmark;
+
+ public LandmarkTriple(PoseLandmark firstLandmark, PoseLandmark middleLandmark, PoseLandmark lastLandmark) {
+ this.firstLandmark = firstLandmark;
+ this.middleLandmark = middleLandmark;
+ this.lastLandmark = lastLandmark;
+ }
+
+ public PoseLandmark getFirstLandmark() {
+ return firstLandmark;
+ }
+
+ public PoseLandmark getMiddleLandmark() {
+ return middleLandmark;
+ }
+
+ public PoseLandmark getLastLandmark() {
+ return lastLandmark;
+ }
+
+ public LandmarkTriple extractLandmark(Pose pose, TargetShape target) {
+ return new LandmarkTriple(
+ extractLandmarkFromType(pose, target.getFirstLandmarkType()),
+ extractLandmarkFromType(pose, target.getMiddleLandmarkType()),
+ extractLandmarkFromType(pose, target.getLastLandmarkType())
+ );
+ }
+
+ public PoseLandmark extractLandmarkFromType(Pose pose, int landmarkType) {
+ return pose.getPoseLandmark(landmarkType);
+ }
+
+ public boolean landmarkNotFound() {
+ return firstLandmark == null || middleLandmark == null || lastLandmark == null;
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/LoadingActivity.java b/app/src/main/java/com/example/newbody/LoadingActivity.java
new file mode 100644
index 0000000..03f6e04
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/LoadingActivity.java
@@ -0,0 +1,29 @@
+package com.example.newbody;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.ImageView;
+
+import com.bumptech.glide.Glide;
+
+public class LoadingActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.background_loading);
+ ImageView walk = (ImageView) findViewById(R.id.gif_image);
+ Glide.with(this).load(R.drawable.walk).into(walk);
+ startLoading();
+ }
+ private void startLoading() {
+ Handler handler = new Handler();
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ finish();
+ }
+ }, 3200);
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/LoginActivity.java b/app/src/main/java/com/example/newbody/LoginActivity.java
new file mode 100644
index 0000000..dc10e98
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/LoginActivity.java
@@ -0,0 +1,176 @@
+package com.example.newbody;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.google.android.gms.auth.api.signin.GoogleSignIn;
+import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
+import com.google.android.gms.auth.api.signin.GoogleSignInClient;
+import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
+import com.google.android.gms.common.api.ApiException;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.AuthCredential;
+import com.google.firebase.auth.AuthResult;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.auth.GoogleAuthProvider;
+import com.google.firebase.auth.SignInMethodQueryResult;
+
+public class LoginActivity extends AppCompatActivity {
+ private static final int RC_SIGN_IN = 9001;
+ EditText editEmail, editPassword;
+ FirebaseAuth mAuth;
+ View google;
+ private GoogleSignInClient mGoogleSignInClient;
+ private GoogleSignInAccount googleAccount;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_login);
+
+ mAuth = FirebaseAuth.getInstance();
+
+ View login = findViewById(R.id.login);
+ View manager = findViewById(R.id.button_manager);
+ Button register = (Button) findViewById(R.id.register);
+
+ editEmail = findViewById(R.id.email);
+ editPassword = findViewById(R.id.password);
+
+ // GoogleSignInClient 객체 초기화
+ GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
+ .requestIdToken(getString(R.string.default_web_client_id))
+ .requestEmail()
+ .build();
+ mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
+
+ google = findViewById(R.id.google);
+
+ login.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(LoginActivity.this, LoadingActivity.class);
+ startActivity(intent);
+
+ String emailS, passwordS;
+ emailS = String.valueOf(editEmail.getText());
+ passwordS = String.valueOf(editPassword.getText());
+
+ if(TextUtils.isEmpty(emailS)){
+ Toast.makeText(LoginActivity.this, "이메일을 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(TextUtils.isEmpty(passwordS)){
+ Toast.makeText(LoginActivity.this, "비밀번호를 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ mAuth.signInWithEmailAndPassword(emailS, passwordS)
+ .addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ } else {
+ Toast.makeText(LoginActivity.this, "로그인 실패",
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+
+
+ }
+ });
+ manager.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), ManagerLogin.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ register.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Membership.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ google.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent signInIntent = mGoogleSignInClient.getSignInIntent();
+ startActivityForResult(signInIntent, RC_SIGN_IN);
+ }
+ });
+ }
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ // GoogleSignInClient.getSignInIntent(...)의 결과 처리
+ if (requestCode == RC_SIGN_IN) {
+ Task task = GoogleSignIn.getSignedInAccountFromIntent(data);
+ try {
+ // Google Sign In이 성공했을 경우, Firebase에 인증
+ googleAccount = task.getResult(ApiException.class);
+ firebaseAuthWithGoogle(googleAccount.getIdToken());
+ } catch (ApiException e) {
+ // Google Sign In 실패
+ Toast.makeText(LoginActivity.this, "로그인 실패", Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+ // Google 로그인 토큰을 이용하여 Firebase에 인증
+ private void firebaseAuthWithGoogle(String idToken) {
+ AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null);
+
+ mAuth.fetchSignInMethodsForEmail(googleAccount.getEmail())
+ .addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ SignInMethodQueryResult result = task.getResult();
+ if (result.getSignInMethods().size() > 0) {
+ // 사용자가 이미 존재: 로그인 진행
+ mAuth.signInWithCredential(credential)
+ .addOnCompleteListener(LoginActivity.this, new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ FirebaseUser user = mAuth.getCurrentUser();
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ } else {
+ // 인증 실패
+ Toast.makeText(LoginActivity.this, "로그인 실패", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ } else {
+ // 사용자가 존재하지 않음: 에러 메시지 출력
+ Toast.makeText(LoginActivity.this, "로그인 실패", Toast.LENGTH_SHORT).show();
+ }
+ } else {
+ // 이메일 확인 실패: 에러 메시지 출력
+ Toast.makeText(LoginActivity.this, "로그인 실패", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }
+
+}
diff --git a/app/src/main/java/com/example/newbody/MainActivity.java b/app/src/main/java/com/example/newbody/MainActivity.java
index ac581d3..8b01fd5 100644
--- a/app/src/main/java/com/example/newbody/MainActivity.java
+++ b/app/src/main/java/com/example/newbody/MainActivity.java
@@ -2,13 +2,52 @@
import androidx.appcompat.app.AppCompatActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
import android.os.Bundle;
+import android.view.View;
+
+import com.example.newbody.mainInfo.MainActivityA;
public class MainActivity extends AppCompatActivity {
+ private static final String PREFS_NAME = "MyPrefsFile";
+ private static final String FIRST_RUN_KEY = "firstRun";
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
+
+ // SharedPreferences에서 "firstRun" 키의 값을 불러옴
+ SharedPreferences preferences = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
+ boolean isFirstRun = preferences.getBoolean(FIRST_RUN_KEY, true);
+
+ View button = findViewById(R.id.button);
+
+ // 처음 실행되는 경우에만 실행
+ if (isFirstRun) {
+ // SharedPreferences에 "firstRun" 값을 false로 저장하여 다음에 앱이 실행될 때는 이 부분이 실행되지 않도록 함
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putBoolean(FIRST_RUN_KEY, false);
+ editor.apply();
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), MainActivityA.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ }else{
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
+ startActivity(intent);
+ }
+ });
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/ManagerLogin.java b/app/src/main/java/com/example/newbody/ManagerLogin.java
new file mode 100644
index 0000000..3afadce
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/ManagerLogin.java
@@ -0,0 +1,36 @@
+package com.example.newbody;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.Toast;
+
+public class ManagerLogin extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_manager_login);
+
+ View login = findViewById(R.id.managerLogin);
+ EditText password = findViewById(R.id.managerPassword);
+
+ String passwordManager = "1234";
+ login.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(password.getText().toString().equals(passwordManager)){
+ Intent intent = new Intent(getApplicationContext(), ManagerMenu.class);
+ startActivity(intent);
+ finish();
+ }else{
+ Toast.makeText(ManagerLogin.this, "로그인 실패", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/ManagerMember.java b/app/src/main/java/com/example/newbody/ManagerMember.java
new file mode 100644
index 0000000..7dca5a1
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/ManagerMember.java
@@ -0,0 +1,236 @@
+package com.example.newbody;
+
+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.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.Query;
+import com.google.firebase.firestore.QueryDocumentSnapshot;
+import com.google.firebase.firestore.QuerySnapshot;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class ManagerMember extends AppCompatActivity {
+
+ private CheckBox entire, free, money;
+ private Button prev, search;
+ private View memberLayout;
+
+ private RecyclerView memberRecyclerView;
+ private MemberAdaptor adapter;
+ private FirebaseFirestore db;
+ private FirebaseUser user;
+ private List memberList = new ArrayList<>();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_manager_member);
+
+ prev = findViewById(R.id.prevButtonMemberManage);
+ memberLayout = findViewById(R.id.layout_member);
+ entire = findViewById(R.id.entire);
+ free = findViewById(R.id.freeMember);
+ money = findViewById(R.id.moneyMember);
+ search = findViewById(R.id.searchMember);
+ memberRecyclerView = findViewById(R.id.memberRecyclerView);
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), ManagerMenu.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ entire.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(entire.isChecked()){
+ free.setChecked(true);
+ money.setChecked(true);
+ }else if(!entire.isChecked()){
+ free.setChecked(false);
+ money.setChecked(false);
+ }
+ }
+ });
+
+ free.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(!free.isChecked()){
+ entire.setChecked(false);
+ }else if(free.isChecked() && money.isChecked()){
+ entire.setChecked(true);
+ }
+ }
+ });
+
+ money.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(!money.isChecked()){
+ entire.setChecked(false);
+ }else if(free.isChecked() && money.isChecked()){
+ entire.setChecked(true);
+ }
+ }
+ });
+
+ search.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ memberLayout.setVisibility(View.VISIBLE);
+ db = FirebaseFirestore.getInstance();
+ memberRecyclerView.setLayoutManager(new LinearLayoutManager(ManagerMember.this));
+
+ fetchData();
+ adapter = new MemberAdaptor(memberList);
+ memberRecyclerView.setAdapter(adapter);
+ }
+ });
+ }
+
+ private void fetchData() {
+ memberList.clear();
+
+ if(entire.isChecked()){
+ db.collection("users").get().addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ QuerySnapshot querySnapshot = task.getResult();
+ if (querySnapshot != null) {
+ for (QueryDocumentSnapshot document : querySnapshot) {
+ String name = document.getString("name");
+ String birth = document.getString("birth");
+ String gender = document.getString("gender");
+ String grade = document.getString("grade");
+
+ if (name == null) name = "정보없음";
+ if (birth == null) birth = "정보없음";
+ if (gender == null) gender = "정보없음";
+ if (grade == null) grade = "일반";
+
+ if(gender.equals("M") || gender.equals("남") || gender.equals("m") ||
+ gender.equals("male") || gender.equals("xy") || gender.equals("man") || gender.equals("XY")){
+ gender = "남자";
+ }else if(gender.equals("W") || gender.equals("여") || gender.equals("w") ||
+ gender.equals("female") || gender.equals("xx") || gender.equals("women") || gender.equals("XX")){
+ gender = "여자";
+ }
+
+ if(!name.equals("정보없음") || !birth.equals("정보없음") || !gender.equals("정보없음")){
+ memberList.add(new MemberItem(name, birth, gender, grade));
+ }
+ }
+ adapter.notifyDataSetChanged();
+ }
+ } else {
+ // 에러 처리
+ Log.d("Firestore Error", "Error getting documents: ", task.getException());
+ }
+ });
+ }else if(money.isChecked() && !entire.isChecked()){
+ db.collection("users").get().addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ QuerySnapshot querySnapshot = task.getResult();
+ if (querySnapshot != null) {
+ for (QueryDocumentSnapshot document : querySnapshot) {
+ String name = document.getString("name");
+ String birth = document.getString("birth");
+ String gender = document.getString("gender");
+ String grade = document.getString("grade");
+
+ if (name == null) name = "정보없음";
+ if (birth == null) birth = "정보없음";
+ if (gender == null) gender = "정보없음";
+ if (grade == null) grade = "일반";
+
+ if(gender.equals("M") || gender.equals("남") || gender.equals("m") ||
+ gender.equals("male") || gender.equals("xy") || gender.equals("man") || gender.equals("XY")){
+ gender = "남자";
+ }else if(gender.equals("W") || gender.equals("여") || gender.equals("w") ||
+ gender.equals("female") || gender.equals("xx") || gender.equals("women") || gender.equals("XX")){
+ gender = "여자";
+ }
+
+ if(grade.equals("프리미엄") && (!name.equals("정보없음") || !birth.equals("정보없음") || !gender.equals("정보없음"))){
+ memberList.add(new MemberItem(name, birth, gender, grade));
+ }
+ }
+ adapter.notifyDataSetChanged();
+ }
+ } else {
+ // 에러 처리
+ Log.d("Firestore Error", "Error getting documents: ", task.getException());
+ }
+ });
+ }else if(free.isChecked() && !entire.isChecked()){
+ db.collection("users").get().addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ QuerySnapshot querySnapshot = task.getResult();
+ if (querySnapshot != null) {
+ for (QueryDocumentSnapshot document : querySnapshot) {
+ String name = document.getString("name");
+ String birth = document.getString("birth");
+ String gender = document.getString("gender");
+ String grade = document.getString("grade");
+
+ if (name == null) name = "정보없음";
+ if (birth == null) birth = "정보없음";
+ if (gender == null) gender = "정보없음";
+ if (grade == null) grade = "일반";
+
+ if(gender.equals("M") || gender.equals("남") || gender.equals("m") ||
+ gender.equals("male") || gender.equals("xy") || gender.equals("man") || gender.equals("XY")){
+ gender = "남자";
+ }else if(gender.equals("W") || gender.equals("여") || gender.equals("w") ||
+ gender.equals("female") || gender.equals("xx") || gender.equals("women") || gender.equals("XX")){
+ gender = "여자";
+ }
+
+ if(grade.equals("일반") && (!name.equals("정보없음") || !birth.equals("정보없음") || !gender.equals("정보없음"))){
+ memberList.add(new MemberItem(name, birth, gender, grade));
+ }
+ }
+ adapter.notifyDataSetChanged();
+ }
+ } else {
+ // 에러 처리
+ Log.d("Firestore Error", "Error getting documents: ", task.getException());
+ }
+ });
+ }
+ }
+
+ static class MemberItem {
+ String name;
+ String birth;
+ String gender;
+ String grade;
+
+ public MemberItem(String name, String birth, String gender, String grade) {
+ this.name = name;
+ this.birth = birth;
+ this.gender = gender;
+ this.grade = grade;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/ManagerMenu.java b/app/src/main/java/com/example/newbody/ManagerMenu.java
new file mode 100644
index 0000000..362c911
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/ManagerMenu.java
@@ -0,0 +1,52 @@
+package com.example.newbody;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.Toast;
+
+public class ManagerMenu extends AppCompatActivity {
+
+ private View member, money;
+ private Button logout;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_manager_menu);
+
+ member = findViewById(R.id.memberManage);
+ money = findViewById(R.id.moneyManage);
+ logout = findViewById(R.id.logout);
+
+ member.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), ManagerMember.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ money.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), ManagerMoney.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ logout.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), MainActivity.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/ManagerMoney.java b/app/src/main/java/com/example/newbody/ManagerMoney.java
new file mode 100644
index 0000000..7b1d969
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/ManagerMoney.java
@@ -0,0 +1,373 @@
+package com.example.newbody;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.DialogFragment;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.NumberPicker;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.github.mikephil.charting.charts.LineChart;
+import com.github.mikephil.charting.components.AxisBase;
+import com.github.mikephil.charting.components.XAxis;
+import com.github.mikephil.charting.components.YAxis;
+import com.github.mikephil.charting.data.Entry;
+import com.github.mikephil.charting.data.LineData;
+import com.github.mikephil.charting.data.LineDataSet;
+import com.github.mikephil.charting.formatter.IAxisValueFormatter;
+import com.github.mikephil.charting.formatter.ValueFormatter;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+public class ManagerMoney extends AppCompatActivity implements OnDateSetListener{
+
+ private Button exerciseRange, graphView, prev, selectCalendar;
+ private String select_range;
+ private FirebaseFirestore db;
+ private FirebaseUser user;
+ private LineChart chart, chart2;
+ private TextView dateSelect;
+ private View dateView;
+ SimpleDateFormat yy, mm;
+ Date date;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_manager_money);
+
+ initView();
+
+ exerciseRange.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ showRangeDialog();
+ }
+ });
+
+ graphView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(exerciseRange.getText().equals("범위")){
+ Toast.makeText(ManagerMoney.this, "범위를 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(exerciseRange.getText().equals("월별 통계")){
+ int yearNum = Integer.parseInt(yy.format(date));
+ int mmNum = Integer.parseInt(mm.format(date));
+ dateView.setVisibility(View.VISIBLE);
+ chart.setVisibility(View.GONE);
+ chart2.setVisibility(View.VISIBLE);
+ dateSelect.setText(yearNum + "년 " + mmNum + "월 ");
+ fetchMonthlyData(yearNum, mmNum);
+ }else if(exerciseRange.getText().equals("최근 7일")){
+ chart.setVisibility(View.VISIBLE);
+ chart2.setVisibility(View.GONE);
+ dateView.setVisibility(View.INVISIBLE);
+ fetchLast7DaysData();
+ }
+ }
+ });
+
+ selectCalendar.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ showDatePickerDialog(view);
+ }
+ });
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), ManagerMenu.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ }
+
+ public void initView(){
+ prev = findViewById(R.id.prevButtonMoneyManage);
+ exerciseRange = findViewById(R.id.graphRange2);
+ graphView = findViewById(R.id.graph_money_button);
+ selectCalendar = findViewById(R.id.selectDate1);
+ db = FirebaseFirestore.getInstance();
+ user = FirebaseAuth.getInstance().getCurrentUser();
+ chart = findViewById(R.id.chart11);
+ chart2 = findViewById(R.id.chart22);
+ dateSelect = findViewById(R.id.calendarText1);
+ dateView = findViewById(R.id.calendarSelect1);
+ date = new Date();
+ yy = new SimpleDateFormat("yyyy");
+ mm = new SimpleDateFormat("MM");
+ }
+
+ @Override
+ public void onDateSet(int year, int month) {
+ dateSelect.setText(year + "년 " + (month + 1) + "월");
+ }
+
+ private void showRangeDialog() {
+ final String[] exOptions = {"월별 통계", "최근 7일"};
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("범위 선택");
+ builder.setItems(exOptions, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ select_range = exOptions[which];
+ exerciseRange.setText(select_range);
+ }
+ });
+ builder.show();
+ }
+
+ // 새로운 클래스
+ public class SalesData {
+ public String date;
+ public int sales;
+
+ public SalesData(String date, int sales) {
+ this.date = date;
+ this.sales = sales;
+ }
+ }
+
+ public void fetchLast7DaysData() {
+ final String collectionName = "payments";
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
+ final ArrayList last7Days = new ArrayList<>();
+ final ArrayList salesDataList = new ArrayList<>();
+
+ // Generate the last 7 days in yyyyMMdd format
+ Calendar cal = Calendar.getInstance();
+ for (int i = 0; i < 7; i++) {
+ last7Days.add(sdf.format(cal.getTime()));
+ cal.add(Calendar.DATE, -1);
+ }
+
+ for (final String date : last7Days) {
+ DocumentReference paymentRecordRef = db.collection(collectionName).document(date);
+ paymentRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ int amount = document.exists() ? document.getLong("amount").intValue() : 0;
+
+ salesDataList.add(new SalesData(date, amount));
+
+ if (salesDataList.size() == 7) {
+ // 날짜로 정렬
+ Collections.sort(salesDataList, (a, b) -> a.date.compareTo(b.date));
+
+ // 날짜와 매출 데이터를 분리
+ ArrayList sortedDates = new ArrayList<>();
+ ArrayList sortedSales = new ArrayList<>();
+ for (SalesData data : salesDataList) {
+ sortedDates.add(data.date);
+ sortedSales.add(data.sales);
+ }
+ plotGraph(sortedSales, sortedDates);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ private void plotGraph(ArrayList salesData, ArrayList last7Days) {
+ ArrayList entries = new ArrayList<>();
+ for (int i = 0; i < salesData.size(); i++) {
+ entries.add(new Entry(i, salesData.get(i)));
+ }
+
+ LineDataSet dataSet = new LineDataSet(entries, " 그래프");
+
+ dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
+ dataSet.setLineWidth(2f);
+ dataSet.setColor(Color.parseColor("#9DCEFF"));
+ dataSet.setCircleColor(Color.parseColor("#9DCEFF"));
+
+ LineData lineData = new LineData(dataSet);
+
+ chart.getXAxis().setValueFormatter(new ValueFormatter() {
+ @Override
+ public String getFormattedValue(float value) {
+ if (value >= 0 && value < last7Days.size()) {
+ return last7Days.get((int) value).substring(4, 8);
+ }
+ return "";
+ }
+ });
+
+ chart.getAxisRight().setEnabled(false);
+
+ chart.setData(lineData);
+ chart.invalidate();
+ }
+
+ // 월별 매출 데이터를 가져오는 메서드
+ public void fetchMonthlyData(int year, int month) {
+ final String collectionName = "payments";
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
+ final ArrayList salesDataList = new ArrayList<>();
+ final ArrayList daysInMonth = new ArrayList<>();
+
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.YEAR, year);
+ cal.set(Calendar.MONTH, month - 1); // Calendar.MONTH is zero-based
+ cal.set(Calendar.DAY_OF_MONTH, 1);
+
+ int maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
+ for (int i = 1; i <= maxDay; i++) {
+ cal.set(Calendar.DAY_OF_MONTH, i);
+ daysInMonth.add(sdf.format(cal.getTime()));
+ }
+
+ for (final String date : daysInMonth) {
+ DocumentReference paymentRecordRef = db.collection(collectionName).document(date);
+ paymentRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ int amount = document.exists() ? document.getLong("amount").intValue() : 0;
+ salesDataList.add(new SalesData(date, amount));
+
+ if (salesDataList.size() == maxDay) {
+ Collections.sort(salesDataList, (a, b) -> a.date.compareTo(b.date));
+ ArrayList sortedDates = new ArrayList<>();
+ ArrayList sortedSales = new ArrayList<>();
+ for (SalesData data : salesDataList) {
+ sortedDates.add(data.date);
+ sortedSales.add(data.sales);
+ }
+ plotMonthGraph(sortedSales, sortedDates);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ private void plotMonthGraph(ArrayList salesData, ArrayList last7Days) {
+ ArrayList entries = new ArrayList<>();
+ for (int i = 0; i < salesData.size(); i++) {
+ entries.add(new Entry(i, salesData.get(i)));
+ }
+
+ LineDataSet dataSet = new LineDataSet(entries, " 그래프");
+
+ dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
+ dataSet.setLineWidth(2f);
+ dataSet.setColor(Color.parseColor("#9DCEFF"));
+ dataSet.setCircleColor(Color.parseColor("#9DCEFF"));
+
+ LineData lineData = new LineData(dataSet);
+
+ chart2.getXAxis().setValueFormatter(new ValueFormatter() {
+ @Override
+ public String getFormattedValue(float value) {
+ if (value >= 0 && value < last7Days.size()) {
+ return last7Days.get((int) value).substring(4, 8);
+ }
+ return "";
+ }
+ });
+
+ chart2.getAxisRight().setEnabled(false);
+
+ chart2.setData(lineData);
+ chart2.invalidate();
+ // 한 화면에 7개의 데이터 포인트만 보이도록 설정
+ chart2.setVisibleXRangeMaximum(7);
+ // 최초로 마지막 7개의 데이터 포인트를 보여줌
+ chart2.moveViewToX(0);
+ }
+
+ public void showDatePickerDialog(View v) {
+ Graph.YearMonthPickerDialog dialog = new Graph.YearMonthPickerDialog();
+ dialog.setListener(new OnDateSetListener() {
+ @Override
+ public void onDateSet(int year, int month) {
+ // 여기에 로직 추가
+ dateSelect.setText(year + "년 " + month + "월");
+ fetchMonthlyData(year, month);
+ }
+ });
+ dialog.show(getSupportFragmentManager(), "YearMonthPickerDialog");
+
+ }
+
+ public static class YearMonthPickerDialog extends DialogFragment {
+ private static final int MAX_YEAR = 2099;
+ private static final int MIN_YEAR = 2000;
+
+ private OnDateSetListener listener;
+
+ public void setListener(OnDateSetListener listener) {
+ this.listener = listener;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+
+ View dialog = inflater.inflate(R.layout.year_month_picker, null);
+ final NumberPicker monthPicker = dialog.findViewById(R.id.monthPicker);
+ final NumberPicker yearPicker = dialog.findViewById(R.id.yearPicker);
+
+ monthPicker.setMinValue(1);
+ monthPicker.setMaxValue(12);
+ monthPicker.setValue(1);
+
+ int year = Calendar.getInstance().get(Calendar.YEAR);
+ yearPicker.setMinValue(MIN_YEAR);
+ yearPicker.setMaxValue(MAX_YEAR);
+ yearPicker.setValue(year);
+
+ builder.setView(dialog)
+ .setPositiveButton("확인", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ if (listener != null) {
+ listener.onDateSet(yearPicker.getValue(), monthPicker.getValue());
+ }
+ }
+ })
+ .setNegativeButton("취소", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ YearMonthPickerDialog.this.getDialog().cancel();
+ }
+ });
+ return builder.create();
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/MemberAdaptor.java b/app/src/main/java/com/example/newbody/MemberAdaptor.java
new file mode 100644
index 0000000..c6f7cfd
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/MemberAdaptor.java
@@ -0,0 +1,60 @@
+package com.example.newbody;
+
+import android.graphics.Color;
+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 java.util.List;
+
+public class MemberAdaptor extends RecyclerView.Adapter{
+ private List memberList;
+
+ public MemberAdaptor(List memberList) {
+ this.memberList = memberList;
+ }
+
+ @NonNull
+ @Override
+ public MemberViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View itemView = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.member_item, parent, false);
+ return new MemberViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull MemberViewHolder holder, int position) {
+ ManagerMember.MemberItem currentItem = memberList.get(position);
+ holder.nameTextView.setText(currentItem.name);
+ holder.birthTextView.setText(currentItem.birth);
+ holder.genderTextView.setText(currentItem.gender);
+ holder.gradeTextView.setText(currentItem.grade);
+ if(currentItem.grade.equals("프리미엄")){
+ holder.gradeTextView.setTextColor(Color.parseColor("#ffcc00"));
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return memberList.size();
+ }
+
+ static class MemberViewHolder extends RecyclerView.ViewHolder {
+ TextView nameTextView;
+ TextView birthTextView;
+ TextView genderTextView;
+ TextView gradeTextView;
+
+ public MemberViewHolder(@NonNull View itemView) {
+ super(itemView);
+ nameTextView = itemView.findViewById(R.id.nameTextView);
+ birthTextView = itemView.findViewById(R.id.birthTextView);
+ genderTextView = itemView.findViewById(R.id.genderTextView);
+ gradeTextView = itemView.findViewById(R.id.gradeTextView);
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/MemberChangeActivity.java b/app/src/main/java/com/example/newbody/MemberChangeActivity.java
new file mode 100644
index 0000000..b7316fe
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/MemberChangeActivity.java
@@ -0,0 +1,296 @@
+package com.example.newbody;
+
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.bumptech.glide.Glide;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.database.annotations.Nullable;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.storage.FirebaseStorage;
+import com.google.firebase.storage.StorageReference;
+import com.google.firebase.storage.UploadTask;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MemberChangeActivity extends AppCompatActivity {
+
+ private static final int PICK_IMAGE_REQUEST = 1;
+ private Uri imageUri;
+ private StorageReference storageRef;
+
+ private FirebaseFirestore db;
+ private FirebaseAuth mAuth;
+ private EditText nameEditText, genderEditText, birthEditText, weightEditText, heightEditText;
+
+ private FirebaseUser user;
+ private Button prev;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_member_change);
+
+ db = FirebaseFirestore.getInstance();
+ mAuth = FirebaseAuth.getInstance();
+ user = mAuth.getCurrentUser();
+
+ nameEditText = findViewById(R.id.name_fix);
+ genderEditText = findViewById(R.id.gender_fix);
+ birthEditText = findViewById(R.id.birth_fix);
+ weightEditText = findViewById(R.id.weight_fix);
+ heightEditText = findViewById(R.id.height_fix);
+
+ View updateButton = findViewById(R.id.fix_button);
+ View imageButton = findViewById(R.id.pic_button);
+ prev = findViewById(R.id.prevButtonfix);
+
+ storageRef = FirebaseStorage.getInstance().getReference("profile_pics");
+
+ loadImageFromFirestore();
+
+ if(user == null){
+ Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
+ startActivity(intent);
+ }else{
+ db.collection("users").document(user.getUid())
+ .get()
+ .addOnCompleteListener(new OnCompleteListener() {
+ @SuppressLint("SetTextI18n")
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ birthEditText.setText(document.getString("birth"));
+ genderEditText.setText(document.getString("gender"));
+ nameEditText.setText(document.getString("name"));
+ weightEditText.setText(document.getString("weight"));
+ heightEditText.setText(document.getString("height"));
+ }
+ } else {
+ }
+ }
+ });
+ }
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ imageButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ openFileChooser();
+ }
+ });
+
+ updateButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (imageUri != null) {
+ uploadFile();
+ }
+
+ String name = nameEditText.getText().toString();
+ String gender = genderEditText.getText().toString();
+ String birth = birthEditText.getText().toString();
+ String weight = weightEditText.getText().toString();
+ String height = heightEditText.getText().toString();
+
+ if (TextUtils.isEmpty(name)) {
+ Toast.makeText(MemberChangeActivity.this, "이름을 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (TextUtils.isEmpty(gender)) {
+ Toast.makeText(MemberChangeActivity.this, "성별을 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (TextUtils.isEmpty(birth)) {
+ Toast.makeText(MemberChangeActivity.this, "생일을 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (TextUtils.isEmpty(weight)) {
+ Toast.makeText(MemberChangeActivity.this, "몸무게를 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (TextUtils.isEmpty(height)) {
+ Toast.makeText(MemberChangeActivity.this, "키를 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ Map userData = new HashMap<>();
+ if (user != null) {
+ userData.put("name", name);
+ userData.put("gender", gender);
+ userData.put("birth", birth);
+ userData.put("weight", weight);
+ userData.put("height", height);
+ }
+
+ db.collection("users").document(user.getUid())
+ .update(userData)
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ }
+ });
+ }
+ });
+ }
+
+ private void openFileChooser() {
+ Intent intent = new Intent();
+ intent.setType("image/*");
+ intent.setAction(Intent.ACTION_GET_CONTENT);
+ startActivityForResult(intent, PICK_IMAGE_REQUEST);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
+ imageUri = data.getData();
+
+ ImageView selectedImageView = findViewById(R.id.profile_pic);
+ Glide.with(this).load(imageUri).into(selectedImageView);
+ }
+ }
+
+ private void uploadFile() {
+ final StorageReference oldFileReference = storageRef.child(mAuth.getCurrentUser().getUid() + ".jpg");
+ oldFileReference.delete().addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ // After deleting the old image, upload the new one
+ final StorageReference fileReference = storageRef.child(mAuth.getCurrentUser().getUid() + ".jpg");
+ fileReference.putFile(imageUri)
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
+ fileReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Uri uri) {
+ String downloadUrl = uri.toString();
+ updateImageUrlToFirestore(downloadUrl);
+ }
+ });
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ }
+ });
+ }
+ }).addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ // If the old image doesn't exist, just upload the new one
+ final StorageReference fileReference = storageRef.child(mAuth.getCurrentUser().getUid() + ".jpg");
+ fileReference.putFile(imageUri)
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
+ fileReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Uri uri) {
+ String downloadUrl = uri.toString();
+ updateImageUrlToFirestore(downloadUrl);
+ }
+ });
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ }
+ });
+ }
+ });
+ }
+
+ private void updateImageUrlToFirestore(String url) {
+ Map data = new HashMap<>();
+ data.put("imageUrl", url);
+
+ db.collection("users").document(mAuth.getCurrentUser().getUid())
+ .update(data)
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ }
+ });
+ }
+
+ private void loadImageFromFirestore() {
+ db.collection("users").document(mAuth.getCurrentUser().getUid())
+ .get()
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(DocumentSnapshot documentSnapshot) {
+ if (documentSnapshot.exists()) {
+ String imageUrl = documentSnapshot.getString("imageUrl");
+ if (!TextUtils.isEmpty(imageUrl)) {
+ loadImageIntoImageView(imageUrl);
+ } else {
+ }
+ } else {
+ }
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ }
+ });
+ }
+
+ private void loadImageIntoImageView(String imageUrl) {
+ ImageView userImageView = findViewById(R.id.profile_pic);
+
+ Glide.with(this)
+ .load(imageUrl)
+ .circleCrop()
+ .into(userImageView);
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/MemberInfo.java b/app/src/main/java/com/example/newbody/MemberInfo.java
new file mode 100644
index 0000000..64c0f29
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/MemberInfo.java
@@ -0,0 +1,223 @@
+package com.example.newbody;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.bumptech.glide.Glide;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.storage.FirebaseStorage;
+import com.google.firebase.storage.StorageReference;
+
+import java.util.ArrayList;
+
+public class MemberInfo extends AppCompatActivity {
+
+ Button prev;
+ TextView name, gender, birth, weight, height;
+ ImageView profile;
+
+ private FirebaseFirestore db;
+ private FirebaseAuth mAuth;
+ private Uri imageUri;
+ private StorageReference storageRef;
+ private FirebaseUser user;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_member_info);
+
+ Intent intentV = new Intent(this, VoiceRecognitionService.class);
+ startService(intentV);
+
+ initViews();
+
+ storageRef = FirebaseStorage.getInstance().getReference("profile_pics");
+ loadImageFromFirestore();
+
+ if(user == null){
+ Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
+ startActivity(intent);
+ }else {
+ db.collection("users").document(user.getUid())
+ .get()
+ .addOnCompleteListener(new OnCompleteListener() {
+ @SuppressLint("SetTextI18n")
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ String date = document.getString("birth");
+ int year = Integer.parseInt(date.substring(0, 4));
+ int mm = Integer.parseInt(date.substring(4, 6));
+ int dd = Integer.parseInt(date.substring(6, 8));
+
+ if(document.getString("gender").equals("M") || document.getString("gender").equals("m")){
+ gender.setText("남자");
+ }else if(document.getString("gender").equals("W") || document.getString("gender").equals("w")){
+ gender.setText("여자");
+ }else{
+ gender.setText(document.getString("gender"));
+ }
+ birth.setText(year + "년 " + mm + "월 " + dd + "일");
+ name.setText(document.getString("name") + "님");
+ weight.setText(document.getString("weight")+"kg");
+ height.setText(document.getString("height")+"cm");
+ }
+ } else {
+ }
+ }
+ });
+ }
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ }
+
+ public void initViews(){
+ prev = findViewById(R.id.prevButtonInfo);
+ name = findViewById(R.id.name_info);
+ gender = findViewById(R.id.gender_info);
+ birth = findViewById(R.id.birth_info);
+ weight = findViewById(R.id.weight_info);
+ height = findViewById(R.id.height_info);
+ profile = findViewById(R.id.profile_pic_info);
+
+ db = FirebaseFirestore.getInstance();
+ mAuth = FirebaseAuth.getInstance();
+ user = mAuth.getCurrentUser();
+ }
+
+ private void loadImageFromFirestore() {
+ db.collection("users").document(mAuth.getCurrentUser().getUid())
+ .get()
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(DocumentSnapshot documentSnapshot) {
+ if (documentSnapshot.exists()) {
+ String imageUrl = documentSnapshot.getString("imageUrl");
+ if (!TextUtils.isEmpty(imageUrl)) {
+ loadImageIntoImageView(imageUrl);
+ } else {
+ }
+ } else {
+ }
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ }
+ });
+ }
+
+ private void loadImageIntoImageView(String imageUrl) {
+
+ Glide.with(this)
+ .load(imageUrl)
+ .circleCrop()
+ .into(profile);
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("이전")){
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 10000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 3000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/Membership.java b/app/src/main/java/com/example/newbody/Membership.java
new file mode 100644
index 0000000..c9a6480
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Membership.java
@@ -0,0 +1,199 @@
+package com.example.newbody;
+
+import android.content.Intent;
+import android.graphics.Color;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.google.android.gms.auth.api.signin.GoogleSignIn;
+import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
+import com.google.android.gms.auth.api.signin.GoogleSignInClient;
+import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
+import com.google.android.gms.common.api.ApiException;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.firebase.auth.AuthCredential;
+import com.google.firebase.auth.AuthResult;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.auth.GoogleAuthProvider;
+import com.google.firebase.firestore.FirebaseFirestore;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Membership extends AppCompatActivity {
+ private static final int RC_SIGN_IN = 9001;
+ EditText email, password, passwordCheck;
+ TextView check_text;
+ private boolean passwordCheckCheck = false;
+ View google;
+ private FirebaseAuth mAuth;
+ private FirebaseFirestore db;
+
+ private GoogleSignInClient mGoogleSignInClient;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_membership);
+
+ View register = findViewById(R.id.register);
+ Button login = findViewById(R.id.login);
+
+ google = findViewById(R.id.google);
+
+ mAuth = FirebaseAuth.getInstance();
+ db = FirebaseFirestore.getInstance();
+
+ email = findViewById(R.id.email);
+ password = findViewById(R.id.password);
+ passwordCheck = findViewById(R.id.passwordCheck);
+ check_text = findViewById(R.id.check_text);
+
+ // GoogleSignInClient 객체 초기화
+ GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
+ .requestIdToken(getString(R.string.default_web_client_id))
+ .requestEmail()
+ .build();
+ mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
+
+ passwordCheck.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+ if(password.getText().toString().equals(passwordCheck.getText().toString())) {
+ passwordCheckCheck = true;
+ check_text.setText("비밀번호와 일치합니다. ");
+ check_text.setTextColor(Color.parseColor("#00cc00"));
+ } else {
+ passwordCheckCheck = false;
+ check_text.setText("비밀번호를 확인해주세요. ");
+ check_text.setTextColor(Color.parseColor("#ff3300"));
+ }
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+
+ }
+ });
+
+ register.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ String emailS, passwordS, passwordCheckS;
+ emailS = String.valueOf(email.getText());
+ passwordS = String.valueOf(password.getText());
+ passwordCheckS = String.valueOf(passwordCheck.getText());
+
+ if(TextUtils.isEmpty(emailS)){
+ Toast.makeText(Membership.this, "이메일을 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(TextUtils.isEmpty(passwordS)){
+ Toast.makeText(Membership.this, "비밀번호를 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(TextUtils.isEmpty(passwordCheckS)){
+ Toast.makeText(Membership.this, "비밀번호를 확인하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ if(passwordCheckCheck == true){
+ // Firebase Authentication을 이용하여 사용자를 생성합니다.
+ mAuth.createUserWithEmailAndPassword(emailS, passwordS)
+ .addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ Intent intent = new Intent(getApplicationContext(), Membership1.class);
+ startActivity(intent);
+ finish();
+ } else {
+ Toast.makeText(Membership.this, "회원가입 실패.", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }else{
+ Toast.makeText(Membership.this, "비밀번호를 확인하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ }
+ });
+
+ login.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ google.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent signInIntent = mGoogleSignInClient.getSignInIntent();
+ startActivityForResult(signInIntent, RC_SIGN_IN);
+ }
+ });
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ // GoogleSignInClient.getSignInIntent(...)의 결과 처리
+ if (requestCode == RC_SIGN_IN) {
+ Task task = GoogleSignIn.getSignedInAccountFromIntent(data);
+ try {
+ // Google Sign In이 성공했을 경우, Firebase에 인증
+ GoogleSignInAccount account = task.getResult(ApiException.class);
+ firebaseAuthWithGoogle(account.getIdToken());
+ } catch (ApiException e) {
+ // Google Sign In 실패
+ Toast.makeText(Membership.this, "회원가입 실패", Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ // Google 로그인 토큰을 이용하여 Firebase에 인증
+ private void firebaseAuthWithGoogle(String idToken) {
+ AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null);
+ mAuth.signInWithCredential(credential)
+ .addOnCompleteListener(this, new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ FirebaseUser user = mAuth.getCurrentUser();
+ Intent intent = new Intent(getApplicationContext(), Membership1.class);
+ startActivity(intent);
+ finish();
+ } else {
+ // 인증 실패
+ Toast.makeText(Membership.this, "회원가입 실패", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/Membership1.java b/app/src/main/java/com/example/newbody/Membership1.java
new file mode 100644
index 0000000..bd93bc2
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Membership1.java
@@ -0,0 +1,29 @@
+package com.example.newbody;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+public class Membership1 extends AppCompatActivity {
+
+ View next;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_membership1);
+
+ next = findViewById(R.id.buttonNext01);
+
+ next.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Membership2.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/Membership2.java b/app/src/main/java/com/example/newbody/Membership2.java
new file mode 100644
index 0000000..337b436
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Membership2.java
@@ -0,0 +1,108 @@
+package com.example.newbody;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.database.DatabaseReference;
+import com.google.firebase.database.FirebaseDatabase;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.messaging.FirebaseMessaging;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Membership2 extends AppCompatActivity {
+
+ FirebaseFirestore db;
+ FirebaseAuth mAuth;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_membership2);
+
+ View register = findViewById(R.id.button);
+ db = FirebaseFirestore.getInstance();
+ mAuth = FirebaseAuth.getInstance();
+ register.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ String name = ((EditText) findViewById(R.id.username)).getText().toString();
+ String gender = ((EditText) findViewById(R.id.sex)).getText().toString();
+ String birth = ((EditText) findViewById(R.id.birth)).getText().toString();
+ String weight = ((EditText) findViewById(R.id.weight)).getText().toString();
+ String height = ((EditText) findViewById(R.id.height)).getText().toString();
+
+ if (TextUtils.isEmpty(name)) {
+ Toast.makeText(Membership2.this, "이름을 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (TextUtils.isEmpty(gender)) {
+ Toast.makeText(Membership2.this, "성별을 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (TextUtils.isEmpty(birth)) {
+ Toast.makeText(Membership2.this, "생일을 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (TextUtils.isEmpty(weight)) {
+ Toast.makeText(Membership2.this, "몸무게를 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (TextUtils.isEmpty(height)) {
+ Toast.makeText(Membership2.this, "키를 입력하세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> {
+ if (!task.isSuccessful()) {
+ return;
+ }
+ String token = task.getResult();
+
+ FirebaseUser user = mAuth.getCurrentUser();
+ Map userData = new HashMap<>();
+ if (user != null) {
+ userData.put("name", name);
+ userData.put("gender", gender);
+ userData.put("birth", birth);
+ userData.put("weight", weight);
+ userData.put("height", height);
+ userData.put("fcmToken", token); // 토큰 값을 저장합니다.
+ userData.put("uid", user.getUid());
+ db.collection("users").document(user.getUid())
+ .set(userData)
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ Intent intent = new Intent(getApplicationContext(), Membership4.class);
+ startActivity(intent);
+ finish();
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ }
+ });
+ }
+ });
+
+ }
+ });
+
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/Membership3.java b/app/src/main/java/com/example/newbody/Membership3.java
new file mode 100644
index 0000000..484ae19
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Membership3.java
@@ -0,0 +1,28 @@
+package com.example.newbody;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+public class Membership3 extends AppCompatActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_membership3);
+ Intent intent = new Intent(this, LoadingActivity.class);
+ startActivity(intent);
+
+ View register = findViewById(R.id.button);
+
+ register.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/Membership4.java b/app/src/main/java/com/example/newbody/Membership4.java
new file mode 100644
index 0000000..4069b05
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Membership4.java
@@ -0,0 +1,202 @@
+package com.example.newbody;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.telephony.SmsManager;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.Manifest;
+
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.FirebaseException;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.auth.PhoneAuthCredential;
+import com.google.firebase.auth.PhoneAuthProvider;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.SetOptions;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+public class Membership4 extends AppCompatActivity {
+
+ EditText inputPhoneNum, inputCheckNum;
+ TextView time, check;
+ Button sendSMSBtn, checkBtn;
+ String checkNum;
+ private boolean checkNext = false;
+ static final int SMS_SEND_PERMISSION = 1;
+
+ SharedPreferences pref;
+ SharedPreferences.Editor editor;
+ private FirebaseAuth mAuth;
+ private FirebaseFirestore db;
+ private FirebaseUser user;
+ private String verificationId;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_membership4);
+
+ mAuth = FirebaseAuth.getInstance();
+ db = FirebaseFirestore.getInstance();
+ user = mAuth.getCurrentUser();
+
+ pref = getPreferences(MODE_PRIVATE);
+ editor = pref.edit();
+
+ inputPhoneNum = findViewById(R.id.input_phone_num);
+ sendSMSBtn = findViewById(R.id.send_sms_button);
+ inputCheckNum = findViewById(R.id.input_check_num);
+ checkBtn = findViewById(R.id.check_button);
+ time = findViewById(R.id.timeText);
+ check = findViewById(R.id.checkPhoneNum);
+ View register = findViewById(R.id.button);
+
+ int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS);
+ if(permissionCheck != PackageManager.PERMISSION_GRANTED){
+ if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS)){
+ Toast.makeText(this, "SMS 권한이 필요합니다. ", Toast.LENGTH_SHORT).show();
+ }
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SEND_SMS}, SMS_SEND_PERMISSION);
+ }
+
+ sendSMSBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ String num = "+82 " + inputPhoneNum.getText().toString().substring(1);
+ startPhoneNumberVerification(num);
+ }
+ });
+
+ checkBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ verifyPhoneNumberWithCode(verificationId, inputCheckNum.getText().toString());
+ }
+ });
+
+ register.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(checkNext){
+ savePhoneNumber(user);
+
+ Intent intent = new Intent(getApplicationContext(), Membership5.class);
+ intent.putExtra("uid", user.getUid());
+ startActivity(intent);
+ finish();
+ }else{
+ Toast.makeText(Membership4.this, "전화번호 인증을 해주세요", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }
+
+ private void startPhoneNumberVerification(String phoneNumber) {
+ PhoneAuthProvider.getInstance().verifyPhoneNumber(
+ phoneNumber,
+ 60,
+ TimeUnit.SECONDS,
+ this,
+ new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
+
+ @Override
+ public void onVerificationCompleted(PhoneAuthCredential credential) {
+ signInWithPhoneAuthCredential(credential);
+ }
+
+ @Override
+ public void onVerificationFailed(FirebaseException e) {
+ Toast.makeText(Membership4.this, "인증 불가" + e.getMessage(), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onCodeSent(String verId, PhoneAuthProvider.ForceResendingToken token) {
+ verificationId = verId;
+ Toast.makeText(Membership4.this, "인증번호가 발송되었습니다. ", Toast.LENGTH_SHORT).show();
+ time.setVisibility(View.VISIBLE);
+ }
+ }
+ );
+ }
+
+ private void verifyPhoneNumberWithCode(String verificationId, String code) {
+ PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
+ signInWithPhoneAuthCredential(credential);
+ }
+
+ private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
+ mAuth.signInWithCredential(credential)
+ .addOnCompleteListener(this, task -> {
+ if (task.isSuccessful()) {
+ FirebaseUser user = task.getResult().getUser();
+ check.setText("인증이 완료되었습니다. ");
+ check.setTextColor(Color.parseColor("#00cc00"));
+ checkNext = true;
+ } else {
+ check.setText("인증번호가 일치하지 않습니다. ");
+ check.setTextColor(Color.parseColor("#ff3300"));
+ }
+ });
+ }
+
+ private void savePhoneNumber(FirebaseUser user){
+ Map userData = new HashMap<>();
+ final String collectionName = "users";
+ userData.put("phone", inputPhoneNum.getText().toString());
+
+ DocumentReference userRecordRef = db.collection(collectionName).document(user.getUid());
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ userRecordRef.set(userData, SetOptions.merge())
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ Log.d("Firestore", "Data successfully written!");
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@org.checkerframework.checker.nullness.qual.NonNull Exception e) {
+ Log.w("Firestore", "Error writing document", e);
+ }
+ });
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/Membership5.java b/app/src/main/java/com/example/newbody/Membership5.java
new file mode 100644
index 0000000..9f88f11
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Membership5.java
@@ -0,0 +1,123 @@
+package com.example.newbody;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.RadioButton;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.SetOptions;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Membership5 extends AppCompatActivity {
+
+ private FirebaseAuth mAuth;
+ private FirebaseFirestore db;
+ private FirebaseUser user;
+ private TextView pre1, pre2;
+ private RadioButton radioButton1, radioButton2;
+ private String userUid;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_membership5);
+
+ mAuth = FirebaseAuth.getInstance();
+ db = FirebaseFirestore.getInstance();
+ user = mAuth.getCurrentUser();
+
+ View register = findViewById(R.id.button);
+ radioButton1 = findViewById(R.id.radioButton1);
+ radioButton2 = findViewById(R.id.radioButton2);
+ pre1 = findViewById(R.id.pre1);
+ pre2 = findViewById(R.id.pre2);
+
+ Intent intent = getIntent();
+ userUid = intent.getStringExtra("uid");
+
+ final String[] selectEx = new String[1];
+
+ radioButton1.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (((RadioButton) v).isChecked()) {
+ radioButton2.setChecked(false);
+ selectEx[0] = pre1.getText().toString();
+ }
+ }
+ });
+
+ radioButton2.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (((RadioButton) v).isChecked()) {
+ radioButton1.setChecked(false);
+ selectEx[0] = pre2.getText().toString();
+ }
+ }
+ });
+
+
+ register.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(!radioButton1.isChecked() && !radioButton2.isChecked()){
+ Toast.makeText(Membership5.this, "선호하는 운동을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ savePreference(selectEx[0], user);
+ Intent intent = new Intent(getApplicationContext(), Membership6.class);
+ intent.putExtra("uid", userUid);
+ startActivity(intent);
+ finish();
+ }
+ });
+ }
+
+ private void savePreference(String selectEx, FirebaseUser user){
+ Map userData = new HashMap<>();
+ final String collectionName = "users";
+ userData.put("preference1", selectEx);
+
+ DocumentReference userRecordRef = db.collection(collectionName).document(userUid);
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ userRecordRef.set(userData, SetOptions.merge())
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ Log.d("Firestore", "Data successfully written!");
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@org.checkerframework.checker.nullness.qual.NonNull Exception e) {
+ Log.w("Firestore", "Error writing document", e);
+ }
+ });
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/Membership6.java b/app/src/main/java/com/example/newbody/Membership6.java
new file mode 100644
index 0000000..97bb4e7
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Membership6.java
@@ -0,0 +1,137 @@
+package com.example.newbody;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.RadioButton;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.SetOptions;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Membership6 extends AppCompatActivity {
+
+ private FirebaseAuth mAuth;
+ private FirebaseFirestore db;
+ private FirebaseUser user;
+ private TextView pre1, pre2, pre3;
+ private RadioButton radioButton1, radioButton2, radioButton3;
+ private String userUid;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_membership6);
+
+ mAuth = FirebaseAuth.getInstance();
+ db = FirebaseFirestore.getInstance();
+ user = mAuth.getCurrentUser();
+
+ View register = findViewById(R.id.button);
+ radioButton1 = findViewById(R.id.radioButton1);
+ radioButton2 = findViewById(R.id.radioButton2);
+ radioButton3 = findViewById(R.id.radioButton3);
+ pre1 = findViewById(R.id.ex1);
+ pre2 = findViewById(R.id.ex2);
+ pre3 = findViewById(R.id.ex3);
+
+ Intent intent = getIntent();
+ userUid = intent.getStringExtra("uid");
+
+ final String[] selectEx = new String[1];
+
+ radioButton1.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (((RadioButton) v).isChecked()) {
+ radioButton2.setChecked(false);
+ radioButton3.setChecked(false);
+ selectEx[0] = pre1.getText().toString();
+ }
+ }
+ });
+
+ radioButton2.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (((RadioButton) v).isChecked()) {
+ radioButton1.setChecked(false);
+ radioButton3.setChecked(false);
+ selectEx[0] = pre2.getText().toString();
+ }
+ }
+ });
+
+ radioButton3.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (((RadioButton) v).isChecked()) {
+ radioButton1.setChecked(false);
+ radioButton2.setChecked(false);
+ selectEx[0] = pre3.getText().toString();
+ }
+ }
+ });
+
+
+ register.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(!radioButton1.isChecked() && !radioButton2.isChecked() && !radioButton3.isChecked()){
+ Toast.makeText(Membership6.this, "선호하는 운동을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ savePreference(selectEx[0], user);
+ Intent intent = new Intent(getApplicationContext(), Membership3.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ }
+
+ private void savePreference(String selectEx, FirebaseUser user){
+ Map userData = new HashMap<>();
+ final String collectionName = "users";
+ userData.put("preference2", selectEx);
+
+ DocumentReference userRecordRef = db.collection(collectionName).document(userUid);
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ userRecordRef.set(userData, SetOptions.merge())
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ Log.d("Firestore", "Data successfully written!");
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@org.checkerframework.checker.nullness.qual.NonNull Exception e) {
+ Log.w("Firestore", "Error writing document", e);
+ }
+ });
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/Menu.java b/app/src/main/java/com/example/newbody/Menu.java
new file mode 100644
index 0000000..3fc4560
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Menu.java
@@ -0,0 +1,271 @@
+package com.example.newbody;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.view.MenuItem;
+import android.widget.Toast;
+import android.Manifest;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
+import com.google.android.material.bottomnavigation.BottomNavigationView;
+
+import java.util.ArrayList;
+
+public class Menu extends AppCompatActivity {
+
+ private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 1;
+
+ private BottomNavigationView bottomNavigationView;
+ private FragmentManager fm;
+ private FragmentTransaction ft;
+ private Home home;
+ private Picture picture;
+ private Calendar calendar;
+ private Person person;
+
+ private int selectMenu;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_menu);
+
+ selectMenu = 0;
+ bottomNavigationView = findViewById(R.id.bottomNavi);
+
+ requestMicrophonePermission();
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
+ // 권한이 없으면 요청
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1);
+ }
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+
+ bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
+ @Override
+ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
+ switch(item.getItemId()){
+ case R.id.action_home:
+ selectMenu = 0;
+ setFrag(0);
+ break;
+ case R.id.action_picture:
+ selectMenu = 1;
+ setFrag(1);
+ break;
+ case R.id.action_calendar:
+ selectMenu = 2;
+ setFrag(2);
+ break;
+ case R.id.action_notifications:
+ selectMenu = 3;
+ setFrag(3);
+ break;
+ }
+ return true;
+ }
+ });
+ home = new Home();
+ picture = new Picture();
+ calendar = new Calendar();
+ person = new Person();
+
+ setFrag(0); // 첫 프래그먼트 화면
+ int selectedFragmentIndex = getIntent().getIntExtra("SELECTED_FRAGMENT_INDEX", 0);
+ setFrag(selectedFragmentIndex);
+ }
+
+ // 프래그먼트 교체가 일어나는 실행문
+ private void setFrag(int n){
+ // 먼저 리스너를 제거
+ bottomNavigationView.setOnNavigationItemSelectedListener(null);
+
+ fm = getSupportFragmentManager();
+ ft = fm.beginTransaction();
+ switch (n){
+ case 0:
+ ft.replace(R.id.main_frame, home);
+ ft.commit();
+ bottomNavigationView.setSelectedItemId(R.id.action_home);
+ break;
+ case 1:
+ ft.replace(R.id.main_frame, picture);
+ ft.commit();
+ bottomNavigationView.setSelectedItemId(R.id.action_picture);
+ break;
+ case 2:
+ ft.replace(R.id.main_frame, calendar);
+ ft.commit();
+ bottomNavigationView.setSelectedItemId(R.id.action_calendar);
+ break;
+ case 3:
+ ft.replace(R.id.main_frame, person);
+ ft.commit();
+ bottomNavigationView.setSelectedItemId(R.id.action_notifications);
+ break;
+ }
+
+ // 다시 리스너를 설정
+ bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
+ @Override
+ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
+ switch(item.getItemId()){
+ case R.id.action_home:
+ selectMenu = 0;
+ setFrag(0);
+ break;
+ case R.id.action_picture:
+ selectMenu = 1;
+ setFrag(1);
+ break;
+ case R.id.action_calendar:
+ selectMenu = 2;
+ setFrag(2);
+ break;
+ case R.id.action_notifications:
+ selectMenu = 3;
+ setFrag(3);
+ break;
+ }
+ return true;
+ }
+ });
+ }
+
+ private void requestMicrophonePermission() {
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
+ // 권한이 허용되지 않은 경우 요청
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_REQUEST_RECORD_AUDIO);
+ } else {
+ // 권한이 이미 허용된 경우
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ switch (requestCode) {
+ case PERMISSIONS_REQUEST_RECORD_AUDIO:
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ } else {
+ }
+ break;
+ }
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("홈") || str.equals("홈 화면")){
+ setFrag(0);
+ }else if(str.equals("사진") || str.equals("카메라")){
+ setFrag(1);
+ }else if(str.equals("스케줄러") || str.equals("달력")){
+ setFrag(2);
+ }else if(str.equals("정보") || str.equals("내 정보")){
+ setFrag(3);
+ }
+ if(selectMenu == 0){
+ if(str.equals("자세교정") || str.equals("자세 교정")){
+ Intent intent = new Intent(getApplicationContext(), Posture.class);
+ startActivity(intent);
+ finish();
+ }else if(str.equals("홈트레이닝") || str.equals("홈 트레이닝")){
+ Intent intent = new Intent(getApplicationContext(), Video.class);
+ startActivity(intent);
+ finish();
+ }else if(str.equals("기록측정") || str.equals("기록 측정")){
+ Intent intent = new Intent(getApplicationContext(), Record.class);
+ startActivity(intent);
+ finish();
+ }else if(str.equals("랭킹") || str.equals("순위")){
+ Intent intent = new Intent(getApplicationContext(), Ranking.class);
+ startActivity(intent);
+ finish();
+ }
+ }else if(selectMenu == 1){
+ if(str.equals("사진 촬영") || str.equals("사진촬영")) {
+ ((Picture) picture).takePicture(); // Picture 프래그먼트의 takePicture 메서드 호출
+ }
+ }else if(selectMenu == 3){
+ if(str.equals("수정") || str.equals("정보 수정")){
+ Intent intent = new Intent(getApplicationContext(), MemberChangeActivity.class);
+ startActivity(intent);
+ }
+ }
+ }
+ restartVoiceRecognitionService();
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 10000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 3000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+
+}
diff --git a/app/src/main/java/com/example/newbody/Notice.java b/app/src/main/java/com/example/newbody/Notice.java
new file mode 100644
index 0000000..f8c1fb4
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Notice.java
@@ -0,0 +1,14 @@
+package com.example.newbody;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.os.Bundle;
+
+public class Notice extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_notice);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/OnDateSetListener.java b/app/src/main/java/com/example/newbody/OnDateSetListener.java
new file mode 100644
index 0000000..a5aab0d
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/OnDateSetListener.java
@@ -0,0 +1,6 @@
+package com.example.newbody;
+
+public interface OnDateSetListener {
+ void onDateSet(int year, int month);
+}
+
diff --git a/app/src/main/java/com/example/newbody/PayActivity.java b/app/src/main/java/com/example/newbody/PayActivity.java
new file mode 100644
index 0000000..6be6889
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/PayActivity.java
@@ -0,0 +1,217 @@
+package com.example.newbody;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.Spinner;
+
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.database.DatabaseReference;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.SetOptions;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import kr.co.bootpay.android.Bootpay;
+import kr.co.bootpay.android.events.BootpayEventListener;
+import kr.co.bootpay.android.models.BootExtra;
+import kr.co.bootpay.android.models.BootUser;
+import kr.co.bootpay.android.models.Payload;
+
+public class PayActivity extends AppCompatActivity {
+
+ private String application_id = "64f1c55dd25985001bda77d7";
+
+ private Button prev;
+ private ImageView pay_button;
+
+ private String productName = "프리미엄"; // 상품 이름
+ private String productPrice = "4900"; // 상품 가격
+
+ FirebaseUser user;
+ DatabaseReference databaseReference;
+ FirebaseAuth auth;
+ private FirebaseFirestore db;
+
+ Spinner spinner_pg;
+ Spinner spinner_method;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_pay);
+
+ initViews();
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ pay_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ goRequest();
+ }
+ });
+ }
+
+ public void goRequest() {
+
+ BootUser user = new BootUser().setPhone("010-9175-3460"); // 구매자 정보
+ BootExtra extra = new BootExtra()
+ .setCardQuota("0,2,3"); // 일시불, 2개월, 3개월 할부 허용, 할부는 최대 12개월까지 사용됨 (5만원 이상 구매시 할부허용 범위)
+
+ Double price = 100d;
+
+ String pg = "이니시스";
+ String method = "카드";
+
+ Payload payload = new Payload();
+ payload.setApplicationId(application_id)
+ .setOrderName("프리미엄 멤버십 결제")
+ .setPg(pg)
+ .setOrderId("1234")
+ .setMethod(method)
+ .setPrice(price)
+ .setUser(user)
+ .setExtra(extra);
+
+ Map map = new HashMap<>();
+ map.put("1", "abcdef");
+ map.put("2", "abcdef55");
+ map.put("3", 1234);
+ payload.setMetadata(map);
+
+ Bootpay.init(getSupportFragmentManager(), getApplicationContext())
+ .setPayload(payload)
+ .setEventListener(new BootpayEventListener() {
+ @Override
+ public void onCancel(String data) {
+ Log.d("cancel", data);
+ }
+
+ @Override
+ public void onError(String data) {
+ Log.d("error", data);
+ }
+
+ @Override
+ public void onClose() {
+ Bootpay.removePaymentWindow();
+ }
+
+ @Override
+ public void onIssued(String data) {
+ Log.d("issued", data);
+ }
+
+ @Override
+ public boolean onConfirm(String data) {
+ Log.d("confirm", data);
+// Bootpay.transactionConfirm(data); //재고가 있어서 결제를 진행하려 할때 true (방법 1)
+ return true; //재고가 있어서 결제를 진행하려 할때 true (방법 2)
+// return false; //결제를 진행하지 않을때 false
+ }
+
+ @Override
+ public void onDone(String data) {
+ Log.d("done", data);
+ savePremium();
+ saveOrUpdatePaymentData(productPrice);
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ }
+
+ }).requestPayment();
+ }
+
+ private void savePremium(){
+ Map userData = new HashMap<>();
+ final String collectionName = "users";
+ userData.put("grade", "프리미엄");
+
+ DocumentReference userRecordRef = db.collection(collectionName).document(user.getUid());
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@androidx.annotation.NonNull Task task) {
+ if (task.isSuccessful()) {
+ userRecordRef.set(userData, SetOptions.merge())
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ Log.d("Firestore", "Data successfully written!");
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@org.checkerframework.checker.nullness.qual.NonNull Exception e) {
+ Log.w("Firestore", "Error writing document", e);
+ }
+ });
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+ }
+
+ private void saveOrUpdatePaymentData(String paymentAmount) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
+ String currentDate = sdf.format(new Date());
+ final String collectionName = "payments";
+
+ DocumentReference paymentRecordRef = db.collection(collectionName).document(currentDate);
+ paymentRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@androidx.annotation.NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ // 문서가 이미 존재하면, 금액을 업데이트
+ long existingAmount = document.getLong("amount");
+ long newAmount = existingAmount + Long.parseLong(paymentAmount);
+ paymentRecordRef.update("amount", newAmount);
+ } else {
+ // 문서가 존재하지 않으면, 새로운 문서 생성
+ Map paymentData = new HashMap<>();
+ paymentData.put("amount", Long.parseLong(paymentAmount));
+ paymentRecordRef.set(paymentData);
+ }
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+ }
+
+ public void initViews(){
+ prev = findViewById(R.id.prevButtonPay);
+ pay_button = findViewById(R.id.payButton);
+ auth = FirebaseAuth.getInstance();
+ user = auth.getCurrentUser();
+ db = FirebaseFirestore.getInstance();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/Person.java b/app/src/main/java/com/example/newbody/Person.java
new file mode 100644
index 0000000..d4870ae
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Person.java
@@ -0,0 +1,248 @@
+package com.example.newbody;
+
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
+import com.bumptech.glide.Glide;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class Person extends Fragment {
+ private View view;
+
+ FirebaseAuth auth;
+ Button button, infoButton, goalButton, progressButton, friendListButton, friendButton, payButton, inviteButton;
+ FirebaseUser user;
+
+ FirebaseFirestore db;
+ TextView name, height, weight, age;
+
+ SimpleDateFormat yy, md;
+ Date date;
+ View fixButton, premiumCheckLayout;
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ view = inflater.inflate(R.layout.activity_person, container, false);
+
+ db = FirebaseFirestore.getInstance();
+ auth = FirebaseAuth.getInstance();
+ button = view.findViewById(R.id.logout);
+ name = view.findViewById(R.id.user_name);
+ height = view.findViewById(R.id.height_data);
+ weight = view.findViewById(R.id.weight_data);
+ age = view.findViewById(R.id.age_data);
+ infoButton = view.findViewById(R.id.info_button);
+ goalButton = view.findViewById(R.id.goal_button);
+ progressButton = view.findViewById(R.id.progress_button);
+ friendListButton = view.findViewById(R.id.friend_list_button);
+ friendButton = view.findViewById(R.id.friend_button);
+ inviteButton = view.findViewById(R.id.friend_invite_button);
+ payButton = view.findViewById(R.id.pay_button);
+ premiumCheckLayout = view.findViewById(R.id.premium_check_layout);
+
+ user = auth.getCurrentUser();
+ date = new Date();
+ yy = new SimpleDateFormat("yyyy");
+ md = new SimpleDateFormat("MMdd");
+
+ fixButton = view.findViewById(R.id.fix);
+
+ premiumCheck();
+
+ fixButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), MemberChangeActivity.class);
+ startActivity(intent);
+ }
+ });
+
+ db.collection("users").document(user.getUid())
+ .get()
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(DocumentSnapshot documentSnapshot) {
+ if (documentSnapshot.exists()) {
+ String imageUrl = documentSnapshot.getString("imageUrl");
+ if (!TextUtils.isEmpty(imageUrl)) {
+ loadImageIntoImageView(imageUrl);
+ } else {
+ }
+ } else {
+
+ }
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ }
+ });
+
+ if(user == null){
+ Intent intent = new Intent(getActivity(), LoginActivity.class);
+ startActivity(intent);
+ }else{
+ db.collection("users").document(user.getUid())
+ .get()
+ .addOnCompleteListener(new OnCompleteListener() {
+ @SuppressLint("SetTextI18n")
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ int yearNum = Integer.parseInt(yy.format(date));
+ int mdNum = Integer.parseInt(md.format(date));
+ String birth = document.getString("birth");
+ int year = Integer.parseInt(birth.substring(0, 4));
+ int md = Integer.parseInt(birth.substring(4, 8));
+
+ if(md < mdNum){
+ age.setText(Integer.toString(yearNum-year));
+ }else{
+ age.setText(Integer.toString(yearNum-year-1));
+ }
+
+ name.setText(document.getString("name"));
+ weight.setText(document.getString("weight"));
+ height.setText(document.getString("height"));
+ } else {
+ age.setText("0");
+ name.setText("0");
+ weight.setText("0");
+ height.setText("0");
+ }
+ } else {
+ // handle the failure case
+ }
+ }
+ });
+ }
+
+ infoButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), MemberInfo.class);
+ startActivity(intent);
+ }
+ });
+
+ goalButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), Target.class);
+ startActivity(intent);
+ }
+ });
+ progressButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), Graph.class);
+ startActivity(intent);
+ }
+ });
+
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ FirebaseAuth.getInstance().signOut();
+ Intent intent = new Intent(getActivity(), LoginActivity.class);
+ startActivity(intent);
+ }
+ });
+
+ friendListButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), FriendListPlus.class);
+ startActivity(intent);
+ }
+ });
+
+ friendButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), FriendList.class);
+ startActivity(intent);
+ }
+ });
+
+ inviteButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), FriendInvite.class);
+ startActivity(intent);
+ }
+ });
+
+ payButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getActivity(), PayActivity.class);
+ startActivity(intent);
+ }
+ });
+
+ return view;
+ }
+
+ private void loadImageIntoImageView(String imageUrl) {
+ ImageView userImageView = view.findViewById(R.id.profile_pic); // Replace with your ImageView's ID
+
+ Glide.with(this)
+ .load(imageUrl)
+ .circleCrop()
+ .into(userImageView);
+ }
+
+ public void premiumCheck(){
+ if(user == null){
+ Intent intent = new Intent(getActivity(), LoginActivity.class);
+ startActivity(intent);
+ }else{
+ db.collection("users").document(user.getUid())
+ .get()
+ .addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@androidx.annotation.NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ String grade = document.getString("grade");
+ if (grade == null) grade = "일반";
+
+ if(grade.equals("프리미엄")){
+ premiumCheckLayout.setVisibility(View.GONE);
+ }
+ }
+ } else {
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/Picture.java b/app/src/main/java/com/example/newbody/Picture.java
new file mode 100644
index 0000000..50a0a7a
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Picture.java
@@ -0,0 +1,127 @@
+package com.example.newbody;
+
+import android.app.Activity;
+import android.Manifest;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.MediaStore;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.GridView;
+import android.widget.ImageView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.Fragment;
+
+import java.io.OutputStream;
+import java.util.ArrayList;
+
+public class Picture extends Fragment {
+ private static final int PERMISSIONS_REQUEST_CAMERA = 2;
+ static final int REQUEST_IMAGE_CAPTURE = 1;
+ private View view;
+ private View camera_button;
+ private Bitmap currentImageBitmap;
+ private Button save;
+ private Uri imageUri;
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.activity_picture, container, false);
+
+ camera_button = view.findViewById(R.id.camera_button);
+ save = view.findViewById(R.id.saveButton);
+
+ camera_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ requestCameraPermission();
+ Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
+ startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
+ }
+ }
+ });
+
+ save.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (currentImageBitmap != null) {
+ saveToGallery(currentImageBitmap);
+ }
+ Toast.makeText(getActivity(), "사진이 저장되었습니다", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ return view;
+ }
+
+ public void takePicture() {
+ requestCameraPermission();
+ Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
+ startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
+ }
+ }
+
+
+ private void requestCameraPermission() {
+ if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
+ != PackageManager.PERMISSION_GRANTED) {
+ ActivityCompat.requestPermissions(getActivity(),
+ new String[]{Manifest.permission.CAMERA},
+ PERMISSIONS_REQUEST_CAMERA);
+ }
+ }
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ if (requestCode == PERMISSIONS_REQUEST_CAMERA) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ // 카메라 권한이 승인됐을 때 실행할 코드를 여기에 작성합니다.
+ } else {
+ // 사용자가 권한 요청을 거부했을 때 실행할 코드를 여기에 작성합니다.
+ }
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
+ save.setVisibility(View.VISIBLE);
+ Bundle extras = data.getExtras();
+ currentImageBitmap = (Bitmap) extras.get("data");
+
+ ImageView imageView = (ImageView) getView().findViewById(R.id.pic_image);
+ imageView.setImageBitmap(currentImageBitmap);
+ }
+ }
+
+ private void saveToGallery(Bitmap bitmap) {
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.Images.Media.TITLE, "New Picture");
+ values.put(MediaStore.Images.Media.DESCRIPTION, "From Camera");
+ values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
+
+ Uri uri = getActivity().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
+
+ try {
+ OutputStream outputStream = getActivity().getContentResolver().openOutputStream(uri);
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
+ outputStream.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/example/newbody/PoseMatcher.java b/app/src/main/java/com/example/newbody/PoseMatcher.java
new file mode 100644
index 0000000..4926fb8
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/PoseMatcher.java
@@ -0,0 +1,77 @@
+package com.example.newbody;
+
+import static java.lang.Math.abs;
+import static java.lang.Math.atan2;
+import static java.lang.Math.toDegrees;
+
+import com.google.mlkit.vision.pose.Pose;
+import com.google.mlkit.vision.pose.PoseLandmark;
+
+public class PoseMatcher {
+
+ private static final double OFFSET = 15.0;
+
+ public boolean match(Pose pose, TargetPose targetPose) {
+ return extractAndMatch(pose, targetPose);
+ }
+
+ public boolean extractAndMatch(Pose pose, TargetPose targetPose) {
+ for (TargetShape target : targetPose.getTargets()) {
+ LandmarkTriple triple = extractLandmark(pose, target);
+ PoseLandmark firstLandmark = triple.getFirstLandmark();
+ PoseLandmark middleLandmark = triple.getMiddleLandmark();
+ PoseLandmark lastLandmark = triple.getLastLandmark();
+
+ if (landmarkNotFound(firstLandmark, middleLandmark, lastLandmark)) {
+ return false;
+ }
+
+ double angle = calculateAngle(firstLandmark, middleLandmark, lastLandmark);
+ double targetAngle = target.getAngle();
+
+ if (abs(angle - targetAngle) > OFFSET) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public LandmarkTriple extractLandmark(Pose pose, TargetShape target) {
+ return new LandmarkTriple(
+ extractLandmarkFromType(pose, target.getFirstLandmarkType()),
+ extractLandmarkFromType(pose, target.getMiddleLandmarkType()),
+ extractLandmarkFromType(pose, target.getLastLandmarkType())
+ );
+ }
+
+ public PoseLandmark extractLandmarkFromType(Pose pose, int landmarkType) {
+ return pose.getPoseLandmark(landmarkType);
+ }
+
+ public boolean landmarkNotFound(PoseLandmark firstLandmark, PoseLandmark middleLandmark, PoseLandmark lastLandmark) {
+ return firstLandmark == null || middleLandmark == null || lastLandmark == null;
+ }
+
+ public double calculateAngle(PoseLandmark firstLandmark, PoseLandmark middleLandmark, PoseLandmark lastLandmark) {
+ double angle = toDegrees(
+ atan2(
+ lastLandmark.getPosition().y - middleLandmark.getPosition().y,
+ lastLandmark.getPosition().x - middleLandmark.getPosition().x
+ ) - atan2(
+ firstLandmark.getPosition().y - middleLandmark.getPosition().y,
+ firstLandmark.getPosition().x - middleLandmark.getPosition().x
+ )
+ );
+
+ double absoluteAngle = abs(angle);
+ if (absoluteAngle > 180) {
+ absoluteAngle = 360 - absoluteAngle;
+ }
+ return absoluteAngle;
+ }
+
+ public boolean anglesMatch(double angle, double targetAngle) {
+ return angle < targetAngle + OFFSET && angle > targetAngle - OFFSET;
+ }
+}
+
diff --git a/app/src/main/java/com/example/newbody/Posture.java b/app/src/main/java/com/example/newbody/Posture.java
new file mode 100644
index 0000000..647544b
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Posture.java
@@ -0,0 +1,401 @@
+package com.example.newbody;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CompoundButton;
+import android.widget.Switch;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.newbody.posture.PostureInfo;
+import com.example.newbody.record.RecordDumbbell;
+import com.example.newbody.record.RecordLegRaise;
+import com.example.newbody.record.RecordPushup;
+import com.example.newbody.record.RecordSidelateralraise;
+import com.example.newbody.record.RecordSquat;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.QueryDocumentSnapshot;
+import com.google.firebase.firestore.QuerySnapshot;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+import java.util.ArrayList;
+
+
+public class Posture extends AppCompatActivity {
+ private View ex_start;
+ private View []ex = new View[8];
+ private TextView []exName = new TextView[8];
+ private TextView []premiumMessage = new TextView[3];
+ private View []lockButton = new View[3];
+ private TextView selectE, pre1, pre2;
+ private Button prev;
+ private Switch customized;
+ private View squatView, pushupView, dumbbellView, sideView, legView, dumbbellCurlView, dumbbellFlyView, dumbbellTricepsView;
+ private FirebaseAuth mAuth;
+ private FirebaseFirestore db;
+ private FirebaseUser user;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.acticity_posture);
+
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+
+ initViews();
+ premiumCheck();
+
+ customized.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ if(customized.isChecked()){
+ pre1.setText(" ");
+ pre2.setText(" ");
+ DocumentReference userRecordRef = db.collection("users").document(user.getUid());
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ String preference1 = document.getString("preference1");
+ pre1.setText(preference1);
+ String preference2 = document.getString("preference2");
+ pre2.setText(preference2);
+
+ if(preference1.equals("도구 이용 운동")){
+ squatView.setVisibility(View.GONE);
+ pushupView.setVisibility(View.GONE);
+ legView.setVisibility(View.GONE);
+ }else if(preference1.equals("맨몸 운동")){
+ dumbbellCurlView.setVisibility(View.GONE);
+ dumbbellFlyView.setVisibility(View.GONE);
+ dumbbellTricepsView.setVisibility(View.GONE);
+ if(preference2.equals("팔 운동")){
+ squatView.setVisibility(View.GONE);
+ dumbbellView.setVisibility(View.GONE);
+ sideView.setVisibility(View.GONE);
+ legView.setVisibility(View.GONE);
+ }else if(preference2.equals("하체 운동")){
+ pushupView.setVisibility(View.GONE);
+ dumbbellView.setVisibility(View.GONE);
+ sideView.setVisibility(View.GONE);
+ }else if(preference2.equals("복근 운동")){
+ squatView.setVisibility(View.GONE);
+ dumbbellView.setVisibility(View.GONE);
+ sideView.setVisibility(View.GONE);
+ }
+ }
+ } else {
+ Log.d("Firestore", "No such document");
+ }
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+ }else if(!customized.isChecked()){
+ squatView.setVisibility(View.VISIBLE);
+ pushupView.setVisibility(View.VISIBLE);
+ dumbbellView.setVisibility(View.VISIBLE);
+ sideView.setVisibility(View.VISIBLE);
+ legView.setVisibility(View.VISIBLE);
+ dumbbellCurlView.setVisibility(View.VISIBLE);
+ dumbbellFlyView.setVisibility(View.VISIBLE);
+ dumbbellTricepsView.setVisibility(View.VISIBLE);
+ }
+ }
+ });
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ ex[0].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[0].getText());
+ }
+ });
+ ex[1].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[1].getText());
+ }
+ });
+ ex[2].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[2].getText());
+ }
+ });
+
+ ex[3].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[3].getText());
+ }
+ });
+
+ ex[4].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[4].getText());
+ }
+ });
+
+ ex[5].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[5].getText());
+ }
+ });
+
+ ex[6].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[6].getText());
+ }
+ });
+
+ ex[7].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[7].getText());
+ }
+ });
+
+ lockButton[0].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Toast.makeText(Posture.this, "프리미엄 전용 운동입니다", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ lockButton[1].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Toast.makeText(Posture.this, "프리미엄 전용 운동입니다", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ lockButton[2].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Toast.makeText(Posture.this, "프리미엄 전용 운동입니다", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ ex_start.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(selectE.getText().equals("운동")){
+ Toast.makeText(Posture.this, "운동을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ Intent intent = new Intent(getApplicationContext(), PostureInfo.class);
+ intent.putExtra("exercise", selectE.getText());
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ }
+ private void initViews(){
+ ex_start = findViewById(R.id.start_button);
+ ex[0] = findViewById(R.id.ex_button1);
+ ex[1] = findViewById(R.id.ex_button2);
+ ex[2] = findViewById(R.id.ex_button3);
+ ex[3] = findViewById(R.id.ex_button4);
+ ex[4] = findViewById(R.id.ex_button5);
+ ex[5] = findViewById(R.id.ex_button6);
+ ex[6] = findViewById(R.id.ex_button7);
+ ex[7] = findViewById(R.id.ex_button8);
+ exName[0] = findViewById(R.id.ex1_name);
+ exName[1] = findViewById(R.id.ex2_name);
+ exName[2] = findViewById(R.id.ex3_name);
+ exName[3] = findViewById(R.id.ex4_name);
+ exName[4] = findViewById(R.id.ex5_name);
+ exName[5] = findViewById(R.id.ex6_name);
+ exName[6] = findViewById(R.id.ex7_name);
+ exName[7] = findViewById(R.id.ex8_name);
+ selectE = findViewById(R.id.exercise_select);
+ prev = findViewById(R.id.prevButton);
+ squatView = findViewById(R.id.squatView1);
+ pushupView = findViewById(R.id.pushupView1);
+ dumbbellView = findViewById(R.id.dumbbellView1);
+ sideView = findViewById(R.id.sideView1);
+ legView = findViewById(R.id.legView1);
+ dumbbellCurlView = findViewById(R.id.dumbbellCurlView);
+ dumbbellFlyView = findViewById(R.id.dumbbellFlyView);
+ dumbbellTricepsView = findViewById(R.id.dumbbellTricepsView);
+ customized = findViewById(R.id.customized2);
+ mAuth = FirebaseAuth.getInstance();
+ db = FirebaseFirestore.getInstance();
+ user = mAuth.getCurrentUser();
+ pre1 = findViewById(R.id.pre11);
+ pre2 = findViewById(R.id.pre22);
+ premiumMessage[0] = findViewById(R.id.premiumMessage6);
+ premiumMessage[1] = findViewById(R.id.premiumMessage7);
+ premiumMessage[2] = findViewById(R.id.premiumMessage8);
+ lockButton[0] = findViewById(R.id.ex_lock_button6);
+ lockButton[1] = findViewById(R.id.ex_lock_button7);
+ lockButton[2] = findViewById(R.id.ex_lock_button8);
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("스쿼트") || str.equals("푸쉬업") || str.equals("푸시업") || str.equals("덤벨 숄더 프레스") || str.equals("덤벨 숄더") || str.equals("덤벨숄더프레스") ||
+ str.equals("사이드 레터럴 레이즈") || str.equals("사레레") || str.equals("사이드레터럴레이즈") || str.equals("레그 레이즈") || str.equals("레그레이즈") ||
+ str.equals("덤벨컬") || str.equals("덤벨 컬") || str.equals("덤벨 플라이") || str.equals("덤벨플라이") || str.equals("덤벨 트라이셉스 익스텐션") || str.equals("덤벨 트라이")){
+ if(str.equals("스쿼트")){
+ selectE.setText(exName[0].getText());
+ }else if(str.equals("푸쉬업") || str.equals("푸시업")){
+ selectE.setText(exName[1].getText());
+ }else if(str.equals("덤벨 숄더 프레스") || str.equals("덤벨 숄더") || str.equals("덤벨숄더프레스")){
+ selectE.setText(exName[2].getText());
+ }else if(str.equals("사이드 레터럴 레이즈") || str.equals("사레레") || str.equals("사이드레터럴레이즈")){
+ selectE.setText(exName[3].getText());
+ }else if(str.equals("레그 레이즈") || str.equals("레그레이즈")){
+ selectE.setText(exName[4].getText());
+ }else if(str.equals("덤벨컬") || str.equals("덤벨 컬")){
+ selectE.setText(exName[5].getText());
+ }else if(str.equals("덤벨 플라이") || str.equals("덤벨플라이")){
+ selectE.setText(exName[6].getText());
+ }else if(str.equals("덤벨 트라이셉스 익스텐션") || str.equals("덤벨 트라이")){
+ selectE.setText(exName[7].getText());
+ }
+ }else if(str.equals("시작") || str.equals("운동 시작")){
+ if(selectE.getText().equals("운동")){
+ Toast.makeText(Posture.this, "운동을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ Intent intent = new Intent(getApplicationContext(), PostureInfo.class);
+ intent.putExtra("exercise", selectE.getText());
+ startActivity(intent);
+ finish();
+ }else if(str.equals("이전")){
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 10000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 3000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+
+ public void premiumCheck(){
+ if(user == null){
+ Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
+ startActivity(intent);
+ }else{
+ db.collection("users").document(user.getUid())
+ .get()
+ .addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@androidx.annotation.NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ String grade = document.getString("grade");
+ if (grade == null) grade = "일반";
+
+ if(grade.equals("프리미엄")){
+ customized.setVisibility(View.VISIBLE);
+ premiumMessage[0].setVisibility(View.GONE);
+ premiumMessage[1].setVisibility(View.GONE);
+ premiumMessage[2].setVisibility(View.GONE);
+ lockButton[0].setVisibility(View.GONE);
+ lockButton[1].setVisibility(View.GONE);
+ lockButton[2].setVisibility(View.GONE);
+ ex[5].setVisibility(View.VISIBLE);
+ ex[6].setVisibility(View.VISIBLE);
+ ex[7].setVisibility(View.VISIBLE);
+ }
+ }
+ } else {
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/PushMessage/AndroidNewFCM.java b/app/src/main/java/com/example/newbody/PushMessage/AndroidNewFCM.java
new file mode 100644
index 0000000..9b60b2c
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/PushMessage/AndroidNewFCM.java
@@ -0,0 +1,143 @@
+package com.example.newbody.PushMessage;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Button;
+import android.widget.Toast;
+import com.example.newbody.Membership3;
+import com.example.newbody.R;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.messaging.FirebaseMessaging;
+
+import org.json.JSONObject;
+
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+public class AndroidNewFCM extends AppCompatActivity {
+
+ @BindView(R.id.btn_get_token)
+ Button btn_get_token;
+
+ private static final String TAG = "AndroidNewFCM";
+ private FirebaseFirestore db;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_android_new_fcm);
+ ButterKnife.bind(this);
+
+ db = FirebaseFirestore.getInstance();
+
+ btn_get_token.setOnClickListener((view) -> {
+ FirebaseMessaging.getInstance().getToken()
+ .addOnSuccessListener(token -> {
+ Log.d(TAG, token);
+
+ // 토큰을 Firestore에 저장하는 로직
+ Map tokenData = new HashMap<>();
+ tokenData.put("token", token);
+
+ db.collection("pushMessage").add(tokenData)
+ .addOnSuccessListener(documentReference -> Log.d(TAG, "Token saved with ID: " + documentReference.getId()))
+ .addOnFailureListener(e -> Log.w(TAG, "Error adding token", e));
+
+ })
+ .addOnFailureListener(e -> Toast.makeText(this, "Failed to get token", Toast.LENGTH_SHORT).show());
+ });
+
+ }
+
+ public void saveUserDataAndNotification(String userUID, Map userData, String name) {
+ db.collection("users").document(userUID)
+ .set(userData)
+ .addOnSuccessListener(aVoid -> {
+ FirebaseMessaging.getInstance().getToken()
+ .addOnCompleteListener(task -> {
+ if (!task.isSuccessful()) {
+ Log.w(TAG, "Fetching FCM registration token failed", task.getException());
+ return;
+ }
+ String token = task.getResult();
+ Map tokenData = new HashMap<>();
+ tokenData.put("token", token);
+
+ db.collection("pushMessage").add(tokenData)
+ .addOnSuccessListener(documentReference -> Log.d(TAG, "Token saved with ID: " + documentReference.getId()))
+ .addOnFailureListener(e -> Log.w(TAG, "Error adding token", e));
+ })
+ .addOnFailureListener(e -> {
+ Log.w(TAG, "Failed to get FCM token", e);
+ });
+
+ Map notificationData = new HashMap<>();
+ notificationData.put("title", "환영합니다!");
+ notificationData.put("body", name + "님 회원가입을 축하합니다.");
+
+ db.collection("pushMessage").add(notificationData)
+ .addOnSuccessListener(documentReference -> {
+ Log.d("Firestore", "Notification saved with ID: " + documentReference.getId());
+ PushNotificationService pushService = new PushNotificationService();
+ pushService.sendNotificationToUser(userUID, "환영합니다!", name + "님 회원가입을 축하합니다.");
+ })
+ .addOnFailureListener(e -> Log.w("Firestore", "Error adding notification", e));
+
+ Toast.makeText(AndroidNewFCM.this, "Data saved successfully.", Toast.LENGTH_SHORT).show();
+ Intent intent = new Intent(getApplicationContext(), Membership3.class);
+ startActivity(intent);
+ finish();
+ })
+ .addOnFailureListener(e -> {
+ Log.w(TAG, "Failed to set user data in Firestore", e);
+ Toast.makeText(AndroidNewFCM.this, "Failed to save data.", Toast.LENGTH_SHORT).show();
+ });
+ }
+}
+
+class PushNotificationService {
+ public void sendNotificationToUser(String userFCMToken, String title, String body) {
+ try {
+ String fcmUrl = "https://fcm.googleapis.com/fcm/send";
+ JSONObject root = new JSONObject();
+ JSONObject notification = new JSONObject();
+ notification.put("title", title);
+ notification.put("body", body);
+ root.put("notification", notification);
+ root.put("to", userFCMToken);
+
+ URL url = new URL(fcmUrl);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("POST");
+ connection.setDoOutput(true);
+ connection.setDoInput(true);
+ String serverKey = "BKKukGOqiZ3gPBnvKuH4WQ4g8uuKisF5vSYw4o6DRLjqlF3g6EGBZPCFKxgRYeMiUTgqlWgfjHMMx1-MRDzopIQ";
+ connection.setRequestProperty("Authorization", "key=" + serverKey);
+ connection.setRequestProperty("Content-Type", "application/json");
+
+ OutputStream os = connection.getOutputStream();
+ os.write(root.toString().getBytes("UTF-8"));
+ os.close();
+
+ int responseCode = connection.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ Log.d("FCM", "Notification sent successfully");
+ } else {
+ Log.e("FCM", "Failed to send notification. Response code: " + responseCode);
+ }
+ } catch (Exception e) {
+ Log.e("FCM", "Exception while sending notification", e);
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/PushMessage/MyFirebaseService.java b/app/src/main/java/com/example/newbody/PushMessage/MyFirebaseService.java
new file mode 100644
index 0000000..4c51a33
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/PushMessage/MyFirebaseService.java
@@ -0,0 +1,31 @@
+package com.example.newbody.PushMessage;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.google.firebase.messaging.FirebaseMessagingService;
+import com.google.firebase.messaging.RemoteMessage;
+import com.google.gson.Gson;
+
+public class MyFirebaseService extends FirebaseMessagingService {
+ @Override
+ public void onNewToken(@NonNull String token) {
+ super.onNewToken(token);
+ //Submit to save with you need
+ Log.d(Utils.TAG,token);
+ }
+
+ @Override
+ public void onMessageReceived(@NonNull RemoteMessage message) {
+ super.onMessageReceived(message);
+ //show notification when we receive it
+ String title = message.getNotification().getTitle();
+ String content = message.getNotification().getBody();
+ String data = new Gson().toJson(message.getData());
+
+ //Create notification to show
+ Utils.showNotification(this,title,content);
+ //Show raw data by log
+ Log.d(Utils.TAG,data);
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/PushMessage/Utils.java b/app/src/main/java/com/example/newbody/PushMessage/Utils.java
new file mode 100644
index 0000000..d720222
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/PushMessage/Utils.java
@@ -0,0 +1,45 @@
+package com.example.newbody.PushMessage;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Build;
+
+import androidx.core.app.NotificationCompat;
+
+import com.example.newbody.R;
+
+import java.util.Random;
+
+public class Utils {
+ public static final String TAG = "EDMTDEV";
+
+ public static void showNotification(Context context,String title,String body) {
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context,"edmt.dev.channel");
+
+ builder.setSmallIcon(R.drawable.ic_launcher_background);
+ builder.setContentTitle(title);
+ builder.setContentText(body);
+ builder.setPriority(NotificationCompat.PRIORITY_MAX);
+
+ //style
+ NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
+ bigTextStyle.bigText(title);
+ bigTextStyle.setBigContentTitle(title);
+ bigTextStyle.setSummaryText(title);
+
+ builder.setStyle(bigTextStyle);
+
+ NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
+ String channelId = "edmt.dev.channel.id";
+ NotificationChannel channel = new NotificationChannel(channelId, "EDMTDEV Channel",
+ NotificationManager.IMPORTANCE_HIGH);
+ manager.createNotificationChannel(channel);
+ builder.setChannelId(channelId);
+ }
+
+ manager.notify(new Random().nextInt(),builder.build());
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/Ranking.java b/app/src/main/java/com/example/newbody/Ranking.java
new file mode 100644
index 0000000..cfec0b3
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Ranking.java
@@ -0,0 +1,494 @@
+package com.example.newbody;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.Query;
+import com.google.firebase.firestore.QueryDocumentSnapshot;
+import com.google.firebase.firestore.QuerySnapshot;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class Ranking extends AppCompatActivity {
+
+ private Button prev, range, exercise, time, ranking_button;
+ private String select_time, select_ex, select_range;
+ private ArrayList uidList;
+ private View rankingView;
+
+ private RecyclerView rankingRecyclerView;
+ private RankingAdapter adapter;
+ private FirebaseFirestore db;
+ private FirebaseUser user;
+ private List rankingList = new ArrayList<>();
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_ranking);
+
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+
+ initViews();
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ range.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {showRangeDialog();}
+ });
+ exercise.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {showExerciseDialog();}
+ });
+ time.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {showTimeDialog();}
+ });
+
+ ranking_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(range.getText().equals("범위")){
+ Toast.makeText(Ranking.this, "범위를 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(exercise.getText().equals("운동")){
+ Toast.makeText(Ranking.this, "운동을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(time.getText().equals("시간")){
+ Toast.makeText(Ranking.this, "시간을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ rankingView.setVisibility(View.VISIBLE);
+ db = FirebaseFirestore.getInstance();
+ rankingRecyclerView.setLayoutManager(new LinearLayoutManager(Ranking.this));
+
+ fetchData();
+ adapter = new RankingAdapter(rankingList);
+ rankingRecyclerView.setAdapter(adapter);
+ }
+ });
+ }
+ public void initViews(){
+ prev = findViewById(R.id.prevButtonRanking);
+ range = findViewById(R.id.range);
+ exercise = findViewById(R.id.exercise);
+ time = findViewById(R.id.timeRanking);
+ ranking_button = findViewById(R.id.ranking_info_button);
+ rankingRecyclerView = findViewById(R.id.rankingRecyclerView);
+ rankingView = findViewById(R.id.layout_ranking);
+ uidList = new ArrayList<>();
+ }
+
+ private void showTimeDialog() {
+ final String[] difficultyOptions = {"1분", "2분", "3분"};
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("시간 선택");
+ builder.setItems(difficultyOptions, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ select_time = difficultyOptions[which];
+ time.setText(select_time);
+ }
+ });
+ builder.show();
+ }
+
+ private void showExerciseDialog() {
+ final String[] exOptions = {"스쿼트", "푸쉬업", "덤벨 숄더 프레스", "사이드 레터럴 레이즈", "레그 레이즈", "덤벨 컬", "덤벨 플라이", "덤벨 트라이셉스 익스텐션"};
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("운동 선택");
+ builder.setItems(exOptions, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ select_ex = exOptions[which];
+ exercise.setText(select_ex);
+ }
+ });
+ builder.show();
+ }
+ private void showRangeDialog() {
+ final String[] rangeOptions = {"전체", "친구"};
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("범위 선택");
+ builder.setItems(rangeOptions, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ select_range = rangeOptions[which];
+ range.setText(select_range);
+ }
+ });
+ builder.show();
+ }
+
+ private void fetchData() {
+ AtomicInteger rank_in = new AtomicInteger(1);
+ rankingList.clear();
+ String collectionName = null;
+ if(range.getText().equals("전체")){
+ if(exercise.getText().equals("스쿼트")){
+ if(time.getText().equals("1분")){
+ collectionName = "countSquat1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countSquat2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countSquat3Minute";
+ }
+ }else if(exercise.getText().equals("푸쉬업")){
+ if(time.getText().equals("1분")){
+ collectionName = "countPushup1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countPushup2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countPushup3Minute";
+ }
+ }else if(exercise.getText().equals("덤벨 숄더 프레스")){
+ if(time.getText().equals("1분")){
+ collectionName = "countDumbbell1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countDumbbell2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countDumbbell3Minute";
+ }
+ }else if(exercise.getText().equals("사이드 레터럴 레이즈")){
+ if(time.getText().equals("1분")){
+ collectionName = "countSide1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countSide2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countSide3Minute";
+ }
+ }else if(exercise.getText().equals("레그 레이즈")){
+ if(time.getText().equals("1분")){
+ collectionName = "countLeg1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countLeg2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countLeg3Minute";
+ }
+ }else if(exercise.getText().equals("덤벨 컬")){
+ if(time.getText().equals("1분")){
+ collectionName = "countCurl1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countCurl2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countCurl3Minute";
+ }
+ }else if(exercise.getText().equals("덤벨 플라이")){
+ if(time.getText().equals("1분")){
+ collectionName = "countFly1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countFly2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countFly3Minute";
+ }
+ }else if(exercise.getText().equals("덤벨 트라이셉스 익스텐션")){
+ if(time.getText().equals("1분")){
+ collectionName = "countTriceps1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countTriceps2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countTriceps3Minute";
+ }
+ }
+ String finalCollectionName = collectionName;
+ db.collection(collectionName).orderBy(collectionName, Query.Direction.DESCENDING)
+ .get()
+ .addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ for (QueryDocumentSnapshot document : task.getResult()) {
+ String name = document.getString("name");
+ int score = document.getLong(finalCollectionName).intValue();
+
+ rankingList.add(new RankingItem(rank_in.get(), name, score));
+ rank_in.getAndIncrement();
+ }
+ adapter.notifyDataSetChanged();
+ }
+ });
+ }else if(range.getText().equals("친구")){
+ if(exercise.getText().equals("스쿼트")){
+ if(time.getText().equals("1분")){
+ collectionName = "countSquat1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countSquat2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countSquat3Minute";
+ }
+ }else if(exercise.getText().equals("푸쉬업")){
+ if(time.getText().equals("1분")){
+ collectionName = "countPushup1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countPushup2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countPushup3Minute";
+ }
+ }else if(exercise.getText().equals("덤벨 숄더 프레스")){
+ if(time.getText().equals("1분")){
+ collectionName = "countDumbbell1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countDumbbell2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countDumbbell3Minute";
+ }
+ }else if(exercise.getText().equals("사이드 레터럴 레이즈")){
+ if(time.getText().equals("1분")){
+ collectionName = "countSide1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countSide2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countSide3Minute";
+ }
+ }else if(exercise.getText().equals("레그 레이즈")){
+ if(time.getText().equals("1분")){
+ collectionName = "countLeg1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countLeg2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countLeg3Minute";
+ }
+ }else if(exercise.getText().equals("덤벨 컬")){
+ if(time.getText().equals("1분")){
+ collectionName = "countCurl1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countCurl2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countCurl3Minute";
+ }
+ }else if(exercise.getText().equals("덤벨 플라이")){
+ if(time.getText().equals("1분")){
+ collectionName = "countFly1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countFly2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countFly3Minute";
+ }
+ }else if(exercise.getText().equals("덤벨 트라이셉스 익스텐션")){
+ if(time.getText().equals("1분")){
+ collectionName = "countTriceps1Minute";
+ }else if(time.getText().equals("2분")){
+ collectionName = "countTriceps2Minute";
+ }else if(time.getText().equals("3분")){
+ collectionName = "countTriceps3Minute";
+ }
+ }
+ friendListInput();
+ String finalCollectionName = collectionName;
+ db.collection(collectionName)
+ .orderBy(collectionName, Query.Direction.DESCENDING)
+ .get()
+ .addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ for (QueryDocumentSnapshot document : task.getResult()) {
+ String docId = document.getId(); // 문서의 ID (여기서는 친구의 UID)
+
+ if (uidList.contains(docId)) { // 문서의 ID가 친구 UID 리스트에 있는 경우만 추가
+ String name = document.getString("name");
+ int score = document.getLong(finalCollectionName).intValue();
+
+ rankingList.add(new RankingItem(rank_in.get(), name, score));
+ rank_in.getAndIncrement();
+ }
+ }
+ adapter.notifyDataSetChanged();
+ }
+ });
+
+ }
+ }
+
+ public void friendListInput(){
+ FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
+ String currentUid = currentUser != null ? currentUser.getUid() : null;
+ FirebaseFirestore db = FirebaseFirestore.getInstance();
+ uidList.clear();
+
+ if (currentUid != null) {
+ db.collection("users")
+ .document(currentUid)
+ .collection("friends")
+ .get()
+ .addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ for (QueryDocumentSnapshot document : task.getResult()) {
+ String friendUid = document.getString("uid");
+ uidList.add(friendUid);
+ }
+ uidList.add(currentUid);
+ for (String uid : uidList) {
+ Log.d("Friend UID", uid);
+ }
+
+ } else {
+ Log.d("Firestore", "Error getting documents: ", task.getException());
+ }
+ }
+ });
+ }
+
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("1분") || str.equals("2분") || str.equals("3분")){
+ time.setText(str);
+ }else if(str.equals("전체") || str.equals("친구")){
+ range.setText(str);
+ }else if(str.equals("스쿼트") || str.equals("푸쉬업") || str.equals("푸시업") || str.equals("덤벨 숄더 프레스") || str.equals("덤벨 숄더") || str.equals("덤벨숄더프레스") ||
+ str.equals("사이드 레터럴 레이즈") || str.equals("사레레") || str.equals("사이드레터럴레이즈") || str.equals("레그 레이즈") || str.equals("레그레이즈") ||
+ str.equals("덤벨컬") || str.equals("덤벨 컬") || str.equals("덤벨 플라이") || str.equals("덤벨플라이") || str.equals("덤벨 트라이셉스 익스텐션") || str.equals("덤벨 트라이")){
+ if(str.equals("스쿼트")){
+ exercise.setText("스쿼트");
+ }else if(str.equals("푸쉬업") || str.equals("푸시업")){
+ exercise.setText("푸쉬업");
+ }else if(str.equals("덤벨 숄더 프레스") || str.equals("덤벨 숄더") || str.equals("덤벨숄더프레스")){
+ exercise.setText("덤벨 숄더 프레스");
+ }else if(str.equals("사이드 레터럴 레이즈") || str.equals("사레레") || str.equals("사이드레터럴레이즈")){
+ exercise.setText("사이드 레터럴 레이즈");
+ }else if(str.equals("레그 레이즈") || str.equals("레그레이즈")){
+ exercise.setText("레그 레이즈");
+ }else if(str.equals("덤벨컬") || str.equals("덤벨 컬")){
+ exercise.setText("덤벨 컬");
+ }else if(str.equals("덤벨 플라이") || str.equals("덤벨플라이")){
+ exercise.setText("덤벨 플라이");
+ }else if(str.equals("덤벨 트라이셉스 익스텐션") || str.equals("덤벨 트라이")){
+ exercise.setText("덤벨 트라이셉스 익스텐션");
+ }
+ }else if(str.equals("이전")){
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ }else if(str.equals("순위조회") || str.equals("순위 조회") || str.equals("순위") || str.equals("랭킹 보여줘")){
+ if(range.getText().equals("범위")){
+ Toast.makeText(Ranking.this, "범위를 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(exercise.getText().equals("운동")){
+ Toast.makeText(Ranking.this, "운동을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(time.getText().equals("시간")){
+ Toast.makeText(Ranking.this, "시간을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ db = FirebaseFirestore.getInstance();
+ rankingRecyclerView.setLayoutManager(new LinearLayoutManager(Ranking.this));
+
+ fetchData();
+ adapter = new RankingAdapter(rankingList);
+ rankingRecyclerView.setAdapter(adapter);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 10000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 3000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+
+ static class RankingItem {
+ int rank;
+ String name;
+ int score;
+
+ public RankingItem(int rank, String name, int score) {
+ this.rank = rank;
+ this.name = name;
+ this.score = score;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/RankingAdapter.java b/app/src/main/java/com/example/newbody/RankingAdapter.java
new file mode 100644
index 0000000..90a373d
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/RankingAdapter.java
@@ -0,0 +1,52 @@
+package com.example.newbody;
+
+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 java.util.List;
+
+public class RankingAdapter extends RecyclerView.Adapter {
+
+ private List rankingList;
+
+ public RankingAdapter(List rankingList) {
+ this.rankingList = rankingList;
+ }
+
+ @NonNull
+ @Override
+ public RankingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View itemView = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.ranking_item, parent, false);
+ return new RankingViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RankingViewHolder holder, int position) {
+ Ranking.RankingItem currentItem = rankingList.get(position);
+ holder.rankTextView.setText(String.valueOf(currentItem.rank));
+ holder.nameTextView.setText(currentItem.name);
+ holder.scoreTextView.setText(String.valueOf(currentItem.score));
+ }
+
+ @Override
+ public int getItemCount() {
+ return rankingList.size();
+ }
+
+ static class RankingViewHolder extends RecyclerView.ViewHolder {
+ TextView rankTextView;
+ TextView nameTextView;
+ TextView scoreTextView;
+
+ public RankingViewHolder(@NonNull View itemView) {
+ super(itemView);
+ rankTextView = itemView.findViewById(R.id.rankTextView);
+ nameTextView = itemView.findViewById(R.id.nameTextView);
+ scoreTextView = itemView.findViewById(R.id.scoreTextView);
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/Record.java b/app/src/main/java/com/example/newbody/Record.java
new file mode 100644
index 0000000..6780330
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Record.java
@@ -0,0 +1,641 @@
+package com.example.newbody;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CompoundButton;
+import android.widget.Switch;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.example.newbody.record.RecordCurl;
+import com.example.newbody.record.RecordDumbbell;
+import com.example.newbody.record.RecordFly;
+import com.example.newbody.record.RecordLegRaise;
+import com.example.newbody.record.RecordPushup;
+import com.example.newbody.record.RecordSidelateralraise;
+import com.example.newbody.record.RecordSquat;
+import com.example.newbody.record.RecordTriceps;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+import java.util.ArrayList;
+
+public class Record extends AppCompatActivity {
+
+ private String select_time, select_ex;
+ private long[] totalTimesInMillis = {1 * 60 * 1000, 2 * 60 * 1000, 3 * 60 * 1000};
+ private Button time;
+ private View ex_start;
+ private View squatView, pushupView, dumbbellView, sideView, legView, dumbbellCurlView, dumbbellFlyView, dumbbellTricepsView;
+ private View []ex = new View[8];
+ private TextView []exName = new TextView[8];
+ private TextView []premiumMessage = new TextView[3];
+ private View []lockButton = new View[3];
+ private TextView selectT, selectE, pre1, pre2;
+ private int select_num;
+ private Button prev;
+ private Switch customized;
+
+ private FirebaseAuth mAuth;
+ private FirebaseFirestore db;
+ private FirebaseUser user;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_record);
+
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+
+ initViews();
+ premiumCheck();
+ customized.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ if(customized.isChecked()){
+ pre1.setText(" ");
+ pre2.setText(" ");
+ DocumentReference userRecordRef = db.collection("users").document(user.getUid());
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ String preference1 = document.getString("preference1");
+ pre1.setText(preference1);
+ String preference2 = document.getString("preference2");
+ pre2.setText(preference2);
+
+ if(preference1.equals("도구 이용 운동")){
+ squatView.setVisibility(View.GONE);
+ pushupView.setVisibility(View.GONE);
+ legView.setVisibility(View.GONE);
+ }else if(preference1.equals("맨몸 운동")){
+ dumbbellCurlView.setVisibility(View.GONE);
+ dumbbellFlyView.setVisibility(View.GONE);
+ dumbbellTricepsView.setVisibility(View.GONE);
+ if(preference2.equals("팔 운동")){
+ squatView.setVisibility(View.GONE);
+ dumbbellView.setVisibility(View.GONE);
+ sideView.setVisibility(View.GONE);
+ legView.setVisibility(View.GONE);
+ }else if(preference2.equals("하체 운동")){
+ pushupView.setVisibility(View.GONE);
+ dumbbellView.setVisibility(View.GONE);
+ sideView.setVisibility(View.GONE);
+ }else if(preference2.equals("복근 운동")){
+ squatView.setVisibility(View.GONE);
+ dumbbellView.setVisibility(View.GONE);
+ sideView.setVisibility(View.GONE);
+ }
+ }
+ } else {
+ Log.d("Firestore", "No such document");
+ }
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+ }else if(!customized.isChecked()){
+ squatView.setVisibility(View.VISIBLE);
+ pushupView.setVisibility(View.VISIBLE);
+ dumbbellView.setVisibility(View.VISIBLE);
+ sideView.setVisibility(View.VISIBLE);
+ legView.setVisibility(View.VISIBLE);
+ dumbbellCurlView.setVisibility(View.VISIBLE);
+ dumbbellFlyView.setVisibility(View.VISIBLE);
+ dumbbellTricepsView.setVisibility(View.VISIBLE);
+ }
+ }
+ });
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ time.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ showTimeDialog();
+ }
+ });
+
+ ex[0].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[0].getText());
+ select_num = 1;
+ }
+ });
+ ex[1].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[1].getText());
+ select_num = 2;
+ }
+ });
+ ex[2].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[2].getText());
+ select_num = 3;
+ }
+ });
+
+ ex[3].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[3].getText());
+ select_num = 4;
+ }
+ });
+
+ ex[4].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[4].getText());
+ select_num = 5;
+ }
+ });
+
+ ex[5].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[5].getText());
+ select_num = 6;
+ }
+ });
+
+ ex[6].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[6].getText());
+ select_num = 7;
+ }
+ });
+
+ ex[7].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(exName[7].getText());
+ select_num = 8;
+ }
+ });
+
+ lockButton[0].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Toast.makeText(Record.this, "프리미엄 전용 운동입니다", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ lockButton[1].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Toast.makeText(Record.this, "프리미엄 전용 운동입니다", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ lockButton[2].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Toast.makeText(Record.this, "프리미엄 전용 운동입니다", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ ex_start.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(selectT.getText().equals("시간") || selectE.getText().equals("운동")){
+ Toast.makeText(Record.this, "시간 또는 운동을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(select_num == 1){
+ Intent intent = new Intent(Record.this, RecordSquat.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 2){
+ Intent intent = new Intent(Record.this, RecordPushup.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 3){
+ Intent intent = new Intent(Record.this, RecordDumbbell.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 4){
+ Intent intent = new Intent(Record.this, RecordSidelateralraise.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 5){
+ Intent intent = new Intent(Record.this, RecordLegRaise.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 6){
+ Intent intent = new Intent(Record.this, RecordCurl.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 7){
+ Intent intent = new Intent(Record.this, RecordFly.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 8){
+ Intent intent = new Intent(Record.this, RecordTriceps.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }
+ }
+ });
+
+ }
+
+ public void initViews(){
+ time = findViewById(R.id.time);
+ ex_start = findViewById(R.id.start_button);
+ ex[0] = findViewById(R.id.ex_button1);
+ ex[1] = findViewById(R.id.ex_button2);
+ ex[2] = findViewById(R.id.ex_button3);
+ ex[3] = findViewById(R.id.ex_button4);
+ ex[4] = findViewById(R.id.ex_button5);
+ ex[5] = findViewById(R.id.ex_button6);
+ ex[6] = findViewById(R.id.ex_button7);
+ ex[7] = findViewById(R.id.ex_button8);
+ exName[0] = findViewById(R.id.ex1_name);
+ exName[1] = findViewById(R.id.ex2_name);
+ exName[2] = findViewById(R.id.ex3_name);
+ exName[3] = findViewById(R.id.ex4_name);
+ exName[4] = findViewById(R.id.ex5_name);
+ exName[5] = findViewById(R.id.ex6_name);
+ exName[6] = findViewById(R.id.ex7_name);
+ exName[7] = findViewById(R.id.ex8_name);
+ selectT = findViewById(R.id.time_select);
+ selectE = findViewById(R.id.exercise_select);
+ prev = findViewById(R.id.prevButtonRecord);
+ squatView = findViewById(R.id.squatView);
+ pushupView = findViewById(R.id.pushupView);
+ dumbbellView = findViewById(R.id.dumbbellView);
+ sideView = findViewById(R.id.sideView);
+ legView = findViewById(R.id.legView);
+ dumbbellCurlView = findViewById(R.id.dumbbellCurlView);
+ dumbbellFlyView = findViewById(R.id.dumbbellFlyView);
+ dumbbellTricepsView = findViewById(R.id.dumbbellTricepsView);
+ customized = findViewById(R.id.customized1);
+ mAuth = FirebaseAuth.getInstance();
+ db = FirebaseFirestore.getInstance();
+ user = mAuth.getCurrentUser();
+ pre1 = findViewById(R.id.pre1);
+ pre2 = findViewById(R.id.pre2);
+ premiumMessage[0] = findViewById(R.id.premiumMessage6);
+ premiumMessage[1] = findViewById(R.id.premiumMessage7);
+ premiumMessage[2] = findViewById(R.id.premiumMessage8);
+ lockButton[0] = findViewById(R.id.ex_lock_button6);
+ lockButton[1] = findViewById(R.id.ex_lock_button7);
+ lockButton[2] = findViewById(R.id.ex_lock_button8);
+ }
+
+ private void showTimeDialog() {
+ final String[] difficultyOptions = {"1분", "2분", "3분"};
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("시간 선택");
+ builder.setItems(difficultyOptions, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ select_time = difficultyOptions[which];
+ time.setText(select_time);
+
+ // 선택한 난이도에 따라 시간 배열을 업데이트
+ if (select_time.equals("1분")) {
+ selectT.setText("1분");
+ } else if (select_time.equals("2분")) {
+ selectT.setText("2분");
+ } else if (select_time.equals("3분")) {
+ selectT.setText("3분");
+ }
+ }
+ });
+ builder.show();
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("1분") || str.equals("2분") || str.equals("3분")){
+ // 선택한 난이도에 따라 시간 배열을 업데이트
+ if (str.equals("1분")) {
+ select_time = "1분";
+ time.setText(select_time);
+ selectT.setText("1분");
+ } else if (str.equals("2분")) {
+ select_time = "2분";
+ time.setText(select_time);
+ selectT.setText("2분");
+ } else if (str.equals("3분")) {
+ select_time = "3분";
+ time.setText(select_time);
+ selectT.setText("3분");
+ }
+ }else if(str.equals("스쿼트") || str.equals("푸쉬업") || str.equals("푸시업") || str.equals("덤벨 숄더 프레스") || str.equals("덤벨 숄더") || str.equals("덤벨숄더프레스") ||
+ str.equals("사이드 레터럴 레이즈") || str.equals("사레레") || str.equals("사이드레터럴레이즈") || str.equals("레그 레이즈") || str.equals("레그레이즈") ||
+ str.equals("덤벨컬") || str.equals("덤벨 컬") || str.equals("덤벨 플라이") || str.equals("덤벨플라이") || str.equals("덤벨 트라이셉스 익스텐션") || str.equals("덤벨 트라이")){
+ if(str.equals("스쿼트")){
+ selectE.setText(exName[0].getText());
+ select_num = 1;
+ }else if(str.equals("푸쉬업") || str.equals("푸시업")){
+ selectE.setText(exName[1].getText());
+ select_num = 2;
+ }else if(str.equals("덤벨 숄더 프레스") || str.equals("덤벨 숄더") || str.equals("덤벨숄더프레스")){
+ selectE.setText(exName[2].getText());
+ select_num = 3;
+ }else if(str.equals("사이드 레터럴 레이즈") || str.equals("사레레") || str.equals("사이드레터럴레이즈")){
+ selectE.setText(exName[3].getText());
+ select_num = 4;
+ }else if(str.equals("레그 레이즈") || str.equals("레그레이즈")){
+ selectE.setText(exName[4].getText());
+ select_num = 5;
+ }else if(str.equals("덤벨컬") || str.equals("덤벨 컬")){
+ selectE.setText(exName[5].getText());
+ select_num = 6;
+ }else if(str.equals("덤벨 플라이") || str.equals("덤벨플라이")){
+ selectE.setText(exName[6].getText());
+ select_num = 7;
+ }else if(str.equals("덤벨 트라이셉스 익스텐션") || str.equals("덤벨 트라이")){
+ selectE.setText(exName[7].getText());
+ select_num = 8;
+ }
+ }else if(str.equals("시작") || str.equals("운동 시작")){
+ if(selectT.getText().equals("시간") || selectE.getText().equals("운동")){
+ Toast.makeText(Record.this, "시간 또는 운동을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(select_num == 1){
+ Intent intent = new Intent(Record.this, RecordSquat.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 2){
+ Intent intent = new Intent(Record.this, RecordPushup.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 3){
+ Intent intent = new Intent(Record.this, RecordDumbbell.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 4){
+ Intent intent = new Intent(Record.this, RecordSidelateralraise.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 5){
+ Intent intent = new Intent(Record.this, RecordLegRaise.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 6){
+ Intent intent = new Intent(Record.this, RecordCurl.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 7){
+ Intent intent = new Intent(Record.this, RecordFly.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }else if(select_num == 8){
+ Intent intent = new Intent(Record.this, RecordTriceps.class);
+ if (select_time.equals("1분")) {
+ intent.putExtra("time", totalTimesInMillis[0]);
+ } else if (select_time.equals("2분")) {
+ intent.putExtra("time", totalTimesInMillis[1]);
+ } else if (select_time.equals("3분")) {
+ intent.putExtra("time", totalTimesInMillis[2]);
+ }
+ startActivity(intent);
+ finish();
+ }
+ }else if(str.equals("이전")){
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 10000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 3000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+
+ public void premiumCheck(){
+ if(user == null){
+ Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
+ startActivity(intent);
+ }else{
+ db.collection("users").document(user.getUid())
+ .get()
+ .addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@androidx.annotation.NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ String grade = document.getString("grade");
+ if (grade == null) grade = "일반";
+
+ if(grade.equals("프리미엄")){
+ customized.setVisibility(View.VISIBLE);
+ premiumMessage[0].setVisibility(View.GONE);
+ premiumMessage[1].setVisibility(View.GONE);
+ premiumMessage[2].setVisibility(View.GONE);
+ lockButton[0].setVisibility(View.GONE);
+ lockButton[1].setVisibility(View.GONE);
+ lockButton[2].setVisibility(View.GONE);
+ ex[5].setVisibility(View.VISIBLE);
+ ex[6].setVisibility(View.VISIBLE);
+ ex[7].setVisibility(View.VISIBLE);
+ }
+ }
+ } else {
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/RecyclerViewAdapter.java b/app/src/main/java/com/example/newbody/RecyclerViewAdapter.java
new file mode 100644
index 0000000..21608cf
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/RecyclerViewAdapter.java
@@ -0,0 +1,243 @@
+package com.example.newbody;
+
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.ListenerRegistration;
+import com.google.firebase.firestore.QueryDocumentSnapshot;
+import com.google.firebase.firestore.QuerySnapshot;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RecyclerViewAdapter extends RecyclerView.Adapter {
+
+ private List originalUsers = new ArrayList<>();
+ private List filteredUsers = new ArrayList<>();
+ private FirebaseFirestore firestore;
+
+ private FirebaseUser user;
+ private FirebaseAuth auth;
+ private String uid;
+ private ListenerRegistration listenerRegistration;
+ private boolean nameFound = true;
+
+ public RecyclerViewAdapter() {
+ firestore = FirebaseFirestore.getInstance();
+ // Firebase Firestore에서 데이터 변경을 감지하고 데이터를 불러오는 코드입니다.
+ listenerRegistration = firestore.collection("users").addSnapshotListener((querySnapshot, e) -> {
+ originalUsers.clear();
+
+ if (querySnapshot != null) {
+ for (QueryDocumentSnapshot snapshot : querySnapshot) {
+ FriendData item = snapshot.toObject(FriendData.class);
+ originalUsers.add(item);
+ }
+ performSearch("", ""); // 초기화 시 전체 데이터로 설정
+ }
+ });
+
+ }
+
+ // 검색 기능을 수행하는 메서드
+ public void performSearch(String searchWord, String option) {
+ filteredUsers.clear();
+ nameFound = false;
+
+ if (searchWord == null || option == null || searchWord.isEmpty() || option.isEmpty()) {
+ // 검색어가 없을 때 전체 데이터를 불러옵니다.
+ filteredUsers.addAll(originalUsers);
+ } else {
+ for (FriendData userData : originalUsers) {
+ String name = userData.getName();
+ String birth = userData.getBirth();
+ String uid = userData.getUid(); // 친구의 고유 UID
+
+ if (name != null && birth != null) {
+ // 검색 옵션에 따라 데이터를 필터링하여 추가합니다.
+ if (option.equals("name") && name.contains(searchWord)) {
+ FriendData friend = new FriendData(name, birth, uid); // 생성자에 데이터 추가
+ friend.setUid(uid);
+ filteredUsers.add(friend);
+ nameFound = true;
+ } else if (option.equals("birth") && birth.contains(searchWord)) {
+ FriendData friend = new FriendData(name, birth, uid); // 생성자에 데이터 추가
+ friend.setUid(uid);
+ filteredUsers.add(friend);
+ nameFound = true;
+ }
+ }
+ }
+ }
+ notifyDataSetChanged(); // 데이터 변경을 어댑터에 알려 화면을 갱신합니다.
+ }
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ // 아이템 뷰를 생성하는 메서드입니다.
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
+ return new ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ FriendData user = filteredUsers.get(position);
+ holder.bind(user);
+ }
+
+ @Override
+ public int getItemCount() {
+ // 아이템 개수를 반환합니다.
+ return filteredUsers.size();
+ }
+
+ public class ViewHolder extends RecyclerView.ViewHolder {
+ TextView name;
+ TextView uid;
+ Button btnadd;
+
+ public ViewHolder(View view) {
+ super(view);
+ // 뷰 홀더에서 아이템 뷰의 요소들을 초기화합니다.
+ name = view.findViewById(R.id.name);
+ uid = view.findViewById(R.id.uid);
+ btnadd = view.findViewById(R.id.btnadd);
+ }
+
+ public void bind(FriendData friend) {
+ // 뷰 홀더에 데이터를 바인딩하여 화면에 표시합니다.
+ name.setText(friend.getName());
+ String maskedUID = maskUID(friend.getUid());
+ uid.setText(maskedUID);
+
+ FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
+ if (currentUser != null) {
+ String currentUid = currentUser.getUid(); // 현재 사용자의 UID
+
+ btnadd.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ boolean isUserAlreadyAdded = checkIfUserAlreadyAddedByUid(currentUid, friend.getUid());
+ if (isUserAlreadyAdded) {
+ return;
+ }
+ FirebaseFirestore db = FirebaseFirestore.getInstance();
+
+ // 상대방의 UID로 친구 문서를 추가
+ DocumentReference friendRef = db.collection("users")
+ .document(friend.getUid()) // 상대방의 UID로 도큐먼트 접근
+ .collection("friends")
+ .document(currentUid); // 사용자 정의 문서 ID
+ Map friendData = new HashMap<>();
+
+ DocumentReference currentUserDocRef = db.collection("users").document(currentUid);
+ currentUserDocRef.get().addOnSuccessListener(documentSnapshot -> {
+ if (documentSnapshot.exists()) {
+ String currentUserName = documentSnapshot.getString("name");
+ String currentUserGender = documentSnapshot.getString("gender");
+ String currentUserHeight = documentSnapshot.getString("height");
+ String currentUserWeight = documentSnapshot.getString("weight");
+ String currentUserBirth = documentSnapshot.getString("birth");
+ String currentUserFcmToken = documentSnapshot.getString("fcmToken");
+
+ friendData.put("name", currentUserName); // 현재 사용자의 이름
+ friendData.put("uid", currentUid);
+ friendData.put("gender", currentUserGender);
+ friendData.put("height", currentUserHeight);
+ friendData.put("weight", currentUserWeight);
+ friendData.put("birth", currentUserBirth);
+ friendData.put("fcmToken", currentUserFcmToken);
+ // 나머지 정보도 필요한 속성에 맞게 추가
+
+ friendRef.set(friendData)
+ .addOnSuccessListener(documentReference -> {
+ // 상대방 친구 목록에 추가 성공 처리
+ })
+ .addOnFailureListener(e -> {
+ // 상대방 친구 목록에 추가 실패 처리
+ });
+
+ // 나의 친구 목록에 상대방을 추가
+ DocumentReference myFriendRef = db.collection("users")
+ .document(currentUid) // 내 UID로 도큐먼트 접근
+ .collection("friends")
+ .document(friend.getUid()); // 사용자 정의 문서 ID
+ Map myFriendData = new HashMap<>();
+ myFriendData.put("name", friend.getName()); // 상대방의 이름
+ myFriendData.put("uid", friend.getUid());
+ myFriendData.put("birth", friend.getBirth());
+ myFriendData.put("gender", friend.getGender());
+ myFriendData.put("height", friend.getHeight());
+ myFriendData.put("weight", friend.getWeight());
+ myFriendData.put("fcmToken", friend.getFcmToken());
+ // 나머지 정보도 필요한 속성에 맞게 추가
+
+ myFriendRef.set(myFriendData)
+ .addOnSuccessListener(documentReference -> {
+ // 나의 친구 목록에 추가 성공 처리
+ })
+ .addOnFailureListener(e -> {
+ // 나의 친구 목록에 추가 실패 처리
+ });
+ }
+ }).addOnFailureListener(e -> {
+ // 데이터 가져오기 실패 처리
+ });
+ }
+ });
+ }
+ }
+ private String maskUID(String uid) {
+ if (uid == null || uid.length() < 6) {
+ return uid; // UID가 null이거나 6자리 미만일 경우 가려지지 않은 UID를 반환
+ }
+
+ String masked = uid.substring(0, 6); // 앞 4자리를 유지
+ for (int i = 6; i < uid.length(); i++) {
+ masked += "*"; // 나머지 자리는 '*'로 대체
+ }
+
+ return masked;
+ }
+ private boolean checkIfUserAlreadyAddedByUid(String currentUid, String friendUid) {
+ FirebaseFirestore db = FirebaseFirestore.getInstance();
+
+ DocumentReference myFriendRef = db.collection("users")
+ .document(currentUid) // 내 UID로 도큐먼트 접근
+ .collection("friends")
+ .document(friendUid); // 사용자의 UID를 문서 ID로 사용
+
+ Log.d("RecyclerViewAdapter", "Checking if user is already added…");
+
+ myFriendRef.get().addOnSuccessListener(documentSnapshot -> {
+ boolean isSuccessful = documentSnapshot.exists();
+ if (isSuccessful) {
+ Toast.makeText(itemView.getContext(), "이미 추가된 사용자입니다.", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(itemView.getContext(), "정상적으로 추가하였습니다.", Toast.LENGTH_SHORT).show();
+ }
+ }).addOnFailureListener(e -> {
+ });
+
+ return false; // 임시 반환값
+ }
+
+
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/RecyclerViewAdapterInvite.java b/app/src/main/java/com/example/newbody/RecyclerViewAdapterInvite.java
new file mode 100644
index 0000000..636902a
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/RecyclerViewAdapterInvite.java
@@ -0,0 +1,119 @@
+package com.example.newbody;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.google.firebase.dynamiclinks.DynamicLink;
+import com.google.firebase.dynamiclinks.FirebaseDynamicLinks;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RecyclerViewAdapterInvite extends RecyclerView.Adapter {
+
+ private List originalUsers;
+ private List filteredUsers;
+ private Context context;
+ private boolean nameFound = true;
+ public RecyclerViewAdapterInvite(Context context, List contactList) {
+ this.context = context;
+ this.originalUsers = new ArrayList<>(contactList); // 원본 목록 초기화
+ this.filteredUsers = new ArrayList<>(contactList); // 필터링된 목록 초기화
+ }
+
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.friendinviteitem, parent, false);
+ return new ViewHolder(view);
+ }
+
+ // 친구초대 창에 나오는 정보
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ FriendInviteContact contact = filteredUsers.get(position);
+ holder.nameTextView.setText(contact.getName());
+ holder.phoneNumberTextView.setText(contact.getPhoneNumber());
+
+ // 초대 버튼 클릭 리스너 설정
+ holder.ivtBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Log.d("RecyclerViewAdapter", "친구 초대 버튼 클릭");
+ // 친구 초대 창으로 이동하는 Intent 생성
+ sendInvitation(contact);
+ }
+ });
+ }
+ // 검색 기능을 수행하는 메서드
+ public void performSearch(String searchWord, String option) {
+ filteredUsers.clear();
+ nameFound = false;
+
+ if (searchWord == null || option == null || searchWord.isEmpty() || option.isEmpty()) {
+ // 검색어가 없을 때 전체 데이터를 불러옵니다.
+ filteredUsers.addAll(originalUsers);
+ } else {
+ for (FriendInviteContact contact : originalUsers) {
+ String name = contact.getName();
+
+ if (name != null) {
+ // 검색 옵션에 따라 데이터를 필터링하여 추가합니다.
+ if (option.equals("name") && name.contains(searchWord)) {
+ filteredUsers.add(contact);
+ nameFound = true;
+ }
+ }
+ }
+ }
+ notifyDataSetChanged(); // 데이터 변경을 어댑터에 알려 화면을 갱신합니다.
+ }
+
+
+ // 메시지 보내기 기능
+ private void sendInvitation(FriendInviteContact contact) {
+ String phoneNumber = contact.getPhoneNumber();
+ String message = "새로운 삶을 살고싶으신가요? 지금부터 시작하세요! 초보자도 쉽게 따라할수 있는 홈트레이닝 NewBody: https://newbody.page.link/mKfG";
+ // SMS를 보내기 위한 Intent 생성
+ Uri uri = Uri.parse("smsto:" + phoneNumber);
+ Intent sendIntent = new Intent(Intent.ACTION_SENDTO, uri);
+ sendIntent.putExtra("sms_body", message);
+
+ if (sendIntent.resolveActivity(context.getPackageManager()) != null) {
+ context.startActivity(sendIntent);
+ Toast.makeText(context, "정상적으로 초대 메시지를 보냈습니다!", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(context, "메시지를 보낼 앱이 설치되어 있지 않습니다.", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return filteredUsers.size();
+ }
+
+ public class ViewHolder extends RecyclerView.ViewHolder {
+ public TextView nameTextView;
+ public TextView phoneNumberTextView;
+ public Button ivtBtn;
+
+ public ViewHolder(View itemView) {
+ super(itemView);
+ nameTextView = itemView.findViewById(R.id.name);
+ phoneNumberTextView = itemView.findViewById(R.id.phoneNumber);
+ ivtBtn = itemView.findViewById(R.id.ivtBtn);
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/RecyclerViewAdapterPlus.java b/app/src/main/java/com/example/newbody/RecyclerViewAdapterPlus.java
new file mode 100644
index 0000000..409c15e
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/RecyclerViewAdapterPlus.java
@@ -0,0 +1,219 @@
+package com.example.newbody;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.recyclerview.widget.RecyclerView;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.squareup.picasso.Picasso;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RecyclerViewAdapterPlus extends RecyclerView.Adapter {
+
+ private List mFriendList = new ArrayList<>();
+ private Map selectedItems = new HashMap<>();
+
+ @NonNull
+ @Override
+ public com.example.newbody.RecyclerViewAdapterPlus.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.friendplusitem, parent, false);
+ return new com.example.newbody.RecyclerViewAdapterPlus.ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull com.example.newbody.RecyclerViewAdapterPlus.ViewHolder holder, int position) {
+ holder.onBind(mFriendList.get(position));
+ }
+
+ public void setFriendList(ArrayList list) {
+ Collections.sort(list, (user1, user2) -> user1.getName().compareTo(user2.getName()));
+ this.mFriendList = list;
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public int getItemCount() {
+ return mFriendList.size();
+ }
+
+ public class ViewHolder extends RecyclerView.ViewHolder {
+ TextView name;
+ FirebaseUser user;
+ TextView uid;
+ ImageView imageUrl;
+ CheckBox checkBox;
+
+ public ViewHolder(View view) {
+ super(view);
+ name = view.findViewById(R.id.name);
+ uid = view.findViewById(R.id.uid);
+ imageUrl = view.findViewById(R.id.profile);
+ checkBox = view.findViewById(R.id.checkbox);
+
+ checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ int position = getAdapterPosition();
+ if (position != RecyclerView.NO_POSITION) {
+ String uid = mFriendList.get(position).getUid();
+ if (isChecked) {
+ selectedItems.put(uid, true);
+ } else {
+ selectedItems.remove(uid);
+ }
+ }
+ });
+ }
+
+ void onBind(FriendData user) {
+ FirebaseFirestore db = FirebaseFirestore.getInstance();
+ DocumentReference userRef = db.collection("users").document(user.getUid());
+
+ // 기본 이미지를 미리 설정
+ imageUrl.setImageResource(R.drawable.baseline_person_24);
+ checkBox.setChecked(selectedItems.containsKey(user.getUid()));
+
+ userRef.get().addOnSuccessListener(documentSnapshot -> {
+ if (documentSnapshot.exists()) {
+ String imageUrl = documentSnapshot.getString("imageUrl");
+ user.setImageUrl(imageUrl);
+ // 이미지 로딩
+ if (user.getImageUrl() != null && !user.getImageUrl().isEmpty()) {
+ Picasso.get()
+ .load(user.getImageUrl())
+ .placeholder(R.drawable.baseline_person_24)
+ .error(R.drawable.baseline_person_24)
+ .into(this.imageUrl);
+ }
+ }
+ });
+
+ name.setText(user.getName());
+ String maskedUID = maskUID(user.getUid());
+ uid.setText(maskedUID);
+ }
+
+ }
+ private String maskUID(String uid) {
+ if (uid == null || uid.length() <= 6) {
+ return uid; // UID가 null이거나 6글자 이하일 경우 가려지지 않은 UID를 반환
+ }
+
+ String masked = uid.substring(0, 6); // 앞 6글자를 유지
+ for (int i = 6; i < uid.length(); i++) {
+ masked += "*"; // 나머지 자리는 '*'로 대체
+ }
+
+ return masked;
+ }
+
+ public void deleteSelectedItems(String currentUserUid) {
+ for (String uid : selectedItems.keySet()) {
+ // Firestore에서 데이터 삭제 처리
+ deleteUserDataAndFriend(currentUserUid, uid);
+ }
+
+ // 선택된 아이템 목록에서 삭제된 아이템 제거
+ List newFriendList = new ArrayList<>();
+ for (FriendData friend : mFriendList) {
+ if (!selectedItems.containsKey(friend.getUid())) {
+ newFriendList.add(friend);
+ }
+ }
+
+ Log.d("NewFriendList", "New friend list after deletion: " + newFriendList.toString());
+
+ mFriendList = newFriendList;
+ selectedItems.clear();
+
+ notifyDataSetChanged(); // RecyclerView 갱신 추가
+
+ // notifyDataSetChanged() 호출 이후에도 Firebase에서 데이터를 삭제하는 로직은 그대로 두세요.
+ }
+
+ private void deleteUserDataAndFriend(String currentUserUid, String friendUid) {
+ FirebaseFirestore db = FirebaseFirestore.getInstance();
+
+ // 상대방의 친구 목록에서 현재 사용자 삭제
+ deleteFromFriendFriendList(friendUid, currentUserUid);
+
+ // 선택된 아이템 목록에서 삭제된 아이템 제거
+ List newFriendList = new ArrayList<>();
+ for (FriendData friend : mFriendList) {
+ if (!selectedItems.containsKey(friend.getUid())) {
+ newFriendList.add(friend);
+ }
+ }
+
+ Log.d("NewFriendList", "New friend list after deletion: " + newFriendList.toString());
+
+ mFriendList = newFriendList;
+ selectedItems.clear();
+
+ notifyDataSetChanged();
+ }
+
+
+ private void deleteFromFriendFriendList(String friendUid, String currentUserUid) {
+ FirebaseFirestore db = FirebaseFirestore.getInstance();
+
+ // 상대방의 친구 목록에서 현재 사용자 삭제
+ db.collection("users").document(friendUid)
+ .collection("friends")
+ .document(currentUserUid)
+ .delete()
+ .addOnSuccessListener(aVoid -> {
+ Log.d("DeleteFriendSuccess", "Friend relationship deleted successfully from friend's list.");
+
+ // 선택된 아이템 목록에서 삭제된 아이템 제거
+ List newFriendList = new ArrayList<>();
+ for (FriendData friend : mFriendList) {
+ if (!selectedItems.containsKey(friend.getUid())) {
+ newFriendList.add(friend);
+ }
+ }
+
+ Log.d("NewFriendList", "New friend list after deletion: " + newFriendList.toString());
+
+ mFriendList = newFriendList;
+ selectedItems.clear();
+
+ notifyDataSetChanged();
+ })
+ .addOnFailureListener(e -> {
+ Log.e("DeleteFriendFailure", "Friend relationship deletion failed from friend's list: " + e.getMessage());
+ });
+
+ // 여기서 friendUid에 해당하는 문서를 삭제하는 로직을 추가하세요.
+ db.collection("users").document(currentUserUid)
+ .collection("friends")
+ .document(friendUid)
+ .delete()
+ .addOnSuccessListener(aVoid -> {
+ Log.d("DeleteFriendSuccess", "Friend relationship deleted successfully from user's list.");
+ })
+ .addOnFailureListener(e -> {
+ Log.e("DeleteFriendFailure", "Friend relationship deletion failed from user's list: " + e.getMessage());
+ });
+ }
+
+
+
+
+}
diff --git a/app/src/main/java/com/example/newbody/Target.java b/app/src/main/java/com/example/newbody/Target.java
new file mode 100644
index 0000000..66c54ed
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Target.java
@@ -0,0 +1,581 @@
+package com.example.newbody;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Switch;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.newbody.videoinfo.VideoDumbbell;
+import com.example.newbody.videoinfo.VideoLegRaise;
+import com.example.newbody.videoinfo.VideoPushups;
+import com.example.newbody.videoinfo.VideoSide;
+import com.example.newbody.videoinfo.VideoSquat;
+import com.example.newbody.videoinfo.VideoWarmup;
+import com.example.newbody.workout.Home_Training_WarmUp;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.Query;
+import com.google.firebase.firestore.QueryDocumentSnapshot;
+import com.google.firebase.firestore.QuerySnapshot;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Target extends AppCompatActivity {
+ FirebaseFirestore db;
+ FirebaseAuth mAuth;
+ FirebaseUser user;
+
+ private Button prev, change;
+ private boolean checkChange = true;
+ private RecyclerView targetRecyclerView;
+ private TargetAdapter adapter;
+ private String selectCnt;
+ private TextView []exName = new TextView[8];
+ private Button []ex = new Button[8];
+ private TextView []exNum = new TextView[8];
+ private Switch []switches = new Switch[8];
+ private View []premiumView = new View[3];
+ private List targetList = new ArrayList<>();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_target);
+
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+
+ db = FirebaseFirestore.getInstance();
+ mAuth = FirebaseAuth.getInstance();
+ user = mAuth.getCurrentUser();
+
+ initViews();
+ premiumCheck();
+ targetRecyclerView.setLayoutManager(new LinearLayoutManager(Target.this));
+
+ startTarget(user);
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ change.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(checkChange){
+ changeOn();
+ checkChange = false;
+ }else{
+ changeOff();
+ checkChange = true;
+ }
+ }
+ });
+ }
+ public void initViews(){
+ prev = findViewById(R.id.prevButtonTarget);
+ change = findViewById(R.id.changeButton);
+ exName[0] = findViewById(R.id.ex1_name);
+ exName[1] = findViewById(R.id.ex2_name);
+ exName[2] = findViewById(R.id.ex3_name);
+ exName[3] = findViewById(R.id.ex4_name);
+ exName[4] = findViewById(R.id.ex5_name);
+ exName[5] = findViewById(R.id.ex6_name);
+ exName[6] = findViewById(R.id.ex7_name);
+ exName[7] = findViewById(R.id.ex8_name);
+ ex[0] = findViewById(R.id.ex1_cnt);
+ ex[1] = findViewById(R.id.ex2_cnt);
+ ex[2] = findViewById(R.id.ex3_cnt);
+ ex[3] = findViewById(R.id.ex4_cnt);
+ ex[4] = findViewById(R.id.ex5_cnt);
+ ex[5] = findViewById(R.id.ex6_cnt);
+ ex[6] = findViewById(R.id.ex7_cnt);
+ ex[7] = findViewById(R.id.ex8_cnt);
+ exNum[0] = findViewById(R.id.targetNum1);
+ exNum[1] = findViewById(R.id.targetNum2);
+ exNum[2] = findViewById(R.id.targetNum3);
+ exNum[3] = findViewById(R.id.targetNum4);
+ exNum[4] = findViewById(R.id.targetNum5);
+ exNum[5] = findViewById(R.id.targetNum6);
+ exNum[6] = findViewById(R.id.targetNum7);
+ exNum[7] = findViewById(R.id.targetNum8);
+ switches[0] = findViewById(R.id.switch1);
+ switches[1] = findViewById(R.id.switch2);
+ switches[2] = findViewById(R.id.switch3);
+ switches[3] = findViewById(R.id.switch4);
+ switches[4] = findViewById(R.id.switch5);
+ switches[5] = findViewById(R.id.switch6);
+ switches[6] = findViewById(R.id.switch7);
+ switches[7] = findViewById(R.id.switch8);
+ targetRecyclerView = findViewById(R.id.targetRecyclerView);
+ premiumView[0] = findViewById(R.id.premiumView1);
+ premiumView[1] = findViewById(R.id.premiumView2);
+ premiumView[2] = findViewById(R.id.premiumView3);
+
+ switches[0].setVisibility(View.GONE);
+ switches[1].setVisibility(View.GONE);
+ switches[2].setVisibility(View.GONE);
+ switches[3].setVisibility(View.GONE);
+ switches[4].setVisibility(View.GONE);
+ switches[5].setVisibility(View.GONE);
+ switches[6].setVisibility(View.GONE);
+ switches[7].setVisibility(View.GONE);
+ ex[0].setVisibility(View.GONE);
+ ex[1].setVisibility(View.GONE);
+ ex[2].setVisibility(View.GONE);
+ ex[3].setVisibility(View.GONE);
+ ex[4].setVisibility(View.GONE);
+ ex[5].setVisibility(View.GONE);
+ ex[6].setVisibility(View.GONE);
+ ex[7].setVisibility(View.GONE);
+ exNum[0].setVisibility(View.VISIBLE);
+ exNum[1].setVisibility(View.VISIBLE);
+ exNum[2].setVisibility(View.VISIBLE);
+ exNum[3].setVisibility(View.VISIBLE);
+ exNum[4].setVisibility(View.VISIBLE);
+ exNum[5].setVisibility(View.VISIBLE);
+ exNum[6].setVisibility(View.VISIBLE);
+ exNum[7].setVisibility(View.VISIBLE);
+ change.setText("수정");
+ }
+
+ public void changeOff(){
+ exNum[0].setText(ex[0].getText().toString());
+ exNum[1].setText(ex[1].getText().toString());
+ exNum[2].setText(ex[2].getText().toString());
+ exNum[3].setText(ex[3].getText().toString());
+ exNum[4].setText(ex[4].getText().toString());
+ exNum[5].setText(ex[5].getText().toString());
+ exNum[6].setText(ex[6].getText().toString());
+ exNum[7].setText(ex[7].getText().toString());
+ switches[0].setVisibility(View.GONE);
+ switches[1].setVisibility(View.GONE);
+ switches[2].setVisibility(View.GONE);
+ switches[3].setVisibility(View.GONE);
+ switches[4].setVisibility(View.GONE);
+ switches[5].setVisibility(View.GONE);
+ switches[6].setVisibility(View.GONE);
+ switches[7].setVisibility(View.GONE);
+ ex[0].setVisibility(View.GONE);
+ ex[1].setVisibility(View.GONE);
+ ex[2].setVisibility(View.GONE);
+ ex[3].setVisibility(View.GONE);
+ ex[4].setVisibility(View.GONE);
+ ex[5].setVisibility(View.GONE);
+ ex[6].setVisibility(View.GONE);
+ ex[7].setVisibility(View.GONE);
+ exNum[0].setVisibility(View.VISIBLE);
+ exNum[1].setVisibility(View.VISIBLE);
+ exNum[2].setVisibility(View.VISIBLE);
+ exNum[3].setVisibility(View.VISIBLE);
+ exNum[4].setVisibility(View.VISIBLE);
+ exNum[5].setVisibility(View.VISIBLE);
+ exNum[6].setVisibility(View.VISIBLE);
+ exNum[7].setVisibility(View.VISIBLE);
+ change.setText("수정");
+
+ saveTarget(user);
+
+ fetchData();
+ adapter = new TargetAdapter(targetList);
+ targetRecyclerView.setAdapter(adapter);
+ }
+ public void changeOn(){
+ ex[0].setText(exNum[0].getText().toString());
+ ex[1].setText(exNum[1].getText().toString());
+ ex[2].setText(exNum[2].getText().toString());
+ ex[3].setText(exNum[3].getText().toString());
+ ex[4].setText(exNum[4].getText().toString());
+ ex[5].setText(exNum[5].getText().toString());
+ ex[6].setText(exNum[6].getText().toString());
+ ex[7].setText(exNum[7].getText().toString());
+ switches[0].setVisibility(View.VISIBLE);
+ switches[1].setVisibility(View.VISIBLE);
+ switches[2].setVisibility(View.VISIBLE);
+ switches[3].setVisibility(View.VISIBLE);
+ switches[4].setVisibility(View.VISIBLE);
+ switches[5].setVisibility(View.VISIBLE);
+ switches[6].setVisibility(View.VISIBLE);
+ switches[7].setVisibility(View.VISIBLE);
+ ex[0].setVisibility(View.VISIBLE);
+ ex[1].setVisibility(View.VISIBLE);
+ ex[2].setVisibility(View.VISIBLE);
+ ex[3].setVisibility(View.VISIBLE);
+ ex[4].setVisibility(View.VISIBLE);
+ ex[5].setVisibility(View.VISIBLE);
+ ex[6].setVisibility(View.VISIBLE);
+ ex[7].setVisibility(View.VISIBLE);
+ exNum[0].setVisibility(View.INVISIBLE);
+ exNum[1].setVisibility(View.INVISIBLE);
+ exNum[2].setVisibility(View.INVISIBLE);
+ exNum[3].setVisibility(View.INVISIBLE);
+ exNum[4].setVisibility(View.INVISIBLE);
+ exNum[5].setVisibility(View.INVISIBLE);
+ exNum[6].setVisibility(View.INVISIBLE);
+ exNum[7].setVisibility(View.INVISIBLE);
+
+ for(int i = 0; i < 8; i++){
+ int finalI = i;
+ ex[i].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ showCntDialog(ex[finalI]);
+ }
+ });
+ }
+
+ change.setText("완료");
+
+
+ }
+
+ private void showCntDialog(Button ex) {
+ final String[] difficultyOptions = {"5개", "10개", "15개", "20개", "25개", "30개"};
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("개수 선택");
+ builder.setItems(difficultyOptions, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ selectCnt = difficultyOptions[which];
+ ex.setText(selectCnt);
+ }
+ });
+ builder.show();
+ }
+
+ private void startTarget(FirebaseUser user){
+
+ // 날짜 정보 생성
+ DateFormat dateFormatTwo = new SimpleDateFormat("yyyyMMdd");
+ String targetDate = dateFormatTwo.format(new Date());
+ String userId = user.getUid();
+
+ db.collection("dailyTarget")
+ .whereEqualTo("date", targetDate)
+ .whereEqualTo("uid", userId)
+ .get()
+ .addOnCompleteListener(new OnCompleteListener() {
+ @SuppressLint("SetTextI18n")
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ for (QueryDocumentSnapshot document : task.getResult()) {
+ // 해당 날짜의 데이터를 UI에 표시
+ exNum[0].setText(document.getString(exName[0].getText().toString()));
+ exNum[1].setText(document.getString(exName[1].getText().toString()));
+ exNum[2].setText(document.getString(exName[2].getText().toString()));
+ exNum[3].setText(document.getString(exName[3].getText().toString()));
+ exNum[4].setText(document.getString(exName[4].getText().toString()));
+ exNum[5].setText(document.getString(exName[5].getText().toString()));
+ exNum[6].setText(document.getString(exName[6].getText().toString()));
+ exNum[7].setText(document.getString(exName[7].getText().toString()));
+ }
+ } else {
+ // 쿼리가 실패한 경우 에러 처리
+ Log.d("Firestore", "Error getting documents: ", task.getException());
+ }
+ }
+ });
+ }
+
+ private void saveTarget(FirebaseUser user){
+ Map userData = new HashMap<>();
+ final String collectionName = "dailyTarget";
+
+ // 날짜 정보 생성
+ DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
+ String currentDate = dateFormat.format(new Date());
+
+ if(user != null){
+ userData.put("date", currentDate);
+ userData.put("uid", user.getUid());
+ userData.put(exName[0].getText().toString(), ex[0].getText().toString());
+ userData.put(exName[1].getText().toString(), ex[1].getText().toString());
+ userData.put(exName[2].getText().toString(), ex[2].getText().toString());
+ userData.put(exName[3].getText().toString(), ex[3].getText().toString());
+ userData.put(exName[4].getText().toString(), ex[4].getText().toString());
+ userData.put(exName[5].getText().toString(), ex[5].getText().toString());
+ userData.put(exName[6].getText().toString(), ex[6].getText().toString());
+ userData.put(exName[7].getText().toString(), ex[7].getText().toString());
+ }
+
+ db.collection(collectionName).document(user.getUid())
+ .set(userData)
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ }
+ });
+ }
+
+ static class TargetItem {
+ String exerciseName;
+ int myScore;
+
+ public TargetItem(String exerciseName, int myScore) {
+ this.exerciseName = exerciseName;
+ this.myScore = myScore;
+ }
+ }
+
+ private void fetchData() {
+ DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
+ String currentDate = dateFormat.format(new Date());
+ String collection = null;
+ String key = null;
+ String exercise = null;
+ int ex_num = 0;
+ targetList.clear();
+ for (int i = 0; i < switches.length; i++) {
+ if (switches[i].isChecked()) {
+ if(i == 0){
+ collection = "dailySquatRecords";
+ key = currentDate+"squatCount";
+ exercise = "스쿼트";
+ }else if(i == 1){
+ collection = "dailyPushupRecords";
+ key = currentDate+"pushupCount";
+ exercise = "푸쉬업";
+ }else if(i == 2){
+ collection = "dailyDumbbellRecords";
+ key = currentDate+"dumbbellCount";
+ exercise = "덤벨 숄더 프레스";
+ }else if(i == 3){
+ collection = "dailySideRecords";
+ key = currentDate+"sideCount";
+ exercise = "사이드 래터럴 레이즈";
+ }else if(i == 4){
+ collection = "dailyLegRecords";
+ key = currentDate+"legCount";
+ exercise = "레그 레이즈";
+ }else if(i == 5){
+ collection = "dailyCurlRecords";
+ key = currentDate+"CurlCount";
+ exercise = "덤벨 컬";
+ }else if(i == 6){
+ collection = "dailyFlyRecords";
+ key = currentDate+"flyCount";
+ exercise = "덤벨 플라이";
+ }else if(i == 7){
+ collection = "dailyTricepsRecords";
+ key = currentDate+"tricepsCount";
+ exercise = "덤벨 트라이셉스 익스텐션";
+ }
+ ex_num = extractNumber(exNum[i].getText().toString());
+ loadSquatRecordWithDate(collection, key, exercise, ex_num);
+ }
+ }
+ }
+ private void loadSquatRecordWithDate(String collection, String date, String ex, int en){
+ final String collectionName = collection;
+ String userId = user.getUid();
+ String key = date;
+
+ DocumentReference userRecordRef = db.collection(collectionName).document(userId);
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ int score = 0;
+ if(document.getLong(key) != null){
+ score = document.getLong(key).intValue();
+ }
+ int scoreSet = (int) ((double)score/(double)en*100);
+ String ex_name = ex + " ( " + score + " / " + en + " ) ";
+ targetList.add(new TargetItem(ex_name, scoreSet));
+ } else {
+ Log.d("Firestore", "No such document");
+ }
+ adapter.notifyDataSetChanged();
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+ }
+
+ public static int extractNumber(String input) {
+ Pattern pattern = Pattern.compile("\\d+"); // 숫자에 해당하는 정규식
+ Matcher matcher = pattern.matcher(input);
+
+ if (matcher.find()) {
+ return Integer.parseInt(matcher.group());
+ } else {
+ return 0; // 숫자가 없을 경우 0을 반환
+ }
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("스쿼트") || str.equals("푸쉬업") || str.equals("푸시업") || str.equals("덤벨 숄더 프레스") || str.equals("덤벨") || str.equals("덤벨숄더프레스") ||
+ str.equals("사이드 레터럴 레이즈") || str.equals("사레레") || str.equals("사이드레터럴레이즈") || str.equals("레그 레이즈") ||
+ str.equals("레그레이즈") || str.equals("준비 운동") || str.equals("준비운동")){
+ if(str.equals("스쿼트")){
+
+ }else if(str.equals("푸쉬업") || str.equals("푸시업")){
+
+ }else if(str.equals("덤벨 숄더 프레스") || str.equals("덤벨") || str.equals("덤벨숄더프레스")){
+
+ }else if(str.equals("사이드 레터럴 레이즈") || str.equals("사레레") || str.equals("사이드레터럴레이즈")){
+
+ }else if(str.equals("레그 레이즈") || str.equals("레그레이즈")){
+
+ }else if(str.equals("준비 운동") || str.equals("준비운동")){
+
+ }
+ }else if(str.equals("수정") || str.equals("완료")) {
+ if(checkChange){
+ changeOn();
+ checkChange = false;
+ }else{
+ changeOff();
+ checkChange = true;
+ }
+ }else if(str.equals("이전")){
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ intent.putExtra("SELECTED_FRAGMENT_INDEX", 3);
+ startActivity(intent);
+ finish();
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 10000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 3000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+
+ public void premiumCheck(){
+ if(user == null){
+ Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
+ startActivity(intent);
+ }else{
+ db.collection("users").document(user.getUid())
+ .get()
+ .addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@androidx.annotation.NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ String grade = document.getString("grade");
+ if (grade == null) grade = "일반";
+
+ if(grade.equals("프리미엄")){
+ premiumView[0].setVisibility(View.VISIBLE);
+ premiumView[1].setVisibility(View.VISIBLE);
+ premiumView[2].setVisibility(View.VISIBLE);
+ }
+ }
+ } else {
+ }
+ }
+ });
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/TargetAdapter.java b/app/src/main/java/com/example/newbody/TargetAdapter.java
new file mode 100644
index 0000000..2b7eb25
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/TargetAdapter.java
@@ -0,0 +1,53 @@
+package com.example.newbody;
+
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.List;
+
+public class TargetAdapter extends RecyclerView.Adapter{
+ private List targetList;
+
+ public TargetAdapter(List targetList) {
+ this.targetList = targetList;
+ }
+
+ @NonNull
+ @Override
+ public TargetViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View itemView = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.target_item, parent, false);
+ return new TargetViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull TargetViewHolder holder, int position) {
+ Target.TargetItem currentItem = targetList.get(position);
+ holder.targetName.setText(String.valueOf(currentItem.exerciseName));
+ holder.progressBar.setProgress(currentItem.myScore);
+ Log.d("num", String.valueOf(currentItem.myScore));
+ }
+
+ @Override
+ public int getItemCount() {
+ return targetList.size();
+ }
+
+ static class TargetViewHolder extends RecyclerView.ViewHolder {
+ TextView targetName;
+ ProgressBar progressBar;
+
+ public TargetViewHolder(@NonNull View itemView) {
+ super(itemView);
+ targetName = itemView.findViewById(R.id.targetName);
+ progressBar = itemView.findViewById(R.id.progressBar);
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/TargetPose.java b/app/src/main/java/com/example/newbody/TargetPose.java
new file mode 100644
index 0000000..55d93d5
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/TargetPose.java
@@ -0,0 +1,36 @@
+package com.example.newbody;
+
+import java.util.List;
+import java.util.Objects;
+
+public class TargetPose {
+ private final List targets;
+
+ public TargetPose(List targets) {
+ this.targets = targets;
+ }
+
+ public List getTargets() {
+ return targets;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ TargetPose that = (TargetPose) o;
+ return Objects.equals(targets, that.targets);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(targets);
+ }
+
+ @Override
+ public String toString() {
+ return "TargetPose{" +
+ "targets=" + targets +
+ '}';
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/TargetShape.java b/app/src/main/java/com/example/newbody/TargetShape.java
new file mode 100644
index 0000000..9a55785
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/TargetShape.java
@@ -0,0 +1,60 @@
+package com.example.newbody;
+
+import java.util.List;
+import java.util.Objects;
+
+public class TargetShape {
+ private final int firstLandmarkType;
+ private final int middleLandmarkType;
+ private final int lastLandmarkType;
+ private final double angle;
+
+ public TargetShape(int firstLandmarkType, int middleLandmarkType, int lastLandmarkType, double angle) {
+ this.firstLandmarkType = firstLandmarkType;
+ this.middleLandmarkType = middleLandmarkType;
+ this.lastLandmarkType = lastLandmarkType;
+ this.angle = angle;
+ }
+
+ public int getFirstLandmarkType() {
+ return firstLandmarkType;
+ }
+
+ public int getMiddleLandmarkType() {
+ return middleLandmarkType;
+ }
+
+ public int getLastLandmarkType() {
+ return lastLandmarkType;
+ }
+
+ public double getAngle() {
+ return angle;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ TargetShape that = (TargetShape) o;
+ return firstLandmarkType == that.firstLandmarkType &&
+ middleLandmarkType == that.middleLandmarkType &&
+ lastLandmarkType == that.lastLandmarkType &&
+ Double.compare(that.angle, angle) == 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(firstLandmarkType, middleLandmarkType, lastLandmarkType, angle);
+ }
+
+ @Override
+ public String toString() {
+ return "TargetShape{" +
+ "firstLandmarkType=" + firstLandmarkType +
+ ", middleLandmarkType=" + middleLandmarkType +
+ ", lastLandmarkType=" + lastLandmarkType +
+ ", angle=" + angle +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/Video.java b/app/src/main/java/com/example/newbody/Video.java
new file mode 100644
index 0000000..f65e8fe
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/Video.java
@@ -0,0 +1,332 @@
+package com.example.newbody;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.speech.RecognizerIntent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.example.newbody.posture.PostureInfo;
+import com.example.newbody.videoinfo.VideoDumbbell;
+import com.example.newbody.videoinfo.VideoLegRaise;
+import com.example.newbody.videoinfo.VideoPushups;
+import com.example.newbody.videoinfo.VideoSide;
+import com.example.newbody.videoinfo.VideoSquat;
+import com.example.newbody.videoinfo.VideoWarmup;
+import com.example.newbody.workout.Home_Training_WarmUp;
+
+import java.util.ArrayList;
+
+public class Video extends AppCompatActivity {
+ private String selectedDifficulty; // 난이도를 저장할 변수
+ private Button difficulty, start, prev;
+ private View []ex = new View[6];
+ private TextView[] LevelCountView = new TextView[6];
+ private View warmupVideo;
+ private View pushupsVideo;
+ private View squatVideo;
+ private View dumbbellVideo;
+ private View sideVideo;
+ private View legraiseVideo;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_video);
+
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+
+ difficulty = findViewById(R.id.difficulty);
+ ex[0] = findViewById(R.id.ex_button1);
+ ex[1] = findViewById(R.id.ex_button2);
+ ex[2] = findViewById(R.id.ex_button3);
+ ex[3] = findViewById(R.id.ex_button4);
+ ex[4] = findViewById(R.id.ex_button5);
+ ex[5] = findViewById(R.id.ex_button6);
+ LevelCountView[0] = findViewById(R.id.levelcountview1);
+ LevelCountView[1] = findViewById(R.id.levelcountview2);
+ LevelCountView[2] = findViewById(R.id.levelcountview3);
+ LevelCountView[3] = findViewById(R.id.levelcountview4);
+ LevelCountView[4] = findViewById(R.id.levelcountview5);
+ LevelCountView[5] = findViewById(R.id.levelcountview6);
+ start = findViewById(R.id.start_b);
+ prev = findViewById(R.id.prevButtonTraning);
+
+ warmupVideo = findViewById(R.id.ellipse_1);
+ squatVideo = findViewById(R.id.ellipse_2);
+ pushupsVideo = findViewById(R.id.ellipse_3);
+ dumbbellVideo = findViewById(R.id.ellipse_4);
+ sideVideo = findViewById(R.id.ellipse_5);
+ legraiseVideo = findViewById(R.id.ellipse_6);
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ difficulty.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ showDifficultyDialog();
+ }
+ });
+
+ warmupVideo.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), VideoWarmup.class);
+ startActivity(intent);
+ }
+ });
+
+ squatVideo.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), VideoSquat.class);
+ startActivity(intent);
+ }
+ });
+
+ pushupsVideo.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), VideoPushups.class);
+ startActivity(intent);
+ }
+ });
+
+ dumbbellVideo.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), VideoDumbbell.class);
+ startActivity(intent);
+ }
+ });
+
+ sideVideo.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), VideoSide.class);
+ startActivity(intent);
+ }
+ });
+
+ legraiseVideo.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), VideoLegRaise.class);
+ startActivity(intent);
+ }
+ });
+
+ start.setOnClickListener(new View.OnClickListener() {
+
+
+ @Override
+ public void onClick(View v) {
+ if (selectedDifficulty != null) {
+
+ Intent intentSub1 = new Intent(Video.this, Home_Training_WarmUp.class);
+ intentSub1.putExtra("difficulty", selectedDifficulty); // 선택한 난이도 정보를 넘겨줌
+ startActivity(intentSub1);
+
+ }
+ else {
+ Toast.makeText(Video.this, "난이도를 먼저 선택해주세요.", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+
+ }
+
+ private void showDifficultyDialog() {
+ final String[] difficultyOptions = {"쉬움", "보통", "어려움"};
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("난이도 선택");
+ builder.setItems(difficultyOptions, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ selectedDifficulty = difficultyOptions[which];
+ difficulty.setText(selectedDifficulty);
+
+ // 선택한 난이도에 따라 시간 배열을 업데이트
+ if (selectedDifficulty.equals("쉬움")) {
+ LevelCountView[0].setText("05:00"); // 준비운동
+ LevelCountView[1].setText("15개"); // 스쿼트
+ LevelCountView[2].setText("7개"); // 푸시업
+ LevelCountView[3].setText("10개"); // 덤프
+ LevelCountView[4].setText("15개"); // 사레레
+ LevelCountView[5].setText("7개"); // 레그라이즈
+ } else if (selectedDifficulty.equals("보통")) {
+ LevelCountView[0].setText("05:00"); // 준비운동
+ LevelCountView[1].setText("20개"); // 스쿼트
+ LevelCountView[2].setText("20개"); // 푸시업
+ LevelCountView[3].setText("10개"); // 덤프
+ LevelCountView[4].setText("25개"); // 사레레
+ LevelCountView[5].setText("15개"); // 레그라이즈
+ } else if (selectedDifficulty.equals("어려움")) {
+ LevelCountView[0].setText("05:00"); // 준비운동
+ LevelCountView[1].setText("25개"); // 스쿼트
+ LevelCountView[2].setText("35개"); // 푸시업
+ LevelCountView[3].setText("10개"); // 덤프
+ LevelCountView[4].setText("35개"); // 사레레
+ LevelCountView[5].setText("20개"); // 레그라이즈
+ }
+ }
+ });
+ builder.show();
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("스쿼트") || str.equals("푸쉬업") || str.equals("푸시업") || str.equals("덤벨 숄더 프레스") || str.equals("덤벨") || str.equals("덤벨숄더프레스") ||
+ str.equals("사이드 레터럴 레이즈") || str.equals("사레레") || str.equals("사이드레터럴레이즈") || str.equals("레그 레이즈") ||
+ str.equals("레그레이즈") || str.equals("준비 운동") || str.equals("준비운동")){
+ if(str.equals("스쿼트")){
+ Intent intent = new Intent(getApplicationContext(), VideoSquat.class);
+ startActivity(intent);
+ }else if(str.equals("푸쉬업") || str.equals("푸시업")){
+ Intent intent = new Intent(getApplicationContext(), VideoPushups.class);
+ startActivity(intent);
+ }else if(str.equals("덤벨 숄더 프레스") || str.equals("덤벨") || str.equals("덤벨숄더프레스")){
+ Intent intent = new Intent(getApplicationContext(), VideoDumbbell.class);
+ startActivity(intent);
+ }else if(str.equals("사이드 레터럴 레이즈") || str.equals("사레레") || str.equals("사이드레터럴레이즈")){
+ Intent intent = new Intent(getApplicationContext(), VideoSide.class);
+ startActivity(intent);
+ }else if(str.equals("레그 레이즈") || str.equals("레그레이즈")){
+ Intent intent = new Intent(getApplicationContext(), VideoLegRaise.class);
+ startActivity(intent);
+ }else if(str.equals("준비 운동") || str.equals("준비운동")){
+ Intent intent = new Intent(getApplicationContext(), VideoWarmup.class);
+ startActivity(intent);
+ }
+ }else if(str.equals("쉬움") || str.equals("보통") || str.equals("어려움")){
+ difficulty.setText(str);
+ selectedDifficulty = difficulty.getText().toString();
+
+ // 선택한 난이도에 따라 시간 배열을 업데이트
+ if (selectedDifficulty.equals("쉬움")) {
+ LevelCountView[0].setText("05:00"); // 준비운동
+ LevelCountView[1].setText("15개"); // 스쿼트
+ LevelCountView[2].setText("7개"); // 푸시업
+ LevelCountView[3].setText("10개"); // 덤프
+ LevelCountView[4].setText("15개"); // 사레레
+ LevelCountView[5].setText("7개"); // 레그라이즈
+ } else if (selectedDifficulty.equals("보통")) {
+ LevelCountView[0].setText("05:00"); // 준비운동
+ LevelCountView[1].setText("20개"); // 스쿼트
+ LevelCountView[2].setText("20개"); // 푸시업
+ LevelCountView[3].setText("10개"); // 덤프
+ LevelCountView[4].setText("25개"); // 사레레
+ LevelCountView[5].setText("15개"); // 레그라이즈
+ } else if (selectedDifficulty.equals("어려움")) {
+ LevelCountView[0].setText("05:00"); // 준비운동
+ LevelCountView[1].setText("25개"); // 스쿼트
+ LevelCountView[2].setText("35개"); // 푸시업
+ LevelCountView[3].setText("10개"); // 덤프
+ LevelCountView[4].setText("35개"); // 사레레
+ LevelCountView[5].setText("20개"); // 레그라이즈
+ }
+ }else if(str.equals("이전")){
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ }else if(str.equals("시작") || str.equals("운동 시작")){
+ if (selectedDifficulty != null) {
+
+ Intent intentSub1 = new Intent(Video.this, Home_Training_WarmUp.class);
+ intentSub1.putExtra("difficulty", selectedDifficulty); // 선택한 난이도 정보를 넘겨줌
+ startActivity(intentSub1);
+
+ }
+ else {
+ Toast.makeText(Video.this, "난이도를 먼저 선택해주세요.", Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 10000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 3000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+
+ @Override
+ public void onBackPressed() {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/VoiceRecognitionService.java b/app/src/main/java/com/example/newbody/VoiceRecognitionService.java
new file mode 100644
index 0000000..7f42d00
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/VoiceRecognitionService.java
@@ -0,0 +1,146 @@
+package com.example.newbody;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.speech.RecognitionListener;
+import android.speech.RecognizerIntent;
+import android.speech.SpeechRecognizer;
+import androidx.core.content.ContextCompat;
+import android.Manifest;
+import android.util.Log;
+import android.widget.Toast;
+import androidx.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.Locale;
+import android.speech.tts.TextToSpeech;
+
+public class VoiceRecognitionService extends Service {
+ protected SpeechRecognizer mSpeechRecognizer;
+ protected Intent mRecognizerIntent;
+ private TextToSpeech mTextToSpeech;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ // Check for permissions
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
+ // Permission handling is more complex in a service, you might want to stop the service if you don't have permissions
+ stopSelf();
+ return;
+ }
+
+ startVoiceRecognition();
+ initTTS();
+ }
+
+ private void initTTS() {
+ mTextToSpeech = new TextToSpeech(this, status -> {
+ if (status != TextToSpeech.ERROR) {
+ mTextToSpeech.setLanguage(Locale.KOREAN);
+ mTextToSpeech.setSpeechRate(0.7f);
+ mTextToSpeech.setPitch(1.1f);
+ }
+ });
+ }
+
+ private void startVoiceRecognition() {
+ mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
+ mRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ mRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, Locale.getDefault());
+ mRecognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, this.getPackageName());
+ mRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
+ mRecognizerIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 3);
+
+ mSpeechRecognizer.setRecognitionListener(new RecognitionListener() {
+ @Override
+ public void onReadyForSpeech(Bundle params) {}
+
+ @Override
+ public void onBeginningOfSpeech() {}
+
+ @Override
+ public void onRmsChanged(float rmsdB) {}
+
+ @Override
+ public void onBufferReceived(byte[] buffer) {}
+
+ @Override
+ public void onEndOfSpeech() {}
+
+ @Override
+ public void onError(int error) {
+ switch (error) {
+ case SpeechRecognizer.ERROR_NETWORK_TIMEOUT:
+ case SpeechRecognizer.ERROR_NETWORK:
+ case SpeechRecognizer.ERROR_AUDIO:
+ case SpeechRecognizer.ERROR_SERVER:
+ case SpeechRecognizer.ERROR_CLIENT:
+ case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
+ case SpeechRecognizer.ERROR_NO_MATCH:
+ case SpeechRecognizer.ERROR_RECOGNIZER_BUSY:
+ case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS:
+ mSpeechRecognizer.startListening(mRecognizerIntent);
+ break;
+ default:
+ mSpeechRecognizer.cancel();
+ mSpeechRecognizer.startListening(mRecognizerIntent);
+ break;
+ }
+ }
+
+ @Override
+ public void onResults(Bundle results) {
+ ArrayList matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
+ if (matches != null && matches.size() > 0) {
+ if (matches.contains("바디야") || matches.contains("뉴바디")) {
+ sendResult(1);
+ speakOut("네");
+ }
+ }
+ new android.os.Handler().postDelayed(() -> mSpeechRecognizer.startListening(mRecognizerIntent), 2000);
+ }
+
+
+ @Override
+ public void onPartialResults(Bundle partialResults) {}
+
+ @Override
+ public void onEvent(int eventType, Bundle params) {}
+ });
+ mSpeechRecognizer.startListening(mRecognizerIntent);
+ }
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null; // For this use-case, we don't need binding.
+ }
+
+ private void speakOut(String text) {
+ mTextToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mSpeechRecognizer != null) {
+ mSpeechRecognizer.destroy();
+ }
+ if (mTextToSpeech != null) {
+ mTextToSpeech.stop();
+ mTextToSpeech.shutdown();
+ }
+ }
+
+ private void sendResult(int resultCode) {
+ Intent intent = new Intent("com.example.newbody.RESULT_ACTION");
+ intent.putExtra("resultCode", resultCode);
+ sendBroadcast(intent);
+ }
+
+}
+
diff --git a/app/src/main/java/com/example/newbody/YogaPosture.java b/app/src/main/java/com/example/newbody/YogaPosture.java
new file mode 100644
index 0000000..26ee139
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/YogaPosture.java
@@ -0,0 +1,184 @@
+package com.example.newbody;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.newbody.posture.PostureInfo;
+
+import java.util.ArrayList;
+
+public class YogaPosture extends AppCompatActivity {
+
+ private View ex_start;
+ private View []yoga = new View[3];
+ private TextView[]yogaName = new TextView[3];
+ private TextView selectE;
+ private View catView, downDogView, cobraView;
+ private Button prev;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_yoga_posture);
+
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+
+ initViews();
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ yoga[0].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(yogaName[0].getText());
+ }
+ });
+ yoga[1].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(yogaName[1].getText());
+ }
+ });
+ yoga[2].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectE.setText(yogaName[2].getText());
+ }
+ });
+
+ ex_start.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if(selectE.getText().equals("운동")){
+ Toast.makeText(YogaPosture.this, "운동을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ Intent intent = new Intent(getApplicationContext(), PostureInfo.class);
+ intent.putExtra("exercise", selectE.getText());
+ startActivity(intent);
+ finish();
+ }
+ });
+ }
+
+ public void initViews(){
+ prev = findViewById(R.id.prevButtonYogaPosture);
+ ex_start = findViewById(R.id.start_button);
+ yoga[0] = findViewById(R.id.yoga_button1);
+ yoga[1] = findViewById(R.id.yoga_button2);
+ yoga[2] = findViewById(R.id.yoga_button3);
+ yogaName[0] = findViewById(R.id.yoga1_name);
+ yogaName[1] = findViewById(R.id.yoga2_name);
+ yogaName[2] = findViewById(R.id.yoga3_name);
+ selectE = findViewById(R.id.exercise_select);
+ catView = findViewById(R.id.catYogaView1);
+ downDogView = findViewById(R.id.downdogYogaView1);
+ cobraView = findViewById(R.id.cobraYogaView1);
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("고양이") || str.equals("고양이자세") || str.equals("고양이 자세") || str.equals("다운 독") || str.equals("다운독") || str.equals("다운독 자세") ||
+ str.equals("코브라") || str.equals("코브라자세") || str.equals("코브라 자세")){
+ if(str.equals("고양이") || str.equals("고양이자세") || str.equals("고양이 자세")){
+ selectE.setText(yogaName[0].getText());
+ }else if(str.equals("다운 독") || str.equals("다운독") || str.equals("다운독 자세")){
+ selectE.setText(yogaName[1].getText());
+ }else if(str.equals("코브라") || str.equals("코브라자세") || str.equals("코브라 자세")){
+ selectE.setText(yogaName[2].getText());
+ }
+ }else if(str.equals("시작") || str.equals("운동 시작")){
+ if(selectE.getText().equals("운동")){
+ Toast.makeText(YogaPosture.this, "운동을 선택해주세요", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ Intent intent = new Intent(getApplicationContext(), PostureInfo.class);
+ intent.putExtra("exercise", selectE.getText());
+ startActivity(intent);
+ finish();
+ }else if(str.equals("이전")){
+ Intent intent = new Intent(getApplicationContext(), Menu.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 10000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 3000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/mainInfo/MainActivityA.java b/app/src/main/java/com/example/newbody/mainInfo/MainActivityA.java
new file mode 100644
index 0000000..7160f5d
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/mainInfo/MainActivityA.java
@@ -0,0 +1,27 @@
+package com.example.newbody.mainInfo;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.example.newbody.R;
+
+public class MainActivityA extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_maina);
+
+ View button = findViewById(R.id.nextbutton1);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), MainActivityB.class);
+ startActivity(intent);
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/mainInfo/MainActivityB.java b/app/src/main/java/com/example/newbody/mainInfo/MainActivityB.java
new file mode 100644
index 0000000..a2796ab
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/mainInfo/MainActivityB.java
@@ -0,0 +1,27 @@
+package com.example.newbody.mainInfo;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.example.newbody.R;
+
+public class MainActivityB extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_mainb);
+
+ View button = findViewById(R.id.nextbutton2);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), MainActivityC.class);
+ startActivity(intent);
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/mainInfo/MainActivityC.java b/app/src/main/java/com/example/newbody/mainInfo/MainActivityC.java
new file mode 100644
index 0000000..d8e3d69
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/mainInfo/MainActivityC.java
@@ -0,0 +1,27 @@
+package com.example.newbody.mainInfo;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.example.newbody.R;
+
+public class MainActivityC extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_mainc);
+
+ View button = findViewById(R.id.nextbutton3);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), MainActivityD.class);
+ startActivity(intent);
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/mainInfo/MainActivityD.java b/app/src/main/java/com/example/newbody/mainInfo/MainActivityD.java
new file mode 100644
index 0000000..f8e3ff0
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/mainInfo/MainActivityD.java
@@ -0,0 +1,28 @@
+package com.example.newbody.mainInfo;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.example.newbody.Membership;
+import com.example.newbody.R;
+
+public class MainActivityD extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_maind);
+
+ View button = findViewById(R.id.nextbutton4);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Membership.class);
+ startActivity(intent);
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/example/newbody/posture/PostureCurl.java b/app/src/main/java/com/example/newbody/posture/PostureCurl.java
new file mode 100644
index 0000000..2595431
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/posture/PostureCurl.java
@@ -0,0 +1,427 @@
+package com.example.newbody.posture;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.speech.RecognizerIntent;
+import android.speech.tts.TextToSpeech;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.Preview;
+import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.camera.view.PreviewView;
+import androidx.core.app.ActivityCompat;
+
+import com.example.newbody.PoseMatcher;
+import com.example.newbody.Posture;
+import com.example.newbody.R;
+import com.example.newbody.TargetPose;
+import com.example.newbody.TargetShape;
+import com.example.newbody.VoiceRecognitionService;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.mlkit.vision.common.InputImage;
+import com.google.mlkit.vision.pose.Pose;
+import com.google.mlkit.vision.pose.PoseDetection;
+import com.google.mlkit.vision.pose.PoseDetector;
+import com.google.mlkit.vision.pose.PoseLandmark;
+import com.google.mlkit.vision.pose.accurate.AccuratePoseDetectorOptions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+public class PostureCurl extends AppCompatActivity {
+
+ private boolean dumbbellStartDetected = false;
+ private boolean dumbbellEndDetected = false;
+ private boolean checkUp = false;
+ private boolean checkDown = false;
+ private boolean checkCurl = false;
+ private TargetPose targetCurlStartSign;
+ private TargetPose targetCurlEndSign;
+ private TargetPose targetCurlLowSign;
+ private TextToSpeech tts;
+
+
+ PreviewView previewView;
+ PoseDetector detector;
+ ImageView guidelineView;
+ ImageCapture imageCapture;
+ TextView curlPosture;
+
+ Button exit;
+
+ Canvas guidelineCanvas;
+ Bitmap guidelineBmp, tempBitmap;
+ Paint guidePointPaint, guidePaint, transPaint;
+
+ private final int UPDATE_TIME = 40;
+ private boolean isFrameBeingTested = false, canvasAlreadyClear = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_posture_curl);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
+ @Override
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int langResult = tts.setLanguage(Locale.KOREAN);
+ if (langResult == TextToSpeech.LANG_MISSING_DATA |
+ langResult == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e("TTS", "Language is not supported or missing data");
+ }else {
+ // 피치와 속도를 조절합니다.
+ tts.setPitch(0.8f); // 높은 톤
+ tts.setSpeechRate(0.9f); // 약간 빠른 속도
+ tts.speak("덤벨 컬을 시작합니다.", TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ } else {
+ Log.e("TTS", "Initialization failed");
+ }
+ }
+ });
+
+ initTargetPoses();
+ initViews();
+ exit.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Posture.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ checkPermissions();
+ }
+
+ private void loadGuidelines(Bitmap bmp, Pose pose){
+ new Handler(getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ guidelineBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
+ guidelineCanvas = new Canvas(guidelineBmp);
+
+ if(transPaint == null || guidePaint == null){
+ transPaint = new Paint();
+ transPaint.setColor(Color.TRANSPARENT);
+ transPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePointPaint = new Paint();
+ guidePointPaint.setColor(Color.RED);
+ guidePointPaint.setStrokeWidth(10f);
+ guidePointPaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePointPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePaint = new Paint();
+ guidePaint.setColor(Color.WHITE);
+ guidePaint.setStrokeWidth(3f);
+ guidePaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePaint.setStyle(Paint.Style.STROKE);
+ }
+
+ // setting everything as transparent
+ guidelineCanvas.drawColor(Color.TRANSPARENT);
+// guidelineCanvas.drawRect(0, 0, guidelineBmp.getWidth(), guidelineBmp.getHeight(), transPaint);
+
+ // drawing just a rect
+ if(pose != null){
+ for(PoseLandmark landmark : pose.getAllPoseLandmarks()){
+ guidelineCanvas.drawCircle(landmark.getPosition().x, landmark.getPosition().y, 6f, guidePointPaint);
+ }
+
+ // drawing lines
+ // TORSO
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, guidePaint);
+
+ //limbs
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().y, guidePaint);
+ //
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().y, guidePaint);
+
+ //MOUTH
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ canvasAlreadyClear = false;
+ }else{
+ canvasAlreadyClear = true;
+ }
+
+ guidelineView.invalidate();
+ guidelineView.setImageBitmap(guidelineBmp);
+ Log.d("debugg", "New Guidelines Drawn");
+ }
+ });
+
+ }
+
+ private void initViews(){
+ previewView = findViewById(R.id.viewFinder);
+ guidelineView = findViewById(R.id.canvas);
+ exit = findViewById(R.id.exitButton);
+ curlPosture = findViewById(R.id.postureCurlEx);
+ }
+
+ private void runTest(){
+ if(detector == null){
+ AccuratePoseDetectorOptions options = new AccuratePoseDetectorOptions.Builder().setDetectorMode(AccuratePoseDetectorOptions.STREAM_MODE).build();
+ detector = PoseDetection.getClient(options);
+ }
+
+ tempBitmap = previewView.getBitmap();
+ if(previewView.getBitmap() == null){
+ return;
+ }
+
+ isFrameBeingTested = true;
+ detector.process(InputImage.fromBitmap(tempBitmap, 0)).addOnCompleteListener(new OnCompleteListener() {
+
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if(task.isSuccessful()){
+ Pose pose = task.getResult();
+ handlePoseDetection(pose); // 포즈 감지 후 적절한 동작 처리
+ List landmarks = pose.getAllPoseLandmarks();
+ Log.d("debugg", "Landmarks found : " + landmarks.size());
+ if(landmarks.size() == 0){
+ isFrameBeingTested = false;
+ if(!canvasAlreadyClear)
+ loadGuidelines(tempBitmap, null);
+ return;
+ }
+
+ loadGuidelines(tempBitmap, pose);
+ isFrameBeingTested = false;
+ }else{
+ Log.e("debugg", "Error in test", task.getException());
+ loadGuidelines(tempBitmap, null);
+ isFrameBeingTested = false;
+ }
+ }
+ });
+ }
+
+ private void initTargetPoses() {
+ targetCurlStartSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST,150.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST,150.0)
+ )
+ );
+
+ targetCurlEndSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST,50.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST,50.0)
+ )
+ );
+
+ targetCurlLowSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST,40.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST,40.0)
+ )
+ );
+ }
+
+ private boolean isPoseMatching(Pose pose, TargetPose targetPose) {
+ PoseMatcher matcher = new PoseMatcher(); // PoseMatcher 객체 생성. 이전에 제공된 코드에서 제공된 것처럼 생성해야 합니다.
+ return matcher.match(pose, targetPose);
+ }
+
+ private void handlePoseDetection(Pose pose) {
+ boolean isCurlStart = isPoseMatching(pose, targetCurlStartSign);
+ boolean isCurlEnd = isPoseMatching(pose, targetCurlEndSign);
+ boolean isCurlLow = isPoseMatching(pose, targetCurlLowSign);
+
+ if (isCurlEnd) {
+ curlPosture.setText("올리세요");
+ if(!checkCurl){
+ speakDumbbellStart();
+ checkCurl = true;
+ }
+ checkDown = true;
+ } else if (isCurlStart) {
+ if (checkDown) {
+ curlPosture.setText("잘했습니다");
+ speakDumbbellEnd();
+ checkCurl = false;
+ }
+ checkDown = false;
+ } else if (!checkDown && !isCurlLow) {
+ curlPosture.setText("더 올리세요");
+ }
+ }
+
+ private void speakDumbbellEnd() {
+ String textToSpeak ="잘했어요 다시 해볼까요?";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ private void speakDumbbellStart() {
+ String textToSpeak ="좋아요";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void startAnalysis(){
+ Handler handler = new Handler(getMainLooper());
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(!isFrameBeingTested){
+ runTest();
+ }
+ handler.postDelayed(this, UPDATE_TIME);
+ }
+ });
+ }
+
+ private void startInit(){
+ ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(this);
+ cameraProviderFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ProcessCameraProvider provider = cameraProviderFuture.get();
+
+ Preview preview = new Preview.Builder().build();
+ preview.setSurfaceProvider(previewView.createSurfaceProvider());
+ imageCapture = new ImageCapture.Builder().build();
+
+ provider.unbindAll();
+ provider.bindToLifecycle(PostureCurl.this, CameraSelector.DEFAULT_FRONT_CAMERA, preview);
+
+ startAnalysis();
+ } catch (Exception e) {
+ Log.e("debugg", "Error Getting camera Provider", e);
+ }
+ }
+ }, ActivityCompat.getMainExecutor(PostureCurl.this));
+ }
+
+ private void checkPermissions(){
+ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 455);
+ }else{
+ startInit();
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == 455) {
+ if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ finish();
+ } else {
+ startInit();
+ }
+ }
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("나가기") || str.equals("종료")){
+ Intent intent = new Intent(PostureCurl.this, Posture.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 2000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/posture/PostureDumbbell.java b/app/src/main/java/com/example/newbody/posture/PostureDumbbell.java
new file mode 100644
index 0000000..60755b6
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/posture/PostureDumbbell.java
@@ -0,0 +1,432 @@
+package com.example.newbody.posture;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.Preview;
+import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.camera.view.PreviewView;
+import androidx.core.app.ActivityCompat;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.speech.RecognizerIntent;
+import android.speech.tts.TextToSpeech;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+import com.example.newbody.PoseMatcher;
+import com.example.newbody.Posture;
+import com.example.newbody.R;
+import com.example.newbody.TargetPose;
+import com.example.newbody.TargetShape;
+import com.example.newbody.VoiceRecognitionService;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.mlkit.vision.common.InputImage;
+import com.google.mlkit.vision.pose.Pose;
+import com.google.mlkit.vision.pose.PoseDetection;
+import com.google.mlkit.vision.pose.PoseDetector;
+import com.google.mlkit.vision.pose.PoseLandmark;
+import com.google.mlkit.vision.pose.accurate.AccuratePoseDetectorOptions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+public class PostureDumbbell extends AppCompatActivity {
+
+ private boolean dumbbellStartDetected = false;
+ private boolean dumbbellEndDetected = false;
+ private boolean checkUp = false;
+ private boolean checkDown = false;
+ private boolean checkDumbbell = false;
+ private TargetPose targetDumbbellStartSign;
+ private TargetPose targetDumbbellEndSign;
+ private TargetPose targetDumbbellLowSign;
+ private TextToSpeech tts;
+
+
+ PreviewView previewView;
+ PoseDetector detector;
+ ImageView guidelineView;
+ ImageCapture imageCapture;
+ TextView dumbbellPosture;
+
+ Button exit;
+
+ Canvas guidelineCanvas;
+ Bitmap guidelineBmp, tempBitmap;
+ Paint guidePointPaint, guidePaint, transPaint;
+
+ private final int UPDATE_TIME = 40;
+ private boolean isFrameBeingTested = false, canvasAlreadyClear = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_posture_dumbbell);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
+ @Override
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int langResult = tts.setLanguage(Locale.KOREAN);
+ if (langResult == TextToSpeech.LANG_MISSING_DATA |
+ langResult == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e("TTS", "Language is not supported or missing data");
+ }else {
+ // 피치와 속도를 조절합니다.
+ tts.setPitch(0.8f); // 높은 톤
+ tts.setSpeechRate(0.9f); // 약간 빠른 속도
+ tts.speak("덤벨숄더프레스를 시작합니다.", TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ } else {
+ Log.e("TTS", "Initialization failed");
+ }
+ }
+ });
+
+ initTargetPoses();
+ initViews();
+ exit.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Posture.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ checkPermissions();
+ }
+
+ private void loadGuidelines(Bitmap bmp, Pose pose){
+ new Handler(getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ guidelineBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
+ guidelineCanvas = new Canvas(guidelineBmp);
+
+ if(transPaint == null || guidePaint == null){
+ transPaint = new Paint();
+ transPaint.setColor(Color.TRANSPARENT);
+ transPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePointPaint = new Paint();
+ guidePointPaint.setColor(Color.RED);
+ guidePointPaint.setStrokeWidth(10f);
+ guidePointPaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePointPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePaint = new Paint();
+ guidePaint.setColor(Color.WHITE);
+ guidePaint.setStrokeWidth(3f);
+ guidePaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePaint.setStyle(Paint.Style.STROKE);
+ }
+
+ // setting everything as transparent
+ guidelineCanvas.drawColor(Color.TRANSPARENT);
+// guidelineCanvas.drawRect(0, 0, guidelineBmp.getWidth(), guidelineBmp.getHeight(), transPaint);
+
+ // drawing just a rect
+ if(pose != null){
+ for(PoseLandmark landmark : pose.getAllPoseLandmarks()){
+ guidelineCanvas.drawCircle(landmark.getPosition().x, landmark.getPosition().y, 6f, guidePointPaint);
+ }
+
+ // drawing lines
+ // TORSO
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, guidePaint);
+
+ //limbs
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().y, guidePaint);
+ //
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().y, guidePaint);
+
+ //MOUTH
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ canvasAlreadyClear = false;
+ }else{
+ canvasAlreadyClear = true;
+ }
+
+ guidelineView.invalidate();
+ guidelineView.setImageBitmap(guidelineBmp);
+ Log.d("debugg", "New Guidelines Drawn");
+ }
+ });
+
+ }
+
+ private void initViews(){
+ previewView = findViewById(R.id.viewFinder);
+ guidelineView = findViewById(R.id.canvas);
+ exit = findViewById(R.id.exitButton);
+ dumbbellPosture = findViewById(R.id.postureDumbbellEx);
+ }
+
+ private void runTest(){
+ if(detector == null){
+ AccuratePoseDetectorOptions options = new AccuratePoseDetectorOptions.Builder().setDetectorMode(AccuratePoseDetectorOptions.STREAM_MODE).build();
+ detector = PoseDetection.getClient(options);
+ }
+
+ tempBitmap = previewView.getBitmap();
+ if(previewView.getBitmap() == null){
+ return;
+ }
+
+ isFrameBeingTested = true;
+ detector.process(InputImage.fromBitmap(tempBitmap, 0)).addOnCompleteListener(new OnCompleteListener() {
+
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if(task.isSuccessful()){
+ Pose pose = task.getResult();
+ handlePoseDetection(pose); // 포즈 감지 후 적절한 동작 처리
+ List landmarks = pose.getAllPoseLandmarks();
+ Log.d("debugg", "Landmarks found : " + landmarks.size());
+ if(landmarks.size() == 0){
+ isFrameBeingTested = false;
+ if(!canvasAlreadyClear)
+ loadGuidelines(tempBitmap, null);
+ return;
+ }
+
+ loadGuidelines(tempBitmap, pose);
+ isFrameBeingTested = false;
+ }else{
+ Log.e("debugg", "Error in test", task.getException());
+ loadGuidelines(tempBitmap, null);
+ isFrameBeingTested = false;
+ }
+ }
+ });
+ }
+
+ private void initTargetPoses() {
+ targetDumbbellStartSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST,150.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST,150.0),
+ new TargetShape(PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_HIP, 150.0 ),
+ new TargetShape(PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_HIP, 150.0 )
+ )
+ );
+
+ targetDumbbellEndSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST, 75.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST, 75.0),
+ new TargetShape(PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_HIP, 75.0 ),
+ new TargetShape(PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_HIP, 75.0 )
+ )
+ );
+
+ targetDumbbellLowSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST, 120.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST, 120.0),
+ new TargetShape(PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_HIP, 120.0 ),
+ new TargetShape(PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_HIP, 120.0 )
+ )
+ );
+ }
+
+ private boolean isPoseMatching(Pose pose, TargetPose targetPose) {
+ PoseMatcher matcher = new PoseMatcher(); // PoseMatcher 객체 생성. 이전에 제공된 코드에서 제공된 것처럼 생성해야 합니다.
+ return matcher.match(pose, targetPose);
+ }
+
+ private void handlePoseDetection(Pose pose) {
+ boolean isDumbbellStart = isPoseMatching(pose, targetDumbbellStartSign);
+ boolean isDumbbellEnd = isPoseMatching(pose, targetDumbbellEndSign);
+ boolean isDumbbellLow = isPoseMatching(pose, targetDumbbellLowSign);
+
+ if (isDumbbellEnd) {
+ dumbbellPosture.setText("올리세요");
+ if(!checkDumbbell){
+ speakDumbbellStart();
+ checkDumbbell = true;
+ }
+ checkDown = true;
+ } else if (isDumbbellStart) {
+ if (checkDown) {
+ dumbbellPosture.setText("잘했습니다");
+ speakDumbbellEnd();
+ checkDumbbell = false;
+ }
+ checkDown = false;
+ } else if (!checkDown && !isDumbbellLow) {
+ dumbbellPosture.setText("더 내리세요");
+ }
+ }
+
+ private void speakDumbbellEnd() {
+ String textToSpeak ="잘했어요 다시 해볼까요?";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ private void speakDumbbellStart() {
+ String textToSpeak ="좋아요";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void startAnalysis(){
+ Handler handler = new Handler(getMainLooper());
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(!isFrameBeingTested){
+ runTest();
+ }
+ handler.postDelayed(this, UPDATE_TIME);
+ }
+ });
+ }
+
+ private void startInit(){
+ ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(this);
+ cameraProviderFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ProcessCameraProvider provider = cameraProviderFuture.get();
+
+ Preview preview = new Preview.Builder().build();
+ preview.setSurfaceProvider(previewView.createSurfaceProvider());
+ imageCapture = new ImageCapture.Builder().build();
+
+ provider.unbindAll();
+ provider.bindToLifecycle(PostureDumbbell.this, CameraSelector.DEFAULT_FRONT_CAMERA, preview);
+
+ startAnalysis();
+ } catch (Exception e) {
+ Log.e("debugg", "Error Getting camera Provider", e);
+ }
+ }
+ }, ActivityCompat.getMainExecutor(PostureDumbbell.this));
+ }
+
+ private void checkPermissions(){
+ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 455);
+ }else{
+ startInit();
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == 455) {
+ if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ finish();
+ } else {
+ startInit();
+ }
+ }
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("나가기") || str.equals("종료")){
+ Intent intent = new Intent(PostureDumbbell.this, Posture.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 2000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/posture/PostureFly.java b/app/src/main/java/com/example/newbody/posture/PostureFly.java
new file mode 100644
index 0000000..b8f269d
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/posture/PostureFly.java
@@ -0,0 +1,431 @@
+package com.example.newbody.posture;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.speech.RecognizerIntent;
+import android.speech.tts.TextToSpeech;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.Preview;
+import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.camera.view.PreviewView;
+import androidx.core.app.ActivityCompat;
+
+import com.example.newbody.PoseMatcher;
+import com.example.newbody.Posture;
+import com.example.newbody.R;
+import com.example.newbody.TargetPose;
+import com.example.newbody.TargetShape;
+import com.example.newbody.VoiceRecognitionService;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.mlkit.vision.common.InputImage;
+import com.google.mlkit.vision.pose.Pose;
+import com.google.mlkit.vision.pose.PoseDetection;
+import com.google.mlkit.vision.pose.PoseDetector;
+import com.google.mlkit.vision.pose.PoseLandmark;
+import com.google.mlkit.vision.pose.accurate.AccuratePoseDetectorOptions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+public class PostureFly extends AppCompatActivity {
+
+ private boolean dumbbellStartDetected = false;
+ private boolean dumbbellEndDetected = false;
+ private boolean checkUp = false;
+ private boolean checkDown = false;
+ private boolean checkFly = false;
+ private TargetPose targetFlyStartSign;
+ private TargetPose targetFlyEndSign;
+ private TargetPose targetFlyLowSign;
+ private TextToSpeech tts;
+
+
+ PreviewView previewView;
+ PoseDetector detector;
+ ImageView guidelineView;
+ ImageCapture imageCapture;
+ TextView flyPosture;
+
+ Button exit;
+
+ Canvas guidelineCanvas;
+ Bitmap guidelineBmp, tempBitmap;
+ Paint guidePointPaint, guidePaint, transPaint;
+
+ private final int UPDATE_TIME = 40;
+ private boolean isFrameBeingTested = false, canvasAlreadyClear = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_posture_fly);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
+ @Override
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int langResult = tts.setLanguage(Locale.KOREAN);
+ if (langResult == TextToSpeech.LANG_MISSING_DATA |
+ langResult == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e("TTS", "Language is not supported or missing data");
+ }else {
+ // 피치와 속도를 조절합니다.
+ tts.setPitch(0.8f); // 높은 톤
+ tts.setSpeechRate(0.9f); // 약간 빠른 속도
+ tts.speak("덤벨 플라이을 시작합니다.", TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ } else {
+ Log.e("TTS", "Initialization failed");
+ }
+ }
+ });
+
+ initTargetPoses();
+ initViews();
+ exit.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Posture.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ checkPermissions();
+ }
+
+ private void loadGuidelines(Bitmap bmp, Pose pose){
+ new Handler(getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ guidelineBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
+ guidelineCanvas = new Canvas(guidelineBmp);
+
+ if(transPaint == null || guidePaint == null){
+ transPaint = new Paint();
+ transPaint.setColor(Color.TRANSPARENT);
+ transPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePointPaint = new Paint();
+ guidePointPaint.setColor(Color.RED);
+ guidePointPaint.setStrokeWidth(10f);
+ guidePointPaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePointPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePaint = new Paint();
+ guidePaint.setColor(Color.WHITE);
+ guidePaint.setStrokeWidth(3f);
+ guidePaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePaint.setStyle(Paint.Style.STROKE);
+ }
+
+ // setting everything as transparent
+ guidelineCanvas.drawColor(Color.TRANSPARENT);
+// guidelineCanvas.drawRect(0, 0, guidelineBmp.getWidth(), guidelineBmp.getHeight(), transPaint);
+
+ // drawing just a rect
+ if(pose != null){
+ for(PoseLandmark landmark : pose.getAllPoseLandmarks()){
+ guidelineCanvas.drawCircle(landmark.getPosition().x, landmark.getPosition().y, 6f, guidePointPaint);
+ }
+
+ // drawing lines
+ // TORSO
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, guidePaint);
+
+ //limbs
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().y, guidePaint);
+ //
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().y, guidePaint);
+
+ //MOUTH
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ canvasAlreadyClear = false;
+ }else{
+ canvasAlreadyClear = true;
+ }
+
+ guidelineView.invalidate();
+ guidelineView.setImageBitmap(guidelineBmp);
+ Log.d("debugg", "New Guidelines Drawn");
+ }
+ });
+
+ }
+
+ private void initViews(){
+ previewView = findViewById(R.id.viewFinder);
+ guidelineView = findViewById(R.id.canvas);
+ exit = findViewById(R.id.exitButton);
+ flyPosture = findViewById(R.id.postureFlyEx);
+ }
+
+ private void runTest(){
+ if(detector == null){
+ AccuratePoseDetectorOptions options = new AccuratePoseDetectorOptions.Builder().setDetectorMode(AccuratePoseDetectorOptions.STREAM_MODE).build();
+ detector = PoseDetection.getClient(options);
+ }
+
+ tempBitmap = previewView.getBitmap();
+ if(previewView.getBitmap() == null){
+ return;
+ }
+
+ isFrameBeingTested = true;
+ detector.process(InputImage.fromBitmap(tempBitmap, 0)).addOnCompleteListener(new OnCompleteListener() {
+
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if(task.isSuccessful()){
+ Pose pose = task.getResult();
+ handlePoseDetection(pose); // 포즈 감지 후 적절한 동작 처리
+ List landmarks = pose.getAllPoseLandmarks();
+ Log.d("debugg", "Landmarks found : " + landmarks.size());
+ if(landmarks.size() == 0){
+ isFrameBeingTested = false;
+ if(!canvasAlreadyClear)
+ loadGuidelines(tempBitmap, null);
+ return;
+ }
+
+ loadGuidelines(tempBitmap, pose);
+ isFrameBeingTested = false;
+ }else{
+ Log.e("debugg", "Error in test", task.getException());
+ loadGuidelines(tempBitmap, null);
+ isFrameBeingTested = false;
+ }
+ }
+ });
+ }
+
+ private void initTargetPoses() {
+ targetFlyStartSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST,120.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST,120.0),
+ new TargetShape(PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_SHOULDER, PoseLandmark.LEFT_SHOULDER,165.0),
+ new TargetShape(PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_SHOULDER, PoseLandmark.RIGHT_SHOULDER,165.0)
+ )
+ );
+
+ targetFlyEndSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_SHOULDER, PoseLandmark.LEFT_SHOULDER,80.0),
+ new TargetShape(PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_SHOULDER, PoseLandmark.RIGHT_SHOULDER,80.0),
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST,150.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST,150.0)
+ )
+ );
+
+ targetFlyLowSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_SHOULDER, PoseLandmark.LEFT_SHOULDER,175.0),
+ new TargetShape(PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_SHOULDER, PoseLandmark.RIGHT_SHOULDER,175.0)
+ )
+ );
+ }
+
+ private boolean isPoseMatching(Pose pose, TargetPose targetPose) {
+ PoseMatcher matcher = new PoseMatcher(); // PoseMatcher 객체 생성. 이전에 제공된 코드에서 제공된 것처럼 생성해야 합니다.
+ return matcher.match(pose, targetPose);
+ }
+
+ private void handlePoseDetection(Pose pose) {
+ boolean isFlyStart = isPoseMatching(pose, targetFlyStartSign);
+ boolean isFlyEnd = isPoseMatching(pose, targetFlyEndSign);
+ boolean isFlyLow = isPoseMatching(pose, targetFlyLowSign);
+
+ if (isFlyEnd) {
+ flyPosture.setText("올리세요");
+ if(!checkFly){
+ speakDumbbellStart();
+ checkFly = true;
+ }
+ checkDown = true;
+ } else if (isFlyStart) {
+ if (checkDown) {
+ flyPosture.setText("잘했습니다");
+ speakDumbbellEnd();
+ checkFly = false;
+ }
+ checkDown = false;
+ } else if (!checkDown && !isFlyLow) {
+ flyPosture.setText("더 내리세요");
+ }
+ }
+
+ private void speakDumbbellEnd() {
+ String textToSpeak ="잘했어요 다시 해볼까요?";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ private void speakDumbbellStart() {
+ String textToSpeak ="좋아요";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void startAnalysis(){
+ Handler handler = new Handler(getMainLooper());
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(!isFrameBeingTested){
+ runTest();
+ }
+ handler.postDelayed(this, UPDATE_TIME);
+ }
+ });
+ }
+
+ private void startInit(){
+ ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(this);
+ cameraProviderFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ProcessCameraProvider provider = cameraProviderFuture.get();
+
+ Preview preview = new Preview.Builder().build();
+ preview.setSurfaceProvider(previewView.createSurfaceProvider());
+ imageCapture = new ImageCapture.Builder().build();
+
+ provider.unbindAll();
+ provider.bindToLifecycle(PostureFly.this, CameraSelector.DEFAULT_FRONT_CAMERA, preview);
+
+ startAnalysis();
+ } catch (Exception e) {
+ Log.e("debugg", "Error Getting camera Provider", e);
+ }
+ }
+ }, ActivityCompat.getMainExecutor(PostureFly.this));
+ }
+
+ private void checkPermissions(){
+ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 455);
+ }else{
+ startInit();
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == 455) {
+ if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ finish();
+ } else {
+ startInit();
+ }
+ }
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("나가기") || str.equals("종료")){
+ Intent intent = new Intent(PostureFly.this, Posture.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 2000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/posture/PostureInfo.java b/app/src/main/java/com/example/newbody/posture/PostureInfo.java
new file mode 100644
index 0000000..8ba62c3
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/posture/PostureInfo.java
@@ -0,0 +1,242 @@
+package com.example.newbody.posture;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.VideoView;
+
+import com.example.newbody.Posture;
+import com.example.newbody.R;
+import com.example.newbody.Record;
+import com.example.newbody.VoiceRecognitionService;
+import com.example.newbody.YogaPosture;
+import com.example.newbody.record.RecordSquat;
+import com.example.newbody.record.RecordSquatMain;
+import com.example.newbody.yoga.Cat;
+import com.example.newbody.yoga.Cobra;
+import com.example.newbody.yoga.DownDog;
+
+import java.util.ArrayList;
+
+public class PostureInfo extends AppCompatActivity {
+
+ private Button start, prev;
+ private VideoView postureVideo;
+ private String exName;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_posture_info);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ prev = findViewById(R.id.prevButtonPostureInfo);
+ start = findViewById(R.id.startPosture);
+ postureVideo = findViewById(R.id.postureVideo);
+
+ Intent intent = getIntent();
+ exName = intent.getStringExtra("exercise");
+
+ Uri uri = null;
+ if (exName.equals("스쿼트")) {
+ uri = Uri.parse("android.resource://" + getPackageName() + "/raw/squat");
+ }else if(exName.equals("푸쉬업")){
+ uri = Uri.parse("android.resource://" + getPackageName() + "/raw/pushups");
+ }else if(exName.equals("덤벨 숄더 프레스")){
+ uri = Uri.parse("android.resource://" + getPackageName() + "/raw/dumbbell");
+ }else if(exName.equals("사이드 레터럴 레이즈")){
+ uri = Uri.parse("android.resource://" + getPackageName() + "/raw/side");
+ }else if(exName.equals("레그 레이즈")){
+ uri = Uri.parse("android.resource://" + getPackageName() + "/raw/legraise");
+ }else if(exName.equals("고양이 자세")){
+ uri = Uri.parse("android.resource://" + getPackageName() + "/raw/cat");
+ }else if(exName.equals("다운 독")){
+ uri = Uri.parse("android.resource://" + getPackageName() + "/raw/downdog");
+ }else if(exName.equals("코브라 자세")){
+ uri = Uri.parse("android.resource://" + getPackageName() + "/raw/cobra");
+ }else if(exName.equals("덤벨 컬")){
+ uri = Uri.parse("android.resource://" + getPackageName() + "/raw/dumbbellcurl");
+ }else if(exName.equals("덤벨 플라이")){
+ uri = Uri.parse("android.resource://" + getPackageName() + "/raw/dumbbellfly");
+ }else if(exName.equals("덤벨 트라이셉스 익스텐션")){
+ uri = Uri.parse("android.resource://" + getPackageName() + "/raw/dumbbelltriceps");
+ }
+ postureVideo.setVideoURI(uri);
+
+ postureVideo.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ mp.start();
+ }
+ });
+ postureVideo.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+ @Override
+ public void onCompletion(MediaPlayer mediaPlayer) {
+ // 동영상 재생이 완료되면 다시 시작
+ postureVideo.start();
+ }
+ });
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = null;
+ if(exName.equals("고양이 자세") || exName.equals("다운 독") || exName.equals("코브라 자세")){
+ intent = new Intent(getApplicationContext(), YogaPosture.class);
+ }else{
+ intent = new Intent(getApplicationContext(), Posture.class);
+ }
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ start.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intentN = null;
+ if (exName.equals("스쿼트")) {
+ intentN = new Intent(getApplicationContext(), PostureSquat.class);
+ }else if(exName.equals("푸쉬업")){
+ intentN = new Intent(getApplicationContext(), PosturePushup.class);
+ }else if(exName.equals("덤벨 숄더 프레스")){
+ intentN = new Intent(getApplicationContext(), PostureDumbbell.class);
+ }else if(exName.equals("사이드 레터럴 레이즈")){
+ intentN = new Intent(getApplicationContext(), PostureSide.class);
+ }else if(exName.equals("레그 레이즈")){
+ intentN = new Intent(getApplicationContext(), PostureLeg.class);
+ }else if(exName.equals("고양이 자세")){
+ intentN = new Intent(getApplicationContext(), Cat.class);
+ }else if(exName.equals("다운 독")){
+ intentN = new Intent(getApplicationContext(), DownDog.class);
+ }else if(exName.equals("코브라 자세")){
+ intentN = new Intent(getApplicationContext(), Cobra.class);
+ }else if(exName.equals("덤벨 컬")){
+ intentN = new Intent(getApplicationContext(), PostureCurl.class);
+ }else if(exName.equals("덤벨 플라이")){
+ intentN = new Intent(getApplicationContext(), PostureFly.class);
+ }else if(exName.equals("덤벨 트라이셉스 익스텐션")){
+ intentN = new Intent(getApplicationContext(), PostureTriceps.class);
+ }
+ startActivity(intentN);
+ finish();
+ }
+ });
+
+
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("시작") || str.equals("운동 시작")){
+ Intent intentN = null;
+ if (exName.equals("스쿼트")) {
+ intentN = new Intent(getApplicationContext(), PostureSquat.class);
+ }else if(exName.equals("푸쉬업")){
+ intentN = new Intent(getApplicationContext(), PosturePushup.class);
+ }else if(exName.equals("덤벨 숄더 프레스")){
+ intentN = new Intent(getApplicationContext(), PostureDumbbell.class);
+ }else if(exName.equals("사이드 레터럴 레이즈")){
+ intentN = new Intent(getApplicationContext(), PostureSide.class);
+ }else if(exName.equals("레그 레이즈")){
+ intentN = new Intent(getApplicationContext(), PostureLeg.class);
+ }else if(exName.equals("고양이 자세")){
+ intentN = new Intent(getApplicationContext(), Cat.class);
+ }else if(exName.equals("다운 독")){
+ intentN = new Intent(getApplicationContext(), DownDog.class);
+ }else if(exName.equals("코브라 자세")){
+ intentN = new Intent(getApplicationContext(), Cobra.class);
+ }else if(exName.equals("덤벨 컬")){
+ intentN = new Intent(getApplicationContext(), PostureCurl.class);
+ }else if(exName.equals("덤벨 플라이")){
+ intentN = new Intent(getApplicationContext(), PostureFly.class);
+ }else if(exName.equals("덤벨 트라이셉스 익스텐션")){
+ intentN = new Intent(getApplicationContext(), PostureTriceps.class);
+ }
+ startActivity(intentN);
+ finish();
+ }else if(str.equals("이전")){
+ Intent intent = null;
+ if(exName.equals("고양이 자세") || exName.equals("다운 독") || exName.equals("코브라 자세")){
+ intent = new Intent(getApplicationContext(), YogaPosture.class);
+ }else{
+ intent = new Intent(getApplicationContext(), Posture.class);
+ }
+ startActivity(intent);
+ finish();
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 2000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/posture/PostureLeg.java b/app/src/main/java/com/example/newbody/posture/PostureLeg.java
new file mode 100644
index 0000000..cad4531
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/posture/PostureLeg.java
@@ -0,0 +1,431 @@
+package com.example.newbody.posture;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.Preview;
+import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.camera.view.PreviewView;
+import androidx.core.app.ActivityCompat;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.speech.RecognizerIntent;
+import android.speech.tts.TextToSpeech;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.newbody.PoseMatcher;
+import com.example.newbody.Posture;
+import com.example.newbody.R;
+import com.example.newbody.TargetPose;
+import com.example.newbody.TargetShape;
+import com.example.newbody.VoiceRecognitionService;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.mlkit.vision.common.InputImage;
+import com.google.mlkit.vision.pose.Pose;
+import com.google.mlkit.vision.pose.PoseDetection;
+import com.google.mlkit.vision.pose.PoseDetector;
+import com.google.mlkit.vision.pose.PoseLandmark;
+import com.google.mlkit.vision.pose.accurate.AccuratePoseDetectorOptions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+public class PostureLeg extends AppCompatActivity {
+
+ private boolean dumbbellStartDetected = false;
+ private boolean dumbbellEndDetected = false;
+ private boolean check = false;
+ private boolean checkLeg = false;
+ private TargetPose targetLegRaiseStartSign;
+ private TargetPose targetLegRaiseEndSign;
+ private TargetPose targetLegRaiseOverSign;
+ private TextToSpeech tts;
+
+ PreviewView previewView;
+ PoseDetector detector;
+ ImageView guidelineView;
+ ImageCapture imageCapture;
+ TextView legPosture;
+
+ Button exit;
+
+ Canvas guidelineCanvas;
+ Bitmap guidelineBmp, tempBitmap;
+ Paint guidePointPaint, guidePaint, transPaint;
+
+ private final int UPDATE_TIME = 40;
+ private boolean isFrameBeingTested = false, canvasAlreadyClear = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_posture_leg);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
+ @Override
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int langResult = tts.setLanguage(Locale.KOREAN);
+ if (langResult == TextToSpeech.LANG_MISSING_DATA |
+ langResult == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e("TTS", "Language is not supported or missing data");
+ }else {
+ // 피치와 속도를 조절합니다.
+ tts.setPitch(0.8f); // 높은 톤
+ tts.setSpeechRate(0.9f); // 약간 빠른 속도
+ tts.speak("레그레이즈를 시작합니다.", TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ } else {
+ Log.e("TTS", "Initialization failed");
+ }
+ }
+ });
+
+ initTargetPoses();
+ initViews();
+ exit.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Posture.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ checkPermissions();
+ }
+
+ private void loadGuidelines(Bitmap bmp, Pose pose){
+ new Handler(getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ guidelineBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
+ guidelineCanvas = new Canvas(guidelineBmp);
+
+ if(transPaint == null || guidePaint == null){
+ transPaint = new Paint();
+ transPaint.setColor(Color.TRANSPARENT);
+ transPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePointPaint = new Paint();
+ guidePointPaint.setColor(Color.RED);
+ guidePointPaint.setStrokeWidth(10f);
+ guidePointPaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePointPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePaint = new Paint();
+ guidePaint.setColor(Color.WHITE);
+ guidePaint.setStrokeWidth(3f);
+ guidePaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePaint.setStyle(Paint.Style.STROKE);
+ }
+
+ // setting everything as transparent
+ guidelineCanvas.drawColor(Color.TRANSPARENT);
+// guidelineCanvas.drawRect(0, 0, guidelineBmp.getWidth(), guidelineBmp.getHeight(), transPaint);
+
+ // drawing just a rect
+ if(pose != null){
+ for(PoseLandmark landmark : pose.getAllPoseLandmarks()){
+ guidelineCanvas.drawCircle(landmark.getPosition().x, landmark.getPosition().y, 6f, guidePointPaint);
+ }
+
+ // drawing lines
+ // TORSO
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, guidePaint);
+
+ //limbs
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().y, guidePaint);
+ //
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().y, guidePaint);
+
+ //MOUTH
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ canvasAlreadyClear = false;
+ }else{
+ canvasAlreadyClear = true;
+ }
+
+ guidelineView.invalidate();
+ guidelineView.setImageBitmap(guidelineBmp);
+ Log.d("debugg", "New Guidelines Drawn");
+ }
+ });
+
+ }
+
+ private void initViews(){
+ legPosture = findViewById(R.id.postureLegEx);
+ previewView = findViewById(R.id.viewFinder);
+ guidelineView = findViewById(R.id.canvas);
+ exit = findViewById(R.id.exitButton);
+ }
+
+ private void runTest(){
+ if(detector == null){
+ AccuratePoseDetectorOptions options = new AccuratePoseDetectorOptions.Builder().setDetectorMode(AccuratePoseDetectorOptions.STREAM_MODE).build();
+ detector = PoseDetection.getClient(options);
+ }
+
+ tempBitmap = previewView.getBitmap();
+ if(previewView.getBitmap() == null){
+ return;
+ }
+
+ isFrameBeingTested = true;
+ detector.process(InputImage.fromBitmap(tempBitmap, 0)).addOnCompleteListener(new OnCompleteListener() {
+
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if(task.isSuccessful()){
+ Pose pose = task.getResult();
+ handlePoseDetection(pose); // 포즈 감지 후 적절한 동작 처리
+ List landmarks = pose.getAllPoseLandmarks();
+ Log.d("debugg", "Landmarks found : " + landmarks.size());
+ if(landmarks.size() == 0){
+ isFrameBeingTested = false;
+ if(!canvasAlreadyClear)
+ loadGuidelines(tempBitmap, null);
+ return;
+ }
+
+ loadGuidelines(tempBitmap, pose);
+ isFrameBeingTested = false;
+ }else{
+ Log.e("debugg", "Error in test", task.getException());
+ loadGuidelines(tempBitmap, null);
+ isFrameBeingTested = false;
+ }
+ }
+ });
+ }
+
+ private void initTargetPoses() {
+ targetLegRaiseStartSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_HIP, PoseLandmark.RIGHT_KNEE,100.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_HIP, PoseLandmark.LEFT_KNEE,100.0)
+
+ )
+ );
+
+ targetLegRaiseEndSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_HIP, PoseLandmark.RIGHT_KNEE, 170.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_HIP, PoseLandmark.LEFT_KNEE, 170.0)
+
+ )
+ );
+
+ targetLegRaiseOverSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_HIP, PoseLandmark.RIGHT_KNEE, 85.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_HIP, PoseLandmark.LEFT_KNEE, 85.0)
+
+ )
+ );
+ }
+
+ private boolean isPoseMatching(Pose pose, TargetPose targetPose) {
+ PoseMatcher matcher = new PoseMatcher(); // PoseMatcher 객체 생성. 이전에 제공된 코드에서 제공된 것처럼 생성해야 합니다.
+ return matcher.match(pose, targetPose);
+ }
+
+ private void handlePoseDetection(Pose pose) {
+ boolean isLegStart = isPoseMatching(pose, targetLegRaiseStartSign);
+ boolean isLegEnd = isPoseMatching(pose, targetLegRaiseEndSign);
+ boolean isLegOver = isPoseMatching(pose, targetLegRaiseOverSign);
+
+ if (isLegEnd) {
+ if (check) {
+ legPosture.setText("잘했어요");
+ speakLegEnd();
+ checkLeg = false;
+ }
+ check = false;
+ } else if (isLegOver) {
+ legPosture.setText("다리를 더이상 올리지 마세요");
+ } else if (!check && !isLegStart) {
+ legPosture.setText("다리을 더 올리세요");
+ } else if (isLegStart) {
+ legPosture.setText("다리를 내리세요");
+ if(!checkLeg){
+ speakLegStart();
+ checkLeg = true;
+ }
+ check = true;
+ }
+ }
+
+ private void speakLegEnd() {
+ String textToSpeak ="잘했어요 다시 해볼까요?";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ private void speakLegStart() {
+ String textToSpeak ="좋아요";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void startAnalysis(){
+ Handler handler = new Handler(getMainLooper());
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(!isFrameBeingTested){
+ runTest();
+ }
+ handler.postDelayed(this, UPDATE_TIME);
+ }
+ });
+ }
+
+ private void startInit(){
+ ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(this);
+ cameraProviderFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ProcessCameraProvider provider = cameraProviderFuture.get();
+
+ Preview preview = new Preview.Builder().build();
+ preview.setSurfaceProvider(previewView.createSurfaceProvider());
+ imageCapture = new ImageCapture.Builder().build();
+
+ provider.unbindAll();
+ provider.bindToLifecycle(PostureLeg.this, CameraSelector.DEFAULT_FRONT_CAMERA, preview);
+
+ startAnalysis();
+ } catch (Exception e) {
+ Log.e("debugg", "Error Getting camera Provider", e);
+ }
+ }
+ }, ActivityCompat.getMainExecutor(PostureLeg.this));
+ }
+
+ private void checkPermissions(){
+ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 455);
+ }else{
+ startInit();
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == 455) {
+ if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ finish();
+ } else {
+ startInit();
+ }
+ }
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("나가기") || str.equals("종료")){
+ Intent intent = new Intent(PostureLeg.this, Posture.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 2000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/posture/PosturePushup.java b/app/src/main/java/com/example/newbody/posture/PosturePushup.java
new file mode 100644
index 0000000..0a791d4
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/posture/PosturePushup.java
@@ -0,0 +1,428 @@
+package com.example.newbody.posture;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.Preview;
+import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.camera.view.PreviewView;
+import androidx.core.app.ActivityCompat;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.speech.RecognizerIntent;
+import android.speech.tts.TextToSpeech;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.newbody.PoseMatcher;
+import com.example.newbody.Posture;
+import com.example.newbody.R;
+import com.example.newbody.TargetPose;
+import com.example.newbody.TargetShape;
+import com.example.newbody.VoiceRecognitionService;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.mlkit.vision.common.InputImage;
+import com.google.mlkit.vision.pose.Pose;
+import com.google.mlkit.vision.pose.PoseDetection;
+import com.google.mlkit.vision.pose.PoseDetector;
+import com.google.mlkit.vision.pose.PoseLandmark;
+import com.google.mlkit.vision.pose.accurate.AccuratePoseDetectorOptions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+public class PosturePushup extends AppCompatActivity {
+
+ private boolean check = false;
+ private boolean checkPushup = false;
+ private TargetPose targetPushupStartSign;
+ private TargetPose targetPushupEndSign;
+ private TargetPose targetPushupHipOverSign;
+ private TargetPose targetPushupUpSign;
+ private TextToSpeech tts;
+
+
+ PreviewView previewView;
+ PoseDetector detector;
+ ImageView guidelineView;
+ ImageCapture imageCapture;
+ TextView pushupPosture;
+
+ Button exit;
+
+ Canvas guidelineCanvas;
+ Bitmap guidelineBmp, tempBitmap;
+ Paint guidePointPaint, guidePaint, transPaint;
+
+ private final int UPDATE_TIME = 40;
+ private boolean isFrameBeingTested = false, canvasAlreadyClear = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_posture_pushup);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
+ @Override
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int langResult = tts.setLanguage(Locale.KOREAN);
+ if (langResult == TextToSpeech.LANG_MISSING_DATA |
+ langResult == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e("TTS", "Language is not supported or missing data");
+ }else {
+ // 피치와 속도를 조절합니다.
+ tts.setPitch(0.8f); // 높은 톤
+ tts.setSpeechRate(0.9f); // 약간 빠른 속도
+ tts.speak("푸쉬업을 시작합니다.", TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ } else {
+ Log.e("TTS", "Initialization failed");
+ }
+ }
+ });
+
+ initTargetPoses();
+ initViews();
+ exit.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Posture.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ checkPermissions();
+ }
+
+ private void loadGuidelines(Bitmap bmp, Pose pose){
+ new Handler(getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ guidelineBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
+ guidelineCanvas = new Canvas(guidelineBmp);
+
+ if(transPaint == null || guidePaint == null){
+ transPaint = new Paint();
+ transPaint.setColor(Color.TRANSPARENT);
+ transPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePointPaint = new Paint();
+ guidePointPaint.setColor(Color.RED);
+ guidePointPaint.setStrokeWidth(10f);
+ guidePointPaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePointPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePaint = new Paint();
+ guidePaint.setColor(Color.WHITE);
+ guidePaint.setStrokeWidth(3f);
+ guidePaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePaint.setStyle(Paint.Style.STROKE);
+ }
+
+ // setting everything as transparent
+ guidelineCanvas.drawColor(Color.TRANSPARENT);
+// guidelineCanvas.drawRect(0, 0, guidelineBmp.getWidth(), guidelineBmp.getHeight(), transPaint);
+
+ // drawing just a rect
+ if(pose != null){
+ for(PoseLandmark landmark : pose.getAllPoseLandmarks()){
+ guidelineCanvas.drawCircle(landmark.getPosition().x, landmark.getPosition().y, 6f, guidePointPaint);
+ }
+
+ // drawing lines
+ // TORSO
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, guidePaint);
+
+ //limbs
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().y, guidePaint);
+ //
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().y, guidePaint);
+
+ //MOUTH
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ canvasAlreadyClear = false;
+ }else{
+ canvasAlreadyClear = true;
+ }
+
+ guidelineView.invalidate();
+ guidelineView.setImageBitmap(guidelineBmp);
+ Log.d("debugg", "New Guidelines Drawn");
+ }
+ });
+
+ }
+
+ private void initViews(){
+ previewView = findViewById(R.id.viewFinder);
+ guidelineView = findViewById(R.id.canvas);
+ exit = findViewById(R.id.exitButton);
+ pushupPosture = findViewById(R.id.posturePushupEx);
+ }
+
+ private void runTest(){
+ if(detector == null){
+ AccuratePoseDetectorOptions options = new AccuratePoseDetectorOptions.Builder().setDetectorMode(AccuratePoseDetectorOptions.STREAM_MODE).build();
+ detector = PoseDetection.getClient(options);
+ }
+
+ tempBitmap = previewView.getBitmap();
+ if(previewView.getBitmap() == null){
+ return;
+ }
+
+ isFrameBeingTested = true;
+ detector.process(InputImage.fromBitmap(tempBitmap, 0)).addOnCompleteListener(new OnCompleteListener() {
+
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if(task.isSuccessful()){
+ Pose pose = task.getResult();
+ handlePoseDetection(pose); // 포즈 감지 후 적절한 동작 처리
+ List landmarks = pose.getAllPoseLandmarks();
+ Log.d("debugg", "Landmarks found : " + landmarks.size());
+ if(landmarks.size() == 0){
+ isFrameBeingTested = false;
+ if(!canvasAlreadyClear)
+ loadGuidelines(tempBitmap, null);
+ return;
+ }
+
+ loadGuidelines(tempBitmap, pose);
+ isFrameBeingTested = false;
+ }else{
+ Log.e("debugg", "Error in test", task.getException());
+ loadGuidelines(tempBitmap, null);
+ isFrameBeingTested = false;
+ }
+ }
+ });
+ }
+
+ private void initTargetPoses() {
+ targetPushupStartSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST, 80.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST, 80.0)
+ )
+ );
+
+ targetPushupEndSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST,160.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST,160.0)
+ )
+ );
+
+ targetPushupHipOverSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_HIP, PoseLandmark.RIGHT_KNEE, 100.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_HIP, PoseLandmark.LEFT_KNEE, 100.0)
+ )
+ );
+ }
+
+ private boolean isPoseMatching(Pose pose, TargetPose targetPose) {
+ PoseMatcher matcher = new PoseMatcher(); // PoseMatcher 객체 생성. 이전에 제공된 코드에서 제공된 것처럼 생성해야 합니다.
+ return matcher.match(pose, targetPose);
+ }
+
+ private void handlePoseDetection(Pose pose) {
+ boolean isPushupStart = isPoseMatching(pose, targetPushupStartSign);
+ boolean isPushupEnd = isPoseMatching(pose, targetPushupEndSign);
+ boolean isPushupHipOver = isPoseMatching(pose, targetPushupHipOverSign);
+
+ if (isPushupEnd) {
+ if (check) {
+ pushupPosture.setText("잘했어요");
+ speakPushupEnd();
+ checkPushup = false;
+ }
+ check = false;
+ } else if (isPushupStart) {
+ check = true;
+ pushupPosture.setText("올라가세요");
+ if(!checkPushup){
+ speakPushupStart();
+ checkPushup = true;
+ }
+ } else if (isPushupHipOver) {
+ pushupPosture.setText("허리를 내리세요");
+ } else if (!check && !isPushupStart) {
+ pushupPosture.setText("더 내려가세요");
+ }
+ }
+
+ private void speakPushupEnd() {
+ String textToSpeak ="잘했어요 다시 해볼까요?";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ private void speakPushupStart() {
+ String textToSpeak ="좋아요";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void startAnalysis(){
+ Handler handler = new Handler(getMainLooper());
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(!isFrameBeingTested){
+ runTest();
+ }
+ handler.postDelayed(this, UPDATE_TIME);
+ }
+ });
+ }
+
+ private void startInit(){
+ ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(this);
+ cameraProviderFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ProcessCameraProvider provider = cameraProviderFuture.get();
+
+ Preview preview = new Preview.Builder().build();
+ preview.setSurfaceProvider(previewView.createSurfaceProvider());
+ imageCapture = new ImageCapture.Builder().build();
+
+ provider.unbindAll();
+ provider.bindToLifecycle(PosturePushup.this, CameraSelector.DEFAULT_FRONT_CAMERA, preview);
+
+ startAnalysis();
+ } catch (Exception e) {
+ Log.e("debugg", "Error Getting camera Provider", e);
+ }
+ }
+ }, ActivityCompat.getMainExecutor(PosturePushup.this));
+ }
+
+ private void checkPermissions(){
+ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 455);
+ }else{
+ startInit();
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == 455) {
+ if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ finish();
+ } else {
+ startInit();
+ }
+ }
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("나가기") || str.equals("종료")){
+ Intent intent = new Intent(PosturePushup.this, Posture.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 2000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/posture/PostureSide.java b/app/src/main/java/com/example/newbody/posture/PostureSide.java
new file mode 100644
index 0000000..58a424f
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/posture/PostureSide.java
@@ -0,0 +1,428 @@
+package com.example.newbody.posture;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.Preview;
+import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.camera.view.PreviewView;
+import androidx.core.app.ActivityCompat;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.speech.RecognizerIntent;
+import android.speech.tts.TextToSpeech;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.newbody.PoseMatcher;
+import com.example.newbody.Posture;
+import com.example.newbody.R;
+import com.example.newbody.TargetPose;
+import com.example.newbody.TargetShape;
+import com.example.newbody.VoiceRecognitionService;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.mlkit.vision.common.InputImage;
+import com.google.mlkit.vision.pose.Pose;
+import com.google.mlkit.vision.pose.PoseDetection;
+import com.google.mlkit.vision.pose.PoseDetector;
+import com.google.mlkit.vision.pose.PoseLandmark;
+import com.google.mlkit.vision.pose.accurate.AccuratePoseDetectorOptions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+public class PostureSide extends AppCompatActivity {
+
+ private boolean dumbbellStartDetected = false;
+ private boolean dumbbellEndDetected = false;
+
+ private boolean check = false;
+ private boolean checkSide = false;
+ private TargetPose targetSideStartSign;
+ private TargetPose targetSideEndSign;
+ private TargetPose targetSideArmOverSign;
+ private TextToSpeech tts;
+
+ PreviewView previewView;
+ PoseDetector detector;
+ ImageView guidelineView;
+ ImageCapture imageCapture;
+ TextView sidePosture;
+
+ Button exit;
+
+ Canvas guidelineCanvas;
+ Bitmap guidelineBmp, tempBitmap;
+ Paint guidePointPaint, guidePaint, transPaint;
+
+ private final int UPDATE_TIME = 40;
+ private boolean isFrameBeingTested = false, canvasAlreadyClear = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_posture_side);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
+ @Override
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int langResult = tts.setLanguage(Locale.KOREAN);
+ if (langResult == TextToSpeech.LANG_MISSING_DATA |
+ langResult == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e("TTS", "Language is not supported or missing data");
+ }else {
+ // 피치와 속도를 조절합니다.
+ tts.setPitch(0.8f); // 높은 톤
+ tts.setSpeechRate(0.9f); // 약간 빠른 속도
+ tts.speak("사이드 래터럴 레이즈를 시작합니다.", TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ } else {
+ Log.e("TTS", "Initialization failed");
+ }
+ }
+ });
+
+ initTargetPoses();
+ initViews();
+ exit.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Posture.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ checkPermissions();
+ }
+
+ private void loadGuidelines(Bitmap bmp, Pose pose){
+ new Handler(getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ guidelineBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
+ guidelineCanvas = new Canvas(guidelineBmp);
+
+ if(transPaint == null || guidePaint == null){
+ transPaint = new Paint();
+ transPaint.setColor(Color.TRANSPARENT);
+ transPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePointPaint = new Paint();
+ guidePointPaint.setColor(Color.RED);
+ guidePointPaint.setStrokeWidth(10f);
+ guidePointPaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePointPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePaint = new Paint();
+ guidePaint.setColor(Color.WHITE);
+ guidePaint.setStrokeWidth(3f);
+ guidePaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePaint.setStyle(Paint.Style.STROKE);
+ }
+
+ // setting everything as transparent
+ guidelineCanvas.drawColor(Color.TRANSPARENT);
+// guidelineCanvas.drawRect(0, 0, guidelineBmp.getWidth(), guidelineBmp.getHeight(), transPaint);
+
+ // drawing just a rect
+ if(pose != null){
+ for(PoseLandmark landmark : pose.getAllPoseLandmarks()){
+ guidelineCanvas.drawCircle(landmark.getPosition().x, landmark.getPosition().y, 6f, guidePointPaint);
+ }
+
+ // drawing lines
+ // TORSO
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, guidePaint);
+
+ //limbs
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().y, guidePaint);
+ //
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().y, guidePaint);
+
+ //MOUTH
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ canvasAlreadyClear = false;
+ }else{
+ canvasAlreadyClear = true;
+ }
+
+ guidelineView.invalidate();
+ guidelineView.setImageBitmap(guidelineBmp);
+ Log.d("debugg", "New Guidelines Drawn");
+ }
+ });
+
+ }
+
+ private void initViews(){
+ previewView = findViewById(R.id.viewFinder);
+ guidelineView = findViewById(R.id.canvas);
+ exit = findViewById(R.id.exitButton);
+ sidePosture = findViewById(R.id.postureSideEx);
+ }
+
+ private void runTest(){
+ if(detector == null){
+ AccuratePoseDetectorOptions options = new AccuratePoseDetectorOptions.Builder().setDetectorMode(AccuratePoseDetectorOptions.STREAM_MODE).build();
+ detector = PoseDetection.getClient(options);
+ }
+
+ tempBitmap = previewView.getBitmap();
+ if(previewView.getBitmap() == null){
+ return;
+ }
+
+ isFrameBeingTested = true;
+ detector.process(InputImage.fromBitmap(tempBitmap, 0)).addOnCompleteListener(new OnCompleteListener() {
+
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if(task.isSuccessful()){
+ Pose pose = task.getResult();
+ handlePoseDetection(pose); // 포즈 감지 후 적절한 동작 처리
+ List landmarks = pose.getAllPoseLandmarks();
+ Log.d("debugg", "Landmarks found : " + landmarks.size());
+ if(landmarks.size() == 0){
+ isFrameBeingTested = false;
+ if(!canvasAlreadyClear)
+ loadGuidelines(tempBitmap, null);
+ return;
+ }
+
+ loadGuidelines(tempBitmap, pose);
+ isFrameBeingTested = false;
+ }else{
+ Log.e("debugg", "Error in test", task.getException());
+ loadGuidelines(tempBitmap, null);
+ isFrameBeingTested = false;
+ }
+ }
+ });
+ }
+
+ private void initTargetPoses() {
+ targetSideStartSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_HIP, PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW,90.0),
+ new TargetShape(PoseLandmark.LEFT_HIP, PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW,90.0)
+ )
+ );
+
+ targetSideEndSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_HIP, PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW,20.0),
+ new TargetShape(PoseLandmark.LEFT_HIP, PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW,20.0)
+ )
+ );
+ targetSideArmOverSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_HIP, PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW,100.0),
+ new TargetShape(PoseLandmark.LEFT_HIP, PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW,100.0)
+ )
+ );
+ }
+
+ private boolean isPoseMatching(Pose pose, TargetPose targetPose) {
+ PoseMatcher matcher = new PoseMatcher(); // PoseMatcher 객체 생성. 이전에 제공된 코드에서 제공된 것처럼 생성해야 합니다.
+ return matcher.match(pose, targetPose);
+ }
+
+ private void handlePoseDetection(Pose pose) {
+ boolean isSideStart = isPoseMatching(pose, targetSideStartSign);
+ boolean isSideEnd = isPoseMatching(pose, targetSideEndSign);
+ boolean isSideOver = isPoseMatching(pose, targetSideArmOverSign);
+
+
+ if (isSideStart) {
+ sidePosture.setText("팔을 내리세요");
+ if(!checkSide){
+ speakSideStart();
+ checkSide = true;
+ }
+ check = true;
+ } else if (isSideOver) {
+ sidePosture.setText("팔을 너무 올리셨습니다");
+ } else if (!check && !isSideStart) {
+ sidePosture.setText("더 올리세요");
+ } else if (isSideEnd) {
+ if (check) {
+ sidePosture.setText("잘했어요");
+ speakSideEnd();
+ checkSide = false;
+ }
+ }
+ }
+
+ private void speakSideEnd() {
+ String textToSpeak ="잘했어요 다시 해볼까요?";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ private void speakSideStart() {
+ String textToSpeak ="좋아요";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void startAnalysis(){
+ Handler handler = new Handler(getMainLooper());
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(!isFrameBeingTested){
+ runTest();
+ }
+ handler.postDelayed(this, UPDATE_TIME);
+ }
+ });
+ }
+
+ private void startInit(){
+ ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(this);
+ cameraProviderFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ProcessCameraProvider provider = cameraProviderFuture.get();
+
+ Preview preview = new Preview.Builder().build();
+ preview.setSurfaceProvider(previewView.createSurfaceProvider());
+ imageCapture = new ImageCapture.Builder().build();
+
+ provider.unbindAll();
+ provider.bindToLifecycle(PostureSide.this, CameraSelector.DEFAULT_FRONT_CAMERA, preview);
+
+ startAnalysis();
+ } catch (Exception e) {
+ Log.e("debugg", "Error Getting camera Provider", e);
+ }
+ }
+ }, ActivityCompat.getMainExecutor(PostureSide.this));
+ }
+
+ private void checkPermissions(){
+ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 455);
+ }else{
+ startInit();
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == 455) {
+ if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ finish();
+ } else {
+ startInit();
+ }
+ }
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("나가기") || str.equals("종료")){
+ Intent intent = new Intent(PostureSide.this, Posture.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 2000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/posture/PostureSquat.java b/app/src/main/java/com/example/newbody/posture/PostureSquat.java
new file mode 100644
index 0000000..bbaa4f2
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/posture/PostureSquat.java
@@ -0,0 +1,442 @@
+package com.example.newbody.posture;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.Preview;
+import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.camera.view.PreviewView;
+import androidx.core.app.ActivityCompat;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.speech.RecognizerIntent;
+import android.speech.tts.TextToSpeech;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.newbody.PoseMatcher;
+import com.example.newbody.Posture;
+import com.example.newbody.R;
+import com.example.newbody.Record;
+import com.example.newbody.TargetPose;
+import com.example.newbody.TargetShape;
+import com.example.newbody.VoiceRecognitionService;
+import com.example.newbody.record.RecordSquatMain;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.mlkit.vision.common.InputImage;
+import com.google.mlkit.vision.pose.Pose;
+import com.google.mlkit.vision.pose.PoseDetection;
+import com.google.mlkit.vision.pose.PoseDetector;
+import com.google.mlkit.vision.pose.PoseLandmark;
+import com.google.mlkit.vision.pose.accurate.AccuratePoseDetectorOptions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+public class PostureSquat extends AppCompatActivity {
+
+ private boolean goodMotionDetected = false;
+ private TargetPose targetSquatStartSign;
+ private TargetPose targetSquatEndSign;
+ private TargetPose targetSquatOverSign;
+ private boolean check = false;
+ private boolean checkSquat = false;
+ private TextToSpeech tts;
+
+ PreviewView previewView;
+ PoseDetector detector;
+ ImageView guidelineView;
+ ImageCapture imageCapture;
+ TextView squatPosture;
+
+ Button exit;
+
+ Canvas guidelineCanvas;
+ Bitmap guidelineBmp, tempBitmap;
+ Paint guidePointPaint, guidePaint, transPaint;
+
+ private final int UPDATE_TIME = 40;
+ private boolean isFrameBeingTested = false, canvasAlreadyClear = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_posture_squat);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
+ @Override
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int langResult = tts.setLanguage(Locale.KOREAN);
+ if (langResult == TextToSpeech.LANG_MISSING_DATA |
+ langResult == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e("TTS", "Language is not supported or missing data");
+ }else {
+ // 피치와 속도를 조절합니다.
+ tts.setPitch(0.8f); // 높은 톤
+ tts.setSpeechRate(0.9f); // 약간 빠른 속도
+ tts.speak("스쿼트를 시작합니다.", TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ } else {
+ Log.e("TTS", "Initialization failed");
+ }
+ }
+ });
+
+ initTargetPoses();
+ initViews();
+ exit.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Posture.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ checkPermissions();
+ }
+
+ private void loadGuidelines(Bitmap bmp, Pose pose){
+ new Handler(getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ guidelineBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
+ guidelineCanvas = new Canvas(guidelineBmp);
+
+ if(transPaint == null || guidePaint == null){
+ transPaint = new Paint();
+ transPaint.setColor(Color.TRANSPARENT);
+ transPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePointPaint = new Paint();
+ guidePointPaint.setColor(Color.RED);
+ guidePointPaint.setStrokeWidth(10f);
+ guidePointPaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePointPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePaint = new Paint();
+ guidePaint.setColor(Color.WHITE);
+ guidePaint.setStrokeWidth(3f);
+ guidePaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePaint.setStyle(Paint.Style.STROKE);
+ }
+
+ // setting everything as transparent
+ guidelineCanvas.drawColor(Color.TRANSPARENT);
+
+ // drawing just a rect
+ if(pose != null){
+ for(PoseLandmark landmark : pose.getAllPoseLandmarks()){
+ guidelineCanvas.drawCircle(landmark.getPosition().x, landmark.getPosition().y, 6f, guidePointPaint);
+ }
+
+ // drawing lines
+ // TORSO
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, guidePaint);
+
+ //limbs
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().y, guidePaint);
+ //
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().y, guidePaint);
+
+ //MOUTH
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ canvasAlreadyClear = false;
+ }else{
+ canvasAlreadyClear = true;
+ }
+
+ guidelineView.invalidate();
+ guidelineView.setImageBitmap(guidelineBmp);
+ Log.d("debugg", "New Guidelines Drawn");
+ }
+ });
+
+ }
+
+ private void initViews(){
+ squatPosture = findViewById(R.id.postureSquatEx);
+ previewView = findViewById(R.id.viewFinder);
+ guidelineView = findViewById(R.id.canvas);
+ exit = findViewById(R.id.exitButton);
+ }
+
+ private void runTest(){
+ if(detector == null){
+ AccuratePoseDetectorOptions options = new AccuratePoseDetectorOptions.Builder().setDetectorMode(AccuratePoseDetectorOptions.STREAM_MODE).build();
+ detector = PoseDetection.getClient(options);
+ }
+
+ tempBitmap = previewView.getBitmap();
+ if(previewView.getBitmap() == null){
+ return;
+ }
+
+ isFrameBeingTested = true;
+ detector.process(InputImage.fromBitmap(tempBitmap, 0)).addOnCompleteListener(new OnCompleteListener() {
+
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if(task.isSuccessful()){
+ Pose pose = task.getResult();
+ try {
+ handlePoseDetection(pose); // 포즈 감지 후 적절한 동작 처리
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ List landmarks = pose.getAllPoseLandmarks();
+ Log.d("debugg", "Landmarks found : " + landmarks.size());
+ if(landmarks.size() == 0){
+ isFrameBeingTested = false;
+ if(!canvasAlreadyClear)
+ loadGuidelines(tempBitmap, null);
+ return;
+ }
+
+ loadGuidelines(tempBitmap, pose);
+ isFrameBeingTested = false;
+ }else{
+ Log.e("debugg", "Error in test", task.getException());
+ loadGuidelines(tempBitmap, null);
+ isFrameBeingTested = false;
+ }
+ }
+ });
+ }
+
+ private void initTargetPoses() {
+ targetSquatStartSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_HIP, PoseLandmark.RIGHT_KNEE, 60.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_HIP, PoseLandmark.LEFT_KNEE, 60.0),
+ new TargetShape(PoseLandmark.LEFT_HIP, PoseLandmark.LEFT_KNEE, PoseLandmark.LEFT_ANKLE, 70.0),
+ new TargetShape(PoseLandmark.RIGHT_HIP, PoseLandmark.RIGHT_KNEE, PoseLandmark.RIGHT_ANKLE, 70.0)
+ )
+ );
+
+ targetSquatEndSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_HIP, PoseLandmark.LEFT_ANKLE, 180.0),
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_HIP, PoseLandmark.RIGHT_ANKLE, 180.0)
+ )
+ );
+
+ targetSquatOverSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.LEFT_HIP, PoseLandmark.LEFT_KNEE, PoseLandmark.LEFT_ANKLE, 50.0),
+ new TargetShape(PoseLandmark.RIGHT_HIP, PoseLandmark.RIGHT_KNEE, PoseLandmark.RIGHT_ANKLE, 50.0)
+ )
+ );
+ }
+
+ private boolean isPoseMatching(Pose pose, TargetPose targetPose) {
+ PoseMatcher matcher = new PoseMatcher(); // PoseMatcher 객체 생성. 이전에 제공된 코드에서 제공된 것처럼 생성해야 합니다.
+ return matcher.match(pose, targetPose);
+ }
+
+ private void handlePoseDetection(Pose pose) throws InterruptedException {
+ Handler h = new Handler();
+
+ boolean isSquatStart = isPoseMatching(pose, targetSquatStartSign);
+ boolean isSquatEnd = isPoseMatching(pose, targetSquatEndSign);
+ boolean isSquatOver = isPoseMatching(pose, targetSquatOverSign);
+
+ if (isSquatEnd) {
+ if (check) {
+ squatPosture.setText("잘했어요 다시 해볼까요?");
+ speakSquatEnd();
+ checkSquat = false;
+ }
+ check = false;
+ } else if (isSquatStart) {
+ check = true;
+ squatPosture.setText("Good Motion ! 이제 올라가세요");
+ if(!checkSquat){
+ speakSquatStart();
+ checkSquat = true;
+ }
+ } else if (!check && !isSquatOver) {
+ squatPosture.setText("더 앉으세요");
+ } else if (isSquatOver) {
+ squatPosture.setText("너무 앉으셨습니다. 다시 하세요.");
+ }
+ }
+ private void speakSquatEnd() {
+ String textToSpeak ="잘했어요 다시 해볼까요?";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ private void speakSquatStart() {
+ String textToSpeak ="좋아요";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void startAnalysis(){
+ Handler handler = new Handler(getMainLooper());
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(!isFrameBeingTested){
+ runTest();
+ }
+ handler.postDelayed(this, UPDATE_TIME);
+ }
+ });
+ }
+
+ private void startInit(){
+ ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(this);
+ cameraProviderFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ProcessCameraProvider provider = cameraProviderFuture.get();
+
+ Preview preview = new Preview.Builder().build();
+ preview.setSurfaceProvider(previewView.createSurfaceProvider());
+ imageCapture = new ImageCapture.Builder().build();
+
+ provider.unbindAll();
+ provider.bindToLifecycle(PostureSquat.this, CameraSelector.DEFAULT_FRONT_CAMERA, preview);
+
+ startAnalysis();
+ } catch (Exception e) {
+ Log.e("debugg", "Error Getting camera Provider", e);
+ }
+ }
+ }, ActivityCompat.getMainExecutor(PostureSquat.this));
+ }
+
+ private void checkPermissions(){
+ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 455);
+ }else{
+ startInit();
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == 455) {
+ if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ finish();
+ } else {
+ startInit();
+ }
+ }
+ }
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("나가기") || str.equals("종료")){
+ Intent intent = new Intent(PostureSquat.this, Posture.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 2000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+ @Override
+ protected void onDestroy() {
+ if (tts != null) {
+ tts.stop();
+ tts.shutdown();
+ }
+ super.onDestroy();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/posture/PostureTriceps.java b/app/src/main/java/com/example/newbody/posture/PostureTriceps.java
new file mode 100644
index 0000000..da9090e
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/posture/PostureTriceps.java
@@ -0,0 +1,446 @@
+package com.example.newbody.posture;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.speech.RecognizerIntent;
+import android.speech.tts.TextToSpeech;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.Preview;
+import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.camera.view.PreviewView;
+import androidx.core.app.ActivityCompat;
+
+import com.example.newbody.PoseMatcher;
+import com.example.newbody.Posture;
+import com.example.newbody.R;
+import com.example.newbody.TargetPose;
+import com.example.newbody.TargetShape;
+import com.example.newbody.VoiceRecognitionService;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.Task;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.mlkit.vision.common.InputImage;
+import com.google.mlkit.vision.pose.Pose;
+import com.google.mlkit.vision.pose.PoseDetection;
+import com.google.mlkit.vision.pose.PoseDetector;
+import com.google.mlkit.vision.pose.PoseLandmark;
+import com.google.mlkit.vision.pose.accurate.AccuratePoseDetectorOptions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+public class PostureTriceps extends AppCompatActivity {
+
+ private boolean goodMotionDetected = false;
+ private TargetPose targetTricepsStartSign;
+ private TargetPose targetTricepsEndSign;
+ private TargetPose targetTricepsLowSign;
+ private TargetPose targetNotTricepsSign;
+ private boolean check = false;
+ private boolean checkTriceps = false;
+ private TextToSpeech tts;
+
+ PreviewView previewView;
+ PoseDetector detector;
+ ImageView guidelineView;
+ ImageCapture imageCapture;
+ TextView tricepsPosture;
+
+ Button exit;
+
+ Canvas guidelineCanvas;
+ Bitmap guidelineBmp, tempBitmap;
+ Paint guidePointPaint, guidePaint, transPaint;
+
+ private final int UPDATE_TIME = 40;
+ private boolean isFrameBeingTested = false, canvasAlreadyClear = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_posture_triceps);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
+ @Override
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int langResult = tts.setLanguage(Locale.KOREAN);
+ if (langResult == TextToSpeech.LANG_MISSING_DATA |
+ langResult == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e("TTS", "Language is not supported or missing data");
+ }else {
+ // 피치와 속도를 조절합니다.
+ tts.setPitch(0.8f); // 높은 톤
+ tts.setSpeechRate(0.9f); // 약간 빠른 속도
+ tts.speak("덤벨 트라이셉스 익스텐션을 시작합니다.", TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ } else {
+ Log.e("TTS", "Initialization failed");
+ }
+ }
+ });
+
+ initTargetPoses();
+ initViews();
+ exit.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Posture.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ checkPermissions();
+ }
+
+ private void loadGuidelines(Bitmap bmp, Pose pose){
+ new Handler(getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ guidelineBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
+ guidelineCanvas = new Canvas(guidelineBmp);
+
+ if(transPaint == null || guidePaint == null){
+ transPaint = new Paint();
+ transPaint.setColor(Color.TRANSPARENT);
+ transPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePointPaint = new Paint();
+ guidePointPaint.setColor(Color.RED);
+ guidePointPaint.setStrokeWidth(10f);
+ guidePointPaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePointPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePaint = new Paint();
+ guidePaint.setColor(Color.WHITE);
+ guidePaint.setStrokeWidth(3f);
+ guidePaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePaint.setStyle(Paint.Style.STROKE);
+ }
+
+ // setting everything as transparent
+ guidelineCanvas.drawColor(Color.TRANSPARENT);
+
+ // drawing just a rect
+ if(pose != null){
+ for(PoseLandmark landmark : pose.getAllPoseLandmarks()){
+ guidelineCanvas.drawCircle(landmark.getPosition().x, landmark.getPosition().y, 6f, guidePointPaint);
+ }
+
+ // drawing lines
+ // TORSO
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, guidePaint);
+
+ //limbs
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().y, guidePaint);
+ //
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().y, guidePaint);
+
+ //MOUTH
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ canvasAlreadyClear = false;
+ }else{
+ canvasAlreadyClear = true;
+ }
+
+ guidelineView.invalidate();
+ guidelineView.setImageBitmap(guidelineBmp);
+ Log.d("debugg", "New Guidelines Drawn");
+ }
+ });
+
+ }
+
+ private void initViews(){
+ tricepsPosture = findViewById(R.id.postureTricepsEx);
+ previewView = findViewById(R.id.viewFinder);
+ guidelineView = findViewById(R.id.canvas);
+ exit = findViewById(R.id.exitButton);
+ }
+
+ private void runTest(){
+ if(detector == null){
+ AccuratePoseDetectorOptions options = new AccuratePoseDetectorOptions.Builder().setDetectorMode(AccuratePoseDetectorOptions.STREAM_MODE).build();
+ detector = PoseDetection.getClient(options);
+ }
+
+ tempBitmap = previewView.getBitmap();
+ if(previewView.getBitmap() == null){
+ return;
+ }
+
+ isFrameBeingTested = true;
+ detector.process(InputImage.fromBitmap(tempBitmap, 0)).addOnCompleteListener(new OnCompleteListener() {
+
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if(task.isSuccessful()){
+ Pose pose = task.getResult();
+ try {
+ handlePoseDetection(pose); // 포즈 감지 후 적절한 동작 처리
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ List landmarks = pose.getAllPoseLandmarks();
+ Log.d("debugg", "Landmarks found : " + landmarks.size());
+ if(landmarks.size() == 0){
+ isFrameBeingTested = false;
+ if(!canvasAlreadyClear)
+ loadGuidelines(tempBitmap, null);
+ return;
+ }
+
+ loadGuidelines(tempBitmap, pose);
+ isFrameBeingTested = false;
+ }else{
+ Log.e("debugg", "Error in test", task.getException());
+ loadGuidelines(tempBitmap, null);
+ isFrameBeingTested = false;
+ }
+ }
+ });
+ }
+
+ private void initTargetPoses() {
+ targetTricepsStartSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST, 150.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST, 150.0)
+ )
+ );
+
+ targetTricepsEndSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST, 40.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST, 40.0)
+ )
+ );
+
+ targetTricepsLowSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST, 140.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST, 140.0)
+ )
+ );
+
+ targetNotTricepsSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_HIP, 90),
+ new TargetShape(PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_HIP, 90)
+ )
+ );
+ }
+
+ private boolean isPoseMatching(Pose pose, TargetPose targetPose) {
+ PoseMatcher matcher = new PoseMatcher(); // PoseMatcher 객체 생성. 이전에 제공된 코드에서 제공된 것처럼 생성해야 합니다.
+ return matcher.match(pose, targetPose);
+ }
+
+ private void handlePoseDetection(Pose pose) throws InterruptedException {
+ Handler h = new Handler();
+
+ boolean isTricepsStart = isPoseMatching(pose, targetTricepsStartSign);
+ boolean isTricepsEnd = isPoseMatching(pose, targetTricepsEndSign);
+ boolean isTricepsLow = isPoseMatching(pose, targetTricepsLowSign);
+ boolean isNotTriceps = isPoseMatching(pose, targetNotTricepsSign);
+
+ if (isTricepsEnd) {
+ if (check) {
+ tricepsPosture.setText("잘했어요 다시 해볼까요?");
+ speakSquatEnd();
+ checkTriceps = false;
+ }
+ check = false;
+ } else if (isTricepsStart) {
+ check = true;
+ tricepsPosture.setText("Good Motion ! 이제 내리세요");
+ if(!checkTriceps){
+ speakSquatStart();
+ checkTriceps = true;
+ }
+ } else if (!checkTriceps && !isTricepsLow) {
+ tricepsPosture.setText("팔을 좀 더 올리세요");
+ } else if (isNotTriceps) {
+ tricepsPosture.setText("팔을 위로 올리세요");
+ }
+ }
+ private void speakSquatEnd() {
+ String textToSpeak ="잘했어요 다시 해볼까요?";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ private void speakSquatStart() {
+ String textToSpeak ="좋아요";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void startAnalysis(){
+ Handler handler = new Handler(getMainLooper());
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(!isFrameBeingTested){
+ runTest();
+ }
+ handler.postDelayed(this, UPDATE_TIME);
+ }
+ });
+ }
+
+ private void startInit(){
+ ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(this);
+ cameraProviderFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ProcessCameraProvider provider = cameraProviderFuture.get();
+
+ Preview preview = new Preview.Builder().build();
+ preview.setSurfaceProvider(previewView.createSurfaceProvider());
+ imageCapture = new ImageCapture.Builder().build();
+
+ provider.unbindAll();
+ provider.bindToLifecycle(PostureTriceps.this, CameraSelector.DEFAULT_FRONT_CAMERA, preview);
+
+ startAnalysis();
+ } catch (Exception e) {
+ Log.e("debugg", "Error Getting camera Provider", e);
+ }
+ }
+ }, ActivityCompat.getMainExecutor(PostureTriceps.this));
+ }
+
+ private void checkPermissions(){
+ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 455);
+ }else{
+ startInit();
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == 455) {
+ if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ finish();
+ } else {
+ startInit();
+ }
+ }
+ }
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("나가기") || str.equals("종료")){
+ Intent intent = new Intent(PostureTriceps.this, Posture.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 2000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+ @Override
+ protected void onDestroy() {
+ if (tts != null) {
+ tts.stop();
+ tts.shutdown();
+ }
+ super.onDestroy();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/record/RecordCurl.java b/app/src/main/java/com/example/newbody/record/RecordCurl.java
new file mode 100644
index 0000000..1bc7892
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/record/RecordCurl.java
@@ -0,0 +1,157 @@
+package com.example.newbody.record;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.VideoView;
+
+import com.example.newbody.R;
+import com.example.newbody.Record;
+import com.example.newbody.VoiceRecognitionService;
+
+import java.util.ArrayList;
+
+public class RecordCurl extends AppCompatActivity {
+
+ Button start, prev;
+ long time;
+ private VideoView mVideoView;
+ private TextView timeInput;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_record_curl);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ prev = findViewById(R.id.prevButtonDumbbellCurl);
+ timeInput = findViewById(R.id.timeInput);
+
+ start = findViewById(R.id.startDumbbellCurl);
+ Intent intent = getIntent();
+ time = intent.getLongExtra("time", 0);
+
+ timeInput.setText((time / 60000) + "분");
+
+ mVideoView = findViewById(R.id.dumbbellCurlEx);
+ Uri uri = Uri.parse("android.resource://" + getPackageName() + "/raw/dumbbellcurl");
+ mVideoView.setVideoURI(uri);
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Record.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ mp.start();
+ }
+ });
+ mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+ @Override
+ public void onCompletion(MediaPlayer mediaPlayer) {
+ // 동영상 재생이 완료되면 다시 시작
+ mVideoView.start();
+ }
+ });
+
+ start.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(RecordCurl.this, RecordCurlMain.class);
+ intent.putExtra("time", time);
+ startActivity(intent);
+ }
+ });
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("시작") || str.equals("운동 시작")){
+ Intent intent = new Intent(RecordCurl.this, RecordCurlMain.class);
+ intent.putExtra("time", time);
+ startActivity(intent);
+ }else if(str.equals("이전")){
+ Intent intent = new Intent(getApplicationContext(), Record.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 2000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/record/RecordCurlMain.java b/app/src/main/java/com/example/newbody/record/RecordCurlMain.java
new file mode 100644
index 0000000..da2cc0b
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/record/RecordCurlMain.java
@@ -0,0 +1,656 @@
+package com.example.newbody.record;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.os.Handler;
+import android.speech.RecognizerIntent;
+import android.speech.tts.TextToSpeech;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.Preview;
+import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.camera.view.PreviewView;
+import androidx.core.app.ActivityCompat;
+
+import com.example.newbody.CustomDialog;
+import com.example.newbody.PoseMatcher;
+import com.example.newbody.R;
+import com.example.newbody.Record;
+import com.example.newbody.TargetPose;
+import com.example.newbody.TargetShape;
+import com.example.newbody.VoiceRecognitionService;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.SetOptions;
+import com.google.mlkit.vision.common.InputImage;
+import com.google.mlkit.vision.pose.Pose;
+import com.google.mlkit.vision.pose.PoseDetection;
+import com.google.mlkit.vision.pose.PoseDetector;
+import com.google.mlkit.vision.pose.PoseLandmark;
+import com.google.mlkit.vision.pose.accurate.AccuratePoseDetectorOptions;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+public class RecordCurlMain extends AppCompatActivity {
+
+ FirebaseFirestore db;
+ FirebaseAuth mAuth;
+
+ private boolean curlStartDetected = false;
+ private boolean curlEndDetected = false;
+ private boolean checkCurl = false;
+ private long time;
+ private int score = 0;
+ private TargetPose targetCurlStartSign;
+ private TargetPose targetCurlEndSign;
+ private CountDownTimer timer;
+
+ private CustomDialog customDialog;
+ private TextToSpeech tts;
+
+ PreviewView previewView;
+ PoseDetector detector;
+ ImageView guidelineView;
+ ImageCapture imageCapture;
+
+ TextView count, timeEx, countEx;
+
+ Canvas guidelineCanvas;
+ Bitmap guidelineBmp, tempBitmap;
+ Paint guidePointPaint, guidePaint, transPaint;
+
+ private final int UPDATE_TIME = 40;
+ private boolean isFrameBeingTested = false, canvasAlreadyClear = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_record_curl_main);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
+ @Override
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int langResult = tts.setLanguage(Locale.KOREAN);
+ if (langResult == TextToSpeech.LANG_MISSING_DATA |
+ langResult == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e("TTS", "Language is not supported or missing data");
+ }else {
+ // 피치와 속도를 조절합니다.
+ tts.setPitch(0.8f); // 높은 톤
+ tts.setSpeechRate(0.9f); // 약간 빠른 속도
+ }
+ } else {
+ Log.e("TTS", "Initialization failed");
+ }
+ }
+ });
+
+ db = FirebaseFirestore.getInstance();
+ mAuth = FirebaseAuth.getInstance();
+
+ Intent intent = getIntent();
+ time = intent.getLongExtra("time", 0);
+
+ initTargetPoses();
+ initViews();
+
+ startCountdown(5000);
+ }
+
+ private void startCountdown(long duration) {
+ new CountDownTimer(duration, 1000) {
+
+ public void onTick(long millisUntilFinished) {
+ speakCount((int)(millisUntilFinished / 1000)+1);
+ count.setText(String.valueOf((millisUntilFinished / 1000)+1));
+ }
+
+ public void onFinish() {
+ count.setText("시작!");
+ speakStart();
+ count.setVisibility(View.INVISIBLE);
+ startTimer();
+ countEx.setText("개수 : " + score);
+ checkPermissions();
+ }
+
+ }.start();
+ }
+ private void speakCount(int count) {
+ String textToSpeak = String.valueOf(count);
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ private void speakStart() {
+ String textToSpeak = "시작";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void startTimer() {
+
+ timer = new CountDownTimer(time, 1000) {
+ @Override
+ public void onTick(long millisUntilFinished) {
+ // 남은 시간을 분과 초로 변환하여 표시
+ long minutes = millisUntilFinished / 60000;
+ long seconds = (millisUntilFinished % 60000) / 1000;
+ String timeLeftFormatted = String.format("%02d:%02d", minutes, seconds);
+ timeEx.setText("남은 시간 : " + timeLeftFormatted);
+ }
+
+ @Override
+ public void onFinish() {
+ FirebaseUser user = mAuth.getCurrentUser();
+ if (user != null) {
+ // 사용자의 정보를 가져오는 부분
+ DocumentReference userRef = db.collection("users").document(user.getUid());
+ userRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ // 사용자의 이름을 가져옵니다.
+ String userName = document.getString("name");
+
+ // 스쿼트 점수와 사용자의 이름을 저장하는 로직
+ saveCurlScoreWithName(userName, user);
+ saveCurlRecordWithDate(userName, user);
+ }
+ }
+ }
+ });
+ }
+ speakCurlResult(score);
+ customDialog = new CustomDialog(RecordCurlMain.this
+ ,"시간 : " + (time/60000) + "분 \n기록 : " + score + "개");
+ customDialog.show();
+ }
+ }.start();
+ }
+
+ private void speakCurlResult(int count) {
+ String textToSpeak ="총 기록은 " + count + "개 입니다. ";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void saveCurlRecordWithDate(String userName, FirebaseUser user){
+ Map userData = new HashMap<>();
+ final String collectionName = "dailyCurlRecords";
+
+ // 날짜 정보 생성
+ DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
+ String currentDate = dateFormat.format(new Date());
+
+ userData.put(currentDate+"CurlCount", score);
+
+ DocumentReference userRecordRef = db.collection(collectionName).document(user.getUid());
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ // 기존의 스쿼트 수를 가져옵니다.
+ Long existingCurlCount = document.getLong(currentDate+"curlCount");
+ if (existingCurlCount != null) {
+ int newCurlCount = existingCurlCount.intValue() + score;
+ userData.put(currentDate+"curlCount", newCurlCount);
+ }
+ }
+ // 새로운 스쿼트 수를 저장합니다.
+ userRecordRef.set(userData, SetOptions.merge())
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ Log.d("Firestore", "Data successfully written!");
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@org.checkerframework.checker.nullness.qual.NonNull Exception e) {
+ Log.w("Firestore", "Error writing document", e);
+ }
+ });
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+ }
+
+ private void saveCurlScoreWithName(String userName, FirebaseUser user){
+ Map userData = new HashMap<>();
+ final String collectionName;
+
+ if (time == 60000) {
+ collectionName = "countCurl1Minute";
+ } else if (time == 120000) {
+ collectionName = "countCurl2Minute";
+ } else if (time == 180000) {
+ collectionName = "countCurl3Minute";
+ } else {
+ collectionName = "";
+ }
+
+ // userName을 추가합니다.
+ userData.put("name", userName);
+ userData.put(collectionName, score);
+
+ DocumentReference userRecordRef = db.collection(collectionName).document(user.getUid());
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ Long curlCountLong;
+ if (time == 60000) {
+ curlCountLong = document.getLong("countCurl1Minute");
+ } else if (time == 120000) {
+ curlCountLong = document.getLong("countCurl2Minute");
+ } else {
+ curlCountLong = document.getLong("countCurl3Minute");
+ }
+ int existingCurlCount = 0; // 초기 값을 0으로 설정
+
+ if (curlCountLong != null) {
+ existingCurlCount = curlCountLong.intValue();
+ }
+
+ if (existingCurlCount <= score) {
+ userData.put(collectionName, score);
+ db.collection(collectionName).document(user.getUid())
+ .set(userData)
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid){
+ // 성공적으로 업데이트했을 때의 로직
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@org.checkerframework.checker.nullness.qual.NonNull Exception e) {
+ // 업데이트 실패했을 때의 로직
+ }
+ });
+ } else {
+ Log.d("Firestore", "User's score is not higher than the existing record.");
+ }
+ } else {
+ // 만약 문서가 없다면, 바로 점수를 저장합니다.
+ userData.put(collectionName, score);
+ userRecordRef.set(userData)
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ Log.d("Firestore", "Data successfully written!");
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@org.checkerframework.checker.nullness.qual.NonNull Exception e) {
+ Log.w("Firestore", "Error writing document", e);
+ }
+ });
+ }
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+
+ }
+
+ private void loadGuidelines(Bitmap bmp, Pose pose){
+ new Handler(getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ guidelineBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
+ guidelineCanvas = new Canvas(guidelineBmp);
+
+ if(transPaint == null || guidePaint == null){
+ transPaint = new Paint();
+ transPaint.setColor(Color.TRANSPARENT);
+ transPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePointPaint = new Paint();
+ guidePointPaint.setColor(Color.RED);
+ guidePointPaint.setStrokeWidth(10f);
+ guidePointPaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePointPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ guidePaint = new Paint();
+ guidePaint.setColor(Color.WHITE);
+ guidePaint.setStrokeWidth(3f);
+ guidePaint.setStrokeCap(Paint.Cap.BUTT);
+ guidePaint.setStyle(Paint.Style.STROKE);
+ }
+
+ // setting everything as transparent
+ guidelineCanvas.drawColor(Color.TRANSPARENT);
+// guidelineCanvas.drawRect(0, 0, guidelineBmp.getWidth(), guidelineBmp.getHeight(), transPaint);
+
+ // drawing just a rect
+ if(pose != null){
+ for(PoseLandmark landmark : pose.getAllPoseLandmarks()){
+ guidelineCanvas.drawCircle(landmark.getPosition().x, landmark.getPosition().y, 6f, guidePointPaint);
+ }
+
+ // drawing lines
+ // TORSO
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, guidePaint);
+
+ //limbs
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_WRIST).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST).getPosition().y, guidePaint);
+ //
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_HIP).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE).getPosition().y, guidePaint);
+
+ //MOUTH
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EAR).getPosition().y, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.LEFT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ guidelineCanvas.drawLine(pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().x, pose.getPoseLandmark(PoseLandmark.RIGHT_EYE).getPosition().y, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().x, pose.getPoseLandmark(PoseLandmark.NOSE).getPosition().y, guidePaint);
+ canvasAlreadyClear = false;
+ }else{
+ canvasAlreadyClear = true;
+ }
+
+ guidelineView.invalidate();
+ guidelineView.setImageBitmap(guidelineBmp);
+ Log.d("debugg", "New Guidelines Drawn");
+ }
+ });
+
+ }
+
+ private void initViews(){
+ previewView = findViewById(R.id.viewFinder);
+ guidelineView = findViewById(R.id.canvas);
+ count = findViewById(R.id.count);
+ timeEx = findViewById(R.id.timeEx);
+ countEx = findViewById(R.id.countEx);
+ }
+
+ private void runTest(){
+ if(detector == null){
+ AccuratePoseDetectorOptions options = new AccuratePoseDetectorOptions.Builder().setDetectorMode(AccuratePoseDetectorOptions.STREAM_MODE).build();
+ detector = PoseDetection.getClient(options);
+ }
+
+ tempBitmap = previewView.getBitmap();
+ if(previewView.getBitmap() == null){
+ return;
+ }
+
+ isFrameBeingTested = true;
+ detector.process(InputImage.fromBitmap(tempBitmap, 0)).addOnCompleteListener(new OnCompleteListener() {
+
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if(task.isSuccessful()){
+ Pose pose = task.getResult();
+ handlePoseDetection(pose); // 포즈 감지 후 적절한 동작 처리
+ List landmarks = pose.getAllPoseLandmarks();
+ Log.d("debugg", "Landmarks found : " + landmarks.size());
+ if(landmarks.size() == 0){
+ isFrameBeingTested = false;
+ if(!canvasAlreadyClear)
+ loadGuidelines(tempBitmap, null);
+ return;
+ }
+
+ loadGuidelines(tempBitmap, pose);
+ isFrameBeingTested = false;
+ }else{
+ Log.e("debugg", "Error in test", task.getException());
+ loadGuidelines(tempBitmap, null);
+ isFrameBeingTested = false;
+ }
+ }
+ });
+ }
+
+ private void initTargetPoses() {
+ targetCurlStartSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST,150.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST,150.0)
+ )
+ );
+
+ targetCurlEndSign = new TargetPose(
+ Arrays.asList(
+ new TargetShape(PoseLandmark.RIGHT_SHOULDER, PoseLandmark.RIGHT_ELBOW, PoseLandmark.RIGHT_WRIST,50.0),
+ new TargetShape(PoseLandmark.LEFT_SHOULDER, PoseLandmark.LEFT_ELBOW, PoseLandmark.LEFT_WRIST,50.0)
+ )
+ );
+ }
+
+ private boolean isPoseMatching(Pose pose, TargetPose targetPose) {
+ PoseMatcher matcher = new PoseMatcher(); // PoseMatcher 객체 생성. 이전에 제공된 코드에서 제공된 것처럼 생성해야 합니다.
+ return matcher.match(pose, targetPose);
+ }
+
+ private void handlePoseDetection(Pose pose) {
+ boolean isCurlStart = isPoseMatching(pose, targetCurlStartSign);
+ boolean isCurlEnd = isPoseMatching(pose, targetCurlEndSign);
+
+ if (curlStartDetected && isCurlEnd) {
+ score++;
+ countEx.setText("개수 : " + score);
+ speakCurlCount(score);
+ curlStartDetected = false; // 다음 연속 감지를 위해 초기화
+ curlEndDetected = false;
+ checkCurl = false;
+ } else if (isCurlStart) {
+ curlStartDetected = true;
+ if(!checkCurl){
+ speakCurl();
+ checkCurl = true;
+ }
+ }
+ }
+
+ private void speakCurlCount(int count) {
+ String textToSpeak = count + "개";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void speakCurl() {
+ double randomValue = Math.random();
+ int value = (int)(randomValue*4)+1;
+ String textToSpeak = null;
+ if(value == 1){
+ textToSpeak = "완벽해요";
+ }else if(value == 2){
+ textToSpeak = "좋아요";
+ }else if(value == 3){
+ textToSpeak = "훌륭해요";
+ }else if(value == 4){
+ textToSpeak = "잘했어요";
+ }
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void startAnalysis(){
+ Handler handler = new Handler(getMainLooper());
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(!isFrameBeingTested){
+ runTest();
+ }
+ handler.postDelayed(this, UPDATE_TIME);
+ }
+ });
+ }
+
+ private void startInit(){
+ ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(this);
+ cameraProviderFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ProcessCameraProvider provider = cameraProviderFuture.get();
+
+ Preview preview = new Preview.Builder().build();
+ preview.setSurfaceProvider(previewView.createSurfaceProvider());
+ imageCapture = new ImageCapture.Builder().build();
+
+ provider.unbindAll();
+ provider.bindToLifecycle(RecordCurlMain.this, CameraSelector.DEFAULT_FRONT_CAMERA, preview);
+
+ startAnalysis();
+ } catch (Exception e) {
+ Log.e("debugg", "Error Getting camera Provider", e);
+ }
+ }
+ }, ActivityCompat.getMainExecutor(RecordCurlMain.this));
+ }
+
+ private void checkPermissions(){
+ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 455);
+ }else{
+ startInit();
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == 455) {
+ if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ finish();
+ } else {
+ startInit();
+ }
+ }
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("나가기") || str.equals("종료")){
+ Intent intent = new Intent(RecordCurlMain.this, Record.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 2000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (tts != null) {
+ tts.stop();
+ tts.shutdown();
+ }
+ super.onDestroy();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/record/RecordDumbbell.java b/app/src/main/java/com/example/newbody/record/RecordDumbbell.java
new file mode 100644
index 0000000..f70fddf
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/record/RecordDumbbell.java
@@ -0,0 +1,158 @@
+package com.example.newbody.record;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.VideoView;
+
+import com.example.newbody.R;
+import com.example.newbody.Record;
+import com.example.newbody.VoiceRecognitionService;
+
+import java.util.ArrayList;
+
+public class RecordDumbbell extends AppCompatActivity {
+
+ Button start, prev;
+ long time;
+ private VideoView mVideoView;
+ private TextView timeInput;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_record_dumbbell);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ prev = findViewById(R.id.prevButtonDumbbell);
+ timeInput = findViewById(R.id.timeInput);
+
+ start = findViewById(R.id.startDumbbell);
+ Intent intent = getIntent();
+ time = intent.getLongExtra("time", 0);
+
+ timeInput.setText((time/60000)+"분");
+
+ mVideoView = findViewById(R.id.dumbbellEx);
+ Uri uri = Uri.parse("android.resource://" + getPackageName() + "/raw/dumbbell");
+ mVideoView.setVideoURI(uri);
+
+ prev.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(getApplicationContext(), Record.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+
+ mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ mp.start();
+ }
+ });
+ mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+ @Override
+ public void onCompletion(MediaPlayer mediaPlayer) {
+ // 동영상 재생이 완료되면 다시 시작
+ mVideoView.start();
+ }
+ });
+
+ start.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(RecordDumbbell.this, RecordDumbbellMain.class);
+ intent.putExtra("time", time);
+ startActivity(intent);
+ }
+ });
+ }
+
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int resultCode = intent.getIntExtra("resultCode", Activity.RESULT_CANCELED);
+ if (resultCode == 1) {
+ VoiceTask voiceTask = new VoiceTask();
+ voiceTask.execute();
+ }
+ }
+ };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
+ ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ String str = results.get(0);
+ if(str.equals("시작") || str.equals("운동 시작")){
+ Intent intent = new Intent(RecordDumbbell.this, RecordDumbbellMain.class);
+ intent.putExtra("time", time);
+ startActivity(intent);
+ }else if(str.equals("이전")){
+ Intent intent = new Intent(getApplicationContext(), Record.class);
+ startActivity(intent);
+ }
+ }
+ }
+
+ private void restartVoiceRecognitionService() {
+ Intent intent = new Intent(this, VoiceRecognitionService.class);
+ startService(intent);
+ }
+
+ public class VoiceTask extends AsyncTask {
+ @Override
+ protected Void doInBackground(String... params) {
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ getVoice();
+ }
+ }
+
+ private void getVoice() {
+ Intent intent = new Intent();
+ intent.setAction(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ String language = "ko-KR";
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
+ intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5000);
+ intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 2000);
+ startActivityForResult(intent, 2);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // 브로드캐스트 리시버 등록
+ registerReceiver(receiver, new IntentFilter("com.example.newbody.RESULT_ACTION"));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // 브로드캐스트 리시버 등록 해제
+ unregisterReceiver(receiver);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/newbody/record/RecordDumbbellMain.java b/app/src/main/java/com/example/newbody/record/RecordDumbbellMain.java
new file mode 100644
index 0000000..c04dbb2
--- /dev/null
+++ b/app/src/main/java/com/example/newbody/record/RecordDumbbellMain.java
@@ -0,0 +1,667 @@
+package com.example.newbody.record;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.Preview;
+import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.camera.view.PreviewView;
+import androidx.core.app.ActivityCompat;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.graphics.drawable.BitmapDrawable;
+import android.media.Image;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.os.Handler;
+import android.speech.RecognizerIntent;
+import android.speech.tts.TextToSpeech;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.example.newbody.CustomDialog;
+import com.example.newbody.PoseMatcher;
+import com.example.newbody.Record;
+import com.example.newbody.TargetPose;
+import com.example.newbody.TargetShape;
+import com.example.newbody.VoiceRecognitionService;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.SetOptions;
+import com.google.mlkit.vision.common.InputImage;
+import com.google.mlkit.vision.pose.Pose;
+import com.google.mlkit.vision.pose.PoseDetection;
+import com.google.mlkit.vision.pose.PoseDetector;
+import com.google.mlkit.vision.pose.PoseLandmark;
+import com.google.mlkit.vision.pose.accurate.AccuratePoseDetectorOptions;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Map;
+
+import com.example.newbody.R;
+
+public class RecordDumbbellMain extends AppCompatActivity {
+
+ FirebaseFirestore db;
+ FirebaseAuth mAuth;
+
+ private boolean dumbbellStartDetected = false;
+ private boolean dumbbellEndDetected = false;
+ private boolean checkDumbbell = false;
+ private long time;
+ private int score = 0;
+ private TargetPose targetDumbbellStartSign;
+ private TargetPose targetDumbbellEndSign;
+ private CountDownTimer timer;
+
+ private CustomDialog customDialog;
+ private TextToSpeech tts;
+
+ PreviewView previewView;
+ PoseDetector detector;
+ ImageView guidelineView;
+ ImageCapture imageCapture;
+
+ TextView count, timeEx, countEx;
+
+ Canvas guidelineCanvas;
+ Bitmap guidelineBmp, tempBitmap;
+ Paint guidePointPaint, guidePaint, transPaint;
+
+ private final int UPDATE_TIME = 40;
+ private boolean isFrameBeingTested = false, canvasAlreadyClear = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_record_dumbbell_main);
+
+ Intent intentS = new Intent(this, VoiceRecognitionService.class);
+ startService(intentS);
+
+ tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
+ @Override
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int langResult = tts.setLanguage(Locale.KOREAN);
+ if (langResult == TextToSpeech.LANG_MISSING_DATA |
+ langResult == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e("TTS", "Language is not supported or missing data");
+ }else {
+ // 피치와 속도를 조절합니다.
+ tts.setPitch(0.8f); // 높은 톤
+ tts.setSpeechRate(0.9f); // 약간 빠른 속도
+ }
+ } else {
+ Log.e("TTS", "Initialization failed");
+ }
+ }
+ });
+
+ db = FirebaseFirestore.getInstance();
+ mAuth = FirebaseAuth.getInstance();
+
+ Intent intent = getIntent();
+ time = intent.getLongExtra("time", 0);
+
+ initTargetPoses();
+ initViews();
+
+ startCountdown(5000);
+ }
+
+ private void startCountdown(long duration) {
+ new CountDownTimer(duration, 1000) {
+
+ public void onTick(long millisUntilFinished) {
+ speakCount((int)(millisUntilFinished / 1000)+1);
+ count.setText(String.valueOf((millisUntilFinished / 1000)+1));
+ }
+
+ public void onFinish() {
+ count.setText("시작!");
+ speakStart();
+ count.setVisibility(View.INVISIBLE);
+ startTimer();
+ countEx.setText("개수 : " + score);
+ checkPermissions();
+ }
+
+ }.start();
+ }
+ private void speakCount(int count) {
+ String textToSpeak = String.valueOf(count);
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+ private void speakStart() {
+ String textToSpeak = "시작";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void startTimer() {
+
+ timer = new CountDownTimer(time, 1000) {
+ @Override
+ public void onTick(long millisUntilFinished) {
+ // 남은 시간을 분과 초로 변환하여 표시
+ long minutes = millisUntilFinished / 60000;
+ long seconds = (millisUntilFinished % 60000) / 1000;
+ String timeLeftFormatted = String.format("%02d:%02d", minutes, seconds);
+ timeEx.setText("남은 시간 : " + timeLeftFormatted);
+ }
+
+ @Override
+ public void onFinish() {
+ FirebaseUser user = mAuth.getCurrentUser();
+ if (user != null) {
+ // 사용자의 정보를 가져오는 부분
+ DocumentReference userRef = db.collection("users").document(user.getUid());
+ userRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ // 사용자의 이름을 가져옵니다.
+ String userName = document.getString("name");
+
+ // 스쿼트 점수와 사용자의 이름을 저장하는 로직
+ saveDumbbellScoreWithName(userName, user);
+ saveDumbbellRecordWithDate(userName, user);
+ }
+ }
+ }
+ });
+ }
+ speakDumbbellResult(score);
+ customDialog = new CustomDialog(RecordDumbbellMain.this
+ ,"시간 : " + (time/60000) + "분 \n기록 : " + score + "개");
+ customDialog.show();
+ }
+ }.start();
+ }
+
+ private void speakDumbbellResult(int count) {
+ String textToSpeak ="총 기록은 " + count + "개 입니다. ";
+ tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null);
+ }
+
+ private void saveDumbbellRecordWithDate(String userName, FirebaseUser user){
+ Map userData = new HashMap<>();
+ final String collectionName = "dailyDumbbellRecords";
+
+ // 날짜 정보 생성
+ DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
+ String currentDate = dateFormat.format(new Date());
+
+ userData.put(currentDate+"dumbbellCount", score);
+
+ DocumentReference userRecordRef = db.collection(collectionName).document(user.getUid());
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ // 기존의 스쿼트 수를 가져옵니다.
+ Long existingDumbbellCount = document.getLong(currentDate+"DumbbellCount");
+ if (existingDumbbellCount != null) {
+ int newDumbbellCount = existingDumbbellCount.intValue() + score;
+ userData.put(currentDate+"dumbbellCount", newDumbbellCount);
+ }
+ }
+ // 새로운 스쿼트 수를 저장합니다.
+ userRecordRef.set(userData, SetOptions.merge())
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ Log.d("Firestore", "Data successfully written!");
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@org.checkerframework.checker.nullness.qual.NonNull Exception e) {
+ Log.w("Firestore", "Error writing document", e);
+ }
+ });
+ } else {
+ Log.d("Firestore", "Failed to get document", task.getException());
+ }
+ }
+ });
+ }
+
+ private void saveDumbbellScoreWithName(String userName, FirebaseUser user){
+ Map userData = new HashMap<>();
+ final String collectionName;
+
+ if (time == 60000) {
+ collectionName = "countDumbbell1Minute";
+ } else if (time == 120000) {
+ collectionName = "countDumbbell2Minute";
+ } else if (time == 180000) {
+ collectionName = "countDumbbell3Minute";
+ } else {
+ collectionName = "";
+ }
+
+ // userName을 추가합니다.
+ userData.put("name", userName);
+ userData.put(collectionName, score);
+
+ DocumentReference userRecordRef = db.collection(collectionName).document(user.getUid());
+ userRecordRef.get().addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (task.isSuccessful()) {
+ DocumentSnapshot document = task.getResult();
+ if (document.exists()) {
+ Long dumbbellCountLong;
+ if (time == 60000) {
+ dumbbellCountLong = document.getLong("countDumbbell1Minute");
+ } else if (time == 120000) {
+ dumbbellCountLong = document.getLong("countDumbbell2Minute");
+ } else {
+ dumbbellCountLong = document.getLong("countDumbbell3Minute");
+ }
+ int existingDumbbellCount = 0; // 초기 값을 0으로 설정
+
+ if (dumbbellCountLong != null) {
+ existingDumbbellCount = dumbbellCountLong.intValue();
+ }
+
+ if (existingDumbbellCount <= score) {
+ userData.put(collectionName, score);
+ db.collection(collectionName).document(user.getUid())
+ .set(userData)
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid){
+ // 성공적으로 업데이트했을 때의 로직
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@org.checkerframework.checker.nullness.qual.NonNull Exception e) {
+ // 업데이트 실패했을 때의 로직
+ }
+ });
+ } else {
+ Log.d("Firestore", "User's score is not higher than the existing record.");
+ }
+ } else {
+ // 만약 문서가 없다면, 바로 점수를 저장합니다.
+ userData.put(collectionName, score);
+ userRecordRef.set(userData)
+ .addOnSuccessListener(new OnSuccessListener