Commit 0a11b6f8 authored by Mattia Ducci's avatar Mattia Ducci

implementato screen tracking

parent f082196a
AppuntiProgetto/
...@@ -25,4 +25,6 @@ dependencies { ...@@ -25,4 +25,6 @@ dependencies {
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation project(':icarus')
} }
...@@ -2,14 +2,45 @@ package framework.everywaretechnologies.it.icarusandroid; ...@@ -2,14 +2,45 @@ package framework.everywaretechnologies.it.icarusandroid;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Switch;
import framework.everywaretechnologies.it.icarus.Icarus;
//classe di test Icarus framework //classe di test Icarus framework
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
private final static String CLASS_NAME="MainActivity";
private Switch enteredExitedScreenTrackSwitch;
private Icarus instance;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
instance=Icarus.getInstance(MainActivity.this);
instance.setApplicationContext(getApplicationContext());
enteredExitedScreenTrackSwitch=findViewById(R.id.entered_exited_screen_track_switch);
}
//------------------------- UI EVENT -----------------------
public void onBtnScreenEventTrack(View view){
Log.d(CLASS_NAME,"on btn screen event track");
String eventType=null;
if(enteredExitedScreenTrackSwitch.isChecked())
eventType=enteredExitedScreenTrackSwitch.getTextOn().toString();
else
eventType=enteredExitedScreenTrackSwitch.getTextOff().toString();
instance.trackScreen(MainActivity.this,eventType);
} }
} }
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <android.widget.LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity"> tools:context=".MainActivity">
<TextView <TextView
android:layout_width="wrap_content" android:id="@+id/lbl_track_screen"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Hello World!" android:text="Track screen"
android:textColor="@android:color/holo_red_light"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout> <Switch
\ No newline at end of file android:id="@+id/entered_exited_screen_track_switch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:showText="true"
android:splitTrack="false"
android:text="Tipo di evento"
android:textOff="EXITED"
android:textOn="ENTERED" />
<Button
android:id="@+id/btn_send_screen_track_event"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onBtnScreenEventTrack"
android:text="Invia screen track event" />
</android.widget.LinearLayout>
\ No newline at end of file
...@@ -33,4 +33,5 @@ dependencies { ...@@ -33,4 +33,5 @@ dependencies {
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.volley:volley:1.1.0' implementation 'com.android.volley:volley:1.1.0'
implementation 'com.google.code.gson:gson:2.8.3'
} }
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="framework.everywaretechnologies.it.icarus" /> package="framework.everywaretechnologies.it.icarus" >
<uses-permission android:name="android.permission.INTERNET"/> <!-- richiesto da Volley -->
</manifest>
\ No newline at end of file
package framework.everywaretechnologies.it.icarus; package framework.everywaretechnologies.it.icarus;
public class EventTrackResource extends IcarusResource { public class EventTrackResource extends IcarusResource {
public EventTrackResource(){
super();
}
} }
package framework.everywaretechnologies.it.icarus; package framework.everywaretechnologies.it.icarus;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.util.Log;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
class Icarus {
public class Icarus {
enum Categories{
APPLICATION,ACTION,NOTIFICATION;
}
private final static String ICARUS_URL="https://webdev.ewlab.di.unimi.it/icarus/str";
private static final Icarus ourInstance = new Icarus(); private static final Icarus ourInstance = new Icarus();
private Queue<IcarusResource> pendingResources; private Queue<JSONObject> pendingResources; //FIFO
private Lock pendingResourceLock; private Lock pendingResourceLock;
private Context appContext;// serve per istanziare un un'unica coda di richieste Volley (e non averne una per Activity)
private static Context curContext; //context dell'Activity corrente
private RequestQueue mVolleyRequestQueue;
public static Icarus getInstance(Context c) {
public static Icarus getInstance() { curContext=c;
return ourInstance; return ourInstance;
} }
...@@ -21,8 +53,94 @@ class Icarus { ...@@ -21,8 +53,94 @@ class Icarus {
pendingResourceLock=new ReentrantLock(); pendingResourceLock=new ReentrantLock();
} }
public void pushResource(IcarusResource icarusResource){ public void setApplicationContext(Context applicationContext){
appContext=applicationContext;
//adesso che ho l'applicationContext dell'app chiamante creo la coda di richieste per Volley
mVolleyRequestQueue= Volley.newRequestQueue(appContext);
}
//----------------- LOG PREFERENCE CHANGES -----------------------
public void logUserSettings(SharedPreferences mySharedPrefs){
Log.d(curContext.getString(R.string.icarus_class),"log pref changes");
}
//---------------------- LOG SCREEN TRACKING ------------------------------
public void trackScreen(Context c,String screenEventType){
Log.d(curContext.getString(R.string.icarus_class),"log screen track");
String screenName=c.getClass().getSimpleName();
if(screenEventType.equalsIgnoreCase(ScreenTrackResource.EVENT_ENTERED) || screenEventType.equalsIgnoreCase(ScreenTrackResource.EVENT_EXITED) ){
IcarusResource resource=new ScreenTrackResource(screenName,screenEventType);
Gson gson=new Gson();
String screenTrackJson=gson.toJson(resource);
try {
JSONObject icarusPayload=new JSONObject(screenTrackJson);
postIcarusHttpRequest(icarusPayload);
Log.d(curContext.getString(R.string.icarus_class),"log screen track -> Volley");
} catch (JSONException e) {
e.printStackTrace();
}
}
}
//---------------------- LOG EVENT TRACKING --------------------------
public void logEvent(String eventName,String category,String label){
Log.d(curContext.getString(R.string.icarus_class),"log event");
}
//--------------------------- UTILITY ----------------------------------
private void postIcarusHttpRequest(final JSONObject icarusPayload){
final JsonObjectRequest jsonObjectRequest=new JsonObjectRequest(Request.Method.POST, ICARUS_URL, icarusPayload, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.d(curContext.getString(R.string.icarus_class),"onVolley response POSITIVE");
//controllo se ho qualche elemento che precedentemente non sono riuscito ad inviare e nel caso lo provo ad inviare
pendingResourceLock.lock();
if(pendingResources.peek() != null){ //se ho qualche elemento pendente da inviare
Log.d(curContext.getString(R.string.icarus_class),"messaggi pendenti");
JSONObject pendingResource=pendingResources.poll();
postIcarusHttpRequest(pendingResource);
}
pendingResourceLock.unlock();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(curContext.getString(R.string.icarus_class),"onVolley response NEGATIVE");
pendingResourceLock.lock();
pendingResources.add(icarusPayload);
pendingResourceLock.unlock();
}
});
mVolleyRequestQueue.add(jsonObjectRequest);//faccio effettivamente la richiesta
} }
} }
package framework.everywaretechnologies.it.icarus; package framework.everywaretechnologies.it.icarus;
public abstract class IcarusResource { public abstract class IcarusResource {
public IcarusResource(){}
} }
package framework.everywaretechnologies.it.icarus; package framework.everywaretechnologies.it.icarus;
public class ScreenTrackResource extends IcarusResource { public class ScreenTrackResource extends IcarusResource {
public final static String EVENT_ENTERED="Entered";
public final static String EVENT_EXITED="Exited";
private String ScreenName; //è un attributo anche se inizia con la lettera maiuscola perchè il server vuole così il nome del campo JSON
private String Event;
public ScreenTrackResource(String _screenName,String _event){
super();
ScreenName=_screenName;
Event=_event;
}
} }
package framework.everywaretechnologies.it.icarus; package framework.everywaretechnologies.it.icarus;
public class UserSettingsResource extends IcarusResource { public class UserSettingsResource extends IcarusResource {
public UserSettingsResource(){
super();
}
} }
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="icarus_class">Icarus</string>
</resources>
\ No newline at end of file
<resources> <resources>
<string name="app_name">Icarus</string> <string name="lib_name">Icarus</string>
</resources> </resources>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment