I am trying to use PackageInstaller to install apk's, when I commit the session to package install to begin the install process my Broadcast Receiver gets the action but none of the extras for the status, package name, status message, session id are in the intent
Here is how I create the session
override suspend fun installUpdates(): Unit = withContext(Dispatchers.IO) {
try {
apkDirectory.listFiles()?.forEach { apk ->
val params = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
val sessionId = context.packageManager.packageInstaller.createSession(params)
val session = context.packageManager.packageInstaller.openSession(sessionId)
apk.inputStream().use { apkStream ->
session.openWrite(apk.nameWithoutExtension, 0, apk.length()).use { sessionStream ->
apkStream.copyTo(sessionStream)
session.fsync(sessionStream)
}
}
val intent = Intent(context, InstallReceiver::class.java)
intent.action = InstallReceiver.ACTION_INSTALL
val pi = PendingIntent.getBroadcast(
context,
InstallReceiver::class.hashCode(),
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
session.commit(pi.intentSender)
session.close()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
Here is my broadcast receiver
<receiver android:name=".shared.updater.InstallReceiver"
android:exported="false">
<intent-filter>
<action android:name="xx.xx.installer.InstallReceiver.ACTION_INSTALL" />
</intent-filter>
</receiver>
Code
override fun onReceive(context: Context, intent: Intent) {
if(intent.action == ACTION_INSTALL){
val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -2)
val message: String? = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)
val pname = intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME)
val sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, 0)
val sessionInfo: SessionInfo? = intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION)
Log.d(TAG, "Status: $status, Message: $message, Package Name: $pname, Session ID: $sessionId")
when (status) {
PackageInstaller.STATUS_PENDING_USER_ACTION -> {
// This test app isn't privileged, so the user has to confirm the install.
Log.d(TAG, "Install needs user interaction")
}
PackageInstaller.STATUS_SUCCESS -> {
Log.d(TAG, "Installed successfully")
}
PackageInstaller.STATUS_FAILURE,
PackageInstaller.STATUS_FAILURE_ABORTED,
PackageInstaller.STATUS_FAILURE_BLOCKED,
PackageInstaller.STATUS_FAILURE_CONFLICT,
PackageInstaller.STATUS_FAILURE_INCOMPATIBLE,
PackageInstaller.STATUS_FAILURE_INVALID,
PackageInstaller.STATUS_FAILURE_STORAGE,
PackageInstaller.STATUS_FAILURE_TIMEOUT -> {
val message: String? = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)
Log.d(TAG, "Install failure, Status: $status, Message: $message")
}
else -> {
//Unknown status
Log.d(TAG, "Unknown install status $status")
}
}
}else{
Log.d(TAG, "Unknown action ${intent.action}")
}
}
}
All the extras come back as the default value or null but the apk's do install correctly.
I have the install packages permission too (app was copied to the system/priv-app folder on a rooted device)
<uses-permission android:name="android.permission.INSTALL_PACKAGES"/>
I am not sure what I am doing wrong, all the examples I have looked at for using package manager appear to be doing what I am doing
The issue was the Pending Intent flag PendingIntent.FLAG_IMMUTABLE
it needs to be PendingIntent.FLAG_MUTABLE
for the extras to be present