Android In APP billing not firing event in my class - android

I am using the 'Dungeon' example as a basis for my code, so it is the standard examplecode for now.
I can call the Market place and successfully place an order. Within BillingReciever the event
public void onReceive is called twice, as I would expect and I can put a breakpoint there and see the result which is fine.
checkResponseCode gets called too and starts
Intent intent = new Intent(Consts.ACTION_RESPONSE_CODE);
intent.setClass(context, BillingService.class);
intent.putExtra(Consts.INAPP_REQUEST_ID, requestId);
intent.putExtra(Consts.INAPP_RESPONSE_CODE, responseCodeIndex);
context.startService(intent);
And there the execution stops, and my app returns to a run state.
I have an extended PurchaseObserver class which is supposed to respond to billing changes, which I have tried starting two different ways
mPurchaseObserver = new iPurchaseObserver(this,mHandler);
private class iPurchaseObserver extends PurchaseObserver {
public iPurchaseObserver(UpgradeActivity upgradeActivity, Handler handler) {
super(upgradeActivity, handler);
}
And
mPurchaseObserver = new iPurchaseObserver(mHandler);
private class iPurchaseObserver extends PurchaseObserver {
public iPurchaseObserver( Handler handler) {
super(upgradeActivity.this, handler);
}
None of the events/methods within the PurchaseObserver are fired, i.e onPurchaseStateChange.
I am suspecting it is the Activity Context I am passing or using when constructing my PurchaseObserver, but I am not sure, and advise would be appreciated!
Thanks

Found it, after loads and loads of wasted time. I had put the classes in a folder, when I moved them back to the root, they worked.

Related

Can push notification execute code in parallel with UI thread or not?

AsFirebaseMessagingService does not use the Main Thread, I am just wondering as all my code in all of my activities or fragments run in UI thread(Main Thread). Now suppose my activity's onCreate method is executing and then I receive the push notification. Will these two blocks of code run in parallel, or will the push notification code wait in the queue until onCreate() method OR Activity's last life cycle method gets executed?
Edit- As you are saying code will run parallelly then suppose I have a variable in App.java
public class App extends Application {
int ctr = 100;
}
StatusActivity.java
public class StatusActivity extends BaseActivity {
public void onCreate() {
fun();
}
public void fun() {
int d = App.ctr - 1;//Step 1 Here d = 99
int m = App.ctr - 1; // Step 3 Here m = 98
}
}
FcmListener.java
public class FcmListener extends FirebaseMessagingService {
Override
public void onMessageReceived(RemoteMessage mssg) {
App.ctr = App.ctr - 1;//STEP 2 // Now App.ctr = 99
}
}
Now as you can see in the above code there will be problems if push notif code executes in parallel with fun(). I want push_notif and fun() to run serially, where order doesn't matter but not in parallel.
As already pointed out in a parallel answer, the overriden methods of FirebaseMessagingService run in a background thread, so you should use synchronization strategies in order to access/use mutable object from different thread.
But the question I want to answer is a bit different. Let's for a moment assume, that overriden methods run on a main thread. So is there a possibility, that the order of execution will be STEP 1 then STEP 2 and then STEP 3?
Android works with a technique called MessageQueue, basically there are Messages posted on that queue, on which Looper loops and "parses/executes" them.
Now if we assume, that you are currently located on STEP 1, it means, that there was a particular Message which is currently being executed (hypothetically, let's assume that action is - perform onCreate() of this activity).
Until this message is fully executed there cannot exist another Message which might get have a chance to be executed. So if we assume, that Firebase dispatches an event on background thread but the actual overriden method is being run on main thread, then this overriden method would have chance to be executed only after current Message (activity's onCreate()) has finished. In other words, there would be posted another Message on the MessageQueue, which would perform onMessageReceived() when the Looper will give chance for this message to be executed.
So, theoretically, there is no chance that the ordering would be STEP 1 -> STEP 2 -> STEP 3.
If STEP 1 is already executed, then it will continue with STEP 3 and the STEP 2 (at some point in future, because you can't know what other Messages are already posted on MessageQueue).
See this article for more details about MessageQueue and related classes.
How about it?
class Sample {
private String message = null;
private final Object lock = new Object();
public void newMessage(String x) {
synchronized (lock) {
message = x;
}
}
public String getMessage() {
synchronized (lock) {
String temp = message;
message = null;
return temp;
}
}
}
Here is my 2 cents. You say,
Suppose my activity's onCreate method is executing and then I receive the push notification. Will these two blocks of code run parallelly or will the push notification code wait in the queue until onCreate method OR Activity's last life cycle method gets executed?
From the official documentation of FirebaseMessagingService:
Extending this class is required to be able to handle downstream messages. It also provides functionality to automatically display notifications, and has methods that are invoked to give the status of upstream messages. Override base class methods to handle any events required by the application. Methods are invoked on a background thread.
So its possible both methods execute at the same time. If you want to do the operations on a shared variable in your Application class, you can do thread safe operations using synchronize. See How to synchronize or lock upon variables in Java?. That will make sure only one thread is making changes at a time on that variable. If a new thread comes in, it waits for the lock to get free and then makes the changes on that variable. However this doesn't guarantee the order. It just means that one thread operates on it at time and is in FIFO order.
I suggest you a different approach, because using those global variables can lead to unexpected behavior.
If your ctr var is related to your activity, then keep it inside. If you need it on other activities consider passing it via the Intent as an extra.
Use LocalBroadcastManager to inform your activity that you received the push message
public class FcmListener extends FirebaseMessagingService {
public static final String ACTION_MESSAGE_RECEIVED = "ACTION_MESSAGE_RECEIVED"
#Override
public void onMessageReceived(RemoteMessage mssg) {
Intent intent = new Intent(ACTION_MESSAGE_RECEIVED) // put extra vars as needed
boolean delivered = LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
// 'delivered' is true if there is at least someone listening to the broadcast, eg. your activity
// If your activity is not running, then 'delivered' is false so you can act accordingly
}
}
Then inside your activity
public class StatusActivity extends BaseActivity {
private BroadcastReceiver messageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (TextUtils.equals(FcmListener.ACTION_MESSAGE_RECEIVED, action)) {
// do stuff with 'ctr'
}
}
};
#Override
protected void onStart() {
super.onStart();
IntentFilter filter = new IntentFilter(FcmListener.ACTION_MESSAGE_RECEIVED);
LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, filter);
}
#Override
protected void onStop() {
super.onStop();
LocalBroadcastManager.getInstance(this).unregisterReceiver(messageReceiver);
}
}

Bus Implementation... Checking For Fragment Equality... Or Something Similar

I have implemented a bus for my app for communication between fragments and activities. I add a subscriber by adding an instance of either a Fragment or an Activity to a list. and I iterate through that list invoking a method to notify each of the subscribers of what is going on. Now I need to keep the list clean, I don't want to add multiple instances of of the same class in the list. I can use equals() for an Activity but I cant for a Fragment because its final so I cant override it.
WHAT I HAVE TRIED
I have tried to keep a Class object of each subscriber in the list which works fine until I go to invoke the method. You cant invoke a method without an instance to invoke it from. So that doesnt work.
I could also keep a separate list, one to hold Class objects and one to hold the actual instance. But I want to avoid adding another dependency if at all possible.
I could also manually do a instanceof check for each Fragment, but I dont want to do that because I already have 5 fragments, and if I add or remove any then I have to come back here and update this method.
So my question is, other than adding another List to hold the Class objects or manual instanceof checks, are there any other ways I can make sure I dont add multiple instances to the subscribers List?
Here is the relevant code if you need it:
public void subscribe(Object object) {
if (!mSubscribers.contains(object)) {
mSubscribers.add(object);
}
}
public void notifySubscribers(BusEvent event) throws InvocationTargetException, IllegalAccessException {
for (Object o : mSubscribers) {
Method methodToCall = getMethodToCall(o);
if (methodToCall != null) {
methodToCall.invoke(o, event);
}
}
}
Ok I have found a suitable answer to my problem. I want to share it here in hopes that it will help someone else out. Android has a class called LocalBroadcastManager. It is available in the v4 support library. In your activity you call 'LocalBroadcastManager.getInstance().registerReceiver()'. You pass into that method a class that extends BroadcastReceiver and an 'IntentFilter' to tell the receiver what to listen for. Then in any class including Fragments you call LocalBroadcastManager.getInstance().sendBroadcast() and pass in an Intent that matches the IntentFilter you used when registering. Here is the code I used to get it to work:
private void registerLocalBroadcastReceiver() {
// call this method in your activity (or any class you want to listen for broadcasts)
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this);
manager.registerReceiver(new OpenMenuBroadcastReceiver(), new IntentFilter("open-html"));
}
private void sendMessageToActivity(int position) {
// use this in a fragment (or any other class) to send a message
LocalBroadcastManager broadcast = LocalBroadcastManager.getInstance(getActivity());
Intent message = new Intent("open-html");
String name = (String) getListAdapter().getItem(position);
message.putExtra("name", name);
broadcast.sendBroadcast(message);
}
class OpenMenuBroadcastReceiver extends BroadcastReceiver {
// this is an inner class to my activity, when you send the message this method
// will be called to handle the message
#Override
public void onReceive(Context context, Intent intent) {
String name = intent.getStringExtra("name");
if (name != null && name.equalsIgnoreCase("home")) {
replaceFragment(Tag.HOME_FRAGMENT.getTag(), new HomeFragment(), R.id.main_frame);
mDrawerLayout.closeDrawer(Gravity.START);
return;
}
openMenuItemsFragment(name);
}
}
The good thing about this is that it is completely local to your app. External apps cant receive your broadcasts so its secure. You can find out more on how to use it on the Android developer site.

Android ListView notifyDataSetChanged() from Service

I have a background service which receive messages from a server and with those message it updates inner properties of objects which are shown in a ListView.
I always uses the runOnUiThread method to run the listArrayAdapter.notifyOnDataSetChanged() command.
From some reason sometimes the ListView is refreshed and it does show me the property update and sometimes it doesn't..
For testing i've added a "refresh" Button to my ListView and when it pressed the listArrayAdapter.notifyOnDataSetChanged() is executed.
Every click on the button the view is refreshed perfectly..
I can't really understand why when trying to refresh from the service it doesn't always work but i think i maybe not always runs on the UIThread...
I'm really hopeless and will glad to get help..
My Code
ServerConnectionManager.java - extends Service
//example of a command executed when a specific message received from the server:
//app is the Application variable
public void unFriend(int userId)
{
serverResponseManager.onUnFriend(app.getApplicationFriend(userId),false);
}
ServerResponseManager.java - a class that handle all application responses to server messages:
public void onUnFriend(FacebookUser facebookUser, boolean isYouRemovedClient) {
//this is the property which will effect the ListView view when calling the
//arrayListAdataper.notifyOnDataSetChanged();
facebookUser.setApplicationFriend(false);
app.getApplicationFriends().remove(facebookUser);
app.getDatabaseManager().deleteApplicationFriend(facebookUser.getId());
//if the application is currently running in the UI (not on the background) it will run a method inside the BaseActivity
if (app.isApplicationInForeground())
{
app.getCurrentActivity().onUnFriend(facebookUser);
if (isYouRemovedClient)
app.showToast(facebookUser.getName() + " has removed from your friends", true);
else
app.showToast(facebookUser.getName() + " has removed you from friends", true);
}
}
BaseActivity.java - an Activity which set all default configuration for all Activities which extends it
//in this exemple the BaseActivity method does nothing but the ListViewActivity.java method override it
public void onUnFriend(FacebookUser facebookUser)
{
}
ListViewActivity.java - extends BaseActivity and have a ListView in it which should reflect the change in the FacebookUser object property which being made in public void onUnFriend(FacebookUser facebookUser, boolean isYouRemovedClient) in ServerResponseManager.
#Override
public void onUnFriend(FacebookUser facebookUser)
{
updateView();
}
private void updateView()
{
runOnUiThread(updateViewRunnable());
}
private Runnable updateViewRunnable()
{
Runnable run = new Runnable() {
#Override
public void run() {
listArrayAdapter.notifyDataSetChanged();
}
};
return run;
}
Don't mix business logic. It looks so complicated that is hard to read.
In your service, broadcast an intent with information about update.
In Activity where ListView is, create and register BroadcastReceiver with IntentFilter for your update events.
In onReceive method of your BroadcastReceiver handle update events, for example update list.
A Service should usually independent from UI concerns. A great way to decouple services and UI related stuff is the event bus pattern. For Android, check out https://github.com/greenrobot/EventBus.
In the ServerConnectionManager, you could post an event:
EventBus.getDefault().post(new UnfriendEvent(userId));
Now register your activity to the event bus, and the event will be delivered to the activity by calling the onEvent method:
public void onEventMainThread(UnfriendEvent event) {...}
Like this, you decouple your components leading to a neat and clean software design, which is very flexible to changes.
You could use a Cursor in your ListView to display your Data.
The Service writes/updates the Data in your ContentProvider. At the End of your Database Transaction you simple use:
getContext().getContentResolver().notifyChange(PROVIDER_URI,null);
and your ListView gets updated automaticly.
Instead use
notifyDataSetChanged on onDestroy of service.
the list view will get refreshed
You can use this tutorial for proper architecture of your code
developing an app with a background service
It shows how to receive notifications from the service and update the UI.
runOnUiThread is mostly used before AsyncTask calls are made. I think you should use a handler instead (it updates the UI and allows the thread to run). Try using the handler and see what happens

Analog of startActivityForResult for Service

Despite similar question was asked, I have differnet situation:
My app consists mostly of a background Service. I want to start external activities and get results back.
I see several options:
Create dummy Activity and keep reference to it for using its startActivityForResult. This consumes quite a lot of memory, as we know.
Use Broadcast Intents instead of Android's results infrastructure: ask client activities to broadcast their results before closing. This kind of breaks the idea and not so performance-efficient.
Use Instrumentation directly - try to copy code from startActivityForResult into my Service.
Use Service interfaces - serialize and add AIDL connection to the Intent for starting an Activity. In this case Activity should call Service directly instead of providing result.
The third approach feels closer to Android for me, but I'm not sure if it's possible to do - Service does not have its Instrumentation, and default implementation seems to always return null.
Maybe you have any other ideas?
I’ve been thinking about this recently when implementing account authenticators with three-legged authorisation flows. Sending a result back to the service for processing performs better than processing it in the activity. It also provides a better separation of concerns.
It’s not that clearly documented, but Android provides an easy way to send and receive results anywhere (including services) with ResultReceiver.
I’ve found it to be a lot cleaner than passing activities around, since that always comes with the risk of leaking those activities. Additionally, calling concrete methods is less flexible.
To use ResultReceiver in a service, you’ll need to subclass it and provide a way to process the received result, usually in an inner class:
public class SomeService extends Service {
/**
* Code for a successful result, mirrors {#link Activity.RESULT_OK}.
*/
public static final int RESULT_OK = -1;
/**
* Key used in the intent extras for the result receiver.
*/
public static final String KEY_RECEIVER = "KEY_RECEIVER";
/**
* Key used in the result bundle for the message.
*/
public static final String KEY_MESSAGE = "KEY_MESSAGE";
// ...
/**
* Used by an activity to send a result back to our service.
*/
class MessageReceiver extends ResultReceiver {
public MessageReceiver() {
// Pass in a handler or null if you don't care about the thread
// on which your code is executed.
super(null);
}
/**
* Called when there's a result available.
*/
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Define and handle your own result codes
if (resultCode != RESULT_OK) {
return;
}
// Let's assume that a successful result includes a message.
String message = resultData.getString(KEY_MESSAGE);
// Now you can do something with it.
}
}
}
When you start an activity in the service, create a result receiver and pack it into the intent extras:
/**
* Starts an activity for retrieving a message.
*/
private void startMessageActivity() {
Intent intent = new Intent(this, MessageActivity.class);
// Pack the parcelable receiver into the intent extras so the
// activity can access it.
intent.putExtra(KEY_RECEIVER, new MessageReceiver());
startActivity(intent);
}
And finally, in the activity, unpack the receiver and use ResultReceiver#send(int, Bundle) to send a result back.
You can send a result at any time, but here I've chosen to do it before finishing:
public class MessageActivity extends Activity {
// ...
#Override
public void finish() {
// Unpack the receiver.
ResultReceiver receiver =
getIntent().getParcelableExtra(SomeService.KEY_RECEIVER);
Bundle resultData = new Bundle();
resultData.putString(SomeService.KEY_MESSAGE, "Hello world!");
receiver.send(SomeService.RESULT_OK, resultData);
super.finish();
}
}
I think option 2 is the most idiomatic way on android. Using startActivityForResult from an Activity is a synchronous/blocking call, i.e., the parent activity waits and does not do anything until the child is done. When working from a Service and interacting with activities your primarily doing asynchronous/non-blocking calls, i.e., the service calls out for some work to be done and then waits for a signal to tell it that it can continue.
If you are using the android local service pattern then you can have your activities acquire a reference of the Service and then call a specific function after it has performed its work. Attempting your option 3 would be counter to what the framework provides for you.

