SDK mạng Thread cho Android

Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.

SDK của chuỗi luồng cung cấp chức năng tương tự như chuỗi khoá kỹ thuật số, cho phép các ứng dụng Android chia sẻ thông tin đăng nhập mạng Luồng với các dịch vụ của Google Play. Việc này cho phép các ứng dụng của bạn thiết lập mọi thiết bị Luồng từ mọi hệ sinh thái nhà thông minh mà không cần để lộ thông tin đăng nhập và dữ liệu người dùng trực tiếp.

Chỉ với một vài lệnh gọi API, bạn có thể:

  1. Yêu cầu thông tin xác thực mạng Chuỗi ưu tiên từ Dịch vụ Google Play.
  2. Thiết lập bộ định tuyến biên mới và thêm thông tin xác thực mạng Chuỗi của bạn vào Dịch vụ Google Play.
  3. Nếu đã có bộ định tuyến biên tại chỗ, bạn có thể kiểm tra xem bộ định tuyến biên có đang nằm trong mạng ưu tiên hay không và di chuyển các bộ định tuyến đó (nếu cần).

Có một số hành trình của người dùng và nhà phát triển mà bạn có thể cân nhắc. Chúng tôi sẽ nói về hầu hết các tính năng này trong hướng dẫn này, cùng với các tính năng chính khác và cách sử dụng đề xuất.

Các thuật ngữ chính và khái niệm về API

Trước khi bắt đầu, bạn cần hiểu các thuật ngữ sau:

  • Thông tin đăng nhập mạng chuỗi: blob nhị phân của TLV luồng giúp mã hoá Tên mạng chuỗi, Khoá mạng và các thuộc tính khác mà thiết bị Chuỗi cần đến để tham gia một Mạng luồng nhất định.

  • Thông tin đăng nhập mạng chuỗi ưu tiên: Thông tin đăng nhập mạng chuỗi được chọn tự động có thể được chia sẻ với các ứng dụng của nhiều nhà cung cấp bằng API getPreferredCredentials.

  • Border Agent ID: Mã nhận dạng duy nhất toàn cầu 16 byte cho thiết bị Bộ định tuyến đường viền luồng. Mã này do các nhà cung cấp bộ định tuyến biên giới tạo và quản lý.

  • Ứng dụng thiết lập bộ định tuyến đường viền luồng: Đây là ứng dụng Android giúp thiết lập các thiết bị Bộ định tuyến đường viền mới và thêm thông tin xác thực mạng Luồng vào dịch vụ Google Play. Ứng dụng của bạn là chủ sở hữu có thẩm quyền của thông tin xác thực đã thêm và có quyền truy cập miễn phí vào thông tin xác thực.

Nhiều API mạng chuỗi (thread Network) trả về một Nhiệm vụ (Nhiệm vụ) hoàn tất không đồng bộ. Bạn có thể sử dụng addOnSuccessListeneraddOnFailureListener để đăng ký các lệnh gọi lại để nhận kết quả. Để tìm hiểu thêm, hãy tham khảo tài liệu về Nhiệm vụ.

Quyền sở hữu và duy trì thông tin đăng nhập

Ứng dụng thêm thông tin đăng nhập mạng Thread sẽ trở thành chủ sở hữu của thông tin xác thực và có toàn quyền truy cập vào thông tin đăng nhập. Nếu cố gắng truy cập vào thông tin đăng nhập do các ứng dụng khác thêm, bạn sẽ gặp lỗi PERMISSION_DENIED.

Là chủ sở hữu ứng dụng, bạn nên luôn cập nhật thông tin xác thực trong Dịch vụ Google Play khi mạng Bộ định tuyến đường viền luồng được cập nhật. Điều này có nghĩa là bạn sẽ phải thêm thông tin đăng nhập khi cần, cập nhật thông tin xác thực khi bộ định tuyến biên và bộ định tuyến của luồng thay đổi và xoá thông tin xác thực khi Bộ định tuyến đường viền bị xoá hoặc đặt lại về trạng thái ban đầu.

Khám phá tác nhân biên giới

Thông tin đăng nhập phải được lưu bằng mã nhân viên hỗ trợ biên giới. Bạn cần đảm bảo rằng ứng dụng Thiết lập bộ định tuyến đường viền của bạn có thể xác định Mã tác nhân đường viền của bộ định tuyến Đường viền chuỗi.

