ارسال داده به برنامه‌های دیگر

‫Android دو روش برای هم‌رسانی داده بین برنامه‌ها دراختیار کاربران قرار می‌دهد:

  • «برگه هم‌رسانی Android» اساساً برای ارسال محتوا به خارج از برنامه یا مستقیماً به کاربر دیگر طراحی شده است. برای مثال، هم‌رسانی نشانی وب با دوست.
  • «حل‌کننده هدف Android» برای انتقال داده به مرحله بعدی یک تکلیف خوش‌تعریف بهترین گزینه است. برای مثال، باز کردن PDF از برنامه‌تان و اجازه دادن به کاربران برای انتخاب نمایشگر دلخواهشان.

چرا باید از «برگه هم‌رسانی Android» استفاده کرد

شکل ۱. برگه هم‌رسانی Android.

از «کاربرگ هم‌رسانی Android» برای ایجاد یکپارچگی برای کاربران در برنامه‌ها استفاده کنید. فهرست هدف‌های هم‌رسانی برنامه‌تان را نمایش ندهید یا انواع «برگه هم‌رسانی» خودتان را ایجاد نکنید.

«برگ هم‌رسانی Android» به کاربران امکان می‌دهد اطلاعات را با فرد مناسب، با پیشنهادهای برنامه مرتبط، و تنها با یک ضربه هم‌رسانی کنند. «برگه هم‌رسانی» می‌تواند هدف‌هایی را پیشنهاد دهد که برای راه‌حل‌های سفارشی دردسترس نیستند و از رتبه‌بندی ثابتی استفاده می‌کند. دلیل این امر این است که «برگ هم‌رسانی» می‌تواند اطلاعات مربوط به فعالیت برنامه و کاربر را درنظر بگیرد که فقط برای سیستم دردسترس است.

«برگ هم‌رسانی Android» نیز ویژگی‌های کاربردی زیادی برای توسعه‌دهندگان دارد. برای مثال، می‌توانید کارهای زیر را انجام دهید:

استفاده از «برگه هم‌رسانی Android»

برای همه انواع هم‌رسانی، قصدی ایجاد کنید و کنش آن را روی Intent.ACTION_SEND تنظیم کنید. برای نمایش «برگه هم‌رسانی Android»، Intent.createChooser() را فراخوانی کنید و شیء Intent را به آن ارسال کنید. این روش نسخه‌ای از هدف شما را برمی‌گرداند که همیشه «برگه هم‌رسانی Android» را نمایش می‌دهد.

ارسال محتوای نوشتاری

ساده‌ترین و رایج‌ترین کاربرد «برگه هم‌رسانی Android» ارسال محتوای نوشتاری از یک فعالیت به فعالیت دیگر است. برای مثال، اکثر مرورگرها می‌توانند نشانی وب صفحه درحال نمایش را به‌صورت نوشتار با برنامه دیگری هم‌رسانی کنند. این ویژگی برای هم‌رسانی مقاله یا وب‌سایت با دوستان ازطریق ایمیل یا شبکه‌های اجتماعی مفید است. در Jetpack Compose، بااستفاده از LocalContext.current، بافت فعلی را بازیابی کنید و context.startActivity() را فراخوانی کنید. در اینجا مثالی از نحوه انجام این کار آورده شده است:

fun shareText(context: Context) {
    val sendIntent: Intent = Intent().apply {
        action = ACTION_SEND
        putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
        type = "text/plain"
    }

    val shareIntent = Intent.createChooser(sendIntent, null)
    context.startActivity(shareIntent)
}

درصورت تمایل، می‌توانید موارد اضافی را برای گنجاندن اطلاعات بیشتر اضافه کنید، مثلاً گیرندگان ایمیل (EXTRA_EMAIL، EXTRA_CC، EXTRA_BCC)، یا موضوع ایمیل (EXTRA_SUBJECT).

توجه: برخی‌از برنامه‌های ایمیل، مثل Gmail، برای موارد اضافی مثل EXTRA_EMAIL و EXTRA_CC، String[] را انتظار دارند. از putExtra(String, String[]) برای افزودن این‌ها به هدف استفاده کنید.

ارسال محتوای دودویی