Google Analytics in Android app - dealing with multiple activities

I was pretty excited to see how easy it is to set up Google Analytics with my app, but the lack of documentation has me sitting with a few questions. The only information that I can find is right from the documentation here, which only looks at reporting PageViews and Events from one Activity. I want to report PageViews and Events across multiple Activities in my app.
Right now in the onCreate() of all of my activities, I am calling:
tracker = GoogleAnalyticsTracker.getInstance();
tracker.start("UA-xxxxxxxxx", this);
And in the onDestroy() of all of my activities:
tracker.stop();
I then track PageViews and Events as needed, and Dispatch them along with another HTTP request I am performing. But I'm not so sure this is the best way. Should I be calling start() and stop() in each activity, or should I only call start() and stop() in my main launcher activity?
The problem with calling start()/stop() in every activity (as suggested by Christian) is that it results in a new "visit" for every activity your user navigates to. If this is okay for your usage, then that's fine, however, it's not the way most people expect visits to work. For example, this would make comparing android numbers to web or iphone numbers very difficult, since a "visit" on the web and iphone maps to a session, not a page/activity.
The problem with calling start()/stop() in your Application is that it results in unexpectedly long visits, since Android makes no guarantees to terminate the application after your last activity closes. In addition, if your app does anything with notifications or services, these background tasks can start up your app and result in "phantom" visits. UPDATE: stefano properly points out that onTerminate() is never called on a real device, so there's no obvious place to put the call to stop().
The problem with calling start()/stop() in a single "main" activity (as suggested by Aurora) is that there's no guarantee that the activity will stick around for the duration that your user is using your app. If the "main" activity is destroyed (say to free up memory), your subsequent attempts to write events to GA in other activities will fail because the session has been stopped.
In addition, there's a bug in Google Analytics up through at least version 1.2 that causes it to keep a strong reference to the context you pass in to start(), preventing it from ever getting garbage collected after its destroyed. Depending on the size of your context, this can be a sizable memory leak.
The memory leak is easy enough to fix, it can be solved by calling start() using the Application instead of the activity instance itself. The docs should probably be updated to reflect this.
eg. from inside your Activity:
// Start the tracker in manual dispatch mode...
tracker.start("UA-YOUR-ACCOUNT-HERE", getApplication() );
instead of
// Start the tracker in manual dispatch mode...
tracker.start("UA-YOUR-ACCOUNT-HERE", this ); // BAD
Regarding when to call start()/stop(), you can implement a sort of manual reference counting, incrementing a count for each call to Activity.onCreate() and decrementing for each onDestroy(), then calling GoogleAnalyticsTracker.stop() when the count reaches zero.
The new EasyTracker library from Google will take care of this for you.
Alternately, if you can't subclass the EasyTracker activities, you can implement this manually yourself in your own activity base class:
public abstract class GoogleAnalyticsActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Need to do this for every activity that uses google analytics
GoogleAnalyticsSessionManager.getInstance(getApplication()).incrementActivityCount();
}
#Override
protected void onResume() {
super.onResume();
// Example of how to track a pageview event
GoogleAnalyticsTracker.getInstance().trackPageView(getClass().getSimpleName());
}
#Override
protected void onDestroy() {
super.onDestroy();
// Purge analytics so they don't hold references to this activity
GoogleAnalyticsTracker.getInstance().dispatch();
// Need to do this for every activity that uses google analytics
GoogleAnalyticsSessionManager.getInstance().decrementActivityCount();
}
}
public class GoogleAnalyticsSessionManager {
protected static GoogleAnalyticsSessionManager INSTANCE;
protected int activityCount = 0;
protected Integer dispatchIntervalSecs;
protected String apiKey;
protected Context context;
/**
* NOTE: you should use your Application context, not your Activity context, in order to avoid memory leaks.
*/
protected GoogleAnalyticsSessionManager( String apiKey, Application context ) {
this.apiKey = apiKey;
this.context = context;
}
/**
* NOTE: you should use your Application context, not your Activity context, in order to avoid memory leaks.
*/
protected GoogleAnalyticsSessionManager( String apiKey, int dispatchIntervalSecs, Application context ) {
this.apiKey = apiKey;
this.dispatchIntervalSecs = dispatchIntervalSecs;
this.context = context;
}
/**
* This should be called once in onCreate() for each of your activities that use GoogleAnalytics.
* These methods are not synchronized and don't generally need to be, so if you want to do anything
* unusual you should synchronize them yourself.
*/
public void incrementActivityCount() {
if( activityCount==0 )
if( dispatchIntervalSecs==null )
GoogleAnalyticsTracker.getInstance().start(apiKey,context);
else
GoogleAnalyticsTracker.getInstance().start(apiKey,dispatchIntervalSecs,context);
++activityCount;
}
/**
* This should be called once in onDestrkg() for each of your activities that use GoogleAnalytics.
* These methods are not synchronized and don't generally need to be, so if you want to do anything
* unusual you should synchronize them yourself.
*/
public void decrementActivityCount() {
activityCount = Math.max(activityCount-1, 0);
if( activityCount==0 )
GoogleAnalyticsTracker.getInstance().stop();
}
/**
* Get or create an instance of GoogleAnalyticsSessionManager
*/
public static GoogleAnalyticsSessionManager getInstance( Application application ) {
if( INSTANCE == null )
INSTANCE = new GoogleAnalyticsSessionManager( ... ,application);
return INSTANCE;
}
/**
* Only call this if you're sure an instance has been previously created using #getInstance(Application)
*/
public static GoogleAnalyticsSessionManager getInstance() {
return INSTANCE;
}
}
The SDK now has a external library which takes care of all of this. Its called EasyTracker. You can just import it and extend the provided Activity or ListActivity, create a string resource with your code and you are done.
The tracker will only track the activity where it's executed. So, why don't you subclass an Activity which start it every time on onCreate:
public class GAnalyticsActivity extends Activity{
public void onCreate(Bundle icicle){
super.onCreate(icile);
tracker = GoogleAnalyticsTracker.getInstance();
tracker.start("UA-xxxxxxxxx", this);
}
// same for on destroy
}
Then, you extends that class for every activity you use:
public class YourActivity extends GAnalyticsActivity{
public void onCreate(Bundle icicle){
super.onCreate(icile);
// whatever you do here you can be sure
// that the tracker has already been started
}
}
The approach I am using is to use a Bound Service (I happen to be using one already so was spared the creation of extra boiler plate code.)
A Bound Service will only last as long as there are Activities bound to it. All the activities in my app bind to this service, so it lasts only as long as the user is actively using my application - therefore very much a real 'session'.
I start the tracker with a singleton instance of Application which I have extended and added a static getInstance() method to retrieve the instance:
// Non-relevant code removed
public IBinder onBind(Intent intent) {
tracker = GoogleAnalyticsTracker.getInstance();
tracker.startNewSession(PROPERTY_ID, MyApp.getInstance());
}
public boolean onUnbind(Intent intent) {
tracker.stopSession();
}
See: http://developer.android.com/guide/topics/fundamentals/bound-services.html
I did a time based split between visits in my app, working like this:
I've build a wrapper singleton Tracker object for the GoogleAnalyticsTracker where i keep the last time something got tracked. If that time's more then x seconds i treat it as a new visit.
Of course this is only useful if you track everything in your app, and may not be the best solution in every situation, works well for my app though.
It only supports trackPageView, but setCustomVar and trackEvent should be easily implemented..
Anywhere you need to track something just add the line:
Tracker.getInstance(getApplicationContext()).trackPageView("/HelloPage");
I usually do it in the onResume of an activity
Tracker gist
You will need something like this: http://mufumbo.wordpress.com/2011/06/13/google-analytics-lags-on-android-how-to-make-it-responsive/
That's on the previous version and used to work very well. Now I'm in the same struggle as you, as V2 doesn't seems to be very consistent.
I wonder if this is something that could be done using AOP.
Android can only use compile-time AOP methods so maybe something like AspectJ?
There's a little more info on using AspectJ in Android in this thread. The main issue being that you would still need to declare on classes you own.

Categories

Resources