Xử lý các phiên hoạt động

Phiên hoạt động thể hiện khoảng thời gian người dùng thực hiện một hoạt động thể dục. Phiên API cho phép ứng dụng của bạn tạo các phiên trong cửa hàng thể dục.

Đối với các hoạt động thể dục đang diễn ra mà người dùng thông báo cho ứng dụng của bạn khi họ bắt đầu và kết thúc một hoạt động thể dục, bạn có thể tạo các phiên theo thời gian thực.

Bạn cũng có thể chèn một phiên hoạt động vào kho lưu trữ hoạt động thể dục sau khi một hoạt động thể dục kết thúc hoặc khi bạn nhập dữ liệu và phiên hoạt động từ bên ngoài Google Fit.

Tạo phiên theo thời gian thực

Để tạo phiên cho các hoạt động thể dục đang diễn ra, hãy hoàn tất các bước sau:

  1. Đăng ký dữ liệu về hoạt động thể dục bằng phương thức RecordingClient.subscribe.

  2. Bắt đầu một phiên bằng phương thức SessionsClient.startSession khi người dùng bắt đầu hoạt động thể dục.

  3. Dừng phiên hoạt động bằng phương thức SessionsClient.stopSession khi người dùng kết thúc hoạt động thể dục.

  4. Huỷ đăng ký nhận dữ liệu về hoạt động thể dục mà bạn không còn quan tâm bằng phương thức RecordingClient.unsubscribe.

Bắt đầu phiên

Để bắt đầu một phiên trong ứng dụng, hãy sử dụng phương thức SessionsClient.startSession:

Kotlin

// 1. Subscribe to fitness data
// 2. Create a session object
// (provide a name, identifier, description, activity and start time)
val session = Session.Builder()
    .setName(sessionName)
    .setIdentifier("UniqueIdentifierHere")
    .setDescription("Morning run")
    .setActivity(FitnessActivities.RUNNING)
    .setStartTime(startTime, TimeUnit.MILLISECONDS)
    .build()

// 3. Use the Sessions client to start a session:
Fitness.getSessionsClient(this, googleSigninAccount)
    .startSession(session)
    .addOnSuccessListener {
        Log.i(TAG, "Session started successfully!")
    }
    .addOnFailureListener { e ->
        Log.w(TAG, "There was an error starting the session", e)
    }

Java

// 1. Subscribe to fitness data
// 2. Create a session object
// (provide a name, identifier, description, activity and start time)
Session session = new Session.Builder()
        .setName(sessionName)
        .setIdentifier("UniqueIdentifierHere")
        .setDescription("Morning run")
        .setActivity(FitnessActivities.RUNNING)
        .setStartTime(startTime, TimeUnit.MILLISECONDS)
        .build();

// 3. Use the Sessions client to start a session:
Fitness.getSessionsClient(this, googleSigninAccount)
        .startSession(session)
        .addOnSuccessListener(unused ->
                Log.i(TAG, "Session started successfully!"))
        .addOnFailureListener(e ->
                Log.w(TAG, "There was an error starting the session", e));

Dừng một phiên

Để dừng một phiên trong ứng dụng, hãy sử dụng phương thức SessionsClient.stopSession:

Kotlin

// Invoke the SessionsClient with the session identifier
Fitness.getSessionsClient(this, googleSigninAccount)
    .stopSession(session.getIdentifier())
    .addOnSuccessListener {
        Log.i(TAG, "Session stopped successfully!")

        // Now unsubscribe from the fitness data (see
        // Recording Fitness data)
    }
    .addOnFailureListener { e ->
        Log.w(TAG, "There was an error stopping the session", e)
    }

Java

// Invoke the SessionsClient with the session identifier
Fitness.getSessionsClient(this, googleSigninAccount)
        .stopSession(session.getIdentifier())
        .addOnSuccessListener (unused -> {
            Log.i(TAG, "Session stopped successfully!");
            // Now unsubscribe from the fitness data (see
            // Recording Fitness data)
        })
        .addOnFailureListener(e ->
                Log.w(TAG, "There was an error stopping the session", e));

