Làm việc với các phiên hoạt động

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

Đối với các hoạt động thể dục liên tục, trong đó 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 vào cửa hàng thể dục sau khi hoạt động thể dục kết thúc hoặc khi bạn nhập dữ liệu và phiên 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 thành 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 hoạt động 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 bằng cách sử dụng phương thức SessionsClient.stopSession khi người dùng kết thúc hoạt động thể dục.

  4. Hủy đăng ký nhận dữ liệu về hoạt động thể dục mà bạn không còn muốn sử dụng phương thức RecordingClient.unsubscribe.

Bắt đầu phiên

Để bắt đầu 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 hoạt động

Để dừng một phiên hoạt động 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 gian ứng dụng của bạn gọi phương thức SessionsClient.startSession.

  • Thời gian kết thúc: Thời gian ứng dụng 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 vào cửa hàng thể dục

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

  1. Tạo một đối tượng Session chỉ định một 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. Nếu muốn, bạn có thể thêm tập dữ liệu và tổng hợp các điểm dữ liệu.

  4. Chèn phiên sử dụng bằng phương thức SessionsClient.insertSession.

Chèn phiên

Để chèn dữ liệu về hoạt động thể dục chứa siêu dữ liệu về phiên hoạt động vào nhật ký thể dục của người dùng, trước tiên, hãy tạo một phiên bản 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ý tập 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ó) đượ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 khúc hoạt động

Dữ liệu phân đoạn hoạt động trong Google Fit cho biết hoạt động thể dục nào mà người dùng đang thực hiện 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ợ tạm dừng trong các bài tập thể dục.

Ví dụ: nếu bạn tạo một phiên chạy trong 30 phút bằng phương thức Session.Builder.setActivity() nhưng người dùng tạm dừng giữa 10 phút, thì ứng dụng sẽ hiển thị không chính xác rằng người dùng đã chạy trong 30 phút. Miễn là ứng dụng của bạn có thể phát hiện người dùng đang đi bộ hay đang chạy, thì dữ liệu phân đoạn hoạt động cho phép ứng dụng của bạn 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 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 điểm trong số này đại diện cho một khoảng thời gian liên tục mà người dùng thực hiện một loại hoạt động duy nhất.

Ví dụ về chạy và đi bộ trước đó 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 về hoạt động thể dục bằng cách sử dụng các phiên hoạt động

API Phiên cho phép bạn lấy danh sách các phiên từ cửa hàng 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 chứa 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 được tạo bởi ứng dụng của bạn hay bởi bất kỳ ứng dụng nào.

Để 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 một bản sao 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 đó, hãy 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ủ bằng các phiên hoạt động

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, các phản hồi đọc chỉ chứa các phiên hoạt động, không chứa các phiên giấc ngủ.

Để đưa các phiên giấc ngủ vào, 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 thị các phiên trong những ứng dụng khác

Để hiển thị cho người dùng 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 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. Trong trường hợp ứng dụng tạo phiên hoạt động chưa được cài đặt trên thiết bị, bạn có thể cho phép mọi ứng dụng có thể hiển thị hoạt động thể dục để phản hồi ý định.

Để tạo ý định hiển thị dữ liệu về phiên trên một ứng dụng khác, hãy sử 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ý ứng dụng của bạn nhằm nhận ý định từ các ứng dụng chăm sóc sức khỏe 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 nhận được từ Google Fit chỉ có một hoạt động, nhưng bạn có thể lọc ra 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 hỗ trợ.

Ý định tập thể dục bao gồm những thành phần 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());
    }
}