داده‌های باینری را بااستفاده از کنش ACTION_SEND هم‌رسانی کنید. نوع MIME مناسب را تنظیم کنید و نشانی وب داده‌ها را در extra EXTRA_STREAM، همان‌طور که در مثال زیر نشان داده شده است، قرار دهید. این مورد معمولاً برای هم‌رسانی تصویر استفاده می‌شود اما می‌تواند برای هم‌رسانی هر نوع محتوای دودویی استفاده شود.

fun shareBinaryContent(context: Context) {
    val shareIntent: Intent = Intent().apply {
        action = ACTION_SEND
        // Example: content://com.google.android.apps.photos.contentprovider/...
        val imageUri: Uri =
            Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/1")
        putExtra(Intent.EXTRA_STREAM, imageUri)
        type = "image/jpeg"
    }
    context.startActivity(Intent.createChooser(shareIntent, null))
}

برنامه دریافت‌کننده برای دسترسی به داده‌هایی که Uri به آن‌ها اشاره می‌کند به اجازه نیاز دارد. دو روش توصیه‌شده برای انجام این کار وجود دارد:

  • داده‌ها را در ContentProvider خودتان ذخیره کنید و مطمئن شوید که برنامه‌های دیگر اجازه دسترسی به ارائه‌دهنده شما را دارند. سازوکار ترجیحی برای ارائه دسترسی استفاده از اجازه‌های هر نشانی وب است که موقتی هستند و فقط به برنامه دریافت‌کننده اجازه دسترسی می‌دهند. برای ایجاد ContentProvider مانند این، از کلاس کمکی FileProvider استفاده کنید.
  • از MediaStore سیستم استفاده کنید. MediaStore در درجه اول برای انواع رسانه ویدیو، صدا، و تصویر است. بااین‌حال، از Android 3.0 (سطح میانای برنامه‌سازی کاربردی ۱۱) به بعد، می‌تواند انواع غیررسانه‌ای را نیز ذخیره کند. برای اطلاعات بیشتر، به اینجا مراجعه کنید: MediaStore.Files. فایل‌ها را می‌توان بااستفاده از scanFile() در MediaStore درج کرد، سپس یک Uri به سبک content:// مناسب برای هم‌رسانی به onScanCompleted() فراخوان ارائه‌شده ارسال می‌شود. توجه داشته باشید که پس‌از اضافه شدن به سیستم MediaStore، محتوا برای هر برنامه‌ای در دستگاه دردسترس است.

از نوع MIME درست استفاده کنید

خاص‌ترین نوع MIME دردسترس برای داده‌هایی را که ارسال می‌کنید ارائه دهید. برای مثال، هنگام هم‌رسانی نوشتار ساده از text/plain استفاده کنید. در اینجا چند نوع MIME رایج هنگام ارسال داده در Android آورده شده است:

گیرندگان برای ثبت‌نام می‌کنند فرستندگان ارسال می‌کنند
text/*
  • text/plain
  • text/rtf
  • text/html
  • text/json
image/*
  • image/jpg
  • image/png
  • image/gif
video/*
  • video/mp4
  • video/3gp
پسوندهای فایل پشتیبانی‌شده application/pdf

برای تعیین نوع MIME به‌صورت پویا در زمان اجرا به‌جای کدگذاری سخت آن، از روش‌های زیر استفاده کنید:

  • برای نشانی‌های وب content:// (مثل نشانی‌های وب ارائه‌شده توسط FileProvider یا MediaStore)، ContentResolver.getType() را فراخوانی کنید.
  • برای پسوندهای فایل، با MimeTypeMap.getSingleton().getMimeTypeFromExtension() تماس بگیرید.
  • اگر از «چارچوب دسترسی به فضای ذخیره‌سازی» استفاده می‌کنید، می‌توانید DocumentFile.getType() را نیز پُرسمان کنید.

اگر نمی‌توانید نوع MIME خاصی را تعیین کنید، از application/octet-stream برای داده‌های باینری عمومی یا در آخرین مرحله از */* استفاده کنید.

برای اطلاعات بیشتر درباره انواع MIME، به ثبت رسمی IANA انواع رسانه MIME مراجعه کنید.