Phiên kết quả có các thông số sau:

  • Thời gian bắt đầu: Thời điểm ứng dụng của bạn gọi phương thức SessionsClient.startSession.

  • Thời gian kết thúc: Thời điểm ứng dụng của bạn gọi phương thức SessionsClient.stopSession.

  • Tên: Tên trong đối tượng Session mà bạn truyền đến SessionsClient.startSession.

Chèn phiên hoạt động vào cửa hàng thể dục

Để chèn phiên có dữ liệu bạn đã thu thập trước đó, hãy làm như sau:

  1. Tạo đối tượng Session chỉ định khoảng thời gian và các thông tin bắt buộc khác.

  2. Tạo SessionInsertRequest với phiên đó.

  3. Thêm tập dữ liệu và điểm dữ liệu tổng hợp (không bắt buộc).

  4. Chèn phiên này bằng phương thức SessionsClient.insertSession.

Chèn một phiên

Để chèn dữ liệu về hoạt động thể dục có chứa siêu dữ liệu phiên vào nhật ký tập thể dục của người dùng, trước tiên, hãy tạo một thực thể SessionInsertRequest:

Kotlin

// Create a session with metadata about the activity.
val session = Session.Builder()
    .setName(SAMPLE_SESSION_NAME)
    .setIdentifier("UniqueIdentifierHere")
    .setDescription("Long run around Shoreline Park")

    .setActivity(FitnessActivities.RUNNING)
    .setStartTime(startTime, TimeUnit.MILLISECONDS)
    .setEndTime(endTime, TimeUnit.MILLISECONDS)
    .build()

// Build a session insert request
val insertRequest = SessionInsertRequest.Builder()
    .setSession(session)
    // Optionally add DataSets for this session.
    .addDataSet(dataset)
    .build()

Java

// Create a session with metadata about the activity.
Session session = new Session.Builder()
        .setName(SAMPLE_SESSION_NAME)
        .setIdentifier("UniqueIdentifierHere")
        .setDescription("Long run around Shoreline Park")

        .setActivity(FitnessActivities.RUNNING)
        .setStartTime(startTime, TimeUnit.MILLISECONDS)
        .setEndTime(endTime, TimeUnit.MILLISECONDS)
        .build();

// Build a session insert request
SessionInsertRequest insertRequest = new SessionInsertRequest.Builder()
        .setSession(session)
        // Optionally add DataSets for this session.
        .addDataSet(dataset)
        .build();

Lớp SessionInsertRequest cung cấp các phương thức thuận tiện để chèn dữ liệu vào nhật ký thể dục và tạo một phiên trong cùng một lệnh gọi đến SessionsClient.insertSession. Các tập dữ liệu (nếu có) sẽ được chèn như thể bạn đã gọi phương thức HistoryClient.insertData trước, sau đó phiên được tạo.

Kotlin

Fitness.getSessionsClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions))
    .insertSession(insertRequest)
    .addOnSuccessListener {
        Log.i(TAG, "Session insert was successful!")
    }
    .addOnFailureListener { e ->
        Log.w(TAG, "There was a problem inserting the session: ", e)
    }

Java

Fitness.getSessionsClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions))
        .insertSession(insertRequest)
        .addOnSuccessListener (unused ->
                Log.i(TAG, "Session insert was successful!"))
        .addOnFailureListener(e ->
        Log.w(TAG, "There was a problem inserting the session: ", e));

Chèn phân đoạn hoạt động

Dữ liệu phân đoạn hoạt động trong Google Fit cho biết người dùng hoạt động thể dục như thế nào trong một khoảng thời gian nhất định. Dữ liệu phân đoạn hoạt động thuộc loại com.google.activity.segment (TYPE_ACTIVITY_SEGMENT) và đặc biệt hữu ích để hỗ trợ các lần tạm dừng trong bài tập thể dục.

