diff --git a/android/app/src/main/java/com/example/petstoremobile/activities/HomeActivity.java b/android/app/src/main/java/com/example/petstoremobile/activities/HomeActivity.java index 01b4ca24..0b2d8a1d 100644 --- a/android/app/src/main/java/com/example/petstoremobile/activities/HomeActivity.java +++ b/android/app/src/main/java/com/example/petstoremobile/activities/HomeActivity.java @@ -1,7 +1,10 @@ package com.example.petstoremobile.activities; import android.Manifest; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; @@ -20,6 +23,7 @@ import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.ui.NavigationUI; import com.example.petstoremobile.R; +import com.example.petstoremobile.api.auth.TokenManager; import com.example.petstoremobile.databinding.ActivityHomeBinding; import com.example.petstoremobile.services.ChatNotificationService; @@ -30,6 +34,16 @@ public class HomeActivity extends AppCompatActivity { private ActivityHomeBinding binding; private NavController navController; + private final BroadcastReceiver forceLogoutReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Intent loginIntent = new Intent(HomeActivity.this, MainActivity.class); + loginIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(loginIntent); + finish(); + } + }; + // Launcher to ask for notification permission private final ActivityResultLauncher requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { @@ -67,10 +81,22 @@ public class HomeActivity extends AppCompatActivity { handleIntent(getIntent()); } - // Start the notification service and request for notification permission + IntentFilter filter = new IntentFilter(TokenManager.ACTION_FORCE_LOGOUT); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + registerReceiver(forceLogoutReceiver, filter, Context.RECEIVER_NOT_EXPORTED); + } else { + registerReceiver(forceLogoutReceiver, filter); + } + startNotificationService(); requestNotificationPermission(); } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(forceLogoutReceiver); + } /** * Handles new intents received while the activity is already running (like notifications). diff --git a/android/app/src/main/java/com/example/petstoremobile/api/auth/AuthInterceptor.java b/android/app/src/main/java/com/example/petstoremobile/api/auth/AuthInterceptor.java index 02bbe3c0..0feac644 100644 --- a/android/app/src/main/java/com/example/petstoremobile/api/auth/AuthInterceptor.java +++ b/android/app/src/main/java/com/example/petstoremobile/api/auth/AuthInterceptor.java @@ -23,19 +23,26 @@ public class AuthInterceptor implements Interceptor { String token = tokenManager.getToken(); String url = chain.request().url().toString(); - if (url.contains("auth/login") || url.contains("auth/register")) { + boolean isAuthEndpoint = url.contains("auth/login") || url.contains("auth/register"); + + if (isAuthEndpoint) { return chain.proceed(chain.request()); } - //If we have a token then add it to the request + Response response; if (token != null) { Request request = chain.request().newBuilder() .addHeader("Authorization", "Bearer " + token) .build(); - return chain.proceed(request); + response = chain.proceed(request); + } else { + response = chain.proceed(chain.request()); } - //If no token then just pass the request - return chain.proceed(chain.request()); + if (response.code() == 401) { + tokenManager.forceLogout(); + } + + return response; } } diff --git a/android/app/src/main/java/com/example/petstoremobile/api/auth/TokenManager.java b/android/app/src/main/java/com/example/petstoremobile/api/auth/TokenManager.java index dc6096de..8d53f8e7 100644 --- a/android/app/src/main/java/com/example/petstoremobile/api/auth/TokenManager.java +++ b/android/app/src/main/java/com/example/petstoremobile/api/auth/TokenManager.java @@ -1,6 +1,7 @@ package com.example.petstoremobile.api.auth; import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; import javax.inject.Inject; @@ -10,6 +11,8 @@ import dagger.hilt.android.qualifiers.ApplicationContext; @Singleton public class TokenManager { + public static final String ACTION_FORCE_LOGOUT = "com.example.petstoremobile.ACTION_FORCE_LOGOUT"; + private static final String TOKEN_KEY = "token"; private static final String USERNAME_KEY = "username"; private static final String ROLE_KEY = "role"; @@ -17,13 +20,22 @@ public class TokenManager { private static final String USER_ID_KEY = "user_id"; private static final String PRIMARY_STORE_ID_KEY = "primary_store_id"; + private final Context context; private SharedPreferences prefs; @Inject public TokenManager(@ApplicationContext Context context) { + this.context = context; prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); } + public void forceLogout() { + clearLoginData(); + Intent intent = new Intent(ACTION_FORCE_LOGOUT); + intent.setPackage(context.getPackageName()); + context.sendBroadcast(intent); + } + //save login data after login public void saveLoginData(String token, String username, String role) { prefs.edit()