7
\$\begingroup\$

I have heard in many places that if my app uses a permission not applicable to a certain device, it will not show up in the play store for that device. Now, in my code, I am playing audio. I mute that audio whenever there is a phone call by doing this:

 private PhoneStateListener phoneStateListener = new PhoneStateListener() {
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
                if (state == TelephonyManager.CALL_STATE_RINGING) {
                    onPhoneCallInterrupt(); //Method I made that mutes audio for phone call
                } else if (state == TelephonyManager.CALL_STATE_IDLE) {
                } else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
                    onPhoneCallInterrupt(); //Method I made that mutes audio for phone call
                }
        }
    };

Now, this uses the following permission in the manifest:

<uses-feature android:name="android.permission.READ_PHONE_STATE"  android:required="false" />

Will I get any exceptions because I have made the permission optional by doing android:required = "false" on devices that don't have phone compatibility (tablets)?

The reason I am so confused on this, is because I am checking if the phone is being used, but I am not using it. So, will my app work on tablets, let alone show up in the play store for them?

Thanks for helping me clear up this confusion,

Ruchir

\$\endgroup\$
1
  • \$\begingroup\$ Can't say for sure, but I'd think so. This might depend on the Android version bring used though. \$\endgroup\$
    – Mario
    Commented Dec 12, 2015 at 8:46

1 Answer 1

6
\$\begingroup\$

Yes, Google Play does filter out content that is not appropriate for the current device. If your device doesn't have a camera, no camera apps should be visible to you, however you may still see apps using the camera as a minor feature. The distinction is made by the use of android:required when declaring a used feature.

Note that permissions are different from features. Permissions are there for security and you declare the use of permissions by the <uses-permission> tag. Features on the other hand is there for compatibility and you declare the use of features by the <uses-feature> tag.

Google Play will filter your application based on what features it uses. However even if your never declare any <uses-feature> tags in your android-manifest file, you app may still be filtered. This is because Google also reads through all of your declared permissions and infers any feature requirements you haven't explicitly declared. So if you declare the READ_SMS permission then this implies the use of the android.hardware.telephony feature. So it won't show up on tablets or other devices without phone capability.

Quoting this section here:

Note: Some system permissions implicitly require the availability of a device feature. For example, if your app requests permission to access to BLUETOOTH, this implicitly requires the FEATURE_BLUETOOTH device feature. You can disable filtering based on this feature and make your app available to devices without Bluetooth by setting the required attribute to "false" in the tag. For more information about implicitly required device features, read Permissions that Imply Feature Requirements.

So to avoid having your app filtered on Google Play based on a certain feature your app is using you need to explicitly declare it with android:required set to false. Do note however that since the feature is no longer guaranteed to be present on the device your app is running on you need to check that the feature exists at run-time.

Example of what your AndroidManifest.xml should contain.

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-feature android:name="android.hardware.telephony" android:required="false" />

And a quote on how google filters apps based on explicitly declared features. Link

An explicitly declared feature is one that your application declares in a element. The feature declaration can include an android:required=["true" | "false"] attribute (if you are compiling against API level 5 or higher), which lets you specify whether the application absolutely requires the feature and cannot function properly without it ("true"), or whether the application prefers to use the feature if available, but is designed to run without it ("false").

Google Play handles explicitly declared features in this way:

  • If a feature is explicitly declared as being required, Google Play adds the feature to the list of required features for the application. It then filters the application from users on devices that do not provide that feature. For example:

<uses-feature android:name="android.hardware.camera" android:required="true" />

  • If a feature is explicitly declared as not being required, Google Play does not add the feature to the list of required features. For that reason, an explicitly declared non-required feature is never considered when filtering the application. Even if the device does not provide the declared feature, Google Play will still consider the application compatible with the device and will show it to the user, unless other filtering rules apply. For example:

<uses-feature android:name="android.hardware.camera" android:required="false" />

  • If a feature is explicitly declared, but without an android:required attribute, Google Play assumes that the feature is required and sets up filtering on it. In general, if your application is designed to run on Android 1.6 and earlier versions, the android:required attribute is not available in the API and Google Play assumes that any and all declarations are required.

Note: By declaring a feature explicitly and including an android:required="false" attribute, you can effectively disable all filtering on Google Play for the specified feature.

Basically if you using permissions that require a feature, see this list, your should explicitly declare that feature with android:required="false" next to it and you are good to go. But also since this feature isn't guaranteed to be there you also need to check that the feature exists at run-time before using any methods requiring it. Otherwise a tablet will crash on Phone.call(5551234), while with android:required="true" you won't be required to check that the phone is there as it must be since otherwise it your app should have been filtered out. Though you might want to check it anyway as people might install it from other sources, something to consider.

Example of checking for feature at run-time.

PackageManager pm = getPackageManager();
if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
   // This device does have a phone.
   havePhone = true;
}

If you have more questions about this I really recommend reading through these:

\$\endgroup\$
9
  • \$\begingroup\$ As usual Christer, great detailed answer. My question is, based on the code that I provided, will I need to catch some exceptions? Because, I am not actually making any calls or anything...Instead, I am checking whether the user is in a call...Also, if you have a tablet and it isn't to much to ask, is my app showing up in the play store? In the search, just type up "Ruchir Popper" and the result should hopefully have an app that says "Balloon Popper". I understand if that is too much to ask, it's just that I only have an android phone, and I don't know anyone that has a tablet. Let me know! :) \$\endgroup\$ Commented Dec 13, 2015 at 12:28
  • \$\begingroup\$ I don't have an android tablet right now, maybe later. But giving my suggested change to the manifest file it should show up. But as I said in my answer if you have further questions you should read my links. The second one shows an example on how to deal with non-required features at run time. developer.android.com/guide/practices/… \$\endgroup\$
    – Christer
    Commented Dec 13, 2015 at 12:35
  • \$\begingroup\$ Why do I need both permissions in the manifest though? Can't I only have android.hardware.telephony? Thanks \$\endgroup\$ Commented Dec 13, 2015 at 12:41
  • \$\begingroup\$ Because they are not both permissions, one is a permission and one is a feature. Permissions are for security reasons, and features are for compatibility reasons. Certain permissions will implicitly require a certain feature, so if you don't want Google Play to filter out based on a feature your app is using you should state so explicitly in your manifest file. \$\endgroup\$
    – Christer
    Commented Dec 13, 2015 at 12:59
  • \$\begingroup\$ But, according to that, I should just let go of the permission. I should just keep the feature only, right? That way, android won't try to filter out my app? \$\endgroup\$ Commented Dec 13, 2015 at 13:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .