Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.dpppt.android.app">

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
Expand Down Expand Up @@ -36,6 +37,16 @@
android:name="org.dpppt.android.app.onboarding.OnboardingActivity"
android:launchMode="singleTop" />

<service android:name=".network.CheckConnectionStatus"
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JobService to register a callback or a receiver for first time

android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true"
/>

<receiver android:name=".notifications.BootReceived" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>

</manifest>
52 changes: 13 additions & 39 deletions app/src/main/java/org/dpppt/android/app/MainApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,13 @@
package org.dpppt.android.app;

import android.app.Application;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;

import org.dpppt.android.app.network.ScheduleMonitoringStatusNetwork;
import org.dpppt.android.app.notifications.NotificationService;
import org.dpppt.android.sdk.DP3T;
import org.dpppt.android.sdk.TracingStatus;
import org.dpppt.android.sdk.internal.backend.models.ApplicationInfo;
Expand All @@ -27,13 +22,17 @@

public class MainApplication extends Application {

private static final String NOTIFICATION_CHANNEL_ID = "contact-channel";
private NotificationService notificationService;

@Override
public void onCreate() {
super.onCreate();

notificationService = new NotificationService(getApplicationContext());

if (ProcessUtil.isMainProcess(this)) {
registerReceiver(broadcastReceiver, DP3T.getUpdateIntentFilter());
ScheduleMonitoringStatusNetwork.scheduleJob(this);
DP3T.init(this, new ApplicationInfo("it.noiapp.demo", "https://protetti.app/"));
}
}
Expand All @@ -56,42 +55,17 @@ public void onReceive(Context context, Intent intent) {
if (status.wasContactExposed()) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel();
}

Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
PendingIntent contentIntent = null;
if (launchIntent != null) {
contentIntent =
PendingIntent.getActivity(context, 0, launchIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notificationService.createNotificationChannel();
}
Notification notification =
new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setContentTitle(context.getString(R.string.push_exposed_title))
.setContentText(context.getString(R.string.push_exposed_text))
.setPriority(NotificationCompat.PRIORITY_MAX)
.setSmallIcon(R.drawable.ic_begegnungen)
.setContentIntent(contentIntent)
.build();

NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(42, notification);

prefs.edit().putBoolean("notification_shown", true).commit();
notificationService.pushNotification(
context.getString(R.string.push_exposed_title),
context.getString(R.string.push_exposed_text),
NotificationService.NOTIFICATION_ID
);
}
}
}
};

@RequiresApi(api = Build.VERSION_CODES.O)
private void createNotificationChannel() {
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move in new class notification\NotificationService

NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String channelName = getString(R.string.app_name);
NotificationChannel channel =
new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_HIGH);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
notificationManager.createNotificationChannel(channel);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