«برگ هم‌رسانی Android» ممکن است پیش‌نمایش محتوا را براساس نوع MIME ارائه‌شده نشان دهد. برخی ویژگی‌های پیش‌نمایشی فقط برای انواع خاصی دردسترس است.

هم‌رسانی چند محتوا

برای هم‌رسانی چند محتوا، از ACTION_SEND_MULTIPLE عمل همراه با فهرست نشانی‌های وب اشاره‌کننده به محتوا استفاده کنید. نوع MIME براساس ترکیب محتوایی که هم‌رسانی می‌کنید متفاوت است. برای مثال، اگر سه تصویر JPEG را هم‌رسانی کنید، از نوع "image/jpg" استفاده می‌کنید. برای ترکیبی از انواع تصویر، از "image/*" برای مطابقت با فعالیتی که هر نوع تصویری را مدیریت می‌کند استفاده کنید. اگرچه امکان هم‌رسانی ترکیبی از انواع وجود دارد، از انجام این کار خودداری کنید زیرا برای گیرنده مشخص نیست که چه چیزی قرار است ارسال شود. اگر لازم است چند نوع ارسال کنید، از "*/*" استفاده کنید. برنامه دریافت‌کننده باید داده‌هایتان را تجزیه و تحلیل و پردازش کند. مثالی در اینجا ارائه شده است:

fun shareMultiple(context: Context) {
    val imageUris: ArrayList<Uri> = arrayListOf(
        Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/1"),
        Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/2")
    )

    val shareIntent = Intent().apply {
        action = Intent.ACTION_SEND_MULTIPLE
        putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris)
        type = "image/*"
    }
    context.startActivity(Intent.createChooser(shareIntent, null))
}

مطمئن شوید که اشیاء Uri ارائه‌شده به داده‌هایی اشاره می‌کنند که برنامه دریافت‌کننده می‌تواند به آن‌ها دسترسی داشته باشد.

افزودن محتوای غنی به پیش‌نمایش‌های نوشتاری

از Android 10 (سطح میانای برنامه‌سازی کاربردی ۲۹)، «برگه هم‌رسانی Android» پیش‌نمایشی از نوشتار درحال هم‌رسانی نشان می‌دهد. در برخی موارد، درک نوشتاری که هم‌رسانی می‌شود ممکن است دشوار باشد. هم‌رسانی نشانی وب پیچیده‌ای مثل https://www.google.com/search?ei=2rRVXcLkJajM0PEPoLy7oA4 را درنظر بگیرید. پیش‌نمایش غنی‌تر می‌تواند به کاربران شما اطمینان دهد که چه چیزی هم‌رسانی می‌شود.

اگر درحال پیش‌نمایش نوشتار هستید، می‌توانید عنوان، تصویر ریزعکس، یا هر دو را تنظیم کنید. قبل‌از فراخوانی Intent.createChooser()، شرحی به Intent.EXTRA_TITLE اضافه کنید و بااستفاده از ClipData، ریزعکس مربوطه را اضافه کنید.

توجه: شناسه منبع یکسان محتوای تصویر از FileProvider، معمولاً از <cache-path> پیکربندی‌شده ارائه می‌شود. برای اطلاعات بیشتر، به هم‌رسانی فایل‌ها مراجعه کنید. حتماً به «برگه هم‌رسانی» اجازه‌های لازم را برای خواندن هر تصویری که می‌خواهید به‌عنوان تصویر کوچک استفاده کنید بدهید. برای اطلاعات بیشتر، به Intent.FLAG_GRANT_READ_URI_PERMISSION مراجعه کنید.

مثالی در اینجا ارائه شده است:

fun richContentToTextPreviewShares(context: Context) {
    val share = Intent.createChooser(
        Intent().apply {
            action = ACTION_SEND
            putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/")

            // (Optional) Here you're setting the title of the content
            putExtra(Intent.EXTRA_TITLE, "Introducing content previews")

            // (Optional) Here you're passing a content URI to an image to be displayed
            data =
                Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/A123456789")
            flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
        },
        null
    )
    context.startActivity(share)
}

پیش‌نمایش چیزی شبیه به این است:

شکل ۲. پیش‌نمایش محتوای نوشتاری در «برگه هم‌رسانی Android».

افزودن کنش‌های سفارشی به برگ هم‌رسانی

