# Android Studio+Firebase
[TOC]
<style>
.flex-container{
display:flex;
justify-content:center;
}
</style>
# 壹、環境建置
## 一、Android Studio
### (一)下載JDK
#### 1. 至[Oracle官網](https://www.oracle.com/java/technologies/javase-downloads.html),點選JDK Download。
<div class="flex-container">
<img src="https://i.imgur.com/WtAz8d7.png"
width="100%"></div>
#### 2. 根據作業系統,下載最新版本JDK。
<div class="flex-container">
<img src="https://i.imgur.com/vipYhtw.png"
width="100%"></div>
### (二)安裝Android Studio
#### 1. 至[Android Developer官網](https://developer.android.com/studio/index.html),根據作業系統點選下載(圖以mac為例)
<div class="flex-container">
<img src="https://i.imgur.com/ykeBjKa.png"
width="90%"></div>
#### 2. 必須勾選已閱讀並同意授權條款,才能按下Download Android Studio鈕, 就會開始下載檔案。
<div class="flex-container">
<img src="https://i.imgur.com/yDNsHtV.png"
width="90%"></div>
:::info
因爲以前裝過android studio,中間步驟不加以敘述。
:::
---
## 二、連接Firebase
### (一)Android Studio 專案連接firebase設定
#### 1. 點選大頭照登入帳號。
<div class="flex-container">
<img src="https://i.imgur.com/XUcmcMX.png"
width="80%"></div>
#### 2. 點選『允許』,存取帳號。
<div class="flex-container">
<img src="https://i.imgur.com/j9TgJn2.png"
width="50%"></div>
#### 3. 顯示『Success!』,點選firebase。
<div class="flex-container">
<img src="https://i.imgur.com/RUCk5PG.png"
width="80%"></div>
### (二)Firebase專案建置
#### 1. 建立Firebase專案,至[Firebase的網站](https://firebase.google.com)登入,之後點擊右上方的按鈕前往「控制台」。
<div class="flex-container">
<img src="https://i.imgur.com/luddlJJ.png"
width="100%"></div>
#### 2. 在控制台中新增一個專案。(檔案名稱為範例)
<div class="flex-container">
<img src="https://i.imgur.com/7QZ6MSs.png"
width="80%"></div>
#### 3. 點選『繼續』
<div class="flex-container">
<img src="https://i.imgur.com/VyEKP3W.png"
width="80%"></div>
#### 4. 點選『建立專案』
<div class="flex-container">
<img src="https://i.imgur.com/7R55nSH.png"
width="80%"></div>
#### 5. 建立專案後進入底下的畫面,點選android的logo。
<div class="flex-container">
<img src="https://i.imgur.com/2j9d2uO.png"
width="100%"></div>
#### 6. 輸入套件名稱。
<div class="flex-container">
<img src="https://i.imgur.com/zQiTPK0.png"
width="90%"></div>
#### 7. 照著指示拖進Android studio專案裡,完成之後按『繼續』。
<div class="flex-container">
<img src="https://i.imgur.com/4n5xEMQ.png"
width="90%"></div>
#### 8. 照著指示,複製到build.gradle(Project:ElderlyApp)。
<div class="flex-container">
<img src="https://i.imgur.com/0DDVfol.png"
width="90%"></div>
#### 9. 照著指示,複製到build.gradle(Module:ElderlyApp)。
<div class="flex-container">
<img src="https://i.imgur.com/0hkXcwj.png"
width="90%"></div>
#### 10. 新增成功。
<div class="flex-container">
<img src="https://i.imgur.com/2yxX1Zm.png"
width="90%"></div>
# 貳、Authentication之使用
## 一、Authentication設定
#### 1. 打開tools裡的firebase
<div class="flex-container">
<img src="https://i.imgur.com/XMxfxmY.png"
width="60%"></div>
#### 2. 在authentication裡,選第一個。
<div class="flex-container">
<img src="https://i.imgur.com/9w6hmmw.png"
width="60%"></div>
#### 3. 選擇Connect to Firebase>。
<div class="flex-container">
<img src="https://i.imgur.com/4Jr5PnX.png"
width="60%"></div>
:::info
若遇到 **Connect to Firebase**
Could not parse the Android Application
Module's Gradle config. ResoIve gradle build issues and/or resync.
將build.gradle(Project:)裡的 allprojects下的jcenter()給註解。
:::
#### 4. 點選Build。
<div class="flex-container">
<img src="https://i.imgur.com/IEeBVqv.png"
width="60%"></div>
#### 5. 導向firebase,選擇專案。
<div class="flex-container">
<img src="https://i.imgur.com/Kbhh7Hd.png"
width="80%"></div>
#### 6. 點選『連結』。
<div class="flex-container">
<img src="https://i.imgur.com/nfOXhLl.png"
width="80%"></div>
#### 7. 回到android studio 執行SDK。
<div class="flex-container">
<img src="https://i.imgur.com/ZuZTz9F.png"
width="60%"></div>
#### 8. SDK建置成功。
<div class="flex-container">
<img src="https://i.imgur.com/rUP2MKu.png"
width="70%"></div>
## 二、Authentication 身份驗證
**>>> 設定e-mail作為驗證方式 <<<**
#### 1. 點選『電子郵件』。
<div class="flex-container">
<img src="https://i.imgur.com/qdnZkld.png"
width="90%"></div>
#### 2. 選擇『啟用』並儲存。
<div class="flex-container">
<img src="https://i.imgur.com/tvOAht3.png"
width="100%"></div>
## 三、Authentication 程式碼
:::info
<div class="flex-container">
<img src="https://i.imgur.com/oG9bqBh.png"
width="100%"></div>
gradle 的地方隨自己的需求新增firebase功能
:::
### (一)註冊功能 (以家屬註冊為例)
<div class="flex-container">
<img src="https://i.imgur.com/vfgQ66j.png"
width="30%"></div>
#### 1. SignUp1Activity.java
```java=
package com.example.elderlyapp;
import android.content.Intent;
import android.os.Bundle;
import android.util.Patterns;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.gms.tasks.OnCompleteListener;
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.database.FirebaseDatabase;
public class SignUp1Activity extends AppCompatActivity implements View.OnClickListener {
private EditText editTextEmail, editTextPassword, editTextFullName, editTextPhone, editTextElderlyId;
private Button signup;
private FirebaseAuth mAuth;
private FirebaseUser user;
private FirebaseAuth.AuthStateListener mAuthListener;
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up1);
mAuth = FirebaseAuth.getInstance();
signup = (Button) findViewById(R.id.sign_up);
signup.setOnClickListener(this);
editTextEmail = (EditText) findViewById(R.id.email);
editTextPassword = (EditText) findViewById(R.id.password);
editTextFullName = (EditText) findViewById(R.id.fullName);
editTextPhone = (EditText) findViewById(R.id.phone);
editTextElderlyId = (EditText) findViewById(R.id.elderlyid);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
}
@Override
public void onClick(View v) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
switch (v.getId()) {
case R.id.sign_up:
signup();
break;
}
}
private void signup() {
final String email = editTextEmail.getText().toString().trim();
final String password = editTextPassword.getText().toString().trim();
final String fullName = editTextFullName.getText().toString().trim();
final String phone = editTextPhone.getText().toString().trim();
final String elderlyid = editTextElderlyId.getText().toString().trim();
//註冊條件限制
if (email.isEmpty()) {
editTextEmail.setError("Email is required!");
editTextEmail.requestFocus();
return;
}
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
editTextPassword.setError("Please enter a valid email!");
editTextPassword.requestFocus();
return;
}
if (password.isEmpty()) {
editTextPassword.setError("Password is required!");
editTextPassword.requestFocus();
return;
}
if (password.length() < 6) {
editTextPassword.setError("Min Password length is 6 characters!");
editTextPassword.requestFocus();
return;
}
if (fullName.isEmpty()) {
editTextFullName.setError("Please enter your name!");
editTextFullName.requestFocus();
return;
}
if (phone.isEmpty()) {
editTextPhone.setError("Please enter your phone number!");
editTextPhone.requestFocus();
return;
}
if (phone.length() != 10) {
editTextPhone.setError("Please enter a valid phone number!");
editTextPhone.requestFocus();
return;
}
if (elderlyid.isEmpty()) {
editTextElderlyId.setError("Please enter Elderly ID!");
editTextElderlyId.requestFocus();
return;
}
progressBar.setVisibility(View.VISIBLE);
mAuth.createUserWithEmailAndPassword(email, password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
User user = new User(email, fullName, phone, elderlyid);
FirebaseDatabase.getInstance().getReference("家屬")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.setValue(user).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(SignUp1Activity.this, R.string.register_success, Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
Intent intent = new Intent();
intent.setClass(SignUp1Activity.this, Login1Activity.class);
startActivity(intent);
finish();
} else {
Toast.makeText(SignUp1Activity.this, "Failed to register! Try again!", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
}
});
} else {
Toast.makeText(SignUp1Activity.this, "Failed to register! Try again!", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
}
});
}
}
```
#### 2. User.java
##### ★ 建立Firebase資料庫內的項目(例:id、name...等)
```java=
package com.example.elderlyapp;
public class User {
public String email,fullname,phone,elderlyid;
public User(){
}
public User(String email,String fullname,String phone,String elderlyid){
this.email = email;
this.fullname = fullname;
this.phone = phone;
this.elderlyid = elderlyid;
}
}
```
### (二)登入功能
<div class="flex-container">
<img src="https://i.imgur.com/5y9sHwx.png"
width="30%"></div>
#### 1. Login1Activity.java
```java=
package com.example.elderlyapp;
import android.content.Intent;
import android.os.Bundle;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.util.Patterns;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.gms.tasks.OnCompleteListener;
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 static maes.tech.intentanim.CustomIntent.customType;
//import android.support.annotation.NonNull;
//import android.support.design.widget.TextInputLayout;
//import android.support.v7.app.AppCompatActivity;
public class Login1Activity extends AppCompatActivity implements View.OnClickListener {
private TextView forgotPassword;
private EditText editTextEmail,editTextPassword;
private Button signIn;
private Button signUp;
private FirebaseAuth mAuth;
private FirebaseUser user;
private FirebaseAuth.AuthStateListener mAuthListener;
private ProgressBar progressBar;
private CheckBox showpassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login1);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
signIn = (Button) findViewById(R.id.signIn);
signIn.setOnClickListener(this);
signUp = (Button) findViewById(R.id.signUp);
editTextEmail = (EditText) findViewById(R.id.email);
editTextPassword = (EditText) findViewById(R.id.password);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
mAuth = FirebaseAuth.getInstance();
showpassword = (CheckBox) findViewById(R.id.showpassword);
forgotPassword = (TextView) findViewById(R.id.forgotPassword);
forgotPassword.setOnClickListener(this);
showpassword.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean b) {
if(b) {
editTextPassword.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
}
else{
editTextPassword.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
}
});
signUp.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(Login1Activity.this, SignUp1Activity.class); //按signup就要去login畫面
startActivity(intent);
//finish();
}
});
}
@Override
public void onClick(View v){
switch (v.getId()){
case R.id.signIn:
userLogin();
customType(this,"left-to-right");
break;
case R.id.forgotPassword:
startActivity(new Intent(this, ForgotPassword.class));
customType(this,"fadein-to-fadeout");
break;
case R.id.signUp:
startActivity(new Intent(this, SignUp1Activity.class));
break;
}
}
private void userLogin(){
final String email = editTextEmail.getText().toString().trim();
final String password = editTextPassword.getText().toString().trim();
if(email.isEmpty()){
editTextEmail.setError("Email is required!");
editTextEmail.requestFocus();
return;
}
if(!Patterns.EMAIL_ADDRESS.matcher(email).matches()){
editTextPassword.setError("Please enter a valid email!");
editTextPassword.requestFocus();
return;
}
if(password.isEmpty()){
editTextPassword.setError("Password is required!");
editTextPassword.requestFocus();
return;
}
if(password.length()<6){
editTextPassword.setError("Min Password length is 6 characters!");
editTextPassword.requestFocus();
return;
}
progressBar.setVisibility(View.VISIBLE);
mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if(user.isEmailVerified()){
startActivity(new Intent(Login1Activity.this, MainActivity.class));
}else{
user.sendEmailVerification();
Toast.makeText(Login1Activity.this, "Check your email to verity your account!", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
} else {
Toast.makeText(Login1Activity.this,"Failed to login! Please check your credentials", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
}
});
}
}
```
### (三)忘記密碼功能
<div class="flex-container">
<img src="https://i.imgur.com/1YVmEgT.png"
width="30%"></div>
#### 1. ForgotPassword.java
```java=package com.example.elderlyapp;
import android.content.Intent;
import android.os.Bundle;
import android.util.Patterns;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
public class ForgotPassword extends AppCompatActivity {
private TextView banner,bannerDescription;
private EditText emailEditText;
private Button resetPasswordButton;
private ProgressBar progressBar;
FirebaseAuth auth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_forgot_password);
emailEditText = (EditText) findViewById(R.id.email);
resetPasswordButton = (Button) findViewById(R.id.resetPassword);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
auth = FirebaseAuth.getInstance();
resetPasswordButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
resetPassword();
}
});
}
private void resetPassword(){
String email = emailEditText.getText().toString().trim();
if(email.isEmpty()){
emailEditText.setError("Email is required!");
emailEditText.requestFocus();
return;
}
if(!Patterns.EMAIL_ADDRESS.matcher(email).matches()){
emailEditText.setError("Please provide valid email!");
emailEditText.requestFocus();
return;
}
progressBar.setVisibility(View.VISIBLE);
auth.sendPasswordResetEmail(email).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if(task.isSuccessful()) {
Toast.makeText(ForgotPassword.this, "Check your Email to reset your new password!", Toast.LENGTH_LONG).show();
progressBar.setVisibility(View.GONE);
Intent intent = new Intent();
intent.setClass(ForgotPassword.this, HomeActivity.class);
startActivity(intent);
finish();
}else{
Toast.makeText(ForgotPassword.this, "Try again! Something wrong happend!", Toast.LENGTH_LONG).show();
progressBar.setVisibility(View.GONE);
}
}
});
}
}
```
# 參、Realtime Database之使用
## ㄧ、專案網頁設定
#### 1. 點選建立資料庫。
<div class="flex-container">
<img src="https://i.imgur.com/M3NoGAM.png"
width="100%"></div>
#### 2. 位置在此選擇美國後,點選下一步。
<div class="flex-container">
<img src="https://i.imgur.com/ef71vlb.png"
width="100%"></div>
#### 3. 選擇測試模式後,點選啟用。
<div class="flex-container">
<img src="https://i.imgur.com/vFVHrI0.png"
width="100%"></div>
## 二、專案使用之程式碼
### (一)ElderlyActivity.java
:::info
「健康紀錄表/長者清單/排班表」都是同類型的清單功能(新增/刪除/修改),其做法相似,因此以「長者清單功能」做示範。
:::
<div class="flex-container">
<img src="https://i.imgur.com/AF6uDTz.jpg"
width="30%"></div>
#### 1. 長者資料表[搜尋功能]
```java=
package com.example.elderlyapp;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.SearchView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.FirebaseDatabase;
public class ElderlyActivity extends AppCompatActivity {
RecyclerView recview;
myadapter adapter;
ImageView fb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.elderly_main);
setTitle("請輸入長者名字..");
recview=(RecyclerView)findViewById(R.id.recview);
recview.setLayoutManager(new LinearLayoutManager(this));
//<model>清單連動firebase
FirebaseRecyclerOptions<model> options =
new FirebaseRecyclerOptions.Builder<model>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("年長者"),model.class)
.build();
adapter=new myadapter(options);
recview.setAdapter(adapter);
//[新增功能]按鈕
fb=(ImageView) findViewById(R.id.fadd);
fb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) { //導至下一個頁面[AddData.class]
startActivity(new Intent(getApplicationContext(), AddData.class));
}
});
}
@Override
protected void onStart(){
super.onStart();
adapter.startListening();
}
@Override
protected void onStop(){
super.onStop();
adapter.stopListening();
}
//[搜尋功能]
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.searchmenu,menu);
MenuItem item=menu.findItem(R.id.search);
SearchView searchView=(SearchView)item.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String E) {
processsearch(E);
return false;
}
@Override
public boolean onQueryTextChange(String E) {
processsearch(E);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
//目標:透過name來搜尋
//連動firebase->找[年長者]->name
private void processsearch(String E)
{
FirebaseRecyclerOptions<model> options =
new FirebaseRecyclerOptions.Builder<model>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("年長者").orderByChild("name").startAt(E).endAt(E+"\uf8ff"),model.class)
.build();
adapter=new myadapter(options);
adapter.startListening();
recview.setAdapter(adapter);
}
}
```
#### 2. 搜尋功能是去firebase裡抓資料
##### ★ 該範例目標是想搜尋年長者底下的name
<div class="flex-container">
<img src="https://i.imgur.com/ccSmhVS.png"
width="100%"></div>
##### ★ 搜尋結果(以搜尋Jenny為例)
<div class="flex-container">
<img src="https://i.imgur.com/GZOBeN0.png"
width="30%"></div>
### (二)AddData.java
#### 1. 資料表[新增資料]的功能
```
視專案設計需求,自行加入至專案裡。
```
<div class="flex-container">
<img src="https://i.imgur.com/9ps0Xxw.png"
width="30%">
<img src="https://i.imgur.com/HPSS1Nq.png"
width="30%"></div>
```java=
package com.example.elderlyapp;
import android.content.Intent;
import android.os.Bundle;
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.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.database.FirebaseDatabase;
import java.util.HashMap;
import java.util.Map;
public class AddData extends AppCompatActivity
{
EditText id,name,birth,purl,manager1,manager2,manager3,identify;
Button submit,back;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_adddata);
id=(EditText)findViewById(R.id.add_id);
identify=(EditText)findViewById(R.id.add_identify);
name=(EditText)findViewById(R.id.add_name);
birth=(EditText)findViewById(R.id.add_birth);
purl=(EditText)findViewById(R.id.add_purl);
manager1=(EditText)findViewById(R.id.add_manager1);
manager2=(EditText)findViewById(R.id.add_manager2);
manager3=(EditText)findViewById(R.id.add_manager3);
back=(Button)findViewById(R.id.add_back);
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(getApplicationContext(),ElderlyActivity.class));
finish();
}
});
submit=(Button)findViewById(R.id.add_submit);
submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
processinsert();
}
});
}
private void processinsert()
{
Map<String,Object> map=new HashMap<>();
map.put("id",id.getText().toString());
map.put("identify",identify.getText().toString());
map.put("name",name.getText().toString());
map.put("birth",birth.getText().toString());
map.put("purl",purl.getText().toString());
map.put("manager1",manager1.getText().toString());
map.put("manager2",manager2.getText().toString());
map.put("manager3",manager3.getText().toString());
FirebaseDatabase.getInstance().getReference().child("年長者").push()
.setValue(map)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
id.setText("");
identify.setText("");
name.setText("");
birth.setText("");
purl.setText("");
manager1.setText("");
manager2.setText("");
manager3.setText("");
Toast.makeText(getApplicationContext(),"新增成功",Toast.LENGTH_LONG).show();
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e)
{
Toast.makeText(getApplicationContext(),"新增失敗,請再試一次",Toast.LENGTH_LONG).show();
}
});
}
}
```
### (三)model.java
#### 1. 建立Firebase資料庫內的項目 (例 : id、name...等)
```java=
package com.example.elderlyapp;
public class model {
String id,name,birth,purl,manager1,manager2;
model()
{
}
public model(String id, String name, String birth, String purl, String manager1, String manager2) {
this.id = id;
this.name = name;
this.birth = birth;
this.purl = purl;
this.manager1 = manager1;
this.manager2 = manager2;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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;
}
public String getPurl() {
return purl;
}
public void setPurl(String purl) {
this.purl = purl;
}
public String getManager1() {
return manager1;
}
public void setManager1(String manager1) {
this.manager1 = manager1;
}
public String getManager2() {
return manager2;
}
public void setManager2(String manager2) {
this.manager2 = manager2;
}
}
```
#### 2. 呈現結果
<div class="flex-container">
<img src="https://i.imgur.com/w6HtzLC.png"
width="100%"></div>
### (四)myadapter.java
#### 1. 資料表[編輯資料/刪除資料]的功能
<div class="flex-container">
<img src="https://i.imgur.com/yjI0cP2.png"
width="30%">
<img src="https://i.imgur.com/7OYsXTU.png"
width="30%"></div>
``` java=
package com.example.elderlyapp;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.database.FirebaseDatabase;
import com.orhanobut.dialogplus.DialogPlus;
import com.orhanobut.dialogplus.ViewHolder;
import java.util.HashMap;
import java.util.Map;
import de.hdodenhof.circleimageview.CircleImageView;
//[長者清單的按鈕功能(編輯、刪除)]
public class myadapter extends FirebaseRecyclerAdapter<model,myadapter.myviewholder>
{
public myadapter(@NonNull FirebaseRecyclerOptions<model> options) {
super(options);
}
@Override
protected void onBindViewHolder(@NonNull final myviewholder holder, final int position, @NonNull final model model)
{
holder.id.setText(model.getId());
holder.identify.setText(model.getIdentify());
holder.name.setText(model.getName());
holder.birth.setText(model.getBirth());
holder.manager1.setText(model.getManager1());
holder.manager2.setText(model.getManager2());
holder.manager3.setText(model.getManager3());
Glide.with(holder.img.getContext()).load(model.getPurl()).into(holder.img);
//[功能]:編輯長者資料
holder.edit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final DialogPlus dialogPlus=DialogPlus.newDialog(holder.img.getContext())
.setContentHolder(new ViewHolder(R.layout.dialogcontent))
.setExpanded(true,1100)
.create();
View myview=dialogPlus.getHolderView();
final EditText purl=myview.findViewById(R.id.uimgurl);
final EditText id=myview.findViewById(R.id.uid);
final EditText identify=myview.findViewById(R.id.uidentify);
final EditText name=myview.findViewById(R.id.uname);
final EditText birth=myview.findViewById(R.id.ubirth);
final EditText manager1=myview.findViewById(R.id.umanager1);
final EditText manager2=myview.findViewById(R.id.umanager2);
final EditText manager3=myview.findViewById(R.id.umanager3);
Button submit=myview.findViewById(R.id.usubmit);
purl.setText(model.getPurl());
id.setText(model.getId());
identify.setText(model.getIdentify());
name.setText(model.getName());
birth.setText(model.getBirth());
manager1.setText(model.getManager1());
manager2.setText(model.getManager2());
manager3.setText(model.getManager3());
dialogPlus.show();
////長者資料編輯完送出
submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Map<String,Object> map=new HashMap<>();
map.put("purl",purl.getText().toString());
map.put("id",id.getText().toString());
map.put("identify",identify.getText().toString());
map.put("birth",birth.getText().toString());
map.put("name",name.getText().toString());
map.put("manager1",manager1.getText().toString());
map.put("manager2",manager2.getText().toString());
map.put("manager3",manager3.getText().toString());
FirebaseDatabase.getInstance().getReference().child("年長者")
.child(getRef(position).getKey()).updateChildren(map)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
dialogPlus.dismiss();
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
dialogPlus.dismiss();
}
});
}
});
}
});
//[功能]:刪除長者資料
holder.delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(holder.img.getContext());
builder.setTitle("刪除資料");
builder.setMessage("確定刪除?");
builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
FirebaseDatabase.getInstance().getReference().child("年長者")
.child(getRef(position).getKey()).removeValue();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
builder.show();
}
});
} // End of OnBindViewMethod
@NonNull
@Override
public myviewholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
{
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.singlerow,parent,false);
return new myviewholder(view);
}
class myviewholder extends RecyclerView.ViewHolder
{
CircleImageView img;
TextView id,name,birth,manager1,manager2,manager3,identify;
ImageView edit,delete;
public myviewholder(@NonNull View itemView)
{
super(itemView);
img=(CircleImageView)itemView.findViewById(R.id.img1);
id=(TextView)itemView.findViewById(R.id.idtext);
identify=(TextView)itemView.findViewById(R.id.identifytext);
name=(TextView)itemView.findViewById(R.id.nametext);
birth=(TextView)itemView.findViewById(R.id.birthtext);
manager1=(TextView)itemView.findViewById(R.id.manager1text);
manager2=(TextView)itemView.findViewById(R.id.manager2text);
manager3=(TextView)itemView.findViewById(R.id.manager3text);
edit=(ImageView)itemView.findViewById(R.id.editicon);
delete=(ImageView)itemView.findViewById(R.id.deleteicon);
}
}
}
```
### (五) 客服功能(一鍵撥電話/傳信箱)
<div class="flex-container">
<img src="https://i.imgur.com/YXjfe4G.png"
width="30%">
</div>
### 1. ContactActivity.java
#### ★ 功能 : 點擊圖示直接撥電話/傳mail
``` java=
package com.example.elderlyapp;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class ContactActivity extends AppCompatActivity {
//private static final int REQUEST_CALL = 1;
ImageView emailMe1;
ImageView emailMe2;
ImageView emailMe3;
ImageView emailMe4;
ImageView emailMe5;
ImageView emailMe6;
ImageView callMe1;
ImageView callMe2;
ImageView callMe3;
ImageView callMe4;
ImageView callMe5;
ImageView callMe6;
TextView callText1;
TextView callText2;
TextView callText3;
TextView callText4;
TextView callText5;
TextView callText6;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact);
emailMe1 = (ImageView) findViewById(R.id.emailMe1);
emailMe2 = (ImageView) findViewById(R.id.emailMe2);
emailMe3 = (ImageView) findViewById(R.id.emailMe3);
emailMe4 = (ImageView) findViewById(R.id.emailMe4);
emailMe5 = (ImageView) findViewById(R.id.emailMe5);
emailMe6 = (ImageView) findViewById(R.id.emailMe6);
callMe1 = (ImageView) findViewById(R.id.callMe1);
callMe2 = (ImageView) findViewById(R.id.callMe2);
callMe3 = (ImageView) findViewById(R.id.callMe3);
callMe4 = (ImageView) findViewById(R.id.callMe4);
callMe5 = (ImageView) findViewById(R.id.callMe5);
callMe6 = (ImageView) findViewById(R.id.callMe6);
callText1 = (TextView) findViewById(R.id.callText1);
callText2 = (TextView) findViewById(R.id.callText2);
callText3 = (TextView) findViewById(R.id.callText3);
callText4 = (TextView) findViewById(R.id.callText4);
callText5 = (TextView) findViewById(R.id.callText5);
callText6 = (TextView) findViewById(R.id.callText6);
emailMe1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:a107000001@mail.shu.edu.tw"));
startActivity(intent);
}
});
emailMe2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:a107000002@mail.shu.edu.tw"));
startActivity(intent);
}
});
emailMe3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:a107000003@mail.shu.edu.tw"));
startActivity(intent);
}
});
emailMe4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:a111111111@mail.shu.edu.tw"));
startActivity(intent);
}
});
emailMe5.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:a222222222@mail.shu.edu.tw"));
startActivity(intent);
}
});
emailMe6.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:a333333333@mail.shu.edu.tw"));
startActivity(intent);
}
});
callMe1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("tel:0900000001"));
startActivity(intent);
}
});
callMe2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("tel:0900000002"));
startActivity(intent);
}
});
callMe3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("tel:0900000003"));
startActivity(intent);
}
});
callMe4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("tel:0911111111"));
startActivity(intent);
}
});
callMe5.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("tel:0922222222"));
startActivity(intent);
}
});
callMe6.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("tel:0933333333"));
startActivity(intent);
}
});
}
}
```
### (六) Android接收yolov5即時動作偵測
<div class="flex-container">
<img src="https://i.imgur.com/Esx6Wz7.png"
width="30%">
</div>
### 1. CameraActivity2.java
#### ★ [搜尋功能] : movement底下的id
``` java=
package com.example.elderlyapp;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.SearchView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.FirebaseDatabase;
//長照員
public class CameraActivity2 extends AppCompatActivity {
RecyclerView recview;
myadapter3 adapter;
//VideoView videoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_main2);
setTitle("請輸入長者id..");
recview=(RecyclerView)findViewById(R.id.recview);
recview.setLayoutManager(new LinearLayoutManager(this));
FirebaseRecyclerOptions<Cameramodel2> options =
new FirebaseRecyclerOptions.Builder<Cameramodel2>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("movement"), Cameramodel2.class)
.build();
adapter=new myadapter3(options);
recview.setAdapter(adapter);
}
@Override
protected void onStart(){
super.onStart();
adapter.startListening();
}
@Override
protected void onStop(){
super.onStop();
adapter.stopListening();
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.searchmenu,menu);
MenuItem item=menu.findItem(R.id.search);
SearchView searchView=(SearchView)item.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String E) {
processsearch(E);
return false;
}
@Override
public boolean onQueryTextChange(String E) {
processsearch(E);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
private void processsearch(String E)
{
FirebaseRecyclerOptions<Cameramodel2> options =
new FirebaseRecyclerOptions.Builder<Cameramodel2>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("movement").orderByChild("ID").startAt(E).endAt(E+"\uf8ff"), Cameramodel2.class)
.build();
adapter=new myadapter3(options);
adapter.startListening();
recview.setAdapter(adapter);
}
}
```
#### ★ ( 目標 : 搜尋movement底下的 id )
<div class="flex-container">
<img src="https://i.imgur.com/9uAVbEo.png"
width="100%">
</div>
### 2. myadapter3.java
#### ★ RecyclerView 清單
``` java=
package com.example.elderlyapp;
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.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
public class myadapter3 extends FirebaseRecyclerAdapter<Cameramodel2,myadapter3.myviewholder>
{
public myadapter3(@NonNull FirebaseRecyclerOptions<Cameramodel2> options) {
super(options);
}
@Override
protected void onBindViewHolder(@NonNull final myviewholder holder, final int position, @NonNull final Cameramodel2 model) {
holder.ID.setText(model.getID());
holder.movement.setText(model.getMovement());
holder.name.setText(model.getName());
holder.times.setText(model.getTimes());
}
@NonNull
@Override
public myviewholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
{
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.singlerow5,parent,false);
return new myviewholder(view);
}
class myviewholder extends RecyclerView.ViewHolder
{
TextView ID,name,movement,times;
public myviewholder(@NonNull View itemView)
{
super(itemView);
ID=(TextView)itemView.findViewById(R.id.idtext);
movement=(TextView)itemView.findViewById(R.id.movementtext);
name=(TextView)itemView.findViewById(R.id.nametext);
times=(TextView)itemView.findViewById(R.id.timestext);
}
}
}
```
### 3. Cameramodel.java
#### ★ 建立Firebase資料庫內的項目 (id、name、movement、times)
``` java=
package com.example.elderlyapp;
public class Cameramodel{
String ID,name,movement,times;
Cameramodel()
{
}
public Cameramodel(String ID, String name, String movement, String times) {
this.ID = ID;
this.name = name;
this.movement = movement;
this.times = times;
}
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID = ID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMovement() {
return movement;
}
public void setMovement(String movement) {
this.movement = movement;
}
public String getTimes() {
return times;
}
public void setTimes(String times) {
this.times = times;
}
}
```
# 肆、Google 地圖應用
## 一、[啟用 API 或 SDK](https://developers.google.com/maps/gmp-get-started?hl=zh_tw)
# 參考資料
安裝Android Studio步驟:
https://ithelp.ithome.com.tw/articles/10200176
註冊/登入:
https://www.youtube.com/watch?v=Z-RE1QuUWPg
清單新增/刪除/修改:
https://www.youtube.com/watch?v=Do4tOzFk3jc
https://www.youtube.com/watch?v=8KGN1272iuk