diff --git a/app/build.gradle b/app/build.gradle
index 579fc29..0275b58 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,16 +1,17 @@
plugins {
id 'com.android.application'
id 'com.google.gms.google-services'
+ id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
}
android {
namespace 'com.capstone.foodify.shipper'
- compileSdk 33
+ compileSdk 31
defaultConfig {
applicationId "com.capstone.foodify.shipper"
minSdk 26
- targetSdk 32
+ targetSdk 30
versionCode 1
versionName "1.0"
@@ -27,16 +28,22 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
+ buildFeatures {
+ viewBinding true
+ }
}
dependencies {
implementation 'androidx.core:core-splashscreen:1.0.0'
- implementation 'androidx.appcompat:appcompat:1.6.1'
- implementation 'com.google.android.material:material:1.9.0-beta01'
+
+ implementation 'androidx.appcompat:appcompat:1.4.1'
+ implementation 'com.google.android.material:material:1.6.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+
implementation 'com.google.firebase:firebase-auth:21.0.3'
implementation 'com.google.firebase:firebase-storage:20.0.1'
+ implementation 'com.google.android.gms:play-services-maps:18.1.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
@@ -48,4 +55,6 @@ dependencies {
implementation 'com.github.gabriel-TheCode:AestheticDialogs:1.3.6'
implementation 'com.saadahmedev.popup-dialog:popup-dialog:1.0.2'
implementation 'com.squareup.picasso:picasso:2.71828'
+
+ implementation 'com.google.android.gms:play-services-location:21.0.1'
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3808799..e0d7d6c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,6 +3,10 @@
xmlns:tools="http://schemas.android.com/tools">
+
+
+
+
+ android:usesCleartextTraffic="true">
+
+
@@ -23,7 +31,7 @@
android:exported="false" />
+ android:exported="true" />
recommendFood();
-//
-// @GET("products/enable?pageNo=0&pageSize=10&sortBy=createdTime&sortDir=desc")
-// Call recentFood();
-//
-// @GET("shops/enable?pageNo=0&pageSize=10&sortBy=id&sortDir=asc")
-// Call allShops();
-//
-// @GET("products/search/{name}")
-// Call searchFoodByName(@Path("name") String name, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
-//
-// @GET("products")
-// Call listFood(@Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
-//
-// @GET("categories/randoms?pageNo=0&pageSize=7")
-// Call listCategory();
-//
-// @GET("products/categories")
-// Call listFoodByCategory(@Query("id") List id, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
-//
-// @GET("products/categoriesAndName")
-// Call listFoodByCategoriesAndName(@Query("id") List id, @Query("name") String name, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
-//
-// @GET("products/{id}")
-// Call detailFood(@Path("id") String id);
-//
-// @GET("shops/{id}")
-// Call detailShop(@Path("id") int id);
-//
-// @GET("products/shops/{id}")
-// Call listFoodByShopId(@Path("id") int id, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
-//
-// @GET("districts/{districtId}/wards")
-// Call> wardResponse(@Path("districtId") int district_id);
-//
-// @GET("districts")
-// Call> districtResponse();
-//
-// @GET("sliders")
-// Call> listSlider();
-//
-// @Headers({"accept: */*", "Content-Type: application/json"})
-// @POST("auth/signup")
-// Call register(@Body User user);
-//
-// @POST("auth/check")
-// Call checkEmailOrPhoneExist (@Body User user);
-//
-// @GET("products/{productId}/comments")
-// Call getCommentByProductId(@Path("productId") int productId, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
-//
-// @GET("products/{productId}/users/{userId}")
-// Call getUserComment(@Path("productId") int productId, @Path("userId") int userId);
-//
-// @GET("shops/{id}")
-// Call getShopById(@Path("id") int id);
-//
-// @GET("products/{productId}/user")
-// Call checkUserBuyProduct(@Path("productId") int productId, @Query("userId") int userId);
+ @GET("shippers/user/{id}")
+ Call getShipper(@Path("id") int userId);
}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/API/FoodApiToken.java b/app/src/main/java/com/capstone/foodify/shipper/API/FoodApiToken.java
index 2f618d2..5bf94ad 100644
--- a/app/src/main/java/com/capstone/foodify/shipper/API/FoodApiToken.java
+++ b/app/src/main/java/com/capstone/foodify/shipper/API/FoodApiToken.java
@@ -3,6 +3,7 @@ package com.capstone.foodify.shipper.API;
import androidx.annotation.NonNull;
import com.capstone.foodify.shipper.Common;
+import com.capstone.foodify.shipper.Model.Response.Orders;
import com.capstone.foodify.shipper.Model.User;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -20,6 +21,7 @@ import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.PUT;
import retrofit2.http.Path;
+import retrofit2.http.Query;
public interface FoodApiToken {
Gson gson = new GsonBuilder().setDateFormat("HH:mm:ss dd-MM-yyyy").setLenient().create();
@@ -41,51 +43,12 @@ public interface FoodApiToken {
.create(FoodApiToken.class);
-// @POST("users/{userId}/loves/{productId}")
-// Call addFoodToFavorite(@Path("userId") int userId, @Path("productId") int productId);
-//
-// @DELETE("users/{userId}/loves/{productId}")
-// Call removeFoodFromFavorite(@Path("userId") int userId, @Path("productId") int productId);
-
@GET("users/email/{userEmail}")
Call getUserFromEmail(@Path("userEmail") String userEmail);
-// @GET("users/{userId}/loves")
-// Call getListFavoriteFood(@Path("userId") int userId, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
-//
@PUT("users/{userId}")
Call updateUser(@Path("userId") int userId, @Body User user);
-//
-// @GET("users/{userId}/loves/{productId}")
-// Call checkFoodIsFavorite(@Path("userId") int userId, @Path("productId") int productId);
-//
-// @POST("users/{userId}/addresses")
-// Call createAddressUser(@Path("userId") int userId, @Body Address address);
-//
-// @PUT("users/{userId}/addresses/{addressId}")
-// Call editAddressUser(@Path("userId") int userId, @Path("addressId") int addressId, @Body Address address);
-//
-// @DELETE("users/{userId}/addresses/{addressId}")
-// Call deleteAddressUser(@Path("userId") int userId, @Path("addressId") int addressId);
-//
-// @POST("users/{userId}/orders")
-// Call createOrder(@Path("userId") int userId, @Body Order order);
-//
-// @POST("products/{productId}/comments")
-// Call createComment(@Path("productId") int productId, @Body Comment comment);
-//
-// @DELETE("products/{productId}/comments/{commentId}")
-// Call deleteComment(@Path("productId") int productId, @Path("commentId") int commentId);
-//
-// @PUT("products/{productId}/comments/{commentId}")
-// Call updateComment(@Path("productId") int productId, @Path("commentId") int commentId, @Body Comment comment);
-//
-// @GET("users/{userId}/orders/status/{status}")
-// Call getOrderUser(@Path("userId") int userId, @Path("status") String status, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
-//
-// @DELETE("users/{userId}/orders/{orderId}")
-// Call deleteOrder(@Path("userId") int userId, @Path("orderId") int orderId);
-//
-// @PUT("users/{userId}/orders/{orderId}/status")
-// Call updateOrderStatus(@Path("userId") int userId, @Path("orderId") int orderId, @Query("status") String status);
+
+ @GET("shippers/{shipperId}/orders")
+ Call getListOrder(@Path("shipperId") int shipperId, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Activity/MainActivity.java b/app/src/main/java/com/capstone/foodify/shipper/Activity/MainActivity.java
index 3dff0ef..daee8ba 100644
--- a/app/src/main/java/com/capstone/foodify/shipper/Activity/MainActivity.java
+++ b/app/src/main/java/com/capstone/foodify/shipper/Activity/MainActivity.java
@@ -1,19 +1,48 @@
package com.capstone.foodify.shipper.Activity;
import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
import androidx.core.splashscreen.SplashScreen;
import androidx.viewpager2.widget.ViewPager2;
+import android.Manifest;
import android.annotation.SuppressLint;
+import android.content.DialogInterface;
import android.content.Intent;
+import android.content.IntentSender;
+import android.content.pm.PackageManager;
+import android.location.Location;
+import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.util.Log;
import android.view.MenuItem;
+import android.widget.Toast;
+import com.capstone.foodify.shipper.BuildConfig;
import com.capstone.foodify.shipper.Common;
import com.capstone.foodify.shipper.R;
import com.capstone.foodify.shipper.ViewPagerAdapter;
+import com.google.android.gms.common.api.ApiException;
+import com.google.android.gms.common.api.ResolvableApiException;
+import com.google.android.gms.location.FusedLocationProviderClient;
+import com.google.android.gms.location.LocationCallback;
+import com.google.android.gms.location.LocationRequest;
+import com.google.android.gms.location.LocationResult;
+import com.google.android.gms.location.LocationServices;
+import com.google.android.gms.location.LocationSettingsRequest;
+import com.google.android.gms.location.LocationSettingsResponse;
+import com.google.android.gms.location.LocationSettingsStatusCodes;
+import com.google.android.gms.location.Priority;
+import com.google.android.gms.location.SettingsClient;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationBarView;
@@ -23,6 +52,22 @@ public class MainActivity extends AppCompatActivity {
ViewPagerAdapter viewPagerAdapter;
BottomNavigationView bottomNavigationView;
+ //Location
+ private static final int REQUEST_CHECK_SETTINGS = 100;
+ private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000;
+ private static final long FASTEST_UPDATE_IN_MILLISECONDS = 3000;
+ private static final long MAX_WAIT_TIME_IN_MILLISECONDS = 1000;
+ private static final int LOCATION_REQUEST_CODE = 100;
+ private static final String TAG = MainActivity.class.getSimpleName();
+
+ private FusedLocationProviderClient mFusedLocationClient;
+ private SettingsClient mSettingsClient;
+ private LocationRequest mLocationRequest;
+ private LocationSettingsRequest mLocationSettingsRequest;
+ private LocationCallback mLocationCallBack;
+ private Location mCurrentLocation;
+ private boolean mRequestingLocationUpdates = false;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -34,6 +79,46 @@ public class MainActivity extends AppCompatActivity {
viewPager2 = findViewById(R.id.viewPager);
bottomNavigation();
+
+ if (Common.CURRENT_LOCATION == null) {
+ mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
+ mSettingsClient = LocationServices.getSettingsClient(this);
+
+ mLocationCallBack = new LocationCallback() {
+ @Override
+ public void onLocationResult(@NonNull LocationResult locationResult) {
+ super.onLocationResult(locationResult);
+ mCurrentLocation = locationResult.getLastLocation();
+ Common.CURRENT_LOCATION = mCurrentLocation;
+ }
+ };
+
+ mLocationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, UPDATE_INTERVAL_IN_MILLISECONDS)
+ .setWaitForAccurateLocation(false)
+ .setMinUpdateDistanceMeters(FASTEST_UPDATE_IN_MILLISECONDS)
+ .setMaxUpdateDelayMillis(MAX_WAIT_TIME_IN_MILLISECONDS)
+ .build();
+
+ LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
+ builder.addLocationRequest(mLocationRequest);
+ mLocationSettingsRequest = builder.build();
+
+ checkLocationPermission();
+
+ }
+
+ //Init location user
+ final Handler handler = new Handler();
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if(mCurrentLocation != null){
+ Common.CURRENT_LOCATION = mCurrentLocation;
+ stopLocationUpdates();
+ }
+
+ }
+ }, 3000);
}
private void bottomNavigation() {
@@ -73,4 +158,131 @@ public class MainActivity extends AppCompatActivity {
}
});
}
+
+ //Location
+ private void checkLocationPermission(){
+ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
+ ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
+
+ requestForPermission();
+
+ }else {
+ //Get location
+ mRequestingLocationUpdates = true;
+ startLocationUpdates();
+ }
+ }
+
+ private void requestForPermission() {
+ ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+
+ if(requestCode == LOCATION_REQUEST_CODE){
+ if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
+ Toast.makeText(this, "Đã cấp quyền thành công!", Toast.LENGTH_SHORT).show();
+ } else {
+ showDialogPermission();
+ }
+ }
+ }
+
+ private void showDialogPermission() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+
+ builder.setMessage("Hãy cho ứng dụng truy cập vào vị trí của bạn để trải nghiệm tốt hơn!")
+ .setCancelable(false)
+ .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ openSettings();
+ dialog.cancel();
+ }
+ })
+ .setNegativeButton("Để sau", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.cancel();
+ }
+ });
+
+ AlertDialog alertDialog = builder.create();
+ alertDialog.setTitle("Thông báo!");
+ alertDialog.show();
+ }
+
+ private void openSettings() {
+ Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ Uri uri = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null);
+ intent.setData(uri);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ }
+
+ private void startLocationUpdates() {
+ mSettingsClient.checkLocationSettings(mLocationSettingsRequest).addOnSuccessListener(this, new OnSuccessListener() {
+ @SuppressLint("MissingPermission")
+ @Override
+ public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
+ mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallBack, Looper.myLooper());
+
+ }
+ }).addOnFailureListener(this, new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ int statusCode = ((ApiException) e).getStatusCode();
+ switch (statusCode) {
+ case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
+ Log.i(TAG, "Location settings are not satisfied. Attempting to upgrade location settings");
+
+ try {
+ ResolvableApiException rae = (ResolvableApiException) e;
+ rae.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
+ } catch (IntentSender.SendIntentException sie) {
+ Log.i(TAG, "PendingIntent unable to execute request");
+ }
+ break;
+ case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
+ String errorMessage = "Location settings are inadequate, and cannot be fixed here. Fix in Settings";
+ Log.e(TAG, errorMessage);
+
+ Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }
+
+ private void stopLocationUpdates() {
+ mFusedLocationClient.removeLocationUpdates(mLocationCallBack).addOnCompleteListener(this, task -> Log.d(TAG, "Location updates stopped!"));
+ }
+
+ private boolean checkPermission() {
+ int permissionState = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
+ return permissionState == PackageManager.PERMISSION_GRANTED;
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (mRequestingLocationUpdates && checkPermission() && Common.CURRENT_LOCATION == null) {
+ startLocationUpdates();
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mRequestingLocationUpdates) {
+ stopLocationUpdates();
+
+ if(Common.CURRENT_LOCATION == null){
+ if(mCurrentLocation != null)
+ Common.CURRENT_LOCATION = mCurrentLocation;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Activity/OrderDetailActivity.java b/app/src/main/java/com/capstone/foodify/shipper/Activity/OrderDetailActivity.java
index 8a86a8e..88e6868 100644
--- a/app/src/main/java/com/capstone/foodify/shipper/Activity/OrderDetailActivity.java
+++ b/app/src/main/java/com/capstone/foodify/shipper/Activity/OrderDetailActivity.java
@@ -1,36 +1,255 @@
package com.capstone.foodify.shipper.Activity;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import android.Manifest;
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.PendingIntent;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
+import android.util.Log;
import android.view.View;
import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+import com.capstone.foodify.shipper.API.GoogleMapApi;
+import com.capstone.foodify.shipper.Adapter.OrderDetailAdapter;
+import com.capstone.foodify.shipper.Common;
+import com.capstone.foodify.shipper.GoogleMap.GeofenceHelper;
+import com.capstone.foodify.shipper.Model.GoogleMap.GoogleMapResponse;
+import com.capstone.foodify.shipper.Model.Order;
import com.capstone.foodify.shipper.R;
+import com.google.android.gms.location.Geofence;
+import com.google.android.gms.location.GeofencingClient;
+import com.google.android.gms.location.GeofencingRequest;
+import com.google.android.gms.location.LocationServices;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.thecode.aestheticdialogs.AestheticDialog;
+import com.thecode.aestheticdialogs.DialogAnimation;
+import com.thecode.aestheticdialogs.DialogStyle;
+import com.thecode.aestheticdialogs.DialogType;
+
+import java.text.DecimalFormat;
+
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
public class OrderDetailActivity extends AppCompatActivity {
- Button btn_shipping;
+ private static final String TAG = "OrderDetailActivity";
+ private static final int REQUEST_PHONE_CALL = 1;
+ Order order;
+ Button btn_shipping, btn_call, btn_confirm_ship_completed;
+ TextView order_tracking_number, txt_user_name, txt_phone, txt_address, txt_distance, txt_status, txt_total,
+ txt_order_time;
+ String status = "";
+ ConstraintLayout progressLayout;
+ RecyclerView rcv_list_order;
+ OrderDetailAdapter adapter;
+ LinearLayout layoutConfirmOrder;
+ private GeofencingClient geofencingClient;
+ private GeofenceHelper geofenceHelper;
+ private float GEOFENCE_RADIUS = 100;
+ private String GEOFENCE_ID = "SOME_GEOFENCE_ID";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order_detail);
- btn_shipping = findViewById(R.id.btn_shipping);
+ //Get information order
+ if(getIntent() != null){
+ order = (Order) getIntent().getSerializableExtra("order");
+ status = getIntent().getStringExtra("status");
+ }
+
+
+ initComponent();
+ initData();
+
+ //Check status shipping
+ if(status != null){
+ btn_shipping.setVisibility(View.GONE);
+ layoutConfirmOrder.setVisibility(View.VISIBLE);
+ }
+
+ getDistanceAndCalculateShipCost(order.getAddress());
+
+ LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
+ rcv_list_order.setLayoutManager(linearLayoutManager);
+
+ adapter.setData(order.getOrderDetails());
+ rcv_list_order.setAdapter(adapter);
btn_shipping.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- Intent intent = new Intent(Intent.ACTION_VIEW,
- Uri.parse("google.navigation:q=16.0230,108.2498&mode=l"));
- intent.setPackage("com.google.android.apps.maps");
- startActivity(intent);
+ if(Common.CURRENT_ORDER == null){
+ LatLng latLng = new LatLng(order.getLat(), order.getLng());
+ addGeofence(latLng, GEOFENCE_RADIUS);
+
+ Common.CURRENT_ORDER = order;
+
+ Intent intent = new Intent(Intent.ACTION_VIEW,
+ Uri.parse("google.navigation:q="+ order.getLat() + "," + order.getLng() + "&mode=l"));
+ intent.setPackage("com.google.android.apps.maps");
+ startActivity(intent);
+ }
}
});
+ btn_call.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + order.getUser().getPhoneNumber()));
+ startActivity(intent);
+ }
+ });
+
+ //Register geofence
+ geofencingClient = LocationServices.getGeofencingClient(this);
+ geofenceHelper = new GeofenceHelper(this);
+ }
+ private void initComponent(){
+ adapter = new OrderDetailAdapter();
+
+ btn_shipping = findViewById(R.id.btn_shipping);
+ btn_call = findViewById(R.id.btn_call);
+ btn_confirm_ship_completed = findViewById(R.id.btn_confirm_ship_complete);
+
+ txt_address = findViewById(R.id.txt_address);
+ order_tracking_number = findViewById(R.id.order_tracking_number);
+ txt_user_name = findViewById(R.id.txt_userName);
+ txt_phone = findViewById(R.id.txt_phone);
+ txt_distance = findViewById(R.id.txt_distance);
+ txt_status = findViewById(R.id.txt_status);
+ txt_total = findViewById(R.id.txt_total);
+ txt_order_time = findViewById(R.id.txt_order_time);
+
+ rcv_list_order = findViewById(R.id.list_order);
+
+ layoutConfirmOrder = findViewById(R.id.layout1);
+
+ progressLayout = findViewById(R.id.progress_layout);
+ }
+
+ private void initData(){
+ txt_user_name.setText(order.getUser().getFullName());
+ txt_phone.setText(order.getUser().getPhoneNumber());
+ txt_address.setText(order.getAddress());
+ txt_status.setText(translateStatus(order.getStatus()));
+ txt_total.setText(Common.changeCurrencyUnit(order.getTotal()));
+ txt_order_time.setText(order.getOrderTime());
+ }
+
+ private String translateStatus(String status){
+ String statusHasTranslate = null;
+
+ if(status.equals("AWAITING")){
+ statusHasTranslate = "Chờ xác nhận";
+ }
+
+ if(status.equals("CONFIRMED")){
+ statusHasTranslate = "Đã xác nhận";
+ }
+
+ if(status.equals("SHIPPING")){
+ statusHasTranslate = "Đang giao";
+ }
+
+ if(status.equals("COMPLETED")){
+ statusHasTranslate = "Đã giao";
+ }
+
+ if(status.equals("CANCELED")){
+ statusHasTranslate = "Đã huỷ";
+ }
+
+ return statusHasTranslate;
+ }
+ @SuppressLint("MissingPermission")
+ private void addGeofence(LatLng latLng, float radius) {
+
+ Geofence geofence = geofenceHelper.getGeofence(GEOFENCE_ID, latLng, radius, Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_DWELL | Geofence.GEOFENCE_TRANSITION_EXIT);
+ GeofencingRequest geofencingRequest = geofenceHelper.getGeofencingRequest(geofence);
+ PendingIntent pendingIntent = geofenceHelper.getPendingIntent();
+
+ geofencingClient.addGeofences(geofencingRequest, pendingIntent)
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ Log.d(TAG, "onSuccess: Geofence Added...");
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ String errorMessage = geofenceHelper.getErrorString(e);
+ Log.d(TAG, "onFailure: " + errorMessage);
+ }
+ });
+ }
+
+ private void getDistanceAndCalculateShipCost(String address) {
+ //Get location from address
+ GoogleMapApi.apiService.getGeoCode(address, Common.MAP_API).enqueue(new Callback() {
+ @Override
+ public void onResponse(Call call, Response response) {
+ GoogleMapResponse jsonResponse = response.body();
+
+ Double lat = jsonResponse.getResults().get(0).getGeometry().getLocation().getLat();
+ Double lng = jsonResponse.getResults().get(0).getGeometry().getLocation().getLng();
+
+ LatLng addressFrom = new LatLng(Common.CURRENT_LOCATION.getLatitude(), Common.CURRENT_LOCATION.getLongitude());
+ LatLng addressTo = new LatLng(lat, lng);
+
+ int distance = CalculationByDistance(addressFrom, addressTo);
+
+ txt_distance.setText(distance + " km");
+ progressLayout.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+ Toast.makeText(OrderDetailActivity.this, Common.ERROR_CONNECT_SERVER, Toast.LENGTH_SHORT).show();
+ }
+ });
}
+
+ public int CalculationByDistance(LatLng from, LatLng to) {
+ int Radius = 6371;// radius of earth in Km
+ double lat1 = from.latitude;
+ double lat2 = to.latitude;
+ double lon1 = from.longitude;
+ double lon2 = to.longitude;
+ double dLat = Math.toRadians(lat2 - lat1);
+ double dLon = Math.toRadians(lon2 - lon1);
+ double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ + Math.cos(Math.toRadians(lat1))
+ * Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2)
+ * Math.sin(dLon / 2);
+ double c = 2 * Math.asin(Math.sqrt(a));
+ double valueResult = Radius * c;
+ double km = valueResult / 1;
+ DecimalFormat newFormat = new DecimalFormat("####");
+
+ return Integer.valueOf(newFormat.format(km));
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Activity/SignInActivity.java b/app/src/main/java/com/capstone/foodify/shipper/Activity/SignInActivity.java
index f292771..0881bb9 100644
--- a/app/src/main/java/com/capstone/foodify/shipper/Activity/SignInActivity.java
+++ b/app/src/main/java/com/capstone/foodify/shipper/Activity/SignInActivity.java
@@ -14,8 +14,10 @@ import androidx.appcompat.app.AppCompatDelegate;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.splashscreen.SplashScreen;
+import com.capstone.foodify.shipper.API.FoodApi;
import com.capstone.foodify.shipper.API.FoodApiToken;
import com.capstone.foodify.shipper.Common;
+import com.capstone.foodify.shipper.Model.Shipper;
import com.capstone.foodify.shipper.Model.User;
import com.capstone.foodify.shipper.R;
import com.google.android.gms.tasks.OnCompleteListener;
@@ -59,35 +61,8 @@ public class SignInActivity extends AppCompatActivity {
if (user != null && Common.CURRENT_USER == null) {
progressLayout.setVisibility(View.VISIBLE);
- user.getIdToken(true)
- .addOnCompleteListener(new OnCompleteListener() {
- @Override
- public void onComplete(@NonNull Task task) {
- if (task.isSuccessful()) {
- Common.TOKEN = task.getResult().getToken();
- //Get user from database
- FoodApiToken.apiService.getUserFromEmail(user.getEmail()).enqueue(new Callback() {
- @Override
- public void onResponse(Call call, Response response) {
- User userData = response.body();
- if (userData != null) {
- Common.CURRENT_USER = userData;
- startActivity(new Intent(SignInActivity.this, MainActivity.class));
-
- progressLayout.setVisibility(View.GONE);
- }
- }
-
- @Override
- public void onFailure(Call call, Throwable t) {
- }
- });
- } else {
- Toast.makeText(SignInActivity.this, "Error when taking token!", Toast.LENGTH_SHORT).show();
- }
- }
- });
+ getInformationAndSignInUser(user);
}
}
@@ -107,10 +82,6 @@ public class SignInActivity extends AppCompatActivity {
//Init Component
initComponent();
setFontUI();
-
- if(Common.CURRENT_USER != null)
- startActivity(new Intent(this, MainActivity.class));
-
btn_sign_in.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -173,66 +144,7 @@ public class SignInActivity extends AppCompatActivity {
// Sign in success, update UI with the signed-in user's information
FirebaseUser user = mAuth.getCurrentUser();
- //Save user
-// Paper.book().write("user", user);
-
- user.getIdToken(true)
- .addOnCompleteListener(new OnCompleteListener() {
- @Override
- public void onComplete(@NonNull Task task) {
- if(task.isSuccessful()){
- Common.TOKEN = task.getResult().getToken();
-
- //Get user from database
- FoodApiToken.apiService.getUserFromEmail(user.getEmail()).enqueue(new Callback() {
- @Override
- public void onResponse(Call call, Response response) {
- if(response.code() == 200){
-
- User userData = response.body();
- if(userData != null){
-
- //Check user is lock or not
- if(!userData.isLocked()){
-
- //Check role account
- if(userData.getRole().getRoleName().equals("ROLE_USER")){
- Common.CURRENT_USER = userData;
-
- //Dismiss progress bar
- progressLayout.setVisibility(View.GONE);
-
- startActivity(new Intent(SignInActivity.this, MainActivity.class));
- finish();
- } else {
- Toast.makeText(SignInActivity.this, "Tài khoản không hợp lệ! Vui lòng kiểm tra lại!", Toast.LENGTH_SHORT).show();
- FirebaseAuth.getInstance().signOut();
-
- //Dismiss progress bar
- progressLayout.setVisibility(View.GONE);
- }
- } else {
- Toast.makeText(SignInActivity.this, "Tài khoản của bạn đã bị khoá!", Toast.LENGTH_SHORT).show();
- FirebaseAuth.getInstance().signOut();
-
- //Dismiss progress bar
- progressLayout.setVisibility(View.GONE);
- }
- }
- }
- }
-
- @Override
- public void onFailure(Call call, Throwable t) {
- System.out.println("ERROR: " + t);
- Common.showErrorServerNotification(SignInActivity.this, "Không thể đăng nhập tài khoản! Vui lòng thử lại sau!");
- }
- });
- } else {
- Toast.makeText(SignInActivity.this, "Error when taking token!", Toast.LENGTH_SHORT).show();
- }
- }
- });
+ getInformationAndSignInUser(user);
} else {
// If sign in fails, display a message to the user.
Toast.makeText(SignInActivity.this, "Thông tin đăng nhập không đúng! Vui lòng kiểm tra và thử lại!",
@@ -245,6 +157,66 @@ public class SignInActivity extends AppCompatActivity {
});
}
+ private void getInformationAndSignInUser(FirebaseUser user) {
+ user.getIdToken(true)
+ .addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if(task.isSuccessful()){
+ Common.TOKEN = task.getResult().getToken();
+
+ //Get user from database
+ FoodApiToken.apiService.getUserFromEmail(user.getEmail()).enqueue(new Callback() {
+ @Override
+ public void onResponse(Call call, Response response) {
+ if(response.code() == 200){
+
+ User userData = response.body();
+ if(userData != null){
+
+ //Check user is lock or not
+ if(!userData.isLocked()){
+
+ //Check role account
+ if(userData.getRole().getRoleName().equals("ROLE_SHIPPER")){
+ Common.CURRENT_USER = userData;
+
+ //Get shipper id
+ getShipperId(userData.getId());
+
+ startActivity(new Intent(SignInActivity.this, MainActivity.class));
+ finish();
+ } else {
+ Toast.makeText(SignInActivity.this, "Tài khoản không hợp lệ! Vui lòng kiểm tra lại!", Toast.LENGTH_SHORT).show();
+ FirebaseAuth.getInstance().signOut();
+
+ //Dismiss progress bar
+ progressLayout.setVisibility(View.GONE);
+ }
+ } else {
+ Toast.makeText(SignInActivity.this, "Tài khoản của bạn đã bị khoá!", Toast.LENGTH_SHORT).show();
+ FirebaseAuth.getInstance().signOut();
+
+ //Dismiss progress bar
+ progressLayout.setVisibility(View.GONE);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+ System.out.println("ERROR: " + t);
+ Common.showErrorServerNotification(SignInActivity.this, "Không thể đăng nhập tài khoản! Vui lòng thử lại sau!");
+ }
+ });
+ } else {
+ Toast.makeText(SignInActivity.this, "Error when taking token!", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }
+
private void initData(){
email = edt_email.getText().toString();
password = edt_password.getText().toString();
@@ -300,4 +272,22 @@ public class SignInActivity extends AppCompatActivity {
return dataHasValidate;
}
+
+ private void getShipperId(int userId){
+ FoodApi.apiService.getShipper(userId).enqueue(new Callback() {
+ @Override
+ public void onResponse(Call call, Response response) {
+ if(response.code() == 200){
+ Common.CURRENT_SHIPPER = response.body();
+ //Dismiss progress bar
+ progressLayout.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+ Toast.makeText(SignInActivity.this, Common.ERROR_CONNECT_SERVER, Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Adapter/OrderAdapter.java b/app/src/main/java/com/capstone/foodify/shipper/Adapter/OrderAdapter.java
index d824cf6..3be2259 100644
--- a/app/src/main/java/com/capstone/foodify/shipper/Adapter/OrderAdapter.java
+++ b/app/src/main/java/com/capstone/foodify/shipper/Adapter/OrderAdapter.java
@@ -1,5 +1,6 @@
package com.capstone.foodify.shipper.Adapter;
+import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
@@ -11,6 +12,7 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.capstone.foodify.shipper.Activity.OrderDetailActivity;
+import com.capstone.foodify.shipper.Common;
import com.capstone.foodify.shipper.Model.Order;
import com.capstone.foodify.shipper.R;
@@ -21,12 +23,14 @@ import java.util.List;
public class OrderAdapter extends RecyclerView.Adapter{
public List listOrders;
-
- public OrderAdapter() {
+ private Activity activity;
+ public OrderAdapter(Activity activity) {
+ this.activity = activity;
}
public void setData(List listOrders){
this.listOrders = listOrders;
+ notifyDataSetChanged();
}
@NonNull
@@ -40,18 +44,24 @@ public class OrderAdapter extends RecyclerView.Adapter{
+
+ public List listOrder;
+
+ public OrderDetailAdapter(){}
+
+ public void setData(List listOrder){
+ this.listOrder = listOrder;
+ }
+
+
+ @NonNull
+ @Override
+ public OrderDetailViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_order_detail, parent, false);
+ return new OrderDetailViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull OrderDetailViewHolder holder, int position) {
+ OrderDetail order = listOrder.get(position);
+
+ if(order == null)
+ return;
+
+ if(order.getFood().getImages().size() == 0){
+ Picasso.get().load(R.drawable.default_image_food).into(holder.image_view);
+ } else {
+ Picasso.get().load(order.getFood().getImages().get(0).getImageUrl()).into(holder.image_view);
+ }
+
+ holder.shop_name.setText(order.getFood().getShop().getName());
+ holder.quantity.setText("Số lượng: " + order.getQuantity());
+
+ holder.food_name.setText(order.getFood().getName());
+
+ holder.shop_name.setText(order.getFood().getShop().getName());
+
+ //Check value discountPercent
+ float cost = 0;
+ if(order.getFood().getDiscountPercent() > 0){
+
+ //Calculate final cost when apply discountPercent
+ cost = order.getFood().getCost() - (order.getFood().getCost() * order.getFood().getDiscountPercent()/100);
+
+ //Show discountPercent value on screen
+ holder.discount.setVisibility(View.VISIBLE);
+ holder.discount.setText("-" + order.getFood().getDiscountPercent()+ "%");
+ } else {
+ cost = order.getFood().getCost();
+ }
+
+ holder.price.setText(Common.changeCurrencyUnit(cost));
+ }
+
+ @Override
+ public int getItemCount() {
+ if(listOrder != null)
+ return listOrder.size();
+ return 0;
+ }
+
+ public class OrderDetailViewHolder extends RecyclerView.ViewHolder{
+ ImageView image_view;
+ TextView food_name, shop_name, price, quantity, discount;
+
+ public OrderDetailViewHolder(@NonNull View itemView) {
+ super(itemView);
+
+ //Init Component
+ image_view = itemView.findViewById(R.id.image_view);
+ food_name = itemView.findViewById(R.id.food_name_text_view);
+ shop_name = itemView.findViewById(R.id.shop_name_text_view);
+ price = itemView.findViewById(R.id.price_text_view);
+ quantity = itemView.findViewById(R.id.quantity_text_view);
+ discount = itemView.findViewById(R.id.discount);
+ }
+ }
+}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Common.java b/app/src/main/java/com/capstone/foodify/shipper/Common.java
index 618418d..78f76d8 100644
--- a/app/src/main/java/com/capstone/foodify/shipper/Common.java
+++ b/app/src/main/java/com/capstone/foodify/shipper/Common.java
@@ -7,23 +7,34 @@ import android.location.Location;
import androidx.annotation.NonNull;
+import com.capstone.foodify.shipper.Model.Order;
+import com.capstone.foodify.shipper.Model.Shipper;
import com.capstone.foodify.shipper.Model.User;
import com.thecode.aestheticdialogs.AestheticDialog;
import com.thecode.aestheticdialogs.DialogStyle;
import com.thecode.aestheticdialogs.DialogType;
import com.thecode.aestheticdialogs.OnDialogClickListener;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
public class Common {
public static User CURRENT_USER = null;
+ public static Shipper CURRENT_SHIPPER = null;
+ public static Order CURRENT_ORDER = null;
public static String TOKEN = null;
public static Location CURRENT_LOCATION = null;
public static final String MAP_API = "AIzaSyAY14Ic32UP26Hg6GILznOfbBihiY5BUxw";
- public static final String IS_FORGOT_PASSWORD = "isForgotPassword";
public static final String FORMAT_DATE="dd-MM-yyyy";
public static final String VALID_EMAIL_ADDRESS_REGEX = "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$";
public static final String PHONE_CODE = "+84";
public static final String PASSWORD_PATTERN = "^(?=.*[0-9])(?=.*[A-Z])(?=.*[@#$%^&+=!_])(?=\\S+$).{4,}$";
public static final String PHONE_PATTERN = "^0[98753]{1}\\d{8}$";
+ public static final String ERROR_CONNECT_SERVER = "Đã có lỗi kết nối đến hệ thống!";
+ public static final List LIST_ORDER = new ArrayList<>();
+ public static final String SHIPPING_COMPLETED = "1";
public static Typeface setFontBebas(AssetManager assetManager){
return Typeface.createFromAsset(assetManager, "font/bebas.ttf");
@@ -48,4 +59,10 @@ public class Common {
}).show();
}
+ public static String changeCurrencyUnit(float price){
+ Locale locale = new Locale("vi", "VN");
+ NumberFormat fmt = NumberFormat.getCurrencyInstance(locale);
+ return fmt.format(price);
+ }
+
}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Fragment/OrderFragment.java b/app/src/main/java/com/capstone/foodify/shipper/Fragment/OrderFragment.java
index 0fb934c..fbaa18d 100644
--- a/app/src/main/java/com/capstone/foodify/shipper/Fragment/OrderFragment.java
+++ b/app/src/main/java/com/capstone/foodify/shipper/Fragment/OrderFragment.java
@@ -2,6 +2,8 @@ package com.capstone.foodify.shipper.Fragment;
import android.os.Bundle;
+import androidx.annotation.NonNull;
+import androidx.core.widget.NestedScrollView;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -9,23 +11,38 @@ import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ProgressBar;
import android.widget.TextView;
+import android.widget.Toast;
+import com.capstone.foodify.shipper.API.FoodApiToken;
import com.capstone.foodify.shipper.Adapter.OrderAdapter;
import com.capstone.foodify.shipper.Common;
import com.capstone.foodify.shipper.Model.Order;
+import com.capstone.foodify.shipper.Model.Response.Orders;
import com.capstone.foodify.shipper.R;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
public class OrderFragment extends Fragment {
+ private static int CURRENT_PAGE = 0;
+ private static int PAGE_SIZE = 8;
+ private static String SORT_BY = "id";
+ private static String SORT_DIR = "asc";
+ private static boolean LAST_PAGE = false;
private List listOrders = new ArrayList<>();
RecyclerView recyclerView;
OrderAdapter orderAdapter;
- TextView welcome_text;
+ TextView welcome_text, end_of_list_text_view;
+ NestedScrollView list_order_layout;
+ ProgressBar progressBar;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -36,27 +53,77 @@ public class OrderFragment extends Fragment {
//Init Component
recyclerView = view.findViewById(R.id.rcv_list_order);
welcome_text = view.findViewById(R.id.welcome_text);
+ list_order_layout = view.findViewById(R.id.list_order_layout);
+ progressBar = view.findViewById(R.id.progress_bar);
+ end_of_list_text_view = view.findViewById(R.id.end_of_list_text);
if(Common.CURRENT_USER != null){
welcome_text.setText("Xin chào, " + Common.CURRENT_USER.getFullName() + "!");
}
- orderAdapter = new OrderAdapter();
+ orderAdapter = new OrderAdapter(getActivity());
+
+ getListOrder();
- for(int i = 0; i < 5; i++){
- int b = (int)(Math.random()*(999999-100000+1)+100000);
- listOrders.add(new Order(String.valueOf(b)));
- }
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
- orderAdapter.setData(listOrders);
recyclerView.setAdapter(orderAdapter);
+ if (list_order_layout != null) {
+ list_order_layout.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
+ @Override
+ public void onScrollChange(@NonNull NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
+ if (scrollY == (v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight())) {
+ //When user scroll to bottom, load more data
+ dataLoadMore();
+ }
+ }
+ });
+ }
+
return view;
}
+ private void getListOrder(){
+ if(Common.CURRENT_SHIPPER != null){
+ FoodApiToken.apiService.getListOrder(Common.CURRENT_SHIPPER.getId(), CURRENT_PAGE++, PAGE_SIZE, SORT_BY, SORT_DIR).enqueue(new Callback() {
+ @Override
+ public void onResponse(Call call, Response response) {
+ if(response.code() == 200){
+ listOrders.addAll(response.body().getOrders());
+ orderAdapter.setData(listOrders);
+
+ LAST_PAGE = response.body().getPage().isLast();
+
+ if(LAST_PAGE)
+ hideProgressBarAndShowEndOfListText();
+ } else {
+ Toast.makeText(getContext(), "Đã có lỗi hệ thống! Mã lỗi: " + response.code(), Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+ Toast.makeText(getContext(), Common.ERROR_CONNECT_SERVER, Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }
+
+ private void hideProgressBarAndShowEndOfListText(){
+ progressBar.setVisibility(View.GONE);
+ end_of_list_text_view.setVisibility(View.VISIBLE);
+ }
+
+ private void dataLoadMore() {
+ if(!LAST_PAGE){
+ getListOrder();
+ } else {
+ hideProgressBarAndShowEndOfListText();
+ }
+ }
@Override
public void onResume() {
super.onResume();
@@ -64,4 +131,5 @@ public class OrderFragment extends Fragment {
//Update user name on textview
welcome_text.setText("Xin chào, " + Common.CURRENT_USER.getFullName() + "!");
}
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/capstone/foodify/shipper/GoogleMap/GeofenceBroadcastReceiver.java b/app/src/main/java/com/capstone/foodify/shipper/GoogleMap/GeofenceBroadcastReceiver.java
new file mode 100644
index 0000000..d691ae8
--- /dev/null
+++ b/app/src/main/java/com/capstone/foodify/shipper/GoogleMap/GeofenceBroadcastReceiver.java
@@ -0,0 +1,48 @@
+package com.capstone.foodify.shipper.GoogleMap;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.capstone.foodify.shipper.Activity.OrderDetailActivity;
+import com.capstone.foodify.shipper.Common;
+import com.google.android.gms.location.Geofence;
+import com.google.android.gms.location.GeofencingEvent;
+
+import java.util.List;
+
+public class GeofenceBroadcastReceiver extends BroadcastReceiver {
+
+ private static final String TAG = "GeofenceBroadcastReceive";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+ GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
+
+ if (geofencingEvent.hasError()) {
+ Log.d(TAG, "onReceive: Error receiving geofence event...");
+ return;
+ }
+
+ List geofenceList = geofencingEvent.getTriggeringGeofences();
+ for (Geofence geofence: geofenceList) {
+ Log.d(TAG, "onReceive: " + geofence.getRequestId());
+ }
+
+ int transitionType = geofencingEvent.getGeofenceTransition();
+
+ switch (transitionType) {
+ case Geofence.GEOFENCE_TRANSITION_ENTER:
+ Intent newIntent = new Intent(context.getApplicationContext(), OrderDetailActivity.class);
+ newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ newIntent.putExtra("order", Common.CURRENT_ORDER);
+ newIntent.putExtra("status", Common.SHIPPING_COMPLETED);
+ context.startActivity(newIntent);
+ break;
+ }
+
+ }
+}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/GoogleMap/GeofenceHelper.java b/app/src/main/java/com/capstone/foodify/shipper/GoogleMap/GeofenceHelper.java
new file mode 100644
index 0000000..00504c9
--- /dev/null
+++ b/app/src/main/java/com/capstone/foodify/shipper/GoogleMap/GeofenceHelper.java
@@ -0,0 +1,64 @@
+package com.capstone.foodify.shipper.GoogleMap;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+
+import com.google.android.gms.common.api.ApiException;
+import com.google.android.gms.location.Geofence;
+import com.google.android.gms.location.GeofenceStatusCodes;
+import com.google.android.gms.location.GeofencingRequest;
+import com.google.android.gms.maps.model.LatLng;
+
+public class GeofenceHelper extends ContextWrapper {
+ PendingIntent pendingIntent;
+ public GeofenceHelper(Context base) {
+ super(base);
+ }
+
+ public GeofencingRequest getGeofencingRequest(Geofence geofence) {
+ return new GeofencingRequest.Builder()
+ .addGeofence(geofence)
+ .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
+ .build();
+ }
+
+ public Geofence getGeofence(String ID, LatLng latLng, float radius, int transitionTypes) {
+ return new Geofence.Builder()
+ .setCircularRegion(latLng.latitude, latLng.longitude, radius)
+ .setRequestId(ID)
+ .setTransitionTypes(transitionTypes)
+ .setLoiteringDelay(5000)
+ .setExpirationDuration(Geofence.NEVER_EXPIRE)
+ .build();
+ }
+
+ public PendingIntent getPendingIntent() {
+ if (pendingIntent != null) {
+ return pendingIntent;
+ }
+ Intent intent = new Intent(this, GeofenceBroadcastReceiver.class);
+ pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ return pendingIntent;
+ }
+
+ public String getErrorString(Exception e) {
+ if (e instanceof ApiException) {
+ ApiException apiException = (ApiException) e;
+ switch (apiException.getStatusCode()) {
+ case GeofenceStatusCodes
+ .GEOFENCE_NOT_AVAILABLE:
+ return "GEOFENCE_NOT_AVAILABLE";
+ case GeofenceStatusCodes
+ .GEOFENCE_TOO_MANY_GEOFENCES:
+ return "GEOFENCE_TOO_MANY_GEOFENCES";
+ case GeofenceStatusCodes
+ .GEOFENCE_TOO_MANY_PENDING_INTENTS:
+ return "GEOFENCE_TOO_MANY_PENDING_INTENTS";
+ }
+ }
+ return e.getLocalizedMessage();
+ }
+}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/GoogleMap/NotificationHelper.java b/app/src/main/java/com/capstone/foodify/shipper/GoogleMap/NotificationHelper.java
new file mode 100644
index 0000000..f94844f
--- /dev/null
+++ b/app/src/main/java/com/capstone/foodify/shipper/GoogleMap/NotificationHelper.java
@@ -0,0 +1,47 @@
+package com.capstone.foodify.shipper.GoogleMap;
+
+import android.annotation.SuppressLint;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
+
+import com.capstone.foodify.shipper.R;
+
+import java.util.Random;
+
+public class NotificationHelper extends ContextWrapper {
+
+ public NotificationHelper(Context base) {
+ super(base);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ createChannels();
+ }
+ }
+
+ private String CHANNEL_NAME = "High priority channel";
+ private String CHANNEL_ID = "com.example.notifications" + CHANNEL_NAME;
+
+ @RequiresApi(api = Build.VERSION_CODES.O)
+ private void createChannels() {
+ NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
+ notificationChannel.enableLights(true);
+ notificationChannel.enableVibration(true);
+ notificationChannel.setDescription("this is the description of the channel.");
+ notificationChannel.setLightColor(Color.RED);
+ notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
+ NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ manager.createNotificationChannel(notificationChannel);
+ }
+
+
+}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Model/Food.java b/app/src/main/java/com/capstone/foodify/shipper/Model/Food.java
new file mode 100644
index 0000000..7ada228
--- /dev/null
+++ b/app/src/main/java/com/capstone/foodify/shipper/Model/Food.java
@@ -0,0 +1,116 @@
+package com.capstone.foodify.shipper.Model;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class Food implements Comparable, Serializable {
+ private String id;
+ private String name;
+ private String description;
+ private boolean isEnabled;
+ private float discountPercent;
+ private float cost;
+ private float averageRating;
+ private String reviewCount;
+ private Shop shop;
+ private int sold;
+ private List images;
+ public Food() {
+ }
+
+ 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 getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public boolean isEnabled() {
+ return isEnabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ isEnabled = enabled;
+ }
+
+ public float getDiscountPercent() {
+ return discountPercent;
+ }
+
+ public void setDiscountPercent(float discountPercent) {
+ this.discountPercent = discountPercent;
+ }
+
+ public float getCost() {
+ return cost;
+ }
+
+ public void setCost(float cost) {
+ this.cost = cost;
+ }
+
+ public float getAverageRating() {
+ return averageRating;
+ }
+
+ public void setAverageRating(float averageRating) {
+ this.averageRating = averageRating;
+ }
+
+ public String getReviewCount() {
+ return reviewCount;
+ }
+
+ public void setReviewCount(String reviewCount) {
+ this.reviewCount = reviewCount;
+ }
+
+ public Shop getShop() {
+ return shop;
+ }
+
+ public void setShop(Shop shop) {
+ this.shop = shop;
+ }
+
+ public int getSold() {
+ return sold;
+ }
+
+ public void setSold(int sold) {
+ this.sold = sold;
+ }
+
+ public List getImages() {
+ return images;
+ }
+
+ public void setImages(List images) {
+ this.images = images;
+ }
+
+ @Override
+ public int compareTo(Food food) {
+ if(getName().isEmpty() || food.getName().isEmpty()){
+ return 0;
+ }
+ return getName().compareTo(food.getName());
+ }
+}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Model/Image.java b/app/src/main/java/com/capstone/foodify/shipper/Model/Image.java
new file mode 100644
index 0000000..b39e970
--- /dev/null
+++ b/app/src/main/java/com/capstone/foodify/shipper/Model/Image.java
@@ -0,0 +1,33 @@
+package com.capstone.foodify.shipper.Model;
+
+import java.io.Serializable;
+
+public class Image implements Serializable {
+ private int id;
+ private String imageUrl;
+ private int productId;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getImageUrl() {
+ return imageUrl;
+ }
+
+ public void setImageUrl(String imageUrl) {
+ this.imageUrl = imageUrl;
+ }
+
+ public int getProductId() {
+ return productId;
+ }
+
+ public void setProductId(int productId) {
+ this.productId = productId;
+ }
+}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Model/Order.java b/app/src/main/java/com/capstone/foodify/shipper/Model/Order.java
index 61cb33a..204f7f4 100644
--- a/app/src/main/java/com/capstone/foodify/shipper/Model/Order.java
+++ b/app/src/main/java/com/capstone/foodify/shipper/Model/Order.java
@@ -1,27 +1,23 @@
package com.capstone.foodify.shipper.Model;
+import java.io.Serializable;
import java.util.List;
-public class Order {
+public class Order implements Serializable {
private int id;
private String orderTrackingNumber;
- private int shipperId;
private String paymentMethod;
private float shippingCost;
+ private float productCost;
private String status;
private String address;
+ private User user;
+ private Shipper shipper;
private List orderDetails;
-
- public Order(String orderTrackingNumber, int shipperId, String paymentMethod, float shippingCost, String status, String address, List orderDetails) {
- this.orderTrackingNumber = orderTrackingNumber;
- this.shipperId = shipperId;
- this.paymentMethod = paymentMethod;
- this.shippingCost = shippingCost;
- this.status = status;
- this.address = address;
- this.orderDetails = orderDetails;
- }
-
+ private String orderTime;
+ private float total;
+ private double lat;
+ private double lng;
public int getId() {
return id;
}
@@ -41,14 +37,6 @@ public class Order {
this.orderTrackingNumber = orderTrackingNumber;
}
- public int getShipperId() {
- return shipperId;
- }
-
- public void setShipperId(int shipperId) {
- this.shipperId = shipperId;
- }
-
public String getPaymentMethod() {
return paymentMethod;
}
@@ -96,4 +84,60 @@ public class Order {
public void setListOrderDetail(List listOrderDetail) {
this.orderDetails = listOrderDetail;
}
+
+ public float getProductCost() {
+ return productCost;
+ }
+
+ public void setProductCost(float productCost) {
+ this.productCost = productCost;
+ }
+
+ public User getUser() {
+ return user;
+ }
+
+ public void setUser(User user) {
+ this.user = user;
+ }
+
+ public Shipper getShipper() {
+ return shipper;
+ }
+
+ public void setShipper(Shipper shipper) {
+ this.shipper = shipper;
+ }
+
+ public String getOrderTime() {
+ return orderTime;
+ }
+
+ public void setOrderTime(String orderTime) {
+ this.orderTime = orderTime;
+ }
+
+ public float getTotal() {
+ return total;
+ }
+
+ public void setTotal(float total) {
+ this.total = total;
+ }
+
+ public double getLat() {
+ return lat;
+ }
+
+ public void setLat(double lat) {
+ this.lat = lat;
+ }
+
+ public double getLng() {
+ return lng;
+ }
+
+ public void setLng(double lng) {
+ this.lng = lng;
+ }
}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Model/OrderDetail.java b/app/src/main/java/com/capstone/foodify/shipper/Model/OrderDetail.java
index 0284f97..f1907f4 100644
--- a/app/src/main/java/com/capstone/foodify/shipper/Model/OrderDetail.java
+++ b/app/src/main/java/com/capstone/foodify/shipper/Model/OrderDetail.java
@@ -1,11 +1,15 @@
package com.capstone.foodify.shipper.Model;
-public class OrderDetail {
+import com.google.gson.annotations.SerializedName;
+
+import java.io.Serializable;
+
+public class OrderDetail implements Serializable {
private int id;
- private int orderId;
- private int productId;
+ @SerializedName("product")
+ private Food food;
private String quantity;
- private float subTotal;
+ private float subtotal;
public int getId() {
return id;
@@ -15,22 +19,6 @@ public class OrderDetail {
this.id = id;
}
- public int getOrderId() {
- return orderId;
- }
-
- public void setOrderId(int orderId) {
- this.orderId = orderId;
- }
-
- public int getProductId() {
- return productId;
- }
-
- public void setProductId(int productId) {
- this.productId = productId;
- }
-
public String getQuantity() {
return quantity;
}
@@ -39,11 +27,19 @@ public class OrderDetail {
this.quantity = quantity;
}
- public float getSubTotal() {
- return subTotal;
+ public float getSubtotal() {
+ return subtotal;
}
- public void setSubTotal(float subTotal) {
- this.subTotal = subTotal;
+ public void setSubtotal(float subtotal) {
+ this.subtotal = subtotal;
+ }
+
+ public Food getFood() {
+ return food;
+ }
+
+ public void setFood(Food food) {
+ this.food = food;
}
}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Model/Page.java b/app/src/main/java/com/capstone/foodify/shipper/Model/Page.java
new file mode 100644
index 0000000..1ac2aaa
--- /dev/null
+++ b/app/src/main/java/com/capstone/foodify/shipper/Model/Page.java
@@ -0,0 +1,49 @@
+package com.capstone.foodify.shipper.Model;
+
+public class Page {
+ private int pageNo;
+ private int pageSize;
+ private int totalElements;
+ private int totalPages;
+ private boolean last;
+
+ public int getPageNo() {
+ return pageNo;
+ }
+
+ public void setPageNo(int pageNo) {
+ this.pageNo = pageNo;
+ }
+
+ public int getPageSize() {
+ return pageSize;
+ }
+
+ public void setPageSize(int pageSize) {
+ this.pageSize = pageSize;
+ }
+
+ public int getTotalElements() {
+ return totalElements;
+ }
+
+ public void setTotalElements(int totalElements) {
+ this.totalElements = totalElements;
+ }
+
+ public int getTotalPages() {
+ return totalPages;
+ }
+
+ public void setTotalPages(int totalPages) {
+ this.totalPages = totalPages;
+ }
+
+ public boolean isLast() {
+ return last;
+ }
+
+ public void setLast(boolean last) {
+ this.last = last;
+ }
+}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Model/Response/Orders.java b/app/src/main/java/com/capstone/foodify/shipper/Model/Response/Orders.java
new file mode 100644
index 0000000..6ccd0e9
--- /dev/null
+++ b/app/src/main/java/com/capstone/foodify/shipper/Model/Response/Orders.java
@@ -0,0 +1,27 @@
+package com.capstone.foodify.shipper.Model.Response;
+
+import com.capstone.foodify.shipper.Model.Order;
+import com.capstone.foodify.shipper.Model.Page;
+
+import java.util.List;
+
+public class Orders {
+ private List orders;
+ private Page page;
+
+ public List getOrders() {
+ return orders;
+ }
+
+ public void setOrders(List orders) {
+ this.orders = orders;
+ }
+
+ public Page getPage() {
+ return page;
+ }
+
+ public void setPage(Page page) {
+ this.page = page;
+ }
+}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Model/Shipper.java b/app/src/main/java/com/capstone/foodify/shipper/Model/Shipper.java
new file mode 100644
index 0000000..c66af38
--- /dev/null
+++ b/app/src/main/java/com/capstone/foodify/shipper/Model/Shipper.java
@@ -0,0 +1,44 @@
+package com.capstone.foodify.shipper.Model;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class Shipper implements Serializable {
+ private int id;
+ private User user;
+ private Shop shop;
+
+ private List orders;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public User getUser() {
+ return user;
+ }
+
+ public void setUser(User user) {
+ this.user = user;
+ }
+
+ public Shop getShop() {
+ return shop;
+ }
+
+ public void setShop(Shop shop) {
+ this.shop = shop;
+ }
+
+ public List getOrders() {
+ return orders;
+ }
+
+ public void setOrders(List orders) {
+ this.orders = orders;
+ }
+}
diff --git a/app/src/main/java/com/capstone/foodify/shipper/Model/Shop.java b/app/src/main/java/com/capstone/foodify/shipper/Model/Shop.java
new file mode 100644
index 0000000..7accd49
--- /dev/null
+++ b/app/src/main/java/com/capstone/foodify/shipper/Model/Shop.java
@@ -0,0 +1,87 @@
+package com.capstone.foodify.shipper.Model;
+
+import java.io.Serializable;
+
+public class Shop implements Serializable {
+ private int id;
+ private String name;
+ private String description;
+ private String imageUrl;
+ private boolean isEnabled;
+ private boolean isStudent;
+ private int userId;
+ private double lat;
+ private double lng;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getImageUrl() {
+ return imageUrl;
+ }
+
+ public void setImageUrl(String imageUrl) {
+ this.imageUrl = imageUrl;
+ }
+
+ public boolean isEnabled() {
+ return isEnabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ isEnabled = enabled;
+ }
+
+ public boolean isStudent() {
+ return isStudent;
+ }
+
+ public void setStudent(boolean student) {
+ isStudent = student;
+ }
+
+ public int getUserId() {
+ return userId;
+ }
+
+ public void setUserId(int userId) {
+ this.userId = userId;
+ }
+
+ public double getLat() {
+ return lat;
+ }
+
+ public void setLat(double lat) {
+ this.lat = lat;
+ }
+
+ public double getLng() {
+ return lng;
+ }
+
+ public void setLng(double lng) {
+ this.lng = lng;
+ }
+}
diff --git a/app/src/main/res/drawable/baseline_local_shipping_24.xml b/app/src/main/res/drawable/baseline_local_shipping_24.xml
new file mode 100644
index 0000000..14c4c7b
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_local_shipping_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/baseline_verified_24.xml b/app/src/main/res/drawable/baseline_verified_24.xml
new file mode 100644
index 0000000..faafa97
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_verified_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/default_image_food.png b/app/src/main/res/drawable/default_image_food.png
new file mode 100644
index 0000000..8cc5216
Binary files /dev/null and b/app/src/main/res/drawable/default_image_food.png differ
diff --git a/app/src/main/res/layout/activity_order_detail.xml b/app/src/main/res/layout/activity_order_detail.xml
index 005c0fe..10e98aa 100644
--- a/app/src/main/res/layout/activity_order_detail.xml
+++ b/app/src/main/res/layout/activity_order_detail.xml
@@ -28,7 +28,7 @@
app:layout_constraintTop_toTopOf="parent" />
@@ -64,7 +64,7 @@
+
+
+
+
+
+
+
+
+
@@ -301,8 +344,28 @@
+
+
+ android:drawableLeft="@drawable/baseline_phone_24"
+ android:drawableTint="@color/white"
+ />
+ android:drawableLeft="@drawable/baseline_verified_24"
+ android:drawableTint="@color/white"/>
@@ -357,7 +424,7 @@
android:background="#80000000"
android:id="@+id/progress_layout"
android:clickable="true"
- android:visibility="gone"
+ android:visibility="visible"
>
+ android:layout_height="match_parent"
+ android:id="@+id/list_order_layout"
+ >
+
+
+
+
diff --git a/app/src/main/res/layout/item_order_detail.xml b/app/src/main/res/layout/item_order_detail.xml
new file mode 100644
index 0000000..831ce33
--- /dev/null
+++ b/app/src/main/res/layout/item_order_detail.xml
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0d73617..8d0d2fc 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -2,4 +2,5 @@
Foodify Shipper
Hello blank fragment
+ MapsActivity
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index e1d8225..954ca80 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,4 +6,5 @@ buildscript {
plugins {
id 'com.android.application' version '7.4.2' apply false
id 'com.android.library' version '7.4.2' apply false
+ id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin' version '2.0.1' apply false
}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 3e927b1..ba32d98 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -15,6 +15,7 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
+android.enableJetifier=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library