Roboblender use annotation databases with multiple modules - android

I'm following the steps from the RoboBlender Wiki to use annotations database but I keep getting java.lang.IllegalStateException: Unable to use annotation database(s) because it cannot find AnnotationDatabaseImpl
I am using Android Studio and Gradle. The project consists of multiple modules.
app
moduleA
moduleB
moduleC
Here is what I added to my build scripts:
app/build.gradle:
dependencies {
provided 'org.roboguice:roboblender:3.0.1'
provided 'org.roboguice:roboblender:3.0.1'
}
project.tasks.withType(JavaCompile) { task ->
options.compilerArgs << "-AguiceAnnotationDatabasePackageName=com.sample.myapp"
}
module[x]/build.gradle:
project.tasks.withType(JavaCompile) { task ->
options.compilerArgs << "-AguiceAnnotationDatabasePackageName=com.sample.module[x]"
}
On the Application Object:
RoboGuice.setUseAnnotationDatabases(true);
RoboGuice.getOrCreateBaseApplicationInjector(this, RoboGuice.DEFAULT_STAGE,
RoboGuice.newDefaultRoboModule(this), new MyModule());
RoboGuice.injectMembers(this, this);
Am I missing something? I found some similar questions but they weren't very useful.
Update:
I forgot to add it on the first time but yes I am including the manifest meta.
<meta-data android:name="roboguice.modules" android:value="your.package.MyModule"/>
<meta-data android:name="roboguice.annotations.packages" android:value="com.sample.myapp,com.sample.modulex,com.sample.moduley"/>
Update 2:
I finally found the problem. Proguard was deleting the class. Fixed by adding:
-keep public class * extends com.google.inject.AnnotationDatabase

Did you list your module and your annotation databases in your AndroidManifest.xml?
<meta-data android:name="roboguice.modules" android:value="your.package.MyModule"/>
<meta-data android:name="roboguice.annotations.packages" android:value="com.sample.myapp,com.sample.modulex,com.sample.moduley"/>

After some hours I found the problem. It was proguard. Adding the following line fixed the issue.
-keep public class * extends com.google.inject.AnnotationDatabase
You can check that the classes are being generated by running in the project folder:
find . | grep -i AnnotationDatabaseImpl

Related

Proguard rules for Jetpack GameActivity

