targetSdkVersion从29升级至30/31后Android 11页面跳转按钮失效问题
问题根因及解决方案
根因定位
从给出的代码逻辑来看,跳转逻辑仅在file.exists()返回true时才会执行,结合升级targetSdk到30+后仅Android 11及以上设备失效的特征,核心原因是两个API 30的系统变更:
- 分区存储强制生效:API 29还可以通过
requestLegacyExternalStorage配置退出分区存储逻辑,API 30及以上该配置完全失效,应用默认只能访问自身私有目录和媒体库内的自有文件,如果saveBitmap方法是写入外部存储公共目录,没有适配分区存储就会写入失败,返回无效路径,导致文件存在性判断不通过,跳过跳转逻辑 getDrawingCacheAPI被废弃:API 30开始该方法正式废弃,调用后大概率返回null,传入saveBitmap后也会导致存储失败- 额外隐藏问题:代码中只要进入else if分支就会把
nextButtonClick设为true,如果首次点击时存储失败,后续再次点击按钮会直接走else分支返回,不会再触发跳转逻辑
修复步骤
- 替换过时的视图截图逻辑,用PixelCopy API替代getDrawingCache,兼容API 30+设备:
// 针对mMainFrameLayout的截图替代逻辑 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Bitmap bitmap = Bitmap.createBitmap(mMainFrameLayout.getWidth(), mMainFrameLayout.getHeight(), Bitmap.Config.ARGB_8888); PixelCopy.request(getWindow(), new Rect(0, 0, mMainFrameLayout.getWidth(), mMainFrameLayout.getHeight()), bitmap, copyResult -> { if (copyResult == PixelCopy.SUCCESS) { // 后续存储和跳转逻辑放这里 saveBitmapAndJump(bitmap); } else { // 截图失败重置点击标记 nextButtonClick = false; } }, new Handler(Looper.getMainLooper())); } else { // 低版本继续用原来的getDrawingCache逻辑 mMainFrameLayout.setDrawingCacheEnabled(true); Bitmap bitmap = Bitmap.createBitmap(mMainFrameLayout.getDrawingCache()); mMainFrameLayout.setDrawingCacheEnabled(false); saveBitmapAndJump(bitmap); }
- 适配分区存储,把截图保存到应用自身的私有外部存储目录,不需要申请额外存储权限,写法参考:
private String saveBitmap(String fileName, int quality, Bitmap bitmap) { // 私有目录路径不会触发分区存储限制 File dir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); File imageFile = new File(dir, fileName + ".png"); try (FileOutputStream fos = new FileOutputStream(imageFile)) { bitmap.compress(Bitmap.CompressFormat.PNG, quality, fos); fos.flush(); return imageFile.getAbsolutePath(); } catch (IOException e) { e.printStackTrace(); return null; } }
- 跳转逻辑增加异常处理,失败时重置点击标记:
String saveBitmap = saveBitmap("imageforaddingstickerandtext", 100, this.mFinalBitmap); this.mMainFrameLayout.destroyDrawingCache(); if (saveBitmap == null) { nextButtonClick = false; Toast.makeText(getApplicationContext(), "图片保存失败,请重试", Toast.LENGTH_SHORT).show(); return; } File file = new File(saveBitmap); if (file.exists()) { OpenShareActivity(); Intent Intent = new Intent(this, ShareActivity.class); startActivity(Intent); // 跳转成功后按需重置nextButtonClick } else { nextButtonClick = false; Toast.makeText(getApplicationContext(), "图片保存失败,请重试", Toast.LENGTH_SHORT).show(); }
内容的提问来源于stack exchange,提问作者Samer apps
相关产品推荐
相关产品推荐

