Commit 396b16a2 authored by Ishankha K.C's avatar Ishankha K.C

Merge branch 'feature/chamod_dev' into 'master'

Feature/chamod dev

See merge request !4
parents e6f88f4f 3954a365
...@@ -47,6 +47,7 @@ dependencies { ...@@ -47,6 +47,7 @@ dependencies {
implementation(libs.swiperefreshlayout) implementation(libs.swiperefreshlayout)
implementation(libs.converter.jackson) implementation(libs.converter.jackson)
implementation(libs.jackson.datatype.jsr310) implementation(libs.jackson.datatype.jsr310)
implementation(libs.okhttp)
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit) androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core) androidTestImplementation(libs.espresso.core)
......
...@@ -17,6 +17,12 @@ ...@@ -17,6 +17,12 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.BabyCare" android:theme="@style/Theme.BabyCare"
tools:targetApi="31"> tools:targetApi="31">
<activity
android:name=".activities.ActivityLogsActivity"
android:exported="false" />
<activity
android:name=".activities.LiveFeedActivity"
android:exported="false" />
<activity <activity
android:name=".activities.BabyDashboardActivity" android:name=".activities.BabyDashboardActivity"
android:exported="false" /> android:exported="false" />
......
package com.kaluwa.enterprises.babycare.activities;
import static com.kaluwa.enterprises.babycare.config.TokenSaver.clearToken;
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.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.PopupMenu;
import androidx.appcompat.widget.Toolbar;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.github.ybq.android.spinkit.SpinKitView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.gson.Gson;
import com.kaluwa.enterprises.babycare.MainActivity;
import com.kaluwa.enterprises.babycare.R;
import com.kaluwa.enterprises.babycare.adapter.ActivityLogsAdapter;
import com.kaluwa.enterprises.babycare.adapter.BabyDashboardAdapter;
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.error.ErrorDto;
import com.kaluwa.enterprises.babycare.service.ActivityLogsApiService;
import com.kaluwa.enterprises.babycare.service.BabyApiService;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class ActivityLogsActivity extends AppCompatActivity {
private final static String TAG = "ActivityLogsActivity";
private SwipeRefreshLayout swipeContainer;
private AuthenticationDto authDto;
private RecyclerView recyclerView;
private TextView tvNoContent;
private View overlay;
private SpinKitView progressbar;
private ActivityLogsApiService activityLogsApiService;
private ActivityLogsAdapter adapter;
private List<ActivityLogDto> activityLogDtos = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logs);
// define actionbar
defineActionbar();
swipeToRefresh();
// initialize user api service
try {
authDto = getToken(getApplicationContext());
} catch (JsonProcessingException e) {
Log.e(TAG, "Error: "+e.getMessage());
Toast.makeText(this, "Error getting token, Please refresh", Toast.LENGTH_SHORT).show();
}
activityLogsApiService = ApiConfig.getInstance().getActivityLogsApi(authDto.getTokenDto().getToken());
// assign ids here
recyclerView = findViewById(R.id.rv_activity_notifications);
tvNoContent = findViewById(R.id.no_content_message);
overlay = findViewById(R.id.overlay);
progressbar = findViewById(R.id.progress_bar);
// load data
loadData();
adapter = new ActivityLogsAdapter(this, activityLogDtos);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
private void loadData() {
Call<List<ActivityLogDto>> call = activityLogsApiService.getAllActivityLogs();
loader(overlay, progressbar, true);
noContentCall();
call.enqueue(new Callback<List<ActivityLogDto>>() {
@Override
public void onResponse(Call<List<ActivityLogDto>> call, Response<List<ActivityLogDto>> response) {
if (response.isSuccessful()) {
List<ActivityLogDto> newActivityLogDtos = new ArrayList<>();
if (response.body() != null) {
newActivityLogDtos = response.body();
}
// Assuming babyDtoList is a class member
// Check for changes and update the list accordingly
if (activityLogDtos == null) {
activityLogDtos = newActivityLogDtos;
adapter.notifyItemRangeInserted(0, newActivityLogDtos.size());
} else {
// Here, you might want to implement a diffing algorithm
// For simplicity, let's assume you replace the entire list
activityLogDtos.clear();
activityLogDtos.addAll(newActivityLogDtos);
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();
}
noContentCall();
loader(overlay, progressbar, false);
}
}
@Override
public void onFailure(Call<List<ActivityLogDto>> call, Throwable throwable) {
noContentCall();
Log.e(TAG, throwable.getMessage());
Toast.makeText(ActivityLogsActivity.this, "Error to Failure", Toast.LENGTH_LONG).show();
loader(overlay, progressbar, false);
}
});
}
private void defineActionbar() {
Toolbar toolbar = findViewById(R.id.b_care_action_bar);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
toolbar.setNavigationIcon(R.drawable.ico_menu_32);
toolbar.setNavigationOnClickListener(v -> {
// Initializing the popup menu and giving the reference as current context
PopupMenu popupMenu = new PopupMenu(this, toolbar);
popupMenu.setGravity(Gravity.BOTTOM);
popupMenu.getMenuInflater().inflate(R.menu.menu_main, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(item -> {
int id = item.getItemId();
if (id == R.id.mm_device_setting) {
Toast.makeText(this, "You Clicked " + item.getTitle(), Toast.LENGTH_SHORT).show();
} else if (id == R.id.mm_app_setting) {
Toast.makeText(this, "You Clicked " + item.getTitle(), Toast.LENGTH_SHORT).show();
} else if (id == R.id.mm_logout) {
clearToken(getApplicationContext());
Toast.makeText(this, "Logout successful.", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
animationChanger(this);
}
return true;
});
popupMenu.show();
});
}
private void swipeToRefresh() {
// Look up for the swipe container
swipeContainer = findViewById(R.id.swipeContainer);
// Setup Refresh Listener which triggers new data loading
swipeContainer.setOnRefreshListener(() -> {
// Code to refresh goes here. Make sure to call swipeContainer.setRefresh(false) once the refreshed.
startActivity(getIntent());
finish();
overridePendingTransition(0,0);
swipeContainer.setRefreshing(false);
});
// Configure refresh colors
swipeContainer.setColorSchemeResources(android.R.color.holo_blue_bright, android.R.color.holo_green_light, android.R.color.holo_orange_light, android.R.color.holo_red_light);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.user_action_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
if (id == R.id.user) {
Intent intent = new Intent(this, UserProfileActivity.class);
startActivity(intent);
animationChanger(this);
} else {
Toast.makeText(this, "No item.", Toast.LENGTH_SHORT).show();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
super.onBackPressed();
animationChanger(this);
}
void noContentCall() {
if (activityLogDtos.isEmpty()) {
tvNoContent.setVisibility(View.VISIBLE);
} else {
tvNoContent.setVisibility(View.GONE);
}
}
}
\ No newline at end of file
...@@ -65,6 +65,7 @@ public class BabyDashboardActivity extends AppCompatActivity implements AddBabyD ...@@ -65,6 +65,7 @@ public class BabyDashboardActivity extends AppCompatActivity implements AddBabyD
private BabyApiService babyApiService; private BabyApiService babyApiService;
private BabyDashboardAdapter adapter; private BabyDashboardAdapter adapter;
private List<BabyDto> babyDtoList = new ArrayList<>(); private List<BabyDto> babyDtoList = new ArrayList<>();
@SuppressLint("NewApi") @SuppressLint("NewApi")
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
......
...@@ -19,7 +19,6 @@ import androidx.appcompat.widget.Toolbar; ...@@ -19,7 +19,6 @@ import androidx.appcompat.widget.Toolbar;
import com.kaluwa.enterprises.babycare.MainActivity; import com.kaluwa.enterprises.babycare.MainActivity;
import com.kaluwa.enterprises.babycare.R; import com.kaluwa.enterprises.babycare.R;
import com.kaluwa.enterprises.babycare.activities.auth.LoginActivity;
public class DashboardActivity extends AppCompatActivity { public class DashboardActivity extends AppCompatActivity {
...@@ -41,13 +40,15 @@ public class DashboardActivity extends AppCompatActivity { ...@@ -41,13 +40,15 @@ public class DashboardActivity extends AppCompatActivity {
btn6 = findViewById(R.id.btn_settings); btn6 = findViewById(R.id.btn_settings);
btn1.setOnClickListener(v -> { btn1.setOnClickListener(v -> {
Intent intent = new Intent(this, LiveFeedActivity.class);
startActivity(intent);
}); });
btn2.setOnClickListener(v -> { btn2.setOnClickListener(v -> {
}); });
btn3.setOnClickListener(v -> { btn3.setOnClickListener(v -> {
Intent intent = new Intent(this, ActivityLogsActivity.class);
startActivity(intent);
}); });
btn4.setOnClickListener(v -> { btn4.setOnClickListener(v -> {
......
package com.kaluwa.enterprises.babycare.activities;
import static com.kaluwa.enterprises.babycare.config.BabyEmotionWebSocketListener.NORMAL_CLOSURE_STATUS;
import static com.kaluwa.enterprises.babycare.config.TokenSaver.clearToken;
import static com.kaluwa.enterprises.babycare.constants.Configs.EMOTIONAL_VIDEO_PROCESS_WS_URL;
import static com.kaluwa.enterprises.babycare.constants.Configs.LIVE_FEED_URL;
import static com.kaluwa.enterprises.babycare.constants.Configs.REFRESH_INTERVAL;
import static com.kaluwa.enterprises.babycare.utils.Utils.animationChanger;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.PopupMenu;
import androidx.appcompat.widget.Toolbar;
import com.kaluwa.enterprises.babycare.MainActivity;
import com.kaluwa.enterprises.babycare.R;
import com.kaluwa.enterprises.babycare.config.BabyEmotionWebSocketListener;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.WebSocket;
public class LiveFeedActivity extends AppCompatActivity {
private static final String TAG = "LiveFeedActivity";
private ImageView ivLiveFeed;
private Button lfFlashBtn;
private TextView tvLlStatusValue;
private Handler handler = new Handler();
private Runnable updateRunnable;
private WebSocket webSocket;
private OkHttpClient client;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_feed);
// define actionbar
defineActionbar();
ivLiveFeed = findViewById(R.id.ivLiveFeed);
lfFlashBtn = findViewById(R.id.lfFlashBtn);
tvLlStatusValue = findViewById(R.id.tvLlStatusValue);
updateRunnable = new Runnable() {
@Override
public void run() {
fetchAndDisplayImage();
handler.postDelayed(this, REFRESH_INTERVAL);
}
};
// Start updating
handler.post(updateRunnable);
// Toggle flashlight
lfFlashBtn.setOnClickListener(v -> toggleFlashlight());
// Initialize the WebSocket connection
// client = new OkHttpClient();
// Request request = new Request.Builder()
// .url(EMOTIONAL_VIDEO_PROCESS_WS_URL)
// .build();
// BabyEmotionWebSocketListener listener = new BabyEmotionWebSocketListener(this, tvLlStatusValue);
// webSocket = client.newWebSocket(request, listener);
//
// // Clean up the WebSocket connection when done
// client.dispatcher().executorService().shutdown();
}
private void toggleFlashlight() {
String currentText = lfFlashBtn.getText().toString();
String url = currentText.equals("FLASH ON") ? LIVE_FEED_URL+"/flashlight/on" : LIVE_FEED_URL+"/flashlight/off";
String newText = currentText.equals("FLASH ON") ? "FLASH OFF" : "FLASH ON";
// Call the API in a background thread
new Thread(() -> {
try {
URL apiUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection();
connection.setRequestMethod("GET");
connection.connect();
int responseCode = connection.getResponseCode();
if (responseCode == 200) {
// Update the button text on the main thread
runOnUiThread(() -> lfFlashBtn.setText(newText));
} else {
Log.e(TAG, "Failed to call API: " + responseCode);
}
connection.disconnect();
} catch (IOException e) {
Log.e(TAG, "Error calling flashlight API", e);
}
}).start();
}
@Override
protected void onStart() {
super.onStart();
connectWebSocket();
}
@Override
protected void onStop() {
super.onStop();
closeWebSocket();
}
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(updateRunnable); // Stop updating when the activity is destroyed
// Close the WebSocket connection
if (webSocket != null) {
webSocket.close(1000, "Activity destroyed");
}
}
private void fetchAndDisplayImage() {
new Thread(() -> {
try {
URL url = new URL(LIVE_FEED_URL+"/cam-hi.jpg");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(input);
runOnUiThread(() -> ivLiveFeed.setImageBitmap(bitmap));
} catch (Exception e) {
Log.e(TAG, "Error fetching image", e);
// If there's an error, set the default image
runOnUiThread(() -> ivLiveFeed.setImageResource(R.drawable.live_offline));
}
}).start();
}
private void defineActionbar() {
Toolbar toolbar = findViewById(R.id.b_care_action_bar);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
toolbar.setNavigationIcon(R.drawable.ico_menu_32);
toolbar.setNavigationOnClickListener(v -> {
// Initializing the popup menu and giving the reference as current context
PopupMenu popupMenu = new PopupMenu(this, toolbar);
popupMenu.setGravity(Gravity.BOTTOM);
popupMenu.getMenuInflater().inflate(R.menu.menu_main, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(item -> {
int id = item.getItemId();
if (id == R.id.mm_device_setting) {
Toast.makeText(this, "You Clicked " + item.getTitle(), Toast.LENGTH_SHORT).show();
} else if (id == R.id.mm_app_setting) {
Toast.makeText(this, "You Clicked " + item.getTitle(), Toast.LENGTH_SHORT).show();
} else if (id == R.id.mm_logout) {
clearToken(getApplicationContext());
Toast.makeText(this, "Logout successful.", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
animationChanger(this);
}
return true;
});
popupMenu.show();
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.user_action_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
if (id == R.id.user) {
Intent intent = new Intent(this, UserProfileActivity.class);
startActivity(intent);
animationChanger(this);
} else {
Toast.makeText(this, "No item.", Toast.LENGTH_SHORT).show();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
super.onBackPressed();
animationChanger(this);
}
private void connectWebSocket() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(EMOTIONAL_VIDEO_PROCESS_WS_URL).build();
webSocket = client.newWebSocket(request, new BabyEmotionWebSocketListener(this, tvLlStatusValue));
}
private void closeWebSocket() {
if (webSocket != null) {
webSocket.close(NORMAL_CLOSURE_STATUS, "Closing WebSocket");
webSocket = null; // Set to null after closing
}
}
}
\ No newline at end of file
package com.kaluwa.enterprises.babycare.adapter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.kaluwa.enterprises.babycare.R;
import com.kaluwa.enterprises.babycare.dto.ActivityLogDto;
import java.util.List;
public class ActivityLogsAdapter extends RecyclerView.Adapter<ActivityLogsAdapter.ActivityLogItemHolder> {
private final static String TAG = "ActivityLogAdapter";
private Context context;
private List<ActivityLogDto> activityLogList;
public ActivityLogsAdapter(Context context, List<ActivityLogDto> activityLogList) {
this.context = context;
this.activityLogList = activityLogList;
}
@NonNull
@Override
public ActivityLogsAdapter.ActivityLogItemHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_activity_log, parent, false);
return new ActivityLogsAdapter.ActivityLogItemHolder(view);
}
@SuppressLint("SetTextI18n")
@Override
public void onBindViewHolder(@NonNull ActivityLogsAdapter.ActivityLogItemHolder holder, int position) {
ActivityLogDto activityLogDto = activityLogList.get(position);
holder.tvActivityLogId.setText(activityLogDto.getActivityLogId().toString());
holder.tvActivityType.setText(activityLogDto.getActivityLogType());
holder.tvDescription.setText(activityLogDto.getActivityLogDescription());
}
@Override
public int getItemCount() {
return activityLogList.size();
}
public static class ActivityLogItemHolder extends RecyclerView.ViewHolder {
public TextView tvActivityLogId, tvActivityType, tvDescription;
public ActivityLogItemHolder(@NonNull View view) {
super(view);
tvActivityLogId = view.findViewById(R.id.tvActivityLogId);
tvActivityType = view.findViewById(R.id.tvActivityType);
tvDescription = view.findViewById(R.id.tvDescription);
}
}
}
...@@ -59,7 +59,7 @@ public class BabyDashboardAdapter extends RecyclerView.Adapter<BabyDashboardAdap ...@@ -59,7 +59,7 @@ public class BabyDashboardAdapter extends RecyclerView.Adapter<BabyDashboardAdap
String sex = babyDto.getSex(); String sex = babyDto.getSex();
String notes = babyDto.getNotes(); String notes = babyDto.getNotes();
Boolean isActive = babyDto.getIsActive(); Boolean isActive = babyDto.getIsActive();
InputStream imageData = babyDto.getImageData(); byte[] imageData = babyDto.getImageData();
if (lastname != null) { if (lastname != null) {
holder.tvBabyName.setText(firstname + " " + lastname); holder.tvBabyName.setText(firstname + " " + lastname);
......
package com.kaluwa.enterprises.babycare.config; package com.kaluwa.enterprises.babycare.config;
import static com.kaluwa.enterprises.babycare.config.TokenSaver.getToken; import static com.kaluwa.enterprises.babycare.config.TokenSaver.getToken;
import static com.kaluwa.enterprises.babycare.constants.Configs.BASE_URL;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.kaluwa.enterprises.babycare.service.ActivityLogsApiService;
import com.kaluwa.enterprises.babycare.service.AuthApiService; import com.kaluwa.enterprises.babycare.service.AuthApiService;
import com.kaluwa.enterprises.babycare.service.BabyApiService; import com.kaluwa.enterprises.babycare.service.BabyApiService;
import com.kaluwa.enterprises.babycare.service.DocumentApiService; import com.kaluwa.enterprises.babycare.service.DocumentApiService;
...@@ -17,7 +19,6 @@ import retrofit2.converter.gson.GsonConverterFactory; ...@@ -17,7 +19,6 @@ import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.jackson.JacksonConverterFactory; import retrofit2.converter.jackson.JacksonConverterFactory;
public class ApiConfig { public class ApiConfig {
private static final String BASE_URL = "http://192.168.1.2:8080/api/v1/baby-care/";
private static ApiConfig instance; private static ApiConfig instance;
private static Retrofit retrofitAuth = null; private static Retrofit retrofitAuth = null;
private static Retrofit retrofitOther = null; private static Retrofit retrofitOther = null;
...@@ -77,4 +78,9 @@ public class ApiConfig { ...@@ -77,4 +78,9 @@ public class ApiConfig {
AUTH_TOKEN = JWTToken; AUTH_TOKEN = JWTToken;
return retrofitOther.create(DocumentApiService.class); return retrofitOther.create(DocumentApiService.class);
} }
public ActivityLogsApiService getActivityLogsApi(String JWTToken) {
AUTH_TOKEN = JWTToken;
return retrofitOther.create(ActivityLogsApiService.class);
}
} }
package com.kaluwa.enterprises.babycare.config;
import android.app.Activity;
import android.util.Log;
import android.widget.TextView;
import org.json.JSONException;
import org.json.JSONObject;
import java.nio.charset.StandardCharsets;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
public class BabyEmotionWebSocketListener extends WebSocketListener {
public static final int NORMAL_CLOSURE_STATUS = 1000;
private final TextView statusValueTextView;
private final Activity activity; // Reference to the Activity
public BabyEmotionWebSocketListener(Activity activity, TextView statusValueTextView) {
this.activity = activity;
this.statusValueTextView = statusValueTextView;
}
@Override
public void onOpen(WebSocket webSocket, Response response) {
// Connection opened
byte[] data = "Hello, WebSocket!".getBytes(StandardCharsets.UTF_8);
webSocket.send(ByteString.of(data));
}
@Override
public void onMessage(WebSocket webSocket, String text) {
// Parse the received message and update the UI
activity.runOnUiThread(() -> {
try {
JSONObject jsonObject = new JSONObject(text);
String emotion = jsonObject.getString("emotion");
// Capitalize the first letter
String capitalizedEmotion = emotion.substring(0, 1).toUpperCase() + emotion.substring(1);
if (capitalizedEmotion.equals("Null")) {
statusValueTextView.setText("No emotion detected!");
} else {
statusValueTextView.setText(capitalizedEmotion);
}
} catch (JSONException e) {
e.printStackTrace();
}
});
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
onMessage(webSocket, bytes.utf8());
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
Log.e("WebSocket", "Connection closing: " + reason);
webSocket.close(NORMAL_CLOSURE_STATUS, null);
activity.runOnUiThread(() -> statusValueTextView.setText("Connection closed"));
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
Log.e("WebSocket", "Error: " + t.getMessage());
activity.runOnUiThread(() -> statusValueTextView.setText("Connection error: " + t.getMessage()));
}
}
package com.kaluwa.enterprises.babycare.constants;
public class Configs {
public static final String URL = "192.168.1.2:8080/api/v1/baby-care/";
public static final String BASE_URL = "http://"+URL;
public static final String LIVE_FEED_URL = "http://192.168.1.7";
public static final String EMOTIONAL_VIDEO_PROCESS_WS_URL = "ws://"+URL+"emotional/video-process";
public static final int REFRESH_INTERVAL = 100; // Refresh every 100 ms
}
package com.kaluwa.enterprises.babycare.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ActivityLogDto {
private Long activityLogId;
private String activityLogType;
private String activityLogDescription;
}
...@@ -49,9 +49,7 @@ public class BabyDto { ...@@ -49,9 +49,7 @@ public class BabyDto {
private UserDto user; private UserDto user;
private Long userId; private Long userId;
private Long documentId; private Long documentId;
private byte[] imageData;
@JsonIgnore
private InputStream imageData;
@JsonIgnore @JsonIgnore
private boolean sys_validated; private boolean sys_validated;
......
package com.kaluwa.enterprises.babycare.service;
import com.kaluwa.enterprises.babycare.dto.ActivityLogDto;
import java.util.List;
import retrofit2.Call;
import retrofit2.http.GET;
public interface ActivityLogsApiService {
@GET("activity-logs")
Call<List<ActivityLogDto>> getAllActivityLogs();
}
...@@ -223,6 +223,16 @@ public class Utils { ...@@ -223,6 +223,16 @@ public class Utils {
} }
} }
public static Bitmap convertByteArrayToBitmap(byte[] byteArray) {
try {
return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
} catch (Exception e) {
Log.e(TAG, "Error decoding image byte array: " + e.getMessage());
throw new RuntimeException("Error decoding image byte array");
}
}
public static int dpToPx(Context context, int dp) { public static int dpToPx(Context context, int dp) {
float density = context.getResources().getDisplayMetrics().density; float density = context.getResources().getDisplayMetrics().density;
return Math.round(dp * density); return Math.round(dp * density);
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.LiveFeedActivity">
<include
layout="@layout/appbar"/>
<ImageView
android:id="@+id/background"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/b_care_action_bar"
app:layout_constraintBottom_toBottomOf="parent"
android:src="@drawable/background"
android:contentDescription="background-image"
android:scaleType="centerCrop"
android:alpha="0.4"/>
<LinearLayout
android:id="@+id/llLiveFeedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@+id/background"
app:layout_constraintStart_toStartOf="@id/background"
app:layout_constraintEnd_toEndOf="@id/background"
android:orientation="vertical"
android:gravity="center"
android:padding="16dp">
<ImageView
android:id="@+id/ivLiveFeed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxHeight="450dp"
android:scaleType="centerInside"
android:src="@drawable/live_offline"
android:background="@drawable/borders"/>
<Button
android:id="@+id/lfFlashBtn"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginTop="28dp"
android:layout_marginRight="40dp"
android:background="@drawable/positive_btn_background"
android:fontFamily="@font/abril_fatface_regular"
android:padding="6dp"
android:text="FLASH ON"
android:textColor="@color/white"
android:textSize="18sp" />
</LinearLayout>
<!-- New LinearLayout for displaying the status -->
<LinearLayout
android:id="@+id/llStatusBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/llLiveFeedBox"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:orientation="horizontal"
android:gravity="center"
android:padding="16dp">
<TextView
android:id="@+id/tvLlStatusLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Last Baby's Status:"
android:textColor="@color/black"
android:textSize="18sp"
android:layout_marginEnd="8dp"/>
<TextView
android:id="@+id/tvLlStatusValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No emotion detected!"
android:textColor="@color/black"
android:textStyle="bold"
android:textSize="18sp"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
...@@ -152,15 +152,15 @@ ...@@ -152,15 +152,15 @@
android:id="@+id/l_btn_login" android:id="@+id/l_btn_login"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="LOGIN"
android:textSize="20sp"
android:fontFamily="@font/abril_fatface_regular"
android:layout_marginLeft="40dp" android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:layout_marginTop="28dp" android:layout_marginTop="28dp"
android:layout_marginRight="40dp"
android:background="@drawable/positive_btn_background" android:background="@drawable/positive_btn_background"
android:fontFamily="@font/abril_fatface_regular"
android:padding="6dp" android:padding="6dp"
android:textColor="@color/white"/> android:text="LOGIN"
android:textColor="@color/white"
android:textSize="20sp" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.ActivityLogsActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="@layout/appbar"/>
<ImageView
android:id="@+id/background"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/b_care_action_bar"
app:layout_constraintBottom_toBottomOf="parent"
android:src="@drawable/background"
android:contentDescription="background-image"
android:scaleType="centerCrop"
android:alpha="0.4"/>
<RelativeLayout
android:id="@+id/rl_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/rl_background"
android:backgroundTint="#62178F"
app:layout_constraintTop_toTopOf="@+id/background"
app:layout_constraintStart_toStartOf="@id/background"
app:layout_constraintEnd_toEndOf="@id/background"
android:padding="8dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Activity Notifications"
android:textAlignment="center"
android:textColor="@color/white"
android:textAllCaps="true"
android:fontFamily="@font/inknut_antiqua_regular"
android:textSize="20sp"
android:gravity="center"/>
</RelativeLayout>
<!-- Header Row for the Table -->
<LinearLayout
android:id="@+id/headerRow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@color/gray"
android:paddingTop="6dp"
android:paddingStart="15dp"
android:paddingEnd="15dp"
android:paddingBottom="6dp"
app:layout_constraintTop_toBottomOf="@id/rl_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:text="Id"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/black"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="Activity Type"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/black"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:text="Description"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/black"/>
</LinearLayout>
<!-- RecyclerView for the Table Content -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_activity_notifications"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/headerRow"
app:layout_constraintBottom_toBottomOf="@id/background"
app:layout_constraintEnd_toEndOf="@id/background"
app:layout_constraintStart_toStartOf="@id/background"
android:scrollbars="none"
android:paddingTop="6dp"
android:paddingStart="15dp"
android:paddingEnd="15dp"
android:paddingBottom="6dp"/>
<TextView
android:id="@+id/no_content_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No content available"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:textStyle="bold"
android:visibility="gone"/>
<View
android:id="@+id/overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#99D5C5DF"
android:visibility="gone"
android:clickable="true"
android:focusable="true"/>
<com.github.ybq.android.spinkit.SpinKitView
android:id="@+id/progress_bar"
style="@style/SpinKitView.Large.DoubleBounce"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:SpinKit_Color="@color/purple"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="gone"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">
<TextView
android:id="@+id/tvActivityLogId"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:text="Id"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/tvActivityType"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="Activity Type"
android:textSize="16sp" />
<TextView
android:id="@+id/tvDescription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:text="Description"
android:textSize="16sp" />
</LinearLayout>
\ No newline at end of file
...@@ -9,4 +9,5 @@ ...@@ -9,4 +9,5 @@
<color name="cancel_dark_red">#CC0000</color> <color name="cancel_dark_red">#CC0000</color>
<color name="success_green">#28A745</color> <color name="success_green">#28A745</color>
<color name="success_dark_green">#218838</color> <color name="success_dark_green">#218838</color>
<color name="gray">#D3D3D3</color> <!-- Light gray color -->
</resources> </resources>
\ No newline at end of file
...@@ -12,4 +12,5 @@ ...@@ -12,4 +12,5 @@
<color name="cancel_dark_red">#CC0000</color> <color name="cancel_dark_red">#CC0000</color>
<color name="success_green">#28A745</color> <color name="success_green">#28A745</color>
<color name="success_dark_green">#218838</color> <color name="success_dark_green">#218838</color>
<color name="gray">#D3D3D3</color> <!-- Light gray color -->
</resources> </resources>
\ No newline at end of file
...@@ -4,5 +4,7 @@ ...@@ -4,5 +4,7 @@
<domain includeSubdomains="true">192.168.1.2</domain> <domain includeSubdomains="true">192.168.1.2</domain>
<domain includeSubdomains="true">192.168.1.6</domain> <domain includeSubdomains="true">192.168.1.6</domain>
<domain includeSubdomains="true">192.168.63.103</domain> <domain includeSubdomains="true">192.168.63.103</domain>
<domain includeSubdomains="true">192.168.1.3</domain>
<domain includeSubdomains="true">192.168.1.7</domain>
</domain-config> </domain-config>
</network-security-config> </network-security-config>
...@@ -16,6 +16,7 @@ materialVersion = "1.13.0-alpha02" ...@@ -16,6 +16,7 @@ materialVersion = "1.13.0-alpha02"
swiperefreshlayout = "1.2.0-alpha01" swiperefreshlayout = "1.2.0-alpha01"
converterJackson = "2.11.0" converterJackson = "2.11.0"
jacksonDatatypeJsr310 = "2.17.1" jacksonDatatypeJsr310 = "2.17.1"
okhttp = "5.0.0-alpha.14"
[libraries] [libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" } junit = { group = "junit", name = "junit", version.ref = "junit" }
...@@ -36,6 +37,7 @@ ucrop = { group = "com.github.yalantis", name = "ucrop", version = "2.2.9" } ...@@ -36,6 +37,7 @@ ucrop = { group = "com.github.yalantis", name = "ucrop", version = "2.2.9" }
swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" } swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" }
converter-jackson = { group = "com.squareup.retrofit2", name = "converter-jackson", version.ref = "converterJackson" } converter-jackson = { group = "com.squareup.retrofit2", name = "converter-jackson", version.ref = "converterJackson" }
jackson-datatype-jsr310 = { group = "com.fasterxml.jackson.datatype", name = "jackson-datatype-jsr310", version.ref = "jacksonDatatypeJsr310" } jackson-datatype-jsr310 = { group = "com.fasterxml.jackson.datatype", name = "jackson-datatype-jsr310", version.ref = "jacksonDatatypeJsr310" }
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
[plugins] [plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" } androidApplication = { id = "com.android.application", version.ref = "agp" }
......
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