I'm trying to use Jetpack GameActivity in my project, but I encounter a strange issue with Proguard. My project has 2 modules, app and my-lib:
my-lib module has MyActivity which extends GameActivity:
api 'androidx.games:games-activity:1.2.1'
app module has MainActivity which extends MyActivity from my-lib module
implementation project(":my-lib")
When I built my project in Release build and had Proguard enabled, I got a native crash:
Abort message: 'Unable to find method setWindowFlags'
=> I tried inspecting GameActivity class from my APK, setWindowFlags method didn't exist at all, which means Proguard has removed it, that's why the native part of the GameActivity library couldn't find the method and it threw an error.
Then, I tried to fix it, by adding Proguard rule like this:
-keep, includedescriptorclasses class com.google.androidgamesdk.GameActivity { *; }
But unfortunately, I got another native crash:
Abort message: 'Unable to find field left'
=> Why does this happen? I tried inspecting the APK again, but have no idea why
Anyway, how can I deal with this situation? Does Jetpack GameActivty need to add Proguard rules to keep methods that will be used by the native part?
There is a know issue in version 1.2.1 and before: the java functions called by native code only were stripped out by proguard for the release build. Version 1.2.2-alpha01 has fixed that and a few other important potential issues, including the static library release in the AAR. To use the 1.2.2-alpha01+:
Add the latest version to the dependency: 1.2.2-alpha01+
Use C/C++ static lib release in the AAR.
add the following or something similar to your project's existing CMakeLists.txt
find_package(game-activity REQUIRED CONFIG)
add_library(${PROJECT_NAME} SHARED sth.cpp) #<=== this is your own.
target_link_libraries(${PROJECT_NAME} game-activity::game-activity_static
# optional: does not hurt to add it; refer to the official doc for update.
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -u \
Java_com_google_androidgamesdk_GameActivity_initializeNativeCode")
If want to use the source code directly(not recommended), do something similar to this:
# Find GameActivity sources to build.
find_package(game-activity REQUIRED CONFIG)
get_target_property(GAME_ACTIVITY_INCLUDE_PATH
game-activity::game-activity
INTERFACE_INCLUDE_DIRECTORIES)
string(REPLACE "include" "" GAME_ACTIVITY_SRCS ${GAME_ACTIVITY_INCLUDE_PATH})
file(GLOB_RECURSE GAME_ACTIVITY_SRCS
${GAME_ACTIVITY_INCLUDE_PATH}/*.c*)
add_library(${PROJECT_NAME} SHARED
sth.cpp. #<== this is your own file
${GAME_ACTIVITY_SRCS})
target_link_libraries(${PROJECT_NAME} PUBLIC
android log
game-activity::game-activity
# other libs
)
Note: it is still just 3 source files now, and you can unzip the latest AAR and list them explicitly like:
add_library(${PROJECT_NAME} SHARED
sth.cpp. #<== this is your own file
${GAME_ACTIVITY_INCLUDE_PATH}/game-activity/GameActivity.cpp
${GAME_ACTIVITY_INCLUDE_PATH}/game-activity/native_app_glue/android_native_app_glue.c
${GAME_ACTIVITY_INCLUDE_PATH}/game-text-input/gametextinput.cpp)
The glob way might be better for future compatibility reasons; but it is not cmake recommended way to do things.
Handle the the "back" button press to exit app either from Kotlin/Java side(handle KEYCODE_BACK in onKeyDown()) or native code (AKEYCODE_BACK in input key event processing).
Referring to the documentation page and probably the list above, you should be able to get your project going. The simple fact is this: all of the C/C++ things are inside AAR, under the prefab sub-directory, you even can copy it out and directly put into your own source tree. This Pull Request might help (but not totally sure).
If you see something or like some new things, please create a bug.
I had the same issues as you and I solved this by adding the following line to my proguard-rules.pro file:
-keep class com.google.androidgamesdk.** { *; }
Of course then I had other proguard related errors so I had to add these
additional lines:
-keep class androidx.core.graphics.Insets { *; }
-keep class androidx.core.view.** { *; }
-keep class org.fmod.** { *; }
Of course you will have different errors in your build, but hopefully this will help you.

Branch.io does not work with multidex because of manifest conflict

Branch wants me to use the "android:name" in the manifests file, but I already use it for multidex. So, how to overcome this conflict?
<application
...
//android:name="io.branch.referral.BranchApp"
android:name="android.support.multidex.MultiDexApplication"
...
</application>
This is the entire code of BranchApp:
public class BranchApp extends Application {
#Override
public void onCreate() {
super.onCreate();
if (BranchUtil.isTestModeEnabled(this) == false) {
Branch.getInstance(this);
} else {
Branch.getTestInstance(this);
}
}
}
Make a custom Application class that extends MultiDexApplication, and use this override for the onCreate and you're good.
The Branch SDK has its own custom activity and application class. Other plugins that use their own custom activity and application classes can cause "conflicts" between these classes. To resolve these conflicts:
Create an empty android library
Add the Branch plugin along with the other plugins into your project
Create a custom Activity and Application class that will contain the custom logic for all your plugins
Build your library
Add your library into Unity project
Change android:name to name of your custom Application class in the application tag of your Manifest
Change android:name to name of your custom Activity class in the activity tag of your Manifest
Some Plugins expand the default AppController the same was as Branch does like Cardboard SDK plugin. To resolve conflicts:
Merge all custom AppControllers in one.
Comment code in other AppControllers (or delete other AppControllers).
Here are some Code Samples for resolving conflicts with other 3rd party plugins
If you still face any issues, please write to integrations#branch.io with the details.

Error: Cannot fit requested classes in a single dex file (# methods: 67593 > 65536)

How to solve this error I'm getting in Android Studio:
Error: Cannot fit requested classes in a single dex file (# methods: 67593 > 65536)
cant build my project now
Do this 4 step
1: Add this library in dependencies of the app build.gradle :
implementation 'com.android.support:multidex:1.0.3'
2: Add in the defaultConfig of the app build.gradle :
defaultConfig {
//other configs
multiDexEnabled true //add this line
}
3: Create new Java class like this :
public class ApplicationClass extends MultiDexApplication {
#Override
public void onCreate() {
super.onCreate();
}
}
4: Add this to your manifest (in application tag):
<application
android:name=".ApplicationClass"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name">
Same situation happened in my Visual Studio 2019 Xamarin project, and the way to solve this problem is just like what mentioned in the link:
Error:Cannot fit requested classes in a single dex file.Try supplying a main-dex list. # methods: 72477 > 65536
multiDexEnabled true
By checking the Enable multiDex checkbox in the option page of the ***.Droid project solves the problem.
Before you take any decision, as said in Google documentation :
Before configuring your app to enable use of 64K or more method
references, you should take steps to reduce the total number of
references called by your app code, including methods defined by your
app code or included libraries.
So try to remove useless importation in your app gradle and do a nice clean project or do multidex
Source : https://developer.android.com/studio/build/multidex

how to create an application havind multidex files with multidex library?

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.

DexIndexOverflowException with build tool 21.0.0 [duplicate]

I have seen various versions of the dex erros before, but this one is new. clean/restart etc won't help. Library projects seems intact and dependency seems to be linked correctly.
Unable to execute dex: method ID not in [0, 0xffff]: 65536
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536
or
Cannot merge new index 65950 into a non-jumbo instruction
or
java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
tl;dr: Official solution from Google is finally here!
http://developer.android.com/tools/building/multidex.html
Only one small tip, you will likely need to do this to prevent out of memory when doing dex-ing.
dexOptions {
javaMaxHeapSize "4g"
}
There's also a jumbo mode that can fix this in a less reliable way:
dexOptions {
jumboMode true
}
Update: If your app is fat and you have too many methods inside your main app, you may need to re-org your app as per
http://blog.osom.info/2014/12/too-many-methods-in-main-dex.html
Update 3 (11/3/2014)
Google finally released official description.
Update 2 (10/31/2014)
Gradle plugin v0.14.0 for Android adds support for multi-dex. To enable, you just have to declare it in build.gradle:
android {
defaultConfig {
...
multiDexEnabled true
}
}
If your application supports Android prior to 5.0 (that is, if your minSdkVersion is 20 or below) you also have to dynamically patch the application ClassLoader, so it will be able to load classes from secondary dexes. Fortunately, there's a library that does that for you. Add it to your app's dependencies:
dependencies {
...
compile 'com.android.support:multidex:1.0.0'
}
You need to call the ClassLoader patch code as soon as possible. MultiDexApplication class's documentation suggests three ways to do that (pick one of them, one that's most convenient for you):
1 - Declare MultiDexApplication class as the application in your AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.multidex.myapplication">
<application
...
android:name="android.support.multidex.MultiDexApplication">
...
</application>
</manifest>
2 - Have your Application class extend MultiDexApplication class:
public class MyApplication extends MultiDexApplication { .. }
3 - Call MultiDex#install from your Application#attachBaseContext method:
public class MyApplication {
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
....
}
....
}
Update 1 (10/17/2014):
As anticipated, multidex support is shipped in revision 21 of Android Support Library. You can find the android-support-multidex.jar in /sdk/extras/android/support/multidex/library/libs folder.
Multi-dex support solves this problem. dx 1.8 already allows generating several dex files.
Android L will support multi-dex natively, and next revision of support library is going to cover older releases back to API 4.
It was stated in this Android Developers Backstage podcast episode by Anwar Ghuloum. I've posted a transcript (and general multi-dex explanation) of the relevant part.
As already stated, you have too many methods (more than 65k) in your project and libs.
Prevent the Problem: Reduce the number of methods with Play Services 6.5+ and support-v4 24.2+
Since often the Google Play services is one of the main suspects in "wasting" methods with its 20k+ methods. Google Play services version 6.5 or later, it is possible for you to include Google Play services in your application using a number of smaller client libraries. For example, if you only need GCM and maps you can choose to use these dependencies only:
dependencies {
compile 'com.google.android.gms:play-services-base:6.5.+'
compile 'com.google.android.gms:play-services-maps:6.5.+'
}
The full list of sub libraries and it's responsibilities can be found in the official google doc.
Update: Since Support Library v4 v24.2.0 it was split up into the following modules:
support-compat, support-core-utils, support-core-ui, support-media-compat and support-fragment
dependencies {
compile 'com.android.support:support-fragment:24.2.+'
}
Do note however, if you use support-fragment, it will have dependencies to all the other modules (ie. if you use android.support.v4.app.Fragment there is no benefit)
See here the official release notes for support-v4 lib
Enable MultiDexing
Since Lollipop (aka build tools 21+) it is very easy to handle. The approach is to work around the 65k methods per dex file problem to create multiple dex files for your app. Add the following to your gradle build file (this is taken from the official google doc on applications with more than 65k methods):
android {
compileSdkVersion 21
buildToolsVersion "21.1.0"
defaultConfig {
...
// Enabling multidex support.
multiDexEnabled true
}
...
}
dependencies {
compile 'com.android.support:multidex:1.0.1'
}
The second step is to either prepare your Application class or if you don't extend Application use the MultiDexApplication in your Android Manifest:
Either add this to your Application.java
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
or use the provided application from the mutlidex lib
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.myapplication">
<application
...
android:name="android.support.multidex.MultiDexApplication">
...
</application>
</manifest>
Prevent OutOfMemory with MultiDex
As further tip, if you run into OutOfMemory exceptions during the build phase you could enlarge the heap with
android {
...
dexOptions {
javaMaxHeapSize "4g"
}
}
which would set the heap to 4 gigabytes.
See this question for more detail on the dex heap memory issue.
Analyze the source of the Problem
To analyze the source of the methods the gradle plugin https://github.com/KeepSafe/dexcount-gradle-plugin can help in combination with the dependency tree provided by gradle with e.g.
.\gradlew app:dependencies
See this answer and question for more information on method count in android
Your project is too large. You have too many methods. There can only be 65536 methods per application. see here https://code.google.com/p/android/issues/detail?id=7147#c6
The below code helps, if you use Gradle. Allows you to easily remove unneeded Google services (presuming you're using them) to get back below the 65k threshold. All credit to this post: https://gist.github.com/dmarcato/d7c91b94214acd936e42
Edit 2014-10-22: There's been a lot of interesting discussion on the gist referenced above. TLDR? look at this one: https://gist.github.com/Takhion/10a37046b9e6d259bb31
Paste this code at the bottom of your build.gradle file and adjust the list of google services you do not need:
def toCamelCase(String string) {
String result = ""
string.findAll("[^\\W]+") { String word ->
result += word.capitalize()
}
return result
}
afterEvaluate { project ->
Configuration runtimeConfiguration = project.configurations.getByName('compile')
ResolutionResult resolution = runtimeConfiguration.incoming.resolutionResult
// Forces resolve of configuration
ModuleVersionIdentifier module = resolution.getAllComponents().find { it.moduleVersion.name.equals("play-services") }.moduleVersion
String prepareTaskName = "prepare${toCamelCase("${module.group} ${module.name} ${module.version}")}Library"
File playServiceRootFolder = project.tasks.find { it.name.equals(prepareTaskName) }.explodedDir
Task stripPlayServices = project.tasks.create(name: 'stripPlayServices', group: "Strip") {
inputs.files new File(playServiceRootFolder, "classes.jar")
outputs.dir playServiceRootFolder
description 'Strip useless packages from Google Play Services library to avoid reaching dex limit'
doLast {
copy {
from(file(new File(playServiceRootFolder, "classes.jar")))
into(file(playServiceRootFolder))
rename { fileName ->
fileName = "classes_orig.jar"
}
}
tasks.create(name: "stripPlayServices" + module.version, type: Jar) {
destinationDir = playServiceRootFolder
archiveName = "classes.jar"
from(zipTree(new File(playServiceRootFolder, "classes_orig.jar"))) {
exclude "com/google/ads/**"
exclude "com/google/android/gms/analytics/**"
exclude "com/google/android/gms/games/**"
exclude "com/google/android/gms/plus/**"
exclude "com/google/android/gms/drive/**"
exclude "com/google/android/gms/ads/**"
}
}.execute()
delete file(new File(playServiceRootFolder, "classes_orig.jar"))
}
}
project.tasks.findAll { it.name.startsWith('prepare') && it.name.endsWith('Dependencies') }.each { Task task ->
task.dependsOn stripPlayServices
}
}
I've shared a sample project which solve this problem using custom_rules.xml build script and a few lines of code.
I used it on my own project and it is runs flawless on 1M+ devices (from android-8 to the latest android-19). Hope it helps.
https://github.com/mmin18/Dex65536
Faced the same problem and solved it by editing my build.gradle file on the dependencies section, removing:
compile 'com.google.android.gms:play-services:7.8.0'
And replacing it with:
compile 'com.google.android.gms:play-services-location:7.8.0'
compile 'com.google.android.gms:play-services-analytics:7.8.0'
Try adding below code in build.gradle, it worked for me -
compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
multiDexEnabled true
}
The perfect solution for this would be to work with Proguard. as aleb mentioned in the comment.
It will decrease the size of the dex file by half.
You can analyse problem (dex file references) using Android Studio:
Build -> Analyse APK ..
On the result panel click on classes.dex file
And you'll see:
gradle + proguard solution:
afterEvaluate {
tasks.each {
if (it.name.startsWith('proguard')) {
it.getInJarFilters().each { filter ->
if (filter && filter['filter']) {
filter['filter'] = filter['filter'] +
',!.readme' +
',!META-INF/LICENSE' +
',!META-INF/LICENSE.txt' +
',!META-INF/NOTICE' +
',!META-INF/NOTICE.txt' +
',!com/google/android/gms/ads/**' +
',!com/google/android/gms/cast/**' +
',!com/google/android/gms/games/**' +
',!com/google/android/gms/drive/**' +
',!com/google/android/gms/wallet/**' +
',!com/google/android/gms/wearable/**' +
',!com/google/android/gms/plus/**' +
',!com/google/android/gms/topmanager/**'
}
}
}
}
}
Remove some jar file from Libs folder and copy to some other folder, And Go to _Project Properties > Select Java Build Path, Select Libraries, Select Add External Jar, Select the Removed jar to your project, Click save, this will be added under Referenced Library instead of Libs folder. Now clean and Run your project. You dont need to add Any code for MultDex. Its simply worked for me.
I was facing the same issue today what worked for is below down
For ANDROID STUDIO... Enable Instant Run
In File->Preferences->Build, Execution, Deployment->Instant Run-> Check Enable Instant run for hot swap...
Hope it helps

Categories

Resources