شکل ۳. کنش‌های سفارشی در «برگه هم‌رسانی Android».

در Android 14 (سطح میانای برنامه‌سازی کاربردی ۳۴) و بالاتر، برنامه‌ها می‌توانند کنش‌های سفارشی به «برگه هم‌رسانی Android» اضافه کنند. کنش‌های سفارشی به‌صورت نمادهای کنش کوچک در بالای «برگه هم‌رسانی Android» نشان داده می‌شوند و برنامه‌ها می‌توانند هر Intent را به‌عنوان کنش فراخوانده‌شده هنگام کلیک کردن روی نماد مشخص کنند.

برای افزودن کنش‌های سفارشی در «برگه هم‌رسانی Android»، ابتدا ChooserAction را با ChooserAction.Builder ایجاد کنید. می‌توانید PendingIntent را به‌عنوان کنشی که هنگام کلیک روی نماد فراخوانده می‌شود مشخص کنید. آرایه‌ای حاوی همه کنش‌های سفارشی‌تان ایجاد کنید و آن را به‌عنوان EXTRA_CHOOSER_CUSTOM_ACTIONS از هم‌رسانی Intent مشخص کنید.

fun sharesheetCustomActions(context: Context, previewText: String) {
    val sendIntent = Intent(ACTION_SEND)
        .setType("text/plain")
        .putExtra(Intent.EXTRA_TEXT, previewText)
    val shareIntent = Intent.createChooser(sendIntent, null)
    val customActions = arrayOf(
        ChooserAction.Builder(
            Icon.createWithResource(context, R.drawable.ic_logo),
            "Custom",
            PendingIntent.getBroadcast(
                context,
                1,
                Intent(Intent.ACTION_VIEW),
                PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
            )
        ).build()
    )
    shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, customActions)
    context.startActivity(shareIntent)
}

افزودن هدف‌های سفارشی

«برگه هم‌رسانی Android» به شما امکان می‌دهد تا دو هدف فعالیت سفارشی را مشخص کنید که قبل‌از پیشنهادهای برنامه بااستفاده از Intent.EXTRA_INITIAL_INTENTS فهرست می‌شوند. برای هدف‌های «هم‌رسانی مستقیم» (مثل مکالمه‌ها یا مخاطبین)، میان‌برهای پویا را بااستفاده از ShortcutManagerCompat به‌جای (به ارائه هدف‌های «هم‌رسانی مستقیم» مراجعه کنید) منتشر کنید:

شکل ۴. هدف‌های سفارشی در «برگه هم‌رسانی Android».

Intent.EXTRA_INITIAL_INTENTS را پس‌از فراخوانی Intent.createChooser() به «هدف هم‌رسانی» خود اضافه کنید:

val sendIntent = Intent(ACTION_SEND).apply {
    type = "text/plain"
    putExtra(Intent.EXTRA_TEXT, previewText)
}

val customIntent = Intent().apply {
    component = ComponentName(context.packageName, "${context.packageName}.CustomActivity")
}

val shareIntent = Intent.createChooser(sendIntent, null).apply {
    putExtra(
        Intent.EXTRA_INITIAL_INTENTS,
        arrayOf(customIntent)
    )
}
context.startActivity(shareIntent)

از این ویژگی بااحتیاط استفاده کنید. هر Intent سفارشی که اضافه می‌کنید، تعداد پیشنهادی سیستم را کاهش می‌دهد. به‌طورکلی، از افزودن هدف‌های سفارشی اجتناب کنید. یک نمونه مناسب رایج برای افزودن Intent.EXTRA_INITIAL_INTENTS ارائه کنش‌های اضافی است که کاربران می‌توانند روی محتوای هم‌رسانی‌شده انجام دهند. برای مثال، کاربری تصاویر را هم‌رسانی می‌کند و از Intent.EXTRA_INITIAL_INTENTS استفاده می‌شود تا به او اجازه دهد به‌جای آن پیوند ارسال کند.

کنار گذاشتن هدف‌های خاص براساس عنصر

