From 92367585a9385fb39ad52391302986b02e27ae22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20L=C3=A4nge?= Date: Thu, 15 Sep 2022 15:05:49 +0200 Subject: [PATCH 1/4] Upgrade Android Gradle Plugin version to 7.2.2 --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 5ea9881..a4ad8f1 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.1' + classpath 'com.android.tools.build:gradle:7.2.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 02c5c99..4a88a51 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,8 +1,6 @@ -#Tue May 14 12:15:43 CEST 2019 +#Thu Sep 15 14:42:43 CEST 2022 distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip -distributionSha256Sum=53b71812f18cdb2777e9f1b2a0f2038683907c90bdc406bc64d8b400e1fb2c3b - +zipStoreBase=GRADLE_USER_HOME From 0b7460e76987927429555d16199b9a89e6438808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20L=C3=A4nge?= Date: Wed, 12 Oct 2022 18:50:52 +0200 Subject: [PATCH 2/4] Automated migration to AndroidX and some fixes --- app/build.gradle | 10 ++--- .../activities/AboutActivity.java | 4 +- .../AppCompatPreferenceActivity.java | 10 ++--- .../activities/BaseActivity.java | 16 ++++---- .../activities/ExerciseActivity.java | 37 +++++++++---------- .../activities/ExerciseSetActivity.java | 19 +++++----- .../MotivationAlertTextsActivity.java | 12 +++--- .../activities/SettingsActivity.java | 2 +- .../activities/SplashActivity.java | 5 +-- .../activities/StatisticsActivity.java | 4 +- .../activities/WorkoutActivity.java | 11 ++---- .../adapters/DialogAdapter.java | 13 +++---- .../adapters/ExerciseAdapter.java | 7 ++-- .../adapters/ExerciseSetAdapter.java | 5 +-- .../adapters/MotivationAlertTextsAdapter.java | 4 +- .../adapters/ReportAdapter.java | 6 +-- .../fragments/DailyReportFragment.java | 6 +-- .../fragments/ExerciseDialogFragment.java | 32 ++++++---------- .../fragments/ExerciseSetDialogFragment.java | 8 ++-- .../fragments/MonthlyReportFragment.java | 6 +-- .../fragments/StatisticsFragment.java | 16 ++++---- .../fragments/WeeklyReportFragment.java | 6 +-- .../receivers/MotivationAlertReceiver.java | 6 +-- .../services/TimerService.java | 2 +- .../tutorial/TutorialActivity.java | 6 +-- .../activity_about_with_navigationdrawer.xml | 16 ++++---- app/src/main/res/layout/activity_exercise.xml | 18 ++++----- .../main/res/layout/activity_exercisesets.xml | 16 ++++---- app/src/main/res/layout/activity_help.xml | 16 ++++---- app/src/main/res/layout/activity_main.xml | 6 +-- .../activity_motivation_alert_texts.xml | 8 ++-- app/src/main/res/layout/activity_settings.xml | 12 +++--- .../main/res/layout/activity_statistics.xml | 10 ++--- app/src/main/res/layout/activity_tutorial.xml | 2 +- app/src/main/res/layout/activity_workout.xml | 10 ++--- app/src/main/res/layout/app_bar_main.xml | 6 +-- .../res/layout/card_activity_bar_chart.xml | 4 +- .../main/res/layout/card_activity_chart.xml | 4 +- .../main/res/layout/card_activity_summary.xml | 4 +- app/src/main/res/layout/card_dialog.xml | 4 +- app/src/main/res/layout/card_exercise.xml | 4 +- app/src/main/res/layout/card_exerciseset.xml | 4 +- .../layout/content_motivation_alert_texts.xml | 4 +- app/src/main/res/layout/exercise_dialog.xml | 12 +++--- .../main/res/layout/exerciseset_dialog.xml | 14 +++---- .../main/res/layout/fragment_daily_report.xml | 2 +- .../main/res/layout/fragment_statistics.xml | 4 +- app/src/main/res/layout/toolbar.xml | 6 +-- gradle.properties | 4 +- 49 files changed, 214 insertions(+), 229 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 3a66036..a2289a2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -31,11 +31,11 @@ repositories { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:appcompat-v7:28.0.0' - implementation 'com.android.support:design:28.0.0' - implementation 'com.android.support:support-v4:28.0.0' - implementation 'com.android.support:cardview-v7:28.0.0' - implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'androidx.appcompat:appcompat:1.0.0' + implementation 'com.google.android.material:material:1.0.0' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.cardview:cardview:1.0.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'com.github.PhilJay:MPAndroidChart:v3.0.0-beta1' implementation 'com.github.bumptech.glide:glide:4.9.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/AboutActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/AboutActivity.java index 0b3afbb..d851580 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/AboutActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/AboutActivity.java @@ -15,8 +15,8 @@ package org.secuso.privacyfriendlycircuittraining.activities; import android.os.Bundle; -import android.support.v7.app.ActionBar; -import android.support.v7.app.AppCompatActivity; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; import android.text.method.LinkMovementMethod; import android.view.View; import android.widget.TextView; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/AppCompatPreferenceActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/AppCompatPreferenceActivity.java index 76ed398..329b3b7 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/AppCompatPreferenceActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/AppCompatPreferenceActivity.java @@ -17,11 +17,11 @@ import android.content.res.Configuration; import android.os.Bundle; import android.preference.PreferenceActivity; -import android.support.annotation.LayoutRes; -import android.support.annotation.Nullable; -import android.support.v7.app.ActionBar; -import android.support.v7.app.AppCompatDelegate; -import android.support.v7.widget.Toolbar; +import androidx.annotation.LayoutRes; +import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; import android.view.MenuInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/BaseActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/BaseActivity.java index b4f9642..a8455ba 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/BaseActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/BaseActivity.java @@ -20,14 +20,14 @@ import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; -import android.support.design.widget.NavigationView; -import android.support.design.widget.NavigationView.OnNavigationItemSelectedListener; -import android.support.v4.app.TaskStackBuilder; -import android.support.v4.view.GravityCompat; -import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.ActionBarDrawerToggle; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; +import com.google.android.material.navigation.NavigationView; +import com.google.android.material.navigation.NavigationView.OnNavigationItemSelectedListener; +import androidx.core.app.TaskStackBuilder; +import androidx.core.view.GravityCompat; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; import android.view.MenuItem; import android.view.View; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/ExerciseActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/ExerciseActivity.java index 7495f68..84c9d7e 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/ExerciseActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/ExerciseActivity.java @@ -20,15 +20,14 @@ import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; -import android.net.Uri; import android.os.Bundle; -import android.support.design.widget.FloatingActionButton; -import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.ActionBar; -import android.support.v7.widget.DefaultItemAnimator; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.util.Log; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.appcompat.app.ActionBar; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import android.view.View; import android.widget.CheckBox; import android.widget.LinearLayout; @@ -90,13 +89,13 @@ protected void onCreate(Bundle savedInstanceState) { acceptFab = (FloatingActionButton) findViewById(R.id.fab_accept_item_ex); noListsLayout = (LinearLayout) findViewById(R.id.no_lists_layout_ex); - deleteFab.setVisibility(View.GONE); + ((View)deleteFab).setVisibility(View.GONE); if(is_in_picker_mode) { - acceptFab.setVisibility(View.VISIBLE); - newListFab.setVisibility(View.GONE); + ((View)acceptFab).setVisibility(View.VISIBLE); + ((View)newListFab).setVisibility(View.GONE); }else{ - acceptFab.setVisibility(View.GONE); - newListFab.setVisibility(View.VISIBLE); + ((View)acceptFab).setVisibility(View.GONE); + ((View)newListFab).setVisibility(View.VISIBLE); } noListsLayout.setVisibility(View.VISIBLE); setNoExererciseMessage(); @@ -214,9 +213,9 @@ public void clearActionMode(){ is_in_picker_mode = false; if(is_in_delete_mode) selection_list.clear(); - newListFab.setVisibility(View.VISIBLE); - deleteFab.setVisibility(View.GONE); - acceptFab.setVisibility(View.GONE); + ((View)newListFab).setVisibility(View.VISIBLE); + ((View)deleteFab).setVisibility(View.GONE); + ((View)acceptFab).setVisibility(View.GONE); getSupportActionBar().setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.colorPrimary))); this.getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimary)); } @@ -238,9 +237,9 @@ public boolean onLongClick(View v) { is_in_delete_mode = true; mAdapter.notifyDataSetChanged(); //getSupportActionBar().setDisplayHomeAsUpEnabled(true); - newListFab.setVisibility(View.GONE); - deleteFab.setVisibility(View.VISIBLE); - acceptFab.setVisibility(View.GONE); + ((View)newListFab).setVisibility(View.GONE); + ((View)deleteFab).setVisibility(View.VISIBLE); + ((View)acceptFab).setVisibility(View.GONE); getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.LTGRAY)); this.getWindow().setStatusBarColor(Color.LTGRAY); } diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/ExerciseSetActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/ExerciseSetActivity.java index 64215eb..0483c6f 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/ExerciseSetActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/ExerciseSetActivity.java @@ -19,10 +19,10 @@ import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; -import android.support.design.widget.FloatingActionButton; -import android.support.v7.widget.DefaultItemAnimator; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.View; import android.widget.CheckBox; import android.widget.LinearLayout; @@ -32,7 +32,6 @@ import org.secuso.privacyfriendlycircuittraining.adapters.ExerciseSetAdapter; import org.secuso.privacyfriendlycircuittraining.database.PFASQLiteHelper; import org.secuso.privacyfriendlycircuittraining.fragments.ExerciseSetDialogFragment; -import org.secuso.privacyfriendlycircuittraining.models.Exercise; import org.secuso.privacyfriendlycircuittraining.models.ExerciseSet; import java.util.ArrayList; @@ -79,7 +78,7 @@ protected void onCreate(Bundle savedInstanceState) { deleteFab = (FloatingActionButton) findViewById(R.id.fab_delete_item); noListsLayout = (LinearLayout) findViewById(R.id.no_lists_layout); - deleteFab.setVisibility(View.GONE); + ((View)deleteFab).setVisibility(View.GONE); noListsLayout.setVisibility(View.VISIBLE); setNoExererciseSetsMessage(); @@ -149,8 +148,8 @@ public void setNoExererciseSetsMessage(){ public void clearActionMode(){ is_in_action_mode = false; selection_list.clear(); - newListFab.setVisibility(View.VISIBLE); - deleteFab.setVisibility(View.GONE); + ((View)newListFab).setVisibility(View.VISIBLE); + ((View)deleteFab).setVisibility(View.GONE); getSupportActionBar().setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.colorPrimary))); this.getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimary)); } @@ -171,8 +170,8 @@ public boolean onLongClick(View v) { is_in_action_mode = true; mAdapter.notifyDataSetChanged(); //getSupportActionBar().setDisplayHomeAsUpEnabled(true); - newListFab.setVisibility(View.GONE); - deleteFab.setVisibility(View.VISIBLE); + ((View)newListFab).setVisibility(View.GONE); + ((View)deleteFab).setVisibility(View.VISIBLE); getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.LTGRAY)); this.getWindow().setStatusBarColor(Color.LTGRAY); return true; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/MotivationAlertTextsActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/MotivationAlertTextsActivity.java index f822b8c..f1091c9 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/MotivationAlertTextsActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/MotivationAlertTextsActivity.java @@ -18,12 +18,12 @@ import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; -import android.support.design.widget.FloatingActionButton; -import android.support.v7.app.AlertDialog; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.helper.ItemTouchHelper; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.ItemTouchHelper; import android.util.Log; import android.view.View; import android.widget.EditText; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/SettingsActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/SettingsActivity.java index e4678d2..739aca7 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/SettingsActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/SettingsActivity.java @@ -27,7 +27,7 @@ import android.preference.PreferenceFragment; import android.preference.PreferenceManager; import android.preference.SwitchPreference; -import android.support.v7.app.ActionBar; +import androidx.appcompat.app.ActionBar; import android.view.MenuItem; import org.secuso.privacyfriendlycircuittraining.R; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/SplashActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/SplashActivity.java index 3142ff7..d63401f 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/SplashActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/SplashActivity.java @@ -15,15 +15,12 @@ package org.secuso.privacyfriendlycircuittraining.activities; import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatActivity; import org.secuso.privacyfriendlycircuittraining.R; import org.secuso.privacyfriendlycircuittraining.database.PFASQLiteHelper; -import org.secuso.privacyfriendlycircuittraining.helpers.BitMapUtility; import org.secuso.privacyfriendlycircuittraining.models.Exercise; import org.secuso.privacyfriendlycircuittraining.models.ExerciseSet; import org.secuso.privacyfriendlycircuittraining.tutorial.PrefManager; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/StatisticsActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/StatisticsActivity.java index bc00409..5184c41 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/StatisticsActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/StatisticsActivity.java @@ -17,6 +17,8 @@ import android.os.Bundle; +import androidx.fragment.app.FragmentTransaction; + import org.secuso.privacyfriendlycircuittraining.R; import org.secuso.privacyfriendlycircuittraining.fragments.DailyReportFragment; import org.secuso.privacyfriendlycircuittraining.fragments.MonthlyReportFragment; @@ -39,7 +41,7 @@ protected void onCreate(Bundle savedInstanceState) { // Load first view - final android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); + final FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); fragmentTransaction.replace(R.id.content_frame, new StatisticsFragment(), "StatisticsFragment"); fragmentTransaction.commit(); } diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/WorkoutActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/WorkoutActivity.java index b80bea1..44090a7 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/WorkoutActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/WorkoutActivity.java @@ -22,18 +22,16 @@ import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.os.Bundle; import android.os.IBinder; import android.preference.PreferenceManager; -import android.support.design.widget.FloatingActionButton; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import androidx.core.content.ContextCompat; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; @@ -49,7 +47,6 @@ import org.secuso.privacyfriendlycircuittraining.R; import org.secuso.privacyfriendlycircuittraining.database.PFASQLiteHelper; -import org.secuso.privacyfriendlycircuittraining.helpers.BitMapUtility; import org.secuso.privacyfriendlycircuittraining.services.TimerService; import java.util.ArrayList; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/DialogAdapter.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/DialogAdapter.java index e158896..0145b64 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/DialogAdapter.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/DialogAdapter.java @@ -24,12 +24,13 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.support.v7.widget.CardView; -import android.support.v7.widget.RecyclerView; + +import androidx.annotation.NonNull; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.CheckBox; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; @@ -37,14 +38,11 @@ import com.bumptech.glide.Glide; import org.secuso.privacyfriendlycircuittraining.R; -import org.secuso.privacyfriendlycircuittraining.activities.ExerciseActivity; import org.secuso.privacyfriendlycircuittraining.database.PFASQLiteHelper; -import org.secuso.privacyfriendlycircuittraining.fragments.ExerciseDialogFragment; import org.secuso.privacyfriendlycircuittraining.fragments.ExerciseSetDialogFragment; import org.secuso.privacyfriendlycircuittraining.models.Exercise; import java.util.ArrayList; -import java.util.List; public class DialogAdapter extends RecyclerView.Adapter { @@ -59,6 +57,7 @@ public DialogAdapter(ArrayList exerciseList, Context ctx) { db = new PFASQLiteHelper(ctx); } + @NonNull @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()) @@ -76,7 +75,7 @@ public void onBindViewHolder(MyViewHolder holder, final int position) { holder.deleteButton.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { - exerciseList.remove(position); + exerciseList.remove(holder.getAdapterPosition()); updateAdapter(exerciseList); } }); diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/ExerciseAdapter.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/ExerciseAdapter.java index 49b2aa3..1670e3c 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/ExerciseAdapter.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/ExerciseAdapter.java @@ -22,10 +22,9 @@ */ import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.support.v7.widget.CardView; -import android.support.v7.widget.RecyclerView; + +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/ExerciseSetAdapter.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/ExerciseSetAdapter.java index 861fdc8..0b5d18b 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/ExerciseSetAdapter.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/ExerciseSetAdapter.java @@ -22,8 +22,8 @@ */ import android.content.Context; -import android.support.v7.widget.CardView; -import android.support.v7.widget.RecyclerView; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -37,7 +37,6 @@ import org.secuso.privacyfriendlycircuittraining.activities.ExerciseSetActivity; import org.secuso.privacyfriendlycircuittraining.database.PFASQLiteHelper; import org.secuso.privacyfriendlycircuittraining.fragments.ExerciseSetDialogFragment; -import org.secuso.privacyfriendlycircuittraining.helpers.BitMapUtility; import org.secuso.privacyfriendlycircuittraining.models.ExerciseSet; import java.util.ArrayList; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/MotivationAlertTextsAdapter.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/MotivationAlertTextsAdapter.java index 76cb761..1e3f6d3 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/MotivationAlertTextsAdapter.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/MotivationAlertTextsAdapter.java @@ -15,8 +15,8 @@ package org.secuso.privacyfriendlycircuittraining.adapters; import android.content.Context; -import android.support.v7.widget.PopupMenu; -import android.support.v7.widget.RecyclerView; +import androidx.appcompat.widget.PopupMenu; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.MenuInflater; import android.view.MenuItem; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/ReportAdapter.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/ReportAdapter.java index 5ac8441..c4f664e 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/ReportAdapter.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/adapters/ReportAdapter.java @@ -15,9 +15,9 @@ package org.secuso.privacyfriendlycircuittraining.adapters; import android.content.Context; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.PopupMenu; -import android.support.v7.widget.RecyclerView; +import androidx.core.content.ContextCompat; +import androidx.appcompat.widget.PopupMenu; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/DailyReportFragment.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/DailyReportFragment.java index e8c9a27..964d15a 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/DailyReportFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/DailyReportFragment.java @@ -17,9 +17,9 @@ import android.app.DatePickerDialog; import android.content.Context; import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/ExerciseDialogFragment.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/ExerciseDialogFragment.java index 0be595e..715b95a 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/ExerciseDialogFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/ExerciseDialogFragment.java @@ -17,20 +17,14 @@ import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; -import android.content.ClipData; import android.content.DialogInterface; import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.drawable.BitmapDrawable; import android.net.Uri; -import android.os.Build; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.DialogFragment; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.View; import android.widget.EditText; import android.widget.ImageView; @@ -41,15 +35,8 @@ import org.secuso.privacyfriendlycircuittraining.R; import org.secuso.privacyfriendlycircuittraining.activities.ExerciseActivity; import org.secuso.privacyfriendlycircuittraining.database.PFASQLiteHelper; -import org.secuso.privacyfriendlycircuittraining.helpers.BitMapUtility; import org.secuso.privacyfriendlycircuittraining.models.Exercise; -import java.io.ByteArrayOutputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - import static android.app.Activity.RESULT_OK; /** @@ -61,6 +48,8 @@ public class ExerciseDialogFragment extends DialogFragment { + private static final int SELECT_IMAGE_REQUEST = 1; + private boolean editDialog = false; private static boolean opened; private View v; @@ -175,7 +164,11 @@ public void onClick(View view) { intent.setType("image/*"); - startActivityForResult(Intent.createChooser(intent, ""), 1); + intent.setFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION + | Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + + startActivityForResult(Intent.createChooser(intent, ""), SELECT_IMAGE_REQUEST); // Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); // photoPickerIntent.setType("image/*"); @@ -195,7 +188,7 @@ public void onClick(View view) { @Override public void onActivityResult(int reqCode, int resultCode, Intent data) { - if (resultCode == RESULT_OK && data != null) { + if (reqCode == SELECT_IMAGE_REQUEST && resultCode == RESULT_OK && data != null) { Uri imageUri = data.getData(); Activity a = getActivity(); @@ -204,8 +197,7 @@ public void onActivityResult(int reqCode, int resultCode, Intent data) { return; } - final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - a.getContentResolver().takePersistableUriPermission(imageUri, takeFlags); + a.getContentResolver().takePersistableUriPermission(imageUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); loadedExercise.setImage(imageUri); Glide.with(a).load(imageUri).into(fragment_img); diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/ExerciseSetDialogFragment.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/ExerciseSetDialogFragment.java index d88a072..a1d8163 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/ExerciseSetDialogFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/ExerciseSetDialogFragment.java @@ -19,10 +19,10 @@ import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; -import android.support.design.widget.FloatingActionButton; -import android.support.v4.app.DialogFragment; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import androidx.fragment.app.DialogFragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/MonthlyReportFragment.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/MonthlyReportFragment.java index c997981..df43c67 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/MonthlyReportFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/MonthlyReportFragment.java @@ -18,9 +18,9 @@ import android.content.Context; import android.os.AsyncTask; import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/StatisticsFragment.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/StatisticsFragment.java index 2770e45..82cc5dd 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/StatisticsFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/StatisticsFragment.java @@ -16,13 +16,13 @@ import android.app.Activity; import android.os.Bundle; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentPagerAdapter; -import android.support.v4.view.ViewPager; -import android.support.v7.app.ActionBar; -import android.support.v7.app.AppCompatActivity; +import com.google.android.material.tabs.TabLayout; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.ViewPager; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -93,7 +93,7 @@ public ViewPagerAdapter(FragmentManager manager) { } @Override - public android.support.v4.app.Fragment getItem(int position) { + public Fragment getItem(int position) { return mFragmentList.get(position); } diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/WeeklyReportFragment.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/WeeklyReportFragment.java index 4e88ed4..c6346c1 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/WeeklyReportFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/WeeklyReportFragment.java @@ -18,9 +18,9 @@ import android.content.Context; import android.os.AsyncTask; import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/receivers/MotivationAlertReceiver.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/receivers/MotivationAlertReceiver.java index d2d47ac..4788ba4 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/receivers/MotivationAlertReceiver.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/receivers/MotivationAlertReceiver.java @@ -20,9 +20,9 @@ import android.content.Intent; import android.content.SharedPreferences; import android.preference.PreferenceManager; -import android.support.v4.app.NotificationCompat; -import android.support.v4.content.ContextCompat; -import android.support.v4.content.WakefulBroadcastReceiver; +import androidx.core.app.NotificationCompat; +import androidx.core.content.ContextCompat; +import androidx.legacy.content.WakefulBroadcastReceiver; import android.util.Log; import org.secuso.privacyfriendlycircuittraining.R; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/services/TimerService.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/services/TimerService.java index d20c323..21b888b 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/services/TimerService.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/services/TimerService.java @@ -29,7 +29,7 @@ import android.os.Handler; import android.os.IBinder; import android.preference.PreferenceManager; -import android.support.v4.app.NotificationCompat; +import androidx.core.app.NotificationCompat; import android.widget.RemoteViews; import org.secuso.privacyfriendlycircuittraining.R; diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/tutorial/TutorialActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/tutorial/TutorialActivity.java index 2a1cf63..21361a8 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/tutorial/TutorialActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/tutorial/TutorialActivity.java @@ -19,9 +19,9 @@ import android.graphics.Color; import android.os.Build; import android.os.Bundle; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewPager; -import android.support.v7.app.AppCompatActivity; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; +import androidx.appcompat.app.AppCompatActivity; import android.text.Html; import android.view.LayoutInflater; import android.view.View; diff --git a/app/src/main/res/layout/activity_about_with_navigationdrawer.xml b/app/src/main/res/layout/activity_about_with_navigationdrawer.xml index fb5fe9b..fc69dc9 100644 --- a/app/src/main/res/layout/activity_about_with_navigationdrawer.xml +++ b/app/src/main/res/layout/activity_about_with_navigationdrawer.xml @@ -1,5 +1,5 @@ - - - - - + - + - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_exercise.xml b/app/src/main/res/layout/activity_exercise.xml index 6d0ac17..2d8dfff 100644 --- a/app/src/main/res/layout/activity_exercise.xml +++ b/app/src/main/res/layout/activity_exercise.xml @@ -1,5 +1,5 @@ - - - - - - - + - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_exercisesets.xml b/app/src/main/res/layout/activity_exercisesets.xml index 223766a..64402b1 100644 --- a/app/src/main/res/layout/activity_exercisesets.xml +++ b/app/src/main/res/layout/activity_exercisesets.xml @@ -1,5 +1,5 @@ - - - - - - + - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_help.xml b/app/src/main/res/layout/activity_help.xml index 7745fb2..4bb8676 100644 --- a/app/src/main/res/layout/activity_help.xml +++ b/app/src/main/res/layout/activity_help.xml @@ -1,5 +1,5 @@ - - - - - + - + - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index f6aacad..50e5c85 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,5 +1,5 @@ - - - + diff --git a/app/src/main/res/layout/activity_motivation_alert_texts.xml b/app/src/main/res/layout/activity_motivation_alert_texts.xml index d5992af..5812f86 100644 --- a/app/src/main/res/layout/activity_motivation_alert_texts.xml +++ b/app/src/main/res/layout/activity_motivation_alert_texts.xml @@ -1,13 +1,13 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 41d88cf..1d1c98e 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -1,5 +1,5 @@ - - - + - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml index 4489669..fb04493 100644 --- a/app/src/main/res/layout/activity_statistics.xml +++ b/app/src/main/res/layout/activity_statistics.xml @@ -1,5 +1,5 @@ - - - + - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_tutorial.xml b/app/src/main/res/layout/activity_tutorial.xml index 78a7d05..51a6287 100644 --- a/app/src/main/res/layout/activity_tutorial.xml +++ b/app/src/main/res/layout/activity_tutorial.xml @@ -7,7 +7,7 @@ tools:showIn="@layout/activity_tutorial"> - diff --git a/app/src/main/res/layout/activity_workout.xml b/app/src/main/res/layout/activity_workout.xml index 9d16845..b8ce56b 100644 --- a/app/src/main/res/layout/activity_workout.xml +++ b/app/src/main/res/layout/activity_workout.xml @@ -1,5 +1,5 @@ - - - + - - + diff --git a/app/src/main/res/layout/app_bar_main.xml b/app/src/main/res/layout/app_bar_main.xml index d5781db..406374c 100644 --- a/app/src/main/res/layout/app_bar_main.xml +++ b/app/src/main/res/layout/app_bar_main.xml @@ -1,5 +1,5 @@ - - + diff --git a/app/src/main/res/layout/card_activity_bar_chart.xml b/app/src/main/res/layout/card_activity_bar_chart.xml index 8486bb9..dc39ef7 100644 --- a/app/src/main/res/layout/card_activity_bar_chart.xml +++ b/app/src/main/res/layout/card_activity_bar_chart.xml @@ -5,7 +5,7 @@ android:orientation="vertical"> - - + \ No newline at end of file diff --git a/app/src/main/res/layout/card_activity_chart.xml b/app/src/main/res/layout/card_activity_chart.xml index 3f18505..6091613 100644 --- a/app/src/main/res/layout/card_activity_chart.xml +++ b/app/src/main/res/layout/card_activity_chart.xml @@ -5,7 +5,7 @@ android:orientation="vertical"> - - + \ No newline at end of file diff --git a/app/src/main/res/layout/card_activity_summary.xml b/app/src/main/res/layout/card_activity_summary.xml index ba9991c..dfaeba8 100644 --- a/app/src/main/res/layout/card_activity_summary.xml +++ b/app/src/main/res/layout/card_activity_summary.xml @@ -6,7 +6,7 @@ android:orientation="vertical"> - - + \ No newline at end of file diff --git a/app/src/main/res/layout/card_dialog.xml b/app/src/main/res/layout/card_dialog.xml index f32154b..942dea2 100644 --- a/app/src/main/res/layout/card_dialog.xml +++ b/app/src/main/res/layout/card_dialog.xml @@ -4,7 +4,7 @@ android:layout_height="wrap_content" android:padding="1dp"> - - + \ No newline at end of file diff --git a/app/src/main/res/layout/card_exercise.xml b/app/src/main/res/layout/card_exercise.xml index 4b1c578..fb577dc 100644 --- a/app/src/main/res/layout/card_exercise.xml +++ b/app/src/main/res/layout/card_exercise.xml @@ -4,7 +4,7 @@ android:layout_height="wrap_content" android:padding="5dp"> - - + \ No newline at end of file diff --git a/app/src/main/res/layout/card_exerciseset.xml b/app/src/main/res/layout/card_exerciseset.xml index 58bfa7f..961ceb5 100644 --- a/app/src/main/res/layout/card_exerciseset.xml +++ b/app/src/main/res/layout/card_exerciseset.xml @@ -4,7 +4,7 @@ android:layout_height="wrap_content" android:padding="5dp"> - - + \ No newline at end of file diff --git a/app/src/main/res/layout/content_motivation_alert_texts.xml b/app/src/main/res/layout/content_motivation_alert_texts.xml index 5e81fd8..f10afa8 100644 --- a/app/src/main/res/layout/content_motivation_alert_texts.xml +++ b/app/src/main/res/layout/content_motivation_alert_texts.xml @@ -1,5 +1,5 @@ - - + diff --git a/app/src/main/res/layout/exercise_dialog.xml b/app/src/main/res/layout/exercise_dialog.xml index 0ca27c4..d5230a4 100644 --- a/app/src/main/res/layout/exercise_dialog.xml +++ b/app/src/main/res/layout/exercise_dialog.xml @@ -32,7 +32,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - - - + - - - + - - - + - - - - + diff --git a/app/src/main/res/layout/fragment_daily_report.xml b/app/src/main/res/layout/fragment_daily_report.xml index 6e59a9d..2bd40e9 100644 --- a/app/src/main/res/layout/fragment_daily_report.xml +++ b/app/src/main/res/layout/fragment_daily_report.xml @@ -5,7 +5,7 @@ tools:context="org.secuso.privacyfriendlycircuittraining.fragments.DailyReportFragment"> - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 1d3591c..915f0e6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,6 @@ # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true +android.enableJetifier=true +android.useAndroidX=true \ No newline at end of file From 74e315b2c9ce46349458b458ea261198c08880c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20L=C3=A4nge?= Date: Thu, 13 Oct 2022 14:58:38 +0200 Subject: [PATCH 3/4] Update dependencies and sdk version - add kotlin-android - add 'exported=true' to AndroidManifest.xml --- app/build.gradle | 17 +++++++++-------- app/src/main/AndroidManifest.xml | 5 ++++- build.gradle | 7 +++++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a2289a2..2c8f868 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,12 +1,13 @@ apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' android { - compileSdkVersion 28 + compileSdkVersion 32 defaultConfig { applicationId "org.secuso.privacyfriendlycircuittraining" minSdkVersion 21 - targetSdkVersion 28 + targetSdkVersion 32 versionCode 2 versionName "1.1" } @@ -21,7 +22,7 @@ android { android.applicationVariants.all { variant -> variant.outputs.all { def appName = "pfa-circuit-training" - outputFileName = appName+"-${variant.name}-v${variant.versionName}.apk" + outputFileName = appName + "-${variant.name}-v${variant.versionName}.apk" } } @@ -31,13 +32,13 @@ repositories { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:1.0.0' - implementation 'com.google.android.material:material:1.0.0' + implementation 'androidx.appcompat:appcompat:1.5.1' + implementation 'com.google.android.material:material:1.6.1' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'com.github.PhilJay:MPAndroidChart:v3.0.0-beta1' - implementation 'com.github.bumptech.glide:glide:4.9.0' + implementation 'com.github.bumptech.glide:glide:4.11.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13.2' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 58ae91a..a531918 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -21,6 +21,7 @@ android:theme="@style/AppTheme"> @@ -85,7 +86,9 @@ android:enabled="true" android:exported="true" /> - + diff --git a/build.gradle b/build.gradle index a4ad8f1..e1663dc 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,15 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + ext.kotlin_version = '1.7.10' + repositories { - jcenter() + mavenCentral() google() } dependencies { classpath 'com.android.tools.build:gradle:7.2.2' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -15,7 +18,7 @@ buildscript { allprojects { repositories { - jcenter() + mavenCentral() google() } } From 8d562dd0106972276184173f4ab8726b73969e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20L=C3=A4nge?= Date: Thu, 27 Oct 2022 14:14:07 +0200 Subject: [PATCH 4/4] Implement backup integration - Add SCHEDULE_EXACT_ALARM permission - Add FLAG_IMMUTABLE to PendingIntents --- .gitmodules | 3 + app/build.gradle | 14 ++ app/src/main/AndroidManifest.xml | 53 ++++--- .../PFCircuitTrainingApplication.kt | 21 +++ .../activities/MainActivity.java | 14 +- .../activities/SettingsActivity.java | 14 +- .../backup/BackupCreator.kt | 54 +++++++ .../backup/BackupRestorer.kt | 138 ++++++++++++++++++ .../backup/PFABackupService.kt | 5 + ...GrantExactAlarmPermissionDialogFragment.kt | 38 +++++ .../helpers/NotificationHelper.java | 32 ++-- .../receivers/MotivationAlertReceiver.java | 18 ++- .../services/TimerService.java | 4 +- app/src/main/res/values-de/strings.xml | 3 +- app/src/main/res/values/strings.xml | 4 +- build.gradle | 4 +- gradle/wrapper/gradle-wrapper.properties | 2 +- libs/privacy-friendly-backup-api | 1 + settings.gradle | 2 + 19 files changed, 382 insertions(+), 42 deletions(-) create mode 100644 .gitmodules create mode 100644 app/src/main/java/org/secuso/privacyfriendlycircuittraining/PFCircuitTrainingApplication.kt create mode 100644 app/src/main/java/org/secuso/privacyfriendlycircuittraining/backup/BackupCreator.kt create mode 100644 app/src/main/java/org/secuso/privacyfriendlycircuittraining/backup/BackupRestorer.kt create mode 100644 app/src/main/java/org/secuso/privacyfriendlycircuittraining/backup/PFABackupService.kt create mode 100644 app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/GrantExactAlarmPermissionDialogFragment.kt create mode 160000 libs/privacy-friendly-backup-api diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5fb4a5c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libs/privacy-friendly-backup-api"] + path = libs/privacy-friendly-backup-api + url = https://github.com/SecUSo/privacy-friendly-backup-api.git diff --git a/app/build.gradle b/app/build.gradle index 2c8f868..6f61968 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,5 +1,6 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' android { compileSdkVersion 32 @@ -41,4 +42,17 @@ dependencies { implementation 'com.github.bumptech.glide:glide:4.11.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' testImplementation 'junit:junit:4.13.2' + + def room_version = "2.4.3" + implementation "androidx.room:room-runtime:$room_version" + annotationProcessor "androidx.room:room-compiler:$room_version" + kapt "androidx.room:room-compiler:$room_version" + implementation "androidx.room:room-ktx:$room_version" + + // Backup API + implementation project(':backup-api') + def work_version = '2.7.1' + implementation "androidx.work:work-runtime:$work_version" + implementation "androidx.work:work-runtime-ktx:$work_version" + androidTestImplementation "androidx.work:work-testing:$work_version" } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a531918..d6cfb70 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/PFCircuitTrainingApplication.kt b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/PFCircuitTrainingApplication.kt new file mode 100644 index 0000000..5417598 --- /dev/null +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/PFCircuitTrainingApplication.kt @@ -0,0 +1,21 @@ +package org.secuso.privacyfriendlycircuittraining + +import android.app.Application +import android.util.Log +import androidx.work.Configuration +import org.secuso.privacyfriendlybackup.api.pfa.BackupManager +import org.secuso.privacyfriendlycircuittraining.backup.BackupCreator +import org.secuso.privacyfriendlycircuittraining.backup.BackupRestorer + +class PFCircuitTrainingApplication : Application(), Configuration.Provider { + + override fun onCreate() { + super.onCreate() + BackupManager.backupCreator = BackupCreator() + BackupManager.backupRestorer = BackupRestorer() + } + + override fun getWorkManagerConfiguration(): Configuration { + return Configuration.Builder().setMinimumLoggingLevel(Log.INFO).build() + } +} \ No newline at end of file diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/MainActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/MainActivity.java index 0a51572..0e40a09 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/MainActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/MainActivity.java @@ -14,6 +14,7 @@ package org.secuso.privacyfriendlycircuittraining.activities; +import android.app.AlarmManager; import android.app.AlertDialog; import android.content.ComponentName; import android.content.Context; @@ -21,6 +22,7 @@ import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; +import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.preference.PreferenceActivity; @@ -40,6 +42,7 @@ import org.secuso.privacyfriendlycircuittraining.R; import org.secuso.privacyfriendlycircuittraining.database.PFASQLiteHelper; +import org.secuso.privacyfriendlycircuittraining.fragments.GrantExactAlarmPermissionDialogFragment; import org.secuso.privacyfriendlycircuittraining.helpers.NotificationHelper; import org.secuso.privacyfriendlycircuittraining.models.Exercise; import org.secuso.privacyfriendlycircuittraining.models.ExerciseSet; @@ -153,7 +156,16 @@ protected void onCreate(Bundle savedInstanceState) { //Schedule the next motivation notification (necessary if permission was not granted) if(NotificationHelper.isMotivationAlertEnabled(this)){ - NotificationHelper.setMotivationAlert(this); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + AlarmManager am = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE); + if (!am.canScheduleExactAlarms()) { //Check permission to schedule exact alarm on versions >= Android S + new GrantExactAlarmPermissionDialogFragment().show(getFragmentManager(), GrantExactAlarmPermissionDialogFragment.TAG); + } else { + NotificationHelper.setMotivationAlert(this); + } + } else { + NotificationHelper.setMotivationAlert(this); + } } //Set the change listener for the switch button to turn block periodization on and off diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/SettingsActivity.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/SettingsActivity.java index 739aca7..92e8e65 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/SettingsActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/activities/SettingsActivity.java @@ -15,6 +15,7 @@ package org.secuso.privacyfriendlycircuittraining.activities; import android.annotation.TargetApi; +import android.app.AlarmManager; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; @@ -31,6 +32,7 @@ import android.view.MenuItem; import org.secuso.privacyfriendlycircuittraining.R; +import org.secuso.privacyfriendlycircuittraining.fragments.GrantExactAlarmPermissionDialogFragment; import org.secuso.privacyfriendlycircuittraining.helpers.NotificationHelper; import java.util.List; @@ -225,7 +227,17 @@ public void onCreate(Bundle savedInstanceState) { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if((Boolean) newValue){ - NotificationHelper.setMotivationAlert(preference.getContext()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + AlarmManager am = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); + if (!am.canScheduleExactAlarms()) { //Check permission to schedule exact alarm on versions >= Android S + new GrantExactAlarmPermissionDialogFragment().show(getChildFragmentManager(), GrantExactAlarmPermissionDialogFragment.TAG); + return false; + } else { + NotificationHelper.setMotivationAlert(preference.getContext()); + } + } else { + NotificationHelper.setMotivationAlert(preference.getContext()); + } } else{ NotificationHelper.cancelMotivationAlert(preference.getContext()); diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/backup/BackupCreator.kt b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/backup/BackupCreator.kt new file mode 100644 index 0000000..3771504 --- /dev/null +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/backup/BackupCreator.kt @@ -0,0 +1,54 @@ +package org.secuso.privacyfriendlycircuittraining.backup + +import android.content.Context +import android.preference.PreferenceManager +import android.util.JsonWriter +import android.util.Log +import org.secuso.privacyfriendlybackup.api.backup.DatabaseUtil.getSupportSQLiteOpenHelper +import org.secuso.privacyfriendlybackup.api.backup.DatabaseUtil.writeDatabase +import org.secuso.privacyfriendlybackup.api.backup.PreferenceUtil.writePreferences +import org.secuso.privacyfriendlybackup.api.pfa.IBackupCreator +import org.secuso.privacyfriendlycircuittraining.database.PFASQLiteHelper +import java.io.OutputStream +import java.io.OutputStreamWriter + +class BackupCreator : IBackupCreator { + override fun writeBackup(context: Context, outputStream: OutputStream): Boolean { + Log.d(TAG, "createBackup() started") + val outputStreamWriter = OutputStreamWriter(outputStream, Charsets.UTF_8) + val writer = JsonWriter(outputStreamWriter) + writer.setIndent("") + + try { + writer.beginObject() + + Log.d(TAG, "Writing database") + writer.name("database") + + val database = getSupportSQLiteOpenHelper(context, PFASQLiteHelper.DATABASE_NAME).readableDatabase + + writeDatabase(writer, database) + database.close() + + Log.d(TAG, "Writing preferences") + writer.name("preferences") + + val pref = PreferenceManager.getDefaultSharedPreferences(context.applicationContext) + writePreferences(writer, pref) + + writer.endObject() + writer.close() + } catch (e: Exception) { + Log.e(TAG, "Error occurred", e) + e.printStackTrace() + return false + } + + Log.d(TAG, "Backup created successfully") + return true + } + + companion object { + const val TAG = "PFABackupCreator" + } +} \ No newline at end of file diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/backup/BackupRestorer.kt b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/backup/BackupRestorer.kt new file mode 100644 index 0000000..c5d0c40 --- /dev/null +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/backup/BackupRestorer.kt @@ -0,0 +1,138 @@ +package org.secuso.privacyfriendlycircuittraining.backup + +import android.content.Context +import android.content.SharedPreferences +import android.preference.PreferenceManager +import android.util.JsonReader +import android.util.Log +import androidx.annotation.NonNull +import org.secuso.privacyfriendlybackup.api.backup.DatabaseUtil +import org.secuso.privacyfriendlybackup.api.backup.FileUtil +import org.secuso.privacyfriendlybackup.api.pfa.IBackupRestorer +import org.secuso.privacyfriendlycircuittraining.database.PFASQLiteHelper +import java.io.IOException +import java.io.InputStream +import java.io.InputStreamReader +import kotlin.system.exitProcess + + +class BackupRestorer : IBackupRestorer { + @Throws(IOException::class) + private fun readDatabase(reader: JsonReader, context: Context) { + reader.beginObject() + val n1: String = reader.nextName() + if (n1 != "version") { + throw RuntimeException("Unknown value $n1") + } + val version: Int = reader.nextInt() + val n2: String = reader.nextName() + if (n2 != "content") { + throw RuntimeException("Unknown value $n2") + } + + Log.d(TAG, "Restoring database...") + val restoreDatabaseName = "restoreDatabase" + + // delete if file already exists + val restoreDatabaseFile = context.getDatabasePath(restoreDatabaseName) + if (restoreDatabaseFile.exists()) { + DatabaseUtil.deleteRoomDatabase(context, restoreDatabaseName) + } + + // create new restore database + val db = DatabaseUtil.getSupportSQLiteOpenHelper(context, restoreDatabaseName, version).writableDatabase + + db.beginTransaction() + db.version = version + + Log.d(TAG, "Copying database contents...") + DatabaseUtil.readDatabaseContent(reader, db) + db.setTransactionSuccessful() + db.endTransaction() + db.close() + + reader.endObject() + + // copy file to correct location + val actualDatabaseFile = context.getDatabasePath(PFASQLiteHelper.DATABASE_NAME) + + DatabaseUtil.deleteRoomDatabase(context, PFASQLiteHelper.DATABASE_NAME) + + FileUtil.copyFile(restoreDatabaseFile, actualDatabaseFile) + Log.d(TAG, "Database Restored") + + // delete restore database + DatabaseUtil.deleteRoomDatabase(context, restoreDatabaseName) + } + + @Throws(IOException::class) + private fun readPreferences(reader: JsonReader, preferences: SharedPreferences.Editor) { + reader.beginObject() + while (reader.hasNext()) { + val name: String = reader.nextName() + when (name) { + "workoutMode", + "org.secuso.privacyfriendlytraining.pref_start_timer_switch_enabled", + "org.secuso.privacyfriendlytraining.pref.motivation_alert_enabled", + "org.secuso.privacyfriendlytraining.pref.calories", + "org.secuso.privacyfriendlytraining.pref.voicecountdownworkout", + "org.secuso.privacyfriendlytraining.pref.voicecountdownrest", + "Blinking progress bar", + "org.secuso.privacyfriendlytraining.pref.cancel_workout_check", + "org.secuso.privacyfriendlytraining.pref.soundrythm", + "org.secuso.privacyfriendlytraining.pref.voicehalftime", + "org.secuso.privacyfriendlytraining.pref_keep_screen_on_switch_enabled" -> preferences.putBoolean(name, reader.nextBoolean()) + "org.secuso.privacyfriendlytraining.pref.weight", + "org.secuso.privacyfriendlytraining.pref.gender", + "org.secuso.privacyfriendlytraining.pref.age", + "org.secuso.privacyfriendlytraining.pref.height" -> preferences.putString(name, reader.nextString()) + "org.secuso.privacyfriendlytraining.pref.timer_set" -> preferences.putInt(name, reader.nextInt()) + "org.secuso.privacyfriendlytraining.pref.motivation_alert_time" -> preferences.putLong(name, reader.nextLong()) + "Motivation texts" -> preferences.putStringSet(name, readPreferenceSet(reader)) + else -> throw RuntimeException("Unknown preference $name") + } + } + reader.endObject() + } + + private fun readPreferenceSet(reader: JsonReader): Set { + val preferenceSet = mutableSetOf() + + reader.beginArray() + while (reader.hasNext()) { + preferenceSet.add(reader.nextString()); + } + reader.endArray() + return preferenceSet + } + + override fun restoreBackup(context: Context, restoreData: InputStream): Boolean { + return try { + val isReader = InputStreamReader(restoreData) + val reader = JsonReader(isReader) + val preferences = PreferenceManager.getDefaultSharedPreferences(context).edit() + + // START + reader.beginObject() + while (reader.hasNext()) { + val type: String = reader.nextName() + when (type) { + "database" -> readDatabase(reader, context) + "preferences" -> readPreferences(reader, preferences) + else -> throw RuntimeException("Can not parse type $type") + } + } + reader.endObject() + preferences.commit() + + exitProcess(0) + } catch (e: Exception) { + e.printStackTrace() + false + } + } + + companion object { + const val TAG = "PFABackupRestorer" + } +} \ No newline at end of file diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/backup/PFABackupService.kt b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/backup/PFABackupService.kt new file mode 100644 index 0000000..d55949c --- /dev/null +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/backup/PFABackupService.kt @@ -0,0 +1,5 @@ +package org.secuso.privacyfriendlycircuittraining.backup + +import org.secuso.privacyfriendlybackup.api.pfa.PFAAuthService + +class PFABackupService : PFAAuthService() \ No newline at end of file diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/GrantExactAlarmPermissionDialogFragment.kt b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/GrantExactAlarmPermissionDialogFragment.kt new file mode 100644 index 0000000..290913f --- /dev/null +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/fragments/GrantExactAlarmPermissionDialogFragment.kt @@ -0,0 +1,38 @@ +package org.secuso.privacyfriendlycircuittraining.fragments + +import android.app.AlertDialog +import android.app.Dialog +import android.content.Intent +import android.os.Build +import android.os.Bundle +import android.provider.Settings +import androidx.annotation.RequiresApi +import android.app.DialogFragment +import org.secuso.privacyfriendlycircuittraining.R + +class GrantExactAlarmPermissionDialogFragment : DialogFragment() { + @RequiresApi(Build.VERSION_CODES.S) + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + return activity.let { + val builder = AlertDialog.Builder(it) + builder.setMessage(R.string.request_schedule_exact_alarm_permission) + .setPositiveButton( + R.string.okay + ) { dialog, _ -> + val askForExactAlarmIntent = Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM) + dialog.dismiss() + context.startActivity(askForExactAlarmIntent) + } + .setNegativeButton( + R.string.cancel + ) { dialog, _ -> + dialog.dismiss() + } + builder.create() + } ?: throw IllegalStateException("Activity cannot be null") + } + + companion object { + const val TAG = "GrantExactAlarmPermissionDialog" + } +} \ No newline at end of file diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/helpers/NotificationHelper.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/helpers/NotificationHelper.java index a339c0d..204d64b 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/helpers/NotificationHelper.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/helpers/NotificationHelper.java @@ -21,6 +21,7 @@ import android.content.SharedPreferences; import android.os.Build; import android.preference.PreferenceManager; +import android.provider.Settings; import android.util.Log; import org.secuso.privacyfriendlycircuittraining.R; @@ -41,13 +42,14 @@ public class NotificationHelper { /** * Schedules (or updates) the motivation alert notification alarm + * * @param context The application context */ - public static void setMotivationAlert(Context context){ + public static void setMotivationAlert(Context context) { Log.i(LOG_CLASS, "Setting motivation alert alarm"); Intent motivationAlertIntent = new Intent(context, MotivationAlertReceiver.class); - PendingIntent motivationAlertPendingIntent = PendingIntent.getBroadcast(context, 1, motivationAlertIntent, 0); + PendingIntent motivationAlertPendingIntent = PendingIntent.getBroadcast(context, 1, motivationAlertIntent, PendingIntent.FLAG_IMMUTABLE); AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); @@ -62,29 +64,36 @@ public static void setMotivationAlert(Context context){ calendar.set(Calendar.DAY_OF_MONTH, Calendar.getInstance().get(Calendar.DAY_OF_MONTH)); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); - if(calendar.before(Calendar.getInstance())){ + if (calendar.before(Calendar.getInstance())) { calendar.add(Calendar.DAY_OF_MONTH, 1); } // Set alarm if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), motivationAlertPendingIntent); - }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if (!am.canScheduleExactAlarms()) { + Log.i(LOG_CLASS, "Motivation alert cannot be scheduled because of missing permission."); + } else { + am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), motivationAlertPendingIntent); + } + } else { + am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), motivationAlertPendingIntent); + } + } else { am.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), motivationAlertPendingIntent); - }else{ - am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), motivationAlertPendingIntent); } Log.i(LOG_CLASS, "Scheduled motivation alert at start time " + calendar.toString()); } /** * Checks if the motivation alert is enabled in the settings + * * @param context The application context */ - public static boolean isMotivationAlertEnabled(Context context){ + public static boolean isMotivationAlertEnabled(Context context) { SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); - if(sharedPref != null){ + if (sharedPref != null) { return sharedPref.getBoolean(context.getString(R.string.pref_notification_motivation_alert_enabled), false); } return false; @@ -92,12 +101,13 @@ public static boolean isMotivationAlertEnabled(Context context){ /** * Cancels the motivation alert + * * @param context The application context */ - public static void cancelMotivationAlert(Context context){ + public static void cancelMotivationAlert(Context context) { Log.i(LOG_CLASS, "Canceling motivation alert alarm"); Intent motivationAlertIntent = new Intent(context, MotivationAlertReceiver.class); - PendingIntent motivationAlertPendingIntent = PendingIntent.getBroadcast(context, 1, motivationAlertIntent, 0); + PendingIntent motivationAlertPendingIntent = PendingIntent.getBroadcast(context, 1, motivationAlertIntent, PendingIntent.FLAG_IMMUTABLE); AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); am.cancel(motivationAlertPendingIntent); } diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/receivers/MotivationAlertReceiver.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/receivers/MotivationAlertReceiver.java index 4788ba4..d2046d2 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/receivers/MotivationAlertReceiver.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/receivers/MotivationAlertReceiver.java @@ -14,11 +14,13 @@ package org.secuso.privacyfriendlycircuittraining.receivers; +import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.os.Build; import android.preference.PreferenceManager; import androidx.core.app.NotificationCompat; import androidx.core.content.ContextCompat; @@ -52,15 +54,17 @@ public class MotivationAlertReceiver extends WakefulBroadcastReceiver { private Context context; public static final int NOTIFICATION_ID = 0; + private static final String NOTIFICATION_CHANNEL = "Circuit_Training_Notifications"; + public void onReceive(Context context, Intent intent) { this.context = context; if(NotificationHelper.isMotivationAlertEnabled(context)){ - motivate(); + motivate(context); } } - private void motivate() { + private void motivate(Context context) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); @@ -89,9 +93,15 @@ private void motivate() { intent.setAction(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); - PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL, context.getString(R.string.app_name), NotificationManager.IMPORTANCE_HIGH); + notificationChannel.setDescription(context.getString(R.string.app_name)); + notificationManager.createNotificationChannel(notificationChannel); + } - NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context.getApplicationContext()) + NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context.getApplicationContext(), NOTIFICATION_CHANNEL) .setSmallIcon(R.drawable.ic_circletraining_logo_white_24dp) .setContentTitle(context.getString(R.string.reminder_notification_title)) .setContentText(motivationText) diff --git a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/services/TimerService.java b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/services/TimerService.java index 21b888b..cd73b5c 100644 --- a/app/src/main/java/org/secuso/privacyfriendlycircuittraining/services/TimerService.java +++ b/app/src/main/java/org/secuso/privacyfriendlycircuittraining/services/TimerService.java @@ -704,10 +704,10 @@ public Notification buildNotification(int time) { intent.setAction(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); - PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0); + PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE); Intent buttonIntent = new Intent(NOTIFICATION_BROADCAST); - PendingIntent buttonPendingIntent = PendingIntent.getBroadcast(this, 4, buttonIntent, PendingIntent.FLAG_CANCEL_CURRENT); + PendingIntent buttonPendingIntent = PendingIntent.getBroadcast(this, 4, buttonIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); notiBuilder.setContentIntent(pendingIntent); String message = ""; diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 864eb89..f07311d 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -91,7 +91,7 @@ Was macht die App privatsphäre-freundlich? Diese App beinhaltet keinerlei Werbung oder Tracking-Mechanismen. Außerdem werden keine Nutzerinformationen, die in der App konfiguriert oder gesammelt wurden, weitergegeben. Welche Berechtigungen braucht die App? - Privacy Friendly Training benötigt die Berechtigung "Startvorgang abgeschlossen". Diese wird verwendet um die täglichen Motivationsbenachrichtigungen, nach einem Neustart, wieder einzuplannen. Wird die Berechtigung nicht gewährt so muss die App, nach einem Neustart, erst wieder einmal gestartet werden. + Privacy Friendly Training benötigt die Berechtigung \"Startvorgang abgeschlossen\". Diese wird verwendet um die täglichen Motivationsbenachrichtigungen, nach einem Neustart, wieder einzuplannen. Wird die Berechtigung nicht gewährt so muss die App, nach einem Neustart, erst wieder einmal gestartet werden.\n\nPrivacy Friendly Training benötigt die Berechtigung \"Genauen Wecker planen\". Diese wird verwendet um die Motivationsbenachrichtigungen zu planen. @@ -227,5 +227,6 @@ Bitte wähle eine Übung aus Möchten Sie die ausgewählten Elemente löschen? Das gewählte Übungsset enthält keine Übungen. + Um Ihnen Motivationsbenachrichtigungen senden zu können, wird die Erlaubnis benötigt, einen Alarm einzustellen. Möchten Sie die Erlaubnis jetzt erteilen? diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e98865b..baa52be 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -89,7 +89,7 @@ What makes the app privacy-friendly? This app does not include any tracking mechanisms or advertisement. It further does not share any user information which may be collected during the usage of this app. Which permissions are required by the app? - Privacy Friendly Training requires the permission "Receive Boot Completed". It is used to reschedule the motivation alert after a reboot. If the permission is not granted, the app has to be launched first to reschedule the daily reminder notification. + Privacy Friendly Training requires the permission \"Receive Boot Completed\". It is used to reschedule the motivation alert after a reboot. If the permission is not granted, the app has to be launched first to reschedule the daily reminder notification.\n\nPrivacy Friendly Training requires the permission \"Schedule Exact Alarm\". It is used to schedule the motivation alerts. About @@ -258,5 +258,7 @@ Please choose an exercise Do you want to delete the selected items? Chosen exercise set has no exercises. + + In order to send you motivation alerts, the permission to set an alarm is needed. Do you want to grant the permission now? diff --git a/build.gradle b/build.gradle index e1663dc..61ce192 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,14 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.7.10' + ext.kotlin_version = '1.7.20' repositories { mavenCentral() google() } dependencies { - classpath 'com.android.tools.build:gradle:7.2.2' + classpath 'com.android.tools.build:gradle:7.3.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4a88a51..5fa02d8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Thu Sep 15 14:42:43 CEST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/libs/privacy-friendly-backup-api b/libs/privacy-friendly-backup-api new file mode 160000 index 0000000..d267b0d --- /dev/null +++ b/libs/privacy-friendly-backup-api @@ -0,0 +1 @@ +Subproject commit d267b0d5e899fe12f41a6b7aac2081b8d4ea71af diff --git a/settings.gradle b/settings.gradle index e7b4def..7264140 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,3 @@ include ':app' +include ':backup-api' +project(':backup-api').projectDir = new File('libs/privacy-friendly-backup-api/BackupAPI') \ No newline at end of file