Android कैमरा android.hardware.Camera अपदस्थ


97

अगर android.hardware.Cameraपदावनत किया जाता है और आप चर का उपयोग नहीं कर सकते हैं Camera, तो इसका विकल्प क्या होगा?



1
मुझे एक ऐप में यह समस्या आई और मुझे यह बहुत मददगार लगी। यदि आप इरादे का उपयोग करते हैं, तो आप सीमित हैं। इसलिए यह ट्यूटोरियल एक विकल्प बताता है: developer.android.com/guide/topics/media/…
Ronaldo Bahia

जवाबों:


103

एपीआई प्रलेखन

के अनुसार एंड्रॉयड डेवलपर्स गाइड के लिए android.hardware.Camera, वे राज्य:

हम नए अनुप्रयोगों के लिए नए android.hardware.camera2 API का उपयोग करने की सलाह देते हैं ।

के बारे में जानकारी पृष्ठ पर android.hardware.camera2, (उपरोक्त लिंक), यह कहा गया है:

Android.hardware.camera2 पैकेज एंड्रॉइड डिवाइस से जुड़े व्यक्तिगत कैमरा उपकरणों के लिए एक इंटरफ़ेस प्रदान करता है। यह हटाए गए कैमरा वर्ग की जगह लेता है।

समस्या

जब आप उस दस्तावेज़ की जांच करते हैं, तो आप पाएंगे कि इन 2 कैमरा एपीआई के कार्यान्वयन बहुत अलग हैं।

उदाहरण के लिए कैमरा ओरिएंटेशन प्राप्त करना android.hardware.camera

@Override
public int getOrientation(final int cameraId) {
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    return info.orientation;
}

बनाम android.hardware.camera2

@Override
public int getOrientation(final int cameraId) {
    try {
        CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        String[] cameraIds = manager.getCameraIdList();
        CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIds[cameraId]);
        return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
    } catch (CameraAccessException e) {
        // TODO handle error properly or pass it on
        return 0;
    }
}

इससे एक से दूसरे पर स्विच करना और कोड लिखना मुश्किल हो जाता है जो दोनों कार्यान्वयन को संभाल सकता है।

ध्यान दें कि इस एकल कोड उदाहरण में मुझे पहले से ही इस तथ्य के आसपास काम करना था कि intपुराना कैमरा एपीआई कैमरा आईडी के लिए प्राइमेटिव्स के साथ काम करता है जबकि नया Stringऑब्जेक्ट के साथ काम करता है। इस उदाहरण के लिए मैंने जल्दी से तय किया कि नए एपीआई में एक इंडेक्स के रूप में इंट का उपयोग करके। यदि कैमरे का रिटर्न हमेशा एक ही क्रम में नहीं होता है तो यह पहले से ही समस्या का कारण होगा। वैकल्पिक दृष्टिकोण स्ट्रिंग ऑब्जेक्ट्स और पुराने इंट कैमराआईडी के स्ट्रिंग प्रतिनिधित्व के साथ काम करना है जो संभवतः सुरक्षित है।

चारों ओर दूर

अब इस विशाल अंतर के आसपास काम करने के लिए आप पहले एक इंटरफ़ेस लागू कर सकते हैं और उस इंटरफ़ेस को अपने कोड में संदर्भित कर सकते हैं।

यहाँ मैं उस इंटरफ़ेस और 2 कार्यान्वयन के लिए कुछ कोड सूचीबद्ध करूँगा। आप कार्यान्वयन को सीमित कर सकते हैं कि आप वास्तव में काम की मात्रा को सीमित करने के लिए कैमरा एपीआई का उपयोग करते हैं।

अगले भाग में मैं जल्दी से समझाऊंगा कि कैसे एक या दूसरे को लोड किया जाए।

इस उदाहरण को सीमित करने के लिए आपको केवल अपनी जरूरत के हिसाब से इंटरफेस की जरूरत है, मेरे यहां केवल 2 तरीके हैं।

public interface CameraSupport {
    CameraSupport open(int cameraId);
    int getOrientation(int cameraId);
}

अब पुराने कैमरा हार्डवेयर एपी के लिए एक वर्ग है:

@SuppressWarnings("deprecation")
public class CameraOld implements CameraSupport {

    private Camera camera;

    @Override
    public CameraSupport open(final int cameraId) {
        this.camera = Camera.open(cameraId);
        return this;
    }

    @Override
    public int getOrientation(final int cameraId) {
       Camera.CameraInfo info = new Camera.CameraInfo();
       Camera.getCameraInfo(cameraId, info);
       return info.orientation;
    }
}

और नए हार्डवेयर एपीआई के लिए एक और एक:

public class CameraNew implements CameraSupport {

    private CameraDevice camera;
    private CameraManager manager;

    public CameraNew(final Context context) {
        this.manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
    }

    @Override
    public CameraSupport open(final int cameraId) {
        try {
            String[] cameraIds = manager.getCameraIdList();
            manager.openCamera(cameraIds[cameraId], new CameraDevice.StateCallback() {
                @Override
                public void onOpened(CameraDevice camera) {
                    CameraNew.this.camera = camera;
                }

                @Override
                public void onDisconnected(CameraDevice camera) {
                    CameraNew.this.camera = camera;
                    // TODO handle
                }

                @Override
                public void onError(CameraDevice camera, int error) {
                    CameraNew.this.camera = camera;
                    // TODO handle
                }
            }, null);
        } catch (Exception e) {
            // TODO handle
        }
        return this;
    }

    @Override
    public int getOrientation(final int cameraId) {
        try {
            String[] cameraIds = manager.getCameraIdList();
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIds[cameraId]);
            return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
        } catch (CameraAccessException e) {
            // TODO handle
            return 0;
        }
    }
}

उचित API लोड हो रहा है

अब अपने CameraOldया CameraNewवर्ग को लोड करने के लिए आपको एपीआई स्तर की जांच करनी होगी क्योंकि CameraNewकेवल एपी स्तर 21 से उपलब्ध है।

यदि आपके पास निर्भरता इंजेक्शन पहले से ही है, तो आप CameraSupportकार्यान्वयन प्रदान करते समय अपने मॉड्यूल में ऐसा कर सकते हैं । उदाहरण:

@Module public class CameraModule {

    @Provides
    CameraSupport provideCameraSupport(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return new CameraNew(context);
        } else {
            return new CameraOld();
        }
    } 
}

यदि आप DI का उपयोग नहीं करते हैं, तो आप बस एक उपयोगिता बना सकते हैं या उचित पैटर्न बनाने के लिए फ़ैक्टरी पैटर्न का उपयोग कर सकते हैं। महत्वपूर्ण हिस्सा यह है कि एपीआई स्तर की जाँच की जाती है।


25
क्या होगा अगर मुझे 21 से कम Android एपीआई स्तर का समर्थन करने की आवश्यकता है?
niveuseverto

1
@Angelius शायद यह दस्तावेज़ीकरण मदद करने वाले डेवलपर होगा ।android.com/guide/topics/media/camera.html - लेकिन यह एक अलग प्रश्न हो सकता है, या पदावनत चर का उपयोग करने के बारे में प्रश्नों की खोज कर सकता है।

@Angelius @SuppressWarningsइस QA stackoverflow.com/questions/7397996/… के

5
मैं न केवल @deprecated कक्षाओं का उपयोग करने के बारे में सोच रहा हूं, लेकिन पिछड़े संगतता के साथ ऐप कैसे बना सकता हूं? इस पर कोई आधिकारिक मदद? मेरे पास इस बारे में विचार है: ICamera इंटरफ़ेस, जो वर्तमान फ़ोन संस्करण पर संगत कैमरा ऑब्जेक्ट के साथ समर्थित है, लेकिन यह थोड़ा सीधा है और इसे बनाए रखने के लिए कठिन है ...
niveuseverto

