From 77c393a191aff6480c16cd304c1428552ecf9372 Mon Sep 17 00:00:00 2001 From: phanhuuloi27 <73208452+Nezumi2711@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:22:29 +0700 Subject: [PATCH] Fix Notification --- Foodify/app/build.gradle | 8 +- Foodify/app/src/main/AndroidManifest.xml | 21 +++- .../main/java/com/waterbase/foodify/Cart.java | 70 +++++++++++- .../com/waterbase/foodify/Common/Common.java | 8 ++ .../main/java/com/waterbase/foodify/Home.java | 17 ++- .../waterbase/foodify/Model/MyResponse.java | 11 ++ .../waterbase/foodify/Model/Notification.java | 27 +++++ .../com/waterbase/foodify/Model/Result.java | 5 + .../com/waterbase/foodify/Model/Sender.java | 11 ++ .../com/waterbase/foodify/Model/Token.java | 31 ++++++ .../waterbase/foodify/Remote/APIService.java | 24 ++++ .../foodify/Remote/RetrofitClient.java | 20 ++++ .../foodify/Service/ListenOrder.java | 105 ------------------ .../foodify/Service/MyFirebaseIdService.java | 25 +++++ .../foodify/Service/MyFirebaseMessaging.java | 57 ++++++++++ FoodifyServer/app/build.gradle | 17 +-- .../app/src/main/AndroidManifest.xml | 20 +++- .../foodifyServer/Common/Common.java | 7 ++ .../com/waterbase/foodifyServer/Home.java | 15 ++- .../foodifyServer/Model/MyResponse.java | 11 ++ .../foodifyServer/Model/Notification.java | 27 +++++ .../waterbase/foodifyServer/Model/Result.java | 5 + .../waterbase/foodifyServer/Model/Sender.java | 11 ++ .../waterbase/foodifyServer/Model/Token.java | 27 +++++ .../waterbase/foodifyServer/OrderStatus.java | 73 +++++++++++- .../foodifyServer/Remote/APIService.java | 24 ++++ .../foodifyServer/Service/ListenOrder.java | 105 ------------------ .../Service/MyFirebaseIdService.java | 25 +++++ .../Service/MyFirebaseMessaging.java | 56 ++++++++++ 29 files changed, 614 insertions(+), 249 deletions(-) create mode 100644 Foodify/app/src/main/java/com/waterbase/foodify/Model/MyResponse.java create mode 100644 Foodify/app/src/main/java/com/waterbase/foodify/Model/Notification.java create mode 100644 Foodify/app/src/main/java/com/waterbase/foodify/Model/Result.java create mode 100644 Foodify/app/src/main/java/com/waterbase/foodify/Model/Sender.java create mode 100644 Foodify/app/src/main/java/com/waterbase/foodify/Model/Token.java create mode 100644 Foodify/app/src/main/java/com/waterbase/foodify/Remote/APIService.java create mode 100644 Foodify/app/src/main/java/com/waterbase/foodify/Remote/RetrofitClient.java delete mode 100644 Foodify/app/src/main/java/com/waterbase/foodify/Service/ListenOrder.java create mode 100644 Foodify/app/src/main/java/com/waterbase/foodify/Service/MyFirebaseIdService.java create mode 100644 Foodify/app/src/main/java/com/waterbase/foodify/Service/MyFirebaseMessaging.java create mode 100644 FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/MyResponse.java create mode 100644 FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Notification.java create mode 100644 FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Result.java create mode 100644 FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Sender.java create mode 100644 FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Token.java create mode 100644 FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Remote/APIService.java delete mode 100644 FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Service/ListenOrder.java create mode 100644 FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Service/MyFirebaseIdService.java create mode 100644 FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Service/MyFirebaseMessaging.java diff --git a/Foodify/app/build.gradle b/Foodify/app/build.gradle index f85c09a..d29a3e0 100644 --- a/Foodify/app/build.gradle +++ b/Foodify/app/build.gradle @@ -43,22 +43,28 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' implementation 'androidx.navigation:navigation-fragment:2.3.5' implementation 'androidx.navigation:navigation-ui:2.3.5' - implementation 'com.google.firebase:firebase-auth:11.8.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' //Add library + implementation 'com.google.firebase:firebase-messaging:11.8.0' implementation 'com.google.firebase:firebase-core:11.8.0' implementation 'com.google.firebase:firebase-database:11.8.0' + implementation 'com.google.firebase:firebase-auth:11.8.0' + implementation 'com.github.jd-alexander:android-flat-button:v1.1' implementation 'com.rengwuxian.materialedittext:library:2.1.4' implementation 'com.stepstone.apprating:app-rating:2.0.0' + implementation 'com.squareup.retrofit2:retrofit:2.7.1' + implementation 'com.squareup.retrofit2:converter-gson:2.7.1' implementation 'com.squareup.picasso:picasso:2.5.2' implementation 'com.firebaseui:firebase-ui-database:1.2.0' implementation 'io.paperdb:paperdb:2.1' implementation 'com.github.rey5137:material:1.2.4' + + implementation 'com.squareup.okhttp3:okhttp:4.9.2' } apply plugin: 'com.google.gms.google-services' \ No newline at end of file diff --git a/Foodify/app/src/main/AndroidManifest.xml b/Foodify/app/src/main/AndroidManifest.xml index b310de7..f6e8f83 100644 --- a/Foodify/app/src/main/AndroidManifest.xml +++ b/Foodify/app/src/main/AndroidManifest.xml @@ -27,11 +27,6 @@ android:name=".VerifyPhone" android:exported="false" /> - - @@ -53,7 +48,6 @@ android:name=".SignUp" android:exported="false" android:theme="@style/Theme.Foodify.NoActionBar" /> - /> + + + + + + + + + + + + + \ No newline at end of file diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Cart.java b/Foodify/app/src/main/java/com/waterbase/foodify/Cart.java index 62bee79..a2fb8fc 100644 --- a/Foodify/app/src/main/java/com/waterbase/foodify/Cart.java +++ b/Foodify/app/src/main/java/com/waterbase/foodify/Cart.java @@ -9,6 +9,7 @@ import androidx.recyclerview.widget.RecyclerView; import android.content.DialogInterface; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; @@ -17,13 +18,22 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; +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.Query; +import com.google.firebase.database.ValueEventListener; import com.rengwuxian.materialedittext.MaterialEditText; import com.waterbase.foodify.Common.Common; import com.waterbase.foodify.Database.Database; +import com.waterbase.foodify.Model.MyResponse; +import com.waterbase.foodify.Model.Notification; import com.waterbase.foodify.Model.Order; import com.waterbase.foodify.Model.Request; +import com.waterbase.foodify.Model.Sender; +import com.waterbase.foodify.Model.Token; +import com.waterbase.foodify.Remote.APIService; import com.waterbase.foodify.ViewHolder.CartAdapter; import java.text.NumberFormat; @@ -32,6 +42,9 @@ import java.util.List; import java.util.Locale; import info.hoang8f.widget.FButton; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; public class Cart extends AppCompatActivity { @@ -47,11 +60,16 @@ public class Cart extends AppCompatActivity { List cart = new ArrayList<>(); CartAdapter adapter; + APIService mService; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_cart); + //Init + mService = Common.getFCMService(); + //Firebase database = FirebaseDatabase.getInstance(); requests = database.getReference("Requests"); @@ -116,12 +134,15 @@ public class Cart extends AppCompatActivity { //Summit to Firebase //We will using System.CurrentMilli to key - requests.child(String.valueOf(System.currentTimeMillis())).setValue(request); + String order_number = String.valueOf(System.currentTimeMillis()); + requests.child(order_number).setValue(request); + + sendNotificationOrder(order_number); //Delete Cart - new Database(getBaseContext()).cleanCart(); - Toast.makeText(Cart.this, "Đặt hàng thành công!", Toast.LENGTH_SHORT).show(); - finish(); +// new Database(getBaseContext()).cleanCart(); +// Toast.makeText(Cart.this, "Đặt hàng thành công!", Toast.LENGTH_SHORT).show(); +// finish(); } }); @@ -135,6 +156,47 @@ public class Cart extends AppCompatActivity { alertDialog.show(); } + private void sendNotificationOrder(String order_number) { + DatabaseReference tokens = FirebaseDatabase.getInstance().getReference("Tokens"); + Query data = tokens.orderByChild("serverToken").equalTo(true); //Get all node with isServerToken is true; + data.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + for(DataSnapshot postSnapShot: dataSnapshot.getChildren()){ + + Token serverToken = postSnapShot.getValue(Token.class); + + //Create raw payload to send + Notification notification = new Notification("Foodify", "Bạn có 1 đơn hàng mới " + order_number); + Sender content = new Sender(serverToken.getToken(), notification); + + mService.sendNotification(content) + .enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if(response.body().success == 1){ + Toast.makeText(Cart.this, "Đặt hàng thành công!", Toast.LENGTH_SHORT).show(); + finish(); + } else { + Toast.makeText(Cart.this, "Hệ thống bị lỗi. Vui lòng thử lại sau!", Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + Log.e("ERROR", t.getMessage()); + } + }); + } + } + + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }); + } + private void loadListFood() { cart = new Database(this).getCarts(); adapter = new CartAdapter(cart, this); diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Common/Common.java b/Foodify/app/src/main/java/com/waterbase/foodify/Common/Common.java index 843fec9..f858c5e 100644 --- a/Foodify/app/src/main/java/com/waterbase/foodify/Common/Common.java +++ b/Foodify/app/src/main/java/com/waterbase/foodify/Common/Common.java @@ -5,10 +5,18 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import com.waterbase.foodify.Model.User; +import com.waterbase.foodify.Remote.APIService; +import com.waterbase.foodify.Remote.RetrofitClient; public class Common { public static User currentUser; + private static final String BASE_URL = "https://fcm.googleapis.com/"; + + public static APIService getFCMService(){ + return RetrofitClient.getClient(BASE_URL).create(APIService.class); + } + public static final String DELETE = "Xoá"; public static final String USER_KEY = "User"; public static final String PWD_KEY = "Password"; diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Home.java b/Foodify/app/src/main/java/com/waterbase/foodify/Home.java index 33a393b..08476ae 100644 --- a/Foodify/app/src/main/java/com/waterbase/foodify/Home.java +++ b/Foodify/app/src/main/java/com/waterbase/foodify/Home.java @@ -2,8 +2,6 @@ package com.waterbase.foodify; import android.content.Intent; import android.os.Bundle; -import android.os.Debug; -import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -24,11 +22,12 @@ import com.firebase.ui.database.FirebaseRecyclerAdapter; import com.google.android.material.navigation.NavigationView; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.iid.FirebaseInstanceId; import com.squareup.picasso.Picasso; import com.waterbase.foodify.Common.Common; import com.waterbase.foodify.Interface.ItemClickListener; import com.waterbase.foodify.Model.Category; -import com.waterbase.foodify.Service.ListenOrder; +import com.waterbase.foodify.Model.Token; import com.waterbase.foodify.ViewHolder.MenuViewHolder; import io.paperdb.Paper; @@ -89,9 +88,15 @@ public class Home extends AppCompatActivity implements NavigationView.OnNavigati TextView navUserName = (TextView) headerView.findViewById(R.id.txtFullName); navUserName.setText(Common.currentUser.getName()); - //Register Service - Intent service = new Intent(Home.this, ListenOrder.class); - startService(service); + updateToken(FirebaseInstanceId.getInstance().getToken()); + + } + + private void updateToken(String token) { + FirebaseDatabase db = FirebaseDatabase.getInstance(); + DatabaseReference tokens = db.getReference("Tokens"); + Token data = new Token(token, false); + tokens.child(Common.currentUser.getPhone()).setValue(data); } private void loadMenu() { diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Model/MyResponse.java b/Foodify/app/src/main/java/com/waterbase/foodify/Model/MyResponse.java new file mode 100644 index 0000000..9e2fd58 --- /dev/null +++ b/Foodify/app/src/main/java/com/waterbase/foodify/Model/MyResponse.java @@ -0,0 +1,11 @@ +package com.waterbase.foodify.Model; + +import java.util.List; + +public class MyResponse { + public long multicast_id; + public int success; + public int failure; + public int canonical_ids; + public List results; +} diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Model/Notification.java b/Foodify/app/src/main/java/com/waterbase/foodify/Model/Notification.java new file mode 100644 index 0000000..1708ae9 --- /dev/null +++ b/Foodify/app/src/main/java/com/waterbase/foodify/Model/Notification.java @@ -0,0 +1,27 @@ +package com.waterbase.foodify.Model; + +public class Notification { + public String body; + public String title; + + public Notification(String body, String title) { + this.body = body; + this.title = title; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Model/Result.java b/Foodify/app/src/main/java/com/waterbase/foodify/Model/Result.java new file mode 100644 index 0000000..11903be --- /dev/null +++ b/Foodify/app/src/main/java/com/waterbase/foodify/Model/Result.java @@ -0,0 +1,5 @@ +package com.waterbase.foodify.Model; + +public class Result { + public String message_id; +} diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Model/Sender.java b/Foodify/app/src/main/java/com/waterbase/foodify/Model/Sender.java new file mode 100644 index 0000000..faa7a1d --- /dev/null +++ b/Foodify/app/src/main/java/com/waterbase/foodify/Model/Sender.java @@ -0,0 +1,11 @@ +package com.waterbase.foodify.Model; + +public class Sender { + public String to; + public Notification notification; + + public Sender(String to, Notification notification) { + this.to = to; + this.notification = notification; + } +} \ No newline at end of file diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Model/Token.java b/Foodify/app/src/main/java/com/waterbase/foodify/Model/Token.java new file mode 100644 index 0000000..2116346 --- /dev/null +++ b/Foodify/app/src/main/java/com/waterbase/foodify/Model/Token.java @@ -0,0 +1,31 @@ +package com.waterbase.foodify.Model; + +public class Token { + + private String token; + private boolean isServerToken; + + public Token() { + } + + public Token(String token, boolean isServerToken) { + this.token = token; + this.isServerToken = isServerToken; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public boolean isServerToken() { + return isServerToken; + } + + public void setServerToken(boolean serverToken) { + isServerToken = serverToken; + } +} diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Remote/APIService.java b/Foodify/app/src/main/java/com/waterbase/foodify/Remote/APIService.java new file mode 100644 index 0000000..1e8ebc4 --- /dev/null +++ b/Foodify/app/src/main/java/com/waterbase/foodify/Remote/APIService.java @@ -0,0 +1,24 @@ +package com.waterbase.foodify.Remote; + +import com.waterbase.foodify.Model.MyResponse; +import com.waterbase.foodify.Model.Sender; + +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.Headers; +import retrofit2.http.POST; + +public interface APIService { + + @Headers( + + { + "Content-Type:application/json", + "Authorization:key=AAAAvBRs8TM:APA91bGQ-HvHMz4_UxiTsq4wY9H9j_ScuMRGOd03BYpQ4RKTuGpN_5CPhtQwycJaVCWMaS2T5S850QgUBhWZauOeM5aVeZsW3VGk1sXFu5GnlOgk2ev0VjzkK8fDsV4mO8D8k5uIknsC" + } + ) + + + @POST("fcm/send") + Call sendNotification(@Body Sender body); +} diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Remote/RetrofitClient.java b/Foodify/app/src/main/java/com/waterbase/foodify/Remote/RetrofitClient.java new file mode 100644 index 0000000..77b9351 --- /dev/null +++ b/Foodify/app/src/main/java/com/waterbase/foodify/Remote/RetrofitClient.java @@ -0,0 +1,20 @@ +package com.waterbase.foodify.Remote; + +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + + +public class RetrofitClient { + private static Retrofit retrofit = null; + + public static Retrofit getClient(String baseURL) + { + if(retrofit == null) { + retrofit = new Retrofit.Builder() + .baseUrl(baseURL) + .addConverterFactory(GsonConverterFactory.create()) + .build(); + } + return retrofit; + } +} diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Service/ListenOrder.java b/Foodify/app/src/main/java/com/waterbase/foodify/Service/ListenOrder.java deleted file mode 100644 index f316c14..0000000 --- a/Foodify/app/src/main/java/com/waterbase/foodify/Service/ListenOrder.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.waterbase.foodify.Service; - -import android.app.Notification; -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.Build; -import android.os.IBinder; - -import androidx.core.app.NotificationCompat; - -import com.google.firebase.database.ChildEventListener; -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.waterbase.foodify.Common.Common; -import com.waterbase.foodify.Model.Request; -import com.waterbase.foodify.OrderStatus; -import com.waterbase.foodify.R; - -public class ListenOrder extends Service implements ChildEventListener { - - FirebaseDatabase db; - DatabaseReference requests; - - public ListenOrder() { - } - - @Override - public IBinder onBind(Intent intent) { - return null; - } - - @Override - public void onCreate() { - super.onCreate(); - db = FirebaseDatabase.getInstance(); - requests = db.getReference("Requests"); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - requests.addChildEventListener(this); - return super.onStartCommand(intent, flags, startId); - } - - @Override - public void onChildAdded(DataSnapshot dataSnapshot, String s) { - - } - - @Override - public void onChildChanged(DataSnapshot dataSnapshot, String s) { - Request request = dataSnapshot.getValue(Request.class); - showNotification(dataSnapshot.getKey(), request); - } - - private void showNotification(String key, Request request) { - Intent intent=new Intent(getBaseContext(), OrderStatus.class); - intent.putExtra("userPhone",request.getPhone()); //we need put user phone - PendingIntent contentIntent=PendingIntent - .getActivity(getBaseContext(),0,intent,PendingIntent.FLAG_UPDATE_CURRENT); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ - NotificationChannel channel= - new NotificationChannel("foodStatus","foodStatus",NotificationManager.IMPORTANCE_DEFAULT); - NotificationManager notificationManager=getSystemService(NotificationManager.class); - notificationManager.createNotificationChannel(channel); - - } - - NotificationCompat.Builder builder=new NotificationCompat.Builder(getBaseContext(),"foodStatus"); - builder.setAutoCancel(true) - .setDefaults(Notification.DEFAULT_ALL) - .setWhen(System.currentTimeMillis()) - .setTicker("food") - .setContentInfo("Tình trạng đơn hàng của bạn đã được cập nhật") - .setContentText("Đơn hàng #"+key+" đã cập nhật thành "+ Common.convertCodeToStatus(request.getStatus())) - .setContentIntent(contentIntent) - .setContentInfo("Thông tin") - .setSmallIcon(R.mipmap.ic_launcher); - - NotificationManager notificationManager=(NotificationManager)getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.notify(1,builder.build()); - } - - @Override - public void onChildRemoved(DataSnapshot dataSnapshot) { - - } - - @Override - public void onChildMoved(DataSnapshot dataSnapshot, String s) { - - } - - @Override - public void onCancelled(DatabaseError databaseError) { - - } -} \ No newline at end of file diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Service/MyFirebaseIdService.java b/Foodify/app/src/main/java/com/waterbase/foodify/Service/MyFirebaseIdService.java new file mode 100644 index 0000000..dafcfd7 --- /dev/null +++ b/Foodify/app/src/main/java/com/waterbase/foodify/Service/MyFirebaseIdService.java @@ -0,0 +1,25 @@ +package com.waterbase.foodify.Service; + +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.iid.FirebaseInstanceId; +import com.google.firebase.iid.FirebaseInstanceIdService; +import com.waterbase.foodify.Common.Common; +import com.waterbase.foodify.Model.Token; + +public class MyFirebaseIdService extends FirebaseInstanceIdService { + + @Override + public void onTokenRefresh() { + super.onTokenRefresh(); + String tokenRefreshed = FirebaseInstanceId.getInstance().getToken(); + updateTokenToFirebase(tokenRefreshed); + } + + private void updateTokenToFirebase(String tokenRefreshed) { + FirebaseDatabase db = FirebaseDatabase.getInstance(); + DatabaseReference tokens = db.getReference("Tokens"); + Token token = new Token(tokenRefreshed, false); + tokens.child(Common.currentUser.getPhone()).setValue(token); + } +} diff --git a/Foodify/app/src/main/java/com/waterbase/foodify/Service/MyFirebaseMessaging.java b/Foodify/app/src/main/java/com/waterbase/foodify/Service/MyFirebaseMessaging.java new file mode 100644 index 0000000..690f891 --- /dev/null +++ b/Foodify/app/src/main/java/com/waterbase/foodify/Service/MyFirebaseMessaging.java @@ -0,0 +1,57 @@ +package com.waterbase.foodify.Service; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Build; +import android.util.Log; + +import androidx.core.app.NotificationCompat; + +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; +import com.waterbase.foodify.Home; +import com.waterbase.foodify.R; + +public class MyFirebaseMessaging extends FirebaseMessagingService { + + @Override + public void onMessageReceived(RemoteMessage remoteMessage) { + super.onMessageReceived(remoteMessage); + showNotification(remoteMessage); + Log.e("INFO", remoteMessage.getNotification().getBody()); + } + + private void showNotification(RemoteMessage remoteMessage) { + RemoteMessage.Notification notification = remoteMessage.getNotification(); + Intent intent = new Intent(this, Home.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ + NotificationChannel channel= + new NotificationChannel("foodStatus","foodStatus",NotificationManager.IMPORTANCE_DEFAULT); + NotificationManager notificationManager=getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); + } + + Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); + + NotificationCompat.Builder builder=new NotificationCompat.Builder(getBaseContext(),"foodStatus"); + builder.setAutoCancel(true) + .setDefaults(Notification.DEFAULT_ALL) + .setContentText(notification.getBody()) + .setContentIntent(pendingIntent) + .setContentTitle(notification.getTitle()) + .setSound(defaultSoundUri) + .setSmallIcon(R.mipmap.ic_launcher_round); + + NotificationManager notificationManager=(NotificationManager)getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.notify(1,builder.build()); + } +} diff --git a/FoodifyServer/app/build.gradle b/FoodifyServer/app/build.gradle index ca7d8bc..a58eb35 100644 --- a/FoodifyServer/app/build.gradle +++ b/FoodifyServer/app/build.gradle @@ -46,20 +46,23 @@ dependencies { //Add library - implementation 'com.google.firebase:firebase-core:10.2.0' - implementation 'com.google.firebase:firebase-database:10.2.0' + implementation 'com.google.firebase:firebase-core:11.8.0' + implementation 'com.google.firebase:firebase-database:11.8.0' implementation 'com.firebaseui:firebase-ui-database:1.2.0' implementation 'com.squareup.picasso:picasso:2.5.2' - implementation 'com.google.firebase:firebase-auth:10.2.0' - implementation 'com.google.firebase:firebase-storage:10.2.0' + implementation 'com.google.firebase:firebase-auth:11.8.0' + implementation 'com.google.firebase:firebase-storage:11.8.0' implementation 'com.github.jd-alexander:android-flat-button:v1.1' implementation 'com.rengwuxian.materialedittext:library:2.1.4' implementation 'com.jaredrummler:material-spinner:1.1.0' - implementation 'com.google.android.gms:play-services-maps:10.2.0' - implementation 'com.google.android.gms:play-services:10.2.0' + implementation 'com.google.android.gms:play-services-maps:11.8.0' + implementation 'com.google.android.gms:play-services:11.8.0' implementation 'com.squareup.retrofit2:retrofit:2.3.0' - implementation 'com.squareup.retrofit2:converter-scalars:2.1.0' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.3.0' + implementation 'com.google.firebase:firebase-messaging:11.8.0' + } apply plugin: 'com.google.gms.google-services' \ No newline at end of file diff --git a/FoodifyServer/app/src/main/AndroidManifest.xml b/FoodifyServer/app/src/main/AndroidManifest.xml index 88dbf8a..882285b 100644 --- a/FoodifyServer/app/src/main/AndroidManifest.xml +++ b/FoodifyServer/app/src/main/AndroidManifest.xml @@ -20,11 +20,6 @@ android:name=".OrderDetail" android:exported="false" /> - - @@ -70,6 +65,21 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Common/Common.java b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Common/Common.java index 4f5d5cf..1fac2f2 100644 --- a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Common/Common.java +++ b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Common/Common.java @@ -7,6 +7,7 @@ import android.graphics.Paint; import com.waterbase.foodifyServer.Model.Request; import com.waterbase.foodifyServer.Model.User; +import com.waterbase.foodifyServer.Remote.APIService; import com.waterbase.foodifyServer.Remote.IGeoCoordinates; import com.waterbase.foodifyServer.Remote.RetrofitClient; @@ -20,6 +21,12 @@ public class Common { public static final String baseUrl = "https://maps.googleapis.com"; + private static final String fcmUrl = "https://fcm.googleapis.com/"; + + public static APIService getFCMClient(){ + return RetrofitClient.getClient(fcmUrl).create(APIService.class); + } + public static String coverCodeToStatus(String code){ if(code.equals("0")) return "Placed"; diff --git a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Home.java b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Home.java index 0a10fd0..fd48dfb 100644 --- a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Home.java +++ b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Home.java @@ -35,6 +35,7 @@ import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.Query; import com.google.firebase.database.ValueEventListener; +import com.google.firebase.iid.FirebaseInstanceId; import com.google.firebase.storage.FirebaseStorage; import com.google.firebase.storage.OnProgressListener; import com.google.firebase.storage.StorageReference; @@ -44,7 +45,7 @@ import com.squareup.picasso.Picasso; import com.waterbase.foodifyServer.Model.Category; import com.waterbase.foodifyServer.Common.Common; import com.waterbase.foodifyServer.Interface.ItemClickListener; -import com.waterbase.foodifyServer.Service.ListenOrder; +import com.waterbase.foodifyServer.Model.Token; import com.waterbase.foodifyServer.ViewHolder.MenuViewHolder; import java.util.UUID; @@ -118,12 +119,18 @@ public class Home extends AppCompatActivity implements NavigationView.OnNavigati loadMenu(); - //Call service - Intent service = new Intent(Home.this, ListenOrder.class); - startService(service); + //Send token + updateToken(FirebaseInstanceId.getInstance().getToken()); } + private void updateToken(String token) { + FirebaseDatabase db = FirebaseDatabase.getInstance(); + DatabaseReference tokens = db.getReference("Tokens"); + Token data = new Token(token, true); + tokens.child(Common.currentUser.getPhone()).setValue(data); + } + private void showDialog() { AlertDialog.Builder alertDialog = new AlertDialog.Builder(Home.this); alertDialog.setTitle("Thêm danh mục:"); diff --git a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/MyResponse.java b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/MyResponse.java new file mode 100644 index 0000000..3234e96 --- /dev/null +++ b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/MyResponse.java @@ -0,0 +1,11 @@ +package com.waterbase.foodifyServer.Model; + +import java.util.List; + +public class MyResponse { + public long multicast_id; + public int success; + public int failure; + public int canonical_ids; + public List results; +} diff --git a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Notification.java b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Notification.java new file mode 100644 index 0000000..2992acd --- /dev/null +++ b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Notification.java @@ -0,0 +1,27 @@ +package com.waterbase.foodifyServer.Model; + +public class Notification { + public String body; + public String title; + + public Notification(String body, String title) { + this.body = body; + this.title = title; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Result.java b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Result.java new file mode 100644 index 0000000..2d1c8a7 --- /dev/null +++ b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Result.java @@ -0,0 +1,5 @@ +package com.waterbase.foodifyServer.Model; + +public class Result { + public String message_id; +} diff --git a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Sender.java b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Sender.java new file mode 100644 index 0000000..def1d2d --- /dev/null +++ b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Sender.java @@ -0,0 +1,11 @@ +package com.waterbase.foodifyServer.Model; + +public class Sender { + public String to; + public Notification notification; + + public Sender(String to, Notification notification) { + this.to = to; + this.notification = notification; + } +} diff --git a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Token.java b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Token.java new file mode 100644 index 0000000..d71a8c1 --- /dev/null +++ b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Model/Token.java @@ -0,0 +1,27 @@ +package com.waterbase.foodifyServer.Model; + +public class Token { + private String token; + private boolean isServerToken; + + public Token(String token, boolean isServerToken) { + this.token = token; + this.isServerToken = isServerToken; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public boolean isServerToken() { + return isServerToken; + } + + public void setServerToken(boolean serverToken) { + isServerToken = serverToken; + } +} diff --git a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/OrderStatus.java b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/OrderStatus.java index 3f83229..4143258 100644 --- a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/OrderStatus.java +++ b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/OrderStatus.java @@ -9,19 +9,33 @@ import androidx.recyclerview.widget.RecyclerView; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; +import android.widget.Toast; import com.firebase.ui.database.FirebaseRecyclerAdapter; +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 com.jaredrummler.materialspinner.MaterialSpinner; import com.waterbase.foodifyServer.Common.Common; import com.waterbase.foodifyServer.Interface.ItemClickListener; +import com.waterbase.foodifyServer.Model.MyResponse; +import com.waterbase.foodifyServer.Model.Notification; import com.waterbase.foodifyServer.Model.Request; +import com.waterbase.foodifyServer.Model.Sender; +import com.waterbase.foodifyServer.Model.Token; +import com.waterbase.foodifyServer.Remote.APIService; import com.waterbase.foodifyServer.ViewHolder.OrderViewHolder; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + public class OrderStatus extends AppCompatActivity { RecyclerView recyclerView; @@ -34,6 +48,8 @@ public class OrderStatus extends AppCompatActivity { MaterialSpinner spinner; + APIService mService; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -42,7 +58,10 @@ public class OrderStatus extends AppCompatActivity { //Firebase db = FirebaseDatabase.getInstance(); requests = db.getReference("Requests"); - + + //Init Service + mService = Common.getFCMClient(); + //Init recyclerView = (RecyclerView) findViewById(R.id.listOrders); recyclerView.setHasFixedSize(true); @@ -73,12 +92,13 @@ public class OrderStatus extends AppCompatActivity { Intent trackingOrder = new Intent(OrderStatus.this, TrackingOrder.class); Common.currentRequest = model; startActivity(trackingOrder); - } else { - Intent orderDetail = new Intent(OrderStatus.this, OrderDetail.class); - Common.currentRequest = model; - orderDetail.putExtra("OrderId", adapter.getRef(position).getKey()); - startActivity(orderDetail); } +// else { +// Intent orderDetail = new Intent(OrderStatus.this, OrderDetail.class); +// Common.currentRequest = model; +// orderDetail.putExtra("OrderId", adapter.getRef(position).getKey()); +// startActivity(orderDetail); +// } } }); } @@ -122,6 +142,8 @@ public class OrderStatus extends AppCompatActivity { item.setStatus(String.valueOf(spinner.getSelectedIndex())); requests.child(localKey).setValue(item); + + sendOrderStatusToUser(localKey, item); } }); alertDialog.setNegativeButton("Huỷ", new DialogInterface.OnClickListener() { @@ -133,4 +155,43 @@ public class OrderStatus extends AppCompatActivity { alertDialog.show(); } + + private void sendOrderStatusToUser(String localKey, Request item) { + DatabaseReference tokens = db.getReference("Tokens"); + tokens.orderByKey().equalTo(item.getPhone()) + .addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + for(DataSnapshot postSnapShot: dataSnapshot.getChildren()) { + Token token = postSnapShot.getValue(Token.class); + + //Make raw payload + Notification notification = new Notification("Foodify", "Đơn của bạn " + localKey + " đã được cập nhật!"); + Sender content = new Sender(token.getToken(), notification); + + mService.sendNotification(content) + .enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if(response.body().success == 1) { + Toast.makeText(OrderStatus.this, "Đơn hàng của bạn đã được cập nhật!", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(OrderStatus.this, "Đơn hàng đã được cập nhật nhưng chưa gửi thông báo!", Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + Log.e("ERROR", t.getMessage()); + } + }); + } + } + + @Override + public void onCancelled(DatabaseError databaseError) { + + } + }); + } } \ No newline at end of file diff --git a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Remote/APIService.java b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Remote/APIService.java new file mode 100644 index 0000000..abc39a5 --- /dev/null +++ b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Remote/APIService.java @@ -0,0 +1,24 @@ +package com.waterbase.foodifyServer.Remote; + +import com.waterbase.foodifyServer.Model.MyResponse; +import com.waterbase.foodifyServer.Model.Sender; + +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.Headers; +import retrofit2.http.POST; + +public interface APIService { + + @Headers( + + { + "Content-Type:application/json", + "Authorization:key=AAAAvBRs8TM:APA91bGQ-HvHMz4_UxiTsq4wY9H9j_ScuMRGOd03BYpQ4RKTuGpN_5CPhtQwycJaVCWMaS2T5S850QgUBhWZauOeM5aVeZsW3VGk1sXFu5GnlOgk2ev0VjzkK8fDsV4mO8D8k5uIknsC" + } + ) + + + @POST("fcm/send") + Call sendNotification(@Body Sender body); +} diff --git a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Service/ListenOrder.java b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Service/ListenOrder.java deleted file mode 100644 index 0b21896..0000000 --- a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Service/ListenOrder.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.waterbase.foodifyServer.Service; - -import android.app.Notification; -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.Build; -import android.os.IBinder; - -import androidx.core.app.NotificationCompat; - -import com.google.firebase.database.ChildEventListener; -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.waterbase.foodifyServer.Model.Request; -import com.waterbase.foodifyServer.OrderStatus; -import com.waterbase.foodifyServer.R; - -import java.util.Random; - -public class ListenOrder extends Service implements ChildEventListener { - - FirebaseDatabase db; - DatabaseReference orders; - - @Override - public void onCreate() { - super.onCreate(); - db = FirebaseDatabase.getInstance(); - orders = db.getReference("Requests"); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - orders.addChildEventListener(this); - return super.onStartCommand(intent, flags, startId); - } - - public ListenOrder() { - } - - @Override - public IBinder onBind(Intent intent) { - return null; - } - - @Override - public void onChildAdded(DataSnapshot dataSnapshot, String s) { - Request request = dataSnapshot.getValue(Request.class); - if(request.getStatus().equals("0")) - showNotification(dataSnapshot.getKey(), request); - } - - private void showNotification(String key, Request request) { - Intent intent = new Intent(getBaseContext(), OrderStatus.class); - PendingIntent contentIntent = PendingIntent.getActivity(getBaseContext(), 0, intent, 0); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ - NotificationChannel channel= - new NotificationChannel("newOrder","newOrder",NotificationManager.IMPORTANCE_DEFAULT); - NotificationManager notificationManager=getSystemService(NotificationManager.class); - notificationManager.createNotificationChannel(channel); - - } - - NotificationCompat.Builder builder = new NotificationCompat.Builder(getBaseContext(), "newOrder"); - - builder.setAutoCancel(true) - .setDefaults(Notification.DEFAULT_ALL) - .setTicker("CBNV") - .setContentInfo("Đơn hàng mới") - .setContentText("Bạn có đơn hàng mới #" + key) - .setSmallIcon(R.mipmap.ic_launcher) - .setContentIntent(contentIntent); - NotificationManager manager = (NotificationManager) getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE); - //Show many notification - int randomInt = new Random().nextInt(9999-1)+1; - manager.notify(randomInt, builder.build()); - } - - @Override - public void onChildChanged(DataSnapshot dataSnapshot, String s) { - - } - - @Override - public void onChildRemoved(DataSnapshot dataSnapshot) { - - } - - @Override - public void onChildMoved(DataSnapshot dataSnapshot, String s) { - - } - - @Override - public void onCancelled(DatabaseError databaseError) { - - } -} \ No newline at end of file diff --git a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Service/MyFirebaseIdService.java b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Service/MyFirebaseIdService.java new file mode 100644 index 0000000..bb40f7a --- /dev/null +++ b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Service/MyFirebaseIdService.java @@ -0,0 +1,25 @@ +package com.waterbase.foodifyServer.Service; + +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.iid.FirebaseInstanceId; +import com.google.firebase.iid.FirebaseInstanceIdService; +import com.waterbase.foodifyServer.Common.Common; +import com.waterbase.foodifyServer.Model.Token; + +public class MyFirebaseIdService extends FirebaseInstanceIdService { + + @Override + public void onTokenRefresh() { + super.onTokenRefresh(); + String refreshedToken = FirebaseInstanceId.getInstance().getToken(); + updateToServer(refreshedToken); + } + + private void updateToServer(String refreshedToken) { + FirebaseDatabase db = FirebaseDatabase.getInstance(); + DatabaseReference tokens = db.getReference("Tokens"); + Token data = new Token(refreshedToken, true); + tokens.child(Common.currentUser.getPhone()).setValue(data); + } +} diff --git a/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Service/MyFirebaseMessaging.java b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Service/MyFirebaseMessaging.java new file mode 100644 index 0000000..c6bce1f --- /dev/null +++ b/FoodifyServer/app/src/main/java/com/waterbase/foodifyServer/Service/MyFirebaseMessaging.java @@ -0,0 +1,56 @@ +package com.waterbase.foodifyServer.Service; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Build; +import android.util.Log; + +import androidx.core.app.NotificationCompat; + +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; +import com.waterbase.foodifyServer.Home; +import com.waterbase.foodifyServer.R; + +public class MyFirebaseMessaging extends FirebaseMessagingService { + @Override + public void onMessageReceived(RemoteMessage remoteMessage) { + super.onMessageReceived(remoteMessage); + showNotification(remoteMessage); + Log.e("INFO", remoteMessage.getNotification().getBody()); + } + + private void showNotification(RemoteMessage remoteMessage) { + RemoteMessage.Notification notification = remoteMessage.getNotification(); + Intent intent = new Intent(this, Home.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ + NotificationChannel channel= + new NotificationChannel("foodStatus","foodStatus",NotificationManager.IMPORTANCE_DEFAULT); + NotificationManager notificationManager=getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); + } + + Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); + + NotificationCompat.Builder builder=new NotificationCompat.Builder(getBaseContext(),"foodStatus"); + builder.setAutoCancel(true) + .setDefaults(Notification.DEFAULT_ALL) + .setContentText(notification.getBody()) + .setContentIntent(pendingIntent) + .setContentTitle(notification.getTitle()) + .setSound(defaultSoundUri) + .setSmallIcon(R.mipmap.ic_launcher_round); + + NotificationManager notificationManager=(NotificationManager)getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.notify(1,builder.build()); + } +}