العمل مع الجلسات

تمثّل الجلسات فاصلاً زمنيًا يجري خلاله المستخدمون نشاطًا للياقة البدنية. تتيح واجهة برمجة تطبيقات الجلسات لتطبيقك إنشاء جلسات في متجر اللياقة البدنية.

بالنسبة إلى أنشطة اللياقة البدنية المستمرة التي يرسل فيها المستخدم إشعارًا إلى تطبيقك عند بدء نشاط اللياقة البدنية وإكماله، يمكنك إنشاء جلسات في الوقت الفعلي.

يمكنك أيضًا إدراج جلسة في متجر اللياقة البدنية بعد الانتهاء من نشاط اللياقة البدنية أو عند استيراد البيانات والجلسات من خارج Google Fit.

إنشاء جلسات في الوقت الفعلي

لإنشاء جلسات لأنشطة اللياقة البدنية المستمرة، أكمِل الخطوات التالية:

  1. الاشتراك في بيانات اللياقة البدنية باستخدام طريقة RecordingClient.subscribe

  2. بدء جلسة باستخدام طريقة SessionsClient.startSession عندما يبدأ المستخدم نشاط اللياقة البدنية.

  3. إيقاف الجلسة باستخدام طريقة SessionsClient.stopSession عند إنهاء المستخدم لنشاط اللياقة البدنية.

  4. إلغاء الاشتراك في بيانات اللياقة البدنية التي لم تعد تريد استخدام طريقة RecordingClient.unsubscribe فيها.

بدء جلسة

لبدء جلسة في تطبيقك، استخدِم الطريقة 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));

إيقاف جلسة

لإيقاف جلسة في تطبيقك، استخدِم الطريقة 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));

تتضمن الجلسة الناتجة المعلمات التالية:

  • وقت البدء: الوقت الذي اتّبع فيه تطبيقك طريقة SessionsClient.startSession.

  • وقت الانتهاء: الوقت الذي يُطلق فيه تطبيقك على طريقة SessionsClient.stopSession

  • الاسم: الاسم الذي يتم تمريره إلى العنصر Session. SessionsClient.startSession

إدراج الجلسات في متجر اللياقة البدنية

لإدراج الجلسات التي تحتوي على بيانات جمعتها سابقًا، نفِّذ ما يلي:

  1. أنشئ كائن Session يحدد الفاصل الزمني والمعلومات الأخرى المطلوبة.

  2. أنشِئ SessionInsertRequest مع الجلسة.

  3. ويمكنك اختياريًا إضافة مجموعات البيانات ونقاط البيانات المجمّعة.

  4. أدرِج الجلسة باستخدام طريقة SessionsClient.insertSession.

إدراج جلسة

لإدراج بيانات اللياقة البدنية التي تتضمن بيانات وصفية للجلسة في سجلّ لياقة المستخدم، أنشئ أولاً مثيل 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();

يقدّم الصف SessionInsertRequest طرقًا مريحة لإدراج البيانات في سجلّ اللياقة البدنية وإنشاء جلسة في المكالمة نفسها إلى SessionsClient.insertSession. ويتم إدراج مجموعات البيانات، إن توفّرت، كما لو كنت تستخدم طريقة HistoryClient.insertData أولاً، ثم يتم إنشاء الجلسة.

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));

إدراج شرائح النشاط

تشير بيانات شريحة النشاط في Google Fit إلى نشاط اللياقة البدنية الذي ينفذه المستخدمون خلال فترة زمنية معيّنة. وتكون بيانات شرائح النشاط من النوع com.google.activity.segment (TYPE_ACTIVITY_SEGMENT) وتكون مفيدة بشكلٍ خاص لدعم عمليات الإيقاف المؤقت أثناء التمارين.