Ví dụ: nếu bạn tạo một phiên chạy bộ kéo dài 30 phút bằng phương thức Session.Builder.setActivity() nhưng người dùng lại nghỉ 10 phút ở giữa, thì ứng dụng của bạn sẽ hiển thị không chính xác rằng người dùng đã chạy trong 30 phút. Với điều kiện là ứng dụng của bạn có thể phát hiện xem người dùng đang đi bộ hay chạy, thì dữ liệu phân khúc hoạt động sẽ cho phép ứng dụng cho biết người dùng đã chạy trong 10 phút, đi bộ trong 10 phút, sau đó chạy thêm 10 phút. Các ứng dụng khác cũng có thể báo cáo hoạt động một cách chính xác bằng cách xem dữ liệu phân đoạn hoạt động mà bạn chèn.

Để thêm dữ liệu phân đoạn hoạt động vào một phiên, hãy tạo tập dữ liệu chứa các điểm thuộc loại com.google.activity.segment. Mỗi thời điểm này đại diện cho một khoảng thời gian liên tục, trong đó người dùng thực hiện một loại hoạt động duy nhất.

Ví dụ trước đây về chạy và đi bộ sẽ yêu cầu 3 điểm phân đoạn hoạt động: một điểm để chạy trong 10 phút đầu tiên, một điểm để đi bộ trong 10 phút tiếp theo và một điểm để chạy trong 10 phút cuối cùng.

Kotlin

// Create a DataSet of ActivitySegments to indicate the runner walked for
// 10 minutes in the middle of a run.
val activitySegmentDataSource = DataSource.Builder()
    .setAppPackageName(this.packageName)
    .setDataType(DataType.TYPE_ACTIVITY_SEGMENT)
    .setStreamName(SAMPLE_SESSION_NAME + "-activity segments")
    .setType(DataSource.TYPE_RAW)
    .build()

val firstRunningDp = DataPoint.builder(activitySegmentDataSource)
    .setActivityField(Field.FIELD_ACTIVITY, FitnessActivities.RUNNING)
    .setTimeInterval(startTime, startWalkTime, TimeUnit.MILLISECONDS)
    .build()

val walkingDp = DataPoint.builder(activitySegmentDataSource)
    .setActivityField(Field.FIELD_ACTIVITY, FitnessActivities.WALKING)
    .setTimeInterval(startWalkTime, endWalkTime, TimeUnit.MILLISECONDS)
    .build()

val secondRunningDp = DataPoint.builder(activitySegmentDataSource)
    .setActivityField(Field.FIELD_ACTIVITY, FitnessActivities.RUNNING)
    .setTimeInterval(endWalkTime, endTime, TimeUnit.MILLISECONDS)
    .build()

val activitySegments = DataSet.builder(activitySegmentDataSource)
    .addAll(listOf(firstRunningDp, walkingDp, secondRunningDp))
    .build()

// Create a session with metadata about the activity.
val session = Session.Builder()
    .setName(SAMPLE_SESSION_NAME)
    .setDescription("Long run around Shoreline Park")
    .setIdentifier("UniqueIdentifierHere")
    .setActivity(FitnessActivities.RUNNING)
    .setStartTime(startTime, TimeUnit.MILLISECONDS)
    .setEndTime(endTime, TimeUnit.MILLISECONDS)
    .build()

// Build a session insert request
val insertRequest = SessionInsertRequest.Builder()
    .setSession(session)
    .addDataSet(activitySegments)
    .build()

Java

// Create a DataSet of ActivitySegments to indicate the runner walked for
// 10 minutes in the middle of a run.
DataSource activitySegmentDataSource = new DataSource.Builder()
        .setAppPackageName(getPackageName())
        .setDataType(DataType.TYPE_ACTIVITY_SEGMENT)
        .setStreamName(SAMPLE_SESSION_NAME + "-activity segments")
        .setType(DataSource.TYPE_RAW)
        .build();

DataPoint firstRunningDp = DataPoint.builder(activitySegmentDataSource)
        .setActivityField(Field.FIELD_ACTIVITY, FitnessActivities.RUNNING)
        .setTimeInterval(startTime, startWalkTime, TimeUnit.MILLISECONDS)
        .build();

DataPoint walkingDp = DataPoint.builder(activitySegmentDataSource)
        .setActivityField(Field.FIELD_ACTIVITY, FitnessActivities.WALKING)
        .setTimeInterval(startWalkTime, endWalkTime, TimeUnit.MILLISECONDS)
        .build();

DataPoint secondRunningDp = DataPoint.builder(activitySegmentDataSource)
        .setActivityField(Field.FIELD_ACTIVITY, FitnessActivities.RUNNING)
        .setTimeInterval(endWalkTime, endTime, TimeUnit.MILLISECONDS)
        .build();

DataSet activitySegments = DataSet.builder(activitySegmentDataSource)
        .addAll(Arrays.asList(firstRunningDp, walkingDp, secondRunningDp))
        .build();

// Create a session with metadata about the activity.
Session session = new Session.Builder()
        .setName(SAMPLE_SESSION_NAME)
        .setDescription("Long run around Shoreline Park")
        .setIdentifier("UniqueIdentifierHere")
        .setActivity(FitnessActivities.RUNNING)
        .setStartTime(startTime, TimeUnit.MILLISECONDS)
        .setEndTime(endTime, TimeUnit.MILLISECONDS)
        .build();

// Build a session insert request
SessionInsertRequest insertRequest = new SessionInsertRequest.Builder()
        .setSession(session)
        .addDataSet(activitySegments)
        .build();

Đọc dữ liệu thể dục bằng phiên

Phiên API cho phép bạn lấy danh sách các phiên từ kho dữ liệu thể dục phù hợp với một số tiêu chí. Ví dụ: bạn có thể lấy tất cả các phiên nằm trong một khoảng thời gian hoặc nhận một phiên cụ thể theo tên hoặc mã nhận dạng. Bạn cũng có thể chỉ định xem bạn quan tâm đến các phiên do ứng dụng của bạn tạo hay do ứng dụng bất kỳ tạo ra.

Để có được danh sách các phiên phù hợp với một số tiêu chí, trước tiên, hãy tạo thực thể SessionReadRequest:

Kotlin

// Use a start time of 1 week ago and an end time of now.
val endTime = LocalDateTime.now().atZone(ZoneId.systemDefault())
val startTime = endTime.minusWeeks(1)

// Build a session read request
val readRequest = SessionReadRequest.Builder()
    .setTimeInterval(startTime.toEpochSecond(), endTime.toEpochSecond(), TimeUnit.SECONDS)
    .read(DataType.TYPE_SPEED)
    .setSessionName(SAMPLE_SESSION_NAME)
    .build()

Java

// Use a start time of 1 week ago and an end time of now.
ZonedDateTime endTime = LocalDateTime.now().atZone(ZoneId.systemDefault())
ZonedDateTime startTime = endTime.minusWeeks(1)

// Build a session read request
SessionReadRequest readRequest = new SessionReadRequest.Builder()
        .setTimeInterval(startTime.toEpochSecond(), endTime.toEpochSecond(), TimeUnit.SECONDS)
        .read(DataType.TYPE_SPEED)
        .setSessionName(SAMPLE_SESSION_NAME)
        .build();

Sau đó, sử dụng phương thức SessionsClient.readSession:

Kotlin

Fitness.getSessionsClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions))
    .readSession(readRequest)
    .addOnSuccessListener { response ->
        // Get a list of the sessions that match the criteria to check the result.
        val sessions = response.sessions
        Log.i(TAG, "Number of returned sessions is: ${sessions.size}")
        for (session in sessions) {
            // Process the session
            dumpSession(session)

            // Process the data sets for this session
            val dataSets = response.getDataSet(session)
            for (dataSet in dataSets) {
                // ...
            }
        }
    }
    .addOnFailureListener { e ->
        Log.w(TAG,"Failed to read session", e)
    }

Java

Fitness.getSessionsClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions))
        .readSession(readRequest)
        .addOnSuccessListener(response -> {
            // Get a list of the sessions that match the criteria to check the
            // result.
            List<Session> sessions = response.getSessions();
            Log.i(TAG, "Number of returned sessions is: ${sessions.size}");
            for (Session session : sessions) {
                // Process the session
                dumpSession(session);

                // Process the data sets for this session
                List<DataSet> dataSets = response.getDataSet(session);
                for (DataSet dataSet : dataSets) {
                    // ...
                }
            }
        })
        .addOnFailureListener(e ->
                Log.w(TAG,"Failed to read session", e));

