1. Giriş
Telefonları her yere yanımızda taşıyoruz ancak bugüne kadar uygulamaların, deneyimlerini kullanıcının sürekli değişen ortamına ve etkinliğine göre ayarlaması zordu.
Geçmişte geliştiriciler bunu yapmak için yürüme veya araba kullanma gibi bir etkinliğin ne zaman başladığını ya da sona erdiğini belirlemek amacıyla çeşitli sinyalleri (konum, sensör vb.) birleştirerek değerli mühendislik zamanını harcıyordu. Daha da kötüsü, uygulamalar bağımsız olarak ve sürekli olarak kullanıcı etkinliğindeki değişiklikleri kontrol ettiğinde pil ömrü etkilenir.
Activity Recognition Transition API, tüm işlemleri sizin için yapan ve sizi gerçekten ilgilendiren şeyi (kullanıcı etkinliğinin ne zaman değiştiğini) bildiren basit bir API sağlayarak bu sorunları çözer. Uygulamanız, ilgilendiğiniz etkinliklerdeki bir geçişe abone olur ve API sizi değişikliklerden haberdar eder.
Örneğin, bir mesajlaşma uygulaması, kullanıcının durumunu meşgul olarak ayarlamak için "kullanıcı bir araca ne zaman girip çıktığını bana bildirin" sorusunu sorabilir. Benzer şekilde, park yeri algılama uygulaması, kullanıcının park yerini kaydetmek için "kullanıcı araçtan çıkıp yürümeye başladığında bana haber ver" isteğinde bulunabilir.
Bu kod laboratuvarında, kullanıcının yürüme veya koşma gibi bir etkinliği ne zaman başlattığını/durdurduğunu belirlemek için Etkinlik Tanıma Geçiş API'sini nasıl kullanacağınızı öğreneceksiniz.
Ön koşullar
Android geliştirme ve geri çağırma hakkında bilgi sahibi olmanız gerekir.
Öğrenecekleriniz
- Etkinlik geçişlerine kaydolma
- Bu etkinlikleri işleme
- Artık gerekli olmayan etkinlik geçişlerinin kaydını iptal etme
İhtiyacınız olanlar
- Android Studio Bumblebee
- Android cihaz veya emülatör
2. Başlarken
Başlangıç projesi deposunu klonlama
En kısa sürede başlamanız için üzerinde çalışabileceğiniz bir başlangıç projesi hazırladık. Git yüklüyse aşağıdaki komutu çalıştırmanız yeterlidir. (Terminale / komut satırına git --version
yazarak kontrol edebilir ve doğru şekilde yürütüldüğünü doğrulayabilirsiniz.)
git clone https://github.com/android/codelab-activity_transitionapi
Git'iniz yoksa projeyi zip dosyası olarak alabilirsiniz:
Projeyi içe aktarma
Android Studio'yu başlatın, karşılama ekranından "Mevcut bir Android Studio projesini aç"ı seçin ve proje dizinini açın.
Proje yüklendikten sonra Git'in yerel değişikliklerinizin tümünü izlemediğine dair bir uyarı da görebilirsiniz. "Yoksay"ı veya sağ üstteki "X"i tıklayabilirsiniz. (Hiçbir değişikliği Git deposuna geri göndermezsiniz.)
Android görünümündeyseniz proje penceresinin sol üst köşesinde aşağıdaki resme benzer bir resim görürsünüz. (Proje görünümündeyseniz aynı şeyi görmek için projeyi genişletmeniz gerekir.)
İki klasör simgesi (base
ve complete
) vardır. Bunların her biri "modül" olarak bilinir.
Android Studio'nun projeyi arka planda ilk kez derlemesinin birkaç saniye sürebileceğini lütfen unutmayın. Bu süre zarfında Android Studio'nun alt kısmındaki durum çubuğunda bir döndürme simgesi görürsünüz:
Kod değişiklikleri yapmadan önce bu işlemin tamamlanmasını beklemenizi öneririz. Bu sayede Android Studio gerekli tüm bileşenleri alabilir.
Ayrıca, "Dil değişikliklerinin geçerli olması için sayfayı yeniden yüklemek istiyor musunuz?" veya benzer bir istem alırsanız "Evet"i seçin.
Başlangıç projesini anlama
Artık etkinlik tanıma özelliğini eklemeye hazırsınız. Bu kod laboratuvarının başlangıç noktası olan base
modülünü kullanacağız. Diğer bir deyişle, her adımdan base
koduna kod eklersiniz.
complete
modülü, çalışmanızı kontrol etmek veya herhangi bir sorunla karşılaşırsanız referans olarak kullanmak için kullanılabilir.
Temel bileşenlere genel bakış:
MainActivity
: Etkinlik algılama için gereken tüm kodu içerir.
Emülatör kurulumu
Android emülatörünü ayarlama konusunda yardıma ihtiyacınız varsa Uygulamanızı çalıştırma başlıklı makaleyi inceleyin.
Başlangıç projesini çalıştırma
Uygulamamızı çalıştıralım.
- Android cihazınızı bilgisayarınıza bağlayın veya bir emülatör başlatın.
- Araç çubuğunda, açılır seçiciden
base
yapılandırmasını seçin ve yanındaki yeşil üçgeni (Çalıştır) düğmesini tıklayın:
- Aşağıda başvuruyu göreceksiniz:
- Uygulama artık mesaj yazdırmanın dışında hiçbir şey yapmıyor. Artık hareket algılama özelliğini de ekleyeceğiz.
Özet
Bu adımda şunları öğrendiniz:
- Codelab'in genel kurulumu.
- Uygulamamızın temel özellikleri.
- Uygulamanızı dağıtma
3. Kitaplığı inceleyin ve manifest dosyasına izin ekleyin
Geçiş API'sini uygulamanızda kullanmak için Google Konum ve Etkinlik Tanıma API'sine bağımlılık beyan etmeniz ve uygulama manifestinde com.google.android.gms.permission.ACTIVITY_RECOGNITION iznini belirtmeniz gerekir.
- build.gradle dosyasında TODO: Etkinlik algılama için gereken Play Hizmetleri kitaplığını inceleyin ifadesini arayın. Bu adımda (1. adım) herhangi bir işlem yapmanız gerekmez. Yalnızca ihtiyacımız olan, bildirilen bağımlılığı inceleyin. Aşağıdaki gibi görünmelidir:
// TODO: Review play services library required for activity recognition.
implementation 'com.google.android.gms:play-services-location:19.0.1'
base
modülünde,AndroidManifest.xml
içinde TODO: Her iki etkinlik algılama iznini de manifest dosyasına ekleyin ifadesini arayın ve aşağıdaki kodu<manifest>
öğesine ekleyin.
<!-- TODO: Add both activity recognition permissions to the manifest. -->
<!-- Required for 28 and below. -->
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<!-- Required for 29+. -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
Kodunuz aşağıdaki gibi görünecektir:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<!-- TODO: Add both activity recognition permissions to the manifest. -->
<!-- Required for 28 and below. -->
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<!-- Required for 29+. -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
...
</manifest>
Yorumlardan da görebileceğiniz gibi, Android 10 için ikinci bir izin eklemeniz gerekiyor. Bu, API sürüm 29'a eklenen çalışma zamanı izni için gereklidir.
İşte bu kadar. Uygulamanız artık etkinlik algılamayı destekleyebilir. Bunun için kodu eklememiz yeterlidir.
Uygulamayı çalıştırma
Uygulamanızı Android Studio'dan çalıştırın. Tam olarak aynı görünmelidir. Henüz geçişleri izlemek için herhangi bir kod eklemedik. Bu işlem bir sonraki bölümde yapılacak.
4. Android'de çalışma zamanı izinlerini kontrol etme/isteme
API 28 ve önceki sürümlerde izinler desteklenirken API 29 ve sonraki sürümlerde çalışma zamanı izinlerini desteklememiz gerekiyor:
MainActivity.java
içinde, kullanıcının Android 10 (29) veya sonraki bir sürümü kullanıp kullanmadığını kontrol ederiz. Kullanıcı bu sürümleri kullanıyorsa etkinlik algılama izinlerini kontrol ederiz.- İzinler verilmezse kullanıcıyı, uygulamanın neden izine ihtiyaç duyduğunu açıklayan bir açılış ekranına (
PermissionRationalActivity.java
) yönlendiririz ve izni onaylamasına izin veririz.
Android sürümünü kontrol eden kodu inceleme
base
modülünde, MainActivity.java
içinde TODO: Android 10 (29+) yüklü cihazlar için inceleme kontrolü ifadesini arayın. Bu kod snippet'ini göreceksiniz.
Bu bölüm için herhangi bir işlem yapmanız gerekmez.
// TODO: Review check for devices with Android 10 (29+).
private boolean runningQOrLater =
android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q;
Daha önce de belirtildiği gibi, Android 10 ve sonraki sürümlerde android.permission.ACTIVITY_RECOGNITION
çalışma zamanı izni için onay almanız gerekir. Çalışma zamanında istenen izinleri kontrol etmemiz gerekip gerekmediğine karar vermek için bu basit kontrolü kullanırız.
Gerekirse hareket tanıma için çalışma zamanında izin kontrolünü inceleyin
base
modülünde, MainActivity.java
içinde TODO: Review permission check for 29+ (TODO: 29 ve üzeri için izin kontrolünü inceleyin) ifadesini arayın. Bu kod snippet'ini göreceksiniz.
Bu bölüm için herhangi bir işlem yapmanız gerekmez.
// TODO: Review permission check for 29+.
if (runningQOrLater) {
return PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACTIVITY_RECOGNITION
);
} else {
return true;
}
Çalışma zamanında istenen izinleri kontrol etmemiz gerekip gerekmediğini görmek için önceki adımda oluşturduğumuz değişkeni kullanırız.
Q ve sonraki sürümlerde, çalışma zamanı iznini kontrol edip sonucu döndürürüz. Bu, geliştiricinin izin isteyip istemememiz gerektiğini tek bir aramada öğrenmesini sağlayan activityRecognitionPermissionApproved()
adlı daha büyük bir yöntemin parçasıdır.
Çalışma zamanı izinleri isteme ve etkinlik algılama geçişlerini etkinleştirme/devre dışı bırakma
base
modülünde, MainActivity.java
içinde TODO: Etkinlik izlemeyi etkinleştirin/devre dışı bırakın ve gerekirse izin isteyin ifadesini arayın. Aşağıdaki kodu yorumdan sonra ekleyin.
// TODO: Enable/Disable activity tracking and ask for permissions if needed.
if (activityRecognitionPermissionApproved()) {
if (activityTrackingEnabled) {
disableActivityTransitions();
} else {
enableActivityTransitions();
}
} else {
// Request permission and start activity for result. If the permission is approved, we
// want to make sure we start activity recognition tracking.
Intent startIntent = new Intent(this, PermissionRationalActivity.class);
startActivityForResult(startIntent, 0);
}
Burada, hareket tanıma özelliğinin onaylanıp onaylanmadığını sorarız. Bu durumda ve etkinlik algılama zaten etkinse devre dışı bırakırız. Aksi takdirde etkinleştiririz.
İzin onaylanmadığı durumlarda kullanıcıyı, izine neden ihtiyaç duyduğumuzu açıklayan ve izni etkinleştirmelerine izin veren açılış ekranı etkinliğine yönlendiririz.
İzin isteği kodunu inceleme
base
modülünde, PermissionRationalActivity.java
içinde TODO: Hareket tanıma için izin isteğini incele ifadesini arayın. Bu kod snippet'ini göreceksiniz.
Bu bölüm için herhangi bir işlem yapmanız gerekmez.
// TODO: Review permission request for activity recognition.
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.ACTIVITY_RECOGNITION},
PERMISSION_REQUEST_ACTIVITY_RECOGNITION)
Bu, etkinliğin en önemli ve incelenmesi gereken kısmıdır. Kod, kullanıcı izin istediğinde izin isteğini tetikler.
Bunun dışında PermissionRationalActivity.java
sınıfı, kullanıcının etkinlik algılama iznini neden onaylaması gerektiğine dair bir gerekçe gösterir (en iyi uygulama). Kullanıcı, Hayır Teşekkür Ederiz düğmesini veya Devam düğmesini (yukarıdaki kodu tetikler) tıklayabilir.
Daha fazla bilgi edinmek isterseniz dosyayı inceleyebilirsiniz.
5. Etkinlik geçişleri için alıcıyı kaydetme/alıcı kaydını iptal etme
Etkinlik algılama kodunu ayarlamadan önce, Etkinlik'imizin sistem tarafından oluşturulan geçiş işlemlerini işleyebildiğinden emin olmak istiyoruz.
Geçiş için BroadcastReceiver oluşturma
base
modülünde, MainActivity.java
içinde TODO: Etkinlik geçişlerini dinlemek için bir BroadcastReceiver oluşturun ifadesini arayın. Aşağıdaki snippet'i yapıştırın.
// TODO: Create a BroadcastReceiver to listen for activity transitions.
// The receiver listens for the PendingIntent above that is triggered by the system when an
// activity transition occurs.
mTransitionsReceiver = new TransitionsReceiver();
Geçiş için bir BroadcastReceiver kaydetme
base
modülünde, MainActivity.java
içinde TODO: Etkinlik geçişlerini dinlemek için bir BroadcastReceiver kaydedin ifadesini arayın. (onStart()
içindedir). Aşağıdaki snippet'i yapıştırın.
// TODO: Register a BroadcastReceiver to listen for activity transitions.
registerReceiver(mTransitionsReceiver, new IntentFilter(TRANSITIONS_RECEIVER_ACTION));
Artık PendingIntent aracılığıyla etkinlik geçişleri yükseltildiğinde güncelleme alma yöntemimiz var.
BroadcastReceiver'ın kaydını iptal etme
base
modülünde, MainActivity.java
içinde Kullanıcı uygulamadan çıktığında etkinlik geçiş alıcısının kaydını silme seçeneğini arayın. (onStop()
içindedir).Snippet'i aşağıya yapıştırın.
// TODO: Unregister activity transition receiver when user leaves the app.
unregisterReceiver(mTransitionsReceiver);
Activity
kapatıldığında alıcının kaydını kaldırmak en iyi uygulamadır.
6. Etkinlik geçişlerini ayarlama ve güncelleme isteğinde bulunma
Etkinlik geçişi güncellemeleri almaya başlamak için şunları uygulamanız gerekir:
- Etkinlik ve geçiş türünü belirten bir ActivityTransitionRequest nesnesi.
- Uygulamanızın bildirim aldığı bir PendingIntent geri çağırma işlevi. Daha fazla bilgi için beklemedeki bir intent'i kullanma bölümüne bakın.
İzlenecek ActivityTransitions listesini oluşturma
ActivityTransitionRequest nesnesini oluşturmak için izlemek istediğiniz geçişi temsil eden ActivityTransition nesnelerinin bir listesini oluşturmanız gerekir. ActivityTransition nesnesi aşağıdaki verileri içerir:
- DetectedActivity sınıfıyla temsil edilen bir etkinlik türü. Geçiş API'si aşağıdaki etkinlikleri destekler:
- ActivityTransition sınıfıyla temsil edilen bir geçiş türü. Geçiş türleri şunlardır:
base
modülünde, MainActivity.java
bölümünde TODO: İzlenecek etkinlik geçişleri ekle ifadesini arayın. Aşağıdaki kodu yorumdan sonra ekleyin.
// TODO: Add activity transitions to track.
activityTransitionList.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.WALKING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
activityTransitionList.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.WALKING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
activityTransitionList.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.STILL)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
activityTransitionList.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.STILL)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
Bu kod, izlemek istediğimiz geçişleri daha önce boş olan bir listeye ekler.
PendingIntent oluşturma
Daha önce de belirtildiği gibi, ActivityTransitionRequest'imizdeki değişikliklerden haberdar olmak istiyorsak bir PendingIntent
'e ihtiyacımız var. Bu nedenle, ActivityTransitionRequest'imizi oluşturmadan önce bir PendingIntent
oluşturmamız gerekir.
base
modülünde, MainActivity.java
içinde TODO: Bir etkinlik geçişi gerçekleştiğinde tetiklenecek PendingIntent'i başlat ifadesini arayın. Aşağıdaki kodu yorumdan sonra ekleyin.
// TODO: Initialize PendingIntent that will be triggered when a activity transition occurs.
Intent intent = new Intent(TRANSITIONS_RECEIVER_ACTION);
mActivityTransitionsPendingIntent =
PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
Artık ActivityTransition'lardan biri gerçekleştiğinde tetikleyebileceğimiz bir PendingIntent'imiz var.
ActivityTransitionRequest oluşturma ve güncelleme isteğinde bulunma
ActivityTransitions listesini ActivityTransitionRequest sınıfına ileterek bir ActivityTransitionRequest nesnesi oluşturabilirsiniz.
base
modülünde, MainActivity.java
bölümünde İstek oluşturma ve etkinlik değişikliklerini dinleme'yi arayın. Aşağıdaki kodu yorumdan sonra ekleyin.
// TODO: Create request and listen for activity changes.
ActivityTransitionRequest request = new ActivityTransitionRequest(activityTransitionList);
// Register for Transitions Updates.
Task<Void> task =
ActivityRecognition.getClient(this)
.requestActivityTransitionUpdates(request, mActivityTransitionsPendingIntent);
task.addOnSuccessListener(
new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void result) {
activityTrackingEnabled = true;
printToScreen("Transitions Api was successfully registered.");
}
});
task.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
printToScreen("Transitions Api could NOT be registered: " + e);
Log.e(TAG, "Transitions Api could NOT be registered: " + e);
}
});
Kodu inceleyelim. Öncelikle etkinlik geçişi listemizden bir ActivityTransitionRequest oluştururuz.
ActivityTransitionRequest request = new ActivityTransitionRequest(activityTransitionList);
Ardından, ActivityTransitionRequest örneğinizi ve son adımda oluşturduğumuz PendingIntent nesnesini requestActivityTransitionUpdates() yöntemine ileterek etkinlik geçişi güncellemelerine kaydoluyoruz. requestActivityTransitionUpdates() yöntemi, kodun sonraki bloğunda gösterildiği gibi, başarılı olup olmadığını kontrol edebileceğiniz bir Task nesnesi döndürür:
// Register for Transitions Updates.
Task<Void> task =
ActivityRecognition.getClient(this)
.requestActivityTransitionUpdates(request, mActivityTransitionsPendingIntent);
task.addOnSuccessListener(
new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void result) {
activityTrackingEnabled = true;
printToScreen("Transitions Api was successfully registered.");
}
});
task.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
printToScreen("Transitions Api could NOT be registered: " + e);
Log.e(TAG, "Transitions Api could NOT be registered: " + e);
}
});
Uygulamanız, etkinlik geçişi güncellemelerine başarıyla kaydolduktan sonra, kayıtlı PendingIntent'te bildirim alır. Ayrıca, kullanıcı düğmeyi tekrar tıkladığında etkinleştirmeyi/devre dışı bırakmayı bilip bilmediğimizi anlamak için etkinlik izlemenin etkin olduğu bir değişken de ayarlarız.
Uygulama kapanırken güncellemeleri kaldırma
Uygulama kapanırken geçiş güncellemelerini kaldırmamız önemlidir.
base
modülünde, MainActivity.java
bölümünde Etkinlik değişikliklerini dinlemeyi durdur'u arayın. Aşağıdaki kodu yorumdan sonra ekleyin.
// TODO: Stop listening for activity changes.
ActivityRecognition.getClient(this).removeActivityTransitionUpdates(mActivityTransitionsPendingIntent)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
activityTrackingEnabled = false;
printToScreen("Transitions successfully unregistered.");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
printToScreen("Transitions could not be unregistered: " + e);
Log.e(TAG,"Transitions could not be unregistered: " + e);
}
});
Şimdi, uygulama kapanırken yukarıdaki kodu içeren yöntemi çağırmamız gerekiyor.
base
modülünde, onPause()
bölümündeki MainActivity.java
altında TODO: Kullanıcı uygulamadan çıktığında etkinlik geçişlerini devre dışı bırak ifadesini arayın. Aşağıdaki kodu yorumdan sonra ekleyin.
// TODO: Disable activity transitions when user leaves the app.
if (activityTrackingEnabled) {
disableActivityTransitions();
}
Etkinlik geçişlerindeki değişiklikleri izlemeyle ilgili bu kadar. Şimdi güncellemeleri işleme almamız gerekiyor.
7. Etkinlikleri işleme
İstenen etkinlik geçişi gerçekleştiğinde uygulamanız bir Intent geri çağırma alır. Intent'ten ActivityTransitionEvent nesnelerinin listesini içeren bir ActivityTransitionResult nesnesi ayıklanabilir. Etkinlikler kronolojik sıraya göre düzenlenir. Örneğin, bir uygulama ACTIVITY_TRANSITION_ENTER ve ACTIVITY_TRANSITION_EXIT geçişlerinde IN_VEHICLE etkinlik türünü isterse kullanıcı araç kullanmaya başladığında bir ActivityTransitionEvent nesnesi, başka bir etkinliğe geçtiğinde ise başka bir ActivityTransitionEvent nesnesi alır.
Bu etkinlikleri işleyen kodu ekleyelim.
base
modülünde, daha önce oluşturduğumuz BroadcastReceiver'ın onReceive()
bölümündeki MainActivity.java
içinde TODO: Dinleyiciden etkinlik geçiş bilgilerini ayıklayın ifadesini arayın. Aşağıdaki kodu yorumdan sonra ekleyin.
// TODO: Extract activity transition information from listener.
if (ActivityTransitionResult.hasResult(intent)) {
ActivityTransitionResult result = ActivityTransitionResult.extractResult(intent);
for (ActivityTransitionEvent event : result.getTransitionEvents()) {
String info = "Transition: " + toActivityString(event.getActivityType()) +
" (" + toTransitionType(event.getTransitionType()) + ")" + " " +
new SimpleDateFormat("HH:mm:ss", Locale.US).format(new Date());
printToScreen(info);
}
}
Bu işlem, bilgileri String
olarak dönüştürür ve ekrana yazdırır.
Hepsi bu kadar. Uygulamayı çalıştırmayı deneyin.
ÖNEMLİ NOT: Etkinlik değişikliklerini emülatörde yeniden oluşturmak zor olduğundan fiziksel bir cihaz kullanmanızı öneririz.
Etkinlik değişikliklerini takip edebilirsiniz.
En iyi sonuçlar için uygulamayı fiziksel bir cihaza yükleyin ve etrafta dolaşın. :)
8. Kodu İnceleme
Etkinlik geçişlerini izleyip ekranda listeleyen basit bir uygulama oluşturdunuz.
Yaptıklarınızı gözden geçirmek ve bunların birlikte nasıl çalıştığı hakkında daha iyi bir fikir edinmek için kodun tamamını okumaktan çekinmeyin.