Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

Project Kotlin suspend APIs as Task<T> instead of raw IContinuation

Đang mở
#1,456 2 bình luận 1 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức phù hợp với người mới
45/100
Loại issue
Tính năng
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Ít trao đổi
Công nghệ
android, csharp, kotlin
Lĩnh vực
mobile

Hướng nghiên cứu

Tái hiện sự cố với Xamarin.AndroidX.Health.Connect.ConnectClient 1.1.0.2 bằng cách sử dụng GetGrantedPermissions và ReadRecords, sau đó kiểm tra cách các Kotlin suspend APIs này được tạo trong binding. Kiểm tra hỗ trợ hiện có của generator hoặc interop cho các phép chiếu Task và việc hủy. Được xem là hoàn tất khi các APIs cung cấp các phương thức dựa trên Task có thể sử dụng, hoặc một mẫu helper chính thức được cung cấp và xác minh cho các lời gọi này.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Android framework version

net10.0-android

Affected platform version

.NET 10 / Xamarin.AndroidX.Health.Connect.ConnectClient 1.1.0.2

Description

The AndroidX Health Connect binding exposes Kotlin suspend APIs as methods that require passing a raw Kotlin.Coroutines.IContinuation.

Example from the binding:

client.PermissionController.GetGrantedPermissions(IContinuation continuation)
client.ReadRecords(ReadRecordsRequest request, IContinuation continuation)

This is technically callable, but difficult to use correctly from .NET. A .NET consumer has to hand-write a coroutine bridge using TaskCompletionSource, detect IntrinsicsKt.COROUTINE_SUSPENDED, implement IContinuation, unwrap Kotlin Result.Failure, map Java exceptions into CLR exceptions, and optionally bridge cancellation.

For .NET consumers, these APIs should ideally be projected as Task / Task methods.

Current required workaround:

static Task<T> Await<T>(Func<IContinuation, object> action, CancellationToken cancelToken)
{
    var continuation = new Continuation<T>(cancelToken);
    var result = action(continuation);
    if (result != IntrinsicsKt.COROUTINE_SUSPENDED) { continuation.SetResult(result); }
    return continuation.Task;
}

sealed class Continuation<T> : Java.Lang.Object, IContinuation
{
    readonly TaskCompletionSource<T> tcs = new(TaskCreationOptions.RunContinuationsAsynchronously);
    readonly CancellationTokenRegistration ctr;

    public Continuation(CancellationToken cancelToken) =>
        ctr = cancelToken.Register(() => tcs.TrySetCanceled(cancelToken));

    public Task<T> Task => tcs.Task;
    public ICoroutineContext Context => EmptyCoroutineContext.Instance;

    public void ResumeWith(Java.Lang.Object result) => SetResult(result);

    public void SetResult(object result)
    {
        if (result is Java.Lang.Object { Class.Name: "kotlin.Result$Failure" } failure)
        {
            var field = failure.Class.GetDeclaredField("exception");
            field.Accessible = true;
            tcs.TrySetException(new Exception(field.Get(failure).ToString()));
        }
        else { tcs.TrySetResult((T)result); }

        ctr.Dispose();
    }
}

Expected behavior:
Kotlin suspend APIs should have generated .NET-friendly overloads such as:

Task<ICollection<string>> GetGrantedPermissionsAsync(CancellationToken cancellationToken = default);
Task<ReadRecordsResponse> ReadRecordsAsync(ReadRecordsRequest request, CancellationToken cancellationToken = default);

Actual behavior:
Only the raw continuation-based API is exposed.

Relevant official documentation:
Google’s Health Connect APIs are documented as Kotlin suspend functions. For example:
https://developer.android.com/reference/kotlin/androidx/health/connect/client/HealthConnectClient#readRecords(androidx.health.connect.client.request.ReadRecordsRequest)

Steps to Reproduce:

  1. Create a .NET Android project targeting net10.0-android36.0.
  2. Add Xamarin.AndroidX.Health.Connect.ConnectClient version 1.1.0.2.
  3. Try to call Health Connect suspend APIs such as GetGrantedPermissions or ReadRecords.
  4. Observe that the API requires IContinuation instead of returning Task.

Workaround:
Manually implement an IContinuation bridge with TaskCompletionSource, detect COROUTINE_SUSPENDED, unwrap kotlin.Result$Failure, and map the Java throwable to a CLR Exception.

Request:
Please consider projecting Kotlin suspend APIs in bound AndroidX packages as Task / Task methods, or provide an official helper/interop pattern for consuming suspend APIs from .NET.

Relevant log output

Ngôn ngữ chính
C#
Star
319
Fork
73
Merge trung bình
2 ngày 22 giờ
Pull request đã merge (30 ngày)
6

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của dotnet/android-libraries

Tất cả issue của dotnet/android-libraries

Issue tương tự

Thêm issue về C#

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.