Activity Recognition ile Kullanıcı Aktivitelerini Tespit Etme

Bazı mobil uygulamalar da insanların  koşma, yürüme, bisiklet ya da araba sürme  gibi eylemlerini tespit edip,  kullanıcıya aktiviteleri hakkında  işlevsel bilgiler vermektedir. Örneğin, adım sayar uygulamaları, fitness spor uygulamaları hatta GoogleFit  uygulaması dahi bu konu üzerine çalışmaktadır.

Android uygulamalarda, insanların  koşma, yürüme, bisiklet ya da araba sürme  gibi eylemlerini tespit edebilmek için ActivityRecognitionClient sınıfını kullanmalıyız. Makalemde ise  bu konu hakkında Android uygulama yapacağım. Kullanıcı bu aktiviteleri yaparken uygulama arka plan da dahi olsa, kullanıcının yaptığı aktiviteler hakkında bilgi vermeyi sağlayan bir program yazacağım.

 

1-Activity Recognition

Android in eski sürümlerinde bu iş için LocationClientActivityRecognitionApi.  sınıfları kullanılıyordu. Ancak bu sınıflar son zamanlarda kullanımdan kaldırılmıştır. Kullanıcıların eylemlerini tespit etmek için artık ActivityRecognitionClient sınıfı kullanmalıyız. İşte, etkinliği saptamak için kullanılabileceğimiz kod:

ActivityRecognitionClient mActivityRecognitionClient = new ActivityRecognitionClient(this);
Task<Void> task = mActivityRecognitionClient.requestActivityUpdates(
Constants.DETECTION_INTERVAL_IN_MILLISECONDS,
mPendingIntent);
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
ArrayList<DetectedActivity> detectedActivities = (ArrayList) result.getProbableActivities();
for (DetectedActivity activity : detectedActivities) {
Log.e(TAG, "Algılanan etkinlik: " + activity.getType() + ", " + activity.getConfidence());
}

2- Android Proje Oluşturma