Bộ định tuyến đường viền Thread phải sử dụng mDNS để quảng cáo thông tin mạng Thread, bao gồm cả Network Network (Mã mạng), Extended Pan ID (Mã vùng mở rộng) và Border Agent ID (Mã đại lý đường viền). Giá trị txt tương ứng cho các thuộc tính này tương ứng là nn, xpid.

Đối với các mạng có bộ định tuyến biên Google, Dịch vụ Google Play sẽ tự động nhận được thông tin đăng nhập mạng Google Thread để sử dụng.

Tích hợp SDK vào ứng dụng Android

Để bắt đầu, hãy hoàn thành các bước sau:

  1. Làm theo hướng dẫn trong bài viết Thiết lập Dịch vụ Google Play.

  2. Thêm phần phụ thuộc dịch vụ Google Play vào tệp build.gradle:

    implementation 'com.google.android.gms:play-services-threadnetwork:16.0.0-beta02'
    
  3. Không bắt buộc: Xác định một lớp dữ liệu BorderAgent để lưu trữ thông tin bộ định tuyến biên. Chúng tôi sẽ sử dụng dữ liệu trong suốt hướng dẫn này:

    data class BorderAgentInfo(
      // Network Name max 16 len
      val networkName: String = "",
      val extPanId: ByteArray = ByteArray(16),
      val borderAgentId: ByteArray = ByteArray(16),
      ...
    )
    

Tiếp theo, chúng tôi sẽ xem các bước đề xuất để thêm và quản lý thông tin xác thực ưu tiên.

Thiết lập bộ định tuyến biên mới

Trước khi tạo mạng mới cho bộ định tuyến biên mới, bạn cần sử dụng thông tin xác thực mạng ưu tiên trước. Điều này đảm bảo rằng các thiết bị Thread được kết nối với một mạng Thread duy nhất khi có thể.

Lệnh gọi đến getPreferredCredentials sẽ chạy một Hoạt động, nhắc người dùng cho phép yêu cầu mạng. Nếu thông tin xác thực mạng được lưu trữ trong chuỗi khoá kỹ thuật số SDK luồng, thì thông tin xác thực sẽ được trả về ứng dụng.

Yêu cầu thông tin đăng nhập

Để nhắc người dùng về thông tin đăng nhập ưu tiên:

  1. Khai báo ActivityLauncher:

    private lateinit var preferredCredentialsLauncher: ActivityResultLauncher<IntentSenderRequest>
    
  2. Xử lý kết quả Hoạt động, được trả về dưới dạng ThreadNetworkCredentials:

    preferredCredentialsLauncher =
     registerForActivityResult(
       StartIntentSenderForResult()
     ) { result: ActivityResult ->
       if (result.resultCode == RESULT_OK) {
         val threadNetworkCredentials = ThreadNetworkCredentials.fromIntentSenderResultData(result.data!!)
         Log.d("debug", threadNetworkCredentials.networkName)
       } else {
         Log.d("debug", "User denied request.")
       }
     }
    
  3. Gọi preferredCredentials và chạy Hoạt động:

    private fun getPreferredThreadNetworkCredentials() {
      ThreadNetwork.getClient(this)
        .preferredCredentials
      .addOnSuccessListener { intentSenderResult ->
        intentSenderResult.intentSender?.let {
          preferredCredentialsLauncher.launch(IntentSenderRequest.Builder(it).build())
          } ?: Log.d("debug", "No preferred credentials found.")
        }
      .addOnFailureListener { e: Exception -> Log.d(TAG, "ERROR: [${e}]") }
    }
    

Tạo Mạng chuỗi mới

Nếu không có thông tin đăng nhập mạng chuỗi ưu tiên nào trong mạng chuỗi của người dùng, thì bạn có thể sử dụng API addCredentials để thêm thông tin đăng nhập vào dịch vụ Google Play. Để thực hiện việc này, bạn cần tạo ThreadBorderAgent và cũng cần cung cấp một đối tượng ThreadNetworkCredentials.

Để tạo mạng ngẫu nhiên, hãy gọi newRandomizeBuilder:

val threadCredentials = ThreadNetworkCredentials.newRandomizedBuilder().build()

