I have an app, which main feature is to track user's workouts. GPS location was working OK for past few years until this month, when strange issue appeared.
Some people (not all), using different devices and android versions experience strange behaviour of gps location. Suddenly, after at least few minutes (sometimes few hours) onLocationChanged stops being fired. Sometimes it's working fine, then next day user has this issue again.
User has to start a new workout to get it back to work. Also, in the app logs I found out that
onConnectionSuspended
is called with cause = 1 (CAUSE_SERVICE_DISCONNECTED).
According to the documentation, lost connection should automatically reconnect, but it doesn't thus causing the described issue.
In order to fix that issue, I've created an internal timer (runnable), which checks when was the last time that location was updated. If it's more than, let's say, 2 minutes, it reconnects everything like this:
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
startLocationUpdates(); //calls requestLocationUpdates
It seems to be working, at least on one's of our test user devices. Seems like a small hack to me, so let me ask you: have you experienced similar issue and do you have a better way to solve it?
By the way, I'm using:
com.google.android.gms:play-services-location:18.0.0
only thing I can think of is to restart gps receiver after not getting location for some time / start vibrating phone so user know and can restart his phone / try to register more providers not only gms. Try fused, classic GPS/network location listener.. if all of them send broadcast to some class and that class wait few seconds then prioritize the best one of those you got in time it would be great! I tried this, it worked but i need to have accuracy like 3 meters.. :D so not possible for me
Related
I'm making an app that keeps track of how many times the user uses their phone, meaning how many times they picked up/checked their phone everyday. I've searched through stackoverflow and other sites but I can't find any information that would help me implement this; any ideas? Is there a certain class I can use?
Use BroadcastService and IntentFilter to keep track of when the screen is turned on and off (ACTION_SCREEN_ON and ACTION_SCREEN_OFF). Each time the screen is turned on, increase a counter.
You could register for the ACTION_SCREEN_ON broadcast. Then just increment a counter (saved to disk just in case) each time its received. But you can't do that via the manifest, so you'd need to do it in a foreground service.
I have a class with a broadcast receiver setup. The receiver listens for the following actions:
ACTION_FOUND
ACTION_DISCOVERY_STARTED
ACTION_DISCOVERY_FINISHED
The found and started actions get emitted as expected, however, the documentation for the BluetoothAdapter specifies that a discovery scan should take ~12 seconds and is then followed by a ACTION_DISCOVERY_FINISHED. This does not seem to be the case, since I can only manually trigger an emit of the finished action by making a call to cancelDiscovery(). If I leave it running long enough, sometimes the event is emitted (but this can take upwards of 1-2 minutes). Sometimes, that doesn't even happen. If I proceed to force the scan to end, by disabling Bluetooth, the action is emitted as expected.
Is the scan supposed to take this long, and am I supposed to manually control the scanning process, i.e. ending it myself after a 12 second countdown? Or am I missing something in the docs. The broadcastreceiver is configured correctly, as evidenced by the arrival of all the actions.
After upgrading the Nexus 5 to android version 6.0.1 as well, I seem to be getting a little more consistent results with the ACTION_DISCOVERY_FINISHEDbroadcast. It also came to light that my other android phone (Xperia Z3) wasn't finding any devices as per the changes in https://developer.android.com/about/versions/marshmallow/android-6.0-changes.htm , which means that it now also requires the ACCESS_COARSE_LOCATION permission, which you need to ask for during runtime. If this is not done, the broadcast will not be received by your application. I hope someone else finds this useful.
I have a bit of a unique issue. I'm collaborating with several other Computer Science Majors at my university on an Android Metronome app that allows two users with the app to sync metronomes. Right now, I can send the desired beats per minute of the metronome from one phone to the other and both phones will start to play their respective metronomes. Due to the latency of Bluetooth, the metronomes are only in sync about 20% of the time.
So, here's where the problem is. We're trying to make it so both of the metronomes will start at the exact same time. One way I've thought of doing this is once the first user presses the send button on their phone, a time stamp will be created. This time stamp will be exactly two seconds after the user presses the send button. The time stamp will then be sent to the second phone and the phone will utilize this time stamp to start it's metronome at the same exact time as the first phone. I've tried accomplishing this by putting UTC time in a while loop and then constantly checking the time, to no avail. Does anyone have any ideas as to how we can go about implementing this? I couldn't find any similar problem on StackOverflow, or any other website for that matter.
It's a bit late probably for your project, but if interested. This is a bit long, it's more like a case study.
If your project was about syncing two device clocks remotely, then this won't help you, but if it was about syncing the metronomes, then this may be a start.
First, getting millisecond accurate timings and callbacks in android using java is next to impossible, since android is not a real time system ( All sleep methods and timer might not execute on the exact millisecond you're expecting ). You may want to go with NDK for triggering your beat events, because native threads in android can achieve that, but if you're happy with your single metronome implementation, then that's good enough to read the rest of this .
Full disclosure :
I am the author of JAM the app referenced in the answer I just published a few days ago.
I ran into the same problem when developing the app.
And whether this answer will help you or not, depending on your situation.
and if you're going down the "clock sync" route ( Which I do plan on exploring to improve my app down the road with more features ) but the solution that I found did not involves time sync.
I will mention my approach and then state what I found as advantages/disadvantages for each of the methods .
Instead of syncing clocks ( A very difficult problem, especially for what the app was supposed to do , and that is trigger ticks on multiple devices at the "same" time ) I opted for a subscribe/publish model, where multiple devices can "subscribe" to a host device via bluetooth, and the host device controls and "publishes" the metronome beats.
most times sending a few hundred bytes ( Enough information about each beat ) via bluetooth takes less than 2ms , it could spike up to 10 and sometimes even 30, but that rarely seems to happen .
That approach took care of the syncing problem, now I can send beat events from one device to another in 2ms , and if some sort of delay happened, it will self correct once the interference is gone, because the other event comes in time.
However that approach does require constant connection, you can't start and separate the devices later on, but it's much easier to implement.
Now the interesting part, the problem I never thought of when starting this, and that was the Android 10 millisecond audio path latency problem. I'm not affiliated with superpowered, but I did use their engine in my app to deal with that problem .
To summarize :
Metronome sync over bluetooth in Android has two issues :
1 - triggering beat events simultaneously ( or within acceptable latency )
2 - The beat event should trigger sound events with minimal delay after the beat event is received
#1 is related to the original question, #2 I thought was an important addition to the original problem this question is asking.
I would use (S)NTP to check the clock drift to a public time server. After that I would just send the interval and a start time and let the devices calculate the interval individually. So you just need to sync changes and relay on the clocks of the individual devices. Together with the now known clock drift you can fix this error.
My app is basically is a schedule app, where I'd like to show notifications x minutes before an (user-set) event occurs.
I read the documentation, but it only covers showing a notification at the time the notification code is being executed (which I guess is the only way).
My guess is that if I want to have notifications show up even when my app is closed, I need to somehow make the app run in the background and constantly check for upcoming events, calculate the time left, and show a notification when the time left equals the time before the event the user chose to be notified at.
I read this question (+answers): How to get android notifications when app was closed?.
There is a pretty detailed answer (using services) I could simply implement, but the other answer claims this approach is "crappy".
The second answer also suggest the usage of AlarmManager which, after reading the doc, doesn't sound that bad (executing code at a specific time).
However, since I'm targeting API19 it's "inexact" (according to the doc).
So what exactly is the most efficient (and the right) way to do this?
You need to implement alarm manager with service. Set the time user chose and show notification at that time. The sample shows a Toast, you can use notification/sound/dialog, anything.
Check out this sample.
Ever played Candy Crush? Know how you run out of lives and have to wait 30 minutes to regenerate a new life and up to a maximum of 5? That is idea I am trying to implement in my app but I am uncertain on how to have code running even when the user closes app and/or phone.
My question is how to have a timer constantly running in the background of phone until the timer hits X minutes. Would I use the Timer class for this? Because I am familiar with that class and already have a form of it implemented in my app.
There are two pieces to your question:
To actually have a timer running so that you have an action taken after a certain period of time, use the AlarmManager. This should only be used if you are going to proactively interrupt or notify the user.
Your scenario doesn't actually need a timer, and it's more efficient not to use one unnecessarily. Instead, store a timestamp. When your app is opened again, compare the current time to the timestamp and calculate the effect. In the regenerating-lives example, you'd compare timestamps, see that 100 minutes have passed, divide by 30 minutes, and add 3 lives (maybe keeping the extra 10 minute remainder).
If you want timer to run in background you may use AlarmManager. You can set Alarm at specified intervals or you can set it in service if you want single shot alarms. Also while using AlarmManager beware that if your phone goes down then all alarms you've set will be vanished. So take care that you are saving alarm times before phone goes off. Take a look at:
http://developer.android.com/reference/android/app/AlarmManager.html
While using AlarmManager, use correct PendingIntent flags or you could lose previous alarms. If you still want more information you can raise here or have a google.
I don't think you can keep a timer running for you application even when the application is closed. Here is an idea i think about:
You need to start a timer when the life is gone and your application is running.
On your application close event, save that timer value in a persistent storage such as file
On appliction start, read the timer value from the persistent storage, and restart the timer for the remaining time
Once timer expires, generate a new life.
Hope it helps!
I found this answer that might be of great help. Hope it helps others.
There are several different approaches.
You can make use of the System's AlarmManager.
You can make your own Service.
You can make your TimerObject persist.
Check the link for the complete answer and links.