diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index d56ec7ace..9dbfdcf1a 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -65,7 +65,7 @@ jobs: - name: Lint :app module recursively run: ./gradlew :app:lintPlayRelease - name: SpotBugs - run: ./gradlew spotbugsPlayDebug spotbugsDebug 2>&1 | grep -i "spotbugs" + run: ./gradlew spotbugsPlayDebug spotbugsDebug unit-test: name: "Unit Test: ${{ matrix.variant }}" diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java index 34aaaa39b..b4d45b262 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -291,7 +291,7 @@ public class MainActivity extends CastEnabledActivity { @Override protected void onDestroy() { super.onDestroy(); - if (drawerLayout != null) { + if (drawerLayout != null && drawerToggle != null) { drawerLayout.removeDrawerListener(drawerToggle); } } @@ -552,7 +552,7 @@ public class MainActivity extends CastEnabledActivity { @Override public void onBackPressed() { - if (isDrawerOpen()) { + if (isDrawerOpen() && drawerLayout != null) { drawerLayout.closeDrawer(navDrawer); } else if (sheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) { sheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java index a304ead3c..176828308 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java @@ -341,7 +341,7 @@ public class NavListAdapter extends RecyclerView.Adapter if (context == null) { return; } - if (tag.isOpen) { + if (tag.isOpen()) { holder.count.setVisibility(View.GONE); } Glide.with(context).clear(holder.image); diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/TimeRangeDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/TimeRangeDialog.java index 85913043e..1d84c7c22 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/TimeRangeDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/TimeRangeDialog.java @@ -139,8 +139,8 @@ public class TimeRangeDialog extends MaterialAlertDialogBuilder { } protected Point radToPoint(float angle, float radius) { - return new Point((int) (getWidth() / 2 + radius * Math.sin(-angle * Math.PI / 180 + Math.PI)), - (int) (getHeight() / 2 + radius * Math.cos(-angle * Math.PI / 180 + Math.PI))); + return new Point((int) (getWidth() / 2.0 + radius * Math.sin(-angle * Math.PI / 180.0 + Math.PI)), + (int) (getHeight() / 2.0 + radius * Math.cos(-angle * Math.PI / 180.0 + Math.PI))); } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java index 291de2a50..34712d428 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java @@ -86,9 +86,9 @@ public class DownloadLogFragment extends BottomSheetDialogFragment @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - Object item = adapter.getItem(position); - if (item instanceof DownloadResult) { - new DownloadLogDetailsDialog(getContext(), (DownloadResult) item).show(); + final DownloadResult item = adapter.getItem(position); + if (item != null) { + new DownloadLogDetailsDialog(getContext(), item).show(); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java index 636c0245b..4c3647669 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/NavDrawerFragment.java @@ -359,10 +359,10 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS .setState(BottomSheetBehavior.STATE_COLLAPSED); } else { NavDrawerData.TagDrawerItem folder = ((NavDrawerData.TagDrawerItem) clickedItem); - if (openFolders.contains(folder.name)) { - openFolders.remove(folder.name); + if (openFolders.contains(folder.getTitle())) { + openFolders.remove(folder.getTitle()); } else { - openFolders.add(folder.name); + openFolders.add(folder.getTitle()); } getContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) @@ -438,8 +438,8 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS flatItems.add(item); if (item.type == NavDrawerData.DrawerItem.Type.TAG) { NavDrawerData.TagDrawerItem folder = ((NavDrawerData.TagDrawerItem) item); - folder.isOpen = openFolders.contains(folder.name); - if (folder.isOpen) { + folder.setOpen(openFolders.contains(folder.getTitle())); + if (folder.isOpen()) { flatItems.addAll(makeFlatDrawerData(((NavDrawerData.TagDrawerItem) item).children, layer + 1)); } } diff --git a/build.gradle b/build.gradle index 1d42382ca..0428e8b2d 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ buildscript { plugins { id 'com.android.application' version "$agpVersion" apply false id 'com.android.library' version "$agpVersion" apply false - id 'com.github.spotbugs' version '4.7.0' apply false + id 'com.github.spotbugs' version '4.8.0' apply false id 'checkstyle' } diff --git a/common.gradle b/common.gradle index a2afc7279..97960149b 100644 --- a/common.gradle +++ b/common.gradle @@ -76,6 +76,7 @@ gradle.projectsEvaluated { apply plugin: 'com.github.spotbugs' spotbugs { + toolVersion = '4.2.3' effort = 'max' reportLevel = 'medium' excludeFilter = rootProject.file('config/spotbugs/exclude.xml') @@ -86,23 +87,33 @@ gradle.taskGraph.whenReady { taskGraph -> taskGraph.allTasks.each { task -> if (task.name.toLowerCase().contains('spotbugs')) { task.doLast { - def reportFile = task.project.file("build/reports/spotbugs/playDebug.xml") - if (!reportFile.exists()) return - def slurped = new groovy.xml.XmlSlurper().parse(reportFile) + def reportFile = task.project.file("build/reports/spotbugs/debug.xml") + def reportFilePlay = task.project.file("build/reports/spotbugs/playDebug.xml") - def foundErrors = false - slurped['BugInstance'].each { bug -> - logger.error "[SpotBugs] ${bug['LongMessage']} [${bug.@'type'}]" - bug['SourceLine'].each { line -> - logger.error "[SpotBugs] ${line['Message']}" - foundErrors = true - } + if (reportFile.exists()) { + parseSpotBugsXml(task, reportFile) } - if (foundErrors) { - throw new TaskExecutionException(task, - new Exception("SpotBugs violations were found. See output above for details.")) + if (reportFilePlay.exists()) { + parseSpotBugsXml(task, reportFilePlay) } } } } } + +def parseSpotBugsXml(task, xmlFile) { + def slurped = new groovy.xml.XmlSlurper().parse(xmlFile) + + def foundErrors = false + slurped['BugInstance'].each { bug -> + logger.error "[SpotBugs] ${bug['LongMessage']} [${bug.@'type'}]" + bug['SourceLine'].each { line -> + logger.error "[SpotBugs] ${line['Message']}" + foundErrors = true + } + } + if (foundErrors) { + throw new TaskExecutionException(task, + new Exception("SpotBugs violations were found. See output above for details.")) + } +} diff --git a/config/spotbugs/exclude.xml b/config/spotbugs/exclude.xml index d544e86d9..b80c0550c 100644 --- a/config/spotbugs/exclude.xml +++ b/config/spotbugs/exclude.xml @@ -5,17 +5,29 @@ - - + + + + + + + + + + + + + + @@ -24,10 +36,6 @@ - - - - @@ -41,46 +49,47 @@ - - + + - - - - - - - - - - - - - - + + - - + + + + + + + + + + - + + + + + + @@ -96,6 +105,8 @@ + + diff --git a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java index 79c6dd6bc..2058d5b2f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java @@ -90,17 +90,18 @@ public class OpmlBackupAgent extends BackupAgentHelper { // Get the old checksum if (oldState != null) { - FileInputStream inState = new FileInputStream(oldState.getFileDescriptor()); - int len = inState.read(); + try (final FileInputStream inState = new FileInputStream(oldState.getFileDescriptor())) { + int len = inState.read(); - if (len != -1) { - byte[] oldChecksum = new byte[len]; - IOUtils.read(inState, oldChecksum, 0, len); - Log.d(TAG, "Old checksum: " + new BigInteger(1, oldChecksum).toString(16)); + if (len != -1) { + byte[] oldChecksum = new byte[len]; + IOUtils.read(inState, oldChecksum, 0, len); + Log.d(TAG, "Old checksum: " + new BigInteger(1, oldChecksum).toString(16)); - if (Arrays.equals(oldChecksum, newChecksum)) { - Log.d(TAG, "Checksums are the same; won't backup"); - return; + if (Arrays.equals(oldChecksum, newChecksum)) { + Log.d(TAG, "Checksums are the same; won't backup"); + return; + } } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 492dff759..b390f5f44 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -736,9 +736,33 @@ public final class DBReader { } public static class MonthlyStatisticsItem { - public int year = 0; - public int month = 0; - public long timePlayed = 0; + private int year = 0; + private int month = 0; + private long timePlayed = 0; + + public int getYear() { + return year; + } + + public void setYear(final int year) { + this.year = year; + } + + public int getMonth() { + return month; + } + + public void setMonth(final int month) { + this.month = month; + } + + public long getTimePlayed() { + return timePlayed; + } + + public void setTimePlayed(final long timePlayed) { + this.timePlayed = timePlayed; + } } @NonNull @@ -752,9 +776,9 @@ public final class DBReader { int indexTotalDuration = cursor.getColumnIndexOrThrow("total_duration"); while (cursor.moveToNext()) { MonthlyStatisticsItem item = new MonthlyStatisticsItem(); - item.month = Integer.parseInt(cursor.getString(indexMonth)); - item.year = Integer.parseInt(cursor.getString(indexYear)); - item.timePlayed = cursor.getLong(indexTotalDuration); + item.setMonth(Integer.parseInt(cursor.getString(indexMonth))); + item.setYear(Integer.parseInt(cursor.getString(indexYear))); + item.setTimePlayed(cursor.getLong(indexTotalDuration)); months.add(item); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java b/core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java index af02a7733..024c5d357 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java @@ -57,8 +57,8 @@ public class NavDrawerData { public static class TagDrawerItem extends DrawerItem { public final List children = new ArrayList<>(); - public final String name; - public boolean isOpen; + private final String name; + private boolean isOpen; public TagDrawerItem(String name) { // Keep IDs >0 but make room for many feeds @@ -70,6 +70,14 @@ public class NavDrawerData { return name; } + public boolean isOpen() { + return isOpen; + } + + public void setOpen(final boolean open) { + isOpen = open; + } + public int getCounter() { int sum = 0; for (DrawerItem item : children) { diff --git a/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/EchoActivity.java b/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/EchoActivity.java index 758eaeac7..5981c7ad4 100644 --- a/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/EchoActivity.java +++ b/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/EchoActivity.java @@ -222,7 +222,7 @@ public class EchoActivity extends AppCompatActivity { long secondsPerDay = queueSecondsLeft / daysUntilNextYear; String timePerDay = Converter.getDurationStringLocalized( getLocalizedResources(this, getEchoLanguage()), secondsPerDay * 1000, true); - double hoursPerDay = (double) (secondsPerDay / 3600); + double hoursPerDay = secondsPerDay / 3600.0; int nextYear = RELEASE_YEAR + 1; if (hoursPerDay < 1.5) { viewBinding.aboveLabel.setText(R.string.echo_queue_title_clean); diff --git a/ui/glide/src/main/java/de/danoeh/antennapod/ui/glide/FastBlurTransformation.java b/ui/glide/src/main/java/de/danoeh/antennapod/ui/glide/FastBlurTransformation.java index a19611100..54040e4b4 100644 --- a/ui/glide/src/main/java/de/danoeh/antennapod/ui/glide/FastBlurTransformation.java +++ b/ui/glide/src/main/java/de/danoeh/antennapod/ui/glide/FastBlurTransformation.java @@ -12,7 +12,7 @@ import java.nio.charset.Charset; import java.security.MessageDigest; public class FastBlurTransformation extends BitmapTransformation { - private static final String ID = "de.danoeh.antennapod.core.glide.FastBlurTransformation"; + private static final String ID = "de.danoeh.antennapod.ui.glide.FastBlurTransformation"; private static final String TAG = FastBlurTransformation.class.getSimpleName(); diff --git a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/BarChartView.java b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/BarChartView.java index eadbb29ee..93b9e3332 100644 --- a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/BarChartView.java +++ b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/BarChartView.java @@ -49,7 +49,7 @@ public class BarChartView extends AppCompatImageView { drawable.data = data; drawable.maxValue = 1; for (DBReader.MonthlyStatisticsItem item : data) { - drawable.maxValue = Math.max(drawable.maxValue, item.timePlayed); + drawable.maxValue = Math.max(drawable.maxValue, item.getTimePlayed()); } } @@ -89,21 +89,21 @@ public class BarChartView extends AppCompatImageView { paintBars.setStrokeWidth(height * 0.015f); paintBars.setColor(colors[0]); int colorIndex = 0; - int lastYear = data.size() > 0 ? data.get(0).year : 0; + int lastYear = data.size() > 0 ? data.get(0).getYear() : 0; for (int i = 0; i < data.size(); i++) { float x = textPadding + (i + 1) * stepSize; - if (lastYear != data.get(i).year) { - lastYear = data.get(i).year; + if (lastYear != data.get(i).getYear()) { + lastYear = data.get(i).getYear(); colorIndex++; paintBars.setColor(colors[colorIndex % 2]); if (i < data.size() - 2) { - canvas.drawText(String.valueOf(data.get(i).year), x + stepSize, + canvas.drawText(String.valueOf(data.get(i).getYear()), x + stepSize, barHeight + (height - barHeight + textSize) / 2, paintGridText); } canvas.drawLine(x, height, x, barHeight, paintGridText); } - float valuePercentage = (float) Math.max(0.005, (float) data.get(i).timePlayed / maxValue); + float valuePercentage = (float) Math.max(0.005, (float) data.get(i).getTimePlayed() / maxValue); float y = (1 - valuePercentage) * barHeight; canvas.drawRect(x, y, x + stepSize * 0.95f, barHeight, paintBars); } diff --git a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/YearStatisticsListAdapter.java b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/YearStatisticsListAdapter.java index 2116a17a4..d000ceb62 100644 --- a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/YearStatisticsListAdapter.java +++ b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/years/YearStatisticsListAdapter.java @@ -57,41 +57,41 @@ public class YearStatisticsListAdapter extends RecyclerView.Adapter statistics) { - int lastYear = statistics.size() > 0 ? statistics.get(0).year : 0; - int lastDataPoint = statistics.size() > 0 ? (statistics.get(0).month - 1) + lastYear * 12 : 0; + int lastYear = statistics.size() > 0 ? statistics.get(0).getYear() : 0; + int lastDataPoint = statistics.size() > 0 ? (statistics.get(0).getMonth() - 1) + lastYear * 12 : 0; long yearSum = 0; yearlyAggregate.clear(); statisticsData.clear(); for (DBReader.MonthlyStatisticsItem statistic : statistics) { - if (statistic.year != lastYear) { + if (statistic.getYear() != lastYear) { DBReader.MonthlyStatisticsItem yearAggregate = new DBReader.MonthlyStatisticsItem(); - yearAggregate.year = lastYear; - yearAggregate.timePlayed = yearSum; + yearAggregate.setYear(lastYear); + yearAggregate.setTimePlayed(yearSum); yearlyAggregate.add(yearAggregate); yearSum = 0; - lastYear = statistic.year; + lastYear = statistic.getYear(); } - yearSum += statistic.timePlayed; - while (lastDataPoint + 1 < (statistic.month - 1) + statistic.year * 12) { + yearSum += statistic.getTimePlayed(); + while (lastDataPoint + 1 < (statistic.getMonth() - 1) + statistic.getYear() * 12) { lastDataPoint++; DBReader.MonthlyStatisticsItem item = new DBReader.MonthlyStatisticsItem(); - item.year = lastDataPoint / 12; - item.month = lastDataPoint % 12 + 1; + item.setYear(lastDataPoint / 12); + item.setMonth(lastDataPoint % 12 + 1); statisticsData.add(item); // Compensate for months without playback } statisticsData.add(statistic); - lastDataPoint = (statistic.month - 1) + statistic.year * 12; + lastDataPoint = (statistic.getMonth() - 1) + statistic.getYear() * 12; } DBReader.MonthlyStatisticsItem yearAggregate = new DBReader.MonthlyStatisticsItem(); - yearAggregate.year = lastYear; - yearAggregate.timePlayed = yearSum; + yearAggregate.setYear(lastYear); + yearAggregate.setTimePlayed(yearSum); yearlyAggregate.add(yearAggregate); Collections.reverse(yearlyAggregate); notifyDataSetChanged();