startScan() in WifiManager deprecated in Android P - java

How to get scan result from wifi for example every 3 seconds, without mWifimanager.startScan();
Google says :
startScan()
This method was deprecated in API level P. The ability for apps to trigger scan requests will be removed in a future release.
Notice for this API level i'm using
List<ScanResult> results = mWifiManager.getScanResults(); without calling startScan , the list contains the wifi AP's but it makes updated very very slow
Update to 12 January 2019 : https://issuetracker.google.com/issues/112688545

Google has now documented the limitations for startScan() function in Android P:
"We are further limiting the number of scans apps can request to improve network performance and improve battery life.
The WifiManager.startScan() usage is limited to:
- Each foreground app is restricted to 4 scans every 2 minutes.
- All background apps combined are restricted to one scan every 30 minutes."
Source:
https://issuetracker.google.com/issues/79906367
Edit 8-Aug-2018: Information has been added also here:
https://developer.android.com/guide/topics/connectivity/wifi-scan#wifi-scan-throttling

I think in API level P they're planning to move startScan() to a different class (WifiScanner) all together with some key differences.
See: https://android.googlesource.com/platform/frameworks/base/+/android-p-preview-1/wifi/java/android/net/wifi/WifiScanner.java
If there's an alternative solution to this, I'd love to hear it as well.
For now, I might just use startScan() until official docs are released.

startScan() is actually pretty buggy on P, as I raised Google Issue 79906367.
I don't think that WifiScanner is the replacement either, as that is marked as a SystemApi which means no access for Apps...
Hopefully we will hear soon, as RTT still means you need to scan for APs which support 802.11mc using ScanResult is80211mcResponder which you check before performing RTT Ranging on the AP.

StartScan() method is deprecated in Android P and new RTT protocol from 802.11mc standard has to be used with trilateration Algorithms.
https://android-developers.googleblog.com/2018/03/previewing-android-p.html
X,Y position of the AP should to be knonw for accurate positioning and the AP should support 802.11mc's Fine Time Measurement. IntelĀ® Wireless-AC 9260 support 802.11mc and several APs start supporting 802.11mc standard.
A couple of examples:
https://medium.com/#rafaelmiguel.ortega/android-p-first-taste-of-rtt-support-febefb679775
https://medium.com/#plinzen/perform-wifi-round-trip-time-measurements-with-android-p-9ffc5277ac6a

From WifiManager#EXTRA_RESULTS_UPDATED
Note: Apps holding android.Manifest.permission.NETWORK_SETTINGS permission are exempted from scan throttling.
Note: This is a system permission, regular apps can't use it without rooting and moving the app to the 'privileged' location or having it baked into a custom ROM.

I would guess the intention is to have developers/users use WifiRttManager instead for indoor location atleast [1].
Or rely on usual Google Play location services, which is an option in some use cases, but definitely not all. It's optimised for the average use case. No use case is the average use case.
Unfortunately with the way WifiRttManager calculates location it requires the wifi accesspoints to have 802.11mc. However you don't need to connect to these points.
Virtually 0 routers today have this standard. [2] [3] [4]
With 3 access points you can get location close to 1-2m accuracy.
Who knows if they'll place restrictions on this functionality as well though.
I'm not happy that this functionality is being taken away from users and developers - all it needs is a permission.
So it appears there will be a dark age for indoor location over the next few years until 802.11mc is popular.
Perhaps a workaround is to have devices you are connected to and ping them.
[1] https://developer.android.com/reference/android/net/wifi/rtt/WifiRttManager
[2] https://github.com/Plinzen/android-rttmanager-sample
Additional reading
[3] https://en.wikipedia.org/wiki/IEEE_802.11mc
[4] https://fit-iot.com/web/wifi-indoor-positioning/

I think google is planning to restrict application from scanning wifi.
This method was deprecated in API level 28. The ability for apps to
trigger scan requests will be removed in a future release.
Check the documentation here.

Related

What are the minimum permissions I need to get incoming phone number and call history for that number for API > 29 and API < 29 for Android app?

