अगर android.hardware.Camera
पदावनत किया जाता है और आप चर का उपयोग नहीं कर सकते हैं Camera
, तो इसका विकल्प क्या होगा?
अगर android.hardware.Camera
पदावनत किया जाता है और आप चर का उपयोग नहीं कर सकते हैं Camera
, तो इसका विकल्प क्या होगा?
जवाबों:
के अनुसार एंड्रॉयड डेवलपर्स गाइड के लिए 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;
}
}
}
अब अपने 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 का उपयोग नहीं करते हैं, तो आप बस एक उपयोगिता बना सकते हैं या उचित पैटर्न बनाने के लिए फ़ैक्टरी पैटर्न का उपयोग कर सकते हैं। महत्वपूर्ण हिस्सा यह है कि एपीआई स्तर की जाँच की जाती है।
@SuppressWarnings
इस QA stackoverflow.com/questions/7397996/… के
एक ही मुद्दे के साथ सामना करना पड़ा , पुराने कैमरे को अपग्रेड किए गए कैमरा एपीआई के माध्यम से समर्थन करना और वर्तमान उपकरणों के लिए नए कैमरा 2 एपीआई की आवश्यकता और भविष्य में आगे बढ़ना; मैं एक ही मुद्दों में भाग गया - और एक 3 पार्टी पुस्तकालय नहीं पाया है जो 2 एपीआई को पुल करता है, संभावना है कि क्योंकि वे बहुत अलग हैं, मैंने मूल ओओपी रियासतों की ओर रुख किया ।
2 एपीआई स्पष्ट रूप से अलग-अलग होते हैं जो पुराने एपीआई में प्रस्तुत इंटरफेस की अपेक्षा करते हुए ग्राहक वस्तुओं के लिए उन्हें समस्याग्रस्त बनाते हैं। नए एपीआई में अलग-अलग तरीकों के साथ अलग-अलग ऑब्जेक्ट हैं, एक अलग आर्किटेक्चर का उपयोग करके बनाया गया है। Google के लिए प्यार है, लेकिन ragnabbit! निराशा होती है।
इसलिए मैंने केवल अपने ऐप की ज़रूरत वाली कैमरा कार्यक्षमता पर एक फ़ोकसिंग बनाया, और दोनों एपीआई के लिए एक सरल आवरण बनाया जो उस इंटरफ़ेस को लागू करता है। इस तरह से मेरी कैमरा गतिविधि को इस बात की परवाह नहीं है कि कौन सा मंच किस पर चल रहा है ...
मैंने API का प्रबंधन करने के लिए एक सिंगलटन भी स्थापित किया; पुराने Android ओएस उपकरणों के लिए अपने इंटरफेस के साथ पुराने एपीआई के आवरण को बढ़ाना, और नए एपीआई का उपयोग करके नए उपकरणों के लिए नए एपीआई के रैपर वर्ग को। सिंगलटन के पास एपीआई स्तर प्राप्त करने के लिए विशिष्ट कोड होता है और फिर सही वस्तु को स्थापित करता है।
एक ही इंटरफ़ेस का उपयोग दोनों आवरण वर्गों द्वारा किया जाता है , इसलिए यह कोई फर्क नहीं पड़ता कि ऐप जेलीबीन या मार्शमैलो पर चलता है - जब तक कि इंटरफ़ेस उसी तरीके के हस्ताक्षर का उपयोग करके कैमरा एपीपी से इसकी आवश्यकता के साथ मेरा ऐप प्रदान करता है; कैमरा ऐप में Android के नए और पुराने संस्करणों के लिए उसी तरह चलता है।
सिंगलटन कुछ संबंधित चीजें भी कर सकता है जो एपीआई से जुड़ी नहीं हैं - जैसे कि यह पता लगाना कि डिवाइस पर वास्तव में एक कैमरा है, और मीडिया लाइब्रेरी को सहेजना है।
मुझे आशा है कि यह विचार आपकी मदद करेगा।
public interface AllCameraInterface { void open(); boolean setDirection(); Bitmap preview(); Bitmap takePhoto(); void close(); }
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(); } }
फिर इसे वापस करने की एक विधि ...
camera2
? मैं वास्तव में उलझन में हूँ ... मुझे सिर्फ enableAutofocus
कैमरा खोलने और अपना ध्यान केंद्रित करने के लिए विधि की आवश्यकता है : stackoverflow.com/questions/19076316/…
अब हमें 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;
}
}
});
}
}
यहां दिए गए उत्तर जो कैमरा आपी का उपयोग करने के लिए गलत हैं। या यह कहना बेहतर होगा कि वे अपर्याप्त हैं।
कुछ फोन (उदाहरण के लिए सैमसंग गैलेक्सी एस 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 को आजमा सकते हैं और यदि यह विफल हो जाता है तो आप अपने लिए डिफॉल्ट कैमरा खोलने के लिए एंड्रॉइड पर कॉल कर सकते हैं।
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();
}
}
android.hardware.camera2