For instrumented tests of location services I need mocked locations. But the current concept from Android seems to be not very practical.
In order to be allowed to use mocked locations the test-package also needs the permission android.permission.ACCESS_MOCK_LOCATION. When added to a debug-manifest I get the hint, that this permission will only be granted to System-Apps. I have to add tools:ignore="ProtectedPermissions" to the permission to suppress this warning. IMHO it makes no sense to issue such a warning for a property that is necessary for such tests.
Then I need to select this test-package as mock-location provider for the test-device. Acceptable for a manual test. But do I really have to manually select this setting for every device I want to test my code on? (What about this firebase-test on a farm of test devices? There I can not make this setting.)
And what if I have more than one app that tests mocked location? Currently I can not test both packages on the same device.
Or am I missing something?
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.
I'd like to write an instrumented test to verify the behaviour of an app that requests location updates using the FusedLocation API on API23+.
I have some requirements:
The test must run in an emulator (AVD) because I'd like the tests to run in a continuous integration service like Travis CI or circle CI.
I want to test that the Marshmallow permissions request dialog properly pops-up using UI Automator.
I want to ensure my code works by checking the Location object returned by requestLocationUpdates() using assertions.
Since testing on an emulated device is a requirement we must then use FusedLocation.setMockLocation() in order to get a location or the requestLocationUpdates() will not yield any results.
Until now I have faced these problems:
Both setMockMode() and setMockLocation() require location permission: this means that I have to request the location permission in my test code and once my code under test reaches the requestLocationUpdates() call it won't request permission again (because it already has it) thereby not letting me test the permission request dialog with UI Automator.
setMockLocation() requires manually setting "Allow mock locations" in developer options so the Continuous Integration will fail because a new emulator is created every build and will have "Allow mock locations" disabled by default.
It seems to my I've reached a dead end. Please prove me wrong!
In my android App, there is an Activity which shows time string according to the System Time Format (12Hr. / 24Hr.).
I am writing espresso test to test this behavior whether the time displays gets changed as the System time format changes.
In order to achieve this, i want to change my System time format through my Instrumentation test for pure testing purpose. and i've added permission in test project's manifest, like this
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
and wrote the following code to change system time format
Context context = InstrumentationRegistry.getContext();
Settings.System.putString(context.getContentResolver(),Settings.System.TIME_12_24, "12");
and it is throwing Permission Denial error. (you can use below link to see the stack trace)
Error StackTrace Screenshot
i am not able to understand, since the code which is trying to change the system time format in the test project itself and it has permission to change the system time setting,
I verified Using this command
adb shell dumpsys package com.my.app.package | grep permission
Please tell me, what i am missing here ?
I've already found an explanation to your issue. Here is it:
The user application does not have permission to change the device
time. Please read the answer by cashbash in the following post
for the alternate option.
Copying here for quick reference:
According to this thread, user apps cannot set the time,
regardless of the permissions we give it. Instead, the best approach
is to make the user set the time manually. We will use:
startActivity(new Intent(android.provider.Settings.ACTION_DATE_SETTINGS));
Unfortunately, there is no way to link them directly to the time
setting (which would save them one more click). By making use of
ellapsedRealtime, we can ensure that the user sets the time correctly.
From: Set Android's date/time programmatically
Try also instead of using Espresso, use uiatomator as that instrumentation test framework can perform actions with Dialogs, Marshmallow permissions or lockscreen.
It works perfectly with Espresso.
Check this site: http://qathread.blogspot.com/2015/05/espresso-uiautomator-perfect-tandem.html
Hope it help
Let's say I have taken over development of an Android app, and my boss asks me why our app requires certain permissions to be displayed to users who buy the app on the Android Market.
Are there any tools or tricks I can use to determine what code triggers each permission, so I can figure out why our app functionally needs those permissions? In particular, I am interested in these permissions:
Phone Calls - Read phone status and identity
System Tools - Retrieve running applications - Allows app to retrieve information about currently and recently running tasks, May allow malicious apps to discover private information about other apps.
The app is a GPS tracking app, and it's not obvious why this permission might be needed.
It would also be helpful to get any tips on why this permission might be needed, even if you can't tell me how to directly analyze the code to find out.
Here is how I would track these down.
Step 1 - Find the manifest permissions declared in your AndroidManifest.xml
Basically everything inside the <uses-permission /> tags e.g.:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Step 2 - Search developer.android.com for classes that use these permissions
Let's take the case of READ_PHONE_STATE, the goal is to find which packages require this permission. A simple search on the dev portal for "READ_PHONE_STATE" starts our search, we are looking for classes here, in the top 5 search results I see the following classes:
TelephonyManager
PhoneStateListener
Click on the classes and get their package names:
android.telephony.TelephonyManager
android.telephony.PhoneStateListener
Step 3 Find classes in your project that import these packages
A simple grep will do, or a Ctrl-H in eclipse, File Search -> Containing text
Step 4 Comment out the import and see what breaks
These are likely candidates for why the permission is required. Confirm the methods in question by looking at the dev portal to validate that the permission is indeed required by that method.
Finally you should be able to tell your boss, READ_PHONE_STATE is required because we call function XYZ which gives us UVW.
Remove a permission and see where the app fails. The answer will be in the logcat output.
That's not an ideal solution though, since you might not know what you need to do in the app to trigger that permission.
I suspect "Read phone status and identity" means that the app is using the device IMEI or similar identifying information to uniquely identify the device to ensure that the app is only being run on a registered device. Or it might just be used as a sort of cookie to track the owner. Look for that code. And remove it, because that's the wrong way to do it. If you need to identify a specific android device, use ANDROID_ID from the Settings.Secure class. http://developer.android.com/reference/android/provider/Settings.Secure.html
As for "Retrieve running applications", I find that one somewhat suspicious. A very common way to implement GPS tracking is to launch a separate service in its own process. This way, if the app should crash, the service will keep going and can be re-attached. In this case, it's possible that the app is using the "Retrieve running applications" to identify and kill the service process. But if so, it's a clumsy way to do it.
With the latest build tools, you can run lint check which will highlight for you all the android SDK method calls which are requiring permissions.
See announcement here http://android-developers.blogspot.com/2015/07/get-your-hands-on-android-studio-13.html and documentation here https://developer.android.com/tools/debugging/annotations.html#permissions .
This is based on android annotations and after some adoption time 3rd party libraries can integrate permission annotations also
The answer for your boss is "because certain API features/calls/methods we use in our app require calee to hold certain permissions. It is for security reasons, and that's the way Android works". As for mentioned permissions - you have to check the code to see if these permissions are really required. Read phone status and identity may indicate your app try to get IMEI or something like this to uniquely identify device. Retrieve running applications - see no reason for GPS tracking app to hold this. But maybe you use 3rd party lib/code that uses this.
My application needs that GPS is active at startup as for it to proceed.
Iam testing the app, so I'm mocking the GPS by adding <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> to my AndroidManisfest.xml file.
This works ok. But I want to keep things separate. Is it possible to add a permission at runtime when we are testing?
EDIT:
I know from the docs that:
Android has no mechanism for granting permissions dynamically (at run-time) because it complicates the user experience to the detriment of security.
But as a matter of testing the application, is there an alternative?
Thanks
There is no way to add Android permissions at run-time. They must be specified in your manifest.
If you have a separate test application, I believe you only need to put this permission on your test application.
EDIT A test application is really no different to Android than a regular one in terms of permissions. I would just put the permission in your test application's manifest and not worry about it.