← Назад к вопросам

Как вернуть результат при возвращении из другого приложения

2.0 Middle🔥 141 комментариев
#Android компоненты#Жизненный цикл и навигация

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Возврат результата из другого приложения в Android

Возвращение результата при переходе из одного приложения в другое — стандартный сценарий взаимодействия между приложениями в Android, реализуемый через механизм Intent и методы startActivityForResult() (для устаревших API) или Activity Result API (современный подход, рекомендуется с AndroidX Activity 1.2.0+). Основная идея: ваше приложение (приложение-источник) запускает активность другого приложения (приложение-цель) с явным запросом на возврат результата, а целевое приложение по завершении работы отправляет обратно Intent с данными.

Ключевые концепции и компоненты

  • Неявный Intent: чаще всего используется для запуска активности другого приложения, так как вы указываете action (например, Intent.ACTION_PICK для выбора контакта или изображения) и тип данных, а система находит подходящее приложение.
  • Код запроса (requestCode): уникальный идентификатор, позволяющий различать, от какой активности пришёл результат, если их несколько.
  • Intent с результатом: целевое приложение перед завершением вызывает setResult(resultCode, dataIntent), где resultCode — обычно RESULT_OK или RESULT_CANCELED, а dataIntent содержит возвращаемые данные (например, URI выбранного изображения).
  • Обработка результата: приложение-источник получает результат в методе onActivityResult() (старый способ) или через Activity Result API.

Современный подход: Activity Result API

Этот API устраняет недостатки startActivityForResult() (например, необходимость переопределять метод в активности, сложность тестирования). Вот полный пример:

// 1. Объявление контракта для запуска активности с возвратом результата
val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
    // Обработка результата: uri выбранного изображения
    uri?.let {
        imageView.setImageURI(it)
    }
}

// 2. Запуск другого приложения для выбора изображения
button.setOnClickListener {
    getContent.launch("image/*") // MIME-тип для фильтрации приложений
}

Если нужно передать дополнительные данные в Intent:

// Контракт для запуска любой активности с возвратом результата
val startActivityForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
    if (result.resultCode == Activity.RESULT_OK) {
        val data: Intent? = result.data
        // Извлечение данных из data
        val returnedValue = data?.getStringExtra("KEY_RESULT")
    }
}

// Создание Intent для запуска другого приложения
val intent = Intent(Intent.ACTION_PICK).apply {
    type = "image/*"
    putExtra("EXTRA_SOURCE", "gallery") // дополнительные параметры
}

// Запуск
startActivityForResult.launch(intent)

Как целевое приложение возвращает результат

Приложение-цель (например, галерея) должно корректно установить результат перед завершением:

// В активности целевого приложения (например, после выбора изображения)
val resultIntent = Intent().apply {
    data = selectedImageUri // URI выбранного изображения
    putExtra("EXTRA_INFO", "Дополнительные данные")
}
setResult(Activity.RESULT_OK, resultIntent)
finish() // Активность завершается, результат отправляется обратно

Если пользователь отменил действие:

setResult(Activity.RESULT_CANCELED)
finish()

Особенности и лучшие практики

  • Разрешения: Убедитесь, что ваше приложение имеет необходимые разрешения (READ_EXTERNAL_STORAGE для доступа к медиа) до или после получения результата.
  • Обработка null: Всегда проверяйте resultCode и data на null, так как целевое приложение может не вернуть ожидаемые данные.
  • Безопасность: При получении URI от другого приложения используйте ContentResolver для безопасного доступа, так как прямое использование файловых путей может быть небезопасным.
  • Контракты: Activity Result API предоставляет готовые контракты для распространённых действий: GetContent(), TakePicture(), RequestPermission(), StartIntentSenderForResult() (для разрешений с API 30+).
  • Архитектура: Для MVVM используйте Activity Result API в сочетании с ViewModel, чтобы не привязывать логику обработки результата к жизненному циклу активности.

Пример реального использования

Предположим, приложению нужно получить номер телефона из контактов:

val pickContact = registerForActivityResult(ActivityResultContracts.PickContact()) { uri: Uri? ->
    uri?.let { contactUri ->
        // Запрос к ContactsContract для извлечения номера телефона
        val cursor = contentResolver.query(contactUri, null, null, null, null)
        cursor?.use {
            if (it.moveToFirst()) {
                val phoneNumber = it.getString(it.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
                phoneNumberTextView.text = phoneNumber
            }
        }
    }
}

// Запуск стандартного приложения контактов
pickContact.launch(null)

Использование Activity Result API делает код более модульным, тестируемым и избегает проблем с жизненным циклом активности, поэтому он является предпочтительным для новых проектов. Для поддержки старых версий Android (до API 11) придётся использовать startActivityForResult(), но с помощью AndroidX эти случаи покрываются библиотекой.