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

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، انتظار دارند String[] برای موارد اضافی مانند EXTRA_EMAIL و EXTRA_CC باشد. از putExtra(String, String[]) برای افزودن این موارد به قصدتان استفاده کنید.

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

داده‌های دودویی را بااستفاده از کنش ACTION_SEND هم‌رسانی کنید. نوع MIME مناسب را تنظیم کنید و URI را در داده‌های اضافی 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 خودتان ذخیره کنید و مطمئن شوید که برنامه‌های دیگر اجازه صحیح برای دسترسی به ارائه‌دهنده شما را دارند. سازوکار ترجیحی برای ارائه دسترسی، استفاده از اجازه‌های هر URI است که موقت هستند و فقط به برنامه دریافت‌کننده دسترسی می‌دهند. برای ایجاد 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 به‌صورت پویا در زمان اجرا به‌جای کدگذاری سخت آن، از روش‌های زیر استفاده کنید:

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

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

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

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

برای هم‌رسانی چند محتوا، از کنش ACTION_SEND_MULTIPLE همراه با فهرستی از URIهایی که به محتوا اشاره می‌کنند استفاده کنید. نوع 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)
}

بیشتر بدانید

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