Yapmamız gereken adımlar şu şekildedir:

  1. Android Studio ide’sinde yeni bir proje oluşturalım.
  2. Android SDK da, SDK Tools sekmesinde bulunan Google Play services APIs‘ini yüklemeliyiz.
  3. Oluşturduğum projemin app dizinin altındaki build.gradle dosyasını açıyoruz. Dependencies kod bloklarının arasına aşağıdaki kodları yerleştirerek  play-services-location kütüphanesini yüklüyoruz.
    build.gradle
    dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    //...
    compile 'com.google.android.gms:play-services-location:11.6.0'
    }
  4. Kullanıcının aktivite değişikliklerini algılayabilmek için belli sürelerde kontrol etmemiz gerekmektedir. Bu zamanı milli saniye cinsinden verip, diğer değişkenleride default değerler vermek için Constant sınıfını tanımlıyoruz.
    public class Constants {
    public static final String BROADCAST_DETECTED_ACTIVITY = "activity_intent";
    static final long DETECTION_INTERVAL_IN_MILLISECONDS = 30 * 1000;
    public static final int CONFIDENCE = 70;
    }
  5. DetectedActivitiesIntentService.java adlı bir sınıf oluşturun. Bu sınıfa, IntentService ‘dan kalıtım alın. OnHandleIntent () metodunda  etkinliklerin listesi elde edilir ve LocalBroadcastManager kullanılarak yayınlanacaktır.
    import android.app.IntentService;
    import android.content.Intent;
    import android.support.v4.content.LocalBroadcastManager;
    import android.util.Log;
    import com.google.android.gms.location.ActivityRecognitionResult;
    import com.google.android.gms.location.DetectedActivity;
    import java.util.ArrayList;
    public class DetectedActivitiesIntentService  extends IntentService {
    protected static final String TAG = DetectedActivitiesIntentService.class.getSimpleName();
    public DetectedActivitiesIntentService() {
    super(TAG);
    }
    @Override
    public void onCreate() {
    super.onCreate();
    }
    @SuppressWarnings("unchecked")
    @Override
    protected void onHandleIntent(Intent intent) {
    ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
    // Cihazın geçerli durumu ile ilgili olası aktivitelerin listesini alır
    ArrayList detectedActivities = (ArrayList) result.getProbableActivities();
    //Döngü ile tüm yapılan faaliyetlerin tipini ve faaliyetin doğruluğu hakkında bilgi verir.(Değer 0 ile 100 arasındadır)  
    for (DetectedActivity activity : detectedActivities) {
    Log.e(TAG, "Algılanan faaliyet: " + activity.getType() + ", " + activity.getConfidence());
    broadcastActivity(activity);
    }
    }
    private void broadcastActivity(DetectedActivity activity) {
    Intent intent = new Intent(Constants.BROADCAST_DETECTED_ACTIVITY);
    intent.putExtra("type", activity.getType());
    intent.putExtra("confidence", activity.getConfidence());
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }
    }
    
  6. Arka planda çalışacak olan ve belirli aralıklıklarla kullanıcının faaliyetleri tespit edecek Android servis sınıfını oluşturmamız gerekir.
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    import android.util.Log;
    import android.widget.Toast;
    import com.google.android.gms.location.ActivityRecognitionClient;
    import com.google.android.gms.tasks.OnFailureListener;
    import com.google.android.gms.tasks.OnSuccessListener;
    import com.google.android.gms.tasks.Task;
    public class BackgroundDetectedActivitiesService extends Service {
    private static final String TAG = BackgroundDetectedActivitiesService.class.getSimpleName();
    private Intent mIntentService;
    private PendingIntent mPendingIntent;
    private ActivityRecognitionClient mActivityRecognitionClient;
    IBinder mBinder = new BackgroundDetectedActivitiesService.LocalBinder();
    public class LocalBinder extends Binder {
    public BackgroundDetectedActivitiesService getServerInstance() {
    return BackgroundDetectedActivitiesService.this;
    }
    }
    @Override
    public void onCreate() {
    super.onCreate();
    mActivityRecognitionClient = new ActivityRecognitionClient(this);
    mIntentService = new Intent(this, DetectedActivitiesIntentService.class);
    mPendingIntent = PendingIntent.getService(this, 1, mIntentService, PendingIntent.FLAG_UPDATE_CURRENT);
    requestActivityUpdatesButtonHandler();
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
    return mBinder;
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    return START_STICKY;
    }
    public void requestActivityUpdatesButtonHandler() {
    Task task = mActivityRecognitionClient.requestActivityUpdates(
    Constants.DETECTION_INTERVAL_IN_MILLISECONDS,
    mPendingIntent);
    task.addOnSuccessListener(new OnSuccessListener() {
    @Override
    public void onSuccess(Void result) {
    Toast.makeText(getApplicationContext(),
    "Başarıyla talep edilen etkinlik güncellemeleri",
    Toast.LENGTH_SHORT)
    .show();
    }
    });
    task.addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
    Toast.makeText(getApplicationContext(),
    "Etkinlik güncelleme talep etme başarısız oldu",
    Toast.LENGTH_SHORT)
    .show();
    }
    });
    }
    public void removeActivityUpdatesButtonHandler() {
    Task task = mActivityRecognitionClient.removeActivityUpdates(
    mPendingIntent);
    task.addOnSuccessListener(new OnSuccessListener() {
    @Override
    public void onSuccess(Void result) {
    Toast.makeText(getApplicationContext(),
    "Etkinlik güncellemeleri başarıyla kaldırdı!",
    Toast.LENGTH_SHORT)
    .show();
    }
    });
    task.addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
    Toast.makeText(getApplicationContext(), "Etkinlik güncellemeleri kaldırılamadı!",
    Toast.LENGTH_SHORT).show();
    }
    });
    }
    @Override
    public void onDestroy() {
    super.onDestroy();
    removeActivityUpdatesButtonHandler();
    }
    }
    
  7. BackgroundDetectedActivitiesService ve DetectedActivitiesIntentService servis sınıflarını AndroidManifest.xml dosyasında tanımlamamız gerekir. Birde AndroidManifest.xml dosyasında ACTIVITY_RECOGNITION iznini vermemiz gerekir.
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.smality.activityrecognition">
    <uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
    <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
    <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    </activity>
    <service
    android:name=".DetectedActivitiesIntentService" android:exported="false" />
    <service android:name=".BackgroundDetectedActivitiesService"></service>
    </application>
    </manifest>

3-Activity Recognition

