API đề xuất Wi-Fi để kết nối Internet

Các thiết bị chạy Android 10 (API cấp 29) trở lên cho phép ứng dụng của bạn thêm thông tin đăng nhập mạng cho một thiết bị để tự động kết nối với một điểm truy cập Wi-Fi. Bạn có thể cung cấp đề xuất về mạng cần kết nối bằng cách sử dụng WifiNetworkSuggestion. Nền tảng này sẽ chọn điểm truy cập nào để chấp nhận dựa trên thông tin đầu vào từ ứng dụng của bạn và các ứng dụng khác.

Trên Android 11 (API cấp 30) trở lên:

  • Khung này thực thi các yêu cầu về quyền sở hữu đối với các đề xuất dành cho doanh nghiệp dựa trên EAP-SIM (EAP-SIM, EAP-AKA, EAP-AKA-PRIME); chỉ những ứng dụng do nhà mạng ký mới được phép sử dụng các đề xuất như vậy.
  • Đối với các đề xuất do một ứng dụng có chữ ký của nhà mạng cung cấp, khung này sẽ tự động chỉ định cho các đề xuất đó một mã nhận dạng nhà mạng tương ứng với chữ ký của nhà mạng của ứng dụng. Những đề xuất như vậy sẽ tự động tắt nếu SIM tương ứng bị xoá khỏi thiết bị.

Trên Android 12 (API cấp 31) trở lên:

  • Bạn có thể bật thêm chế độ cài đặt quyền riêng tư thông qua chế độ tạo địa chỉ MAC ngẫu nhiên không liên tục. Chế độ này sẽ định kỳ tạo lại địa chỉ MAC ngẫu nhiên. Sử dụng setMacRandomizationSetting để chỉ định mức độ ngẫu nhiên cho mạng của bạn.

  • isPasspointTermsAndConditionsSupported(): Điều khoản và điều kiện là một tính năng của Passpoint. Tính năng này cho phép các hoạt động triển khai mạng thay thế các trang xác thực không an toàn (sử dụng mạng mở) bằng một mạng Passpoint an toàn. Thông báo sẽ xuất hiện cho người dùng khi họ phải chấp nhận các điều khoản và điều kiện. Những ứng dụng đề xuất các mạng Passpoint bị giới hạn bởi các điều khoản và điều kiện phải gọi API này trước để đảm bảo rằng thiết bị hỗ trợ chức năng này. Nếu không hỗ trợ tính năng này, thiết bị sẽ không thể kết nối với mạng này và bạn phải đề xuất một mạng thay thế hoặc mạng cũ.

  • isDecoratedIdentitySupported(): Khi xác thực với các mạng có tiền tố trang trí, tiền tố nhận dạng được trang trí cho phép nhà khai thác mạng cập nhật Mã nhận dạng truy cập mạng (NAI) để thực hiện định tuyến rõ ràng thông qua nhiều proxy bên trong mạng AAA (xem RFC 7542 để biết thêm về vấn đề này).

    Android 12 triển khai tính năng này để tuân thủ quy cách WBA cho các tiện ích PPS-MO. Những ứng dụng đề xuất các mạng Passpoint yêu cầu một danh tính được trang trí trước tiên phải gọi API này để đảm bảo rằng thiết bị hỗ trợ khả năng này. Nếu thiết bị không hỗ trợ tính năng này, danh tính sẽ không được trang trí và quá trình xác thực với mạng có thể không thành công.

Để tạo một đề xuất Passpoint, các ứng dụng phải sử dụng các lớp PasspointConfiguration, CredentialHomeSp. Các lớp này mô tả hồ sơ Passpoint, được xác định trong quy cách Passpoint của Liên minh Wi-Fi.

Mẫu mã sau đây cho thấy cách cung cấp thông tin đăng nhập cho một mạng mở, một mạng WPA2, một mạng WPA3 và một mạng Passpoint:

Kotlin

val suggestion1 = WifiNetworkSuggestion.Builder()
        .setSsid("test111111")
        .setIsAppInteractionRequired(true) // Optional (Needs location permission)
        .build();

val suggestion2 = WifiNetworkSuggestion.Builder()
        .setSsid("test222222")
        .setWpa2Passphrase("test123456")
        .setIsAppInteractionRequired(true) // Optional (Needs location permission)
        .build();

val suggestion3 = WifiNetworkSuggestion.Builder()
        .setSsid("test333333")
        .setWpa3Passphrase("test6789")
        .setIsAppInteractionRequired(true) // Optional (Needs location permission)
        .build();