با ارائه Intent.EXTRA_EXCLUDE_COMPONENTS می‌توانید هدف‌های خاصی را مستثنی کنید. این کار را فقط برای برداشتن هدف‌هایی انجام دهید که بر آن‌ها کنترل دارید. یک مورد استفاده رایج این است که وقتی کاربران از داخل برنامه شما هم‌رسانی می‌کنند، هدف‌های هم‌رسانی برنامه‌تان را پنهان کنید، زیرا احتمالاً قصد آن‌ها هم‌رسانی در خارج از برنامه شما است.

پس‌از فراخوانی Intent.createChooser()،‏ Intent.EXTRA_EXCLUDE_COMPONENTS را به قصدتان اضافه کنید:

fun excludeSpecificTargets(context: Context) {
    val share = Intent.createChooser(Intent(ACTION_SEND), null).apply {
        // Only use for components you have control over
        val excludedComponentNames =
            arrayOf(ComponentName("com.example.android", "ExampleClass"))
        putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames)
    }
    context.startActivity(share)
}

دریافت اطلاعات درباره هم‌رسانی

دانستن اینکه کاربران شما چه زمانی هم‌رسانی می‌کنند و چه هدفی را انتخاب می‌کنند می‌تواند مفید باشد. «برگ هم‌رسانی Android» با ارائه ComponentName از هدف‌هایی که کاربران بااستفاده از IntentSender انتخاب می‌کنند، به شما امکان می‌دهد این اطلاعات را دریافت کنید.

ابتدا PendingIntent را برای BroadcastReceiver ایجاد کنید و IntentSender آن را در Intent.createChooser() ارائه دهید:

fun infoAboutSharing(context: Context, requestCode: Int) {
    var share = Intent(ACTION_SEND)
    // ...
    val pi = PendingIntent.getBroadcast(
        context, requestCode,
        Intent(context, ShareBroadcastReceiver::class.java),
        PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
    )
    share = Intent.createChooser(share, null, pi.intentSender)
    context.startActivity(share)
}

پاسخ تماس را در MyBroadcastReceiver دریافت کنید و در Intent.EXTRA_CHOOSER_RESULT ببینید:

override fun onReceive(context: Context?, intent: Intent) {
    val TAG = ShareBroadcastReceiver::class.simpleName
    val chooserResult: ChooserResult? = IntentCompat.getParcelableExtra(
        intent,
        Intent.EXTRA_CHOOSER_RESULT,
        ChooserResult::class.java,
    )
    chooserResult?.let {
        Log.i(TAG,
            "Share callback: isShortcut: ${it.isShortcut}, type: ${typeToString(it.type)}, componentName: ${it.selectedComponent}",
        )
    } ?: Log.i(TAG, "chooserResult is null")
}

برای اطلاعات بیشتر، به نمونه سهم پلاتفرم مراجعه کنید.

استفاده از حل‌کننده هدف Android

شکل ۵. حل‌کننده هدف ACTION_SEND.

بهترین زمان استفاده از حل‌کننده هدف Android وقتی است که داده‌ها به‌عنوان بخشی از جریان کاری خوش‌تعریف به برنامه دیگری ارسال می‌شود.

برای استفاده از حل‌کننده هدف Android، هدفی ایجاد کنید و موارد اضافی را همان‌طور که برای فراخوانی «برگه هم‌رسانی Android» انجام می‌دهید اضافه کنید. اما با Intent.createChooser() تماس نگیرید.

اگر چند برنامه نصب‌شده با فیلترهایی وجود داشته باشد که با ACTION_SEND و نوع MIME مطابقت داشته باشد، سیستم یک چارگوش ابهام‌زدایی به‌نام حل‌کننده هدف نمایش می‌دهد که به کاربر امکان می‌دهد هدف موردنظر را برای هم‌رسانی انتخاب کند. اگر یک برنامه واحد مطابقت داشته باشد، اجرا می‌شود.

در اینجا نمونه‌ای از نحوه استفاده از حل‌کننده هدف Android برای ارسال نوشتار آورده شده است:

fun intentResolver(context: Context) {
    val sendIntent: Intent = Intent().apply {
        action = ACTION_SEND
        putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
        type = "text/plain"
    }
    context.startActivity(sendIntent)
}

بیشتر بدانید

برای اطلاعات بیشتر درباره ارسال داده‌ها، به هدف‌ها و فیلترهای هدف مراجعه کنید.