مخابرات

کتابخانه جدید Android Telecom Jetpack تشخیص وضعیت تماس شما را به پلتفرم آسان می‌کند. می‌توانید کد منبع و یک برنامه نمونه را در GitHub پیدا کنید.

وابستگی ها و مجوزها

ابتدا فایل build.gradle ماژول برنامه خود را باز کنید و یک وابستگی برای ماژول androidx Telecom اضافه کنید:

dependencies {
    implementation ("androidx.core:core-telecom:1.0.0-alpha02")
}

در مانیفست برنامه خود، اعلام کنید که برنامه شما از مجوز MANAGE_OWN_CALLS استفاده می‌کند:

<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />

اپلیکیشن را ثبت کنید

برای اینکه اندروید از برنامه خود مطلع شود، باید آن و قابلیت های آن را ثبت کنید. این به Android می‌گوید که برنامه شما از چه ویژگی‌هایی مانند تماس ویدیویی، پخش جریانی تماس و برقراری تماس پشتیبانی می‌کند. این اطلاعات مهم است تا Android بتواند خود را برای کار با ویژگی‌های برنامه شما پیکربندی کند.

 private val callsManager = CallsManager(context)

var capabilities: @CallsManager.Companion.Capability Int =
    CallsManager.CAPABILITY_BASELINE or
          CallsManager.CAPABILITY_SUPPORTS_CALL_STREAMING or
          CallsManager.CAPABILITY_SUPPORTS_VIDEO_CALLING

callsManager.registerAppWithTelecom(capabilities)

ادغام پلتفرم

دو سناریوی تماس رایج برای هر برنامه تماسی، تماس های ورودی و خروجی هستند. برای ثبت صحیح جهت تماس و اطلاع رسانی مناسب به کاربر با اعلان ها، از API های زیر استفاده کنید.

ثبت تماس

این مثال نحوه ثبت تماس ورودی را نشان می دهد:

companion object {
  const val APP_SCHEME = "MyCustomScheme"
  const val ALL_CALL_CAPABILITIES = (CallAttributes.SUPPORTS_SET_INACTIVE
    or CallAttributes.SUPPORTS_STREAM or CallAttributes.SUPPORTS_TRANSFER)

  const val INCOMING_NAME = "Luke"
  val INCOMING_URI: Uri = Uri.fromParts(APP_SCHEME, "", "")
  // Define all possible properties for CallAttributes
  val INCOMING_CALL_ATTRIBUTES =
    CallAttributes(
      INCOMING_NAME,
      INCOMING_URI,
      DIRECTION_INCOMING,
      CALL_TYPE_VIDEO_CALL,
      ALL_CALL_CAPABILITIES)
}

شی callAttributes می تواند ویژگی های زیر را داشته باشد:

  • displayName : نام تماس‌گیرنده، جلسه یا جلسه.
  • address : آدرس تماس. توجه داشته باشید، این را می توان به یک پیوند جلسه گسترش داد.
  • direction : جهت تماس، مانند ورودی یا خروجی .
  • callType : اطلاعات مربوط به داده های در حال انتقال، مانند تصویر و صدا.
  • callCapabilities : شیئی که قابلیت های تماس را مشخص می کند.

شی callCapabilities می تواند ویژگی های زیر را داشته باشد:

  • streaming : نشان می دهد که آیا تماس از پخش صدا به دستگاه دیگری که دارای Android است پشتیبانی می کند یا خیر.
  • transfer : نشان می دهد که آیا تماس قابل انتقال است یا خیر.
  • hold : نشان می دهد که آیا می توان تماس را در حالت انتظار قرار داد یا خیر.

تماس اضافه کنید

متد addCall() در صورتی که دستگاه از مخابرات پشتیبانی نکند یا در هنگام تنظیم تماس خطایی رخ داده باشد یک استثنا برمی گرداند.

try {
    callsManager.addCall(
        INCOMING_CALL_ATTRIBUTES,
        onIsCallAnswered, // Watch needs to know if it can answer the call
        onIsCallDisconnected,
        onIsCallActive,
        onIsCallInactive
    ) {
        callControlScope = this
    }
}

یک تماس را پاسخ دهید

پس از برقراری تماس ورودی، باید تماس را پاسخ دهید یا رد کنید. این مثال نحوه پاسخ به تماس را نشان می دهد:

when (answer(CallAttributesCompat.CALL_TYPE_AUDIO_CALL)) {
    is CallControlResult.Success -> {

    }

    is CallControlResult.Error -> {

    }
}

اگر تماس دیگری در حال انجام باشد، answer() CallControlResult.Error را برمی‌گرداند که دلیل عدم پاسخگویی به تماس را نشان می‌دهد. در این حالت، کاربر باید تماس دیگر را در حالت انتظار قرار دهد.

رد تماس

برای رد تماس، تماس را با DisconnectCause.Rejected قطع کنید.

