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

Android Studio读取模拟器Download目录txt文件运行崩溃如何解决

崩溃原因及修复方案

核心崩溃原因

  • 权限适配问题:Android 6.0以上读取外部存储需要动态申请权限,Android 10开始引入分区存储,直接访问Environment.getExternalStorageDirectory()会被系统拦截,导致listFiles()返回null,遍历files.length时触发空指针崩溃
  • Activity未注册:ListaFilesActivity作为内部类定义在MainActivity中,未在AndroidManifest.xml注册,启动时会抛出Activity未找到异常
  • 布局错误:ListaFilesActivity复用了R.layout.activity_main,如果该布局没有id=ruta的TextView和id=listaFiles的ListView,findViewById返回null,调用相关方法时触发空指针
  • 无空值校验:未对listFiles()的返回值做非空判断,即使没有权限或者目录不存在也直接遍历,必然触发崩溃

分步修复方案

第一步:配置AndroidManifest.xml权限及Activity注册

<!-- 安卓13及以下通用存储权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- 安卓13及以上媒体权限,适配公共目录读取 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<!-- 如需读取所有类型文件可申请全文件访问权限,上架应用商店需提供用途说明 -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

<application
    ...
    <!-- 安卓10兼容配置,关闭分区存储限制 -->
    android:requestLegacyExternalStorage="true">
    <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <!-- 注册列表Activity,若后续拆成独立类,此处改为android:name=".ListaFilesActivity" -->
    <activity android:name=".MainActivity$ListaFilesActivity" />
</application>

第二步:MainActivity增加动态权限申请逻辑

public class MainActivity extends AppCompatActivity {
    Button Tomar_datos;
    // 权限申请回调
    private ActivityResultLauncher<String> requestPermissionLauncher = registerForActivityResult(
            new ActivityResultContracts.RequestPermission(),
            isGranted -> {
                if (isGranted) {
                    startActivity(new Intent(MainActivity.this, ListaFilesActivity.class));
                } else {
                    Toast.makeText(this, "请授予存储权限后重试", Toast.LENGTH_SHORT).show();
                }
            }
    );

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Tomar_datos = findViewById(R.id.Tomar_datos);
    }

    public void onClick(View view) {
        String permission;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            permission = Manifest.permission.READ_MEDIA_IMAGES;
        } else {
            permission = Manifest.permission.READ_EXTERNAL_STORAGE;
        }
        // 先判断是否已有权限
        if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED) {
            startActivity(new Intent(MainActivity.this, ListaFilesActivity.class));
        } else {
            requestPermissionLauncher.launch(permission);
        }
    }
    // 内部类ListaFilesActivity保留,也可单独拆成独立Java文件
    class ListaFilesActivity extends Activity {
        // 内部类逻辑见第三步修改
    }
}

第三步:修复ListaFilesActivity逻辑,增加空校验和txt过滤

首先建议新建独立的activity_lista_files.xml布局文件,包含id为ruta的TextView和id为listaFiles的ListView,然后修改Activity代码:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    // 替换为列表页专属布局
    setContentView(R.layout.activity_lista_files);
    List<String> item = new ArrayList<>();

    // 直接获取系统公共下载目录,不要自己拼接路径
    File downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
    File[] files = downloadDir.listFiles();
    // 非空判断避免空指针
    if (files != null) {
        for (File file : files) {
            // 只保留.txt后缀的文件
            if (!file.isDirectory() && file.getName().toLowerCase().endsWith(".txt")) {
                item.add(file.getName());
            }
        }
    } else {
        Toast.makeText(this, "无法读取下载目录,请检查权限配置", Toast.LENGTH_SHORT).show();
    }

    TextView ruta = findViewById(R.id.ruta);
    ruta.setText(downloadDir.getAbsolutePath());

    ListView lstOpciones = findViewById(R.id.listaFiles);
    ArrayAdapter<String> fileList = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, item);
    lstOpciones.setAdapter(fileList);

    // 原有点击事件逻辑可保留不变
    lstOpciones.setOnItemClickListener((parent, view, position, id) -> {
        Intent data = new Intent();
        data.putExtra("filename", item.get(position));
        setResult(RESULT_OK, data);
        finish();
    });
}

额外注意事项

  • 优先将ListaFilesActivity拆成独立的Java类,避免内部类带来的上下文泄漏、生命周期异常等问题
  • 若需要适配Android 13以上读取非媒体类txt文件,可申请MANAGE_EXTERNAL_STORAGE权限,该权限需要跳转系统设置页由用户手动开启
  • 所有文件操作前都要做非空校验,不要直接假设返回的文件数组一定存在

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 15:54:06