How to track user preferences with Google Analytics for Android? - android

I would like to understand what kind of Preferences my users have in my application.
I was thinking about something like:
EasyTracker easyTracker = EasyTracker.getInstance(context);
easyTracker.send(MapBuilder
.createEvent("user",
"prefs",
"data",
(long) data)
.build()
);
And then pass the data like:
if (user_name != "") { data += 1; }
if (user_address != "") { data += 10; }
if (user_phone != "") { data += 100; }
But will I be able to track then for ex., how many users have empty user_address?

I think there are 2 better options for this type of data.
Your applications database. SQL select statements can give you counts and specific values already. No need to track in an additional place. Example:
select sum(if(user_name is null,0,1)) as num_Users_With_UserName
from users
group by if(user_name is null,0,1)
If you only have these 3 preferences to track and you want to see them in GA for whatever reason I recommend custom variables or custom dimensions (depending on what version of GA you're using) not events. These can be set with a user scope you can track changes for a user but keep the state of their preference across visits. Events are best for tracking clicks and user variables are best tracked in custom variables or custom dimensions. (You may want to combine a custom dimension for 'Has Username' and an event for when the Username field changes state for example.)

I would recommend using:
EasyTracker.getTracker().sendEvent("user", "prefs","has_name", 1l);
EasyTracker.getTracker().sendEvent("user", "prefs","has_address", 1l);
EasyTracker.getTracker().sendEvent("user", "prefs","has_phone", 1l);
Although you have to be sure to send such even once, when entering it for the first maybe?
You could send -1 when user unsets ( not 100% if it would work ), and you dont have to care if he edits it.

Related

Get event when replacing node with the same value?

is it possible to get an event in a Listener when I replace value of a node with the same value? seams like if firebase notice that the value is the same no event accures..:s
The Firebase Database synchronizes state between clients. If a write operation doesn't change the state, there is nothing to synchronize to the other listening clients.
In simple code:
ref.setValue(1);
ref.setValue(1); // won't trigger listeners
ref.setValue(2); // will trigger active listeners
ref.setValue(2); // won't trigger listeners
It sounds like you want to instead pass messages between clients. This is totally feasible, but means that you should model your data differently. Instead of storing the value in your database, store the fact that the client wrote a value.
In simple code:
ref.push(1);
ref.push(1);
ref.push(2);
ref.push(2);
In this last sample each write will trigger listeners on ref, since each write is new.
This is a common pattern: instead of storing the final state, you're storing the state changes. It essentially similar the mechanism behind oplogs in databases and many other systems.
Because nothing happens there is no event that is triggered. What can you do in stead, is to check the value before you are setting it.
if(myValue.equals(firebaseValue)) {
//do something
} else {
//do something else
}
Hope it helps.

Add a service to my android app to get notifications whenever a fire base child is added [duplicate]

I have a node in Firebase getting continually updated with information from a logfile. The node is lines/ and each child of lines/ is from a post() so it has a unique ID.
When a client first loads, I want to be able to grab the last X number of entries. I expect I'll do this with once(). From then on, however, I want to use an on() with child_added so that I get all new data. However, child_added gets all data stored in the Firebase and, after the initial setup, only want the new stuff.
I see that I can add a limitToLast() on the on(), but, if I say limitToLast(1) and a flood of entries come in, will my app still get all the new entries? Is there some other way to do this?
You need to include a timestamp property and run a query.
// Get the current timestamp
var now = new Date().getTime();
// Create a query that orders by the timestamp
var query = ref.orderByChild('timestamp').startAt(now);
// Listen for the new children added from that point in time
query.on('child_added', function (snap) {
console.log(snap.val()
});
// When you add this new item it will fire off the query above
ref.push({
title: "hello",
timestamp: Firebase.ServerValue.TIMESTAMP
});
The Firebase SDK has methods for ordering, orderByChild() and methods for creating a range startAt(). When you combine the two you can limit what comes back from Firebase.
I think there is a problem in #David East's solution. He is using the local timestamp which may cause problem if the time is not accurate in client device. Here is my suggested solution (iOS Swift):
Using observeSingleEvent to get the complete data set
Then returned it in reversed order by reversed()
Get the last timestamp by for example data[0].timestamp
Using queryStarting for timestamp
self._dbref.queryOrdered(byChild: "timestamp").queryStarting(atValue: timestamp+1)
.observe(.childAdded, with: {
snapshot in
print(snapshot.value)
})
You have the right idea. child_added should be called only for the new nodes. Without source code it's hard to tell why you get all the data in your child_added event.
You can check the chat demo app to see how they load new chat messages. The use case sounds similar.
https://github.com/firebase/firechat/blob/master/src/js/firechat.js#L347
Here's temporary but quick solution:
// define a boolean
var bool = false;
// fetch the last child nodes from firebase database
ref.limitToLast(1).on("child_added", function(snap) {
if (bool) {
// all the existing child nodes are restricted to enter this area
doSomething(snap.val())
} else {
// set the boolean true to doSomething with newly added child nodes
bool = true;
}
});
Disadvantage: It will load all the child nodes.
Advantage: It will not process existing child nodes but just the newly added child nodes.
limitToLast(1) will do the work.

Flux: Detail Page/Single Item Store

I'm an early and very happy adopter of both Flux and React so much so that, recently, I ported Fluxxor into Android and it's been okay so far.
The issue I am having with it Flux is dealing with data for a Single Item or Details Page. Bear with me below. I will try to be as clear as I can.
The pattern I am using is.
On page load(componentWillMount/componentWillReceiveProps and onStart), I check if the id passed to the page (via url or bundle) matches the id of the item currently in the store and the page if the store is in a processing or success state.
If yes, I do nothing, else, I dispatch an action to load the data for that item.
componentWillMount: function () {
id = this.props.params.path.split("-")[0];
var artistData = this.props.state.artistData;
if(artistData.id != id)
this.getFlux().actions.artistActions.loadArtist(id);
else if (!artistData.artist && !artistData.loading)
this.getFlux().actions.artistActions.loadArtist(id);
this.getFlux().actions.userActions.fetchSuggestions();
}
protected void onStart() {
GenreSongsStore.State state = App.getFlux().getStore(GenreSongsStore.class).getState();
if(mId == state.Genre.getId()) {
if (state.HasMore)
App.getFlux().getActions().Genres.songs(mId, state.Page + 1);
}
else
App.getFlux().getActions().Genres.songs(mId, 1);
super.onStart();
}
In React this is fine since you use a single state on the root. I didn't bother too much until I started working with Android.
Here, I don't use a single state but query the relevant store and it totally smells
If you are not using that page, the data is still held in memory
Since the data is not shared it seems there is no benefit to doing it like this
Won't it simply be easier to load the data in the component/activity/fragment?
However, I get the benefit of maintaining the currently loading state. So the user can minimize and reopen the app and we continue (no need for saving an instance bundle).
I know by doing it like this, I lose the benefit of unidirectional data flow. But it seems to make more sense in the context of Android (pun intended).
Can I have your views on how you do this and if I'm simply worried about nothing.
NB: The data is not shared by any other stores at.

Android : Popup certain dialog at first startiup only

I am trying to develop an app that requires certain values to be set by the users at the app's first startup only, because i don't wanna bother them frequently inputting the values everytime they launch the app. My app has a single activity main and uses certain values that are inputted by the users at first startup. How can I make this possible.
Please explain me elaborately . :-)
You should use SharedPreferences to keep a track of the first use.
In the onCreate Method of your Activity (Startup activity), you could do something like this,
SharedPreferences userPrefs = getSharedPreferences("UserPrefs", 0);
Boolean firstUse = userPrefs.getBoolean("firstUse", true);
if(firstUse){
//this implies it is the first use of the app
//also once you are done implementing the logic for first use you need to put firstUse as true
SharedPreferences.Editor editor = userPrefs.edit();
editor.putBoolean("firstUse", false);
editor.commit();
}
else{
//take the user directly inside the app
}
Also, if you plan to save user information in the first use, look at different ways of storing data here.
show the alert initially and after getting the input values keep it in preference and next time check whether the required values existing or not. If it is already there avoid popup
For getting more information about shared preference check this link http://www.vogella.com/tutorials/AndroidFileBasedPersistence/article.html
preferences_statusFirst.getString("boot", "");
if (status.length() <= 0)
{
showDialog(DIALOG_birth);
editor_boot.putString("boot", "1");
editor_boot.commit();
}
else
{
}
}

Programatically change "Reject call with message"

I'd like to change the messages in the list "Reject call with message" according to the calling number (whether I have it in my contacts or if it has a certain carrier, etc) or even hide this option completely for some numbers.
What I'm asking for is a starting point since I couldn't find anything on developer.android.com nor on the internet.
Note: I don't want to reject or mute a call, no, I just want to modify the "Reject call with message" list on the fly depending on the caller or even disable it completely for some numbers.
Quick response messages can only be altered through Call settings UI as the values are stored in Phone app's shared preference, respond_via_sms_prefs.xml. See RespondViaSmsManager.java:
/** SharedPreferences file name for our persistent settings. */
private static final String SHARED_PREFERENCES_NAME = "respond_via_sms_prefs";
public void setInCallScreenInstance(InCallScreen inCallScreen) {
mInCallScreen = inCallScreen;
if (mInCallScreen != null) {
// Prefetch shared preferences to make the first canned response lookup faster
// (and to prevent StrictMode violation)
mInCallScreen.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
}
}
Only Phone app can read/write from/to the file.
Default values are set in respond_via_sms_settings.xml.
As far as I can tell, what you are trying to achieve is not feasible at this moment.

Categories

Resources