How Can I call startIntentSenderForResult in Service properly? - android

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.

Related

For ActivityResultContracts, what is the alternative for In-App Updates?

I am restructuring my code to use ActivityResultContracts, and I've been able to recreate the old way of doing things with onActivityResult by passing in "codes" with my Intents and just passing them back from the called activity. Everything is working fine, but how would I manage to do that with App Updates, even the Google documentation is still using onActivityResult to check for app updates.
After looking at it for the past few days, it does not seem like it is possible to forgo using onActivityResult; the cancel response is only returned to that method. If you have a listener setup to check for resumed downloads, you will get a response there (as onResume is called when the calling activity is moved back to the foreground) but you only get that an update is available and the install status is unknown (which coincidentally is the same value as cancelled, and you can't do anything there as you get the same values on the initial call to check for an update). I don't see the point in deprecating a method you're still required to use, but oh well.

How to get results via BroadcastReceiver from a given IntentSender

I know how to do the following
Get results of a PendingIntent via a BroadcastReceiver (e.g. launching a chooser and getting the results after the user makes a choice)
Get results of an IntentSender via an activity's onActivityResult by calling startIntentSenderForResult
However, what I need to do is launch the IntentSender but get the results back via a BroadcastReceiver. Note that IntentSender is given to me, so I have no access to the original PendingIntent corresponding to the IntentSender.
Is there a way to do this, perhaps by bundling additional intents to intentSender.sendIntent()?
I have also read this question and have verified that the onFinished callback in sendIntent() fires right away and doesn't actually return the results of the intent being launched.
Context
I'm doing companion device pairing using Android's CompanionDeviceManager. When it finds a device, it gives me IntentSender chooserLauncher. It expects an activity to call startIntentSenderForResult() with chooserLauncher and get the results back from the activity. However, this does not work for me because I'm developing a library and I don't want the results delivered to the activity, but rather to a BroadcastReceiver that I own.
That is not possible.
Only an Activity can call startActivityForResult() and that will launch an Activity. The result can only be returned to an Activity in onActivityResult(). There is no way to have the result be returned directly to a BroadcastReceiver. It doesn't work that way.
You would have to have the user of your library receive the result in his Activity.onActivityResult() and pass it to your library via whatever means you can provide.

Android: How do I call startResolutionForResult from a Service?

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

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.

Passing data from receiver to activity

I am really stuck. After test lots of different approaches. I'm asking this question.
I'm trying to make an app which should alert the users at the specific date and time, like lots of other apps that you have definitely seen before. I'm using BroadcastReceiver as it should. I register it in manifest to activate it the first time the app gets installed and after restarting the phone but the problem is in android 3.1- taskkillers can kill this receiver so I thought it would be better to activate it again each time the app gets opened but The problem is that I don't know how many instance I'm creating so the first question is:
How to get the active receiver?
so I can make a decision upon it. If it is not active so I can active it again.
What I'm doing within onReceive is: getting data from database and comparing the time and date to now. If the app is not open I want to notify the user in notification area and pass extra data to the app' which is working pretty well. But if the app is open I do not want to notify the user in notification area, instead I want to pass data to an activity and alert the user in my app. I made my activity singleTask and used startActivity to pass data to the activity also I used onNewIntent method to handle new data but the problem is what if the user is using another activity. The second and third questions are:
How to know if my app is open? (I used ActivityManager.getRunningTasks but I realized it is not a good solution because it is an api for Task Manger apps.)
how to pass data from receiver to my activity? (I used interface to pass data from fragment to activity so I thought it can be used here but it does not work here)
After a lot of exertion -Reading and Trying- I know i'm still doing wrong So please guide me.
I suggest that you start a ServiceIntent from the Broadcast reciever. and from there you can send an intent that you can catch in the activity
Okay no one answered my question but I got it myself so here is my own answer:
Every receiver has only one instance and you can just enable or disable it. So to ensure that it is working you can enable it in your activity every time it gets run.
Within onReceive instead of doing stuff there, start a service and in your activity bind the activity with this service so in onBind and onUnbind method you can change a Boolean value and make decision upon it. In onBind make the value True which means your app is open and vice versa in onUnBind.
And finally the best way to pass data from service to activity is using Interface.
Now my app is working just like I want. . Hope to be helpful and save someone's time.

Categories

Resources