An application I work on calls TelephonyManger.getCallState() to find out if the call state is CALL_STATE_IDLE.
Our intention is to avoid distracting the user by opening an activity while a call is in progress.
A courtesy.
However, as of API 31, this call is deprecated:
https://developer.android.com/reference/android/telephony/TelephonyManager#getCallState()
This method was deprecated in API level 31.
Use getCallStateForSubscription() to retrieve the call state for a specific telephony subscription (which allows carrier privileged apps), TelephonyCallback.CallStateListener for real-time call state updates, or TelecomManager#isInCall(), which supplies an aggregate "in call" state for the entire device.
Worse, it now requires a dangerous and scary permission.
Requires Permission: READ_PHONE_STATE for applications targeting API level 31+.
For any alternatives it suggests - you must either have READ_PHONE_STATE or carrier privileges.
https://developer.android.com/reference/android/telephony/TelephonyManager.html#getCallStateForSubscription()
The application I work on does have carrier privileges in some variants, but not all.
But WHY would this be required?
In Behavior changes: Apps targetting Android 12, this change is not mentioned at all:
https://developer.android.com/about/versions/12/behavior-changes-12
It says nothing whatsoever about the fact that you will no longer be able to tell if a call is in progress.
There is nowhere I can find the reason for this change.
It seems that knowing if user in call is something basic that an app might want to know. Not just apps that have carrier privileges.
Why was it okay for 12 years and suddenly not?
For example, some apps, like Audible, will stop audio when a call comes in and resume when call is completed. So is that not going to happen anymore without dangerous permissions?
READ_PHONE_STATE Permission includes the current cellular network information, the status of any ongoing calls, and a list of any PhoneAccounts registered on the device. A permission which a user will not grant lightly.
Related
I am talking about the quality issue (bug) that an Android app needs a permission that is declared in the Manifest, but fails to request it from the user at the appropriate time and executes the code without the necessary permission. This was not possible in older Android versions (user accepts all permissions in bulk), but seems to be possible when using newer versions that copy Apple in most regards.
At least during testing one can start background services and use bluetooth without any alert by Google popping up. Is that different for apps in production?
Does the app crash with an Exception?
Does the code get executed?
Does the app get rejected in review? (Always?)
Does the app get delisted from the store?
Does it depend on Android's Version?
I deal with an age old app that has bluetooth discovery code to find and connect to dedicated hardware, that is rarely used via a cordova plugin triggered by content. There is old altbeacon code potentially activated that may even need access background location (https://developer.android.com/guide/topics/connectivity/bluetooth#Permissions). It will take some time to get this dead code up to quality. Definitely more time than the week we have.
Does the app crash with an Exception?
yes if you try to have operations depends on returned date witch is null
Does the code get executed?
code will execute with exceptions because data access denied you can check if permission granted or not and add scenario for each state
Does the app get rejected in review? (Always?) not sure but with crashes there is high potential to get rejected
Does the app get delisted from the store?
depends on why and how you are using data
Does it depend on Android's Version?
yes access data and permissions changing point is android oreo
My tests with Bluetooth permissions revealed the following: Required permissions are BLUETOOTH_ADMIN, BLUETOOTH and for VERSION_CODES.Q additionally Manifest.permission.ACCESS_BACKGROUND_LOCATION (see: https://developer.android.com/guide/topics/connectivity/bluetooth#Permissions).
BLUETOOTH_ADMIN, BLUETOOTH do not show any system alert-dialogue to the user. In Android Q+ if you fail to check for the required ACCESS_BACKGROUND_LOCATION permission, nothing happens and your code executes without exception (mine did execute an UART command on hardware with Samsung tablet). The app passed review although the check is missing (of course I will fix that ASAP).
Note: the doc is ambiguous and states: "Services running on Android 10 and higher cannot discover Bluetooth devices unless they have the ACCESS_BACKGROUND_LOCATION permission." Probably general scanning while the app is active could be allowed. In that case missing exception would be explained.
In order to use the Geofence API the user has to give the app ACCESS_FINE_LOCATION. This location is considered to be dangerous and can be revoked at any time; once this permission is revoked, the app can not request the geofence updates.
How does ACCESS_BACKGROUND_LOCATION permission fit in this picture? We know for sure that this permission is also dangerous and can be revoked at any time. Does it mean that if we want to register some IntentService to be invoked every time the geofence change occurs, we also have to make sure the user has provided ACCESS_BACKGROUND_LOCATION permission? Or do we need to use this permission only if we attempt to get a current location in our own background Service/BroadcastReceiver?
The reason I'm asking this question is that the documentation seems to be a bit vague at this point: the documentation describing the Q Developer Preview mentions that geofencing is one of the use cases for the background location retrieval, while the Geofencing API page does not mention ACCESS_BACKGROUND_LOCATION among its requirements.
Geofencing API Documentation is now updated and we need to define ACCESS_BACKGROUND_LOCATION to monitor Geofences if we target Android Q
From the doc:
To use geofencing, your app must request ACCESS_FINE_LOCATION. If your app targets Android 10 (API level 29) or higher, your app must also request ACCESS_BACKGROUND_LOCATION.
My guess the section "Re-register geofences only when required":
Registered geofences are kept in the com.google.process.location process owned by the com.google.android.gms package.
will be that it is not really needed, as com.google.process.location should be the one getting the location data (so the one needing to request the ACCESS_BACKGROUND_LOCATION permission).
That being said, following this logic ACCESS_FINE_LOCATION permission should neither be needed. The fact that it is needed may be because of two reasons (I don't know the real reason):
that either when registering the geofence or when receiving a notification location is checked,
or that this permission is checked by Google Play Services to forbid an app to circumvent the lack of location permission by using Play Services as a proxy process to obtain the information.
For me, the second assumption makes more sense, meaning that even when technically will not be needed by the app (the process getting the location is Play Service), it is required for privacy/security reasons.
Following this logic, Google should (will?) also enforce the ACCESS_BACKGROUND_LOCATION, both to ensure user's privacy/security and to reduce battery consumption.
On beta 4, adding a geofence when ACCESS_BACKGROUND_LOCATION is not granted, even when the app is fully in the foreground, fails with status code 13 ("error").
You need Android 10 API Level 29+ to use ACCES_BACKGROUND_LOCATION
I'm looking into porting some existing code to take Android M's new way of dealing with permissions into consideration. However the permission API needs to have an activity associated with it (for example the requestPermissions() method's first parameter is an activity).
So how should a service that needs to check if a permissions has been granted and request for permissions use this new API if the service doesn't have an activity?
Is it possible for the service to create a dummy invisible activity just for use with the permissions API? (if its possible I don't like the thought of doing that anyway though).
Or suppose its not a service but a model class that needs to perform a permissions check, in MVC a model shouldn't have any knowledge of the Vs and Cs and yet now either it has to in order to know which Activity to use with the permission API. Or potentially lots of code might have to migrate from model code into Activity code.
Any thoughts on how to migrate non activity based code that needs to check/prompt for permissions over to Android 6.0?
Update: I left out an important piece of information - this is code that is pre-installed (our company provides code that device manufacture's place in rom) and often may be run at device boot time and run in the background. Therefore the usual situation of a user being prompted for permission when they launch the app or later (and there therefore being an activity at that point) does not necessarily apply.
So how should a service that needs to check if a permissions has been granted and request for permissions use this new API if the service doesn't have an activity?
There is almost always an activity, except for pre-installed apps and plugins for other apps. Otherwise, your service is unlikely to ever run, as nothing will have used an explicit Intent to start up one of your app's components, so it will remain in the stopped state.
For the ~99.9% of Android apps that have an activity already, if the permissions are needed for the whole operation of the app, request them on first run. As Snild Dolkow notes, if the user later revokes the permission through Settings, you can detect that without an activity, then use other UI options (e.g., Notification, app widget) to let the user know that operation is suspended until they grant you the permissions again, which they would then do through your activity.
Is it possible for the service to create a dummy invisible activity just for use with the permissions API?
Presumably you can have a Theme.NoDisplay activity use requestPermissions(). However, from the user's standpoint, it will not make much sense, unless there's some alternative UI (app widget?) that they are interacting with. Popping up a permission dialog out of nowhere is unlikely to make you popular.
UPDATE 2019-06-15: Note that Android Q bans services popping up activities frmo the background. Please use a notification instead.
in MVC a model shouldn't have any knowledge of the Vs and Cs and yet now either it has to in order to know which Activity to use with the permission API
Do not touch the models until you have requested the permission, and gracefully fail if the permission is revoked. You already have to gracefully fail in other circumstances (out of disk space, no Internet connection, etc.), so a revoked permission should be handled in much the same way.
using this new 6.0 API seems like an recipe for bad design and tight coupling
You are welcome to your opinion. Based on what I have read, the Android engineers believe that asking the user for permissions is part of the user experience and is best handled at the UI layer as a result.
Again: the vast majority of Android apps will not have a problem with this, as they have a user interface. Apps that do not have a user interface and need dangerous permissions are in for some amount of rework.
this is code that is pre-installed (our company provides code that device manufacture's place in rom) and often may be run at device boot time
First, please understand that this is so far from normal that you can't even see normal from where you are due to the curvature of the Earth. :-) You can't really complain that Google did not optimize this particular scenario.
As I understand it, even system apps should be asking for runtime permissions. The Camera app did, for example, on the 6.0 preview. That being said, there's gotta be some database on the device somewhere that is tracking what has been granted, and presumably there is some way to pre-populate it. However, the user could still revoke it from Settings, presumably. But, the manufacturer could pull some stunts (e.g., messing with the Settings app) to possibly even preclude that scenario. I'd be looking in the same area as "how do I get it so my app cannot be force-stopped?" that device manufacturers can do.
Your alternatives would be to get rid of the dangerous permissions or to migrate your app off the SDK and into a standard Linux binary that would be run as part of the boot process and be put into a Linux user group that has access to the stuff that you need.
Ask for it when the user enables whatever feature your service provides. They'll be in one of your activities at the time. Yes, it means that your activities need knowledge of what permissions your services will require.
The service can always check for the permission by itself, though, since checkSelfPermission() is available in all Context instances. So you don't need an activity for that.
I guess an alternative would be to have your service post a notification saying "feature X requires you to approve more permissions". Actually, that may be a good idea regardless, in case the user goes into settings and revokes any permissions after the fact. That notification would then take the user to some activity with an "enable feature X" button/checkbox -- ask for the permission when that is selected.
You can send a notification. Look this library to manage the permissions: permission library
I have some code that detects when there is new voicemail. It's based on a PhoneStateListener.onMessageWaitingIndicatorChanged() implementation (so technically it fires only when the MWI indicator changes, not necessarily for every new voicemail).
It has been working perfectly for many months until 4.x.x updates to the devices.
Now, this works when the device is rebooted, otherwise its very unreliable. I can see the voicemail icon appear in the notification bar, but the debug logs in onMWIChanged stay silent.
I know that with 4.x.x there is a voicemail provider API. Thinking that this may have a connection, I added the android.intent.action.NEW_VOICEMAIL and android.intent.action.PROVIDER_CHANGED intents to my receiver, but they don't fire (in my BroadcastReceiver onReceive) either (my app's minSdkVersion is 8).
This is a post from Android Developers about the Android 4.0 APIs.
http://developer.android.com/about/versions/android-4.0.html
If you scroll down there is a section about Voicemail Providers where it explains:
Because the APIs currently do not allow third-party apps to read all the voicemails from the system, the only third-party apps that should use the voicemail APIs are those that have voicemail to deliver to the user.
However, I assume if you are trying to receive voicemails from a third party and not from your service then this still may be possible. Check out this link about VoicemailContracts where I believe it says you need the permission ADD_VOICEMAIL in your manifest to use the actions you are using above.
http://developer.android.com/reference/android/provider/VoicemailContract.html
There are also samples that I did not get a chance to look at called Voicemail Provider Demo in your SDK. I hope this helps.
It does require the READ_PHONE_STATE permission. Although, if it worked before you must of had it set.
See LISTEN_MESSAGE_WAITING_INDICATOR.
This question has been asked before at How does Android enforce permissions?. While the discussions there are good, the question is still not fully answered.
In the development environment, exceptions are thrown when the app tries to do something that requires permissions not declared in AndroidManifest.xml. So how does the run-time system implement the run-time checking?
I guess it's most likely done in the core framework, which may or may not need support from native code. But I don't know what source code files in AOSP are relevant to this.
Android uses a lot of the standard Linux(-kernel?) mechanisms especially when it comes to hardware restrictions.
Every app gets assigned a new unique (Linux-)user id and whenever the app process is created the system creates it with that user id. The id will never change unless you remove the app. That means for accessing the lower system levels your app will appear as a certain user and every (Linux-)permission system that works with users will also apply to your app.
If you request WRITE_EXTERNAL_STORAGE in the manifest your app will also become member of the (Linux-)group (called sdcard_rw) that has permissions to write to that storage. Permissions on the filesystem are enforced to only allow writing to the system user (=owner) and the sdcard_rw group, anyone else (=other) may only read. See also Is Google blocking apps writing to SD cards
By doing that Android has to do pretty much nothing except for setting the correct UID/GIDs of the processes it spawns once the app starts and the rest is handled at lower levels. Apps that are not member of a certain group simply don't get access to certain hardware.
List of permission <> group mappings: platform.xml
There are also some (Android software) restrictions that are based on either the signature of your app and / or simply by looking up the permissions your app requested: e.g. ContextImpl#checkPermission() - but those permissions have to be checked at every entrypoint to code that allows restricted actions.
From time to time people discover ways to e.g. turn on GPS programmatically because a check like that is missing somewhere.
With regard to your second paragraph, "exceptions" are runtime faults. Permissions are not enforced at build time, only at run time.
Accessing hardware, low level operating system resources, and system files generally requires the app userid to be a member of an appropriate group which it may be assigned by the package manager as a result of having a corresponding android permission. (Familiar examples of that would be network sockets, and the sdcard write which zapl mentioned, but also system-only things like talking directly to the GSM modem or reading the raw touchscreen coordinates).
For the majority of android operations that are done by way of calling library functions which are stubs for interprocess communication to services running in a different process, the platform code running in the more privileged process on the receiving end of the ipc request checks with the package manager to find out if the calling application has the necessary android permission.
Many special permissions are only available to apps signed with the system signature - even if another app claims those in its manifest, they will not be applied by the package manager.