I am looking to access the following functionalities for my Android App:
DONE Detect states of incoming call (achieved via EXTRA_STATE, see below for more info)
Get incoming number (do not know how for API > 29, see below)
Get history for the incoming number (this is optional since my app could build the phone history since I only need it for short term for this stage so I could technically build it in my app if I cannot easily access Missed/Answered call log for that number only.
From research, I found that for older versions I could simply use
intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
And I would get the number but it does not work for API > 29 (number comes out as null for API = 29 because it is deprecated in API level 29.). Also, I am not sure what is the easiest way to get the history for that number only.
I could use inCallService and Google suggests to create the Default Phone App which could be then default call app and gives me all the required permissions. However, my app does not need all those permissions and ideally it should not be a full blown call app, and it would be only a feature that would work on top of a default app therefore I am looking for alternative that would require the least amounts of permissions that Google would actually grant me.
I also ask user for PHONE_CALL_STATE in order to get PHONE_STATE via EXTRA_STATE which only allows me to know when call started, ended, answered and missed. But I need a number itself and some history of missed/answered calls as well for different API's.
Any help will be greatly appreciated.
According to the docs, EXTRA_INCOMING_NUMBER is provided if the receiver app has the READ_CALL_LOG (in addition to the READ_PHONE_STATE permission).
Once you add that READ_CALL_LOG, you'll notice your app will start receiving that broadcast twice, once with getString(EXTRA_INCOMING_NUMBER) returning null, and another with getString(EXTRA_INCOMING_NUMBER) containing the actual number.
See docs note here.
Notes:
The order of the 2 broadcasts is not guaranteed, so if you get 2 broadcasts, where one has EXTRA_INCOMING_NUMBER = null, you can ignore that one.
EXTRA_INCOMING_NUMBER is only received on incoming calls, there's no way to get the number of an outgoing call
That extra is indeed deprecated on API >= 29, but that only means your targetSdk (in your gradle file) should be < 29 for it to work.

How can I use Google Places API multiple times in a location aware app?

I am developing an app which will give you nearby Mosques within 10 km of your current location. Now that the Places API allows a certain number of queries per day, I have used firebase to store nearby Mosques for a certain location and I first check if the data is in database or not before querying. But this still doesn't solve the problem. e.g. if a user is on the go the whole day then the results must be changing every single minute, according to his/her location. How can I achieve the desirable results?
As mentioned earlier, I am saving nearby locations in a database with their relative location (around which they exist). But this doesn't quite solve the problem.
Any help will be greatly appreciated.
Places API is a commercial offering - you are meant to pay for using it, if you want to make applications around it.
There's a certain small number of calls that you can do for free, but this is only meant as testing grounds or private use. I am no lawyer, but I would guess that circumventing the fee by scraping the map (like setting a bot to go around a country to build a database of points of interests) would be illegal and would probably get you a letter from Google saying you should stop.
Use AutocompleteSessionToken class to generate a token and place it after your key , this token will reduce your usage because you can request the places api multiple times and still it will be considered as a single request. i hope this will help cause i didnt get your question very well. here is sample of the link:
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=1600+Amphitheatre&key=&sessiontoken=1234567890.
For more details.see here

How to get the WiFi noise level in Android?

I want to implement an app which measures the quality of the WiFi signal from an indoor environment. From my research I found that the best way to get an accurate measurement is not to get only the RSSI but instead to use the SNR (Signal to Noise Ratio).
How can I obtain the noise level from the Android SDK? As I heard, there is no API available for this. However, I've found a method which provides the SNR (getEvdoSnr()). Unfortunately, this one works only for a GSM/CDMA signal and not for a WiFi connection.
Is anything possible to calculate the SNR in Android? I believe that's doable because I've found an app on Play store (called WiFi SNR) which successfully measures this ratio.
NOTE: The Android ScanResult doesn't provide the noise level, even if it's specified in the official documentation:
Describes information about a detected access point. In addition to the attributes described here, the supplicant keeps track of quality, noise, and maxbitrate attributes, but does not currently report them to external clients.
Use https://developer.android.com/reference/android/net/wifi/ScanResult.html.
Describes information about a detected access point. In addition to the attributes described here, the supplicant keeps track of quality, noise, and maxbitrate attributes, but does not currently report them to external clients.
I bet something like this will give to you desired information:
WifiManager manager = (WifiManager) getApplication().getSystemService(Context.WIFI_SERVICE);
for (ScanResult result : wifiManager.getScanResults()) {
// do your stuff
}

How should I manage Bluetooth connections in Android?

Q. What are your best practices in managing bluetooth connectivity?
I've read the android bluetooth guide & many bluetooth connectivity tutorials. Not helpful with encapsulation-design nor best practices.
When should I open/close the connection?
Is the "connection" with a single bluetooth device called a "socket" connection?
Can a single connection send data while listening? (...or between listening states).
I've never coded connectivity with external devices before. It took two weeks for me to wrap my head around the code that scans for near-by bluetooth devices and throw them into a ListView. Listeners, Broadcasts, and Adapters!
My project will be printing 1-40 receipts every 15 minutes on a bluetooth receipt printer. At the moment, security is not an issue. On the same connection, it will also be receiving data (sending & receiving simultaneously does not appear to be necessary but would be useful). I'm not yet sure how the devices are configured on this single dongle device but I would guess the devices are connected via USB controller to the dongle.
So far, I have 1 object to manage a single I/O connection. Staticly I open an activity to select a connection (to later save the label, mac, and pin in the database). Based on tutorials, I have "open", "listen", "send", and "close" methods. What confuses me is "how" to use these functions. Can I leave a connection open all day (10hrs) and use it every 3mins? Should I open/close the connection when sending or requesting data? Where would I detect the need to reconnect?
sorry for the short answer, but from my practice with the Bluetooth API, I have found that this video describe the things very good (totally personal opinion...)
Video 1
In addition this is useful when you do NOT have any previous experience
Tutorial
And as last check out this question in stackoverflow it has a bunch of good references and examples!!
Again sorry for the shortage, but I believe that if you check these out at least most of your questions and concerns will become answered!
:)
EDIT
So, let me be a bit more descriptive and share some of my experience.
I have written an App that communicates with BLE device that has 3 functions
double sided event driven button (push the button on phone -> event is fired to the device; push the button on the BLE device -> event is fired to the phone)
send request from phone -> BLE device answers with current battery percentage
continuously reading strength signal (as aprox. distance) between the phone and the BLE device
So far so good, now the things is that the basic approach is:
Search for BLE devices (bluetooth search or "discovery" of nearby bluetooth devices)
Here you will need android permissions!
Choose the device you want to connect to
To differ the devices (maybe there are a lot around you :) ) you can use BLE device's name or UUID or ... best - use the name ;)
After both devices connect to each other you can then start the Gatt communication. The approach with state machine is a little too much overkill for me. But anyway the communication is done through bytes (in my case...)
In one of the videos/resources there was something specific and VERY HELPFUL at least for me! To be honest I don't remember it exactly, but the idea was that before any communication it's RECOMMENDED to read/get all the options from the BLE device or something similar...
Maybe it was something like discoverOptions() or something like that
Great thing will be to know your device "communication codes" or at least I call them that way.
Check this link for example: Link
** Now you can see there are tables with the USEFUL INFO! E.g. if you want to read the battery level you navigate to this page and find that in order to read the battery, the service name is UUID XXXXX and you need to send 0x01 to the BLE device and it will "answer" to your call with some data which is again in bytes.
I really hope that this is somehow helpful!
PLEASE NOTE
This is strictly coming from my experience and there could be some mismatches or wrong terms, but that's how I personally see the things and because my project was long ago, I don't remember most of the things exactly.
IMPORTANT:
This is only a summery of STUCI's provided links above. He has since updated his answer and I have not updated/edited this summery. Topics in my summery are not explanatory but provided for reference and help in generating specific questions.
Original Post...
Thank you Stuci! Some of that was helpful:- some not. I thought it best to collect my thoughts and see what has been explained and if anything hasn't.
(I can't post this much in a comment tho, sorry)
PLEASE CALL ME ON ANYTHING THAT IS INCORRECT.
Video of Bluetooth LE
(Covers a bunch of random things)
While I "dont-like" videos of code:- I watched it because it was recommended ... and I am glad I did. While not very helpful it did introduce some concepts I was unaware of. Since I am targeting old android devices (v8+) the LE features are inconsequential.
Pushing Data: [Depending on the source feature-set], one does not need to continually pull data (ex. with a temperature sensor) but some devices can "push" it to the device on change. Seems to use the 'advertisement" design concept.
UUIDs define Services and/or Characteristics of the connected device.
Possibility to write configuration on (to) connected devices.
Characteristics which seem to be simply "settings" that can be assigned over bluetooth. Not sure if this (~19mins) applies to non-gatt connectoins but seems similar to the state-machine that controls
Advertisements which seem to be the "metadata" regarding the devices current state or config (~24mins). Again, not sure if this even applies to non LE Bluetooth.
Leaving Connections Open
Bluetooth connections can indeed remain open; starting at the point which the "startActivityForResult(...) method is successfully called.
Two basic things affect whether or not one would want to maintain an open connection:
Understand the power consumption.
Having the adapter active simply consumes additional power. If one can keep the adapter shut-off while it is not "absolutely-needed" will mearly save battery power.
Accidental disconnects are managed.
Other than leaving the connection continually connected, one could disconnect & reconnect regularly at specified intervals to ensure a connection is up.
In the thread(s) used for I/O, one could check for a disconnect and reconnect (possibly starting a new thread).
I/O Streams pr Connection
A single connection can indeed "have" simultaneous Input & Output streams. I
Since it was suggested, I re-read Android's Bluetooth Guide and under "managing a connection" (talking about a single socket) I noticed this...
Get the InputStream and OutputStream that handle transmissions through the socket, via getInputStream() and getOutputStream(), respectively.
Read and write data to the streams with read(byte[]) and write(byte[]).
...but continues with noting that read & write block each other. Something I still need to look further into. It seems like you cant I/O simultaneously on the same socket???
Max Connections
I also looked into the max connection issue Stuci added and found no documentation on the Android-side. It might exist, I cant find it. However, most people seem to agree that there is a limitation (that could be as low as 4) imposed by whatever hardware you are coding for.
Some notable links:
- How many devices we can pair via Bluetooth of BLE to Android?
- How many maximum device can we pair via Bluetooth to android device at a time?
- https://groups.google.com/forum/#!topic/android-developers/adeBD275u30

Does the getFocusDistances() camera API function actually work for Nexus 5? or any other device?

I would like to determine the distance of an object from my Nexus 5 camera, preferably without using an object like a coin for scale. I figured the Camera.Parameters getFocusDistances function would work for this.
I attempted to do this via something like the following in my takePicture() jpeg callback:
Parameters params = camera.getParameters();
Float focusDistances[] = new float [3];
params.getFocusDistances( focusDistances );
I tried running this a few times with objects of different distances from the camera, though each time, focusDistances[FOCUS_DISTANCE_NEAR_INDEX], focusDistances[FOCUS_DISTANCE_OPTIMAL_INDEX], and focusDistances[FOCUS_DISTANCE_FAR_INDEX] all contained the value positive infinity.
It's possible I'm doing something wrong, in which case please let me know if there is a specific way I'm which this will work on the Nexus 5. However the android API specifically states you can call getParameters() (and then getFocusDistances()) at any time to get the latest focus distances and therefore I think this should work. One thing I haven't tried yet is doing the above in an on auto focus handler, however I don't see why this should matter.
I did some research to try and see what was going on, and I found several questions regarding this sort of behavior from getFocusDistances() and typically the answer, if there was one, was that the function is not supported by the android API and/or the hardware manufacturer. Now a lot of these discussions I found online were from several years ago, and dispite the questionable feelings it gives me about getFocusDistances, I've still seen this function suggested to be used for getting the focus distance so I figure it must work on SOME device for SOME android API version.
Does anybody know if getFocusDistances() works for any particular version of android on the Nexus 5? If not, does anybody know ANY device it does work on?
EDIT:
Since posting, I have tried obtaining the focus distances in the onAutoFocus handler, as well as trying a bit more extensively for objects atvarious distances. The results have been consistent - positive infinity is always returned for all 3 focus distances (NEAR, OPTIMAL, and FAR). I even tried this with a Nexus 7 and getFocusDistances always returns the constant values (0.95, 1.9, and infinity), so apparently getFocusDistances isn't implemented on that device either.
Therefore, I really have two questions:
Is there any way to get somewhat accurate focus distances using the android Camera API with the Nexus 5? I'm even wondering if there is custom android version where getFocusDistances is actually implemented, since otherwise I may attempt to do so myself depending on what I find when examining the API code.
Are there any android capable devices that are known to implement getFocusDistances in a somewhat accurate manner?
First of all, It's very difficult to measure the object distance from one single shot/view. You would find many research papers which tried to employ vision based techniques to judge the object distance. I can refer you one such paper. They tried to implement a positioning system that would solely work on mobile camera+sensors. You would probably realize how non-trivial it is to measure the object distance from one single camera view. They finally used a method called "structure from motion" vision technique to calculate the distance (From multiple photos taken from multiple angle).
Even traditional apps like SmartDistance and SmartMeasure needs to use geometric tricks to measure the distance. None of them could only rely on camera parameters. Sorry for the elongated introduction. I have done a project of this sort before and I am telling you all these based on my experience.
To answer your query, I haven't found any Android device yet which returns realistic values of focus distances. They are either returned as some constant values or sometimes 0 and infinity. I found someone reporting that it worked for Galaxy Nexus but only within 30cm object distance, it doesn't work for distances more than that. The bottom line is that you cannot rely on this function from camera API which is heavily dependent on the device drivers. And, phone camera's are not well-known for their lens/sensor qualities. It would be very very difficult for you to work on any optics based formula for mobile-phone cameras. I would suggest you to rather go for some sensor based geometric tricks.

Categories