@Angelius जो आप बता रहे हैं वह एक अलग प्रश्न हो सकता है (यह देखने के लिए जांचें कि क्या यह पहले पूछा गया है)।

5

एक ही मुद्दे के साथ सामना करना पड़ा , पुराने कैमरे को अपग्रेड किए गए कैमरा एपीआई के माध्यम से समर्थन करना और वर्तमान उपकरणों के लिए नए कैमरा 2 एपीआई की आवश्यकता और भविष्य में आगे बढ़ना; मैं एक ही मुद्दों में भाग गया - और एक 3 पार्टी पुस्तकालय नहीं पाया है जो 2 एपीआई को पुल करता है, संभावना है कि क्योंकि वे बहुत अलग हैं, मैंने मूल ओओपी रियासतों की ओर रुख किया

2 एपीआई स्पष्ट रूप से अलग-अलग होते हैं जो पुराने एपीआई में प्रस्तुत इंटरफेस की अपेक्षा करते हुए ग्राहक वस्तुओं के लिए उन्हें समस्याग्रस्त बनाते हैं। नए एपीआई में अलग-अलग तरीकों के साथ अलग-अलग ऑब्जेक्ट हैं, एक अलग आर्किटेक्चर का उपयोग करके बनाया गया है। Google के लिए प्यार है, लेकिन ragnabbit! निराशा होती है।

इसलिए मैंने केवल अपने ऐप की ज़रूरत वाली कैमरा कार्यक्षमता पर एक फ़ोकसिंग बनाया, और दोनों एपीआई के लिए एक सरल आवरण बनाया जो उस इंटरफ़ेस को लागू करता है। इस तरह से मेरी कैमरा गतिविधि को इस बात की परवाह नहीं है कि कौन सा मंच किस पर चल रहा है ...

मैंने API का प्रबंधन करने के लिए एक सिंगलटन भी स्थापित किया; पुराने Android ओएस उपकरणों के लिए अपने इंटरफेस के साथ पुराने एपीआई के आवरण को बढ़ाना, और नए एपीआई का उपयोग करके नए उपकरणों के लिए नए एपीआई के रैपर वर्ग को। सिंगलटन के पास एपीआई स्तर प्राप्त करने के लिए विशिष्ट कोड होता है और फिर सही वस्तु को स्थापित करता है।

एक ही इंटरफ़ेस का उपयोग दोनों आवरण वर्गों द्वारा किया जाता है , इसलिए यह कोई फर्क नहीं पड़ता कि ऐप जेलीबीन या मार्शमैलो पर चलता है - जब तक कि इंटरफ़ेस उसी तरीके के हस्ताक्षर का उपयोग करके कैमरा एपीपी से इसकी आवश्यकता के साथ मेरा ऐप प्रदान करता है; कैमरा ऐप में Android के नए और पुराने संस्करणों के लिए उसी तरह चलता है।

सिंगलटन कुछ संबंधित चीजें भी कर सकता है जो एपीआई से जुड़ी नहीं हैं - जैसे कि यह पता लगाना कि डिवाइस पर वास्तव में एक कैमरा है, और मीडिया लाइब्रेरी को सहेजना है।

मुझे आशा है कि यह विचार आपकी मदद करेगा।


उदाहरण के लिए:public interface AllCameraInterface { void open(); boolean setDirection(); Bitmap preview(); Bitmap takePhoto(); void close(); }
रॉबर्ट शर्मन

