How to make Android apps which support both 32-bit and 64-bit architecture?
Asked Answered
M

12

40

I've just received and read a newsletter from Google Play mentioning that from next year on, the store "will require that new apps and app updates with native libraries provide 64-bit versions in addition to their 32-bit versions".

For those who haven't read it yet, it states:

64-bit support requirement in 2019

Platform support for 64-bit architectures was introduced in Android 5.0. Today, over 40% of Android devices coming online have 64-bit support, while still maintaining 32-bit compatibility. For apps that use native libraries, 64-bit code typically offers significantly better performance, with additional registers and new instructions.

In anticipation of future Android devices that support 64-bit code only, the Play Console will require that new apps and app updates with native libraries provide 64-bit versions in addition to their 32-bit versions. This can be within a single APK or as one of the multiple APKs published.

We are not removing 32-bit support. Google Play will continue to support 32-bit apps and devices. Apps that do not include native code are unaffected.

This change will come into effect in August 2019. We're providing advance notice today to allow plenty of time for developers who don't yet support 64-bit to plan the transition. Stay tuned for a future post in which we'll take an in-depth look at the performance benefits of 64-bit native libraries on Android, and check out the CPUs and Architectures guide of the NDK for more info.

What practical changes will we need to make to perfectly comply with this new requirement when applicable?

Matriarch answered 31/1, 2018 at 19:0 Comment(6)
If you have your own NDK code, it will need to support 64-bit versions of ABIs. If you do not have your own NDK code, but you are using libraries that do, they will need to offer versions of their libraries that support 64-bit CPU architectures.Regalia
Thanks for the answer, CommonsWare! Judging by your answer and the things I read, it doesn't seem to be that complicated. Just let me ask you one more thing: if a developer neither own nor use NDK code, does it mean regular apps are already ready for both? Also, if you'd like to deliver the text as an answer, I'd be pleased to accept it at ease.Matriarch
"if a developer neither own nor use NDK code, does it mean regular apps are already ready for both?" -- since I am uncertain what you mean by "neither own nor use", I cannot answer that, sorry. To put it another way: if you examine your APK (e.g., Analyze APK in Android Studio), and you do not find a lib/ directory containing .so files, then there is nothing that you need to do with respect to this upcoming requirement. If you do find .so files, and you do not see 64-bit architectures in the roster, you need to find the source of those .so files and update them.Regalia
Sorry for the way I asked you the question (it was the first thing I did after I woke up today). Anyway, you practically clarified all my doubts regarding this topic and I thank you so much for your attention and support.Matriarch
How can I know which dependency is having that .so file @RegaliaPauperism
@kvadityaaz: Hopefully, you can identify it via the .so filename. Perhaps it will be obvious, or perhaps a search on it will turn up a match. Otherwise, you could copy your dependencies into a scrap project, confirm the .so appears in that scrap project's app, then start commenting out dependencies until you find which one pulls in the .so.Regalia
M
28

According to an official email sent by the Google Play Team, the action required is:

If you haven't yet, we encourage you to begin work for the 64-bit requirement as soon as possible. Many apps are written entirely in non-native code (e.g. the Java programming language or Kotlin) and will not need code changes.

Please note that we are not making changes to our policy on 32-bit support. Google Play will continue to deliver apps with 32-bit native code to 32-bit devices. The requirement means that those apps will need to have a 64-bit version as well.

To help you make the transition, we've prepared documentation on how to check whether your app already supports 64-bit and how to become 64-bit compliant.

We're also providing a high-level timeline below.

So, the linked documentation explains:

If your app uses only code written in the Java programming language or Kotlin, including any libraries or SDKs, your app is already ready for 64-bit devices. If your app uses any native code, or you are unsure if it does, you will need to assess your app and take action.

[...]

The simplest way to check for 64-bit libraries is to inspect the structure of your APK file. When built, the APK will be packaged with any native libraries needed by the app. Native libraries are stored in various folders based on the ABI. It is not required to support every 64-bit architecture, but for each native 32-bit architecture you support you must include the corresponding 64-bit architecture.

For the ARM architecture, the 32-bit libraries are located in armeabi-v7a. The 64-bit equivalent is arm64-v8a.

For the x86 architecture, look for x86 for 32-bit and x86_64 for 64-bit.

The first thing to do is ensure that you have native libraries in both of these folders.[...]

And, to build 64-bit libraries, you basically need to follow the instructions below:

Most Android Studio projects use Gradle as the underlying build system, so this section applies to both cases. Enabling builds for your native code is as simple as adding the arm64-v8a and/or x86_64, depending on the architecture(s) you wish to support, to the ndk.abiFilters setting in your app's 'build.gradle' file:

// Your app's build.gradle
apply plugin: 'com.android.app'

