如何避免Android文件选择器选中.apk文件?现有代码可正常选文档
Hey there! Let's sort out that annoying issue where your file picker is grabbing .apk files when it shouldn't. The root problem here is how you're specifying multiple MIME types in your Intent—your current setType() syntax isn't following Android's official guidelines, which leads to loose matching in some file managers.
What's Wrong with Your Current Code?
Using setType("application/x-excel|application/pdf|text/plain|text/csv|image/*") with a pipe separator (|) isn't a valid way to define multiple MIME types. Android's setType() expects a single MIME type string, and some file managers misinterpret this pipe-separated format, resulting in unintended matches like .apk files (which use the MIME type application/vnd.android.package-archive).
The Correct Solution
Use Android's Intent.EXTRA_MIME_TYPES extra to explicitly list all allowed MIME types. This is the official, reliable way to restrict file selection to specific formats. We'll also update the Excel MIME types to cover both .xls and .xlsx for better compatibility.
Here's your revised code:
@Override public void onClick(View v) { switch (v.getId()){ case R.id.rlSelectFile: Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); // Set a generic base type, then specify exact allowed types via EXTRA_MIME_TYPES intent.setType("*/*"); // Define all valid MIME types (covers Excel, PDF, text, images) String[] allowedMimeTypes = { "application/vnd.ms-excel", // .xls files "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // .xlsx files "application/pdf", "text/plain", "text/csv", "image/*" }; intent.putExtra(Intent.EXTRA_MIME_TYPES, allowedMimeTypes); // Launch the file picker (replace YOUR_REQUEST_CODE with your actual request code) startActivityForResult(intent, YOUR_REQUEST_CODE); break; // Handle other cases here... } }
Extra Safety: Double-Check File Extension (Optional)
For extra assurance—especially if you're targeting older devices with less strict file managers—you can add a check on the selected file's extension after picking it. This ensures even if a file slips through the MIME type filter, you can reject it:
// In your onActivityResult method (or ActivityResultCallback for AndroidX) @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == YOUR_REQUEST_CODE && resultCode == RESULT_OK && data != null) { Uri selectedFileUri = data.getData(); if (selectedFileUri != null) { String fileName = getFileNameFromUri(selectedFileUri); // Reject if the file is an APK if (fileName != null && fileName.toLowerCase().endsWith(".apk")) { Toast.makeText(this, "APK files are not allowed. Please select a valid document.", Toast.LENGTH_SHORT).show(); return; } // Proceed with handling your valid file here // ... } } } // Helper method to extract filename from Uri private String getFileNameFromUri(Uri uri) { String fileName = null; if ("content".equals(uri.getScheme())) { Cursor cursor = getContentResolver().query(uri, null, null, null, null); if (cursor != null && cursor.moveToFirst()) { fileName = cursor.getString(cursor.getColumnIndex(android.provider.OpenableColumns.DISPLAY_NAME)); cursor.close(); } } // Fallback to path segment if content resolver didn't return a name if (fileName == null) { fileName = uri.getLastPathSegment(); } return fileName; }
This approach will lock down your file picker to only the formats you want, and the extra extension check adds a safety net for edge cases.
内容的提问来源于stack exchange,提问作者MohammadAli

