ממשק API של תוספי Camera2

הערה: הדף הזה מתייחס לחבילה camera2. מומלץ להשתמש ב-CameraX, אלא אם לאפליקציה שלך נדרשים תכונות ספציפיות ברמה נמוכה. גם CameraX וגם Camera2 תומכים ב-Android 5.0 (רמת API 21) ואילך.

Camera2 מספקת תוספים API לגישה לתוספים שיצרני המכשירים הטמיעו במכשירי Android שונים. במאמר תוספי מצלמה תוכלו למצוא רשימה של מצבי התוספים הנתמכים.

רשימה של מכשירים שתומכים בתוספים מופיעה ברשימה מכשירים נתמכים.

ארכיטקטורת תוספים

בתמונה הזו מוצגת הארכיטקטורה של תוספי המצלמה.

איור 1. הארכיטקטורה של תוספי המצלמה

אפליקציית Camera2 יכולה להשתמש בתוספים באמצעות ממשק ה-API של Camera2. המצלמה2 ה-API מספק דרכים להריץ שאילתות על תוספים זמינים, להגדיר תוסף תיעוד המצלמה של המכשיר ולתקשר עם ספריית ה-OEM של ה-OEM של התוספים למצלמה. הזה מאפשרת לאפליקציה להשתמש בתוספים כמו Night, HDR, Auto, Bokeh או ריטוש פנים.

בדיקת התאימות של Camera2 extensions API למכשיר מצלמה

קטע הקוד הבא בודק אם המכשיר תומך במצלמה2 API לתוספים. התוספים לא נתמכים בכל המכשירים, או שהמכשיר תומך בקבוצת משנה של תוספים. קטע הקוד מחזיר רשימה של מזהי מצלמות תואמים שתומכים תוספי מצלמה.

KotlinJava

private fun getExtensionCameraIds(cameraManager: CameraManager): List<String> =
   
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        cameraManager
.cameraIdList.filter { cameraId ->
           
val characteristics = cameraManager.getCameraCharacteristics(cameraId)
           
val extensionCharacteristics =
                cameraManager
.getCameraExtensionCharacteristics(cameraId)
           
val capabilities =
                characteristics
.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
            extensionCharacteristics
.supportedExtensions.isNotEmpty() &&
                    capabilities
?.contains(
                       
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
                   
) ?: false
       
}
   
} else emptyList()


private List<String> getExtensionCameraIds(CameraManager cameraManager)
       
throws CameraAccessException {
   
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
       
return Arrays.stream(cameraManager.getCameraIdList()).filter(cameraId -> {
           
try {
               
CameraCharacteristics characteristics =
                        cameraManager
.getCameraCharacteristics(cameraId);
               
CameraExtensionCharacteristics extensionCharacteristics =
                        cameraManager
.getCameraExtensionCharacteristics(cameraId);
               
IntStream capabilities =
                   
Arrays.stream(
                                characteristics
.get(
                                       
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES
                               
)
                       
);
               
return !extensionCharacteristics.getSupportedExtensions().isEmpty() &&
                       capabilities
.anyMatch(capability -> capability == CameraCharacteristics
                                       
.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
                       
);
           
} catch (CameraAccessException e) {
               
throw new RuntimeException(e);
           
}
       
}).collect(Collectors.toList());
   
} else {
       
return Collections.emptyList();
   
}
}

יצירת סשן של תוסף מצלמה באמצעות ממשק ה-API של תוספי Camera2

כשה-API של התוספים למצלמה, כשמשתמשים במכשירים תואמים, אפשר לגשת תוספי מצלמה מסוימים. קטע הקוד הבא מציג דוגמה איך יוצרים CameraExtensionSession לשימוש במצב צילום לילה באפליקציית Camera2 קיימת.

KotlinJava

