Android 11选择存储CSV文件后应用自动关闭问题求助
问题:Android 11设备选中CSV文件后应用闪退,ActivityResultLauncher未触发
在Android 11设备开发应用时,尝试读取存储中的CSV文件,打开文件选择器并选中文件后应用自动关闭。已在AndroidManifest.xml中声明READ_EXTERNAL_STORAGE权限且申请了运行时权限,但无任何异常或错误提示,同时activityResultLauncher未被调用。
相关代码
UnitTestMarksActivity.java
package com.suyogbauskar.attenteachers; import android.app.Activity; import android.content.Intent; import android.graphics.Color; import android.graphics.Typeface; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.view.Gravity; import android.view.Menu; import android.view.View; import android.widget.Button; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; import android.widget.Toast; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.PopupMenu; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseUser; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener; import com.suyogbauskar.attenteachers.pojos.StudentData; import com.suyogbauskar.attenteachers.pojos.UnitTestMarks; import java.io.InputStream; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import java.util.TreeMap; import cn.pedant.SweetAlert.SweetAlertDialog; public class UnitTestMarksActivity extends AppCompatActivity { private Button uploadBtn; private int selectedSemester; private FirebaseUser user; private TableLayout table; private boolean isFirstRow; private String subjectCodeTeacher; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_unit_test_marks); setTitle("Unit Test Marks"); getSupportActionBar().setDisplayHomeAsUpEnabled(true); init(); } private void init() { user = FirebaseAuth.getInstance().getCurrentUser(); findAllViews(); uploadBtn.setOnClickListener(view -> uploadFile()); } private void findAllViews() { uploadBtn = findViewById(R.id.uploadBtn); } ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { Toast.makeText(UnitTestMarksActivity.this, "Success", Toast.LENGTH_SHORT).show(); } } ); private void uploadFile() { Intent data = new Intent(Intent.ACTION_GET_CONTENT); Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()); data.setDataAndType(uri, "text/csv"); data = Intent.createChooser(data, "Choose unit test marks"); activityResultLauncher.launch(data); } }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.AttenTeachers" tools:targetApi="31"> <activity android:name=".UnitTestMarksActivity" android:exported="false" android:noHistory="true"/> <activity android:name=".MainActivity" android:exported="true" android:noHistory="true" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
应用闪退演示

修复方案
1. 移除android:noHistory="true"属性
UnitTestMarksActivity的Manifest配置中添加了android:noHistory="true",该属性会让Activity在离开(比如启动文件选择器)时被系统销毁,导致返回时找不到原Activity,直接引发闪退。
修改后的Activity配置:
<activity android:name=".UnitTestMarksActivity" android:exported="false"/>
2. 调整文件选择Intent写法
Android 11及以上版本禁止直接通过Environment.getExternalStorageDirectory()指定路径,且ACTION_GET_CONTENT无需设置初始Uri,正确写法如下:
private void uploadFile() { Intent data = new Intent(Intent.ACTION_GET_CONTENT); data.setType("text/csv"); data.addCategory(Intent.CATEGORY_OPENABLE); Intent chooser = Intent.createChooser(data, "Choose unit test marks"); activityResultLauncher.launch(chooser); }
3. 补充权限校验(可选)
虽然已申请运行时权限,可在打开文件选择器前添加权限校验,确保权限已获取:
private void uploadFile() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityResultLauncher<String> permissionLauncher = registerForActivityResult( new ActivityResultContracts.RequestPermission(), isGranted -> { if (isGranted) { openFileChooser(); } else { Toast.makeText(this, "需要存储权限才能读取文件", Toast.LENGTH_SHORT).show(); } } ); permissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE); return; } openFileChooser(); } private void openFileChooser() { Intent data = new Intent(Intent.ACTION_GET_CONTENT); data.setType("text/csv"); data.addCategory(Intent.CATEGORY_OPENABLE); Intent chooser = Intent.createChooser(data, "Choose unit test marks"); activityResultLauncher.launch(chooser); }
内容的提问来源于stack exchange,提问作者Suyog
相关产品推荐
相关产品推荐

