How to find required Android Marshmallow runtime permissions in code? - android

I'm preparing my app to target Android 6.0 Marshmallow.
When setting the target api to 23, the app immediately crashes upon launch. There is no useful information in the logcat output. (It gives a "Requested window does not exist" IllegalStateException, but still, nothing actually useful like class name or line number.)
This is fine (not really), I eventually narrowed it down to my launch activity where I get the user's device IMEI code (TelephonyManager.getDeviceId()). There needs to be a runtime permission request added. I understand this.
However, the app has something like 60 classes across numerous activities, so there is a lot of code to sort through. How can I possibly search through the code to find all of the cases where runtime permissions are required?
Surely Google must have thought of an easy way for developers to track down where the permission requests are required? I thought perhaps commenting out the permissions in the manifest would trigger a compile-time error where the permissions are used, or something of the sort, but nope.
My current method is by going through the app and when it crashes, do like the above with my launch activity and very slowly narrow down where it is. This is extremely inefficient and time-consuming. I'm tempted to just leave it at API 22 for now, but I know sooner or later this will have to be done.

Delete all AndroidManifest.xml permission.
Analyze -> Run Inspection by Name ->Constant and Resource Type Mismatches in Android Studio.
You can detect permission.
But this detection is not perfect...
Because this detects only method that contains this xmls files.
https://android.googlesource.com/platform/tools/adt/idea/+/master/android/annotations/android
https://android.googlesource.com/platform/tools/adt/idea/+/master/android/annotations/android/accounts/annotations.xml#118

What worked for me is this :
Analyze -> Run Inspection by Name -> Missing Permissions

Related

java.lang.NoClassDefFoundError being thrown In some devices, but not all

I get Crash Analytics from Google for my Android app and I have been seeing this popup once in a while:
java.lang.NoClassDefFoundError
with regards to trying to open an Intent.
The scenario is, user clicks on button, they my code in the app is:
Intent intent = new Intent(nameOfCurrentActivity.this, nameOfNewActivity.class);
startActivity(intent);
Pretty straightforward stuff. It works fine on nearly all devices, including all the ones I own and have tested on. This new class being started isn't unique in that it requires any weird hardware (IE, not a camera activity), but it does access the internet via an Http request.
I have already researched the following links without gaining a hint towards a solution:
Why am I getting a NoClassDefFoundError in Java?
How to solve java.lang.NoClassDefFoundError?
My question is, how is it possible that this exception is being thrown on some devices (IE, a Samsung tablet), but not other devices? Shouldn't a new intent work on all devices if it works on one?
Thanks!
A lot of times this can be caused by classes running code that is dependent upon it being a certain API level, IE Marshmallow, but the device using it is on a previous API and the check for permissions is either ignored or not included; Like when you click disable inspection.
An example would be, say you are running something like a View.OnScrollChangeListener for a recyclerview. If you are coding and set it:
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
myRecyclerview.setOnScrollChangeListener(this);
}
But don't include the build if check, it will throw the error. Another example would be if you are using the class itself as the context (this) for setting the scroll listener. If you use the class itself as the context for extending the Scroll listener but are on a device Pre-API 21, it will throw the error when the class loads. The error it throws is, as you probably guessed, NoClassDefError.
This happens because the Class mentioned in the 'future' API doesn't exist yet in the old phone and so it cannot find the class defined.
Check your code to see if anything in the class is requiring a certain API level to function and if it is, check to confirm you included the if checks for build version. Many times before I have disabled inspection because the red lines were bugging me and forgot to go back and add the checks.
I just wanted to add my own experience today. Apparently Supplier<T> exists in Java 8, however implementation of it and running it on Marshmallow generates NoClassDefFoundError. I was able to solve the problem by declaring custom MySupplier<T>. I tried to add as a comment but failed. Thanks for the explanation given by user7293284 above.

Checking which code uses permissions

I've recently changed an app to target Marshmallow and as you know, I now need to handle the Marshmallow permissions model.
The app hasmany files and thousands of lines of code. Aside from the brute force way ie
turn off permissions and use the app , noting where exceptions happen
is there a more efficient way of finding out which lines of api calls request certain permissions so that they can be wrapped in a permission request?
There are some methods that will raise a lint error if they do not detect permission checks (for example location updates using Google Play Services.) To trigger that run Analyze > Inspect Code and look under the Android Lint Errors.
Other than that brute force is the only way. I had to do this for a project I was working on (also many many thousands of lines of code). I suggest monitoring Logcat for errors and hitting the app hard. Be careful though... if you catch the errors in code then they may not appear in logcat so you'll have to make sure the app functionality is as expected.
But, it's not as hard as it sounds. If take a moment to review your app and the potential locations where permissions are required you'll find that its pretty straight forward. Review this article to determine what permissions you'll need http://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en

