अगर आपको अपने गेम में गेम कंट्रोलर की मदद करनी है, तो यह आपकी ज़िम्मेदारी है यह पक्का करने के लिए कि आपका गेम सभी डिवाइसों पर कंट्रोलर के हिसाब से काम करता है अलग-अलग वर्शन पर काम करते हैं. इससे आपके गेम को ज़्यादा लोगों तक पहुंचाने में मदद मिलती है और आपके खिलाड़ी बिना किसी रुकावट के गेमप्ले का आनंद ले सकते हैं. अपने कंट्रोलर को तब भी मैनेज किया जा सकता है, जब वे अपने Android डिवाइसों को स्विच या अपग्रेड करते हों.
यह लेख Android 4.1 और इसके बाद के वर्शन में उपलब्ध एपीआई के इस्तेमाल का तरीका बताता है पुराने सिस्टम के साथ काम करने की सुविधा देता है, ताकि आपका गेम नीचे बताए गए काम कर सके Android 3.1 और उसके बाद वाले वर्शन चला रहे डिवाइस पर फीचर्स:
- गेम यह पता लगा सकता है कि कोई नया गेम कंट्रोलर जोड़ा गया है, बदला गया है या हटाया गया है.
- गेम, गेम कंट्रोलर की क्षमताओं के बारे में क्वेरी कर सकता है.
- गेम, गेम कंट्रोलर से आने वाली मोशन इवेंट की पहचान कर सकता है.
इस लेसन में दिए गए उदाहरण, रेफ़रंस फ़ाइलों को लागू करने के तरीके पर आधारित हैं
डाउनलोड के लिए उपलब्ध नमूने ControllerSample.zip
से दिया गया
पढ़ें. इस सैंपल में, InputManagerCompat
को लागू करने का तरीका बताया गया है
अलग-अलग वर्शन के साथ काम करता है. सैंपल इकट्ठा करने के लिए, आपको
को Android 4.1 (एपीआई लेवल 16) या उसके बाद के वर्शन का इस्तेमाल करना चाहिए. कंपाइल हो जाने के बाद, ऐप्लिकेशन का सैंपल
बिल्ड के तौर पर, Android 3.1 (एपीआई लेवल 12) या उसके बाद के वर्शन वाले किसी भी डिवाइस पर काम करता है
टारगेट.
गेम कंट्रोलर से जुड़ी सहायता के लिए ऐब्स्ट्रैक्ट एपीआई तैयार करना
मान लीजिए कि आपको यह पता लगाना है कि गेम कंट्रोलर का कनेक्शन है या नहीं Android 3.1 (एपीआई लेवल 12) पर चल रहे डिवाइसों की स्थिति बदल गई है. हालांकि, ये एपीआई सिर्फ़ Android 4.1 (एपीआई लेवल 16) और उसके बाद वाले वर्शन में उपलब्ध हैं. इसलिए, आपको को Android 4.1 और इसके बाद के वर्शन के साथ काम करता हो. Android 3.1 से लेकर Android 4.0 तक के वर्शन पर काम करने वाला फ़ॉलबैक तरीका उपलब्ध कराते हैं.
यह पता लगाने में आपकी मदद करने के लिए कि किन सुविधाओं के लिए, इस तरह के फ़ॉलबैक तरीके की ज़रूरत है पुराने वर्शन वाली टेबल 1 में, गेम कंट्रोलर के काम करने के तरीके में अंतर बताया गया है Android 3.1 (एपीआई लेवल 12) और 4.1 (एपीआई लेवल) के बीच 16).
टेबल 1. गेम कंट्रोलर सपोर्ट के लिए सभी एपीआई अलग-अलग Android वर्शन हैं.
नियंत्रक की जानकारी | नियंत्रक API | एपीआई लेवल 12 | एपीआई लेवल 16 |
---|---|---|---|
डिवाइस की पहचान | getInputDeviceIds() |
• | |
getInputDevice() |
• | ||
getVibrator() |
• | ||
SOURCE_JOYSTICK |
• | • | |
SOURCE_GAMEPAD |
• | • | |
कनेक्शन स्थिति | onInputDeviceAdded() |
• | |
onInputDeviceChanged() |
• | ||
onInputDeviceRemoved() |
• | ||
इनपुट इवेंट की पहचान | डी-पैड दबाएं (
KEYCODE_DPAD_UP ,
KEYCODE_DPAD_DOWN ,
KEYCODE_DPAD_LEFT ,
KEYCODE_DPAD_RIGHT ,
KEYCODE_DPAD_CENTER ) |
• | • |
गेमपैड का बटन दबाएं (
BUTTON_A ,
BUTTON_B ,
BUTTON_THUMBL ,
BUTTON_THUMBR ,
BUTTON_SELECT ,
BUTTON_START ,
BUTTON_R1 ,
BUTTON_L1 ,
BUTTON_R2 ,
BUTTON_L2 ) |
• | • | |
जॉयस्टिक और टोपी स्विच करने की हलचल (
AXIS_X ,
AXIS_Y ,
AXIS_Z ,
AXIS_RZ ,
AXIS_HAT_X ,
AXIS_HAT_Y ) |
• | • | |
एनालॉग ट्रिगर प्रेस (
AXIS_LTRIGGER ,
AXIS_RTRIGGER ) |
• | • |
ऐब्स्ट्रक्शन का इस्तेमाल करके, वर्शन के हिसाब से गेम कंट्रोलर के लिए सपोर्ट बनाया जा सकता है अलग-अलग प्लैटफ़ॉर्म पर काम करता है. इस तरीके में ये चरण शामिल हैं:
- इंटरमीडियरी Java इंटरफ़ेस तय करें, जो आपके गेम के लिए ज़रूरी, गेम कंट्रोलर की सुविधाएं.
- Android में एपीआई का इस्तेमाल करने वाले इंटरफ़ेस को लागू करने के लिए, प्रॉक्सी को लागू करना 4.1 और उसके बाद के वर्शन.
- अपने इंटरफ़ेस को अपनी पसंद के मुताबिक लागू करें, जो उपलब्ध एपीआई का इस्तेमाल करता हो Android 3.1 से लेकर Android 4.0 तक.
- रनटाइम के दौरान, इन तरीकों के बीच स्विच करने के लिए लॉजिक बनाएं, और अपने गेम में इंटरफ़ेस का इस्तेमाल करना शुरू करें.
यह सुनिश्चित करने के लिए कि अमूर्तीकरण का उपयोग कैसे किया जा सकता है, Android के अलग-अलग वर्शन पर पुराने सिस्टम के साथ काम करने की सुविधा के साथ काम कर सकता है. लिखने में पुराने सिस्टम के साथ काम करने वाले यूज़र इंटरफ़ेस (यूआई).
पुराने सिस्टम के साथ काम करने की सुविधा के लिए इंटरफ़ेस जोड़ें
पुराने सिस्टम के साथ काम करने की सुविधा देने के लिए, अपनी ज़रूरत के हिसाब से कोई इंटरफ़ेस बनाएं वर्शन के हिसाब से लागू करने की सुविधा जोड़ें. इस तरीके का एक फ़ायदा यह है कि इससे Android 4.1 (एपीआई लेवल 16) के ऐसे सार्वजनिक इंटरफ़ेस का डुप्लीकेट वर्शन मिलता है सहायता करते हैं.
Kotlin
// The InputManagerCompat interface is a reference example. // The full code is provided in the ControllerSample.zip sample. interface InputManagerCompat { val inputDeviceIds: IntArray fun getInputDevice(id: Int): InputDevice fun registerInputDeviceListener( listener: InputManager.InputDeviceListener, handler: Handler? ) fun unregisterInputDeviceListener(listener:InputManager.InputDeviceListener) fun onGenericMotionEvent(event: MotionEvent) fun onPause() fun onResume() interface InputDeviceListener { fun onInputDeviceAdded(deviceId: Int) fun onInputDeviceChanged(deviceId: Int) fun onInputDeviceRemoved(deviceId: Int) } }
Java
// The InputManagerCompat interface is a reference example. // The full code is provided in the ControllerSample.zip sample. public interface InputManagerCompat { ... public InputDevice getInputDevice(int id); public int[] getInputDeviceIds(); public void registerInputDeviceListener( InputManagerCompat.InputDeviceListener listener, Handler handler); public void unregisterInputDeviceListener( InputManagerCompat.InputDeviceListener listener); public void onGenericMotionEvent(MotionEvent event); public void onPause(); public void onResume(); public interface InputDeviceListener { void onInputDeviceAdded(int deviceId); void onInputDeviceChanged(int deviceId); void onInputDeviceRemoved(int deviceId); } ... }
InputManagerCompat
इंटरफ़ेस में ये तरीके मौजूद हैं:
getInputDevice()
- मिरर
getInputDevice()
.InputDevice
हासिल करता है ऐसा ऑब्जेक्ट जो गेम कंट्रोलर की क्षमताओं के बारे में बताता हो. getInputDeviceIds()
- मिरर
getInputDeviceIds()
. पूर्णांकों की सरणी देता है, जिनमें से हर एक जो किसी दूसरे इनपुट डिवाइस का आईडी है. यह तब उपयोगी होता है, जब आपको एक ऐसा गेम जिसमें कई खिलाड़ी काम करते हैं और आपको यह पता लगाना है कि कितने कंट्रोलर कनेक्ट किए गए हैं. registerInputDeviceListener()
- मिरर
registerInputDeviceListener()
. इससे आपको रजिस्टर किया जा सकता है, ताकि नई सेवाओं के लिए आपको सूचना दी जा सके डिवाइस को जोड़ा, बदला या हटाया गया है. unregisterInputDeviceListener()
- मिरर
unregisterInputDeviceListener()
. इनपुट डिवाइस लिसनर का रजिस्ट्रेशन रद्द करता है. onGenericMotionEvent()
- मिरर
onGenericMotionEvent()
. आपके गेम को इंटरसेप्ट और हैंडल करने देता हैMotionEvent
ऑब्जेक्ट और ऐक्सिस की वैल्यू, जो इवेंट दिखाती हैं जैसे, जॉयस्टिक मूवमेंट और ऐनालॉग ट्रिगर दबाना. onPause()
- गेम कंट्रोलर इवेंट के लिए पोलिंग को बंद कर देता है, जब मुख्य गतिविधि को रोक दिया जाता है या जब गेम पर फ़ोकस न हो.
onResume()
- गेम कंट्रोलर इवेंट के लिए पोलिंग तब शुरू की जाती है, जब मुख्य गतिविधि फिर से शुरू हो जाती है या जब गेम शुरू होता है और फ़ोरग्राउंड है.
InputDeviceListener
InputManager.InputDeviceListener
मिरर करता है इंटरफ़ेस पर कॉपी करने की सुविधा मिलती है. इससे आपके गेम को यह पता चलता है कि गेम कंट्रोलर को जोड़ा गया है, बदला गया है या हटाया गया.
इसके बाद, काम करने वाले InputManagerCompat
के लिए लागू करें
वर्शन पर काम कर रहे हैं. अगर आपका गेम Android 4.1 या
बहुत बढ़िया करता है और InputManagerCompat
तरीके को कॉल करता है, यानी कि प्रॉक्सी लागू करने का तरीका
InputManager
में समान तरीके को कॉल करता है.
हालांकि, अगर आपका गेम Android 3.1 से लेकर Android 4.0 तक के वर्शन पर चल रहा है, तो
InputManagerCompat
तरीकों में किए गए कॉल को प्रोसेस करता है
सिर्फ़ ऐसे एपीआई जो Android 3.1 के बाद पेश किए गए हैं. फिर चाहे जो भी
रनटाइम के दौरान, वर्शन के हिसाब से लागू करने की सुविधा का इस्तेमाल किया जाता है, तो लागू करने की प्रक्रिया पास हो जाती है
कॉल के नतीजे साफ़ तौर पर गेम में दिखते हैं.
![](https://developer.android.google.cn/static/images/training/backward-compatible-inputmanager.png?authuser=5&hl=hi)
पहला डायग्राम. अलग-अलग वर्शन और इंटरफ़ेस का क्लास डायग्राम लागू करना.
इंटरफ़ेस को Android 4.1 और इसके बाद वाले वर्शन पर लागू करें
InputManagerCompatV16
,
InputManagerCompat
इंटरफ़ेस, जो
असल InputManager
और InputManager.InputDeviceListener
. कॉन्टेंट बनाने
InputManager
को सिस्टम से लिया गया है
Context
.
Kotlin
// The InputManagerCompatV16 class is a reference implementation. // The full code is provided in the ControllerSample.zip sample. public class InputManagerV16( context: Context, private val inputManager: InputManager = context.getSystemService(Context.INPUT_SERVICE) as InputManager, private val listeners: MutableMap<InputManager.InputDeviceListener, V16InputDeviceListener> = mutableMapOf() ) : InputManagerCompat { override val inputDeviceIds: IntArray = inputManager.inputDeviceIds override fun getInputDevice(id: Int): InputDevice = inputManager.getInputDevice(id) override fun registerInputDeviceListener( listener: InputManager.InputDeviceListener, handler: Handler? ) { V16InputDeviceListener(listener).also { v16listener -> inputManager.registerInputDeviceListener(v16listener, handler) listeners += listener to v16listener } } // Do the same for unregistering an input device listener ... override fun onGenericMotionEvent(event: MotionEvent) { // unused in V16 } override fun onPause() { // unused in V16 } override fun onResume() { // unused in V16 } } class V16InputDeviceListener( private val idl: InputManager.InputDeviceListener ) : InputManager.InputDeviceListener { override fun onInputDeviceAdded(deviceId: Int) { idl.onInputDeviceAdded(deviceId) } // Do the same for device change and removal ... }
Java
// The InputManagerCompatV16 class is a reference implementation. // The full code is provided in the ControllerSample.zip sample. public class InputManagerV16 implements InputManagerCompat { private final InputManager inputManager; private final Map<InputManagerCompat.InputDeviceListener, V16InputDeviceListener> listeners; public InputManagerV16(Context context) { inputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE); listeners = new HashMap<InputManagerCompat.InputDeviceListener, V16InputDeviceListener>(); } @Override public InputDevice getInputDevice(int id) { return inputManager.getInputDevice(id); } @Override public int[] getInputDeviceIds() { return inputManager.getInputDeviceIds(); } static class V16InputDeviceListener implements InputManager.InputDeviceListener { final InputManagerCompat.InputDeviceListener mIDL; public V16InputDeviceListener(InputDeviceListener idl) { mIDL = idl; } @Override public void onInputDeviceAdded(int deviceId) { mIDL.onInputDeviceAdded(deviceId); } // Do the same for device change and removal ... } @Override public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) { V16InputDeviceListener v16Listener = new V16InputDeviceListener(listener); inputManager.registerInputDeviceListener(v16Listener, handler); listeners.put(listener, v16Listener); } // Do the same for unregistering an input device listener ... @Override public void onGenericMotionEvent(MotionEvent event) { // unused in V16 } @Override public void onPause() { // unused in V16 } @Override public void onResume() { // unused in V16 } }
इंटरफ़ेस को Android 3.1 और Android 4.0 तक के वर्शन पर लागू करें
Android 3.1 से लेकर Android 4.0 तक के वर्शन पर चलने वाले InputManagerCompat
को लागू करने के लिए,
ये ऑब्जेक्ट:
- आइटम को ट्रैक करने के लिए,
SparseArray
डिवाइस आईडी डिवाइस से कनेक्ट किए गए गेम कंट्रोलर. - डिवाइस इवेंट प्रोसेस करने के लिए
Handler
. जब कोई ऐप्लिकेशन शुरू किया जाता है या फिर से शुरू करने पर,Handler
को पोलिंग शुरू करने के लिए मैसेज मिलेगा गेम कंट्रोलर के डिस्कनेक्शन के लिए किया जा सकता है.Handler
, कनेक्ट किए गए हर गेम कंट्रोलर को देखने के लिए, उसे लूप में चलाएं. साथ ही, यह भी देखें कि डिवाइस आईडी वापस किया गया.null
रिटर्न वैल्यू से पता चलता है कि गेम कंट्रोलर डिसकनेक्ट किया गया. ऐप्लिकेशन के चालू होने पर,Handler
पोल करना बंद कर देता है रोका गया. InputManagerCompat.InputDeviceListener
काMap
ऑब्जेक्ट हैं. ट्रैक की गई कनेक्शन स्थिति को अपडेट करने के लिए, लिसनर का इस्तेमाल किया जाएगा गेम कंट्रोलर.
Kotlin
// The InputManagerCompatV9 class is a reference implementation. // The full code is provided in the ControllerSample.zip sample. class InputManagerV9( val devices: SparseArray<Array<Long>> = SparseArray(), private val listeners: MutableMap<InputManager.InputDeviceListener, Handler> = mutableMapOf() ) : InputManagerCompat { private val defaultHandler: Handler = PollingMessageHandler(this) … }
Java
// The InputManagerCompatV9 class is a reference implementation. // The full code is provided in the ControllerSample.zip sample. public class InputManagerV9 implements InputManagerCompat { private final SparseArray<long[]> devices; private final Map<InputDeviceListener, Handler> listeners; private final Handler defaultHandler; … public InputManagerV9() { devices = new SparseArray<long[]>(); listeners = new HashMap<InputDeviceListener, Handler>(); defaultHandler = new PollingMessageHandler(this); } }
ऐसा PollingMessageHandler
ऑब्जेक्ट लागू करें जो बड़ा हो
Handler
से शुरू होगा और
handleMessage()
तरीका. इस तरीके से यह पता चलता है कि अटैच किया गया गेम कंट्रोलर
इससे, रजिस्टर किए गए लिसनर को डिसकनेक्ट किया जाता है और रजिस्टर किए गए लिसनर को इसकी सूचना दी जाती है.
Kotlin
private class PollingMessageHandler( inputManager: InputManagerV9, private val mInputManager: WeakReference<InputManagerV9> = WeakReference(inputManager) ) : Handler() { override fun handleMessage(msg: Message) { super.handleMessage(msg) when (msg.what) { MESSAGE_TEST_FOR_DISCONNECT -> { mInputManager.get()?.also { imv -> val time = SystemClock.elapsedRealtime() val size = imv.devices.size() for (i in 0 until size) { imv.devices.valueAt(i)?.also { lastContact -> if (time - lastContact[0] > CHECK_ELAPSED_TIME) { // check to see if the device has been // disconnected val id = imv.devices.keyAt(i) if (null == InputDevice.getDevice(id)) { // Notify the registered listeners // that the game controller is disconnected imv.devices.remove(id) } else { lastContact[0] = time } } } } sendEmptyMessageDelayed(MESSAGE_TEST_FOR_DISCONNECT, CHECK_ELAPSED_TIME) } } } } }
Java
private static class PollingMessageHandler extends Handler { private final WeakReference<InputManagerV9> inputManager; PollingMessageHandler(InputManagerV9 im) { inputManager = new WeakReference<InputManagerV9>(im); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case MESSAGE_TEST_FOR_DISCONNECT: InputManagerV9 imv = inputManager.get(); if (null != imv) { long time = SystemClock.elapsedRealtime(); int size = imv.devices.size(); for (int i = 0; i < size; i++) { long[] lastContact = imv.devices.valueAt(i); if (null != lastContact) { if (time - lastContact[0] > CHECK_ELAPSED_TIME) { // check to see if the device has been // disconnected int id = imv.devices.keyAt(i); if (null == InputDevice.getDevice(id)) { // Notify the registered listeners // that the game controller is disconnected imv.devices.remove(id); } else { lastContact[0] = time; } } } } sendEmptyMessageDelayed(MESSAGE_TEST_FOR_DISCONNECT, CHECK_ELAPSED_TIME); } break; } } }
गेम कंट्रोलर को डिसकनेक्ट करने के लिए पोलिंग को शुरू और बंद करने के लिए, नीति को बदलें ये तरीके अपनाएं:
Kotlin
private const val MESSAGE_TEST_FOR_DISCONNECT = 101 private const val CHECK_ELAPSED_TIME = 3000L class InputManagerV9( val devices: SparseArray<Array<Long>> = SparseArray(), private val listeners: MutableMap<InputManager.InputDeviceListener, Handler> = mutableMapOf() ) : InputManagerCompat { ... override fun onPause() { defaultHandler.removeMessages(MESSAGE_TEST_FOR_DISCONNECT) } override fun onResume() { defaultHandler.sendEmptyMessageDelayed(MESSAGE_TEST_FOR_DISCONNECT, CHECK_ELAPSED_TIME) } ... }
Java
private static final int MESSAGE_TEST_FOR_DISCONNECT = 101; private static final long CHECK_ELAPSED_TIME = 3000L; @Override public void onPause() { defaultHandler.removeMessages(MESSAGE_TEST_FOR_DISCONNECT); } @Override public void onResume() { defaultHandler.sendEmptyMessageDelayed(MESSAGE_TEST_FOR_DISCONNECT, CHECK_ELAPSED_TIME); }
यह पता लगाने के लिए कि किसी इनपुट डिवाइस को जोड़ा गया है, को ओवरराइड करें
onGenericMotionEvent()
तरीका. जब सिस्टम किसी हलचल की सूचना देता है, तो
जांचें कि यह इवेंट पहले से ट्रैक किए जा रहे डिवाइस आईडी से या किसी
नया डिवाइस आईडी. अगर डिवाइस आईडी नया है, तो रजिस्टर किए गए लिसनर को सूचित करें.
Kotlin
override fun onGenericMotionEvent(event: MotionEvent) { // detect new devices val id = event.deviceId val timeArray: Array<Long> = mDevices.get(id) ?: run { // Notify the registered listeners that a game controller is added ... arrayOf<Long>().also { mDevices.put(id, it) } } timeArray[0] = SystemClock.elapsedRealtime() }
Java
@Override public void onGenericMotionEvent(MotionEvent event) { // detect new devices int id = event.getDeviceId(); long[] timeArray = mDevices.get(id); if (null == timeArray) { // Notify the registered listeners that a game controller is added ... timeArray = new long[1]; mDevices.put(id, timeArray); } long time = SystemClock.elapsedRealtime(); timeArray[0] = time; }
इसका इस्तेमाल करके, लिसनर को सूचना देने की सुविधा को लागू किया जाता है
DeviceEvent
भेजने के लिए Handler
ऑब्जेक्ट
Runnable
ऑब्जेक्ट को मैसेज की सूची में शामिल करता है. DeviceEvent
में InputManagerCompat.InputDeviceListener
का संदर्भ है. टास्क कब शुरू होगा
इसका इस्तेमाल करने पर, लिसनर के हिसाब से कॉलबैक का सही तरीका DeviceEvent
चलता है
यह कहा जाता है कि गेम कंट्रोलर को जोड़ा गया हो, बदला गया हो या हटाया गया हो.
Kotlin
class InputManagerV9( val devices: SparseArray<Array<Long>> = SparseArray(), private val listeners: MutableMap<InputManager.InputDeviceListener, Handler> = mutableMapOf() ) : InputManagerCompat { ... override fun registerInputDeviceListener( listener: InputManager.InputDeviceListener, handler: Handler? ) { listeners[listener] = handler ?: defaultHandler } override fun unregisterInputDeviceListener(listener: InputManager.InputDeviceListener) { listeners.remove(listener) } private fun notifyListeners(why: Int, deviceId: Int) { // the state of some device has changed listeners.forEach { listener, handler -> DeviceEvent.getDeviceEvent(why, deviceId, listener).also { handler?.post(it) } } } ... } private val sObjectQueue: Queue<DeviceEvent> = ArrayDeque<DeviceEvent>() private class DeviceEvent( private var mMessageType: Int, private var mId: Int, private var mListener: InputManager.InputDeviceListener ) : Runnable { companion object { fun getDeviceEvent(messageType: Int, id: Int, listener: InputManager.InputDeviceListener) = sObjectQueue.poll()?.apply { mMessageType = messageType mId = id mListener = listener } ?: DeviceEvent(messageType, id, listener) } override fun run() { when(mMessageType) { ON_DEVICE_ADDED -> mListener.onInputDeviceAdded(mId) ON_DEVICE_CHANGED -> mListener.onInputDeviceChanged(mId) ON_DEVICE_REMOVED -> mListener.onInputDeviceChanged(mId) else -> { // Handle unknown message type } } } }
Java
@Override public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) { listeners.remove(listener); if (handler == null) { handler = defaultHandler; } listeners.put(listener, handler); } @Override public void unregisterInputDeviceListener(InputDeviceListener listener) { listeners.remove(listener); } private void notifyListeners(int why, int deviceId) { // the state of some device has changed if (!listeners.isEmpty()) { for (InputDeviceListener listener : listeners.keySet()) { Handler handler = listeners.get(listener); DeviceEvent odc = DeviceEvent.getDeviceEvent(why, deviceId, listener); handler.post(odc); } } } private static class DeviceEvent implements Runnable { private int mMessageType; private int mId; private InputDeviceListener mListener; private static Queue<DeviceEvent> sObjectQueue = new ArrayDeque<DeviceEvent>(); ... static DeviceEvent getDeviceEvent(int messageType, int id, InputDeviceListener listener) { DeviceEvent curChanged = sObjectQueue.poll(); if (null == curChanged) { curChanged = new DeviceEvent(); } curChanged.mMessageType = messageType; curChanged.mId = id; curChanged.mListener = listener; return curChanged; } @Override public void run() { switch (mMessageType) { case ON_DEVICE_ADDED: mListener.onInputDeviceAdded(mId); break; case ON_DEVICE_CHANGED: mListener.onInputDeviceChanged(mId); break; case ON_DEVICE_REMOVED: mListener.onInputDeviceRemoved(mId); break; default: // Handle unknown message type ... break; } // Put this runnable back in the queue sObjectQueue.offer(this); } }
अब आपके पास InputManagerCompat
के दो इंप्लीमेंटेशन हैं: एक
Android 4.1 और उसके बाद वाले वर्शन चला रहे डिवाइसों पर काम करता है और अन्य
जो Android 3.1 से लेकर Android 4.0 तक के वर्शन वाले डिवाइसों पर काम करता है.
वर्शन के हिसाब से लागू करने की सुविधा का इस्तेमाल करना
वर्शन के हिसाब से स्विच करने वाला लॉजिक, ऐसी क्लास में लागू किया जाता है जो इस तरह काम करती है: फ़ैक्ट्री.
Kotlin
object Factory { fun getInputManager(context: Context): InputManagerCompat = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { InputManagerV16(context) } else { InputManagerV9() } }
Java
public static class Factory { public static InputManagerCompat getInputManager(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { return new InputManagerV16(context); } else { return new InputManagerV9(); } } }
अब आप आसानी से InputManagerCompat
ऑब्जेक्ट को इंस्टैंशिएट कर सकते हैं और
अपने मुख्य खाते में InputManagerCompat.InputDeviceListener
को रजिस्टर करें
View
. आपके सेट किए गए वर्शन-स्विचिंग लॉजिक की वजह से
होता है, तो आपका गेम अपने-आप उस सुविधा का इस्तेमाल करता है जो
Android का एक वर्शन है जिस पर डिवाइस चल रहा है.
Kotlin
class GameView(context: Context) : View(context), InputManager.InputDeviceListener { private val inputManager: InputManagerCompat = Factory.getInputManager(context).apply { registerInputDeviceListener(this@GameView, null) ... } ... }
Java
public class GameView extends View implements InputDeviceListener { private InputManagerCompat inputManager; ... public GameView(Context context, AttributeSet attrs) { inputManager = InputManagerCompat.Factory.getInputManager(this.getContext()); inputManager.registerInputDeviceListener(this, null); ... } }
इसके बाद,
आपके मुख्य व्यू में onGenericMotionEvent()
तरीका, जैसा कि इसमें बताया गया है
किसी गेम से MotionEvent मैनेज करें
कंट्रोलर. अब आपका गेम, गेम कंट्रोलर के इवेंट प्रोसेस कर पाएगा
यह सुविधा, Android 3.1 (एपीआई लेवल 12) और उसके बाद के वर्शन वाले डिवाइसों पर लगातार काम करती है.
Kotlin
override fun onGenericMotionEvent(event: MotionEvent): Boolean { inputManager.onGenericMotionEvent(event) // Handle analog input from the controller as normal ... return super.onGenericMotionEvent(event) }
Java
@Override public boolean onGenericMotionEvent(MotionEvent event) { inputManager.onGenericMotionEvent(event); // Handle analog input from the controller as normal ... return super.onGenericMotionEvent(event); }
साथ काम करने वाले इस कोड को पूरी तरह लागू करने पर, आपको
ControllerSample.zip
सैंपल में GameView
क्लास दी गई
ऊपर डाउनलोड करने के लिए उपलब्ध है.