android {
   compileSdkVersion 27
   defaultConfig {
       appId "com.google.example.64bit"
       minSdkVersion 15
       targetSdkVersion 28
       versionCode 1
       versionName "1.0"
       ndk.abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
// ...

Finally, a quick note:

The 64-bit version of your app should offer the same quality and feature set as the 32-bit version.

By the way, this official video talks a little bit about it.

Matriarch answered 1/2, 2019 at 6:57 Comment(6)
Great answer, very helpful. Although I believe there is a syntax error in your answer. ndk.abiFilters = ... should not have an equals sign =. I will edit your answer to remove this. Hope you do not mind. BTW, this answer seems to confirm that the equal sign is not needed: https://mcmap.net/q/408348/-error-could-not-find-method-armeabi-v7a-for-arguments-arm64-v8aGrenade
No problem, @EJK, but I had just copied from their own documentartion which still states: "ndk.abiFilters = 'armeabi-v7a' 'arm64-v8a' 'x86' 'x86_64". What's weird! However, as this answer hasn't been useful for personal use yet, I can't confirm if it works with the signal or not.Matriarch
In recent Android Studio builds, ndk.abiFilters 'armeabi-v7a' 'arm64-v8a' 'x86' 'x86_64' needs to have commas between like this: ndk.abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'Capillaceous
Have you found a way around, @Debugger?Matriarch
Yes,I found @MatriarchMyriagram
I have added this line in gradle but now the error says that i need to add 64bit and 32 bit native code in your app. Any further steps needed.I am only using realm in my project "implementation 'io.realm:realm-android:0.82.1"Luckily
L
13

If you have no native (NDK) code, that is you only write Java/Dex code, then you don't need to do anything.

If you have native code (or libraries) then you need to supply their 64-bit versions.

Lipoprotein answered 2/2, 2018 at 16:5 Comment(2)
how can i supply 64-bit versions ?if i have ndk in my appRuberta
Make sure you compile for the 64 bit targets as described in the NDK docs on this page. Specifically x86_64 if you use x86 and arm64-v8a if you use armeabi-v7a.Lipoprotein
A
11

As per documentation here, if your app is using native code or external library, for example, realm (in the picture below) which is based on native, then a support for 64-bit should be provided. If any of external libraries in your app which uses any C/C++ (native) should have both 32-bit and 64-bit architecture support otherwise you should make contact with the library owner. In Android Studio, we can check whether versions for both architectures are available by Build > Analyze APK and the following window appears:

Android Studio tab showing available architectures

If you are using NDK and creating native code, you should provide support for all architecture by enlisting them in the gradle as:

defaultConfig {  
   ndk.abiFilters = 'armeabi-v7a' 'arm64-v8a' 'x86' 'x86_64'
   }
Alvy answered 5/3, 2019 at 11:11 Comment(5)
I have added this but when I analyze, I only see armeabi-v7a & x86 and not others. Any suggestions?Dotson
Same with @TusharGogna ... Have you solved yours @Tushar?Tripoli
Hello, yes I dug deep and figured that one of the 3rd party libs (in my case Here Maps) wasn't updated. The lib wasn't having 64 bit support. Once I updated it to the latest version, it worked. So make sure all the 3rd party libs are updated to the latest versions and then try again.Dotson
@TusharGogna is there a way to quickly check which libs that doesn't support 64 bit? I'm a bit confuse what to check.. :)Tripoli
This was the solution for me. I was flummoxed to see Google Play complain about 32-bit code, since I wasn't using any native code myself, and neither were any of my dependencies (or so I thought). Of course, it turned out one of my dependencies was transitively adding a very old 32-bit version of sqlcipher to my project. Would never have found it without this tip - thanks!Mathilda
B
7

If your Android APK is not including 64-bit support, you need not to worry. Go to Build -> Analyze APK, in Android Studio. You are able to see APK structure. Under lib, if you see armeabi-v7a libraries and if you do not have any arm64-v8a or x86_64 libraries, then your APK does not support 64-bit architecture.

Just go to app level build.gradle and add abiFilters in NDK under defaultConfig as below:

ndk {
    abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
}
Bedell answered 11/7, 2019 at 11:37 Comment(3)
adding commas saved the day for me!Capillaceous
I tried this and still it doesn't add the 64bit support.. I still see only 'armeabi-v7a' and 'x86' Is there anything I've missed?Tripoli
Can you please show me defaultConfig block from your build.gradle file?Bedell
A
4

Step 1 :

app=> build.gradle (put below code in build.gradle)

android {
........

 defaultConfig {

 .........

   ndk {
            abiFilters = []
            abiFilters.addAll(PROP_APP_ABI.split(':').collect{it as String})
        }
........        
}
.......
 packagingOptions {
        exclude 'lib/armeabi-v7a/libARM_ARCH.so'
    }

}

Step : 2

gradle.properties

(put below line in gradle.properties)

PROP_APP_ABI=armeabi-v7a:arm64-v8a

Step 3 : Build propject again. Try to upload that apk to play store.

Alley answered 13/6, 2020 at 12:29 Comment(0)
O
2

Adding

ndk {
    abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
} 

in the build.Gradle file under DefaultConfig. Note that push to play store 64-bit requirement is coming.

Oxpecker answered 9/9, 2019 at 13:56 Comment(0)
D
2

I tried this By Official Android Docs. Working Excellent. In this Solution, I have Build Multi APKs You can see in Attachment... Make Sure Your Compile Skd Version is 29 or Build Tools Version Is 29.0.3 Written Bellow:

    Android {
    compileSdkVersion 29
    buildToolsVersion '29.0.3'
    
    defaultConfig {
        applicationId "com.myapp.sk"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 2
        versionName "1.0"
        multiDexEnabled true
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    
    }
        splits {
            density {
                enable true
                reset()
                include "mdpi", "hdpi"
            }
            abi {
                enable true
                reset()
                include "x86", "x86_64"
            }
        }
    }

// Map for the version code that gives each ABI a value.
ext.abiCodes = ['armeabi-v7a':1, x86:2, x86_64:3]

// For per-density APKs, create a similar map like this:
// ext.densityCodes = ['mdpi': 1, 'hdpi': 2, 'xhdpi': 3]

import com.android.build.OutputFile

// For each APK output variant, override versionCode with a combination of
// ext.abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode
// is equal to defaultConfig.versionCode. If you configure product flavors that
// define their own versionCode, variant.versionCode uses that value instead.
android.applicationVariants.all { variant ->

    // Assigns a different version code for each output APK
    // other than the universal APK.
    variant.outputs.each { output ->

        // Stores the value of ext.abiCodes that is associated with the ABI for this variant.
        def baseAbiVersionCode =
                // Determines the ABI for this variant and returns the mapped value.
                project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))

        // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes,
        // the following code does not override the version code for universal APKs.
        // However, because we want universal APKs to have the lowest version code,
        // this outcome is desirable.
        if (baseAbiVersionCode != null) {

            // Assigns the new version code to versionCodeOverride, which changes the version code
            // for only the output APK, not for the variant itself. Skipping this step simply
            // causes Gradle to use the value of variant.versionCode for the APK.
            output.versionCodeOverride =
                    baseAbiVersionCode * 1000 + variant.versionCode
        }
    }
}

