diff --git a/app/build.gradle b/app/build.gradle index 7f599798e..ffc2f3557 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -33,7 +33,7 @@ dependencies { compile "com.android.support:cardview-v7:${supportLibVersion}" compile "com.android.support:design:${supportLibVersion}" compile "com.android.support:support-vector-drawable:${supportLibVersion}" - compile 'com.android.support.constraint:constraint-layout:1.0.1' + compile 'com.android.support.constraint:constraint-layout:1.0.2' compile "com.android.support:palette-v7:${supportLibVersion}" compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' @@ -112,8 +112,8 @@ if (!hasProperty('sourceDeps')) { 'ch.acra:acra:d2762968c448757a7d6acc9f141881d9632f664988e9723ece33b5f7c79f3bc9', 'commons-io:commons-io:a10418348d234968600ccb1d988efcbbd08716e1d96936ccc1880e7d22513474', 'commons-net:commons-net:c25b0da668b3c5649f002d504def22d1b4cb30d206f05428d2fe168fa1a901c2', - 'com.android.support.constraint:constraint-layout-solver:d03a406eb505dfa673b0087bf17e16d5a4d6bf8afdf452ee175e346207948cdf', - 'com.android.support.constraint:constraint-layout:df1add69d11063eebba521818d63537b22207376b65f30cc35feea172b84e300', + 'com.android.support.constraint:constraint-layout-solver:8c62525a9bc5cff5633a96cb9b32fffeccaf41b8841aa87fc22607070dea9b8d', + 'com.android.support.constraint:constraint-layout:b0c688cc2b7172608f8153a689d746da40f71e52d7e2fe2bfd9df2f92db77085', 'com.android.support:animated-vector-drawable:d2d59a11809abe3e64535346f05c22437b458de115f06ea35021fd0714960213', 'com.android.support:appcompat-v7:120f3ce6cac682d69e53d80ccfa9cee076f0f11ccbe56d4ccd72099a745e81f9', 'com.android.support:cardview-v7:c8610b0c334e4438d7e1ac58fcf2ac891fb26bac662c8351cd6b345c8d7b7076', diff --git a/app/src/main/java/org/fdroid/fdroid/AppDetails2.java b/app/src/main/java/org/fdroid/fdroid/AppDetails2.java index 7bd70df9a..067631236 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppDetails2.java +++ b/app/src/main/java/org/fdroid/fdroid/AppDetails2.java @@ -469,9 +469,20 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog case Installer.ACTION_INSTALL_COMPLETE: adapter.clearProgress(); unregisterInstallReceiver(); - // Don't try and update the view here, because the InstalledAppProviderService + // Ideally, we wouldn't try to update the view here, because the InstalledAppProviderService // hasn't had time to do its thing and mark the app as installed. Instead, we // wait for that service to notify us, and then we will respond in appObserver. + + // Having said that, there are some cases where the PackageManager doesn't + // return control back to us until after it has already braodcast to the + // InstalledAppProviderService. This means that we are not listening for any + // feedback from InstalledAppProviderService (we intentionally stop listening in + // onPause). Empirically, this happens when upgrading an app rather than a clean + // install. However given the nature of this race condition, it may be different + // on different operating systems. As such, we'll just update our view now. It may + // happen again in our appObserver, but that will only cause a little more load + // on the system, it shouldn't cause a different UX. + onAppChanged(); break; case Installer.ACTION_INSTALL_INTERRUPTED: adapter.clearProgress(); diff --git a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java index 67c92743b..adf78e0f4 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java +++ b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java @@ -10,6 +10,7 @@ import android.content.pm.Signature; import android.net.Uri; import android.os.Process; import android.support.annotation.Nullable; +import android.util.Log; import org.acra.ACRA; import org.fdroid.fdroid.Hasher; @@ -173,6 +174,7 @@ public class InstalledAppProviderService extends IntentService { if (ACTION_INSERT.equals(action)) { PackageInfo packageInfo = getPackageInfo(intent, packageName); if (packageInfo != null) { + Log.i(TAG, "Marking " + packageName + " as installed"); File apk = new File(packageInfo.applicationInfo.publicSourceDir); if (apk.isDirectory()) { FilenameFilter filter = new FilenameFilter() { @@ -204,6 +206,7 @@ public class InstalledAppProviderService extends IntentService { } } } else if (ACTION_DELETE.equals(action)) { + Log.i(TAG, "Marking " + packageName + " as no longer installed"); deleteAppFromDb(this, packageName); } notifyEvents.onNext(null); diff --git a/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java b/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java index 60f4ac2e5..dc83000e4 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java @@ -81,6 +81,7 @@ public class CategoryController extends RecyclerView.ViewHolder implements Loade int categoryNameId = getCategoryResource(activity, categoryName, "string", false); String translatedName = categoryNameId == 0 ? categoryName : activity.getString(categoryNameId); heading.setText(translatedName); + heading.setContentDescription(activity.getString(R.string.tts_category_name, translatedName)); viewAll.setVisibility(View.INVISIBLE); 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 839626207..59768ed58 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 @@ -6,12 +6,14 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.content.LocalBroadcastManager; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.text.TextUtils; +import android.view.ViewGroup; import android.widget.Toast; import android.support.v7.widget.RecyclerView; @@ -81,6 +83,13 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB pager.setLayoutManager(new NonScrollingHorizontalLayoutManager(this)); pager.setAdapter(adapter); + // Without this, the focus is completely busted on pre 15 devices. Trying to use them + // without this ends up with each child view showing for a fraction of a second, then + // reverting back to the "Latest" screen again, in completely non-deterministic ways. + if (Build.VERSION.SDK_INT <= 15) { + pager.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); + } + updatesBadge = new BadgeItem().hide(false); bottomNavigation = (BottomNavigationBar) findViewById(R.id.bottom_navigation); diff --git a/app/src/main/res/layout/app_details2_header.xml b/app/src/main/res/layout/app_details2_header.xml index 965cc4a3b..45c8d6301 100755 --- a/app/src/main/res/layout/app_details2_header.xml +++ b/app/src/main/res/layout/app_details2_header.xml @@ -21,7 +21,9 @@ android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginStart="8dp" + android:layout_marginLeft="8dp" android:layout_marginEnd="8dp" + android:layout_marginRight="8dp" > @@ -141,7 +144,7 @@ android:layout_weight="1" android:ellipsize="marquee" android:padding="12dp" - tools:text="THIS IS BUTTON 1" /> + tools:text="Uninstall" />