على سبيل المثال، إذا أنشأت جلسة ركض لمدة 30 دقيقة باستخدام الطريقة Session.Builder.setActivity() ولكن حصل المستخدم على استراحة لمدة 10 دقائق في الوقت نفسه، سيبيّن تطبيقك بشكل غير صحيح أنّ المستخدم قد بقي لمدة 30 دقيقة. بشرط أن يتمكّن تطبيقك من رصد ما إذا كان المستخدم يمارس المشي أو جريًا، فإنّ بيانات شريحة النشاط تسمح لتطبيقك بالإشارة إلى أنّ المستخدم قد شغّل لمدة 10 دقائق، ومشى لمدة 10 دقائق، ثم تم تشغيله لمدة 10 دقائق إضافية. يمكن للتطبيقات الأخرى أيضًا الإبلاغ عن النشاط بشكل صحيح من خلال الاطّلاع على بيانات شريحة النشاط التي تدرجها.

لإضافة بيانات شريحة النشاط إلى جلسة، أنشئ مجموعة بيانات تحتوي على نقاط من النوع com.google.activity.segment. تمثّل كل نقطة من هذه النقاط فاصلاً زمنيًا مستمرًا أجرى خلاله المستخدم نوعًا واحدًا من الأنشطة.

يتطلّب مثال الركض والمشي السابق ثلاثة نقاط أنشطة: نقطة للركض خلال أول 10 دقائق، وأخرى للمشي خلال الدقائق العشر التالية، وأخرى للركض خلال الدقائق العشر الأخيرة.

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();

قراءة بيانات اللياقة البدنية باستخدام الجلسات

تتيح لك واجهة برمجة تطبيقات الجلسات الحصول على قائمة بالجلسات من متجر اللياقة البدنية التي تتطابق مع بعض المعايير. على سبيل المثال، يمكنك الحصول على جميع الجلسات المضمّنة في فترة زمنية، أو الحصول على جلسة معيّنة بالاسم أو رقم التعريف. يمكنك أيضًا تحديد ما إذا كنت مهتمًا بالجلسات التي أنشأها تطبيقك أو أي تطبيق آخر.

للحصول على قائمة بالجلسات التي تطابق بعض المعايير، أنشئ أولاً مثيل 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();

بعد ذلك، استخدِم الطريقة 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));

قراءة بيانات النوم باستخدام الجلسات

يتم التعامل مع جلسات النوم بأنها مختلفة عن جلسات النشاط الأخرى. وفقًا للإعدادات التلقائية، تتضمّن الردود المقروءة جلسات أنشطة فقط، وليست جلسات نوم.

لتضمين جلسات النوم، استخدِم طريقة includeSleepSessions عند إنشاء SessionReadRequest. لتضمين الأنشطة والجلسات، استخدِم كلاً من includeSleepSessions وincludeActivitySessions.

عرض الجلسات في التطبيقات الأخرى

ليوفّر للمستخدمين عرضًا أكثر تفصيلاً لجلسة معيّنة في تطبيق مختلف، يمكن لتطبيقك استدعاء هدف يتضمن معلومات الجلسة. يمكنك تحديد تطبيق معين، مثل التطبيق الذي أنشأ الجلسة. أو إذا لم يكن التطبيق الذي أنشأ الجلسة مثبتًا على الجهاز، يمكنك السماح لأي تطبيق يمكنه عرض نشاط اللياقة البدنية بالاستجابة للقصد.

لإنشاء هدف لعرض بيانات الجلسة على تطبيق مختلف، استخدِم فئة 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);

تلقّي نوايا من التطبيقات الأخرى

لتسجيل تطبيقك لتلقّي أغراض من تطبيقات أخرى متعلقة بالصحة والعافية، يمكنك الإعلان عن فلتر الأهداف في البيان الذي يشبه ما يلي:

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

يُقصد بكل غرض يتلقاه تطبيقك من Google Fit نشاطًا واحدًا فقط، ولكن يمكنك الفلترة بحثًا عن أنواع MIME متعددة في فلتر واحد للأهداف. يحتاج فلتر intent لتطبيقك إلى تضمين جميع الأنشطة التي يدعمها تطبيقك.

تتضمن أغراض اللياقة البدنية العناصر الإضافية التالية:

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

يمكنك الحصول على البيانات من هذه الإضافات على النحو التالي:

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());
    }
}