Commit e522cd6d authored by Ishankha K.C's avatar Ishankha K.C

Merge branch 'feature/chamod_dev' into 'master'

enable push notifications

See merge request !7
parents 061b8cca 65f7e087
......@@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application
android:allowBackup="true"
......
......@@ -4,11 +4,15 @@ import static com.kaluwa.enterprises.babycare.config.TokenSaver.getToken;
import static com.kaluwa.enterprises.babycare.utils.Utils.animationChanger;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import com.fasterxml.jackson.core.JsonProcessingException;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.util.Log;
......@@ -28,6 +32,15 @@ public class MainActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Access request
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.POST_NOTIFICATIONS}, 101);
}
}
Button startedBtn = findViewById(R.id.m_btn_get_started);
startedBtn.setOnClickListener(v -> {
......
......@@ -5,8 +5,16 @@ import static com.kaluwa.enterprises.babycare.config.TokenSaver.getToken;
import static com.kaluwa.enterprises.babycare.utils.Utils.animationChanger;
import static com.kaluwa.enterprises.babycare.utils.Utils.loader;
import android.annotation.SuppressLint;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
......@@ -23,6 +31,8 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.PopupMenu;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
......@@ -43,10 +53,12 @@ import com.kaluwa.enterprises.babycare.config.ApiConfig;
import com.kaluwa.enterprises.babycare.dto.ActivityLogDto;
import com.kaluwa.enterprises.babycare.dto.BabyDto;
import com.kaluwa.enterprises.babycare.dto.responseDto.AuthenticationDto;
import com.kaluwa.enterprises.babycare.dto.responseDto.ResponseDto;
import com.kaluwa.enterprises.babycare.error.ErrorDto;
import com.kaluwa.enterprises.babycare.service.ActivityLogsApiService;
import com.kaluwa.enterprises.babycare.service.BabyApiService;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
......@@ -66,12 +78,13 @@ public class ActivityLogsActivity extends AppCompatActivity {
private ActivityLogsApiService activityLogsApiService;
private ActivityLogsAdapter adapter;
private List<ActivityLogDto> activityLogDtos = new ArrayList<>();
private Handler handler = new Handler();
private boolean isActivityOpen = false; // Flag to track activity state
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logs);
// define actionbar
defineActionbar();
swipeToRefresh();
......@@ -91,7 +104,8 @@ public class ActivityLogsActivity extends AppCompatActivity {
progressbar = findViewById(R.id.progress_bar);
// load data
loadData();
loadData(false);
startNotificationPolling();
adapter = new ActivityLogsAdapter(this, activityLogDtos);
recyclerView.setAdapter(adapter);
......@@ -122,15 +136,125 @@ public class ActivityLogsActivity extends AppCompatActivity {
clearIcon.setOnClickListener(v -> {
// Handle the click action here
// You can add your click handling logic here
clearNotification();
});
}
private void clearNotification() {
Call<ResponseDto> call = activityLogsApiService.deleteAllActivityLogs();
loader(overlay, progressbar, true);
call.enqueue(new Callback<ResponseDto>() {
@Override
public void onResponse(Call<ResponseDto> call, Response<ResponseDto> response) {
if (response.isSuccessful()) {
Toast.makeText(ActivityLogsActivity.this, "All activity logs cleared successfully", Toast.LENGTH_LONG).show();
activityLogDtos.clear();
adapter.notifyDataSetChanged();
noContentCall();
loader(overlay, progressbar, false);
} else {
try {
Gson gson = new Gson();
assert response.errorBody() != null;
String errorBodyString = response.errorBody().string();
// Check if the error body is in JSON format
if (errorBodyString.startsWith("{")) {
ErrorDto errorDto = gson.fromJson(errorBodyString, ErrorDto.class);
Toast.makeText(ActivityLogsActivity.this, errorDto.getMessage(), Toast.LENGTH_LONG).show();
} else {
// If the error body is not in JSON format, display a generic error message
Log.e(TAG, errorBodyString);
Toast.makeText(ActivityLogsActivity.this, "An unexpected error occurred", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Log.e(TAG, "else-error: " + e.getMessage());
Toast.makeText(ActivityLogsActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
loader(overlay, progressbar, false);
}
}
@Override
public void onFailure(Call<ResponseDto> call, Throwable throwable) {
Log.e(TAG, throwable.getMessage());
Toast.makeText(ActivityLogsActivity.this, "Error to Failure", Toast.LENGTH_LONG).show();
loader(overlay, progressbar, false);
}
});
}
private void startNotificationPolling() {
// Define a Runnable task for periodic execution
Runnable notificationPollingTask = new Runnable() {
@Override
public void run() {
// Call the API to fetch unread notifications
loadData(true);
Log.e(TAG, "Polling for new notifications...");
sendNotification(activityLogDtos);
if (isActivityOpen) {
handler.postDelayed(this, 5000); // 5 seconds delay
} else {
// Schedule the next execution after 30 seconds
handler.postDelayed(this, 30000); // 30 seconds delay
}
}
};
// Start the polling task immediately
handler.post(notificationPollingTask);
}
@SuppressLint("NewApi")
private void sendNotification(List<ActivityLogDto> unreadNotifications) {
// Check if there are any notifications to send
if (unreadNotifications.isEmpty()) return;
// Extract notification details (assuming the first unread notification is shown)
ActivityLogDto firstUnreadNotification = unreadNotifications.get(0);
LocalDateTime logTime = firstUnreadNotification.getLogTime();
LocalDateTime currentTime = LocalDateTime.now();
String notificationTitle = "New Baby Mood";
String notificationMessage = firstUnreadNotification.getActivityLogDescription();
// Create the Notification Channel (required for Android O and above)
String channelId = "babycare_notifications_channel";
Log.e(TAG, "Notification sent: " + notificationMessage);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId, "Baby Care Notifications", NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("Notifications for baby activity logs");
notificationManager.createNotificationChannel(channel);
}
// Create an Intent for the notification
Intent intent = new Intent(this, ActivityLogsActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
// Build the notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher) // Use your notification icon
.setContentTitle(notificationTitle)
.setContentText(notificationMessage)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setAutoCancel(true); // Automatically removes the notification when clicked
// Show the notification
notificationManager.notify(1, builder.build()); // '1' is the notification ID, change if needed
}
private void loadData() {
private void loadData(boolean isPolling) {
Call<List<ActivityLogDto>> call = activityLogsApiService.getAllActivityLogs();
loader(overlay, progressbar, true);
if (isPolling) {
loader(overlay, progressbar, false);
}
noContentCall();
call.enqueue(new Callback<List<ActivityLogDto>>() {
@Override
......@@ -190,6 +314,18 @@ public class ActivityLogsActivity extends AppCompatActivity {
});
}
@Override
protected void onResume() {
super.onResume();
isActivityOpen = true; // Activity is in the foreground
}
@Override
protected void onPause() {
super.onPause();
isActivityOpen = false; // Activity is in the background
}
private void defineActionbar() {
Toolbar toolbar = findViewById(R.id.b_care_action_bar);
setSupportActionBar(toolbar);
......
......@@ -52,7 +52,7 @@ public class ActivityLogsAdapter extends RecyclerView.Adapter<ActivityLogsAdapte
holder.tvDescription.setText(activityLogDto.getActivityLogDescription());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
holder.tvLogTime.setText(LocalDateTime.now().format(formatter));
holder.tvLogTime.setText(activityLogDto.getLogTime().format(formatter));
}
}
......
package com.kaluwa.enterprises.babycare.dto;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
......@@ -11,4 +13,5 @@ public class ActivityLogDto {
private Long activityLogId;
private String activityLogType;
private String activityLogDescription;
private LocalDateTime logTime;
}
package com.kaluwa.enterprises.babycare.service;
import com.kaluwa.enterprises.babycare.dto.ActivityLogDto;
import com.kaluwa.enterprises.babycare.dto.responseDto.ResponseDto;
import java.util.List;
import retrofit2.Call;
import retrofit2.http.DELETE;
import retrofit2.http.GET;
public interface ActivityLogsApiService {
......@@ -12,4 +14,7 @@ public interface ActivityLogsApiService {
@GET("activity-logs")
Call<List<ActivityLogDto>> getAllActivityLogs();
@DELETE("activity-logs")
Call<ResponseDto> deleteAllActivityLogs();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment