Add support for background activity start mode

See https://developer.android.com/about/versions/14/behavior-changes-14#background-activity-restrictions
This commit is contained in:
cketti 2024-04-02 15:14:23 +02:00
parent 62fbfa0102
commit 1c4925b05d
10 changed files with 109 additions and 57 deletions

View file

@ -118,6 +118,7 @@ import com.fsck.k9.ui.helper.SizeFormatter;
import com.fsck.k9.ui.messagelist.DefaultFolderProvider;
import org.openintents.openpgp.OpenPgpApiManager;
import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpIntentStarter;
import timber.log.Timber;
@ -1622,7 +1623,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
public void onMessageBuildReturnPendingIntent(PendingIntent pendingIntent, int requestCode) {
requestCode |= REQUEST_MASK_MESSAGE_BUILDER;
try {
startIntentSenderForResult(pendingIntent.getIntentSender(), requestCode, null, 0, 0, 0);
OpenPgpIntentStarter.startIntentSenderForResult(this, pendingIntent.getIntentSender(), requestCode);
} catch (SendIntentException e) {
Timber.e(e, "Error starting pending intent from builder!");
}
@ -1631,9 +1632,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
public void launchUserInteractionPendingIntent(PendingIntent pendingIntent, int requestCode) {
requestCode |= REQUEST_MASK_RECIPIENT_PRESENTER;
try {
startIntentSenderForResult(pendingIntent.getIntentSender(), requestCode, null, 0, 0, 0);
OpenPgpIntentStarter.startIntentSenderForResult(this, pendingIntent.getIntentSender(), requestCode);
} catch (SendIntentException e) {
e.printStackTrace();
Timber.e(e, "Error starting pending intent from builder!");
}
}
@ -1689,11 +1690,10 @@ public class MessageCompose extends K9Activity implements OnClickListener,
}
@Override
public boolean startIntentSenderForMessageLoaderHelper(IntentSender si, int requestCode, Intent fillIntent,
int flagsMask, int flagValues, int extraFlags) {
public boolean startIntentSenderForMessageLoaderHelper(IntentSender intentSender, int requestCode) {
try {
requestCode |= REQUEST_MASK_LOADER_HELPER;
startIntentSenderForResult(si, requestCode, fillIntent, flagsMask, flagValues, extraFlags);
OpenPgpIntentStarter.startIntentSenderForResult(MessageCompose.this, intentSender, requestCode);
} catch (SendIntentException e) {
Timber.e(e, "Irrecoverable error calling PendingIntent!");
}

View file

@ -357,14 +357,12 @@ public class MessageLoaderHelper {
}
@Override
public boolean startPendingIntentForCryptoHelper(IntentSender si, int requestCode, Intent fillIntent,
int flagsMask, int flagValues, int extraFlags) {
public boolean startPendingIntentForCryptoHelper(IntentSender intentSender, int requestCode) {
if (callback == null) {
throw new IllegalStateException("unexpected call when callback is already detached");
}
return callback.startIntentSenderForMessageLoaderHelper(si, requestCode, fillIntent,
flagsMask, flagValues, extraFlags);
return callback.startIntentSenderForMessageLoaderHelper(intentSender, requestCode);
}
};
@ -524,8 +522,7 @@ public class MessageLoaderHelper {
void setLoadingProgress(int current, int max);
boolean startIntentSenderForMessageLoaderHelper(IntentSender si, int requestCode, Intent fillIntent,
int flagsMask, int flagValues, int extraFlags);
boolean startIntentSenderForMessageLoaderHelper(IntentSender intentSender, int requestCode);
void onDownloadErrorMessageNotFound();
void onDownloadErrorNetworkError();

View file

@ -1,7 +1,6 @@
package com.fsck.k9.ui.crypto;
import android.content.Intent;
import android.content.IntentSender;
import com.fsck.k9.mailstore.MessageCryptoAnnotations;
@ -10,6 +9,5 @@ import com.fsck.k9.mailstore.MessageCryptoAnnotations;
public interface MessageCryptoCallback {
void onCryptoHelperProgress(int current, int max);
void onCryptoOperationsFinished(MessageCryptoAnnotations annotations);
boolean startPendingIntentForCryptoHelper(IntentSender si, int requestCode, Intent fillIntent,
int flagsMask, int flagValues, int extraFlags);
boolean startPendingIntentForCryptoHelper(IntentSender intentSender, int requestCode);
}

View file

@ -795,7 +795,7 @@ public class MessageCryptoHelper {
callback.onCryptoOperationsFinished(queuedResult);
} else if (queuedPendingIntent != null) {
boolean pendingIntentHandled = callback.startPendingIntentForCryptoHelper(
queuedPendingIntent.getIntentSender(), REQUEST_CODE_USER_INTERACTION, null, 0, 0, 0);
queuedPendingIntent.getIntentSender(), REQUEST_CODE_USER_INTERACTION);
if (pendingIntentHandled) {
queuedPendingIntent = null;
}

View file

@ -19,6 +19,7 @@ import com.fsck.k9.view.StatusIndicator
import kotlinx.coroutines.delay
import org.koin.android.ext.android.inject
import org.koin.core.parameter.parametersOf
import org.openintents.openpgp.util.OpenPgpIntentStarter
import timber.log.Timber
class AutocryptKeyTransferActivity : K9Activity() {
@ -161,9 +162,9 @@ class AutocryptKeyTransferActivity : K9Activity() {
fun launchUserInteractionPendingIntent(pendingIntent: PendingIntent) {
try {
startIntentSender(pendingIntent.intentSender, null, 0, 0, 0)
OpenPgpIntentStarter.startIntentSender(this, pendingIntent.intentSender)
} catch (e: SendIntentException) {
Timber.e(e)
Timber.e(e, "Error starting PendingIntent")
}
}

View file

@ -2,6 +2,7 @@ package com.fsck.k9.ui.messagedetails
import android.app.PendingIntent
import android.content.Intent
import android.content.IntentSender.SendIntentException
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
@ -36,6 +37,8 @@ import com.mikepenz.fastadapter.listeners.ClickEventHook
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import org.openintents.openpgp.util.OpenPgpIntentStarter
import timber.log.Timber
class MessageDetailsFragment : ToolbarBottomSheetDialogFragment() {
private val viewModel: MessageDetailsViewModel by viewModel()
@ -333,7 +336,11 @@ class MessageDetailsFragment : ToolbarBottomSheetDialogFragment() {
}
private fun showCryptoKeys(pendingIntent: PendingIntent) {
requireActivity().startIntentSender(pendingIntent.intentSender, null, 0, 0, 0)
try {
OpenPgpIntentStarter.startIntentSender(requireActivity(), pendingIntent.intentSender)
} catch (e: SendIntentException) {
Timber.e(e, "Error starting PendingIntent")
}
}
private fun searchCryptoKeys() {

View file

@ -120,7 +120,7 @@ public class MessageCryptoPresenter {
PendingIntent pendingIntent = cryptoResultAnnotation.getOpenPgpSigningKeyIntentIfAny();
if (pendingIntent != null) {
messageCryptoMvpView.startPendingIntentForCryptoPresenter(
pendingIntent.getIntentSender(), REQUEST_CODE_UNKNOWN_KEY, null, 0, 0, 0);
pendingIntent.getIntentSender(), REQUEST_CODE_UNKNOWN_KEY);
}
} catch (IntentSender.SendIntentException e) {
Timber.e(e, "SendIntentException");
@ -136,7 +136,7 @@ public class MessageCryptoPresenter {
PendingIntent pendingIntent = cryptoResultAnnotation.getOpenPgpInsecureWarningPendingIntent();
if (pendingIntent != null) {
messageCryptoMvpView.startPendingIntentForCryptoPresenter(
pendingIntent.getIntentSender(), REQUEST_CODE_SECURITY_WARNING, null, 0, 0, 0);
pendingIntent.getIntentSender(), REQUEST_CODE_SECURITY_WARNING);
}
} catch (IntentSender.SendIntentException e) {
Timber.e(e, "SendIntentException");
@ -171,8 +171,8 @@ public class MessageCryptoPresenter {
void redisplayMessage();
void restartMessageCryptoProcessing();
void startPendingIntentForCryptoPresenter(IntentSender si, Integer requestCode, Intent fillIntent,
int flagsMask, int flagValues, int extraFlags) throws IntentSender.SendIntentException;
void startPendingIntentForCryptoPresenter(IntentSender intentSender, Integer requestCode)
throws IntentSender.SendIntentException;
void showCryptoConfigDialog();
}

View file

@ -54,6 +54,7 @@ import com.fsck.k9.ui.share.ShareIntentBuilder
import com.fsck.k9.ui.withArguments
import java.util.Locale
import org.koin.android.ext.android.inject
import org.openintents.openpgp.util.OpenPgpIntentStarter
import timber.log.Timber
class MessageViewFragment :
@ -828,24 +829,9 @@ class MessageViewFragment :
}
@Throws(SendIntentException::class)
override fun startPendingIntentForCryptoPresenter(
intentSender: IntentSender,
requestCode: Int,
fillIntent: Intent?,
flagsMask: Int,
flagValues: Int,
extraFlags: Int,
) {
override fun startPendingIntentForCryptoPresenter(intentSender: IntentSender, requestCode: Int) {
val maskedRequestCode = requestCode or REQUEST_MASK_CRYPTO_PRESENTER
startIntentSenderForResult(
intentSender,
maskedRequestCode,
fillIntent,
flagsMask,
flagValues,
extraFlags,
null,
)
OpenPgpIntentStarter.startIntentSenderForResult(this@MessageViewFragment, intentSender, maskedRequestCode)
}
override fun restartMessageCryptoProcessing() {
@ -921,27 +907,16 @@ class MessageViewFragment :
Toast.makeText(requireContext(), R.string.status_network_error, Toast.LENGTH_LONG).show()
}
override fun startIntentSenderForMessageLoaderHelper(
intentSender: IntentSender,
requestCode: Int,
fillIntent: Intent?,
flagsMask: Int,
flagValues: Int,
extraFlags: Int,
): Boolean {
override fun startIntentSenderForMessageLoaderHelper(intentSender: IntentSender, requestCode: Int): Boolean {
if (!isActive) return false
showProgressThreshold = null
try {
val maskedRequestCode = requestCode or REQUEST_MASK_LOADER_HELPER
startIntentSenderForResult(
OpenPgpIntentStarter.startIntentSenderForResult(
this@MessageViewFragment,
intentSender,
maskedRequestCode,
fillIntent,
flagsMask,
flagValues,
extraFlags,
null,
)
} catch (e: SendIntentException) {
Timber.e(e, "Irrecoverable error calling PendingIntent!")

View file

@ -0,0 +1,75 @@
package org.openintents.openpgp.util
import android.app.Activity
import android.app.ActivityOptions
import android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
import android.content.IntentSender
import android.os.Build
import android.os.Bundle
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
/**
* Start OpenPGP crypto provider intents.
*
* On Android 14+ we need to use [MODE_BACKGROUND_ACTIVITY_START_ALLOWED] in order to start those intents.
*/
object OpenPgpIntentStarter {
@Throws(IntentSender.SendIntentException::class)
fun startIntentSender(activity: Activity, intentSender: IntentSender) {
val options = buildOptionsBundle()
activity.startIntentSender(
intentSender,
/* fillInIntent = */ null,
/* flagsMask = */ 0,
/* flagsValues = */ 0,
/* extraFlags = */ 0,
options,
)
}
@JvmStatic
@Throws(IntentSender.SendIntentException::class)
fun startIntentSenderForResult(activity: Activity, intentSender: IntentSender, requestCode: Int) {
val options = buildOptionsBundle()
activity.startIntentSenderForResult(
intentSender,
requestCode,
/* fillInIntent = */ null,
/* flagsMask = */ 0,
/* flagsValues = */ 0,
/* extraFlags = */ 0,
options,
)
}
@JvmStatic
@Throws(IntentSender.SendIntentException::class)
fun startIntentSenderForResult(fragment: Fragment, intentSender: IntentSender, requestCode: Int) {
val options = buildOptionsBundle()
@Suppress("DEPRECATION")
fragment.startIntentSenderForResult(
intentSender,
requestCode,
/* fillInIntent = */ null,
/* flagsMask = */ 0,
/* flagsValues = */ 0,
/* extraFlags = */ 0,
options,
)
}
private fun buildOptionsBundle(): Bundle? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
ActivityOptions.makeBasic().apply {
setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
setShareIdentityEnabled(true)
}.toBundle()
} else {
null
}
}
}

View file

@ -196,9 +196,8 @@ public class OpenPgpKeyPreference extends Preference implements OpenPgpApiManage
}
try {
intentSenderFragment
.startIntentSenderForResult(pendingIntentSelectKey.getIntentSender(), REQUEST_CODE_KEY_PREFERENCE,
null, 0, 0, 0, null);
OpenPgpIntentStarter.startIntentSenderForResult(intentSenderFragment,
pendingIntentSelectKey.getIntentSender(), REQUEST_CODE_KEY_PREFERENCE);
} catch (IntentSender.SendIntentException e) {
Timber.e(e,"Error launching pending intent");
} finally {