Cách chỉ định Tên mạng chuỗi:

val threadCredentials = ThreadNetworkCredentials.newRandomizedBuilder()
  .setNetworkName("ThreadNetworkSDK")
  .build()

Thêm thông tin đăng nhập

Để cung cấp thông tin đăng nhập mạng Thread cho các nhà cung cấp Thread khác, chúng tôi cần thêm thông tin đó vào Dịch vụ Google Play. Trước khi có thể thêm thông tin xác thực mới, chúng ta cũng cần biết thiết bị bộ định tuyến biên này thuộc mạng nào của luồng này.

Trong ví dụ này, chúng ta sẽ tạo ThreadBorderAgent từ Mã tác nhân biên giới và chuyển thông tin xác thực mới của mạng Luồng mà bạn vừa tạo:

private fun addCredentials(borderAgentInfo: BorderAgentInfo, credentialsToBeAdded: ThreadNetworkCredentials) {

  val threadBorderAgent = ThreadBorderAgent.newBuilder(borderAgentInfo.borderAgentId).build()
  Log.d("debug", "border router id:" + threadBorderAgent.id)

  ThreadNetwork.getClient(this)
    .addCredentials(threadBorderAgent, credentialsToBeAdded)
      .addOnSuccessListener {
        Log.d("debug", "Credentials added.")
      }
      .addOnFailureListener { e: Exception -> Log.d(TAG, "ERROR: [${e}]") }
}

Phát hiện và di chuyển bộ định tuyến biên trong thực tế

Nếu đang có bộ định tuyến biên tại chỗ, bạn có thể sử dụng isPreferredCredentials để xác định xem các bộ định tuyến biên có thuộc mạng ưa thích hay không. API này không nhắc người dùng cấp quyền và kiểm tra thông tin xác thực của bộ định tuyến biên giới so với thông tin được lưu trữ trong Dịch vụ Google Play.

isPreferredCredentails trả về 0 nếu không khớp và 1 để được so khớp dưới dạng kiểu dữ liệu Int. Bạn có thể sử dụng IsPreferredCredentialsResult để kiểm tra kết quả của mình.

public @interface IsPreferredCredentialsResult {
    int PREFERRED_CREDENTIALS_NOT_FOUND = -1;
    int PREFERRED_CREDENTIALS_NOT_MATCHED = 0;
    int PREFERRED_CREDENTIALS_MATCHED = 1;
}

Để sử dụng isPreferredCredentials, trước tiên, bạn cần tạo một đối tượng ThreadNetworkCredentials. Có một số cách để tạo bản sao ThreadNetworkCredentials. Trong các bước tiếp theo, chúng tôi sẽ xem xét các tuỳ chọn này.

Thông tin xác thực mạng của chuỗi theo Tập dữ liệu hoạt động

Có trường hợp Bộ định tuyến luồng của bạn đã được thiết lập với một Luồng và bạn muốn thêm Mạng luồng này vào Dịch vụ Google Play để chia sẻ với các nhà cung cấp khác. Bạn có thể tạo một phiên bản ThreadNetworkCredential từ danh sách TLV tập dữ liệu hoạt động theo luồng thô:

  1. Chuyển đổi Tập dữ liệu hoạt động thành ByteArray. Ví dụ:

    val activeDataset =
          "0e080000000000010000000300000f35060004001fffe0020833333333...".dsToByteArray()
    
    fun String.dsToByteArray(): ByteArray {
      return chunked(2).map { it.toInt(16).toByte() }.toByteArray()
    }
    
  2. Sử dụng fromActiveOperationalDataset để tạo ThreadNetworkCredentials. Khi thành công, bạn sẽ có thể lấy Tên mạng, Kênh và thông tin khác về mạng. Để xem danh sách đầy đủ các thuộc tính, hãy tham khảo ThreadNetworkCredentials.

    val threadNetworkCredentials =
        ThreadNetworkCredentials.fromActiveOperationalDataset(activeDataset)
    Log.d(
        "threadNetworkCredentials",
        threadNetworkCredentials.channel.toString() + " - " + threadNetworkCredentials.networkName)
    
  3. Gọi API isPreferredCredentials và chuyển ThreadNetworkCredentials.

    ThreadNetwork.getClient(this)
    .isPreferredCredentials(threadNetworkCredentials)
    .addOnSuccessListener { result ->
      when (result) {
        IsPreferredCredentialsResult.PREFERRED_CREDENTIALS_NOT_MATCHED ->
            Log.d("isPreferredCredentials", "Credentials not matched.")
        IsPreferredCredentialsResult.PREFERRED_CREDENTIALS_MATCHED ->
            Log.d("isPreferredCredentials", "Credentials matched.")
      }
    }
    .addOnFailureListener { e: Exception -> Log.d("isPreferredCredentials", "ERROR: [${e}]") }
    

