diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..c8b1495 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..ce6d546 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 4412b1a..773fe0f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,6 @@ - - + diff --git a/app/build.gradle b/app/build.gradle index bba9473..15d6f24 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,7 +26,7 @@ android { minSdk 26 targetSdk 32 versionCode 1 - versionName "0.1.2" + versionName "0.3.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" signingConfig signingConfigs.release @@ -96,6 +96,7 @@ dependencies { implementation 'com.saadahmedev.popup-dialog:popup-dialog:1.0.2' implementation 'com.github.gabriel-TheCode:AestheticDialogs:1.3.6' implementation 'io.github.pilgr:paperdb:2.7.2' + implementation 'com.github.techinessoverloaded:progress-dialog:1.5.1' implementation 'androidx.browser:browser:1.5.0' @@ -105,7 +106,8 @@ dependencies { implementation platform('com.google.firebase:firebase-bom:31.2.3') implementation("com.squareup.okhttp3:okhttp:4.10.0") + // ADD the API-only library to all variants - implementation 'com.google.firebase:firebase-appdistribution-api:16.0.0-beta07' + implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta08' } \ No newline at end of file diff --git a/app/release/app-release.apk b/app/release/app-release.apk index 5c6c760..50909c4 100644 Binary files a/app/release/app-release.apk and b/app/release/app-release.apk differ diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index 521f4a6..9a655b0 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -12,7 +12,7 @@ "filters": [], "attributes": [], "versionCode": 1, - "versionName": "0.1.2", + "versionName": "0.3.2", "outputFile": "app-release.apk" } ], diff --git a/app/src/main/java/com/capstone/foodify/Activity/MainActivity.java b/app/src/main/java/com/capstone/foodify/Activity/MainActivity.java index 4483ee4..08185cc 100644 --- a/app/src/main/java/com/capstone/foodify/Activity/MainActivity.java +++ b/app/src/main/java/com/capstone/foodify/Activity/MainActivity.java @@ -61,12 +61,14 @@ import com.google.android.gms.tasks.OnSuccessListener; import com.google.android.gms.tasks.Task; import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.navigation.NavigationBarView; -import com.google.firebase.appdistribution.FirebaseAppDistribution; -import com.google.firebase.appdistribution.InterruptionLevel; +import com.google.firebase.appdistribution.AppDistributionRelease; +import com.google.firebase.appdistribution.OnProgressListener; +import com.google.firebase.appdistribution.UpdateProgress; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseUser; import com.google.firebase.auth.GetTokenResult; import com.google.firebase.messaging.FirebaseMessaging; +import com.techiness.progressdialoglibrary.ProgressDialog; import java.util.Arrays; import java.util.List; @@ -79,13 +81,11 @@ import retrofit2.Response; public class MainActivity extends AppCompatActivity { public static boolean slider, shop, recommendFood, recentFood, loadUser; - private final FirebaseAppDistribution firebaseAppDistribution = FirebaseAppDistribution.getInstance(); private ViewPager2 viewPager2; private BottomNavigationView bottomNavigationView; private FirebaseAuth mAuth; private FirebaseUser user; private static ConstraintLayout progressLayout; - //Location private static final int REQUEST_CHECK_SETTINGS = 100; private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000; @@ -169,6 +169,56 @@ public class MainActivity extends AppCompatActivity { //Initialize Firebase Auth mAuth = FirebaseAuth.getInstance(); + + if(Common.firebaseAppDistribution.isTesterSignedIn()){ + + //Customise progress dialog + ProgressDialog progressDialog = new ProgressDialog(this); + progressDialog.setTheme(ProgressDialog.THEME_LIGHT); + progressDialog.setMode(ProgressDialog.MODE_DETERMINATE); + progressDialog.setProgress(0); + progressDialog.setMessage("Xin vui lòng chờ..."); + progressDialog.showProgressTextAsFraction(true); + progressDialog.setProgressTintList(getColorStateList(R.color.primaryColor)); + progressDialog.setSecondaryProgressTintList(getColorStateList(R.color.primaryLightColor)); + + Common.firebaseAppDistribution.checkForNewRelease().addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if(task.isSuccessful()){ + AppDistributionRelease appDistributionRelease = task.getResult(); + + if(appDistributionRelease != null){ + progressDialog.show(); + } + } + } + }); + + Common.firebaseAppDistribution.updateIfNewReleaseAvailable().addOnProgressListener(new OnProgressListener() { + @Override + public void onProgressUpdate(@NonNull UpdateProgress updateProgress) { + double totalBytes = updateProgress.getApkFileTotalBytes(); + + double number = (updateProgress.getApkBytesDownloaded() / totalBytes) * 100; + + progressDialog.setProgress((int) number); + progressDialog.setSecondaryProgress((int) number + 10); + + if(number == 100){ + progressDialog.dismiss(); + } + } + }).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if(!task.isSuccessful()){ + progressDialog.dismiss(); + } + } + }); + } + //Paper Init Paper.init(this); @@ -179,14 +229,12 @@ public class MainActivity extends AppCompatActivity { startPowerSaverIntent(this); checkNotificationPermission(); - firebaseAppDistribution.showFeedbackNotification( - // Text providing notice to your testers about collection and - // processing of their feedback data - "Nhấp vào đây để đánh giá app Foodify!", - // The level of interruption for the notification - InterruptionLevel.HIGH); + getLocation(); + } + + private void getLocation() { if (Common.CURRENT_LOCATION == null) { mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); mSettingsClient = LocationServices.getSettingsClient(this); @@ -212,22 +260,21 @@ public class MainActivity extends AppCompatActivity { 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(); + } + - //Init location user - final Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - @Override - public void run() { - if(mCurrentLocation != null){ - Common.CURRENT_LOCATION = mCurrentLocation; - stopLocationUpdates(); } + }, 4000); - - } - }, 4000); - + } } private void getTokenFCM(){ @@ -355,8 +402,8 @@ public class MainActivity extends AppCompatActivity { 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(); + if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ + getLocation(); } else { showDialogPermission("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!"); } diff --git a/app/src/main/java/com/capstone/foodify/Activity/OrderCheckOutActivity.java b/app/src/main/java/com/capstone/foodify/Activity/OrderCheckOutActivity.java index c33564f..bbcc0d4 100644 --- a/app/src/main/java/com/capstone/foodify/Activity/OrderCheckOutActivity.java +++ b/app/src/main/java/com/capstone/foodify/Activity/OrderCheckOutActivity.java @@ -479,7 +479,7 @@ public class OrderCheckOutActivity extends AppCompatActivity { new AestheticDialog.Builder(OrderCheckOutActivity.this, DialogStyle.FLAT, DialogType.SUCCESS) .setTitle("Thành công!") .setMessage("Bạn đã đặt hàng thành công cho đơn hàng #" + transactionId) - .setCancelable(true) + .setCancelable(false) .setOnClickListener(new OnDialogClickListener() { @Override public void onClick(@NonNull AestheticDialog.Builder builder) { diff --git a/app/src/main/java/com/capstone/foodify/Activity/SignInActivity.java b/app/src/main/java/com/capstone/foodify/Activity/SignInActivity.java index 635aa3f..58f55bf 100644 --- a/app/src/main/java/com/capstone/foodify/Activity/SignInActivity.java +++ b/app/src/main/java/com/capstone/foodify/Activity/SignInActivity.java @@ -1,28 +1,25 @@ package com.capstone.foodify.Activity; -import android.content.Context; import android.content.Intent; -import android.net.ConnectivityManager; -import android.net.NetworkCapabilities; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; -import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; -import androidx.annotation.IntRange; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import com.capstone.foodify.API.FoodApiToken; import com.capstone.foodify.Common; +import com.capstone.foodify.Fragment.HomeFragment; import com.capstone.foodify.Model.User; import com.capstone.foodify.R; import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.Task; import com.google.android.material.button.MaterialButton; import com.google.android.material.textfield.TextInputEditText; @@ -43,7 +40,7 @@ import retrofit2.Callback; import retrofit2.Response; public class SignInActivity extends AppCompatActivity { - private static final String TAG = "SignInActivity"; + private FirebaseAuth mAuth; private TextView signUp_textView, forgotPassword_textView; private TextInputLayout textInput_email, textInput_password; @@ -52,34 +49,10 @@ public class SignInActivity extends AppCompatActivity { private ImageView back_image; private ConstraintLayout progressLayout; private String email, password = null; - - @IntRange(from = 0, to = 3) - public int getConnectionType() { - int result = 0; // Returns connection type. 0: none; 1: mobile data; 2: wifi - ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); - if (cm != null) { - NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork()); - if (capabilities != null) { - if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { - result = 2; - } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { - result = 1; - } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { - result = 3; - } - } - } - return result; - } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - //Check internet connection - if(getConnectionType() == 0){ - Common.showErrorInternetConnectionNotification(this); - } - //Init firebase app FirebaseApp.initializeApp(SignInActivity.this); setContentView(R.layout.activity_sign_in); @@ -274,7 +247,8 @@ public class SignInActivity extends AppCompatActivity { @Override public void onFailure(Call call, Throwable t) { - Log.e(TAG, t.toString()); + 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 { diff --git a/app/src/main/java/com/capstone/foodify/Common.java b/app/src/main/java/com/capstone/foodify/Common.java index 43eab78..984cede 100644 --- a/app/src/main/java/com/capstone/foodify/Common.java +++ b/app/src/main/java/com/capstone/foodify/Common.java @@ -23,6 +23,7 @@ import com.capstone.foodify.Fragment.HomeFragment; import com.capstone.foodify.Model.Basket; import com.capstone.foodify.Model.Food; import com.capstone.foodify.Model.User; +import com.google.firebase.appdistribution.FirebaseAppDistribution; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseUser; import com.thecode.aestheticdialogs.AestheticDialog; @@ -41,7 +42,7 @@ import retrofit2.Response; public class Common { //https://foodify-backend-production.up.railway.app/ - public static final String BASE_URL = "http://192.168.1.183:8080/api/"; + public static final String BASE_URL = "https://foodify-backend-production.up.railway.app/api/"; public static String FCM_TOKEN = null; public static Location CURRENT_LOCATION = null; public static final String MAP_API = "AIzaSyAY14Ic32UP26Hg6GILznOfbBihiY5BUxw"; @@ -55,6 +56,7 @@ public class Common { public static String TOKEN = null; public static User CURRENT_USER = null; public static String FINAL_SHOP = null; + public static final FirebaseAppDistribution firebaseAppDistribution = FirebaseAppDistribution.getInstance(); public static String changeCurrencyUnit(float price){ Locale locale = new Locale("vi", "VN"); diff --git a/app/src/main/java/com/capstone/foodify/Fragment/ProfileFragment.java b/app/src/main/java/com/capstone/foodify/Fragment/ProfileFragment.java index 559f115..f723c3d 100644 --- a/app/src/main/java/com/capstone/foodify/Fragment/ProfileFragment.java +++ b/app/src/main/java/com/capstone/foodify/Fragment/ProfileFragment.java @@ -1,5 +1,7 @@ package com.capstone.foodify.Fragment; +import static com.capstone.foodify.Common.firebaseAppDistribution; + import android.app.Dialog; import android.content.Intent; import android.os.Bundle; @@ -9,6 +11,7 @@ import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import com.capstone.foodify.Activity.AccountAndProfileActivity; @@ -18,6 +21,9 @@ import com.capstone.foodify.Activity.MainActivity; import com.capstone.foodify.Activity.OrderActivity; import com.capstone.foodify.Common; import com.capstone.foodify.R; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.appdistribution.FirebaseAppDistribution; import com.google.firebase.auth.FirebaseAuth; import com.makeramen.roundedimageview.RoundedImageView; import com.saadahmedsoft.popupdialog.PopupDialog; @@ -29,7 +35,7 @@ import io.paperdb.Paper; public class ProfileFragment extends Fragment { private static final String TAG = "ProfileFragment"; - LinearLayout account_and_profile, manage_address, favorite_food, order_history, log_out; + LinearLayout account_and_profile, manage_address, favorite_food, order_history, feed_back, log_out; PopupDialog popupDialog; TextView user_name; RoundedImageView profile_avatar; @@ -40,13 +46,7 @@ public class ProfileFragment extends Fragment { View rootView = inflater.inflate(R.layout.fragment_profile, container, false); //Init component - account_and_profile = rootView.findViewById(R.id.account_and_profile); - manage_address = rootView.findViewById(R.id.manage_address); - favorite_food = rootView.findViewById(R.id.favorite_food); - order_history = rootView.findViewById(R.id.order_history); - log_out = rootView.findViewById(R.id.log_out); - user_name = rootView.findViewById(R.id.user_name); - profile_avatar = rootView.findViewById(R.id.profile_avatar); + initComponent(rootView); popupDialog = PopupDialog.getInstance(getContext()); @@ -90,6 +90,13 @@ public class ProfileFragment extends Fragment { } }); + feed_back.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + firebaseAppDistribution.startFeedback("Cảm ơn vì sự đóng góp ý kiến từ các bạn!"); + } + }); + log_out.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -129,6 +136,17 @@ public class ProfileFragment extends Fragment { return rootView; } + private void initComponent(View rootView) { + account_and_profile = rootView.findViewById(R.id.account_and_profile); + manage_address = rootView.findViewById(R.id.manage_address); + favorite_food = rootView.findViewById(R.id.favorite_food); + order_history = rootView.findViewById(R.id.order_history); + log_out = rootView.findViewById(R.id.log_out); + user_name = rootView.findViewById(R.id.user_name); + profile_avatar = rootView.findViewById(R.id.profile_avatar); + feed_back = rootView.findViewById(R.id.feedback); + } + @Override public void onResume() { super.onResume(); diff --git a/app/src/main/res/drawable/feedback.png b/app/src/main/res/drawable/feedback.png new file mode 100644 index 0000000..d5bf1bf Binary files /dev/null and b/app/src/main/res/drawable/feedback.png differ diff --git a/app/src/main/res/layout/fragment_basket.xml b/app/src/main/res/layout/fragment_basket.xml index 3472fae..ee19911 100644 --- a/app/src/main/res/layout/fragment_basket.xml +++ b/app/src/main/res/layout/fragment_basket.xml @@ -117,7 +117,7 @@ + + + + + + + + + + #FFFFFFFF #ff8084 + #FF9FA1 #CF2E33 #A3A3A3 #F99928