diff --git a/android-app/app/src/main/AndroidManifest.xml b/android-app/app/src/main/AndroidManifest.xml index b424460..bcd96f4 100644 --- a/android-app/app/src/main/AndroidManifest.xml +++ b/android-app/app/src/main/AndroidManifest.xml @@ -11,7 +11,7 @@ + android:theme="@style/Theme.AppCompat.Light.NoActionBar"> - val buffer = image.planes[0].buffer - val bytes = ByteArray(buffer.remaining()) - buffer.get(bytes) + /** + * 保存最新一帧到系统相册,返回是否成功 + */ + fun captureAndSave(): Boolean { + val jpeg = latestJpeg ?: return false - val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date()) - val file = File( - context.getExternalFilesDir(null), - "envelope_$timestamp.jpg" - ) + val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date()) + val filename = "envelope_$timestamp.jpg" - FileOutputStream(file).use { it.write(bytes) } + val contentValues = ContentValues().apply { + put(MediaStore.Images.Media.DISPLAY_NAME, filename) + put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg") + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/信封拍照") + put(MediaStore.Images.Media.IS_PENDING, 1) + } + } + + val resolver = context.contentResolver + val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) + ?: return false + + return try { + resolver.openOutputStream(uri)?.use { it.write(jpeg) } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + contentValues.clear() + contentValues.put(MediaStore.Images.Media.IS_PENDING, 0) + resolver.update(uri, contentValues, null, null) + } + true + } catch (e: Exception) { + resolver.delete(uri, null, null) + e.printStackTrace() + false } } @@ -156,25 +174,15 @@ class CameraHelper( e.printStackTrace() } - try { - captureSession?.close() - } catch (e: Exception) { - e.printStackTrace() - } + try { captureSession?.close() } catch (_: Exception) {} captureSession = null - try { - imageReader?.close() - } catch (e: Exception) { - e.printStackTrace() - } + try { imageReader?.close() } catch (_: Exception) {} imageReader = null - try { - cameraDevice?.close() - } catch (e: Exception) { - e.printStackTrace() - } + try { cameraDevice?.close() } catch (_: Exception) {} cameraDevice = null + + latestJpeg = null } } diff --git a/android-app/app/src/main/java/com/usbwebcam/MainActivity.kt b/android-app/app/src/main/java/com/usbwebcam/MainActivity.kt index 9ed0e29..be94d38 100644 --- a/android-app/app/src/main/java/com/usbwebcam/MainActivity.kt +++ b/android-app/app/src/main/java/com/usbwebcam/MainActivity.kt @@ -3,12 +3,14 @@ package com.usbwebcam import android.Manifest import android.content.pm.PackageManager import android.os.Bundle +import android.view.View import android.widget.Button import android.widget.TextView import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat +import java.net.NetworkInterface class MainActivity : AppCompatActivity() { private var mjpegServer: MjpegServer? = null @@ -28,29 +30,24 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - val btnStart = findViewById