Şimdi herşeye hazırız. Kullanıcının yaptığı güncel  aktiviteyi  veya herhangi bir başka aktivite yaptığında bunun bilgisini nasıl alacağımızı görelim.

  1. ImageView (etkinliği temsil eden bir simge görüntülemek için) ve TextView (etkinliği görüntülemek için) ekliyoruz. Ayrıca, etkinlik tanıma hizmetini başlatmak ve başlatmak için iki button ekledim.
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    tools:context="com.smality.activityrecognition.MainActivity">
    <LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:orientation="vertical">
    <ImageView
    android:id="@+id/img_activity"
    android:layout_width="wrap_content"
    android:layout_height="200dp"
    android:tint="#606060" />
    <TextView
    android:id="@+id/txt_activity"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:textAllCaps="true"
    android:textColor="@color/colorPrimary"
    android:textSize="18dp"
    android:textStyle="bold" />
    <TextView
    android:id="@+id/txt_confidence"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="10dp"
    android:textAllCaps="true"
    android:textSize="14dp" />
    </LinearLayout>
    <Button
    android:id="@+id/btn_start_tracking"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:text="Start Tracking" />
    <Button
    android:id="@+id/btn_stop_tracking"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    android:text="Stop Tracking" />
    </RelativeLayout>

     

  2. MainActivity  sınıfında kullanılan startTracking() ve stopTracking() metodlar,hizmet durumunu değiştirerek kullanıcı etkinliği güncellemelerini başlatır veya durdurur. BroadcastReceiver  sınıfı, IntentService’den etkinlik güncellemelerini almak için kullanılır. handleUserActivity() metodu, kullanıcının yaptığı güncel aktivite tipini,aktivitenin doğruluğu bilgisini kullanarak arayüzde ilgili faaliyetin resmini ve doğruluk bilgisini gösterir.
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.support.v4.content.LocalBroadcastManager;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    import android.widget.TextView;
    import com.google.android.gms.location.DetectedActivity;
    public class MainActivity extends AppCompatActivity {
    private String TAG = MainActivity.class.getSimpleName();
    BroadcastReceiver broadcastReceiver;
    private TextView txtActivity, txtConfidence;
    private ImageView imgActivity;
    private Button btnStartTrcking, btnStopTracking;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    txtActivity = findViewById(R.id.txt_activity);
    txtConfidence = findViewById(R.id.txt_confidence);
    imgActivity = findViewById(R.id.img_activity);
    btnStartTrcking = findViewById(R.id.btn_start_tracking);
    btnStopTracking = findViewById(R.id.btn_stop_tracking);
    btnStartTrcking.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
    startTracking();
    }
    });
    btnStopTracking.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
    stopTracking();
    }
    });
    broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(Constants.BROADCAST_DETECTED_ACTIVITY)) {
    int type = intent.getIntExtra("type", -1);
    int confidence = intent.getIntExtra("confidence", 0);
    handleUserActivity(type, confidence);
    }
    }
    };
    startTracking();
    }
    private void handleUserActivity(int type, int confidence) {
    String label = getString(R.string.activity_unknown);
    int icon = R.drawable.ic_still;
    switch (type) {
    case DetectedActivity.IN_VEHICLE: {
    label = getString(R.string.activity_in_vehicle);
    icon = R.drawable.ic_driving;
    break;
    }
    case DetectedActivity.ON_BICYCLE: {
    label = getString(R.string.activity_on_bicycle);
    icon = R.drawable.ic_on_bicycle;
    break;
    }
    case DetectedActivity.ON_FOOT: {
    label = getString(R.string.activity_on_foot);
    icon = R.drawable.ic_walking;
    break;
    }
    case DetectedActivity.RUNNING: {
    label = getString(R.string.activity_running);
    icon = R.drawable.ic_running;
    break;
    }
    case DetectedActivity.STILL: {
    label = getString(R.string.activity_still);
    break;
    }
    case DetectedActivity.TILTING: {
    label = getString(R.string.activity_tilting);
    icon = R.drawable.ic_tilting;
    break;
    }
    case DetectedActivity.WALKING: {
    label = getString(R.string.activity_walking);
    icon = R.drawable.ic_walking;
    break;
    }
    case DetectedActivity.UNKNOWN: {
    label = getString(R.string.activity_unknown);
    break;
    }
    }
    Log.e(TAG, "User activity: " + label + ", Confidence: " + confidence);
    if (confidence > Constants.CONFIDENCE) {
    txtActivity.setText(label);
    txtConfidence.setText("Confidence: " + confidence);
    imgActivity.setImageResource(icon);
    }
    }
    @Override
    protected void onResume() {
    super.onResume();
    LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver,
    new IntentFilter(Constants.BROADCAST_DETECTED_ACTIVITY));
    }
    @Override
    protected void onPause() {
    super.onPause();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
    }
    private void startTracking() {
    Intent intent1 = new Intent(MainActivity.this, BackgroundDetectedActivitiesService.class);
    startService(intent1);
    }
    private void stopTracking() {
    Intent intent = new Intent(MainActivity.this, BackgroundDetectedActivitiesService.class);
    stopService(intent);
    }
    }

Dilerseniz aşağıda vermiş olduğum Kod İndir resmine tıklayarak github’a yüklemiş olduğum projeyi indirip, inceleyebilirsiniz.

download

Kaynaklar

1-https://smality.com/activity-recognition-ile-kullanici-aktivitelerini-tespit-etme/

2- http://www.androhub.com/android-floating-widget-like-facebook-messenger-chat-head/

3- http://www.androidhive.info/2016/11/android-floating-widget-like-facebook-chat-head/

Kategori Genel
Etiketler