Thông tin đăng nhập mạng chuỗi của Tác nhân biên giới

Mã nhân viên biên giới xác định duy nhất một thiết bị bộ định tuyến biên. Để sử dụng API getCredentialsByBorderAgent, trước tiên, bạn cần tạo một đối tượng ThreadBorderAgent và truyền mã nhận dạng tác nhân biên giới.

Sau khi bạn tạo đối tượng ThreadBorderAgent, hãy gọi getCredentialsByBorderAgent. Nếu thông tin đăng nhập đã được lưu, hãy kiểm tra xem thông tin đăng nhập đó có được ưu tiên hay không.

private fun isPreferredThreadNetworkByBorderAgent(borderAgentInfo: BorderAgentInfo) {

  val threadBorderAgent = ThreadBorderAgent.newBuilder(borderAgentInfo.borderAgentId).build()
  Log.d("debug", "border router id:" + threadBorderAgent.id)

  var isPreferred = IsPreferredCredentialsResult.PREFERRED_CREDENTIALS_NOT_FOUND
  var borderAgentCredentials: ThreadNetworkCredentials?
  val taskByBorderAgent = ThreadNetwork.getClient(this)
  taskByBorderAgent
      .getCredentialsByBorderAgent(threadBorderAgent)
      .addOnSuccessListener { result: ThreadNetworkCredentialsResult ->
        borderAgentCredentials = result.credentials
        result.credentials?.let {
          taskByBorderAgent.isPreferredCredentials(it).addOnSuccessListener { result ->
            isPreferred = result
          }
        }
      }
      .addOnFailureListener { e: Exception -> Log.d(TAG, "ERROR: [${e}]") }
}

Thông tin xác thực mạng của chuỗi theo Mã Pan mở rộng

Tương tự như getPreferredCredentials, bạn cũng có thể nhắc người dùng xác thực thông tin xác thực từ Mã mở rộng của bộ định tuyến biên. getCredentialsByExtendedPanId trả về một IntentSender và kết quả Activity (Hoạt động) chứa một đối tượng ThreadNetworkCredentials khi người dùng chấp thuận.

private fun getCredentialsByExtPanId(borderAgentInfo: BorderAgentInfo) {
  ThreadNetwork.getClient(this)
    .getCredentialsByExtendedPanId(borderAgentInfo.extPanId)
    .addOnSuccessListener { intentSenderResult ->
      intentSenderResult.intentSender?.let {
        preferredCredentialsLauncher.launch(IntentSenderRequest.Builder(it).build())
      }
        ?: Log.d("debug", "No credentials found.")
    }
    .addOnFailureListener { e: Exception -> Log.d(TAG, "ERROR: [${e}]") }
}

Xóa thông tin đăng nhập

Khi thiết bị Bộ định tuyến biên bị xoá khỏi nhà hoặc trạng thái đặt lại về trạng thái ban đầu, bạn cần xóa Mạng chuỗi đó khỏi Dịch vụ Google Play.

private fun removeCredentials(borderAgentInfo: BorderAgentInfo) {

  val threadBorderAgent = ThreadBorderAgent.newBuilder(borderAgentInfo.borderAgentId).build()
  Log.d("debug", "border router id:" + threadBorderAgent.id)

  ThreadNetwork.getClient(this)
      .removeCredentials(threadBorderAgent)
      .addOnSuccessListener { Log.d("debug", "Credentials removed.") }
      .addOnFailureListener { e: Exception -> Log.d(TAG, "ERROR: [${e}]") }
}

Nguồn tham khảo

Để tìm hiểu thêm về SDK Mạng luồng, hãy tham khảo Tài liệu tham khảo API.