I am writing my first Android app and I am running into what I thought would be a simple issue. I am trying to get the temperature of the device (using the 2.1 APIs). I have followed this example.
If the temperature changes, the app updates as expected. If the device is sitting on my desk, the temperature does not change and I never get an onSensorChanged() callback.
Although this sounds right (i.e. the sensor didn't change, so no update), I can't figure out how to get the current temperature when the app starts out. I was hoping that onSensorChanged() would be called when the app starts, but that is not the case.
Is there some API I have missed? I can't believe that there is no way to display the temperature until it changes.
Thank you.
Related
How does one monitor location in the background on Android these days?
We were using a foreground service to do this but with the changes in Android 12 and 13 this does not seem like the right way to achieve continuous location updates and seems like we are getting crashes. Fatal Exception: android.app.ForegroundServiceStartNotAllowedException: startForegroundService() not allowed due to mAllowStartForeground false:
Our use case is:
app integrates with a bluetooth speaker and when a button is pressed on the speaker an event is triggered in the app. The app calculates a distance and sends that back to the speaker to be announced. We are calculating the position between the phone and another known location (LatLng). So we need to keep track of the users current position in order to calculate the distance at any point in time. A user could be doing this for a couple hours without opening their phone.
I have been trying to find good resources on how to monitor location in the background but is a bit tricky to find any resources that take into account the recent changes from the OS and newer Android APIs.
It seems like WorkManager would be an appropriate solution but I am not sure about hitting work restrictions when trying to monitor location for an extended time.
Any and all help / resources appreciated.
I have a small test App that with an Android GPS API map fragment. I use FusedLocationProvider. TarketSDK=29. Using Java.
As long as the app is active it works beautifully. On locationUpdates, I add a new point to the track and everything looks great and stays accurate. The goal is to track my hike, total distance and track and show it on the map. Works great.
As soon I lock my phone or loses focus, then the updates stop and I no longer get location updates.
Solution seems to be:
Background Service (discouraged)
Foreground Service
PendingIntent
I have poured over the docs, StackOverflow, all examples/tutorials I can find, developer.android.com, etc. I have downloaded examples of the latter 2 from GitHub; they seem incredibly obtuse (probably just me).
What are the dis/advantages of ForegroundService vs PendingIntent?
How about a bare-bones example illustrating the min features of each to implement location updates while your phone is locked in your pocket or some other app is active? Just the template minimum.
I need to save the locationUpdates that occur while my app is not active or phone is locked; in order to fill in Track when activity is restored to the app.
Some simple end-to-end guidance from my working app to something that will maintain locationUpdates and save the data would be great.
Ok - I have answered my question in a roundabout way.
I had been Searching on "retrieving location updates when app is not active". This lead to the various solutions of background service, foreground service, pendingIntents, etc.
I eventually found that if you just start a Foreground Service with a Notification, even if your phone is locked or you switch active apps, your App continues to receive LocationUpdates; as the Foreground Service runs in the same thread and therefore activates your app code (if I understand the reasons why correctly).
So, I started searching on just how to start a Foreground Service. As anyone knows that has tried to figure this out lately, this has changed more than a couple times over recent versions. The online docs at developer.android.com are not up to date. You will spend a lot of time wondering why things do not work following these docs.
Eventually, with just searching on how to start a foreground service, I came across this simple and straightforward (non-youtube-video - don't you just hate those things) tutorial. https://androidwave.com/foreground-service-android-example/
I just added this code to my existing Mapping code that works when the app is active, and tested with locking the phone and putting it in my pocket and switching apps and doing the same. It appears to solve the problem.
Update: Added code to count number of location updates and average accuracy of each update holding the phone in hand, screen on and app active as the baseline. Phone locked, or App not active no difference in number of updates nor accuracy. Phone locked and in pocket, no difference in number of updates, but accuracy suffered by from an average of 10m to an average of 13m; to be expected I assume whilst in the pocket.
I managed to get the heart rate sensor and it is working, with some exceptions.
I start the measurement on click, and when there is at least one result with accuracy >= LOW I stop the measurement (by unregistering the listener).
This sequence works 1-2 times, and then it just do not return a value with accuracy >= LOW. I am waiting a few minutes before I give up and close the application. But after opening the app again, most often it works the first 1-2 measurements and then it stops working with the same issue. (but other times it needs a lot of re-launches of the app in order to start giving some results)
Another issue is that if I start the measurement when the watch is not on my wrist/skin but lets say it is floating in the air, then even if I put it on my hand and wait a few minutes it doesn't start giving any valid/accurate value.
Have anybody observed similar behaviour? Is there any specific sequence that needs to be done in order for the sensor to provide more reliable data? Maybe a calibration can be done somehow to make the sensor more sensitive about my skin type or something?
I've run into an issue trying to create an application that keeps track of Proximity Sensor values. The intent of the application is to record the instantaneous proximity value on regular intervals (say 30 seconds).
Following the API Documentation, the standard listener is created and attached for that type of sensor. However, the value is ALWAYS reported as '5.0' (5cm, the max value of the sensor) even when I cover the sensor with my hand.
However, if I start a DIFFERENT application (that also monitors Proximity sensor values) both applications start to correctly report proximity. When I close the other application (Android Sensor Box) my application reverts to just reporting 5.0 all the time.
I have debugged the application and set a breakpoint in the 'onSensorChanged' event to double-check what SensorEvent object is being passed to the onSensorChanged method, and it's always 5.0
EDIT #2: It doesn't appear to be limited to the Proximity sensor. The Gyroscope sensor behaves in the same manner while Accelerometer and Magnetometer appear to show the correct and up-to-date values. All four are referenced and accessed in the same fashion.
Any ideas?
Well, it turns out that I will once again be answering my own question.
The way the application was structured (and there was a good reason for this) meant that a Listener was registered and the first reported value from the sensor(s) was taken as the reading without continuously accepting new readouts. This works fine for Accelerometer readings but it turned out that some sensors reported their DEFAULT value in this first reading (such as 'FAR' for the proximity sensor or 0.0/0.0/0.0 for the Gyroscope). It was only after 2-3 'onSensorChanged' events that correct values start to be reported.
I am assuming this has something to do with power saving and certain sensors needing time to become 'ready' to report data. I have no idea why the acceptable practice is to fire off a sensorChanged event with incorrect values but that's what appears to be happening.
Nonetheless, the fix for me was to discard the first 2-3 readings (they come in at millisecond intervals anyway) and simply use the fourth one as the more reliable reading.
Let me summarize my problem and what I would like to achieve.
I have a SonyEricsson X10i phone with Android 2.3.3. I realized that sometimes my phone not receiving calls even if it indicating full coverage. I checked myself in the MSC/VLR and it indicates that I registered and my phone is currently active (and also there is no IMSI DETACH flag), so it should working correctly (only the last Activate Date is a little bit old ~couple of hours, which can be good as well, without SMS/Call/Location Update), as I mentioned before the phone indicates full coverage and it seems it’s on the network. But when I tried to call it I only reached the Voice Mail.
In the MSC/VLR I see No Paging Response Cause for the call, but the phone does nothing. I tried with other SW version (4.0.3 ICS), but the same result. But I not noticed similar behaviour with a different handset (same type).
Sorry for the long summary.
So because what I described above, I ‘m trying to write an application/service which will perform GSM/UMTS location update in 15-20 minutes, but I couldn’t find any kind of procedure in android.telephony.gsm.GsmCellLocation, android.telephony.TelephonyManager which will do this for me.
My other concern is the
getState()/setStateOutOfService()/ setState() procedures from ServiceState class…
It seems they not really working. For example, when I first call the getState() I always get back STATE_OUT_OF_SERVICE, which is not true…
When I’m set the state to STATE_POWER_OFF or STATE_IN_SERVICE, at least I get back that state from getState() afterwards, but the phone does nothing for that . (Not even indicate out of coverage,etc…)
Every suggestion/comment are welcome.
I have also seen this problem many times (2 phones from the same manufacturer as yours). From your question, I understand that you want to force the phone to send an MM periodic location update (which it should be sending anyway).
This is too low level, and there's nowhere you can force this directly in the programming interface. The mobility management procedure is part of the phone stack, and is specified in detail in 3GPP TS 24.008, available from www.3gpp.org. Paragraph 4.2.2 defines when the phone is supposed to send these location updates.
The only other thing would be to try by indirect means to force the phone into a condition where it would send a location update. You might be able to do that by trying to select another network manually. If it's successful, and you then manually re-select your home network, then you would trigger a location update. If it's rejected and falls back to its home network, then I think a location update would be triggered as well.
But there would also be small costs to this - battery use while it does a networks scan, and time lost while it scans and does manual network selection.
(My personal experience is that the lost calls don't happen often enough to justify this.)