ex: public interface AllCameraInterface { void open(); Bitmap takePhoto(); void close(); etc... } public class NCamera implements AllCameraInterface... public class OCamera implements AllCameraInterface... public class AllCamera { private static AllCamera ourInstance = new AllCamera(); public static AllCamera getInstance() {...} private AllCameraInterface camera; private AllCamera() { if (android.os.Build.VERSION.SDK_INT <= 20) { camera = new OCamera(); } else { camera = new NCamera(); } }फिर इसे वापस करने की एक विधि ...
रॉबर्ट शर्मन

जाहिरा तौर पर टिप्पणियों में कोई लाइन टूटने की अनुमति नहीं है;; लेकिन यह वास्तव में काम करता है।
रॉबर्ट शर्मन

4
सीधे उत्तर में टिप्पणियों में कोड संलग्न क्यों नहीं?
एन्जिल कोह

@ रोबर्टशर्मन हाय रॉबर्ट, क्या आप कृपया मुझे इस छोटे से छोटे स्निपेट को फिर से लिखने में मदद कर सकते हैं camera2? मैं वास्तव में उलझन में हूँ ... मुझे सिर्फ enableAutofocusकैमरा खोलने और अपना ध्यान केंद्रित करने के लिए विधि की आवश्यकता है : stackoverflow.com/questions/19076316/…

0

अब हमें android.hardware.camera2 को android.hardware.Camera के रूप में उपयोग करना है, जो केवल API> 23 FlashLight पर काम करेगा

   public class MainActivity extends AppCompatActivity {

     Button button;

     Boolean light=true;

     CameraDevice cameraDevice;

     private CameraManager cameraManager;

     private CameraCharacteristics cameraCharacteristics;

     String cameraId;

     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=(Button)findViewById(R.id.button);
        cameraManager = (CameraManager) 
        getSystemService(Context.CAMERA_SERVICE);
        try {
          cameraId = cameraManager.getCameraIdList()[0];
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(light){
                    try {

                        cameraManager.setTorchMode(cameraId,true);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }

                    light=false;}
                    else {

                    try {

                      cameraManager.setTorchMode(cameraId,false);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }


                    light=true;
                    }


            }
        });
    }
}

0

यहां दिए गए उत्तर जो कैमरा आपी का उपयोग करने के लिए गलत हैं। या यह कहना बेहतर होगा कि वे अपर्याप्त हैं।

कुछ फोन (उदाहरण के लिए सैमसंग गैलेक्सी एस 6) एपीआई स्तर 21 से ऊपर हो सकते हैं, लेकिन फिर भी कैमरा 2 एपी को सपोर्ट नहीं कर सकते हैं।

CameraCharacteristics mCameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId);
Integer level = mCameraCharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (level == null || level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
    return false;
}

Camera2Api में CameraManager वर्ग में कैमरा विशेषताओं को पढ़ने की एक विधि है। आपको जांचना चाहिए कि हार्डवेयर वार डिवाइस Camera2 Api को सपोर्ट कर रहा है या नहीं।

लेकिन अगर आप वास्तव में इसे एक गंभीर अनुप्रयोग के लिए काम करना चाहते हैं, तो इसे संभालने के लिए और अधिक मुद्दे हैं: जैसे, कुछ उपकरणों के लिए ऑटो-फ्लैश विकल्प काम नहीं कर सकता है या फोन का बैटरी स्तर कैमरा पर एक RuntimeException बना सकता है या फोन एक अमान्य वापस आ सकता है कैमरा आईडी और आदि

तो सबसे अच्छा तरीका यह है कि किसी कारणवश आपके पास फालबैक मैकेनिज्म हो, क्योंकि कैमरा 2 शुरू करने में विफल रहता है आप कैमरा 1 को आजमा सकते हैं और यदि यह विफल हो जाता है तो आप अपने लिए डिफॉल्ट कैमरा खोलने के लिए एंड्रॉइड पर कॉल कर सकते हैं।


0
 if ( getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {

          CameraManager cameraManager=(CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);


           try {
               String cameraId = cameraManager.getCameraIdList()[0];
               cameraManager.setTorchMode(cameraId,true);
           } catch (CameraAccessException e) {
               e.printStackTrace();
           }


 }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.