Skip to content

Commit

Permalink
fix: add custom tab query to AndroidManifest.xml
Browse files Browse the repository at this point in the history
Android 11 requires the app to declare queries to the list of installed apps.

ref: minors
  • Loading branch information
VaiTon committed Jun 19, 2021
1 parent 94c4cfe commit 211c96e
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 225 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Expand Up @@ -39,7 +39,7 @@ dependencies {
val coroutinesVersion = "1.5.0"
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$coroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion-RC")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion")


// Android KTX
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/AndroidManifest.xml
Expand Up @@ -4,6 +4,15 @@
package="openfoodfacts.github.scrachx.openfood"
android:installLocation="auto">

<!-- Add permission to query apps for CustomTabs -->
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
</queries>


<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Expand Down
Expand Up @@ -18,11 +18,11 @@ package openfoodfacts.github.scrachx.openfood.customtabs
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.util.Log
import androidx.appcompat.app.AppCompatDelegate
import androidx.browser.customtabs.CustomTabsIntent
import androidx.browser.customtabs.CustomTabsSession
import androidx.core.net.toUri
import openfoodfacts.github.scrachx.openfood.R
import openfoodfacts.github.scrachx.openfood.utils.Utils.getBitmapFromDrawable

Expand Down Expand Up @@ -77,8 +77,9 @@ object CustomTabsHelper {
if (sPackageNameToUse != null) return sPackageNameToUse

val pm = context.packageManager

// Get default VIEW intent handler.
val activityIntent = Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"))
val activityIntent = Intent(Intent.ACTION_VIEW, "https://www.example.com".toUri())
val defaultViewHandlerInfo = pm.resolveActivity(activityIntent, 0)
var defaultViewHandlerPackageName: String? = null
if (defaultViewHandlerInfo != null) {
Expand All @@ -87,12 +88,13 @@ object CustomTabsHelper {

// Get all apps that can handle VIEW intents.
val resolvedActivityList = pm.queryIntentActivities(activityIntent, 0)
val packagesSupportingCustomTabs: List<String?> = resolvedActivityList.mapNotNull { info ->
val packagesSupportingCustomTabs = resolvedActivityList.mapNotNull { info ->
val serviceIntent = Intent().apply {
action = ACTION_CUSTOM_TABS_CONNECTION
setPackage(info.activityInfo.packageName)
}
return if (pm.resolveService(serviceIntent, 0) != null) info.activityInfo.packageName else null
return@mapNotNull if (pm.resolveService(serviceIntent, 0) != null) info.activityInfo.packageName
else null
}

// Now packagesSupportingCustomTabs contains all apps that can handle both VIEW intents
Expand Down
Expand Up @@ -32,6 +32,7 @@ import io.reactivex.rxkotlin.addTo
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.launch
import kotlinx.coroutines.rx2.await
import kotlinx.coroutines.rx2.rxSingle
import net.steamcrafted.loadtoast.LoadToast
import openfoodfacts.github.scrachx.openfood.R
import openfoodfacts.github.scrachx.openfood.analytics.AnalyticsEvent
Expand Down Expand Up @@ -86,25 +87,25 @@ class AllergensAlertFragment : NavigationBaseFragment() {
val language = localeManager.getLanguage()

productRepository.getAllergensByEnabledAndLanguageCode(true, language)
.observeOn(AndroidSchedulers.mainThread())
.doOnError { Log.e(LOG_TAG, "getAllergensByEnabledAndLanguageCode", it) }
.subscribe { allergens ->
mAllergensEnabled = allergens.toMutableList()
adapter = AllergensAdapter(productRepository, mAllergensEnabled!!)

binding.allergensRecycle.adapter = adapter
binding.allergensRecycle.layoutManager = LinearLayoutManager(view.context)
binding.allergensRecycle.setHasFixedSize(true)
adapter.registerAdapterDataObserver(dataObserver)
dataObserver.onChanged()
}
.addTo(disp)
.observeOn(AndroidSchedulers.mainThread())
.doOnError { Log.e(LOG_TAG, "getAllergensByEnabledAndLanguageCode", it) }
.subscribe { allergens ->
mAllergensEnabled = allergens.toMutableList()
adapter = AllergensAdapter(productRepository, mAllergensEnabled!!)

binding.allergensRecycle.adapter = adapter
binding.allergensRecycle.layoutManager = LinearLayoutManager(view.context)
binding.allergensRecycle.setHasFixedSize(true)
adapter.registerAdapterDataObserver(dataObserver)
dataObserver.onChanged()
}
.addTo(disp)

productRepository.getAllergensByLanguageCode(language)
.observeOn(AndroidSchedulers.mainThread())
.doOnError { Log.e(LOG_TAG, "getAllergensByLanguageCode", it) }
.subscribe { allergens -> allergensFromDao = allergens }
.addTo(disp)
.observeOn(AndroidSchedulers.mainThread())
.doOnError { Log.e(LOG_TAG, "getAllergensByLanguageCode", it) }
.subscribe { allergens -> allergensFromDao = allergens }
.addTo(disp)

mSettings = requireActivity().getSharedPreferences("prefs", 0)
}
Expand Down Expand Up @@ -135,55 +136,55 @@ class AllergensAlertFragment : NavigationBaseFragment() {
private fun addAllergen() {
if (mAllergensEnabled != null && !allergensFromDao.isNullOrEmpty()) {
productRepository.getAllergensByEnabledAndLanguageCode(false, localeManager.getLanguage())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError { it.printStackTrace() }
.map { allergens -> allergens.sortedBy { it.name } }
.subscribe { allergens ->
MaterialDialog.Builder(requireContext())
.title(R.string.title_dialog_alert)
.items(allergens.map { it.name })
.itemsCallback { _, _, position, _ ->
viewLifecycleOwner.lifecycleScope.launch {
productRepository.setAllergenEnabled(allergens[position].allergenTag, true).await()
}
mAllergensEnabled!!.add(allergens[position])
adapter.notifyItemInserted(mAllergensEnabled!!.size - 1)
binding.allergensRecycle.scrollToPosition(adapter.itemCount - 1)
matomoAnalytics.trackEvent(AnalyticsEvent.AllergenAlertCreated(allergens[position].allergenTag))
}
.show()
}
.addTo(disp)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError { it.printStackTrace() }
.map { allergens -> allergens.sortedBy { it.name } }
.subscribe { allergens ->
MaterialDialog.Builder(requireContext())
.title(R.string.title_dialog_alert)
.items(allergens.map { it.name })
.itemsCallback { _, _, position, _ ->
viewLifecycleOwner.lifecycleScope.launch {
productRepository.setAllergenEnabled(allergens[position].allergenTag, true).await()
}
mAllergensEnabled!!.add(allergens[position])
adapter.notifyItemInserted(mAllergensEnabled!!.size - 1)
binding.allergensRecycle.scrollToPosition(adapter.itemCount - 1)
matomoAnalytics.trackEvent(AnalyticsEvent.AllergenAlertCreated(allergens[position].allergenTag))
}
.show()
}
.addTo(disp)
} else {
if (Utils.isNetworkConnected(requireContext())) {
val lt = LoadToast(context)
.setText(requireActivity().getString(R.string.toast_retrieving))
.setBackgroundColor(ResourcesCompat.getColor(requireContext().resources, R.color.blue, requireContext().theme))
.setTextColor(ResourcesCompat.getColor(requireActivity().resources, R.color.white, requireContext().theme))
.show()
.setText(requireActivity().getString(R.string.toast_retrieving))
.setBackgroundColor(ResourcesCompat.getColor(requireContext().resources, R.color.blue, requireContext().theme))
.setTextColor(ResourcesCompat.getColor(requireActivity().resources, R.color.white, requireContext().theme))
.show()

productRepository.getAllergens()
.observeOn(AndroidSchedulers.mainThread())
.doOnError {
mSettings.edit { putBoolean("errorAllergens", true) }
lt.error()
}
.subscribe { _ ->
mSettings.edit { putBoolean("errorAllergens", false) }
adapter.allergens = mAllergensEnabled!!
adapter.notifyDataSetChanged()
updateAllergenDao()
addAllergen()
lt.success()
}
.addTo(disp)
rxSingle { productRepository.getAllergens() }
.observeOn(AndroidSchedulers.mainThread())
.doOnError {
mSettings.edit { putBoolean("errorAllergens", true) }
lt.error()
}
.subscribe { _ ->
mSettings.edit { putBoolean("errorAllergens", false) }
adapter.allergens = mAllergensEnabled!!
adapter.notifyDataSetChanged()
updateAllergenDao()
addAllergen()
lt.success()
}
.addTo(disp)
} else {
MaterialDialog.Builder(requireContext())
.title(R.string.title_dialog_alert)
.content(R.string.info_download_data_connection)
.neutralText(R.string.txtOk)
.show()
.title(R.string.title_dialog_alert)
.content(R.string.info_download_data_connection)
.neutralText(R.string.txtOk)
.show()
}
}
}
Expand All @@ -194,15 +195,15 @@ class AllergensAlertFragment : NavigationBaseFragment() {
private fun updateAllergenDao() {
val language = localeManager.getLanguage()
productRepository.getAllergensByEnabledAndLanguageCode(true, language)
.observeOn(AndroidSchedulers.mainThread())
.doOnError { Log.e(AllergensAlertFragment::class.simpleName, "getAllergensByEnabledAndLanguageCode", it) }
.subscribe { allergens -> mAllergensEnabled = allergens.toMutableList() }
.addTo(disp)
.observeOn(AndroidSchedulers.mainThread())
.doOnError { Log.e(AllergensAlertFragment::class.simpleName, "getAllergensByEnabledAndLanguageCode", it) }
.subscribe { allergens -> mAllergensEnabled = allergens.toMutableList() }
.addTo(disp)
productRepository.getAllergensByLanguageCode(language)
.observeOn(AndroidSchedulers.mainThread())
.doOnError { Log.e(AllergensAlertFragment::class.simpleName, "getAllergensByLanguageCode", it) }
.subscribe { allergens -> allergensFromDao = allergens.toMutableList() }
.addTo(disp)
.observeOn(AndroidSchedulers.mainThread())
.doOnError { Log.e(AllergensAlertFragment::class.simpleName, "getAllergensByLanguageCode", it) }
.subscribe { allergens -> allergensFromDao = allergens.toMutableList() }
.addTo(disp)
}

@NavigationDrawerType
Expand Down
Expand Up @@ -26,6 +26,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.addTo
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.rx2.rxSingle
import openfoodfacts.github.scrachx.openfood.models.entities.category.Category
import openfoodfacts.github.scrachx.openfood.models.entities.category.CategoryName
import openfoodfacts.github.scrachx.openfood.repositories.ProductRepository
Expand All @@ -36,8 +37,8 @@ import javax.inject.Inject

@HiltViewModel
class CategoryFragmentViewModel @Inject constructor(
private val productRepository: ProductRepository,
private val localeManager: LocaleManager
private val productRepository: ProductRepository,
private val localeManager: LocaleManager
) : ViewModel() {
private val allCategories = mutableListOf<CategoryName>()
val shownCategories = ObservableArrayList<CategoryName>()
Expand All @@ -60,37 +61,37 @@ class CategoryFragmentViewModel @Inject constructor(
*/
fun refreshCategories() {
productRepository.getAllCategoriesByLanguageCode(localeManager.getLanguage())
.doOnSubscribe {
showOffline.set(View.GONE)
showProgress.set(View.VISIBLE)
}
.flatMap {
if (it.isEmpty()) {
productRepository.getAllCategoriesByDefaultLanguageCode()
} else Single.just(it)
}
.flatMap {
if (it.isEmpty()) {
productRepository.getCategories().map(this::extractCategoriesNames)
} else Single.just(it)
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError {
Log.e(CategoryFragmentViewModel::class.simpleName, "Error loading categories", it)
if (it is UnknownHostException) {
showOffline.set(View.VISIBLE)
showProgress.set(View.GONE)
}
.doOnSubscribe {
showOffline.set(View.GONE)
showProgress.set(View.VISIBLE)
}
.flatMap {
if (it.isEmpty()) {
productRepository.getAllCategoriesByDefaultLanguageCode()
} else Single.just(it)
}
.flatMap {
if (it.isEmpty()) {
rxSingle { extractCategoriesNames(productRepository.getCategories()) }
} else Single.just(it)
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError {
Log.e(CategoryFragmentViewModel::class.simpleName, "Error loading categories", it)
if (it is UnknownHostException) {
showOffline.set(View.VISIBLE)
showProgress.set(View.GONE)
}
.subscribe { categoryList ->
allCategories += categoryList
}
.subscribe { categoryList ->
allCategories += categoryList

shownCategories.clear()
shownCategories += categoryList
shownCategories.clear()
shownCategories += categoryList

showProgress.set(View.GONE)
}.addTo(disposable)
showProgress.set(View.GONE)
}.addTo(disposable)
}

/**
Expand All @@ -99,9 +100,9 @@ class CategoryFragmentViewModel @Inject constructor(
* @param categories list of all the categories loaded using API
*/
private fun extractCategoriesNames(categories: List<Category>) = categories
.flatMap { it.names }
.filter { it.languageCode == localeManager.getLanguage() }
.sortedWith { o1, o2 -> o1.name!!.compareTo(o2.name!!) }
.flatMap { it.names }
.filter { it.languageCode == localeManager.getLanguage() }
.sortedWith { o1, o2 -> o1.name!!.compareTo(o2.name!!) }

/**
* Search for all the category names that or equal to/start with a given string
Expand Down
Expand Up @@ -47,6 +47,7 @@ import com.squareup.picasso.Picasso
import dagger.hilt.android.AndroidEntryPoint
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.rxkotlin.addTo
import kotlinx.coroutines.runBlocking
import openfoodfacts.github.scrachx.openfood.AppFlavors.OFF
import openfoodfacts.github.scrachx.openfood.AppFlavors.isFlavors
import openfoodfacts.github.scrachx.openfood.R
Expand Down Expand Up @@ -842,7 +843,8 @@ class SummaryProductFragment : BaseFragment(), ISummaryProductPresenter.View {

private fun onBookmarkProductButtonClick() {
val activity: Activity = requireActivity()
val productLists = daoSession.getProductListsDaoWithDefaultList(activity).loadAll()
// TODO: 19/06/2021 remove runBlocking
val productLists = runBlocking { daoSession.getProductListsDaoWithDefaultList(activity).loadAll() }
val productBarcode = product.code
val productName = product.productName
val imageUrl = product.getImageSmallUrl(localeManager.getLanguage())
Expand Down

0 comments on commit 211c96e

Please sign in to comment.