I need to get the name of the app chosen by user fired with Intent.ACTION_SEND for analytic purposes. The name of app will be obtained through BroadcastReceiver.
It works until one day, the security engineer in our team informed us that all PendingIntent in the codebase must have PendingIntent.FLAG_IMMUTABLE to be secure.
The flag added breaks the existing functionality because intent?.getParcelableExtra<ComponentName>(Intent.EXTRA_CHOSEN_COMPONENT)?.packageName will always return null.
Is there anything I can do? PendingIntent.FLAG_MUTABLE is sadly not an option for me.
You can find same way of doing this from Android Documentation - Getting information about sharing
MainActivity.kt
const val PENDING_INTENT_REQUEST_CODE = 0x1000
const val THIRD_PARTY_SHARE_REQUEST_CODE = 0x1001
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnShare.setOnClickListener {
openThirdPartyShareDialog()
}
}
private fun openThirdPartyShareDialog() {
val thirdPartyShareIntent = Intent().apply {
action = Intent.ACTION_SEND
type = "text/plain"
}
val broadcastIntent = Intent(this, ThirdPartyAppBroadcastReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this,
PENDING_INTENT_REQUEST_CODE,
broadcastIntent,
getPendingFlagIntent()
)
startActivityForResult(Intent.createChooser(
thirdPartyShareIntent,
null,
pendingIntent.intentSender
), THIRD_PARTY_SHARE_REQUEST_CODE)
}
private fun getPendingFlagIntent(): Int {
var flags = PendingIntent.FLAG_UPDATE_CURRENT
if (Build.VERSION.SDK_INT >= 23) {
flags = flags or PendingIntent.FLAG_IMMUTABLE
}
return flags
}
}
ThirdPartyAppBroadcastReceiver.kt
class ThirdPartyAppBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
// packageName will always be null !
val packageName =
intent?.getParcelableExtra<ComponentName>(Intent.EXTRA_CHOSEN_COMPONENT)?.packageName
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.flamyoad.broadcast_share"
>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Broadcastshare"
>
<receiver android:name="com.flamyoad.broadcast_share.ThirdPartyAppBroadcastReceiver" />
<activity
android:name=".MainActivity"
android:exported="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>