I used to receive DexIndexOverflowException a couple of days ago and what I did is :
a) adding multiDexEnabled true to defaultConfig in my build.gradle file.
b) adding compile 'com.android.support:multidex:1.0.1' in the dependencies section.
and after that everything is running OK again.
Today I was reading multidex user guide in d.android.com site ( link here ) and it says that I should also override MultiDexApplication class (since I already extend from Application ).
My question is : since I'm not extending MultiDexApplication how is it possible, by doing only the two things I mentioned above, not to receive the Exception I was receiving before ? And what should I do now ? Should I try and extend MultiDexApplication even if now everything is OK?
Your code must be near in the number limit of methods, i recomend make the total implementation. Otherwise you can review your dependencies and remove those you are not using and use ProGuard. Good pratice is helpfull, like prefer use methods private when possible.
You have some possibilities to use MultiDex.
Minimal MultiDex capable application. To use the legacy multidex
library there is 3 possibility:
Declare this class as the application in your AndroidManifest.xml.
Have your Application extends this class.
Have your Application override attachBaseContext starting with protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this);
The last one should fit for you.
Related
I have an issue with R8. In MyLib I have public abstract MyLibsClass in which I have protected methods. MyChildClass extends from MyLibsClass in MyApp and after R8's magic all protected methods (including protected abstract) in MyLibsClass are changed into public ones, and of course in MyChildClass I'm getting "attempting to assign weaker access privileges ('protected'); was 'public') issue as trying to override protected abstract methods.
Additional info
gradle-6.0.1
MyLib's build.gradle
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro'
}
proguard-rules.pro
-keep class com.example.mylib.*{
public protected *; }
-keep class com.example.mylib.*$*{
public protected *; }
Anyone had this kind of issue or know a way to fix this?
So based on discussion here ,
DON'T USE DEFAULT PROGUARD SETTINGS FOR LIBRARIES
as allowAccessModification is enabled in default proguard settings, which is located in Android SDK (\Android\Sdk\tools\proguard\proguard-android-optimize.txt) and my mistake was using this for my libraries.
Citation from proguard manual
you probably shouldn't use this option when processing code that is to
be used as a library, since classes and class members that weren't
designed to be public in the API may become public.
So if anyone has the same issue I will suggest to create your own base config file for proguard and copy past whole default configs without "allowAccessModification" into it.
Also if someone interested more, you can track this issue. Hopefully will get separate config file for libraries in near feature.
I faced the same problem, and thanks to #Hayk Nahapetyan's answer, I could resolve it.
Here is my solution with a little more detail.
In the library module's build.gradle, remove the default file from the buildTypes's release closure:
release {
minifyEnabled true
proguardFiles 'proguard-rules.pro'
}
R8 no longer uses the default file that is provided in the Android SDK. It generates one at build time, and puts it in the module's build directory at build/intermediates/default_proguard_files/global.
Copy the contents of proguard-android-optimize.txt-a.b.c (where a.b.c is the library version, if set) from that location to the top of the module's proguard-rules.pro. Then remove -allowaccessmodification; two times, if it originally appeared in both files.
This was also reported on the R8 bug tracker, and resolved there. See http://issuetracker.google.com/147447502.
Timber is a great library for logging in Android. In Kotlin classes though, doesn't output anything. How can I fix this?
MainActivity.kt code:
Timber.e("Timber Log 1")
Log.e("MainActivity", "Log 1")
Gradle:
I've tried the regular Java Timber:
implementation 'com.jakewharton.timber:timber:4.7.1'
And this Kotlin specific wrapper:
implementation 'com.github.ajalt:timberkt:1.5.1'
Same result. No output with either. Only from the Log.e()
The first step of Timber is to plant the tree as mentioned in docs
Behavior is added through Tree instances. You can install an instance
by calling Timber.plant. Installation of Trees should be done as early
as possible. The onCreate of your application is the most logical
choice.
And use the debugTree
The DebugTree implementation will automatically figure out from which
class it's being called and use that class name as its tag. Since the
tags vary
If you don't do this then you will have no logs entry and do this as soon as possible, like in oncreate or better inside application class so do this
Timber.plant(Timber.DebugTree());
I have faced same problem, using Kotlin and Android studio 3.6
Follow these steps:
Add the following in build.gradle(Module: App)
implementation 'com.jakewharton.timber:timber:4.7.1'
Initialize Timber in Application Class:
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
if(BuildConfig.DEBUG){
Timber.plant(Timber.DebugTree())
}
}
}
Add the Application class(MyApp) to the Manifest (AndroidManifest.xml)
<application
android:name=".MyApp"
Now you can use Timber: Timber.i("Timber logs")
Also can use custom tags if you wish: Timber.tag("Yo").I("used custom tag for logs")
In my case it was wrong BuildConfig import
import org.koin.android.BuildConfig
but my app has
import com.company.example.BuildConfig
Probably late to the party but my problem was the my phone was set to "Charge only" and not "file transfer". Apparently I was allowed to build and run, but logs were blocked
EDIT Another solution:
Check your RUN tab in the bottom of Android Studio. Sometimes the logs get output to there instead
For me it started showing up when I commented the Debug check
// if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree());
// }
I don't know why this is working because the build varient is selected to debug only.
I'm trying to build an Android app that I've been working on (it's a project I adopted so most of the code isn't mine - which isn't helping :P) and I'm running into an issue.
The app builds just fine in debug mode (building and installing it on a device for testing). But when I try to build a release it fails.
This is the error in the gradle console:
Execution failed for task ':app:lintVitalRelease'.
Lint found fatal errors while assembling a release target.
And this is what it says in Messages Gradle Build:
Error:Error: This fragment class should be public ([com.company.appname].fragments.create_dilemma.CreateDilemmaFragment1_2.UploadDialogFragment) [ValidFragment]
This is the offending line:
private class UploadDialogFragment extends DialogFragment implements View.OnClickListener
So I change private to public and then it complains that it should be a static class. Thing is, it looks like this class isn't supposed to be static because AS isn't happy with pretty much any of the code as soon as I make it static.
So I'm left with a few questions:
How is this only an issue for the release build and not for debug?
Is there a way to ignore this 'error' when building a release?
There must be a reason for this error, right? Why is it ignored for debug and not for release? What are the up/downsides of fixing this? Because the app works just fine as far as I can tell so I don't really see the problem..?
PS: My java skills are so-so. I know my way around the language but I have a lot to learn when it comes to knowing what a static class exactly is and what is allowed and what not, why it is(n't), etc. So plz be gentle, I'm trying to learn this stuff :)
Update: As per request here's the relevant part of my build.gradle:
android {
compileSdkVersion 24
buildToolsVersion '24.0.1'
useLibrary 'org.apache.http.legacy'
defaultConfig {
applicationId "[com.pany.appname]"
minSdkVersion 15
targetSdkVersion 22
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
productFlavors {
}
}
I'm summarizing some of the answers given in this post to collect them in one. Makes it easier to accept it, too :)
-- WHY THE QUICK FIX IS NOT A REAL FIX --
It's POSSIBLE to have this project build a release apk successfully (see below). But it's probably not a good idea to just do that and not think about it.
As pointed out by X3Btel:
Fragments needs to be public because systems recreates them on orientation change. The other warning is because non static inner classes holds reference to their outter class, hence it creates memmory leak. Best course of action would be move the fragment to his own class. Or make it public and ignore the lint warning (this may create memmory leak but keeping it private may crash the app)
In my case I can keep it non-static and circumvent memory leaks by making sure I finish the fragment whenever its parent activity is finished. It's not pretty but it'll fix the memory leak and I don't have to refactor A LOT of code I didn't write. That said: It apparently is bad practice to have an activity or fragment and declare another activity/fragment as an inner class because of the way the Android lifecycle works.
Here's some more reading on the topic which I found useful (and only found AFTER I posted this question):
Should an internal DialogFragment class be static or not?
-- THE QUICK FIXES --
1) Don't check for lint errors during build (as pointed out by Jay Shan)
Add lintOptions -> checkReleaseBuilds option to build.gradle
android {
// ..
lintOptions {
checkReleaseBuilds false
}
}
2) Check for errors but keep building even when they are found
This is probably a little bit safer than not checking for errors at all because at least you'll get a warning somewhere in the log output.
Add lintOptions -> abortOnError option to build.gradle
android {
// ..
lintOptions {
abortOnError false
}
}
3) Supress the error where it happens
I find this to be the preferred method because you can still use lint for finding other problems AND have it abort when that happens BUT at the same time you can ignore things you've checked.
In my case I had to add #SuppressLint("ValidFragment") before the offending line:
#SuppressLint("ValidFragment")
private class UploadDialogFragment extends DialogFragment implements View.OnClickListener
{
// ..
}
UPDATE 2018/01/04
If you use a recent version of Android Support Library (and its Fragment implementation instead of the OS's) your app will crash (IllegalStateException) if you try to initialize that Fragment. Suppressing the warning will not help you. You'll just have to fix the underlying problem, make the inner class public and static, or move the class to a separate file.
You can put this option in android block of build.gradle section
lintOptions {
checkReleaseBuilds false
}
Jay Shan`s answer should work. But better to understand what is the problem. Fragments needs to be public because systems recreates them on orientation change. The other warning is because non static inner classes holds reference to their outter class, hence it creates memmory leak.
Best course of action would be move the fragment to his own class. Or make it public and ignore the lint warning (this may create memmory leak but keeping it private may crash the app)
for reporting my Application Crashes use Acra library via Android Studio Gradle Dependencies in this form :
dependencies {
compile 'ch.acra:acra:4.6.2'
}
Now in Bebug version it work and return crash report goodly but after export Release version of application not work and return this error in logcat :
Not adding buildConfig to log. Class Not found : " + className + ". Please configure 'buildConfigClass' in your ACRA config
Then i use acra-4-6-2.jar file instead dependencies but not work still!
Too before saw this link but was not helpful fore me.
With thanks for your attention
It sounds like you are Proguardng your app on release but have not added the relevant ACRA classes to your Proguard config.
See https://github.com/ACRA/acra/wiki/ProGuard
None of the other answers actually provided the fix.
To fix this issue, assign your BuildConfig.class to the buildConfigClass field on your ReportsCrashes annotation declaration.
#ReportsCrashes(
buildConfigClass = BuildConfig.class )
public class YourApplication extends Application { ... }
If you are using so called "dynamic" configuration you are probably having "empty" annotation like #ReportsCrashes().
In that case it turns out that ACRA does not create proper default config. The solution is simple: just add some fake property there like:
#ReportsCrashes(formUri = "placeholder")
which you will later override in the dynamic config...
What's the solution for 65k ? I tried almost all the post but still not able to . Working on Android Studio but it is not letting me enable multidex option . Anyone having idea about it?
Any idea how to integrate with eclipse?
For Android Studio and Gradle the answer is here:
https://developer.android.com/tools/building/multidex.html#mdex-gradle
In Eclipse import the MultiDex library project from this location:
[android-sdk]\extras\android\support\multidex\library
Next you have three options:
Option 1
In your AndroidManifest.xml file update your <application> element like so:
<application
name="android.support.multidex.MultiDexApplication">
...
</application>
Option 2
If you use custom Application class make sure you extend MultiDexApplication.
MyApplication.java
public class MyApplication extends MultiDexApplication {
...
}
AndroidManifest.xml
<application
name=".MyApplication">
...
</application>
Option 3
If your application class cannot extend MultiDexApplication for some reason override the following method:
MyApplication.java
public class MyApplication extends Application {
...
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}
AndroidManifest.xml
<application
name=".MyApplication">
...
</application>
Source: https://developer.android.com/reference/android/support/multidex/MultiDexApplication.html
Warning: Eclipse build tools do not support multidex. Look here for further info:
Android multidex support library using eclipse
I did this tut and worked http://android-developers.blogspot.com.es/2011/07/custom-class-loading-in-dalvik.html
I have now rhino.jar in a dex file in my asset folder
This problem is solved with Android studio 1.0 and above. We need to set multidexEnabled parameter to true.
That's all we need to implement. So, if anyone what to solve this problem you need to go with android studio.