Android 14设备上Razorpay AAR动态代码加载SecurityException问题求助
问题描述
以下是初始化Razorpay支付的代码片段:
public void setPayment(PaymentResponse response){ this.response = response; layout.findViewById(R.id.loader).setVisibility(View.GONE); layout.findViewById(R.id.payment_area).setVisibility(View.VISIBLE); if(razorpay==null){ // 错误源于引用本地aar文件 razorpay = new Razorpay(getActivity(),response.getPayment().getGatewayKey()); } razorpay.setWebView(paymentLayout.findViewById(R.id.payments)); // 后续代码省略 }
在Android 14设备上运行时触发如下错误:
java.lang.SecurityException: writable dex file '/data/user/io.project.package.name/cache/. ' is not allowed.
环境信息
- 本地libs目录存放
razorpay.aar,build.gradle依赖配置:implementation fileTree(dir: 'libs', include: ['*.aar']) implementation files('libs/razorpay.aar') - 仅Android 14设备出现该问题,低版本系统运行正常
- 已知升级Razorpay AAR可解决问题,但涉及大量代码重构及服务端改动,需寻求无需升级AAR的应用层热修复方案
- 编译环境:Android Studio Iguana | 2023.2.1 Patch 1
无需升级AAR的修复方案
方案1:临时禁用Dex优化(应急热修复)
在AndroidManifest.xml的<application>标签中添加以下属性,强制系统不优化内嵌Dex,避免旧版Razorpay的Dex写入操作触发安全限制:
android:extractNativeLibs="true" android:useEmbeddedDex="false"
⚠️ 注意:该方案可能影响应用运行性能,仅作为临时修复使用,后续仍需规划升级AAR。
方案2:重定向临时目录到系统允许的路径
Android 14禁止在应用缓存目录加载可写Dex文件,旧版Razorpay恰好在此目录写入临时Dex。可通过自定义Application类,将系统临时目录重定向到code_cache(Android 14允许加载Dex的目录):
- 自定义Application类:
public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); File codeCacheDir = getCodeCacheDir(); if (codeCacheDir != null) { // 将系统临时目录替换为code_cache System.setProperty("java.io.tmpdir", codeCacheDir.getAbsolutePath()); } } }
- 在
AndroidManifest.xml中指定该Application:
<application android:name=".MyApp" <!-- 其他原有属性 --> > <!-- 其他组件配置 --> </application>
方案3:反射修改Razorpay的缓存路径
如果上述方案无效,可尝试通过反射修改Razorpay内部使用的缓存目录,指向code_cache:
// 必须在初始化Razorpay实例之前执行这段代码 try { // 替换为旧版Razorpay中实际处理缓存的类名 Class<?> razorpayClass = Class.forName("com.razorpay.Razorpay"); // 替换为该类中存储缓存目录的字段名 Field cacheDirField = razorpayClass.getDeclaredField("cacheDir"); cacheDirField.setAccessible(true); // 设置为系统允许的code_cache目录 File allowedDir = getActivity().getCodeCacheDir(); cacheDirField.set(null, allowedDir); } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); }
⚠️ 注意:需根据旧版Razorpay AAR的内部结构调整反射的类名和字段名,建议反编译本地AAR确认具体结构后再使用。
内容的提问来源于stack exchange,提问作者Siddharth Pandalai
相关产品推荐
相关产品推荐

