Android 系統拍照完成後會發送廣播,並更新 MediaStore 媒體庫。應用可通過以下兩種方式實現照片自動上傳:
<!-- AndroidManifest.xml -->
<receiver android:name=".CameraBroadcastReceiver">
<intent-filter>
<action android:name="android.hardware.action.NEW_PICTURE" />
<action android:name="android.hardware.action.NEW_VIDEO" />
<!-- Android 7.0+ 需動態註冊 -->
</intent-filter>
</receiver>
// CameraBroadcastReceiver.java
public class CameraBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.hardware.action.NEW_PICTURE")) {
// 獲取新照片 URI
Uri imageUri = intent.getData();
if (imageUri != null) {
// 啟動上傳服務
Intent uploadIntent = new Intent(context, UploadService.class);
uploadIntent.setData(imageUri);
context.startService(uploadIntent);
}
}
}
}
// 使用 ContentObserver 監聽媒體庫變化
public class MediaStoreObserver extends ContentObserver {
private Context context;
private Uri lastUri;
public MediaStoreObserver(Handler handler, Context context) {
super(handler);
this.context = context;
}
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
// 過濾圖片類型變化
if (uri != null && uri.toString().contains("images")) {
// 查詢最新圖片
queryAndUploadLatestImage();
}
}
private void queryAndUploadLatestImage() {
String[] projection = {MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA};
String sortOrder = MediaStore.Images.Media.DATE_ADDED + " DESC";
try (Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection, null, null, sortOrder)) {
if (cursor != null && cursor.moveToFirst()) {
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
// 啟動上傳
startUpload(path);
}
}
}
}
// 在 Service/Application 中註冊
getContentResolver().registerContentObserver(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, mediaStoreObserver);
public class UploadService extends IntentService {
public UploadService() { super("UploadService"); }
@Override
protected void onHandleIntent(Intent intent) {
Uri imageUri = intent.getData();
// 1. 獲取文件路徑
String filePath = getRealPathFromUri(imageUri);
// 2. 壓縮圖片(可選)
File compressedFile = compressImage(filePath);
// 3. 多部分上傳
uploadToServer(compressedFile);
// 4. 記錄上傳狀態到本地數據庫
recordUploadStatus(filePath, success);
}
}
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Android 10 以下 -->
<!-- Android 10+ 使用 Scoped Storage,無需 WRITE 權限 -->
| 維度 | 廣播監聽 | MediaStore 監聽 |
|---|---|---|
| 即時性 | 高(拍照瞬間觸發) | 中(需查詢最新) |
| Android 版本兼容 | 7.0+ 需動態註冊,部分機型受限 | 全版本支持 |
| 獲取文件路徑 | 直接從 Intent 獲取 URI | 需查詢 Cursor 獲取路徑 |
| 推薦場景 | 拍照即上傳、實時性要求高 | 相冊同步、批量備份、兼容性優先 |
