Android: How do I call startResolutionForResult from a Service? - android

I'm trying to add GPS tracking functionality to my app by writing a GPS tracking Service. I've been following the Android Developer materials on how to do this via Google Play Services, but I'm stuck on the onConnectionFailed method. I'm trying to call startResolutionForResult to let Google Play Services handle the error. However this method requires that an activity be passed in as the first parameter, and since I'm calling it from a Service I'm not really sure what I should do.
I assume that I'm going about this all wrong and there's a completely different way to handle this from a service.

The authentication process for Google Play Services needs an activity since it may need to display UI to the user. Since services don't have UI, you need to send a message to an activity to set up the connection, then the service can continue. There is a good answer demonstrating one way to do this here: Example: Communication between Activity and Service using Messaging

You can use Status.getResolution() and start Activity with it. For example:
In Service
PendingIntent pI = status.getResolution();
mGoogleApiClient.getContext().startActivity(new Intent(mGoogleApiClient.getContext(), SomeActivity.class)
.putExtra("resolution", pI).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
In Activity onCreate:
PendingIntent pI = (PendingIntent) (getIntent().getParcelableExtra("resolution"));
startIntentSenderForResult(pI.getIntentSender(),1,null,0,0,0);
also add onActivityResult(int requestCode, int resultCode, Intent data) to receive result of resolution

Related

How to get info from a Google API during a widget's onUpdate function?

I'm trying to make an android widget that shows information from a Google API, specifically the Fitness API. Right now, the Fitness API client (GoogleAPIClient object) is set up in the Main activity as a public static variable, and the onUpdate function grabs it, calls .connect(), then attempts to get information from that API. It works, but only when the app's main activity is active - If I close it, then the next time the app updates, it crashes with the error:
java.lang.RuntimeException: Unable to start receiver
Caused by: java.lang.NullPointerException
At the .connect() call in the onUpdate() function.
Is there a proper way to do this that I'm missing? How do I make it so that I can get the information every time onUpdate is called, but still handle the onConnectionFailed call - I have to start the resolution to the failed connection (usually just giving the app permissions or specifying an account) within an enclosing activity, and the AppWidgetProvider is not an activity, so I can't just put the client object in the Provider, which was my first thought.
Can I put the client inside the Provider, then launch a new activity to pass into the call to startResolutionForResult call during onConnectionFailed? If so, how would I start that intent so that it counts as an "enclosing class" - that was the error I got when I tried to put the Provider in as an argument for startResolutionForResult.
I'm new to both widgets and Google APIs, and still sort of a beginner to Android development in general though much more experienced with that than with widgets of APIs. Thanks for any help.
Is there a proper way to do this that I'm missing?
Have onUpdate() delegate work to a Service by calling startService(). Have that service talk to the Fit API. When the Service gets the results from the Fit API, it updates the app widget using AppWidgetManager, then calls stopSelf() as the Service is no longer needed.

How Can I call startIntentSenderForResult in Service properly?

I'm working on a Service which gets a location and I'm using Google Play Services for it.
According to http://developer.android.com/reference/com/google/android/gms/common/ConnectionResult.html#hasResolution%28%29, if hasResolution() returns true, calling startResolutionForResult may resolve an error. But it needs an Activity as first parameter.
Of course ConnectionResult returns a PendingIntent by getResolution() but the Service doesn't have a startIntentSenderForResult() like an Activity.
As far as I know, there is no way to get a result back in a Service.
How can I get a result in the Service? Or is there another proper way?
Edit:
Google Play Service SDK provides GooglePlayServicesUtil.showErrorNotification for background tasks. Of course accepted answer is good solution.
Edit 2:
showErrorNotification is only for a return value of isGooglePlayServicesAvailable.
I would proceed this way:
Show a notification indicating that there is a problem doing task X
(actually, interacting with Google Play Services, but you may say something else
more specific to your app).
For this notification, provide a PendingIntent that starts your activity. As part of the extras for this PendingIntent, pass the PendingIntent provided by ConnectionResult.getResolution(). PendingIntents are parcelable so this shouldn't pose a problem.
In onCreate() for this Activity, obtain the original PendingIntent from the extras, then call startIntentSenderForResult() with it. This will automatically redirect the user to wherever Google Play Services needed him to go (possibly log-in?)
Then, in onActivityResult(), finish the activity, having first notified your service (via an Intent) that the problem is resolved (or not). The transient activity will have been invisible to the user.
I admit this solution is theoretical, but it should work.

how to retrieve the result code from a PendingIntent starting a service?

I have provide two objects of type PendingIntent to be passed to SmsManager.sendDataSms(). These two pendingIntents are used to trigger a service at a later time.
According to documentation:
this PendingIntent is
broadcast when the message is successfully
sent, or failed. The result code will be
Activity.RESULT_OK
The question is how can I retrieve this 'result code' inside my service?
Basically, except for Activity (through onActivityResult() or something), none of the application components has a mean to retrieve this 'result code' passed to different variations of PendingIntent.send().
First of all, at least in my head, a resultCode for service would not make much sense as it i suppose to be a self contained process. Again, that is just my perspective.
Secondly, the documentation of the getResultCode() for BroadcastReceiver says:
Retrieve the current result code, as set by the previous receiver.
which implies a dependency to an earlier receiver that Services does not have.
As I suggest in the comments to the question, I think the way to go would be to register a BroadcastReceiver inside the Service.
A final note to your comment:
However, I (and I'm sure lots of other people) still wanna know if there's a way of retrieving the result code from inside a service or not. If not, whay such a thing hasn't been explicitely mentioned in documentation?
The fact that the documentation does not state that you can get a resultCode in a Service is a good indication that it is not possible. Furthermore, it is fairly uncommon to document explicitly what some code cannot do.
I think you would retrieve the result code in the BroadcastReceiver and put it in a extra int or something in the intent and send it to the service through the startService.

android application design

I have to develop an application where i have to continuously collect the GPS, accelerometer data [esp. when user is in motion i.e traveling, else it can be relaxed). Also I have to communicate with web server and handle the response from the sever. So for this(handling response ) part application should continuously poll.
Based on response from server I have show UI to the user.
I am not very clear about the design.
Do I have to create activity from where I start service. Should service be ran as a separate thread(this always runs in background).
I am planning to create two services. One service to continuously collect GPS data.
Other service for communicating with the web server[start timer/alarm manager] for polling.
ALso can these two services communicate with each other.
Also after processing the response frm server the service should be able to start user interface to show some form. I am not clear how to handle this.
Also is acquiring wakelock required if I have to collect GPS data continuously.
Please clarify.
Thanks
You can use an AlarmManager for polling. You just need to set the interval. You will notice that most components Application, Service, Activity all are Contexts. So they all can get Application Context. The way to think about communication is that the android message/event is essentially the Intent. So you define your custom Intents. You just need to give them a custom name for the action. Then you use Intent filters. You can do point to point messaging by doing startService, startActivity or you can broadcast the intent. I would recommend that you communicate via broadcasted intents. Message routing is handled using Intent filters. Starting form etc would just be a startActivity(Intent) and the Intent itself could contain using intent.getExtras(). Just so long as you can put it in the Bundle you can pass it and display. So to answer your question, just use Intents for everything. Use broadcasting and filtering for communication and Intents again to start your activity for display.
The May 10th Google I/O had an afternoon session called Android Pro Tips. The first section covered several different approaches to making your app more continuously location aware.

Android and RESTful services

In Virgil Dobjanschi talk during Google I/O he mentioned using Services for doing the fetching and then using a callback to notify the Activity when this was completed. He never went into specifics on how to implement this callback and I can't seem to find anything helpful on this topic anywhere.
I think he said that you didn't need to implement binding at all?
Any clues?
Option #1: Service sends a broadcast Intent, which the Activity catches via a BroadcastReceiver registered via registerReceiver().
Option #2: If the Activity is binding to the Service, have the Activity pass a listener to the Service, which the Service invokes when the work is complete.
Option #3: Service doesn't do much, but the ContentProvider calls notifyChange() when the data changes, which can ripple back through to the Activity and/or its Cursor on the data.
Option #4: Singletons, which should be avoided.
...
Option #237: Service sends a letter via FedEx to the Activity. :-)
...
All that being said, once they release the Twitter app as open source, you'll know for certain what the Twitter app does.
Check out the Google I/O 2010 app. It uses the pattern he was referring to. It uses Option #2 from CommonsWare's answer.
i think they're talking ab out using AIDL to communicate between the activity & the service...

Categories

Resources