Revision control

Copy as Markdown

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.focus.utils
import android.app.PendingIntent
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.LabeledIntent
import android.os.Build
import android.os.Parcelable
import mozilla.components.support.utils.ext.queryIntentActivitiesCompat
object IntentUtils {
/**
* Since Android 12 we need to set PendingIntent mutability explicitly, but Android 6 can be the minimum version
* This additional requirement improves your app's security.
* FLAG_IMMUTABLE -> Flag indicating that the created PendingIntent should be immutable.
*/
fun defaultIntentPendingFlags(buildVersion: Int = Build.VERSION.SDK_INT): Int =
if (buildVersion >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE
} else {
0 // No flags. Default behavior.
}
/**
* Method for creating an intent chooser but without the current app
*/
fun getIntentChooser(
context: Context,
intent: Intent,
chooserTitle: CharSequence? = null,
): Intent {
val chooserIntent: Intent
val resolveInfos = context.packageManager.queryIntentActivitiesCompat(intent, 0).toHashSet()
val excludedComponentNames = resolveInfos
.map { it.activityInfo }
.filter { it.packageName == context.packageName }
.map { ComponentName(it.packageName, it.name) }
// Starting with Android N we can use Intent.EXTRA_EXCLUDE_COMPONENTS to exclude components
// other way we are constrained to use Intent.EXTRA_INITIAL_INTENTS.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
chooserIntent = Intent.createChooser(intent, chooserTitle)
.putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames.toTypedArray())
} else {
var targetIntents = resolveInfos
.filterNot { it.activityInfo.packageName == context.packageName }
.map { resolveInfo ->
val activityInfo = resolveInfo.activityInfo
val targetIntent = Intent(intent).apply {
component = ComponentName(activityInfo.packageName, activityInfo.name)
}
LabeledIntent(
targetIntent,
activityInfo.packageName,
resolveInfo.labelRes,
resolveInfo.icon,
)
}
// Sometimes on Android M and below an empty chooser is displayed, problem reported also here
// To fix that we are creating a chooser with an empty intent
chooserIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent.createChooser(Intent(), chooserTitle)
} else {
targetIntents = targetIntents.toMutableList()
Intent.createChooser(targetIntents.removeAt(0), chooserTitle)
}
chooserIntent.putExtra(
Intent.EXTRA_INITIAL_INTENTS,
targetIntents.toTypedArray<Parcelable>(),
)
}
return chooserIntent
}
}