Multi-Aks Attachment

Dicarlo answered 31/7, 2020 at 9:29 Comment(0)
F
1

Native code: refers to an executable program that was compiled directly to the CPU instructions of the computer it is running on.

Non-native code: refers to an executable program that was compiled to the CPU instructions of the original Tandem architecture of the late 1970s and 1980s. When such a program is run, it cannot execute directly on the CPU of the computer it is running on. The NonStop operating system includes an interpreter for that original Tandem architecture, which is used to run such non-native code.

If your app uses only code written in the Java programming language or Kotlin, including any libraries or SDKs, your app is already ready for 64-bit devices. If your app uses any native code, or you are unsure if it does, you will need to assess your app and take action.

Does your app use native code?

The first thing to do is to check to see if your app uses any native code. Your app makes use of native code if it:

  • uses any C/C++ (native) code in your app.
  • links with any third party native libraries.
  • is built by a third party app builder that uses native libraries.

For more, visit the docs.

Fidele answered 4/7, 2019 at 16:16 Comment(0)
S
1
  • Option 1 - remove lib from APK.
    • Step 1 - convert the APK to ZIP and find lib folder; if you have lib folder, see the library dependency.
    • Step 2 - remove dependency from build Gradle.
  • Option 2 - Download 64-bit and 32-bit JAR file and add in your lib folder in app and build.
Subscribe answered 21/8, 2019 at 3:53 Comment(4)
I am trying to xWalkCorelibrary, but unfortunately it provide 32 ad 64 bit separate .aar files, when I add these both it gives me duplicate libraries, can you help me ?Thermotensile
you need to download xWalkCore jar file and add in your project moduleSubscribe
yes, I have added it. it provide 32 and 64 bit libraries separately and when I add these two into my project it works in the debug mode but when I create a sign apk it shows me duplicate files errorThermotensile
Zip and then unzip Apk file , show the duplicate librariesSubscribe
C
1

first open build.gradle module app and add these lines in order to remove .so files and add 64 bit liobraries removing all .so files present in libs of apk

android {    
    compileSdkVersion 29    
    defaultConfig {    
        -----    
        -----    
        ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'    
        ndk {    
            abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'    
        }    
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"    
    }    
packagingOptions{     
        packagingOptions {    
            exclude 'lib/armeabi-v7a/libvudroid.so'    
            exclude 'lib/x86/libvudroid.so'    
            exclude 'lib/arm64-v8a/libvudroid.so'    
        }    
    }`
Commonly answered 5/5, 2020 at 16:46 Comment(1)
My app runs fine on my 64bit device but my app doesn't have libs folder when I extract it .. what is that means?Feverwort
D
1

In my case, I was using a library (ESRI ArcGIS for Android) that makes use of OpenGL C libraries. Instead of the ndk.abiFilters... string that seems to fix everyone else's issues, I had to use the following:

ndk { abiFilters "armeabi-v7a", "arm64-v8a" }

Divergent answered 13/5, 2020 at 15:32 Comment(0)
S
1

Add this in your build.gradle

ndk.abiFilters 'arm64-v8a','x86_64'
Squinteyed answered 22/8, 2020 at 10:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.