From 56ddbf2056bddd2d635166bec146b3a8bb0eb126 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 28 Mar 2019 19:52:21 +0100 Subject: [PATCH 1/7] fix crash on bad values in minSdkVersion java.lang.NumberFormatException: For input string: "@2131034146" at java.lang.Integer.parseInt(Integer.java:615) at java.lang.Integer.parseInt(Integer.java:650) at org.fdroid.fdroid.data.App.getMinTargetMaxSdkVersions(App.java:1092) at org.fdroid.fdroid.data.App.initInstalledApk(App.java:769) at org.fdroid.fdroid.data.App.getInstance(App.java:395) at org.fdroid.fdroid.localrepo.CacheSwapAppsService.onHandleIntent(CacheSwapAppsService.java:77) at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:76) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:193) at android.os.HandlerThread.run(HandlerThread.java:65) --- app/src/main/java/org/fdroid/fdroid/data/App.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/fdroid/fdroid/data/App.java b/app/src/main/java/org/fdroid/fdroid/data/App.java index 23bf8af20..c7badbb29 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/App.java +++ b/app/src/main/java/org/fdroid/fdroid/data/App.java @@ -1112,7 +1112,10 @@ public class App extends ValueObject implements Comparable, Parcelable { } eventType = xml.nextToken(); } - } catch (PackageManager.NameNotFoundException | IOException | XmlPullParserException e) { + } catch (PackageManager.NameNotFoundException + | IOException + | XmlPullParserException + | NumberFormatException e) { Log.e(TAG, "Could not get min/max sdk version", e); } if (targetSdkVersion < minSdkVersion) { From f21e4b59315f6f477f62cb6c79d9919f943f0939 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 28 Mar 2019 20:29:58 +0100 Subject: [PATCH 2/7] fix crashes when parsing bad dates java.lang.ArrayIndexOutOfBoundsException: length=13; index=42 at sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(BaseCalendar.java:454) at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2340) at java.util.GregorianCalendar.computeTime(GregorianCalendar.java:2740) at java.util.Calendar.updateTime(Calendar.java:2589) at java.util.Calendar.getTimeInMillis(Calendar.java:1101) at java.util.Calendar.getTime(Calendar.java:1074) at java.text.SimpleDateFormat.parseInternal(SimpleDateFormat.java:1518) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1413) at java.text.DateFormat.parse(DateFormat.java:356) at org.fdroid.fdroid.Utils.parseDateFormat(Utils.java:577) at org.fdroid.fdroid.Utils.parseDate(Utils.java:592) at org.fdroid.fdroid.data.Apk.(Apk.java:178) java.lang.NumberFormatException: Not a number: at android.icu.math.BigDecimal.bad(BigDecimal.java:3349) at android.icu.math.BigDecimal.(BigDecimal.java:526) at android.icu.math.BigDecimal.(BigDecimal.java:910) at android.icu.text.DigitList.getBigDecimalICU(DigitList.java:278) at android.icu.text.DecimalFormat.parse(DecimalFormat.java:2058) at android.icu.text.DecimalFormat.parse(DecimalFormat.java:1931) at java.text.DecimalFormat.parse(DecimalFormat.java:804) at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2353) at java.text.SimpleDateFormat.parseInternal(SimpleDateFormat.java:1615) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1528) at java.text.DateFormat.parse(DateFormat.java:360) at org.fdroid.fdroid.Utils.parseDateFormat(Utils.java:577) at org.fdroid.fdroid.Utils.parseDate(Utils.java:592) at org.fdroid.fdroid.data.App.(App.java:311) at org.fdroid.fdroid.views.whatsnew.WhatsNewAdapter.onBindViewHolder(WhatsNewAdapter.java:95) at org.fdroid.fdroid.views.whatsnew.WhatsNewAdapter.onBindViewHolder(WhatsNewAdapter.java:19) java.lang.ArrayIndexOutOfBoundsException: length=13; index=36 at sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(BaseCalendar.java:454) at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2411) at java.util.GregorianCalendar.computeTime(GregorianCalendar.java:2813) at java.util.Calendar.updateTime(Calendar.java:3397) at java.util.Calendar.getTimeInMillis(Calendar.java:1761) at java.util.Calendar.getTime(Calendar.java:1734) at java.text.SimpleDateFormat.parseInternal(SimpleDateFormat.java:1633) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1528) at java.text.DateFormat.parse(DateFormat.java:360) at org.fdroid.fdroid.Utils.parseDateFormat(Utils.java:577) at org.fdroid.fdroid.Utils.parseDate(Utils.java:592) at org.fdroid.fdroid.data.App.(App.java:314) at org.fdroid.fdroid.views.updates.UpdatesAdapter.onCanUpdateLoadFinished(UpdatesAdapter.java:241) at org.fdroid.fdroid.views.updates.UpdatesAdapter.onLoadFinished(UpdatesAdapter.java:224) at org.fdroid.fdroid.views.updates.UpdatesAdapter.onLoadFinished(UpdatesAdapter.java:67) --- app/src/main/java/org/fdroid/fdroid/Utils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/fdroid/fdroid/Utils.java b/app/src/main/java/org/fdroid/fdroid/Utils.java index 110838af2..16e3aa508 100644 --- a/app/src/main/java/org/fdroid/fdroid/Utils.java +++ b/app/src/main/java/org/fdroid/fdroid/Utils.java @@ -578,7 +578,8 @@ public final class Utils { Date result; try { result = format.parse(str); - } catch (ParseException e) { + } catch (ArrayIndexOutOfBoundsException | NumberFormatException | ParseException e) { + e.printStackTrace(); result = fallback; } return result; From d2018517841ded9f8b3598201e609dc690599ea6 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 28 Mar 2019 21:21:17 +0100 Subject: [PATCH 3/7] fix crash when ExternalStorage fails to find something java.lang.IllegalArgumentException: Failed to find storage device at null at android.os.Environment.isExternalStorageRemovable(Environment.java:859) at org.fdroid.fdroid.views.main.NearbyViewBinder.(NearbyViewBinder.java:85) at org.fdroid.fdroid.views.main.MainViewController.bindSwapView(MainViewController.java:64) at org.fdroid.fdroid.views.main.MainViewAdapter.onCreateViewHolder(MainViewAdapter.java:94) at org.fdroid.fdroid.views.main.MainViewAdapter.onCreateViewHolder(MainViewAdapter.java:47) at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6685) --- .../fdroid/fdroid/views/main/MainViewController.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/full/java/org/fdroid/fdroid/views/main/MainViewController.java b/app/src/full/java/org/fdroid/fdroid/views/main/MainViewController.java index 447ec21f1..277f5d41d 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/main/MainViewController.java +++ b/app/src/full/java/org/fdroid/fdroid/views/main/MainViewController.java @@ -60,8 +60,17 @@ class MainViewController extends RecyclerView.ViewHolder { new CategoriesViewBinder(activity, frame); } + /** + * {@link android.os.Environment#isExternalStorageRemovable()} sometimes + * throughs {@link IllegalArgumentException}s when it can't find the + * storage. + */ public void bindSwapView() { - new NearbyViewBinder(activity, frame); + try { + new NearbyViewBinder(activity, frame); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } } /** From 0322e87d18e414ddb655b86ceed5de070a1f9f3b Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 28 Mar 2019 21:27:13 +0100 Subject: [PATCH 4/7] purge debug message that causes NullPointerException java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File java.io.File.getCanonicalFile()' on a null object reference at android.os.storage.StorageManager.getStorageVolume(StorageManager.java:844) at android.os.storage.StorageManager.getStorageVolume(StorageManager.java:838) at android.os.Environment.isExternalStorageRemovable(Environment.java:725) at org.fdroid.fdroid.views.main.NearbyViewBinder.(NearbyViewBinder.java:85) at org.fdroid.fdroid.views.main.MainViewController.bindSwapView(MainViewController.java:64) at org.fdroid.fdroid.views.main.MainViewAdapter.onCreateViewHolder(MainViewAdapter.java:94) at org.fdroid.fdroid.views.main.MainViewAdapter.onCreateViewHolder(MainViewAdapter.java:47) at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6685) --- .../java/org/fdroid/fdroid/views/main/NearbyViewBinder.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/full/java/org/fdroid/fdroid/views/main/NearbyViewBinder.java b/app/src/full/java/org/fdroid/fdroid/views/main/NearbyViewBinder.java index cf2a24223..26b3f56b2 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/main/NearbyViewBinder.java +++ b/app/src/full/java/org/fdroid/fdroid/views/main/NearbyViewBinder.java @@ -81,8 +81,6 @@ class NearbyViewBinder { }); if (Build.VERSION.SDK_INT >= 21) { - Log.i(TAG, "Environment.isExternalStorageRemovable(activity.getExternalFilesDir(\"\")) " + - Environment.isExternalStorageRemovable(activity.getExternalFilesDir(""))); File[] dirs = activity.getExternalFilesDirs(""); if (dirs != null) { for (File dir : dirs) { From 43d36537536d8b142be0c67d48ccdcf7555eb869 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 28 Mar 2019 22:22:44 +0100 Subject: [PATCH 5/7] create utility method for sending Toasts from Services --- .../java/org/fdroid/fdroid/UpdateService.java | 22 +------------------ .../main/java/org/fdroid/fdroid/Utils.java | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/UpdateService.java b/app/src/main/java/org/fdroid/fdroid/UpdateService.java index 63f5da89b..e4627e4e7 100644 --- a/app/src/main/java/org/fdroid/fdroid/UpdateService.java +++ b/app/src/main/java/org/fdroid/fdroid/UpdateService.java @@ -19,7 +19,6 @@ package org.fdroid.fdroid; import android.app.AlarmManager; -import android.app.IntentService; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.job.JobInfo; @@ -33,8 +32,6 @@ import android.content.IntentFilter; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; -import android.os.Handler; -import android.os.Looper; import android.os.Process; import android.os.SystemClock; import android.support.annotation.NonNull; @@ -87,7 +84,6 @@ public class UpdateService extends JobIntentService { private static final int NOTIFY_ID_UPDATING = 0; private static UpdateService updateService; - private static Handler toastHandler; private NotificationManager notificationManager; private NotificationCompat.Builder notificationBuilder; @@ -391,22 +387,6 @@ public class UpdateService extends JobIntentService { } } - /** - * In order to send a {@link Toast} from a {@link IntentService}, we have to do these tricks. - */ - private void sendNoInternetToast() { - if (toastHandler == null) { - toastHandler = new Handler(Looper.getMainLooper()); - } - toastHandler.post(new Runnable() { - @Override - public void run() { - Toast.makeText(getApplicationContext(), - R.string.warning_no_internet, Toast.LENGTH_SHORT).show(); - } - }); - } - private static boolean isLocalRepoAddress(String address) { return address != null && (address.startsWith(BluetoothDownloader.SCHEME) @@ -453,7 +433,7 @@ public class UpdateService extends JobIntentService { if (!foundLocalRepo) { Utils.debugLog(TAG, "No internet, cannot update"); if (manualUpdate) { - sendNoInternetToast(); + Utils.showToastFromService(this, getString(R.string.warning_no_internet), Toast.LENGTH_SHORT); } return; } diff --git a/app/src/main/java/org/fdroid/fdroid/Utils.java b/app/src/main/java/org/fdroid/fdroid/Utils.java index 16e3aa508..392699f72 100644 --- a/app/src/main/java/org/fdroid/fdroid/Utils.java +++ b/app/src/main/java/org/fdroid/fdroid/Utils.java @@ -27,6 +27,8 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; +import android.os.Handler; +import android.os.Looper; import android.os.StatFs; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -42,6 +44,7 @@ import android.text.style.TypefaceSpan; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; +import android.widget.Toast; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.assist.ImageScaleType; import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; @@ -101,6 +104,8 @@ public final class Utils { private static Pattern safePackageNamePattern; + private static Handler toastHandler; + public static final String FALLBACK_ICONS_DIR = "/icons/"; /* @@ -840,4 +845,21 @@ public final class Utils { Utils.debugLog(logTag, "[" + duration + "ms] " + message); } } + + /** + * In order to send a {@link Toast} from a {@link android.app.Service}, we + * have to do these tricks. + */ + public static void showToastFromService(final Context context, final String msg, final int length) { + if (toastHandler == null) { + toastHandler = new Handler(Looper.getMainLooper()); + } + toastHandler.post(new Runnable() { + + @Override + public void run() { + Toast.makeText(context.getApplicationContext(), msg, length).show(); + } + }); + } } From 81139c40fab388cd3c60e3b648fe86c74724af01 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 28 Mar 2019 23:02:04 +0100 Subject: [PATCH 6/7] trigger WifiStateChangeService after user accepts location perms Normally, WifiStateChangeService finds the SSID when F-Droid starts. But if the user hasn't granted location permissions yet, then WifiStateChangeService won't have been able to read the SSID yet. --- .../main/java/org/fdroid/fdroid/views/main/MainActivity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java index 4022b3c79..5e9daf06b 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java @@ -57,6 +57,7 @@ import org.fdroid.fdroid.UpdateService; import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.data.NewRepoConfig; import org.fdroid.fdroid.localrepo.SDCardScannerService; +import org.fdroid.fdroid.net.WifiStateChangeService; import org.fdroid.fdroid.views.AppDetailsActivity; import org.fdroid.fdroid.views.ManageReposActivity; import org.fdroid.fdroid.views.apps.AppListActivity; @@ -249,6 +250,7 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { // NOCHECKSTYLE LineLength super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_LOCATION_PERMISSIONS) { + WifiStateChangeService.start(this, null); startActivity(new Intent(this, SwapWorkflowActivity.class)); } else if (requestCode == REQUEST_STORAGE_PERMISSIONS) { Toast.makeText(this, From 934eb06ff13f8d33218d88af9a2ac48d0ae1884f Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 29 Mar 2019 00:05:00 +0100 Subject: [PATCH 7/7] SwapAppsView: don't crash on update if app is null java.lang.NullPointerException: Attempt to read from field 'java.lang.String org.fdroid.fdroid.data.App.packageName' on a null object reference at org.fdroid.fdroid.views.swap.SwapAppsView$AppListAdapter$ViewHolder$2.onChange(SwapAppsView.java:294) at android.database.ContentObserver.onChange(ContentObserver.java:130) at android.database.ContentObserver.onChange(ContentObserver.java:145) at android.database.ContentObserver$NotificationRunnable.run(ContentObserver.java:216) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:152) at android.app.ActivityThread.main(ActivityThread.java:5497) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) --- .../full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java b/app/src/full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java index 076d4ec45..88ad58021 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java +++ b/app/src/full/java/org/fdroid/fdroid/views/swap/SwapAppsView.java @@ -288,9 +288,9 @@ public class SwapAppsView extends ListView implements @Override public void onChange(boolean selfChange) { Activity activity = getActivity(); - if (activity != null) { + if (activity != null && app != null) { app = AppProvider.Helper.findSpecificApp( - getActivity().getContentResolver(), + activity.getContentResolver(), app.packageName, app.repoId, AppMetadataTable.Cols.ALL);