Skip to content

Commit

Permalink
Merge branch 'hotfix/1.9.5'
Browse files Browse the repository at this point in the history
  • Loading branch information
douglasrafael committed Jan 27, 2020
2 parents 3860fae + 15b6c8b commit a4824cd
Show file tree
Hide file tree
Showing 27 changed files with 193 additions and 142 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ out/
# Gradle files
.gradle/
build/
app/release/

# Local configuration file (sdk path, etc)
local.properties
Expand Down
26 changes: 15 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
# OCARIoT Data Acquisition
[![License][license-image]][license-url] [![Vulnerabilities][known-vulnerabilities-image]][known-vulnerabilities-url] [![Commit][last-commit-image]][last-commit-url] [![Releases][releases-image]][releases-url] [![Contributors][contributors-image]][contributors-url]

[![Download][apk-download]][apk-brazil-url]
[![Download][apk-download]][apk-download-url]

<p align="center"><img width="120" src="https://i.imgur.com/Z31yxK2.png"/></p>

Native Android application responsible for OCARIoT platform data acquisition. The application acts as an external services access token manager. Currently, only Fitbit service is available.

**Main Features:**
- Fitbit access token management:
- The **Child** may grant access to the OCARIoT platform to collect data from their Fitbit account;
- **Family**, **Educator** or **Health Professional** provider can grant access to the OCARIoT platform to collect data from children who have privileges to manage their data.
- Listing of data saved on OCARIoT platform:
- Physical Activity;
- The educator and the qualified professional can grant the OCARIoT platform permission to collect Fitbit data from children who have privileges to manage their data according to the consent of those responsible;
- Support to request collection of Fitbit data from the child at any time, automatically saving to the OCARIoT platform;
- Revocation of permission to collect Fitbit data;

- Display of data saved on the OCARIoT platform:
- Physical activity;
- Sleep;
- Weight.
- Display of Heart Rate data collected in real time from Polar OH1 device.
- Support for Fitbit data synchronization with OCARIoT platform.
- Fitbit access revocation.

- Display of heart rate data collected in real time. Supported devices:
- Polar OH;
- Polar H10.


## Prerequisites
- Android SDK v28
Expand All @@ -28,7 +33,6 @@ Native Android application responsible for OCARIoT platform data acquisition. Th

```console
git clone https://github.com/ocariot/da-app.git

```
2. **Set up the environment:**
- Make a copy of the `gradle.properties.example` file in the `/app` directory named `gradle.properties` _(This file will not be tracked by git because it is in .gitignore)_.
Expand Down Expand Up @@ -66,13 +70,13 @@ From Android Studio:
[contributors-image]: https://img.shields.io/github/contributors/ocariot/da-app.svg
[contributors-url]: https://github.com/ocariot/da-app/graphs/contributors
[apk-download]: https://img.shields.io/badge/download%20apk-BR/EU-blue.svg?style=for-the-badge&logo=android
[apk-brazil-url]: https://github.com/ocariot/da-app/releases/download/1.9.3/ocariot_da_v1.9.3.apk
[apk-download-url]: https://play.google.com/store/apps/details?id=br.edu.uepb.nutes.ocariot

---

### Screenshots

