So, I have a bunch of activities. The flow is as follows:
Main Activity: I connect to Google Plus account here, then call Show Logs, to get data from Google account.
I also have About and Setting activities.
Now if I go to About then come back to Logs, Android throws error that GoogleApiClient is not connected. So should I again call the MainActivity for connecting else should I move all of the connection code to Common or Base Activity.
I am sorry if I am not clear enough.
If the GoogleApiClient is instantiated in the Main activity, once you leave that activity it will disconnect.
For your purposes you can try having multiple instances of the GoogleApiClient across your activities (might be inefficient) but Google's interface will not require the user to sign in multiple times for each activity. Each instance will access the same state.
You can check this post for more info
Access google plus client from multiple activities
Or have try to implement the connection in an AsyncTask that will keep running in the background.
Have a look at this link
http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html
Related
I am currently working on an messaging application for Android that communicates with other devices using Nearby Messages API. Since this is the first time that I work with this API, I would like to know if there is a pattern or strategy to handle the connections.
For instance, when the user changes the activity (e.g. opens a new conversation), I would like to keep the connection active, so I would like to work with a Connection Manager or something to keep listening and parsing the messages.
We kept working on our code, and finally we decided to implement a ConnectionManager as a single instance. This way all the activities in the application are able to access to the same methods. We also avoid to have several instances of GoogleApiClient, and then know if we are connected or not (e.g. isConnected() method).
However, we also needed in some methods the context or the activity, but we solved passing these parameters as arguments in those methods.
To sum up:
Singleton pattern: avoid creating several instances of the same GoogleApiClient
Proxy pattern: encapsulate GoogleApiClient methods in a class that handles the whole connection, instead of delegating this task on activities
I thought this would be straightforward, but I've been going in circles trying to figure out how to keep a user logged in between Activities.
I have a "Main" and a "Details" Activity. A user logs into Google Play Services in the "Main" Activity and I want to submit achievements and leaderboard data in the "Details" Activity.
I'm inheriting from BaseGameActivity in both Activities and using:
mGoogleApiClient = getApiClient();
in "Details", however when I call isConnected it always returns false.
I even tried copying all the login/callback code from the "Main" Activity over, but it's still doesn't detect the user is logged in.
This post suggests not using BaseGameActivity and pass GameHelper using a singleton:
How to use BaseGameActivity.getApiClient() in multiple activities?
Not sure what the correct approach is.
The most simple way to do this is to have both activities create a separate instance of the api client. The state of the connection is shared between them internally, so you don't need worry about how to pass around the client and handle callbacks that may happen when an activity is not active, and the player will only log in on your main activity.
Extending your activity from BaseGameActivity really is not needed any longer (for an entertaining explanation watch: Death of BasegameActivity. What you do need to do is implement the two interfaces that handle initializing the GoogleAPIClient:
public class MainActivity extends Activity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
}
To implement these, refer to the samples and the doc: https://developers.google.com/games/services/android/init
In the wonderful article by Chet Haase I read this advice which I find quite important:
never make a network request in your Application object. That object
may be created when one of the app’s Services or BroadcastReceivers is
started; hitting the network will turn code that does a local update
at a specific frequency into a regular DDoS.
The application I work on currently follows this (bad) practise: it performs a user login in Application.onCreate() - on a background thread of course, but still. This is a requirement: user needs to be logged in before any activity would do any other tasks, which usually depend on logged in user. I currently do this using RxJava in a way that any activity task observables are flatMapped onto an userlogin event and it works quite nice.
So if I should take that login task out of Application, where should it go? At first I thought it would be nice to use ActivityLifecycleCallbacks and watch for the first activity to be created. But this callback (onActivityCreated) will be called after creation, which is too late for me.
So I think that this should be done by creating some BaseActivity class and putting login and other initialization calls in it's first onCreate(). But I don't feel this is too good, because I'm mixing some app-wide logic in an activity class, it's smelly...
Anything I could have missed?
SplashActivity
An activity that starts the application. It checks for resources availability and if needed, obtains them. It also checks whether there is an active user session, and if there isn't performs a log in, if there are remembered credentials, or redirects the user to the Login/Register screen
BaseActivity
An activity that is specific for your app and that holds initialization and lifecycle callback code that is applicable for all your activities in the application.
I want to connect to Google Play Games in my MainActivity then pass my mGoogleClientApi object to my GameActivity.
How do I go about it?
Plus! Every time I start the MainActivity is reconnects to GoogleApiClient.
Anything helps.
My suggestion would be, if you need to connect to google play games in the main activity
AND in the GameActivity, that you do exactly that thing. There is no need to hand over
a clientApi instance.
I assume that your main activity is kind of a login and afterwards you start the GameActivity?
Than use the api to connect in the first place, handle the login and start the GameActivity.
There you connect to the api again and handle the game relevant part.
Or you could use fragments and hand over the api client via a public method in your activity which
implements an interface to return the client.
Play Game Services are really made with Fragments in mind. It is almost mandatory to use Fragments instead of Activities, and to have a single Activity in your app (that you can made a subclass of GameActivity...)
In the Google+ Android PlusClient documentation it states that you should be executing .connect() and .disconnect() in onStart() and onStop().
I have several activities (about 8) which stack on top of eachother in various ways, and about 4 of those activities will require the PlusClient.
My base activity (which all those activities use).. I'm thinking of putting the PlusClient logic in there.
Without knowing the inner workings of the PlusClient itself I'm not sure how heavyweight it is to run connect()/disconnect() all the time in loads of activities. This was not clear in the documentation referenced above. The connect() / disconnect() methods are doing network requests in a background thread. It seems wasteful to me for the user to be clicking through all the activities and it doing multiple network requests doing the same thing.
I guess I am comparing this to the Facebook Android API which to me seems to have a "Session" type pattern which presents itself as being more efficient.
Is this really the best pattern to adopt for an app which browses through multiple Activities a lot?
Can these methods cope with not having a connection elegantly?
PlusClient is designed to be a lightweight interface to Google Play services, see:
Access google plus client from multiple activities
Google Play services will manage an OAuth 2.0 access token for you which is roughly equivalent to a 'session'. When a specific Activity calls PlusClient.connect() and Google Play services already has an access token for the user for your app, it will immediately return in the onConnected() callback of your app.
As ianhanniballake says, any network calls needed to get the access token are carried out in the background, so they don't cause problems for your UI thread.
For an example of using PlusClient in a base activity take a look at the PhotoHunt example application:
https://github.com/googleplus/gplus-photohunt-client-android/tree/master/src/com/google/plus/samples/photohunt
connect() and disconnect() do all work in a background thread and therefore can be called in the UI thread (such as in onStart() or onStop()) without any affect on the performance of your application.
As long as you are calling connect()/disconnect() in onStart()/onStop(), respectively, the PlusClient will work on any number of Activities.