> # APP端 [TOC] # 進入Firebase 請先下載&安裝好Android Studio(文章使用版本為4.0.1) --- ## 登入Firebase&建立專案 ### step1:至Firebase 官網登入 gmail ![](https://i.imgur.com/vaAnrTW.png) ### step2:建立專案 按照步驟輸入如圖 ![](https://i.imgur.com/IJL1kR0.png) ![](https://i.imgur.com/vVmmQcd.png) ![](https://i.imgur.com/7AmLMAC.png) 位置看想在哪...應該是都行,然後建立專案! --- ## Android Studio 專案連接firebase設定 ### step1:先到Android Studio中完成設定 在Firebase上建立完成新專案之後,如何導入android studio ![](https://i.imgur.com/G9PmD0s.png) 首先點選android studio程式中右上角進行登入(建立專案的gmail) ![](https://i.imgur.com/P8BqLMj.png) 點選允許 ![](https://i.imgur.com/Hjg5NX7.png) 點選Firebase 接著先回來android studio 點選Tools 選擇 Firebase ![](https://i.imgur.com/IEEoK9y.png) 接著就可以看需求選擇需要的服務進行連接 (此處使用身分驗證功能作範例) ![](https://i.imgur.com/CdWkcLm.png) 點選 Email and password authentication ![](https://i.imgur.com/npztncG.png) 按照上面說明的順序選擇 1.Connect to Firebase ![](https://i.imgur.com/OMhiLZx.png) 選擇前面已在Firebase上建置的專案 ![](https://i.imgur.com/NiKNCyG.png) 如成功連結 會打勾勾 接著點選 2.Add Firebase Authentication to your app ![](https://i.imgur.com/uSn8rZ5.png) 選擇Accept Changes ![](https://i.imgur.com/j1tAkIx.png) 將會自動幫你產生到你的gradle 代表你目前的app中已經擁有這項服務(但是還沒有完全連接) 啟用其他服務也是以此類推(只是不用再設定前面的Connect to Firebase) 接下來是最關鍵的步驟 ### step2:下載該專案的鑰匙 ![](https://i.imgur.com/gPWtoNv.png) 回到Firebase 網頁 並且重新整理後 發現我們已經成功將兩邊的專案連接在一起了 接著首先點選 專案總覽-->專案設定 ![](https://i.imgur.com/fQPp6hh.png) 可以看到您的應用程式中(已產生我們在Android Studio的專案) ##### 接著點選 ![](https://i.imgur.com/ckotZFt.png) 請將此檔案放置Android Studio 專案目錄底下的app資料夾中 (如果想要使用別人做好的專案也是如此) ![](https://i.imgur.com/tRhxJXF.png) ![](https://i.imgur.com/PzbsSYt.png) 完成之後就可以來開始寫APP的功能囉! --- # 關於Authentication身分驗證 ## 設定e-mail作為驗證方式(使用該服務的入口) ### step1:專案網頁設定 ![](https://i.imgur.com/wGL4LrL.png) 首先先到專案網頁上的 Authentication 點選設定登入方式 ![](https://i.imgur.com/THXoO02.png) ![](https://i.imgur.com/1aE4hzd.png) 點選編輯設定 ![](https://i.imgur.com/AMPpMXS.png) 勾選啟用並儲存 ##### 設定e-mail 系統郵件內容 ![](https://i.imgur.com/TlzXshR.png) 由此設定 可編輯郵件內容 ### step2:APP端程式碼 #### 請記得先到Tools 先加入該服務到app中 ##### 在app上的登入程式碼 ``` import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseUser; public class MainActivity extends AppCompatActivity { EditText emailId , password; Button btnSignIn; TextView tvSignUp; private FirebaseAuth mAuth; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mAuth = FirebaseAuth.getInstance(); emailId = findViewById(R.id.EmaileditText); password = findViewById(R.id.PasseditText); btnSignIn = findViewById(R.id.BtnSignIn); tvSignUp = findViewById(R.id.textView3); btnSignIn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String email = emailId.getText().toString(); String pwd = password.getText().toString(); if (email.isEmpty()){ emailId.setError("您尚未輸入信箱"); emailId.requestFocus(); } else if(pwd.isEmpty()){ password.setError("您尚未輸入密碼"); password.requestFocus(); } else if (email.isEmpty() && pwd.isEmpty()){ Toast.makeText(MainActivity.this,"請先輸入帳號密碼",Toast.LENGTH_LONG).show(); } else if(!(email.isEmpty() && pwd.isEmpty())){ mAuth.signInWithEmailAndPassword(email,pwd).addOnSuccessListener(MainActivity.this, new OnSuccessListener<AuthResult>() { @Override public void onSuccess(AuthResult authResult) { Toast.makeText(MainActivity.this,"您已登入",Toast.LENGTH_SHORT).show(); Intent intToHome = new Intent(MainActivity.this,HomeActivity.class); startActivity(intToHome); } }); } else { Toast.makeText(MainActivity.this,"Error",Toast.LENGTH_SHORT).show(); } } }); } } ``` ##### 在app上的認證信程式碼 ``` public void sendVerificationEmail(){ FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); if (user !=null){ user.sendEmailVerification().addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { Toast.makeText(SignUp_page.this,"Sign Up Success pls check your email",Toast.LENGTH_LONG).show(); } else{ Toast.makeText(SignUp_page.this,"Sign Up Error pls try again",Toast.LENGTH_LONG).show(); } } }); } } ``` 有關於註冊由於會使用FireStore DB所以這裡先不講。 --- # 關於FireStore 資料庫 ## 專案網頁設定 ### step1:建立資料庫 ![](https://i.imgur.com/GLw52cX.png) 至專案網頁上點選建立資料庫 ![](https://i.imgur.com/3xDuKD9.png) 這裡先以測試模式啟動(日後有需要可再修改) 此處也可設定不同使用者之權限 ![](https://i.imgur.com/KDMr8gs.png) 選擇位置(我是都挑亞洲選) ## 在app上透過身分驗證後授權有效使用者 ### 請記得先到Tools 先加入該服務到app中 以下將會達成 在app上進行註冊(透過e-mail地址) 註冊時所輸入的資料會儲存在FireStore成功後發送驗證信 如果確認使用者有成功點擊驗證信 才可以進入下一個Activity ### 登入code(包含選擇不同階級引導至不同Activity) ``` package com.example.elderlycare_project; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.content.Intent; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.android.gms.tasks.Task; import com.google.firebase.auth.AuthResult; 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; public class MainActivity extends AppCompatActivity { EditText emailId , password; Button btnSignIn,btnSignUp,btnForget; private FirebaseAuth mAuth; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setTitle("ElderlyCare"); mAuth = FirebaseAuth.getInstance(); emailId = findViewById(R.id.Username); password = findViewById(R.id.Password); btnSignIn = findViewById(R.id.login); btnSignUp = findViewById(R.id.Signup); btnForget = findViewById(R.id.Forget); btnForget.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String email = emailId.getText().toString(); mAuth.sendPasswordResetEmail(email).addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { Toast.makeText(MainActivity.this,"Check your mailbox to reset pw ",Toast.LENGTH_LONG).show(); } else { Toast.makeText(MainActivity.this,"please enter the true mailaddress ",Toast.LENGTH_LONG).show(); } } }); } }); btnSignUp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent inToSignUp = new Intent(MainActivity.this,SignUp_page.class); startActivity(inToSignUp); } }); btnSignIn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { final String email = emailId.getText().toString(); String pwd = password.getText().toString(); if (email.isEmpty() &&pwd.isEmpty()) { Toast.makeText(MainActivity.this,"please enter AC & pw ",Toast.LENGTH_LONG).show(); } else if (!(email.isEmpty() &&pwd.isEmpty())) { mAuth.signInWithEmailAndPassword(email,pwd).addOnSuccessListener(MainActivity.this, new OnSuccessListener<AuthResult>() { @Override public void onSuccess(AuthResult authResult) { FirebaseUser user =mAuth.getCurrentUser(); try { if (user.isEmailVerified()) { //Toast.makeText(MainActivity.this, "Login Success", Toast.LENGTH_SHORT).show(); String uid = mAuth.getUid(); FirebaseFirestore FFS =FirebaseFirestore.getInstance(); DocumentReference df = FFS.collection("Users").document(uid); df.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() { @Override public void onSuccess(DocumentSnapshot documentSnapshot) { if (documentSnapshot.getString("Rank").equals("rank1")) { String name= documentSnapshot.getString("Name"); String Email= documentSnapshot.getString("Email"); Intent intent = new Intent(MainActivity.this,Rank1HomeActivity.class); Bundle bundle = new Bundle(); bundle.putString("Email",Email); intent.putExtras(bundle); startActivity(intent); //startActivity(new Intent(getApplicationContext(),Rank1HomeActivity.class)); finish(); } if (documentSnapshot.getString("Rank").equals("rank2")) { startActivity(new Intent(getApplicationContext(), Rank2HomeActivity.class)); //Toast.makeText(MainActivity.this, list.indexOf(1), Toast.LENGTH_SHORT).show(); // bundle.putStringArrayList("Bed",list); // intent.putExtras(bundle); // startActivity(intent); // finish(); //Toast.makeText(MainActivity.this, "Login fail", Toast.LENGTH_SHORT).show(); } if (documentSnapshot.getString("Rank").equals("rank3")) { String Email= documentSnapshot.getString("Email"); Intent intent = new Intent(MainActivity.this,Rank3HomeActivity.class); Bundle bundle = new Bundle(); bundle.putString("Email",Email); intent.putExtras(bundle); startActivity(intent); finish(); //Toast.makeText(MainActivity.this, "Login fail", Toast.LENGTH_SHORT).show(); } } }); } else{ Toast.makeText(MainActivity.this, "Login fail", Toast.LENGTH_SHORT).show(); } } catch (NullPointerException e){} } }); } } }); } } ``` ### 註冊code(包含選擇不同階級) ``` package com.example.elderlycare_project; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; import android.widget.Toast; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.android.gms.tasks.Task; import com.google.firebase.auth.AuthResult; 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 java.util.HashMap; import java.util.Map; public class SignUp_page extends AppCompatActivity { String rankClass; //for firestore rank Button SignUp; EditText Username,Usermail,Usertel,password1,password2; //SaveUserInf users; private Spinner spinner; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_up_page); spinner = (Spinner)findViewById(R.id.Rankspinner); setAdapter(); setListener(); final FirebaseAuth mAuth = FirebaseAuth.getInstance(); Username = findViewById(R.id.editTextTextPersonName); Usermail = findViewById(R.id.editTextTextEmailAddress); Usertel = findViewById(R.id.editTextPhone); password1 = findViewById(R.id.editTextTextPassword); password2 = findViewById(R.id.editTextTextPassword2); SignUp = findViewById(R.id.SignUp); SignUp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { final String mail = Usermail.getText().toString(); final String name = Username.getText().toString(); final String tel = Usertel.getText().toString(); String pwd = password1.getText().toString(); String pwd2 = password2.getText().toString(); final String UserRank = rankClass; boolean checkfield = mail.isEmpty() || name.isEmpty() || tel.isEmpty() || pwd.isEmpty() || pwd2.isEmpty() || UserRank.equals("null"); if (checkfield) { Toast.makeText(SignUp_page.this,"please enter every field",Toast.LENGTH_LONG).show(); } else { if (pwd.equals(pwd2)) { if (UserRank.equals("rank1")) { //admin sign up mAuth.createUserWithEmailAndPassword(mail, pwd).addOnSuccessListener(SignUp_page.this, new OnSuccessListener<AuthResult>() { @Override public void onSuccess(AuthResult authResult) { sendVerificationEmail(); String token = authResult.getUser().getUid(); Toast.makeText(SignUp_page.this, token, Toast.LENGTH_SHORT).show(); FirebaseFirestore FFS = FirebaseFirestore.getInstance(); DocumentReference documentReference = FFS.collection("Users").document(token); Map<String, Object> userdata = new HashMap<>(); userdata.put("Name", name); userdata.put("Email", mail); userdata.put("Rank", UserRank); userdata.put("Tel", tel); userdata.put("Token", token); documentReference.set(userdata).addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { } }); } }); } else if (UserRank.equals("rank2")){ //taker sign up mAuth.createUserWithEmailAndPassword(mail, pwd).addOnSuccessListener(SignUp_page.this, new OnSuccessListener<AuthResult>() { @Override public void onSuccess(AuthResult authResult) { sendVerificationEmail(); String token = authResult.getUser().getUid(); Toast.makeText(SignUp_page.this, token, Toast.LENGTH_SHORT).show(); FirebaseFirestore FFS = FirebaseFirestore.getInstance(); DocumentReference documentReference = FFS.collection("Users").document(token); DocumentReference employeedocument = FFS.collection("Employee").document(token); Map<String, Object> userdata = new HashMap<>(); userdata.put("Name", name); userdata.put("Email", mail); userdata.put("Rank", UserRank); userdata.put("Tel", tel); userdata.put("Token", token); //userdata.put("Bed",""); employeedocument.set(userdata).addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { } }); documentReference.set(userdata).addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { } }); } }); } else if (UserRank.equals("rank3")){ //family sign up mAuth.createUserWithEmailAndPassword(mail, pwd).addOnSuccessListener(SignUp_page.this, new OnSuccessListener<AuthResult>() { @Override public void onSuccess(AuthResult authResult) { sendVerificationEmail(); String token = authResult.getUser().getUid(); Toast.makeText(SignUp_page.this, token, Toast.LENGTH_SHORT).show(); FirebaseFirestore FFS = FirebaseFirestore.getInstance(); DocumentReference documentReference = FFS.collection("Users").document(token); DocumentReference familydocument = FFS.collection("Family").document(token); Map<String, Object> userdata = new HashMap<>(); userdata.put("Name", name); userdata.put("Email", mail); userdata.put("Rank", UserRank); userdata.put("Tel", tel); userdata.put("Token", token); familydocument.set(userdata).addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { } }); documentReference.set(userdata).addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { } }); } }); } else { } } } } }); } private void setAdapter(){ String [] rank = getResources().getStringArray(R.array.Rank); ArrayAdapter <String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,rank); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); } private void setListener(){ spinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { String [] rankdb = getResources().getStringArray(R.array.Rankdb); rankClass = rankdb[i] ; } @Override public void onNothingSelected(AdapterView<?> adapterView) { } }); } public void sendVerificationEmail(){ FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); if (user !=null){ user.sendEmailVerification().addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { Toast.makeText(SignUp_page.this,"Sign Up Success pls check your email",Toast.LENGTH_LONG).show(); } else{ Toast.makeText(SignUp_page.this,"Sign Up Error pls try again",Toast.LENGTH_LONG).show(); } } }); } } } ``` ## FireStore RecyclerView ### step1:implementation ``` implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'com.firebaseui:firebase-ui-firestore:7.0.0' implementation "androidx.recyclerview:recyclerview:1.1.0" implementation "androidx.recyclerview:recyclerview-selection:1.1.0-rc03" implementation "com.google.android.material:material:1.2.1" //漂浮按鈕 ``` ### step2:Create item.xml ``` <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:layout_marginTop="8dp" android:background="#FFFFFF"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:padding="8dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_toStartOf="@+id/text_view_rank3_pose_time" android:maxLines="1" android:text="Title" android:id="@+id/text_view_rank3_pose_pose" android:ellipsize="end" android:textAppearance="@style/TextAppearance.AppCompat.Large" /> <TextView android:id="@id/text_view_rank3_pose_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Bed" android:layout_alignParentTop="true" android:layout_alignParentEnd="true" android:textAppearance="@style/TextAppearance.AppCompat"/> <TextView android:id="@+id/text_view_rank3_pose_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/text_view_rank3_pose_pose" android:layout_alignParentStart="true" android:text="123" /> </RelativeLayout> </androidx.constraintlayout.widget.ConstraintLayout> ``` ### step3:Create list_Model.java ``` package com.example.elderlycare_project.Model; public class taker_pose_model { private String Name; private String Time; private String Pose; public taker_pose_model(){} public taker_pose_model(String Name,String Pose,String Time){ this.Name=Name; this.Pose=Pose; this.Time=Time; } public String getName() { return Name; } public void setName(String name) { Name = name; } public String getTime() { return Time; } public void setTime(String time) { Time = time; } public String getPose() { return Pose; } public void setPose(String pose) { Pose = pose; } } ``` ### step4:Create Activity ``` package com.example.elderlycare_project; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import android.os.Bundle; import android.widget.Button; import android.widget.TextView; import com.example.elderlycare_project.Adapter.rank3_pose_adapter; import com.example.elderlycare_project.Model.patient_pose_model; import com.firebase.ui.firestore.FirestoreRecyclerOptions; import com.google.firebase.firestore.FirebaseFirestore; import com.google.firebase.firestore.Query; public class Rank3PoseActivity extends AppCompatActivity { FirebaseFirestore FFS = FirebaseFirestore.getInstance(); TextView txv,txv2,txv3; private rank3_pose_adapter adapter; // private String buuid = (String) txv.getText(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_rank3_pose); setTitle("被照顧者姿勢頁面"); Bundle bundle = getIntent().getExtras(); final String uuid=bundle.getString("uuid"); txv = findViewById(R.id.textView16);//站 txv2 = findViewById(R.id.textView17);//坐 txv3 = findViewById(R.id.textView18); Button test = findViewById(R.id.testbtn); // txv = findViewById(R.id.textView30); //txv.setText(uuid); setRecyclerView(uuid.trim()); } private void setRecyclerView(String a){ //Query query = FFS.collection("1d16e844-d471-4911-95eb-554c14e7976ep"); Query query = FFS.collection(a+"p"); FirestoreRecyclerOptions<patient_pose_model> options= new FirestoreRecyclerOptions.Builder<patient_pose_model>() .setQuery(query,patient_pose_model.class) .build(); adapter=new rank3_pose_adapter(options); RecyclerView recyclerView = findViewById(R.id.recycler_view_rank3_pose); recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(adapter); options.getClass(); //ArrayList<String> c = } @Override protected void onStart() { super.onStart(); adapter.startListening(); } @Override protected void onStop() { super.onStop(); adapter.startListening(); } } ``` #### Layout ``` <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".Rank3PoseActivity"> <TextView android:id="@+id/textView13" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="28dp" android:text="躺著" app:layout_constraintBottom_toTopOf="@+id/textView12" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/textView12" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="40dp" android:text="坐" app:layout_constraintBottom_toTopOf="@+id/textView11" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/textView11" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="站" app:layout_constraintBottom_toTopOf="@+id/recycler_view_rank3_pose" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.094" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="1.0" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view_rank3_pose" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="150sp"/> <TextView android:id="@+id/textView14" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginBottom="28dp" android:text="各別時間" app:layout_constraintBottom_toTopOf="@+id/textView12" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/textView16" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="230dp" android:text="TextView" app:layout_constraintBottom_toTopOf="@+id/recycler_view_rank3_pose" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/textView11" app:layout_constraintTop_toBottomOf="@+id/textView17" app:layout_constraintVertical_bias="1.0" /> <TextView android:id="@+id/textView17" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="230dp" android:text="TextView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/textView12" app:layout_constraintTop_toBottomOf="@+id/textView18" /> <TextView android:id="@+id/textView18" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="90dp" android:layout_marginEnd="230dp" android:text="TextView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.489" app:layout_constraintStart_toEndOf="@+id/textView13" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/testbtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="50dp" android:layout_marginTop="85dp" android:layout_marginBottom="17dp" android:text="Button" app:layout_constraintBottom_toTopOf="@+id/recycler_view_rank3_pose" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/textView12" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> ``` ### step5:Create adapter ``` package com.example.elderlycare_project.Adapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.example.elderlycare_project.Datechange.SecondtoDate; import com.example.elderlycare_project.Model.patient_pose_model; import com.example.elderlycare_project.R; import com.firebase.ui.firestore.FirestoreRecyclerAdapter; import com.firebase.ui.firestore.FirestoreRecyclerOptions; public class rank3_pose_adapter extends FirestoreRecyclerAdapter<patient_pose_model,rank3_pose_adapter.rank3_pose_Holder>{ public rank3_pose_adapter(@NonNull FirestoreRecyclerOptions<patient_pose_model> options) { super(options); } @Override protected void onBindViewHolder(@NonNull rank3_pose_adapter.rank3_pose_Holder holder, int position, @NonNull patient_pose_model model) { holder.txttime.setText(SecondtoDate.getSecDate(model.getTime())); holder.txtname.setText(model.getName()); holder.txtpose.setText(model.getPose()); } @NonNull @Override public rank3_pose_Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.rank3_pose_item,parent,false); return new rank3_pose_Holder(v); } class rank3_pose_Holder extends RecyclerView.ViewHolder{ TextView txtname; TextView txtpose; TextView txttime; public rank3_pose_Holder(View rank3_pose_item){ super(rank3_pose_item); txtname=rank3_pose_item.findViewById(R.id.text_view_rank3_pose_name); txtpose=rank3_pose_item.findViewById(R.id.text_view_rank3_pose_pose); txttime=rank3_pose_item.findViewById(R.id.text_view_rank3_pose_time); } } } ``` ### 參考影片 https://www.youtube.com/watch?v=ub6mNHWGVHw --- # 關於Cloud Messaging https://medium.com/firebase-developers/mobile-app-push-notification-with-firebase-cloud-functions-and-realtime-database-194a82e43ba 尚未實作成功 --- # 關於Cloud Functions ### step1: 安裝Firebase CLI Reference 首先我們先至官網 https://firebase.google.com/docs/cli ![](https://i.imgur.com/I4cyvRk.png) 可以看到有兩種選項(這裡使用npm) 因此我們必須先裝 "Node.js" 才能繼續操作 至Node.js官網下載 https://nodejs.org/en/ ![](https://i.imgur.com/JpJhy7J.png) 裝LTS版本就行 安裝完後請打開終端機(命令提示字元) (右鍵win選擇) [Windows PowerShell系統管理員]。 ☆macOS使用也是相同☆ 開啟 終端機 ![](https://i.imgur.com/vnS7vRt.png) 按照網頁說明輸入 npm install -g firebase-tools ![](https://i.imgur.com/OBIISZe.png) ![](https://i.imgur.com/tS4F9QS.png) 安裝完之後就可以來進行登入帳號囉! 輸入 "firebase login" 選擇Y ![](https://i.imgur.com/HlB7vbg.png) ### step2: 登入Firebase CLI Reference 接著便會引導到Browser 的登入畫面 ![](https://i.imgur.com/jBETnMf.png) 選擇允許 ![](https://i.imgur.com/a7PzX4V.png) 成功登入CLI ![](https://i.imgur.com/F1Z3LfN.png) ![](https://i.imgur.com/HtQVzlJ.png) ### step3: 初始化Firebase CLI Reference 首先請你先找一個地方建一個新資料夾(英文名稱) 接著使用 cd 指令 到該資料夾中 輸入指令 firebase init ![](https://i.imgur.com/31euVrX.png) 輸入Y ![](https://i.imgur.com/AZreEKU.png) 這裡就是看你需要哪些服務 需要的用空白鍵去標記 我只使用Functions 故僅標記 Functions ![](https://i.imgur.com/Im7PzZ0.png) 確認請按Enter ![](https://i.imgur.com/xDLU33P.png) 接著根據你的需求選擇相對應的選項 這裡我是選使用已存在的專案 ![](https://i.imgur.com/iAyyrR0.png) 語言選擇JS ![](https://i.imgur.com/BAVnjGC.png) 選項都默認選Y就可以了 ![](https://i.imgur.com/14gzqvP.png) 完成後可以發現資料夾內已有產生檔案 ### step4:開始使用 由於node.js我不太熟 為了讓他能夠成功發布 因此我們必須先去修改使用的版本 ![](https://i.imgur.com/uDsk5us.png) 首先先至剛剛CLI的目錄底下的functions資料夾中 開啟package.json 並修改 ![](https://i.imgur.com/qScqsBU.png) 然後我們就可以開始寫想要的cloud function了 修改方式,編輯index.js 接著透過 終端機 到該目錄底下 輸入指令 firebase deploy 如通過規則,便能成功發布。 #### 原始的index.js ![](https://i.imgur.com/JUsFiq7.png) #### 修改過的index.js ![](https://i.imgur.com/hprwxbi.png) #### 成功發布後 可在Functions中顯示 ![](https://i.imgur.com/qW5FBD9.png) #### 參考影片 https://www.youtube.com/watch?v=Y6jMKQ9zo-o --- # 時間轉換 java ## 日期轉換成秒數 import java.util.Calendar; public class DatetoSecond { private String year ; private String month; private String day; public DatetoSecond(int year ,int month,int day ) { this.year=String.valueOf(year); this.month=String.valueOf(month); this.day=String.valueOf(day); daytosec(year,month,day); } public static String daytosec(int year, int month, int day) { Calendar calendar = Calendar.getInstance(); calendar.set(year,month,day,0,0,0); //年月日 long daytosec = calendar.getTimeInMillis(); return String.valueOf(daytosec); } public String getYear() { return year; } public void setYear(String year) { this.year = year; } public String getMonth() { return month; } public void setMonth(String month) { this.month = month; } public String getDay() { return day; } public void setDay(String day) { this.day = day; } } ## 秒數轉換成日期 import android.util.Log; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; public class SecondtoDate { private String seconds; public SecondtoDate(String seconds) { this.seconds = seconds; int i = Integer.parseInt(seconds);//+28800; String ii = String.valueOf(i); getSecDate(ii); } public static String getSecDate(String seconds) { if(seconds==null) return ""; else { Date date = new Date(); try{ date.setTime(Long.parseLong(seconds)*1000); } catch (NumberFormatException ignored){} SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ", Locale.TAIWAN); return sdf.format(date); } } public String getSeconds() { return seconds; } public void setSeconds(String seconds) { this.seconds = seconds; } } --- # 計算不同動作時間 ## Pseudocode private void timeCount(ArrayList pos_arr, ArrayList moment_arr){ int sumA = sumB = sumC = 0; int currentTime = time.getCurrent(); int i = 0; for (int i=0; i<pos_arr.length-1;i++){ if(pos == "sit"){ sumA += mommenmt_arr.get(i+1)- } else if (pos == 'stand'){} } if(pos_arr.get(pos.arr.length)-1 == 'sit'){ sumA += currentTime - momment_arr.get(moment_arr.get (momment_arr.length-1))); } } ---