Make AntennaPod pass the medium SpotBugs findings

This commit is contained in:
ByteHamster 2021-03-27 22:31:10 +01:00
parent b1e15e8704
commit 998535515b
20 changed files with 103 additions and 45 deletions

View File

@ -53,6 +53,9 @@ public class ViewPagerBottomSheetBehavior<V extends View> extends BottomSheetBeh
} }
public void updateScrollingChild() { public void updateScrollingChild() {
if (viewRef == null) {
return;
}
final View scrollingChild = findScrollingChild(viewRef.get()); final View scrollingChild = findScrollingChild(viewRef.get());
nestedScrollingChildRef = new WeakReference<>(scrollingChild); nestedScrollingChildRef = new WeakReference<>(scrollingChild);
} }

View File

@ -99,7 +99,10 @@ public class BugReportActivity extends AppCompatActivity {
private void exportLog() { private void exportLog() {
try { try {
File filename = new File(UserPreferences.getDataFolder(null), "full-logs.txt"); File filename = new File(UserPreferences.getDataFolder(null), "full-logs.txt");
filename.createNewFile(); boolean success = filename.createNewFile();
if (!success) {
throw new IOException("Unable to create output file");
}
String cmd = "logcat -d -f " + filename.getAbsolutePath(); String cmd = "logcat -d -f " + filename.getAbsolutePath();
Runtime.getRuntime().exec(cmd); Runtime.getRuntime().exec(cmd);
//share file //share file

View File

@ -2,7 +2,6 @@ package de.danoeh.antennapod.activity;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
@ -479,7 +478,6 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
cardViewSeek = findViewById(R.id.cardViewSeek); cardViewSeek = findViewById(R.id.cardViewSeek);
txtvSeek = findViewById(R.id.txtvSeek); txtvSeek = findViewById(R.id.txtvSeek);
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
showTimeLeft = UserPreferences.shouldShowRemainingTime(); showTimeLeft = UserPreferences.shouldShowRemainingTime();
Log.d("timeleft", showTimeLeft ? "true" : "false"); Log.d("timeleft", showTimeLeft ? "true" : "false");
txtvLength = findViewById(R.id.txtvLength); txtvLength = findViewById(R.id.txtvLength);

View File

@ -5,7 +5,6 @@ import android.net.Uri;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile; import androidx.documentfile.provider.DocumentFile;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
@ -37,9 +36,6 @@ public class DocumentFileExportWorker {
OutputStreamWriter writer = null; OutputStreamWriter writer = null;
try { try {
Uri uri = output.getUri(); Uri uri = output.getUri();
if (uri == null) {
throw new FileNotFoundException("Export file not found.");
}
outputStream = context.getContentResolver().openOutputStream(uri); outputStream = context.getContentResolver().openOutputStream(uri);
if (outputStream == null) { if (outputStream == null) {
throw new IOException(); throw new IOException();

View File

@ -41,8 +41,8 @@ public class ExportWorker {
public Observable<File> exportObservable() { public Observable<File> exportObservable() {
if (output.exists()) { if (output.exists()) {
Log.w(TAG, "Overwriting previously exported file."); boolean success = output.delete();
output.delete(); Log.w(TAG, "Overwriting previously exported file: " + success);
} }
return Observable.create(subscriber -> { return Observable.create(subscriber -> {
OutputStreamWriter writer = null; OutputStreamWriter writer = null;

View File

@ -1,7 +1,6 @@
package de.danoeh.antennapod.discovery; package de.danoeh.antennapod.discovery;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log; import android.util.Log;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
@ -24,8 +23,6 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static android.content.Context.MODE_PRIVATE;
public class ItunesTopListLoader { public class ItunesTopListLoader {
private static final String TAG = "ITunesTopListLoader"; private static final String TAG = "ITunesTopListLoader";
private final Context context; private final Context context;
@ -38,13 +35,6 @@ public class ItunesTopListLoader {
this.context = context; this.context = context;
} }
public Single<List<PodcastSearchResult>> loadToplist() {
String defaultCountry = Locale.getDefault().getCountry();
SharedPreferences prefs = context.getSharedPreferences(PREFS, MODE_PRIVATE);
String countryCode = prefs.getString(PREF_KEY_COUNTRY_CODE, COUNTRY_CODE_UNSET);
return this.loadToplist(countryCode, 25);
}
public Single<List<PodcastSearchResult>> loadToplist(String country, int limit) { public Single<List<PodcastSearchResult>> loadToplist(String country, int limit) {
return Single.create((SingleOnSubscribe<List<PodcastSearchResult>>) emitter -> { return Single.create((SingleOnSubscribe<List<PodcastSearchResult>>) emitter -> {
OkHttpClient client = AntennapodHttpClient.getHttpClient(); OkHttpClient client = AntennapodHttpClient.getHttpClient();

View File

@ -1,5 +1,6 @@
package de.danoeh.antennapod.fragment; package de.danoeh.antennapod.fragment;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.viewpager2.widget.ViewPager2; import androidx.viewpager2.widget.ViewPager2;
@ -14,12 +15,12 @@ public abstract class PagedToolbarFragment extends Fragment {
/** /**
* Invalidate the toolbar menu if the current child fragment is visible. * Invalidate the toolbar menu if the current child fragment is visible.
* @param child The fragment, or null to force-refresh whatever the active fragment is. * @param child The fragment to invalidate
*/ */
void invalidateOptionsMenuIfActive(Fragment child) { void invalidateOptionsMenuIfActive(@NonNull Fragment child) {
Fragment visibleChild = getChildFragmentManager().findFragmentByTag("f" + viewPager.getCurrentItem()); Fragment visibleChild = getChildFragmentManager().findFragmentByTag("f" + viewPager.getCurrentItem());
if (visibleChild == child || child == null) { if (visibleChild == child) {
child.onPrepareOptionsMenu(toolbar.getMenu()); visibleChild.onPrepareOptionsMenu(toolbar.getMenu());
} }
} }

View File

@ -291,6 +291,9 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem
@Override @Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo); super.onCreateContextMenu(menu, v, menuInfo);
if (menuInfo == null) {
return;
}
AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo; AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
int position = adapterInfo.position; int position = adapterInfo.position;

View File

@ -31,7 +31,7 @@ allprojects {
spotbugs { spotbugs {
effort = 'max' effort = 'max'
reportLevel = 'high' // for now reportLevel = 'medium'
excludeFilter = rootProject.file('config/spotbugs/exclude.xml') excludeFilter = rootProject.file('config/spotbugs/exclude.xml')
ignoreFailures = true // Handled by printing task ignoreFailures = true // Handled by printing task
} }

View File

@ -1,16 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter> <FindBugsFilter>
<Match>
<Bug pattern="BC_UNCONFIRMED_CAST"/>
<Class name="de.danoeh.antennapod.adapter.NavListAdapter"/>
</Match>
<Match>
<Bug pattern="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE"/>
<Class name="de.danoeh.antennapod.net.ssl.NoV1SslSocketFactory"/>
</Match>
<Match> <Match>
<Bug pattern="DM_DEFAULT_ENCODING"/> <Bug pattern="DM_DEFAULT_ENCODING"/>
<Class name="de.danoeh.antennapod.core.util.vorbiscommentreader.VorbisCommentReader"/> <Class name="de.danoeh.antennapod.core.util.vorbiscommentreader.VorbisCommentReader"/>
</Match> </Match>
<Match> <Match>
<Bug pattern="MS_MUTABLE_ARRAY"/> <Bug pattern="HSC_HUGE_SHARED_STRING_CONSTANT"/>
<Class name="de.danoeh.antennapod.fragment.NavDrawerFragment"/> <Class name="de.danoeh.antennapod.net.ssl.BackportCaCerts"/>
</Match> </Match>
<Match> <Match>
<Bug pattern="MS_SHOULD_BE_FINAL"/> <Bug pattern="MS_CANNOT_BE_FINAL"/>
<Class name="de.danoeh.antennapod.core.ClientConfig"/> <Class name="de.danoeh.antennapod.core.service.playback.PlaybackService"/>
</Match>
<Match>
<Bug pattern="MS_MUTABLE_ARRAY"/>
<Class name="de.danoeh.antennapod.fragment.NavDrawerFragment"/>
</Match> </Match>
<Match> <Match>
<Bug pattern="NM_SAME_SIMPLE_NAME_AS_SUPERCLASS"/> <Bug pattern="NM_SAME_SIMPLE_NAME_AS_SUPERCLASS"/>
@ -28,12 +40,58 @@
<Bug pattern="NP_NULL_ON_SOME_PATH"/> <Bug pattern="NP_NULL_ON_SOME_PATH"/>
<Class name="de.danoeh.antennapod.core.feed.FeedMedia"/> <Class name="de.danoeh.antennapod.core.feed.FeedMedia"/>
</Match> </Match>
<Match>
<Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"/>
<Class name="de.danoeh.antennapod.dialog.PlaybackControlsDialog"/>
</Match>
<Match> <Match>
<Bug pattern="NP_NULL_PARAM_DEREF"/> <Bug pattern="NP_NULL_PARAM_DEREF"/>
<Class name="de.danoeh.antennapod.core.feed.FeedMedia"/> <Class name="de.danoeh.antennapod.core.feed.FeedMedia"/>
</Match> </Match>
<Match>
<Bug pattern="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE"/>
<Class name="de.danoeh.antennapod.preferences.PreferenceUpgrader"/>
</Match>
<Match>
<Bug pattern="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"/>
<Class name="de.danoeh.antennapod.PodcastApp"/>
</Match>
<Match>
<Bug pattern="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"/>
<Class name="de.danoeh.antennapod.core.service.download.DownloadService"/>
</Match>
<Match>
<Bug pattern="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"/>
<Class name="de.danoeh.antennapod.core.service.playback.PlaybackService"/>
</Match>
<Match>
<Bug pattern="UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD"/>
<Class name="de.danoeh.antennapod.core.storage.NavDrawerData$FolderDrawerItem"/>
</Match>
<Match>
<Bug pattern="UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD"/>
<Class name="de.danoeh.antennapod.core.cast.CastButtonVisibilityManager"/>
</Match>
<Match><Class name="de.danoeh.antennapod.core.ClientConfig"/></Match>
<Match><Package name="de.danoeh.antennapod.core.glide"/></Match>
<Match><Package name="de.danoeh.antennapod.databinding"/></Match>
<Match><Bug pattern="EI_EXPOSE_REP"/></Match>
<Match><Bug pattern="EI_EXPOSE_REP2"/></Match>
<Match><Bug pattern="HE_EQUALS_NO_HASHCODE"/></Match>
<Match><Bug pattern="ICAST_INTEGER_MULTIPLY_CAST_TO_LONG"/></Match>
<Match><Bug pattern="IS2_INCONSISTENT_SYNC"/></Match>
<Match><Bug pattern="NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION"/></Match>
<Match><Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"/></Match>
<Match><Bug pattern="OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE"/></Match>
<Match><Bug pattern="OS_OPEN_STREAM"/></Match>
<Match><Bug pattern="OS_OPEN_STREAM_EXCEPTION_PATH"/></Match>
<Match><Bug pattern="RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN"/></Match>
<Match><Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"/></Match>
<Match><Bug pattern="RV_RETURN_VALUE_IGNORED"/></Match>
<Match><Bug pattern="SE_COMPARATOR_SHOULD_BE_SERIALIZABLE"/></Match>
<Match><Bug pattern="SE_NO_SERIALVERSIONID"/></Match>
<Match><Bug pattern="SE_TRANSIENT_FIELD_NOT_RESTORED"/></Match>
<Match><Bug pattern="SF_SWITCH_NO_DEFAULT"/></Match>
<Match><Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/></Match>
<Match><Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/></Match>
<Match><Bug pattern="WMI_WRONG_MAP_ITERATOR"/></Match>
</FindBugsFilter> </FindBugsFilter>

View File

@ -94,7 +94,7 @@ public class OpmlBackupAgent extends BackupAgentHelper {
if (len != -1) { if (len != -1) {
byte[] oldChecksum = new byte[len]; byte[] oldChecksum = new byte[len];
inState.read(oldChecksum); IOUtils.read(inState, oldChecksum, 0, len);
Log.d(TAG, "Old checksum: " + new BigInteger(1, oldChecksum).toString(16)); Log.d(TAG, "Old checksum: " + new BigInteger(1, oldChecksum).toString(16));
if (Arrays.equals(oldChecksum, newChecksum)) { if (Arrays.equals(oldChecksum, newChecksum)) {

View File

@ -43,7 +43,7 @@ public abstract class Chapter extends FeedComponent {
String imageUrl = cursor.getString(indexImage); String imageUrl = cursor.getString(indexImage);
int chapterType = cursor.getInt(indexChapterType); int chapterType = cursor.getInt(indexChapterType);
Chapter chapter = null; Chapter chapter;
switch (chapterType) { switch (chapterType) {
case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER: case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER:
chapter = new SimpleChapter(start, title, link, imageUrl); chapter = new SimpleChapter(start, title, link, imageUrl);
@ -54,6 +54,8 @@ public abstract class Chapter extends FeedComponent {
case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER: case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER:
chapter = new VorbisCommentChapter(start, title, link, imageUrl); chapter = new VorbisCommentChapter(start, title, link, imageUrl);
break; break;
default:
throw new IllegalArgumentException("Unknown chapter type");
} }
chapter.setId(id); chapter.setId(id);
return chapter; return chapter;

View File

@ -65,7 +65,7 @@ public class FeedItem extends FeedComponent implements Serializable {
* The list of chapters of this item. This might be null even if there are chapters of this item * The list of chapters of this item. This might be null even if there are chapters of this item
* in the database. The 'hasChapters' attribute should be used to check if this item has any chapters. * in the database. The 'hasChapters' attribute should be used to check if this item has any chapters.
* */ * */
private List<Chapter> chapters; private transient List<Chapter> chapters;
private String imageUrl; private String imageUrl;
/* /*

View File

@ -188,8 +188,11 @@ public class HttpDownloader extends Downloader {
out = new RandomAccessFile(destination, "rw"); out = new RandomAccessFile(destination, "rw");
out.seek(request.getSoFar()); out.seek(request.getSoFar());
} else { } else {
destination.delete(); boolean success = destination.delete();
destination.createNewFile(); success |= destination.createNewFile();
if (!success) {
throw new IOException("Unable to recreate partially downloaded file");
}
out = new RandomAccessFile(destination, "rw"); out = new RandomAccessFile(destination, "rw");
} }

View File

@ -217,7 +217,7 @@ public abstract class PlaybackServiceMediaPlayer {
* could result in nonsensical results (like a status of PLAYING, but a null playable) * could result in nonsensical results (like a status of PLAYING, but a null playable)
* @return the current player status * @return the current player status
*/ */
public PlayerStatus getPlayerStatus() { public synchronized PlayerStatus getPlayerStatus() {
return playerStatus; return playerStatus;
} }

View File

@ -91,7 +91,10 @@ public class DatabaseExporter {
db.close(); db.close();
File currentDB = context.getDatabasePath(PodDBAdapter.DATABASE_NAME); File currentDB = context.getDatabasePath(PodDBAdapter.DATABASE_NAME);
currentDB.delete(); boolean success = currentDB.delete();
if (!success) {
throw new IOException("Unable to delete old database");
}
FileUtils.moveFile(tempDB, currentDB); FileUtils.moveFile(tempDB, currentDB);
} catch (IOException | SQLiteException e) { } catch (IOException | SQLiteException e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));

View File

@ -331,7 +331,7 @@ public class PodDBAdapter {
PodDBAdapter.context = context.getApplicationContext(); PodDBAdapter.context = context.getApplicationContext();
} }
public static PodDBAdapter getInstance() { public static synchronized PodDBAdapter getInstance() {
if (instance == null) { if (instance == null) {
instance = new PodDBAdapter(); instance = new PodDBAdapter();
} }

View File

@ -35,7 +35,6 @@ public class CastUtils {
public static final String KEY_FEED_URL = "de.danoeh.antennapod.core.cast.FeedUrl"; public static final String KEY_FEED_URL = "de.danoeh.antennapod.core.cast.FeedUrl";
public static final String KEY_FEED_WEBSITE = "de.danoeh.antennapod.core.cast.FeedWebsite"; public static final String KEY_FEED_WEBSITE = "de.danoeh.antennapod.core.cast.FeedWebsite";
public static final String KEY_EPISODE_NOTES = "de.danoeh.antennapod.core.cast.EpisodeNotes"; public static final String KEY_EPISODE_NOTES = "de.danoeh.antennapod.core.cast.EpisodeNotes";
public static final int EPISODE_NOTES_MAX_LENGTH = Integer.MAX_VALUE;
/** /**
* The field <code>AntennaPod.FormatVersion</code> specifies which version of MediaMetaData * The field <code>AntennaPod.FormatVersion</code> specifies which version of MediaMetaData

View File

@ -39,9 +39,6 @@ public class MediaInfoCreator {
} }
String notes = media.getNotes(); String notes = media.getNotes();
if (notes != null) { if (notes != null) {
if (notes.length() > CastUtils.EPISODE_NOTES_MAX_LENGTH) {
notes = notes.substring(0, CastUtils.EPISODE_NOTES_MAX_LENGTH);
}
metadata.putString(CastUtils.KEY_EPISODE_NOTES, notes); metadata.putString(CastUtils.KEY_EPISODE_NOTES, notes);
} }
// Default id value // Default id value

View File

@ -6,10 +6,12 @@ import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager; import javax.net.ssl.X509TrustManager;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -52,7 +54,7 @@ public class BackportTrustManager {
managers.add(getSystemTrustManager(keystore)); managers.add(getSystemTrustManager(keystore));
managers.add(getSystemTrustManager(null)); managers.add(getSystemTrustManager(null));
return new CompositeX509TrustManager(managers); return new CompositeX509TrustManager(managers);
} catch (Exception e) { } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));
return null; return null;
} }