Mobil uygulamadaki adım verilerini bu bölümde açıklandığı şekilde doldurmak için Sensör Yöneticisi'ni kullanın rehberini inceleyin. Bir egzersiz uygulamasının kullanıcı arayüzünü tasarlayıp yönetmeyle ilgili daha fazla bilgi için referans Temel bir fitness uygulaması geliştirin.
Başlarken
Temel adım sayacınızın adımlarını ölçmeye başlamak için
kullanıyorsanız, bağımlılıkları uygulama modülünüze eklemeniz
build.gradle
dosyası yükleyin. Bağımlılıkların en yeni sürümlerini kullandığınızdan emin olun.
Ayrıca, uygulamanızın desteğini Wear OS gibi diğer form faktörlerini de kapsayacak şekilde genişlettiğinizde
ve bu form faktörlerinin gerektirdiği
bağımlılıkları toplayın.
Aşağıda, kullanıcı arayüzü bağımlılıklarından bazılarına dair birkaç örnek verilmiştir. Tam liste için bu Kullanıcı Arayüzü Öğeleri kılavuzuna bakın.
implementation(platform("androidx.compose:compose-bom:2023.10.01"))
implementation("androidx.activity:activity-compose")
implementation("androidx.compose.foundation:foundation")
implementation("androidx.compose.material:material")
Adım sayacı sensörünü edinme
Kullanıcı gerekli etkinlik tanıma iznini verdikten sonra, adım sayacı sensörüne erişebilirsiniz:
getSystemService()
öğesindenSensorManager
nesnesini alın.SensorManager
cihazından adım sayacı sensörünü alın:
private val sensorManager by lazy {
getSystemService(Context.SENSOR_SERVICE) as SensorManager }
private val sensor: Sensor? by lazy {
sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER) }
Bazı cihazlarda adım sayacı sensörü yoktur. Sensörü kontrol etmelisiniz ve cihazda yoksa bir hata mesajı gösterilir:
if (sensor == null) {
Text(text = "Step counter sensor is not present on this device")
}
Ön plan hizmetinizi oluşturma
Temel fitness uygulamalarında bir düğme izleme adımları için kullanıcıdan başlangıç ve bitiş etkinlikleri almak için.
Sensör en iyi uygulamalarını göz önünde bulundurun. Özellikle, adım sayacı sensörü adımları sayarken sensör sadece kayıtlı olduğundan emin olun. Sensör kaydını bir ön planla ilişkilendirerek sensör gerektiği süre boyunca kayıtlı kalır ve sensör Uygulama ön planda olmadığında kayıtlı kalır.
onPause()
yönteminde sensörün kaydını iptal etmek için aşağıdaki snippet'i kullanın:
ön plan hizmetiniz:
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(this)
}
Etkinlikler için verileri analiz etme
Sensör verilerine erişmek için SensorEventListener
arayüzünü uygulayın. Not
ön plan hizmetinizin
yaşam döngüsü boyunca, hizmet duraklatıldığında veya sonlandırıldığında sensörün kaydı silinir. İlgili içeriği oluşturmak için kullanılan
aşağıdaki snippet, SensorEventListener
arayüzünün nasıl uygulanacağını gösterir
Sensor.TYPE_STEP_COUNTER
için:
private const val TAG = "STEP_COUNT_LISTENER"
context(Context)
class StepCounter {
private val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
private val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
suspend fun steps() = suspendCancellableCoroutine { continuation ->
Log.d(TAG, "Registering sensor listener... ")
val listener: SensorEventListener by lazy {
object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent?) {
if (event == null) return
val stepsSinceLastReboot = event.values[0].toLong()
Log.d(TAG, "Steps since last reboot: $stepsSinceLastReboot")
if (continuation.isActive) {
continuation.resume(stepsSinceLastReboot)
}
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
Log.d(TAG, "Accuracy changed to: $accuracy")
}
}
}
val supportedAndEnabled = sensorManager.registerListener(listener,
sensor, SensorManager.SENSOR_DELAY_UI)
Log.d(TAG, "Sensor listener registered: $supportedAndEnabled")
}
}
Sensör etkinlikleri için veritabanı oluşturma
Uygulamanızda, kullanıcının zaman içindeki adımlarını görüntüleyebileceği bir ekran gösterilebilir. Uygulamanızda bu özelliği sağlamak için Oda kalıcılık kitaplığını kullanın.
Aşağıdaki snippet, adım sayısı grubunu içeren bir tablo oluşturur uygulamanızın her bir ölçüme ne zaman eriştiğiyle birlikte
@Entity(tableName = "steps")
data class StepCount(
@ColumnInfo(name = "steps") val steps: Long,
@ColumnInfo(name = "created_at") val createdAt: String,
)
Veri erişim nesnesi (DAO) oluşturma okuması ve yazması için:
@Dao
interface StepsDao {
@Query("SELECT * FROM steps")
suspend fun getAll(): List<StepCount>
@Query("SELECT * FROM steps WHERE created_at >= date(:startDateTime) " +
"AND created_at < date(:startDateTime, '+1 day')")
suspend fun loadAllStepsFromToday(startDateTime: String): Array<StepCount>
@Insert
suspend fun insertAll(vararg steps: StepCount)
@Delete
suspend fun delete(steps: StepCount)
}
DAO'yu örneklendirmek için RoomDatabase
nesnesi oluşturun:
@Database(entities = [StepCount::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun stepsDao(): StepsDao
}
Sensör verilerini veritabanında depolayın
ViewModel, yeni StepCounter sınıfını kullanır, böylece adımları en kısa sürede depolayabilirsiniz Siz bu e-postaları okurken:
viewModelScope.launch {
val stepsFromLastBoot = stepCounter.steps()
repository.storeSteps(stepsFromLastBoot)
}
repository
sınıfı aşağıdaki gibi görünür:
class Repository(
private val stepsDao: StepsDao,
) {
suspend fun storeSteps(stepsSinceLastReboot: Long) = withContext(Dispatchers.IO) {
val stepCount = StepCount(
steps = stepsSinceLastReboot,
createdAt = Instant.now().toString()
)
Log.d(TAG, "Storing steps: $stepCount")
stepsDao.insertAll(stepCount)
}
suspend fun loadTodaySteps(): Long = withContext(Dispatchers.IO) {
printTheWholeStepsTable() // DEBUG
val todayAtMidnight = (LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT).toString())
val todayDataPoints = stepsDao.loadAllStepsFromToday(startDateTime = todayAtMidnight)
when {
todayDataPoints.isEmpty() -> 0
else -> {
val firstDataPointOfTheDay = todayDataPoints.first()
val latestDataPointSoFar = todayDataPoints.last()
val todaySteps = latestDataPointSoFar.steps - firstDataPointOfTheDay.steps
Log.d(TAG, "Today Steps: $todaySteps")
todaySteps
}
}
}
}
Sensör verilerini düzenli olarak alma
Ön plan hizmeti kullanıyorsanız WorkManager
uygulamasını yapılandırmanız gerekmez
Çünkü uygulamanızın kullanıcının adımlarını aktif olarak izlediği sırada
güncellenmiş toplam adım sayısı uygulamanızda görünecektir.
Bununla birlikte, adım kayıtlarınızı toplu hale getirmek istiyorsanız WorkManager
öğesini kullanarak
Belirli bir aralıktaki adımları (ör. 15 dakikada bir) ölçmelidir.
WorkManager
, arka planı gerçekleştiren bileşendir
sağlamak için çok önemlidir. WorkManager codelab'de daha fazla bilgi edinin.
Verileri alacak şekilde Worker
nesnesini yapılandırmak için doWork()
öğesini geçersiz kılın
yöntemini çağırın:
private const val TAG = " StepCounterWorker"
@HiltWorker
class StepCounterWorker @AssistedInject constructor(
@Assisted appContext: Context,
@Assisted workerParams: WorkerParameters,
val repository: Repository,
val stepCounter: StepCounter
) : CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
Log.d(TAG, "Starting worker...")
val stepsSinceLastReboot = stepCounter.steps().first()
if (stepsSinceLastReboot == 0L) return Result.success()
Log.d(TAG, "Received steps from step sensor: $stepsSinceLastReboot")
repository.storeSteps(stepsSinceLastReboot)
Log.d(TAG, "Stopping worker...")
return Result.success()
}
}
WorkManager
uygulamasını geçerli adım sayısını her 15 dakikada bir kaydedecek şekilde ayarlamak için şunları yapın:
şu:
Configuration.Provider
öğesini uygulamak içinApplication
sınıfını genişletin kullanır.onCreate()
yönteminde birPeriodicWorkRequestBuilder
sıraya koyun.
Bu işlem aşağıdaki kod snippet'inde görünür:
@HiltAndroidApp
@RequiresApi(Build.VERSION_CODES.S)
internal class PulseApplication : Application(), Configuration.Provider {
@Inject
lateinit var workerFactory: HiltWorkerFactory
override fun onCreate() {
super.onCreate()
val myWork = PeriodicWorkRequestBuilder<StepCounterWorker>(
15, TimeUnit.MINUTES).build()
WorkManager.getInstance(this)
.enqueueUniquePeriodicWork("MyUniqueWorkName",
ExistingPeriodicWorkPolicy.UPDATE, myWork)
}
override val workManagerConfiguration: Configuration
get() = Configuration.Builder()
.setWorkerFactory(workerFactory)
.setMinimumLoggingLevel(android.util.Log.DEBUG)
.build()
}
Uygulamanızın adımına erişimi kontrol eden içerik sağlayıcıyı başlatmak için Karşı veritabanını ayarlamak için aşağıdaki öğeyi uygulamanızın manifest dosyasına ekleyin:
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove" />