Android 64bit系统中app以32bit运行

Android L后开始支持64位的。大部分系统默认都是以64位进行运行,但是在很多时候我们还是希望我们的app在系统中以32位运行。
对于app来说,32bit和64bit主要区别就是JAVA加载so的规则:
如果APP需要加载的所有so都是32bit,则使用32bit方式加载so库;如果APP需要加载的so库中只要有一个so是64bit的,则必须以64bit方式加载so库;不能同时加载32bit和64bit的so库。

对于系统应用来说,so一般放到 /system/lib/ 或者 /system/lib64/下面,如果app以32bit运行,就到/system/lib/下面找对于so加载;反之则到加载/system/lib64/下面的so。


下面主要就是谈论如何在64bit系统中,集成apk,以32bit方式运行:

1、直接以apk的形式集成
 这里就有两种情况,so已经打包到了apk中,此时我们使用以下方法只打包32bit的so即可满足要求。
 用gradle编译 apk,可以加上
 ndk {
            abiFilters "armeabi"
        }    
 在android源码中使用Android.mk编译,则用 LOCAL_MULTILIB :=32,这样apk中就只包含了32bit的so。
 
 还有一种情况就是apk中没有包含任何so,对应的so我们直接copy到 /system/lib/下面,这个时候如何指定app以32bit运行呢?
 加上LOCAL_MULTILIB :=32是否可行呢,使用Android.mk中编译时使用LOCAL_MULTILIB :=32没有任何效果,因为这样编译的apk跟之前的apk没有任何区别,也不包含任何so。
 此时可以在对应apk目录下新建 /system/app/*/lib/arm/,此目录下可以不用放任何so,就能保证此apk以32bit运行。
 
2、直接源码编译的形式集成
   android.mk 中使用LOCAL_MULTILIB :=32 即可。
   需要注意的是 JAVA编译不分32bit和64bit(APK,JAR),如果需要编译的apk没有用到so,那么app以32bit还是64bit运行,对于我们来说没有任何区别,不会存在到 /system/lib/ 和 /system/lib64/ 加载so的情况。
   
3、当app用到 android:sharedUserId="android.uid.system" 时,所有相同 sharedUserId 的应用必现以同样的方式运行,要么都是32bit要么都是64bit。
如果有app需要特殊处理,可以尝试下面修改( "com.android.xxx" 为单独处理的包名):
PackageManagerService.java 中方法 private void adjustCpuAbisForSharedUserLPw(Set packagesForUser, PackageParser.Package scannedPackage, boolean forceDexOpt, boolean deferDexOpt)
        for (PackageSetting ps : packagesForUser) {
            // If packagesForUser contains scannedPackage, we skip it. This will happen
            // when scannedPackage is an update of an existing package. Without this check,
            // we will never be able to change the ABI of any package belonging to a shared
            // user, even if it's compatible with other packages.
            if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) {
                if (ps.primaryCpuAbiString == null
+                       || "com.android.xxx".equals(ps.name)) {
                    continue;
                }

                final String instructionSet = VMRuntime.getInstructionSet(ps.primaryCpuAbiString);
                if (requiredInstructionSet != null && !instructionSet.equals(requiredInstructionSet)) {
                    // We have a mismatch between instruction sets (say arm vs arm64) warn about
                    // this but there's not much we can do.
                    String errorMessage = "Instruction set mismatch, "
                            + ((requirer == null) ? "[caller]" : requirer)
                            + " requires " + requiredInstructionSet + " whereas " + ps
                            + " requires " + instructionSet;
                    Slog.w(TAG, errorMessage);
                }

                if (requiredInstructionSet == null) {
                    requiredInstructionSet = instructionSet;
                    requirer = ps;
                }
            }
        }
 

你可能感兴趣的:(Android,android)