You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部分设备授予WRITE_EXTERNAL_STORAGE权限后App意外崩溃求助

解决权限允许后App崩溃的问题

我仔细看了你的代码,发现两个核心问题导致了点击"允许"后App崩溃、重启后正常的现象:


1. 权限检查与申请完全不匹配!

你在checkIfAlreadyhavePermission()里检查的是GET_ACCOUNTS权限,但实际申请的却是WRITE_EXTERNAL_STORAGE。这种逻辑错误会导致权限判断完全混乱——即使用户允许了存储权限,你的检查方法还是会认为权限未授予(因为它在验证账户权限)。重启后正常可能是因为设备上恰好已经有了GET_ACCOUNTS权限,或者重启时没有触发权限申请流程。

先把权限检查修正为和申请一致的类型:

private boolean checkIfAlreadyhavePermission() {
    int result = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    return result == PackageManager.PERMISSION_GRANTED;
}

2. 权限回调中直接执行UI操作时Activity状态不稳定

当系统弹出权限弹窗时,你的Activity可能会进入暂停甚至停止状态。用户点击允许后触发onRequestPermissionsResult,如果此时Activity已经被系统回收,直接调用createall()里的UI初始化代码(比如findViewById、setSupportActionBar)就会导致空指针崩溃。

修复方法是在执行UI操作前先判断Activity是否处于活跃状态:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    if (requestCode == 1) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 确保Activity没有被销毁或正在结束
            if (!isFinishing() && !isDestroyed()) {
                createall();
            }
        } else {
            Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
        }
    }
}

另外,你代码里的switch语句完全多余(已经判断了requestCode == 1),可以直接删掉简化代码。


额外的优化建议

为了更符合Android生命周期规范,建议把文件目录创建和UI初始化的逻辑拆分,让UI初始化更稳妥:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main); // 确保你已经设置了布局文件

    int currentVersion = Build.VERSION.SDK_INT;
    if (currentVersion >= Build.VERSION_CODES.M) {
        if (!checkIfAlreadyhavePermission()) {
            requestForSpecificPermission();
        } else {
            // 权限已存在,直接初始化
            setupApp();
        }
    } else {
        // 低于Android 6.0,无需权限申请
        setupApp();
    }
}

// 拆分后的统一初始化方法
private void setupApp() {
    createStorageFolder();
    initUIComponents();
}

// 单独处理文件目录创建
private void createStorageFolder() {
    String mediaLocation = "/VApp";
    String myFolder = Environment.getExternalStorageDirectory() + mediaLocation;
    File mediaDir = new File(myFolder);
    if (!mediaDir.exists()) {
        mediaDir.mkdir();
    }
}

// 单独处理UI初始化
private void initUIComponents() {
    Toolbar toolBar = findViewById(R.id.toolBar);
    setSupportActionBar(toolBar);
    
    ViewPager viewPager = findViewById(R.id.pager);
    ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
    adapter.addFragment(new RecentActivity(), "Recent");
    adapter.addFragment(new SavedActivity(), "Saved");
    viewPager.setAdapter(adapter);
    
    TabLayout tabLayout = findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(viewPager);
}

这样拆分后,代码逻辑更清晰,也能避免在不合适的时机执行UI操作。

另外提醒一下:从Android 10(API 29)开始,Environment.getExternalStorageDirectory()已经被废弃,建议使用getExternalFilesDir()来获取应用专属的外部存储目录,这种方式不需要申请WRITE_EXTERNAL_STORAGE权限(除非你需要访问公共目录)。


内容的提问来源于stack exchange,提问作者vinayak180696

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:53:30