<img align="left" src="https://i.imgur.com/zc7UN5k.png" width="200" />
<img align="left" src="https://i.imgur.com/ttlvzao.png" width="200" />
<img align="left" src="https://i.imgur.com/5WLaJlq.png" width="200" />
<img align="left" src="https://i.imgur.com/c5WjiZn.png" width="200" />
<img src="https://i.imgur.com/gxOEdZq.png" width="200" />
Expand Down
6 changes: 3 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ android {
applicationId "br.edu.uepb.nutes.ocariot"
minSdkVersion 21
targetSdkVersion 28
versionCode 10
versionName "1.9.4"
versionCode 11
versionName "1.9.5"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

manifestPlaceholders = [
Expand Down Expand Up @@ -92,7 +92,7 @@ dependencies {
implementation 'com.github.nutes-uepb:simple-ble-scanner:v1.0.1'

// Firebase SDK for Google Analytics
implementation 'com.google.firebase:firebase-analytics:17.2.1'
implementation 'com.google.firebase:firebase-analytics:17.2.2'
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'

// Logs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class Child extends User implements Comparable<Child> {
private String gender;

@SerializedName("age")
private int age;
private String age;

@SerializedName("last_sync")
private String lastSync;
Expand All @@ -48,11 +48,11 @@ public void setGender(String gender) {
this.gender = gender;
}

public int getAge() {
public String getAge() {
return age;
}

public void setAge(int age) {
public void setAge(String age) {
this.age = age;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package br.edu.uepb.nutes.ocariot.data.repository.remote;

import android.annotation.SuppressLint;

import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
Expand All @@ -14,6 +16,8 @@

import br.edu.uepb.nutes.ocariot.BuildConfig;
import br.edu.uepb.nutes.ocariot.OcariotApp;
import br.edu.uepb.nutes.ocariot.exception.ConnectivityException;
import br.edu.uepb.nutes.ocariot.utils.ConnectionUtils;
import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
Expand All @@ -39,8 +43,11 @@ public BaseNetRepository() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(s -> Timber.tag("OkHttp").d(s));
logging.level(HttpLoggingInterceptor.Level.BODY);
this.addInterceptor(logging);
this.addInterceptor(new NetworkConnectionInterceptor());
}
this.addInterceptor(chain -> {
if (!ConnectionUtils.isNetworkAvailable(OcariotApp.getContext())) throw new ConnectivityException();
return chain.proceed(chain.request().newBuilder().build());
});
}

protected Retrofit provideRetrofit(String baseUrl) {
Expand Down Expand Up @@ -79,11 +86,13 @@ private OkHttpClient.Builder getUnsafeOkHttpClient() {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@SuppressLint("TrustAllX509TrustManager")
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
// Not implemented!
}

@SuppressLint("TrustAllX509TrustManager")
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
// Not implemented!
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package br.edu.uepb.nutes.ocariot.utils;

import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

/**
* Provides routines for checking connection with internet and bluetooth.
*
* @author Douglas Rafael <[email protected]>
* @version 0.1
* @copyright Copyright (c) 2017, NUTES/UEPB
*/
public class ConnectionUtils {
/**
* Checks if the device supports bluetooth.
*
* @return true for device supports bluetooth or false otherwise.
*/
public static boolean isSupportedBluetooth() {
return BluetoothAdapter.getDefaultAdapter() != null;
}

/**
* Checks if bluetooth is enabled.
*
* @return true to enabled or false otherwise.
*/
public static boolean isBluetoothAvailable() {
return BluetoothAdapter.getDefaultAdapter() != null &&
BluetoothAdapter.getDefaultAdapter().isEnabled();
}

/**
* Checks if the device has an internet connection.
*
* @param context
* @return boolean
*/
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnectedOrConnecting());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ public static Date convertDateTime(String datetime) {
public static String convertDateTimeToUTC(String datetime) {
if (datetime == null) return null;

Date dateUTC = null;
Date dateUTC;
DateFormat formatUTC = new SimpleDateFormat(DateUtils.DATE_FORMAT_DATE_TIME, Locale.getDefault());

try {
dateUTC = formatUTC.parse(datetime);
formatUTC.setTimeZone(TimeZone.getTimeZone("UTC"));
if (datetime.contains("Z")) formatUTC.setTimeZone(TimeZone.getTimeZone("UTC"));
} catch (ParseException e) {
return "";
}
Expand All @@ -103,13 +103,13 @@ public static String convertDateTimeUTCToLocale(String datetime, String formatDa
if (timezone == null) timezone = TimeZone.getDefault();
if (formatDate == null) formatDate = DateUtils.DATE_FORMAT_DATE_TIME;

Date dateUTC = null;
Date dateUTC;
DateFormat formatLocale = new SimpleDateFormat(formatDate, Locale.getDefault());
formatLocale.setTimeZone(timezone);

try {
DateFormat utcFormat = new SimpleDateFormat(DateUtils.DATE_FORMAT_DATE_TIME, Locale.getDefault());
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
if (datetime.contains("Z")) utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
dateUTC = utcFormat.parse(datetime);
} catch (ParseException e) {
return "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
Expand All @@ -12,6 +13,7 @@
import androidx.annotation.Nullable;

import br.edu.uepb.nutes.ocariot.R;
import timber.log.Timber;

/**
* Dialog Loading.
Expand Down Expand Up @@ -80,12 +82,21 @@ public void show(FragmentManager fragmentManager) {
}
}

@Override
public void show(FragmentManager manager, String tag) {
try {
super.show(manager, tag);
} catch (IllegalStateException e) {
Timber.d(e);
}
}

public void close() {
if (fragmentManager == null) return;
Fragment dialogFragment = fragmentManager.findFragmentByTag(DIALOG_TAG);

if (dialogFragment != null && this.isVisible()) {
this.dismiss();
if (dialogFragment != null && super.isVisible()) {
super.dismissAllowingStateLoss();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package br.edu.uepb.nutes.ocariot.view.adapter;

import android.content.Context;
import android.content.res.ColorStateList;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.core.widget.ImageViewCompat;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
Expand Down Expand Up @@ -69,13 +68,8 @@ public void showData(RecyclerView.ViewHolder holder, int position, List<Child> i
}

// Fitbit status
ColorStateList colorFitbitStatus = ColorStateList.valueOf(mContext.getResources()
.getColor(R.color.colorFitbitInactive));
if (child.isFitbitAccessValid()) {
colorFitbitStatus = ColorStateList.valueOf(mContext.getResources()
.getColor(R.color.colorFitbitActive));
}
ImageViewCompat.setImageTintList(h.fitBitStatus, colorFitbitStatus);
h.fitBitStatus.setChecked(false);
if (child.isFitbitAccessValid()) h.fitBitStatus.setChecked(true);

// Gender
if (child.getGender().equalsIgnoreCase("male")) {
Expand Down Expand Up @@ -143,8 +137,8 @@ class ViewHolderChild extends RecyclerView.ViewHolder {
@BindView(R.id.child_last_sync_tv)
TextView lastSync;

@BindView(R.id.fitbit_status_img)
ImageView fitBitStatus;
@BindView(R.id.fitbit_status_cb)
CheckBox fitBitStatus;

@BindView(R.id.gender_img)
ImageView gender;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ public void showData(RecyclerView.ViewHolder holder, int position, List<Sleep> i
final Sleep sleep = itemsList.get(position);
ViewHolderSleep h = (ViewHolderSleep) holder;

h.dateStart.setText(DateUtils.convertDateTimeUTCToLocale(sleep.getStartTime(),
h.dateStart.setText(DateUtils.convertDateTimeUTCToLocale(sleep.getEndTime(),
context.getResources().getString(R.string.date_time_abb4), null));
h.period.setText(String.format(Locale.getDefault(), "%s - %s",
DateUtils.convertDateTimeUTCToLocale(sleep.getStartTime(),
context.getResources().getString(R.string.hour_format2), null),
context.getResources().getString(R.string.hour_format1), null),
DateUtils.convertDateTimeUTCToLocale(sleep.getEndTime(),
context.getResources().getString(R.string.hour_format2), null)));
context.getResources().getString(R.string.hour_format1), null)));
h.duration.setText(String.format(Locale.getDefault(), "%02dhrs %02dmin",
sleep.getDuration() / 3600000, (sleep.getDuration() / 60000) % 60));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private void initToolbar() {
mActionBar.setHomeAsUpIndicator(R.drawable.ic_close_dark);

if (sleep.getStartTime() != null) {
mActionBar.setTitle(DateUtils.convertDateTimeUTCToLocale(sleep.getStartTime(),
mActionBar.setTitle(DateUtils.convertDateTimeUTCToLocale(sleep.getEndTime(),
getString(R.string.date_time_abb4), null));
}
mActionBar.setSubtitle(appPref.getLastSelectedChild().getUsername());
Expand Down
Loading

0 comments on commit a4824cd

Please sign in to comment.