public class MainActivity extends FragmentActivity {

private static final String PREFS_COVID = "PREFS_COVID";
public static final String PREFS_COVID = "PREFS_COVID";
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change visibility to use in other parts

private static final String PREF_KEY_ONBOARDING_COMPLETED = "PREF_KEY_ONBOARDING_COMPLETED";

private static final int REQ_ONBOARDING = 123;
Expand Down
54 changes: 46 additions & 8 deletions app/src/main/java/org/dpppt/android/app/main/MainFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
Expand All @@ -18,6 +20,7 @@
import org.dpppt.android.app.R;
import org.dpppt.android.app.contacts.ContactsFragment;
import org.dpppt.android.app.debug.DebugFragment;
import org.dpppt.android.app.main.model.AppState;
import org.dpppt.android.app.util.DebugUtils;
import org.dpppt.android.app.main.views.HeaderView;
import org.dpppt.android.app.notifications.NotificationsFragment;
Expand Down Expand Up @@ -67,6 +70,18 @@ private void setupHeader(View view) {
headerView = view.findViewById(R.id.main_header_container);
tracingViewModel.getAppStateLiveData()
.observe(getViewLifecycleOwner(), appState -> headerView.setState(appState));

tracingViewModel.getNetworkEnableLiveData()
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds new liveData to intercept changes of the network connection by change the UI according to this input

.observe(getViewLifecycleOwner(),
networkStatus -> {

if (networkStatus) {
headerView.setState(AppState.NETWORK_OK);
return;
}

headerView.setState(AppState.NETWORK_KO);
});
}

private void setupCards(View view) {
Expand All @@ -78,16 +93,23 @@ private void setupCards(View view) {
View contactStatusView = view.findViewById(R.id.contacts_status);
tracingViewModel.getTracingEnabledLiveData().observe(getViewLifecycleOwner(),
isTracing -> {
List<TracingStatus.ErrorState> errors = tracingViewModel.getErrorsLiveData().getValue();
TracingStatusHelper.State state = errors.size() > 0 || !isTracing ? TracingStatusHelper.State.WARNING :
TracingStatusHelper.State.OK;
int titleRes = state == TracingStatusHelper.State.OK ? R.string.tracing_active_title
: R.string.tracing_error_title;
int textRes = state == TracingStatusHelper.State.OK ? R.string.tracing_active_text
: R.string.tracing_error_text;
TracingStatusHelper.updateStatusView(contactStatusView, state, titleRes, textRes);
assignInformationNotice(contactStatusView, isTracing);
});

tracingViewModel.getNetworkEnableLiveData()
.observe(getViewLifecycleOwner(),
networkStatus -> {
Boolean status = tracingViewModel.getTracingEnabledLiveData().getValue();
assignInformationNotice(contactStatusView, status);

if (!networkStatus) {
TextView textView = contactStatusView.findViewById(R.id.status_text);
textView.setText(String.format("%s %s",
textView.getText(),
getString(R.string.warning_text_network_ko)));
}
});

view.findViewById(R.id.card_notifications).setOnClickListener(
v -> getParentFragmentManager().beginTransaction()
.replace(R.id.main_fragment_container, NotificationsFragment.newInstance())
Expand Down Expand Up @@ -123,6 +145,22 @@ private void setupCards(View view) {
});
}

private void assignInformationNotice(View contactStatusView, Boolean isTracing) {
TracingStatusHelper.State state = revealTracingStatus(isTracing);
int titleRes = state == TracingStatusHelper.State.OK ? R.string.tracing_active_title
: R.string.tracing_error_title;
int textRes = state == TracingStatusHelper.State.OK ? R.string.tracing_active_text
: R.string.tracing_error_text;
TracingStatusHelper.updateStatusView(contactStatusView, state, titleRes, textRes);
}

private TracingStatusHelper.State revealTracingStatus(Boolean isTracing) {
List<TracingStatus.ErrorState> errors = tracingViewModel.getErrorsLiveData().getValue();
assert errors != null;
return errors.size() > 0 || !isTracing ? TracingStatusHelper.State.WARNING :
TracingStatusHelper.State.OK;
}

private void setupDebugButton(View view) {
View debugButton = view.findViewById(R.id.main_button_debug);
if (DebugUtils.isDev()) {
Expand Down
28 changes: 28 additions & 0 deletions app/src/main/java/org/dpppt/android/app/main/TracingViewModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

import org.dpppt.android.app.debug.model.DebugAppState;
import org.dpppt.android.app.main.model.AppState;
import org.dpppt.android.app.network.InfoStatusNetwork;
import org.dpppt.android.app.util.DebugUtils;
import org.dpppt.android.app.util.DeviceFeatureHelper;
import org.dpppt.android.sdk.DP3T;
import org.dpppt.android.sdk.TracingStatus;
Expand All @@ -43,6 +45,21 @@ public void onReceive(Context context, Intent intent) {
private final MutableLiveData<List<TracingStatus.ErrorState>> errorsLiveData = new MutableLiveData<>(Collections.emptyList());
private final MutableLiveData<AppState> appStateLiveData = new MutableLiveData<>();

private final MutableLiveData<Boolean> networkEnableLiveData = new MutableLiveData<>();
private BroadcastReceiver networkReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
DebugUtils.logDebug("onReceive viewmodel");

if (InfoStatusNetwork.UPDATE_NETWORK_STATUS.equals(intent.getAction())) {
DebugUtils.logDebug("onReceive changeNetworkStatus");

changeNetworkStatus();
}
}
};


private final MutableLiveData<Boolean> bluetoothEnabledLiveData = new MutableLiveData<>();
private BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
@Override
Expand All @@ -63,6 +80,7 @@ public TracingViewModel(@NonNull Application application) {
tracingEnabledLiveData.setValue(status.isAdvertising() && status.isReceiving());
numberOfHandshakesLiveData.setValue(status.getNumberOfHandshakes());
tracingStatusWrapper.setStatus(status);
changeNetworkStatus();

exposedLiveData.setValue(new Pair<>(tracingStatusWrapper.isReportedAsExposed(), tracingStatusWrapper.wasContactExposed()));

Expand All @@ -76,6 +94,7 @@ public TracingViewModel(@NonNull Application application) {

application.registerReceiver(tracingStatusBroadcastReceiver, DP3T.getUpdateIntentFilter());
application.registerReceiver(bluetoothReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
application.registerReceiver(networkReceiver, InfoStatusNetwork.getUpdateIntentFilter());
}

public void resetSdk(Runnable onDeleteListener) {
Expand Down Expand Up @@ -113,6 +132,10 @@ public LiveData<Boolean> getBluetoothEnabledLiveData() {
return bluetoothEnabledLiveData;
}

public MutableLiveData<Boolean> getNetworkEnableLiveData() {
return networkEnableLiveData;
}

public void setTracingEnabled(boolean enabled) {
if (enabled) {
DP3T.start(getApplication());
Expand All @@ -132,10 +155,15 @@ private void invalidateBluetoothState() {
bluetoothEnabledLiveData.setValue(DeviceFeatureHelper.isBluetoothEnabled());
}

private void changeNetworkStatus() {
networkEnableLiveData.setValue(InfoStatusNetwork.isConnect(getApplication().getApplicationContext()));
}

@Override
protected void onCleared() {
getApplication().unregisterReceiver(tracingStatusBroadcastReceiver);
getApplication().unregisterReceiver(bluetoothReceiver);
getApplication().unregisterReceiver(networkReceiver);
}

public DebugAppState getDebugAppState() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ public enum AppState {
TRACING,
ERROR,
EXPOSED,
EXPOSED_ERROR
EXPOSED_ERROR,
NETWORK_OK,
NETWORK_KO,
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import android.view.animation.*;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;

Expand Down Expand Up @@ -122,13 +124,18 @@ public void setState(AppState state) {
int iconRes = 0;
switch (state) {
case TRACING:
case NETWORK_OK:
iconRes = (R.drawable.ic_header_check);
backgroundColor = getResources().getColor(R.color.status_green, null);
break;
case ERROR:
iconRes = (R.drawable.ic_header_error);
backgroundColor = getResources().getColor(R.color.status_red, null);
break;
case NETWORK_KO:
iconRes = (R.drawable.ic_header_info);
backgroundColor = getResources().getColor(R.color.status_red, null);
break;
case EXPOSED_ERROR:
case EXPOSED:
iconRes = (R.drawable.ic_header_info);
Expand Down Expand Up @@ -161,7 +168,9 @@ public void setState(AppState state) {
}

stopArcAnimation();
if (state != AppState.ERROR && state != AppState.EXPOSED_ERROR) {
if (state != AppState.ERROR &&
state != AppState.EXPOSED_ERROR &&
state != AppState.NETWORK_KO) {
arcRunnable = new ArcRunnable(3);
arcHandler.postDelayed(arcRunnable, initialUpdate ? INITIAL_DELAY_ARC : 0);
}
Expand Down
Loading