val passpointConfig = PasspointConfiguration(); // configure passpointConfig to include a valid Passpoint configuration
val suggestion4 = WifiNetworkSuggestion.Builder()
        .setPasspointConfig(passpointConfig)
        .setIsAppInteractionRequired(true) // Optional (Needs location permission)
        .build();

val suggestionsList = listOf(suggestion1, suggestion2, suggestion3, suggestion4);

val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager;

val status = wifiManager.addNetworkSuggestions(suggestionsList);
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
    // do error handling here
}

// Optional (Wait for post connection broadcast to one of your suggestions)
val intentFilter = IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);

val broadcastReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (!intent.action.equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
            return;
        }
        // do post connect processing here
    }
};
context.registerReceiver(broadcastReceiver, intentFilter);

Java

final WifiNetworkSuggestion suggestion1 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test111111")
  .setIsAppInteractionRequired(true) // Optional (Needs location permission)
  .build();

final WifiNetworkSuggestion suggestion2 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test222222")
  .setWpa2Passphrase("test123456")
  .setIsAppInteractionRequired(true) // Optional (Needs location permission)
  .build();

final WifiNetworkSuggestion suggestion3 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test333333")
  .setWpa3Passphrase("test6789")
  .setIsAppInteractionRequired(true) // Optional (Needs location permission)
  .build();

final PasspointConfiguration passpointConfig = new PasspointConfiguration();
// configure passpointConfig to include a valid Passpoint configuration

final WifiNetworkSuggestion suggestion4 =
  new WifiNetworkSuggestion.Builder()
  .setPasspointConfig(passpointConfig)
  .setIsAppInteractionRequired(true) // Optional (Needs location permission)
  .build();

final List<WifiNetworkSuggestion> suggestionsList =
  new ArrayList<WifiNetworkSuggestion> {{
    add(suggestion1);
    add(suggestion2);
    add(suggestion3);
    add(suggestion4);
  }};

final WifiManager wifiManager =
  (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

final int status = wifiManager.addNetworkSuggestions(suggestionsList);
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
// do error handling here…
}

// Optional (Wait for post connection broadcast to one of your suggestions)
final IntentFilter intentFilter =
  new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);

final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    if (!intent.getAction().equals(
      WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
      return;
    }
    // do post connect processing here...
  }
};
context.registerReceiver(broadcastReceiver, intentFilter);

Ngay sau khi ứng dụng đưa ra đề xuất lần đầu tiên, người dùng sẽ nhận được thông báo. Loại thông báo phụ thuộc vào phiên bản Android đang chạy trên thiết bị:

  • Trên Android 11 (API cấp 30) trở lên, người dùng sẽ thấy một hộp thoại nếu ứng dụng đang chạy ở nền trước và một thông báo nếu ứng dụng đang chạy ở nền sau.
  • Trên Android 10 (API cấp 29), người dùng sẽ thấy một thông báo, bất kể ứng dụng đang chạy ở nền trước hay nền sau.

Khi nền tảng kết nối với một trong các đề xuất mạng, phần cài đặt sẽ hiển thị văn bản ghi nhận kết nối mạng cho ứng dụng đề xuất tương ứng.

Xử lý trường hợp người dùng ngắt kết nối

Nếu người dùng sử dụng bộ chọn Wi-Fi để ngắt kết nối rõ ràng với một trong các đề xuất mạng khi kết nối với mạng đó, thì mạng đó sẽ bị bỏ qua khi vẫn nằm trong phạm vi. Trong thời gian này, mạng đó sẽ không được xem xét để kết nối tự động, ngay cả khi ứng dụng xoá và thêm lại đề xuất mạng tương ứng với mạng đó. Nếu người dùng sử dụng bộ chọn Wi-Fi để kết nối rõ ràng với một mạng đã bị ngắt kết nối trước đó, thì mạng đó sẽ được xem xét để kết nối tự động ngay lập tức.

Thay đổi trạng thái phê duyệt cho ứng dụng

Nếu người dùng từ chối thông báo đề xuất mạng, thì quyền CHANGE_WIFI_STATE sẽ bị xoá khỏi ứng dụng. Sau này, người dùng có thể cấp quyền phê duyệt này bằng cách chuyển đến trình đơn điều khiển Wi-Fi (Cài đặt > Ứng dụng và thông báo > Quyền truy cập đặc biệt của ứng dụng > Quyền điều khiển Wi-Fi > App name).