fun onRejectCall(){
    coroutineScope.launch {
        callControlScope?.let {
            it.disconnect(DisconnectCause(DisconnectCause.REJECTED))
        }
    }
}

تماس خروجی

هنگام برقراری تماس خروجی، هنگامی که طرف راه دور پاسخ داد، باید تماس را روی فعال تنظیم کنید تا پلتفرم از اینکه تماس در حال انجام است مطلع شود:

when (setActive()) {
    is CallControlResult.Success -> {
        onIsCallActive()
    }

    is CallControlResult.Error -> {
        updateCurrentCall {
            copy(errorCode = result.errorCode)
        }
    }
}

تماس را در حالت انتظار قرار دهید

اگر برنامه تماس شما از برقراری تماس پشتیبانی می‌کند، از setInActive استفاده کنید تا به پلتفرم بگویید که تماس شما فعال نیست و میکروفون و دوربین برای سایر برنامه‌ها رایگان هستند:

when (setInActive()) {
    is CallControlResult.Success -> {

    }

    is CallControlResult.Error -> {
        updateCurrentCall {
            copy(errorCode = result.errorCode)
        }
    }
}

قطع کن

برای قطع تماس، به پشته Telecom اطلاع دهید تا با ارائه یک دلیل معتبر، اتصال را قطع کند:

coroutineScope.launch {
    callControlScope?.disconnect(DisconnectCause(DisconnectCause.LOCAL))
}

صوتی مسیر

در طول تماس، کاربران گاهی اوقات بین دستگاه‌هایی مانند بلندگو، گوشی یا دستگاه بلوتوث جابجا می‌شوند. برای دریافت لیستی از تمام دستگاه های موجود در دسترس کاربر و اینکه کدام دستگاه فعال است، از availableEndpoints و currentCallEndpoint APIها استفاده کنید.

این مثال هر دو جریان را برای ایجاد یک شی UI ترکیب می کند تا لیستی از دستگاه ها را به کاربر نشان دهد و اینکه کدام یک فعال است:

availableEndpoint = combine(callControlScope.availableEndpoints,
    callControlScope.currentCallEndpoint) {
    availableDevices: List<CallEndpoint>, activeDevice : CallEndpoint ->
    availableDevices.map {
        EndPointUI(
            isActive = activeDevice.endpointName == it.endpointName, it
        )
    }
}

برای تغییر یک دستگاه فعال، از requestEndpointChange با CallEndpoint که می خواهید به آن تغییر دهید استفاده کنید.

coroutineScope.launch {
     callControlScope?.requestEndpointChange(callEndpoint)
}

پشتیبانی پیش زمینه

کتابخانه Telecom با پشتیبانی پیش زمینه ارائه می شود. این کتابخانه از ConnectionService برای دستگاه‌های دارای Android نسخه 13 و پایین‌تر استفاده می‌کند. برای اندروید 14 و بالاتر از میکروفون و دوربین پیش زمینه برای پشتیبانی صحیح از خدمات پیش زمینه استفاده می کند. درباره خدمات پیش زمینه بیشتر بیاموزید .

به عنوان بخشی از الزامات پیش زمینه، برنامه باید یک اعلان ارسال کند تا کاربران بدانند که برنامه در پیش زمینه در حال اجرا است.

برای اطمینان از اینکه برنامه شما اولویت اجرای پیش زمینه را دارد، پس از ثبت تماس با پلتفرم، یک اعلان ایجاد کنید. وقتی برنامه شما تماس را قطع می کند یا اعلان شما دیگر معتبر نیست، اولویت پیش زمینه حذف می شود.

is TelecomCall.Registered -> {
    val notification = createNotification(call)
    notificationManager.notify(TELECOM_NOTIFICATION_ID, notification)
}

پشتیبانی سطحی

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

در صورتی که برنامه شما پاسخ ندهد، هر تابع لامبدا پس از 5 ثانیه با تراکنش ناموفق تمام می شود.

callsManager.addCall(
        attributes,
        onIsCallAnswered, // Watch/Auto need to know if they can answer the call
        onIsCallDisconnected,
        onIsCallActive,
        onIsCallInactive
    ) {
//Call Scope
}
/**
  *  Can the call be successfully answered??
  *  TIP: Check the connection/call state to see if you can answer a call
  *  Example you may need to wait for another call to hold.
  **/
val onIsCallAnswered: suspend(type: Int) -> Unit = {}

/**
  * Can the call perform a disconnect
  */
val onIsCallDisconnected: suspend (cause: DisconnectCause) -> Unit = {}

/**
  *  Check is see if you can make the call active.
  *  Other calls and state might stop us from activating the call
  */
val onIsCallActive: suspend () -> Unit = {
    updateCurrentCall {
    }
}

/**
  * Check to see if you can make the call inactivate
  */
val onIsCallInactive: suspend () -> Unit = {}