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

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.

Related

Enable Bluetooth without auto-connecting to devices ("quietly") in Android

I found out there's a system function called IBluetoothManager.enableNoAutoConnect(), which by the name, seems to do exactly what I've been searching for hours: enable Bluetooth without auto-connecting to devices.
I can call the function, but...
java.lang.SecurityException: no permission to enable Bluetooth quietly
Because...
if (callingAppId != Process.NFC_UID) {
throw new SecurityException("no permission to enable Bluetooth quietly");
}
So, is there any other way of calling this function? Like some ADB command? Or through another class? I also found a function that does the same here, in AdapterService.java. But I don't know how to get to it (doesn't even appear on Android Studio).
Note: I have root and system-privileged permissions (just not signature ones), and I'm using the internal/hidden SDK, so I have access to the classes and everything without needing reflection (and still, AdapterService doesn't show up - unless there's a problem with the "SDK" and it's not showing all it should?).
(PS: I say "quietly" in the title because in the source, the variable that tells if it's auto-connect or not is called quietMode.)
EDIT: actually the function is directly in BluetoothAdapter, without needing to go for the interface. Not sure how I didn't notice it. But anyway, same problem.
EDIT 2: more specifically for Android Oreo and below (or Pie and below), as I just found a function called setSilenceMode() on BluetoothDevice, and it might do what I'm wanting (not tested), but still, missing on older APIs.
Thank you

How to find required Android Marshmallow runtime permissions in code?

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

Detect Outgoing Calls Reject Reason in Android

Is is possible to detect network reject reason for outgoing calls in Android?
For example, let's assume a person is out of credit and is attempting a phone call. In this case, the Network will reject the call (since the person is out of credit). How can an App detect this?
Thanks!
A "bit" late xD, but I believe you're looking for this: https://android.googlesource.com/platform/frameworks/base/+/master/telephony/java/android/telephony/DisconnectCause.java. I just found it with help of what you said on one of the error codes: "Network is busy" --> searched "network is busy site:android.googlesource.com" on Google, without the quotes (saying this because they matter on Google searches, in case anyone didn't know).
That's DisconnectCause class and there's also PreciseDisconnectCause: https://android.googlesource.com/platform/frameworks/base/+/master/telephony/java/android/telephony/PreciseDisconnectCause.java. You can know this last one because on the first one, it's said that class is used on PhoneStateListener on onCallDisconnectCauseChanged() (which may be what you want), and on Android Developers, we can see that method has 2 parameters, which give 404 error on Android Developers. So I seached the .java class file on Google for Android Source links and there they are.
Notes on using this method:
it requires API 30 at minimum (pity...);
but more important, it requires READ_PRECISE_PHONE_STATE (the app must be installed as system app) - or some other trick with root commands.

ParseInstaller.getCurrentInstallation().saveInBackground() is freezing my application

I am finding that about 1/5 of my tests are freezing, and after some searching for the problem I have narrowed it down to the line:
ParseInstallation.getCurrentInstallation().saveInBackground();
I am using Parse 1.5.1, and an Android 4.4.2 device. My application class looks like:
public class InitApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
Parse.initialize(this, "my_App_ID", "my_Client_Key");
PushService.setDefaultPushCallback(this, MainActivity.class);
System.out.println("execution DOES reach here");
ParseInstallation.getCurrentInstallation().saveInBackground();
System.out.println("execution DOES NOT reach here");
}
}
The behaviour on my device is that I will first see a blank white screen for about 5 seconds, and then the screen goes black. I am not sure how long the screen stays black, as I usually force close. I've let it sit for about 10 minutes once with no change. I am unable to press the back button and any touch on the screen does nothing. I am forced to use my home button, then force the application to close. Upon reopening the application, it behaves and functions normally.
Further research led me to find this post: https://www.parse.com/questions/android-saveinbackground-lock-the-main-thread
But still, I have been unable to find a solution. One suggestion in the above post is to simply move the location of this code. I have tried this to some point after my main activity's onCreate() method (not to be confused with the application's onCreate() method). Behaviour appeared to be normal up until I got to the point where the getCurrentInstallation.saveInBackground() code is called, where my application froze and failed to respond until I forced it closed.
Are there any solutions to this problem?
I encountered the same problem as well using Parse SDK 1.5.1.
And I just downloaded the latest SDK 1.6.0 and problem solved.
Link to download the latest SDK.
You can track reported issue here:
Parse installation save causing app freeze
I already provided (confidentially) thread dump traces from my app. However at time of writing this post there is no useful feedback from Parse guys.
My humble opinion after looking into traces is a deadlock causing this issue after some trouble with server interaction. But it's just guessing.
Link updated
I do have the same issue and more.
The blank or black screen however happen not to all my test phones. It happens only to one of them (Android 2.3).
SaveEventually also does not work to the problematic phone above (all the other phones I have are working fine). It does not send data through successfully to the server. So I suspect that phone configuration of saving data on the phone itself before passing to the server when network is back on may be the issue.

How to check if some service on android is unavailable?

I discovered, that on some devices VPNService is unavailable even if they has proper android version (4.0 or grater). Is there a way to check is some serivce is realy available on device?
The tricky part is, that on some devices exception is thrown after calling establish() method, but on other devices this methods works fine, but app crashes after trying to open confirmation window. So resolution can not relay on check whether establish() throws an exception.
I am the author of the OpenVPN for Android app. I had to deal with these bugs too. The first one is easy. It will throw a ActivityNotFoundException. If you want to check this before you probably can check if the Activity mentioned in the intent exists.
http://code.google.com/p/ics-openvpn/source/browse/src/de/blinkt/openvpn/LaunchVPN.java?name=v0.5.28#380
The establish() problem is much harder to get. I use a catch all exception. In almost all cases the /dev/tun device does not exist or has the wrong rights. Checking for this will work but the implementation can change and headset vendor can theoretically roll their own implementation. It is like asking the OS: "Are you buggy?" and expecting a right answer ...
http://code.google.com/p/ics-openvpn/source/browse/src/de/blinkt/openvpn/OpenVpnService.java?name=v0.5.28#351

Categories

Resources