How to determine the needed permission for my app

I'd like to know if there is any way to determine the permissions my app needs.
There is a similar question here:How do I determine why my Android app requires certain permissions?
But the answer states, that you basically have to find out yourself and I can't believe this.
Is there really no way to tell Eclipse to take a look at my code and determine the needed permissions or something like this? There should be no problem to automate this.
Or is there a way to test permissions on a device. When I install my app on my local device I'm not asked for any permissions.
Any help is really welcome.
This should work:
boolean crashes = true
while (crashes) {
ReadLogCat()
AddPermissionFoundMissingAccordingToLogCat()
crashes = TryAgain()
}
PS: This is pseudocode ;)
PPS: You didn't copy this to Eclipse, did you? Just kiddin' ;)
Believe it.
The app crashes and tells you the reason why: it expected some permission(s) declared in its manifest file.
It normally tells you in 2 ways: in a Dialog (FC Dialog) and in the LogCat.
You have to define permissions according to what your apps doing, if it's accessing the internet, it needs permission to do it. If it wants to locate you via GPS, it needs a permission for it and no you can't automate it, not officially anyway.
Think your app as a virtual child, you need to grant it permission to do stuff or else it won't do anything. So you have to pretty much decide yourself.
But you need not worry, if you're missing a permission, the log will let you know which one it is.
well i won't consider this as official solution for this problem
usually when i miss any permission in my application say i am using internet connectivity or get tasks but i didn't declared them in manifest
when i run my app i get it in log cat saying internet permission and get tasks permissions are required for this app to run
hope that answer your question
Is there really no way to tell Eclipse to take a look at my code and determine the needed permissions or something like this?
If you have a test suite that adequately tests your app, running the test suite will tell you the needed permissions, because your tests will crash if you do not have them.
Or is there a way to test permissions on a device. When I install my app on my local device I'm not asked for any permissions.
The permissions that you see on install are based on your <uses-permission> elements in your manifest, not some analysis of the app beyond that. Hence, this will not help you. That being said, installing your app by any means other than adb, such as downloading the app from a Web server, will pop up the permissions dialog, so you can see what prospective users will see at install time.

Does Eclipse automatically set "uses-permissions" in Manifest?

I know it's a simple question but I can't find any answer. Well actually it's three related questions:
If my code requires a uses-permission manifest element, does Eclipse automatically add it to the manifest?
If Eclipse doesn't automatically add it, how do I know which permissions my app needs? Of course there is this list, but it's hard to go though this list checking if what my app does falls within each of these permissions.
If Eclipse doesn't automatically add the permission and I fail to do it, how will I find out? Will the app fail to install on the emulator? Will it install on the emulator but be force-closed when trying to access something it doesn't have permissions for? Or do I have to install the apk on a real device in order to find out?
If my code requires a uses-permission manifest element, does Eclipse automatically add it to the manifest?
No.
how do I know which permissions my app needs?
Generally, by reading the JavaDocs, which do a decent job of pointing out what permissions you need. Otherwise, you will find out in testing, when your app crashes with a SecurityException.
If Eclipse doesn't automatically add the permission and I fail to do it, how will I find out?
See above.
Will it install on the emulator but be force-closed when trying to access something it doesn't have permissions for?
Correct.
Eclipse will not add permissions automatically. However, if you try to use a feature that requires permission, you will be made aware of the missing permission. Here's an excerpt from android resource page on Permissions: Link
Often times a permission failure will result in a SecurityException
being thrown back to the application. However, this is not guaranteed
to occur everywhere. For example, the sendBroadcast(Intent) method
checks permissions as data is being delivered to each receiver, after
the method call has returned, so you will not receive an exception if
there are permission failures. In almost all cases, however, a
permission failure will be printed to the system log.
Your third question is answered by:
In almost all cases, however, a permission failure will be printed to
the system log.
Just in case you're wondering about what you would see in Logcat:
11-20 08:08:47.766: E/AndroidRuntime(9380):
java.lang.SecurityException: Need BLUETOOTH permission: Neither user
10111 nor current process has android.permission.BLUETOOTH.
Eclipse does not automatically add the uses-permission to your manifest. I once had forgot to add a permission and had my app fail when it got to that part of the code. I can't remember the exact error but it did mention that a permission was required to use the method I tried using and I believe that it told me what permission.
If you don't add one in then you will soon find out.

How do I determine why my Android app requires certain permissions?

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.

Categories

Resources