Android应用写入文件时崩溃问题排查求助
问题分析与解决方案
从你提供的Logcat日志可以直接定位到崩溃根源:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getExternalFilesDir(java.lang.String)' on a null object reference
简单来说,你的WriteToFile类继承了AppCompatActivity,但你应该是直接通过new WriteToFile()来实例化它的——这种方式不会触发Activity的初始化流程,导致内部的Context对象为null,调用getExternalFilesDir时自然抛出空指针异常。
核心修复步骤
1. 重构WriteToFile为普通工具类
它只是负责文件写入,完全不需要继承Activity。我们将它改成依赖外部传入Context的工具类:
public class WriteToFile { private final Context mContext; // 通过构造函数传入有效的Context public WriteToFile(Context context) { this.mContext = context; } public void write(String fileName, String textToWrite) { // 检查外部存储状态 String state = Environment.getExternalStorageState(); if (!Environment.MEDIA_MOUNTED.equals(state)) { Toast.makeText(mContext, "外部存储不可用,无法写入文件", Toast.LENGTH_SHORT).show(); return; } // 文件写入不需要互联网权限,修正为检查存储权限 if (!PermissionChecker.checkStoragePermission(mContext)) { PermissionChecker.requestFilePermission((Activity) mContext, mContext); return; } // 获取外部文件目录,先判空 File dir = mContext.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS); if (dir == null) { Toast.makeText(mContext, "无法获取文件存储目录", Toast.LENGTH_SHORT).show(); return; } // 用mkdirs创建多级目录(mkdir只能创建一级) if (!dir.exists()) { dir.mkdirs(); } File file = new File(dir, fileName); // 使用try-with-resources自动管理流资源,避免泄漏 try (FileOutputStream os = new FileOutputStream(file)) { os.write(textToWrite.getBytes()); } catch (IOException e) { e.printStackTrace(); Toast.makeText(mContext, "文件写入失败:" + e.getMessage(), Toast.LENGTH_SHORT).show(); } } }
2. 修正调用方式
在你的validateCredentials方法中,实例化WriteToFile时传入当前Activity的Context:
private void validateCredentials(){ if (PermissionChecker.checkInternetPermission(this)) { if (!EmptyChecker.isEmpty(usernameTextInputLayout) && !EmptyChecker.isEmpty(passwordTextInputLayout)) { password = Objects.requireNonNull(passwordTextInputLayout.getEditText()).getText().toString(); userName = Objects.requireNonNull(usernameTextInputLayout.getEditText()).getText().toString(); logInValidator(userName, (success) -> { if (success) { String textToWrite = getTextToWrite(); // 传入当前Activity的Context实例化工具类 WriteToFile writeToFile = new WriteToFile(LogInActivity.this); writeToFile.write("UserData.txt",textToWrite); //Intent mainIntent = new Intent(LogInActivity.this, MainActivity.class); //startActivity(mainIntent); } else { showResult.setText(getString(userNotFound)); } }); } else { showResult.setText(getString(string.emptyField)); } } else PermissionChecker.requestInternetPermission(TestActivity.this,ContextGetter.getAppContext()); }
额外注意事项
- 权限逻辑修正:原代码中错误地在文件写入前检查互联网权限,文件操作需要的是存储权限(Android 10及以上版本无需申请,系统自动授予),请确保
PermissionChecker中的checkStoragePermission和requestFilePermission逻辑正确。 - 空指针防护:对
getExternalFilesDir的返回值一定要判空,部分特殊设备或存储异常场景下会返回null。 - 资源自动管理:使用try-with-resources语法可以自动关闭文件流,避免手动关闭时可能出现的异常或泄漏问题。
内容的提问来源于stack exchange,提问作者muratcanyeldan
相关产品推荐
相关产品推荐