Đọc dữ liệu giấc ngủ theo phiên

Phiên giấc ngủ được coi là khác biệt với các phiên hoạt động khác. Theo mặc định, phản hồi đã đọc chỉ chứa các phiên hoạt động, chứ không phải phiên ngủ.

Để đưa vào các phiên giấc ngủ, hãy sử dụng phương thức includeSleepSessions khi bạn tạo SessionReadRequest. Để bao gồm cả hoạt động và phiên, hãy sử dụng cả includeSleepSessionsincludeActivitySessions.

Hiện các phiên sự kiện trong các ứng dụng khác

Để cho người dùng thấy chế độ xem chi tiết hơn về một phiên cụ thể trong một ứng dụng khác, ứng dụng của bạn có thể gọi một ý định chứa thông tin về phiên đó. Bạn có thể chỉ định một ứng dụng cụ thể, chẳng hạn như ứng dụng đã tạo phiên. Hoặc, trong trường hợp ứng dụng đã tạo phiên không được cài đặt trên thiết bị, bạn có thể cho phép bất kỳ ứng dụng nào có thể hiển thị hoạt động thể dục để phản hồi ý định.

Để tạo ý định hiện dữ liệu phiên trên một ứng dụng khác, hãy dùng lớp SessionsApi.ViewIntentBuilder:

Kotlin

// Pass your activity object to the constructor
val intent = SessionsApi.ViewIntentBuilder(this)
    .setPreferredApplication("com.example.someapp") // optional
    .setSession(session)
    .build()

// Invoke the intent
startActivity(intent)

Java

// Pass your activity object to the constructor
Intent intent = new SessionsApi.ViewIntentBuilder(this)
        .setPreferredApplication("com.example.someapp") // optional
        .setSession(session)
        .build();

// Invoke the intent
startActivity(intent);

Nhận ý định từ các ứng dụng khác

Để đăng ký cho ứng dụng của bạn nhận ý định từ các ứng dụng sức khoẻ thể chất và tinh thần khác, hãy khai báo bộ lọc ý định trong tệp kê khai tương tự như sau:

<intent-filter>
    <action android:name="vnd.google.fitness.VIEW"/>
    <data android:mimeType="vnd.google.fitness.session/running"/>
</intent-filter>

Mỗi ý định mà ứng dụng của bạn nhận được từ Google Fit chỉ là một hoạt động, nhưng bạn có thể lọc nhiều loại MIME trong một bộ lọc ý định duy nhất. Bộ lọc ý định của ứng dụng cần bao gồm tất cả hoạt động mà ứng dụng của bạn hỗ trợ.

Ý định về hoạt động thể dục bao gồm các dữ liệu bổ sung sau:

  • vnd.google.gms.fitness.start_time
  • vnd.google.gms.fitness.end_time
  • vnd.google.gms.fitness.session

Bạn có thể lấy dữ liệu từ các dữ liệu bổ sung này như sau:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    ...
    val supportedType = Session.getMimeType(FitnessActivities.RUNNING)

    if (Intent.ACTION_VIEW == intent.action && supportedType == intent.type) {
        // Get the intent extras
        val startTime = Fitness.getStartTime(intent, TimeUnit.MILLISECONDS);
        val endTime = Fitness.getEndTime(intent, TimeUnit.MILLISECONDS)
        val session = Session.extract(intent)
    }
}

Java

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...

    String supportedType = Session.getMimeType(FitnessActivities.RUNNING);

    if (Intent.ACTION_VIEW.equals(getIntent().getAction()) && supportedType.equals(getIntent().getType())) {
        // Get the intent extras
        long startTime = Fitness.getStartTime(getIntent(), TimeUnit.MILLISECONDS);
        long endTime = Fitness.getEndTime(getIntent(), TimeUnit.MILLISECONDS);
        Session session = Session.extract(getIntent());
    }
}