private val captureCallbacks = object : CameraExtensionSession.ExtensionCaptureCallback() {
   
// Implement Capture Callbacks
}
private val extensionSessionStateCallback = object : CameraExtensionSession.StateCallback() {
   
override fun onConfigured(session: CameraExtensionSession) {
        cameraExtensionSession
= session
       
try {
           
val captureRequest =
                cameraDevice
.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
                    addTarget
(previewSurface)
               
}.build()
            session
.setRepeatingRequest(
                captureRequest
,
               
Dispatchers.IO.asExecutor(),
                captureCallbacks
           
)
       
} catch (e: CameraAccessException) {
           
Snackbar.make(
                previewView
,
               
"Failed to preview capture request",
               
Snackbar.LENGTH_SHORT
           
).show()
            requireActivity
().finish()
       
}
   
}

   
override fun onClosed(session: CameraExtensionSession) {
       
super.onClosed(session)
        cameraDevice
.close()
   
}

   
override fun onConfigureFailed(session: CameraExtensionSession) {
       
Snackbar.make(
            previewView
,
           
"Failed to start camera extension preview",
           
Snackbar.LENGTH_SHORT
       
).show()
        requireActivity
().finish()
   
}
}

private fun startExtensionSession() {
   
val outputConfig = arrayListOf(
       
OutputConfiguration(stillImageReader.surface),
       
OutputConfiguration(previewSurface)
   
)
   
val extensionConfiguration = ExtensionSessionConfiguration(
       
CameraExtensionCharacteristics.EXTENSION_NIGHT,
        outputConfig
,
       
Dispatchers.IO.asExecutor(),
        extensionSessionStateCallback
   
)
    cameraDevice
.createExtensionSession(extensionConfiguration)
}


private CameraExtensionSession.ExtensionCaptureCallback captureCallbacks =
       
new CameraExtensionSession.ExtensionCaptureCallback() {
           
// Implement Capture Callbacks
       
};

private CameraExtensionSession.StateCallback extensionSessionStateCallback =
       
new CameraExtensionSession.StateCallback() {
           
@Override
           
public void onConfigured(@NonNull CameraExtensionSession session) {
                cameraExtensionSession
= session;
               
try {
                   
CaptureRequest.Builder captureRequestBuilder =
                            cameraDevice
.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                    captureRequestBuilder
.addTarget(previewSurface);
                   
CaptureRequest captureRequest = captureRequestBuilder.build();
                    session
.setRepeatingRequest(captureRequest, backgroundExecutor, captureCallbacks);
               
} catch (CameraAccessException e) {
                   
Snackbar.make(
                            previewView
,
                           
"Failed to preview capture request",
                           
Snackbar.LENGTH_SHORT
                   
).show();
                    requireActivity
().finish();
               
}
           
}

           
@Override
           
public void onClosed(@NonNull CameraExtensionSession session) {
               
super.onClosed(session);
                cameraDevice
.close();
           
}

           
@Override
           
public void onConfigureFailed(@NonNull CameraExtensionSession session) {
               
Snackbar.make(
                        previewView
,
                       
"Failed to start camera extension preview",
                       
Snackbar.LENGTH_SHORT
               
).show();
                requireActivity
().finish();
           
}
       
};

private void startExtensionSession() {
   
ArrayList<OutputConfiguration> outputConfig = new ArrayList<>();
    outputConfig
.add(new OutputConfiguration(stillImageReader.getSurface()));
    outputConfig
.add(new OutputConfiguration(previewSurface));
   
ExtensionSessionConfiguration extensionConfiguration = new ExtensionSessionConfiguration(
           
CameraExtensionCharacteristics.EXTENSION_NIGHT,
            outputConfig
,
            backgroundExecutor
,
            extensionSessionStateCallback
   
);
}

מקורות מידע נוספים

מידע נוסף זמין במאמר הבא: CameraExtensionCharacteristics ולצפות בדוגמאות הציבוריות של Camera2 extensions API לקבלת מידע נוסף.