首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 拍照保存至自定義目錄:FileProvider 適配 Android 7+ 與 MediaStore 插入相冊

     編輯:程式設計綜合問答

需求:拍照後保存至 SD 卡自定義目錄 /MyFolder/,並出現在系統相冊中。需適配 Android 7.0+ FileProvider 強制規範。

核心步驟

  1. 創建目標文件(含目錄創建)。
  2. Android 7+:用 FileProvider.getUriForFile() 獲取 content:// URI,授予 FLAG_GRANT_READ_URI_PERMISSION。
  3. Android 6-:直接用 Uri.fromFile() (file://)。
  4. 啟動 MediaStore.ACTION_IMAGE_CAPTURE,putExtra(MediaStore.EXTRA_OUTPUT, uri)。
  5. 拍攝完成後,發送廣播通知 MediaStore 掃描:Intent.ACTION_MEDIA_SCANNER_SCAN_FILE。

完整實現代碼

public class PhotoCaptureActivity extends AppCompatActivity {
    private static final int REQUEST_CAPTURE = 100;
    private Uri photoUri;
    private File photoFile;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // ... UI 初始化
        findViewById(R.id.btnCapture).setOnClickListener(v -> dispatchTakePictureIntent());
    }

    private void dispatchTakePictureIntent() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (intent.resolveActivity(getPackageManager()) == null) return;

        // 1. 創建文件
        photoFile = createImageFile();
        if (photoFile == null) return;

        // 2. 獲取 URI(適配 7.0+)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            photoUri = FileProvider.getUriForFile(this, 
                getPackageName() + ".fileprovider", photoFile);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            photoUri = Uri.fromFile(photoFile);
        }

        intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
        startActivityForResult(intent, REQUEST_CAPTURE);
    }

    private File createImageFile() {
        File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyFolder");
        if (!dir.exists() && !dir.mkdirs()) return null;
        
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        String fileName = "IMG_" + timeStamp + ".jpg";
        return new File(dir, fileName);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_CAPTURE && resultCode == RESULT_OK) {
            // 通知相冊掃描
            Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            scanIntent.setData(photoUri);
            sendBroadcast(scanIntent);
            
            // 顯示縮略圖
            Bitmap bitmap = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
            imageView.setImageBitmap(bitmap);
        }
    }
}

FileProvider 配置

AndroidManifest.xml

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

res/xml/file_paths.xml

<paths xmlns:android="https://schemas.android.com/apk/res/android">
    <external-files-path name="my_pictures" path="Pictures/MyFolder/" />
</paths>

關鍵點總結

  • 使用 Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES) 獲取標準圖片目錄,無需權限(Android 10+ 作用域存儲下仍可訪問)。
  • FileProvider 必須配置 external-files-path 或 external-path 指向目標目錄。
  • 發送 ACTION_MEDIA_SCANNER_SCAN_FILE 讓相冊即時顯示。
  • Android 10+ (Q) 建議直接用 MediaStore.insert() 替代文件操作,完全適配作用域存儲。

標準化拍照保存流程,完美適配全 Android 版本與相冊集成。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved