ইনপুট এবং সেন্সর

অ্যান্ড্রয়েড এসডিকে আপনাকে গ্লাস EE2 এর সাথে উপলব্ধ বিভিন্ন ইনপুট এবং সেন্সরগুলিতে অ্যাক্সেস দেয়। এই পৃষ্ঠাটি আপনাকে উপলব্ধ বৈশিষ্ট্যগুলির একটি সারসংক্ষেপ, বাস্তবায়নের বিবরণ এবং সহায়ক টিপস প্রদান করে।

স্পর্শ অঙ্গভঙ্গি

আপনি Glass টাচপ্যাড থেকে raw ডেটা অ্যাক্সেস সক্ষম করতে Android SDK ব্যবহার করতে পারেন। এটি একটি জেসচার ডিটেক্টরের মাধ্যমে সম্পন্ন করা হয় যা স্বয়ংক্রিয়ভাবে Glass-এ ট্যাপ, ফ্লিং এবং স্ক্রোলের মতো সাধারণ অঙ্গভঙ্গি সনাক্ত করে।

আপনি আপনার অ্যাপগুলিতে এই জেসচার ডিটেক্টরটি ব্যবহার করে ট্যাপ, সোয়াইপ ফরোয়ার্ড, সোয়াইপ ব্যাক এবং সোয়াইপ ডাউনের হিসাব রাখতে পারেন। এটি পূর্ববর্তী গ্লাস ডিভাইসগুলির মতোই।

এই অঙ্গভঙ্গিগুলি নিম্নলিখিত উপায়ে ব্যবহার করা ভাল:

  • ট্যাপ করুন : নিশ্চিত করুন অথবা প্রবেশ করুন।
  • সামনের দিকে সোয়াইপ করুন , পিছনে সোয়াইপ করুন : কার্ড এবং স্ক্রিনের মধ্য দিয়ে নেভিগেট করুন।
  • নিচের দিকে সোয়াইপ করুন : পিছনে যান অথবা প্রস্থান করুন।

বাস্তবায়নের বিশদ বিবরণের জন্য, নমুনা অঙ্গভঙ্গি সনাক্তকারী পড়ুন।

অ্যান্ড্রয়েড জেসচার ডিটেক্টর দিয়ে অঙ্গভঙ্গি সনাক্ত করুন

অ্যান্ড্রয়েড GestureDetector আপনাকে সহজ এবং জটিল অঙ্গভঙ্গি সনাক্ত করতে দেয়, যেমন একাধিক আঙুল ব্যবহার করে বা স্ক্রলিং করে।

অ্যাক্টিভিটি-লেভেলের অঙ্গভঙ্গি সনাক্ত করুন

আপনার UI এর কোন অংশে ফোকাস আছে তা বিবেচ্য নয়, শুধুমাত্র তখনই অ্যাক্টিভিটি লেভেলে জেসচার সনাক্ত করুন। উদাহরণস্বরূপ, যদি আপনি কোনও ব্যবহারকারী টাচপ্যাডে ট্যাপ করলে একটি মেনু আনতে চান, কোন ভিউতে ফোকাস আছে তা নির্বিশেষে, অ্যাক্টিভিটির ভিতরে MotionEvent পরিচালনা করুন।

নিচে অ্যাক্টিভিটি-লেভেল জেসচার ডিটেকশনের একটি উদাহরণ দেওয়া হল যা GestureDetector ব্যবহার করে এবং GestureDetector.OnGestureListener প্রয়োগ করে স্বীকৃত জেসচারগুলি প্রক্রিয়া করে, যা পরে পরিচালনা করা হয় এবং নিম্নলিখিতগুলিতে অনুবাদ করা হয়:

  • TAP
  • SWIPE_FORWARD
  • SWIPE_BACKWARD
  • SWIPE_UP
  • SWIPE_DOWN

কোটলিন

class GlassGestureDetector(context: Context, private val onGestureListener: OnGestureListener) :
    GestureDetector.OnGestureListener {

    private val gestureDetector = GestureDetector(context, this)

    enum class Gesture {
        TAP,
        SWIPE_FORWARD,
        SWIPE_BACKWARD,
        SWIPE_UP,
        SWIPE_DOWN
    }

    interface OnGestureListener {
        fun onGesture(gesture: Gesture): Boolean
    }

    fun onTouchEvent(motionEvent: MotionEvent): Boolean {
        return gestureDetector.onTouchEvent(motionEvent)
    }

    override fun onDown(e: MotionEvent): Boolean {
        return false
    }

    override fun onShowPress(e: MotionEvent) {}

    override fun onSingleTapUp(e: MotionEvent): Boolean {
        return onGestureListener.onGesture(Gesture.TAP)
    }

    override fun onScroll(
        e1: MotionEvent,
        e2: MotionEvent,
        distanceX: Float,
        distanceY: Float
    ): Boolean {
        return false
    }

    override fun onLongPress(e: MotionEvent) {}

    /**
     * Swipe detection depends on the:
     * - movement tan value,
     * - movement distance,
     * - movement velocity.
     *
     * To prevent unintentional SWIPE_DOWN and SWIPE_UP gestures, they are detected if movement
     * angle is only between 60 and 120 degrees.
     * Any other detected swipes, will be considered as SWIPE_FORWARD and SWIPE_BACKWARD, depends
     * on deltaX value sign.
     *
     * ______________________________________________________________
     * |                     \        UP         /                    |
     * |                       \               /                      |
     * |                         60         120                       |
     * |                           \       /                          |
     * |                             \   /                            |
     * |  BACKWARD  <-------  0  ------------  180  ------>  FORWARD  |
     * |                             /   \                            |
     * |                           /       \                          |
     * |                         60         120                       |
     * |                       /               \                      |
     * |                     /       DOWN        \                    |
     * --------------------------------------------------------------
     */
    override fun onFling(
        e1: MotionEvent,
        e2: MotionEvent,
        velocityX: Float,
        velocityY: Float
    ): Boolean {
        val deltaX = e2.x - e1.x
        val deltaY = e2.y - e1.y
        val tan =
            if (deltaX != 0f) abs(deltaY / deltaX).toDouble() else java.lang.Double.MAX_VALUE

        return if (tan > TAN_60_DEGREES) {
            if (abs(deltaY) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityY) < SWIPE_VELOCITY_THRESHOLD_PX) {
                false
            } else if (deltaY < 0) {
                onGestureListener.onGesture(Gesture.SWIPE_UP)
            } else {
                onGestureListener.onGesture(Gesture.SWIPE_DOWN)
            }
        } else {
            if (Math.abs(deltaX) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityX) < SWIPE_VELOCITY_THRESHOLD_PX) {
                false
            } else if (deltaX < 0) {
                onGestureListener.onGesture(Gesture.SWIPE_FORWARD)
            } else {
                onGestureListener.onGesture(Gesture.SWIPE_BACKWARD)
            }
        }
    }

    companion object {

        private const val SWIPE_DISTANCE_THRESHOLD_PX = 100
        private const val SWIPE_VELOCITY_THRESHOLD_PX = 100
        private val TAN_60_DEGREES = tan(Math.toRadians(60.0))
    }
}

জাভা

  public class GlassGestureDetector implements GestureDetector.OnGestureListener {

   enum Gesture {
     TAP,
     SWIPE_FORWARD,
     SWIPE_BACKWARD,
     SWIPE_UP,
     SWIPE_DOWN,
   }

   interface OnGestureListener {
     boolean onGesture(Gesture gesture);
   }

   private static final int SWIPE_DISTANCE_THRESHOLD_PX = 100;
   private static final int SWIPE_VELOCITY_THRESHOLD_PX = 100;
   private static final double TAN_60_DEGREES = Math.tan(Math.toRadians(60));

   private GestureDetector gestureDetector;
   private OnGestureListener onGestureListener;

   public GlassGestureDetector(Context context, OnGestureListener onGestureListener) {
     gestureDetector = new GestureDetector(context, this);
     this.onGestureListener = onGestureListener;
   }

   public boolean onTouchEvent(MotionEvent motionEvent) {
     return gestureDetector.onTouchEvent(motionEvent);
   }

   @Override
   public boolean onDown(MotionEvent e) {
     return false;
   }

   @Override
   public void onShowPress(MotionEvent e) {
   }

   @Override
   public boolean onSingleTapUp(MotionEvent e) {
     return onGestureListener.onGesture(Gesture.TAP);
   }

   @Override
   public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
     return false;
   }

   @Override
   public void onLongPress(MotionEvent e) {
   }

   /**
    * Swipe detection depends on the:
    * - movement tan value,
    * - movement distance,
    * - movement velocity.
    *
    * To prevent unintentional SWIPE_DOWN and SWIPE_UP gestures, they are detected if movement
    * angle is only between 60 and 120 degrees.
    * Any other detected swipes, will be considered as SWIPE_FORWARD and SWIPE_BACKWARD, depends
    * on deltaX value sign.
    *
    *           ______________________________________________________________
    *          |                     \        UP         /                    |
    *          |                       \               /                      |
    *          |                         60         120                       |
    *          |                           \       /                          |
    *          |                             \   /                            |
    *          |  BACKWARD  <-------  0  ------------  180  ------>  FORWARD  |
    *          |                             /   \                            |
    *          |                           /       \                          |
    *          |                         60         120                       |
    *          |                       /               \                      |
    *          |                     /       DOWN        \                    |
    *           --------------------------------------------------------------
    */
   @Override
   public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
     final float deltaX = e2.getX() - e1.getX();
     final float deltaY = e2.getY() - e1.getY();
     final double tan = deltaX != 0 ? Math.abs(deltaY/deltaX) : Double.MAX_VALUE;

     if (tan > TAN_60_DEGREES) {
       if (Math.abs(deltaY) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityY) < SWIPE_VELOCITY_THRESHOLD_PX) {
         return false;
       } else if (deltaY < 0) {
         return onGestureListener.onGesture(Gesture.SWIPE_UP);
       } else {
         return onGestureListener.onGesture(Gesture.SWIPE_DOWN);
       }
     } else {
       if (Math.abs(deltaX) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityX) < SWIPE_VELOCITY_THRESHOLD_PX) {
         return false;
       } else if (deltaX < 0) {
         return onGestureListener.onGesture(Gesture.SWIPE_FORWARD);
       } else {
         return onGestureListener.onGesture(Gesture.SWIPE_BACKWARD);
       }
     }
   }
  }

নমুনা ব্যবহার

অ্যাক্টিভিটি-লেভেল জেসচার ডিটেকশন ব্যবহার করার জন্য, আপনাকে নিম্নলিখিত কাজগুলি সম্পন্ন করতে হবে:

  1. অ্যাপ্লিকেশন ঘোষণার ভেতরে আপনার ম্যানিফেস্ট ফাইলে নিম্নলিখিত ঘোষণাটি যোগ করুন। এটি আপনার অ্যাপটিকে কার্যকলাপে MotionEvent গ্রহণ করতে সক্ষম করে:
    <application>
    <!-- Copy below declaration into your manifest file -->
    <meta-data
      android:name="com.google.android.glass.TouchEnabledApplication"
      android:value="true" />
    </application>
  2. জেসচার ডিটেক্টরের onTouchEvent(motionEvent) dispatchTouchEvent(motionEvent) ) পদ্ধতিটি ওভাররাইড করুন।
  3. আপনার কার্যকলাপে GlassGestureDetector.OnGestureListener প্রয়োগ করুন।

নিচে একটি অ্যাক্টিভিটি-লেভেল জেসচার ডিটেক্টরের উদাহরণ দেওয়া হল:

কোটলিন

class MainAcvitiy : AppCompatActivity(), GlassGestureDetector.OnGestureListener {

    private lateinit var glassGestureDetector: GlassGestureDetector

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        glassGestureDetector = GlassGestureDetector(this, this)
    }

    override fun onGesture(gesture: GlassGestureDetector.Gesture): Boolean {
        when (gesture) {
            TAP ->
                // Response for TAP gesture
                return true
            SWIPE_FORWARD ->
                // Response for SWIPE_FORWARD gesture
                return true
            SWIPE_BACKWARD ->
                // Response for SWIPE_BACKWARD gesture
                return true
            else -> return false
        }
    }

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        return if (glassGestureDetector.onTouchEvent(ev)) {
            true
        } else super.dispatchTouchEvent(ev)
    }
}

জাভা

  public class MainActivity extends AppCompatActivity implements OnGestureListener {

   private GlassGestureDetector glassGestureDetector;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);

     glassGestureDetector = new GlassGestureDetector(this, this);
   }

   @Override
   public boolean onGesture(Gesture gesture) {
     switch (gesture) {
       case TAP:
         // Response for TAP gesture
         return true;
       case SWIPE_FORWARD:
         // Response for SWIPE_FORWARD gesture
         return true;
       case SWIPE_BACKWARD:
         // Response for SWIPE_BACKWARD gesture
         return true;
       default:
         return false;
     }
   }

   @Override
   public boolean dispatchTouchEvent(MotionEvent ev) {
     if (glassGestureDetector.onTouchEvent(ev)) {
       return true;
     }
     return super.dispatchTouchEvent(ev);
   }
  }

অডিও ইনপুট

গ্লাস এন্টারপ্রাইজ এডিশন ২ হল একটি স্ট্যান্ডার্ড AOSP-ভিত্তিক ডিভাইস যা মৌলিক অডিও উৎস সমর্থন করে।

নিম্নলিখিত অডিও উৎসগুলিতে উন্নত সংকেত প্রক্রিয়াকরণ বাস্তবায়িত হয়েছে:

কণ্ঠস্বর স্বীকৃতি

গ্লাস এন্টারপ্রাইজ সংস্করণ ২ স্পিচ রিকগনিশনের জন্য একটি নেটিভ বাস্তবায়ন সমর্থন করে। এটি শুধুমাত্র ইংরেজির জন্য সমর্থিত।

কাচের ভয়েস রিকগনিশন ছবি।

স্পিচ রিকগনিশন UI ব্যবহারকারীর কথা বলার জন্য অপেক্ষা করে এবং তারপর লেখাটি শেষ হওয়ার পরে তা ফেরত দেয়। কার্যকলাপ শুরু করতে, এই পদক্ষেপগুলি অনুসরণ করুন:

  1. ACTION_RECOGNIZE_SPEECH ইন্টেন্ট ব্যবহার করে startActivityForResult() কল করুন। অ্যাক্টিভিটি শুরু করার সময় নিম্নলিখিত ইন্টেন্ট অতিরিক্তগুলি সমর্থিত হবে:
  2. নিম্নলিখিত কোড নমুনায় দেখানো EXTRA_RESULTS intent extra থেকে ট্রান্সক্রাইব করা টেক্সট পেতে onActivityResult() কলব্যাক ওভাররাইড করুন। ব্যবহারকারী যখন কথা বলা শেষ করেন তখন এই কলব্যাকটি ডাকা হয়।

কোটলিন

private const val SPEECH_REQUEST = 109

private fun displaySpeechRecognizer() {
    val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
    startActivityForResult(intent, SPEECH_REQUEST)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) {
        val results: List<String>? =
            data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
        val spokenText = results?.get(0)
        // Do something with spokenText.
    }
    super.onActivityResult(requestCode, resultCode, data)
}

জাভা

private static final int SPEECH_REQUEST = 109;

private void displaySpeechRecognizer() {
    Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
    startActivityForResult(intent, SPEECH_REQUEST);
}

@Override
protected void onActivityResult(int requestCode, int resultCode,
        Intent data) {
    if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) {
        List<String> results = data.getStringArrayListExtra(
                RecognizerIntent.EXTRA_RESULTS);
        String spokenText = results.get(0);
        // Do something with spokenText.
    }
    super.onActivityResult(requestCode, resultCode, data);
}

বাস্তবায়নের বিশদ বিবরণের জন্য, নমুনা ভয়েস স্বীকৃতি অ্যাপটি পড়ুন।

কীওয়ার্ডের জন্য পক্ষপাত

গ্লাসে স্পিচ রিকগনিশন কীওয়ার্ডের তালিকার জন্য পক্ষপাতদুষ্ট হতে পারে। পক্ষপাতদুষ্টতা কীওয়ার্ড শনাক্তকরণের নির্ভুলতা বৃদ্ধি করে। কীওয়ার্ডের জন্য পক্ষপাতদুষ্টতা সক্ষম করতে, নিম্নলিখিতগুলি ব্যবহার করুন:

কোটলিন

val keywords = arrayOf("Example", "Biasing", "Keywords")

val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
intent.putExtra("recognition-phrases", keywords)

startActivityForResult(intent, SPEECH_REQUEST)

জাভা

final String[] keywords = {"Example", "Biasing", "Keywords"};

Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra("recognition-phrases", keywords);

startActivityForResult(intent, SPEECH_REQUEST);

ভয়েস কমান্ড

ভয়েস কমান্ড ব্যবহারকারীদের কার্যকলাপ থেকে ক্রিয়া সম্পাদন করতে দেয়। আপনি স্ট্যান্ডার্ড অ্যান্ড্রয়েড মেনু API ব্যবহার করে ভয়েস কমান্ড তৈরি করতে পারেন, কিন্তু ব্যবহারকারীরা স্পর্শের পরিবর্তে ভয়েস কমান্ড ব্যবহার করে মেনু আইটেমগুলি ব্যবহার করতে পারেন।

একটি নির্দিষ্ট কার্যকলাপের জন্য ভয়েস কমান্ড সক্ষম করতে, এই পদক্ষেপগুলি অনুসরণ করুন:

  1. ভয়েস কমান্ড সক্রিয় করতে কাঙ্ক্ষিত কার্যকলাপে getWindow().requestFeature(FEATURE_VOICE_COMMANDS) কল করুন। এই বৈশিষ্ট্যটি সক্ষম করলে, যখনই এই কার্যকলাপটি ফোকাস পাবে তখনই স্ক্রিনের নীচে বাম কোণে মাইক্রোফোন আইকনটি প্রদর্শিত হবে।
  2. আপনার অ্যাপে RECORD_AUDIO অনুমতির জন্য অনুরোধ করুন।
  3. onCreatePanelMenu() ওভাররাইড করুন এবং একটি মেনু রিসোর্স ফুলিয়ে দিন।
  4. সনাক্ত করা ভয়েস কমান্ডগুলি পরিচালনা করতে onContextItemSelected() ওভাররাইড করুন।

কোটলিন

class VoiceCommandsActivity : AppCompatActivity() {

    companion object {
        const val FEATURE_VOICE_COMMANDS = 14
        const val REQUEST_PERMISSION_CODE = 200
        val PERMISSIONS = arrayOf(Manifest.permission.RECORD_AUDIO)
        val TAG = VoiceCommandsActivity::class.java.simpleName
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        window.requestFeature(FEATURE_VOICE_COMMANDS)
        setContentView(R.layout.activity_voice_commands)

        // Requesting permissions to enable voice commands menu
        ActivityCompat.requestPermissions(
            this,
            PERMISSIONS,
            REQUEST_PERMISSION_CODE
        )
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        if (requestCode == REQUEST_PERMISSION_CODE) {
            for (result in grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    Log.d(TAG, "Permission denied. Voice commands menu is disabled.")
                }
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        }
    }

    override fun onCreatePanelMenu(featureId: Int, menu: Menu): Boolean {
        menuInflater.inflate(R.menu.voice_commands_menu, menu)
        return true
    }

    override fun onContextItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            // Handle selected menu item
            R.id.edit -> {
                // Handle edit action
                true
            }
            else -> super.onContextItemSelected(item)
        }
    }
}

জাভা

public class VoiceCommandsActivity extends AppCompatActivity {

  private static final String TAG = VoiceCommandsActivity.class.getSimpleName();
  private static final int FEATURE_VOICE_COMMANDS = 14;
  private static final int REQUEST_PERMISSION_CODE = 200;
  private static final String[] PERMISSIONS = new String[]{Manifest.permission.RECORD_AUDIO};

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(FEATURE_VOICE_COMMANDS);
    setContentView(R.layout.activity_voice_commands);

    // Requesting permissions to enable voice commands menu
    ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION_CODE);
  }

  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == REQUEST_PERMISSION_CODE) {
      for (int result : grantResults) {
        if (result != PackageManager.PERMISSION_GRANTED) {
          Log.d(TAG, "Permission denied. Voice commands menu is disabled.");
        }
      }
    } else {
      super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
  }

  @Override
  public boolean onCreatePanelMenu(int featureId, @NonNull Menu menu) {
    getMenuInflater().inflate(R.menu.voice_commands_menu, menu);
    return true;
  }

  @Override
  public boolean onContextItemSelected(@NonNull MenuItem item) {
    switch (item.getItemId()) {
      // Handle selected menu item
      case R.id.edit:
        // Handle edit action
        return true;
      default:
        return super.onContextItemSelected(item);
    }
  }
}

পূর্ববর্তী কার্যকলাপে ব্যবহৃত মেনু রিসোর্সের একটি উদাহরণ নিচে দেওয়া হল:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/delete"
        android:icon="@drawable/ic_delete"
        android:title="@string/delete"/>
    <item
        android:id="@+id/edit"
        android:icon="@drawable/ic_edit"
        android:title="@string/edit"/>
    <item
        android:id="@+id/find"
        android:icon="@drawable/ic_search"
        android:title="@string/find"/>
</menu>

সম্পূর্ণ উদাহরণের জন্য নমুনা নোট নেওয়ার অ্যাপটি পড়ুন।

ভয়েস কমান্ড তালিকা পুনরায় লোড হচ্ছে

আপনি ভয়েস কমান্ড তালিকাটি গতিশীলভাবে পুনরায় লোড করতে পারেন। এটি করার জন্য, onCreatePanelMenu() পদ্ধতিতে menu রিসোর্সটি প্রতিস্থাপন করুন, অথবা onPreparePanel() পদ্ধতিতে মেনু অবজেক্টটি পরিবর্তন করুন। পরিবর্তনগুলি প্রয়োগ করতে, invalidateOptionsMenu() পদ্ধতিটি কল করুন।

কোটলিন

private val options = mutableListOf<String>()

fun onPreparePanel(featureId: Int, view: View?, menu: Menu): Boolean {
  if (featureId != FEATURE_VOICE_COMMANDS) {
    return super.onCreatePanelMenu(featureId, menu)
  }
  for (optionTitle in options) {
    menu.add(optionTitle)
  }
  return true
}

/**
 * Method showing example implementation of voice command list modification
 *
 * If you call [Activity.invalidateOptionsMenu] method, voice command  list will be
 * reloaded (onCreatePanelMenu and onPreparePanel methods will be called).
 */
private fun modifyVoiceCommandList() {
  options.add("Delete")
  options.add("Play")
  options.add("Pause")
  invalidateOptionsMenu()
}

জাভা

private final List<String> options = new ArrayList<>();

@Override
public boolean onPreparePanel(int featureId, View view, Menu menu) {
  if (featureId != FEATURE_VOICE_COMMANDS) {
    return super.onCreatePanelMenu(featureId, menu);
  }
  for (String optionTitle : options) {
    menu.add(optionTitle);
  }
  return true;
}

/**
 * Method showing example implementation of voice command list modification
 *
 * If you call {@link Activity#invalidateOptionsMenu()} method, voice command  list will be
 * reloaded (onCreatePanelMenu and onPreparePanel methods will be called).
 */
private void modifyVoiceCommandList() {
  options.add("Delete");
  options.add("Play");
  options.add("Pause");
  invalidateOptionsMenu();
}

অ্যাপকম্প্যাটঅ্যাক্টিভিটি সমাধান

AppCompatActivity প্রসারিত করে এমন একটি কার্যকলাপে ভয়েস কমান্ড তালিকা পুনরায় লোড করতে, reload-voice-commands ইন্টেন্ট অ্যাকশন সহ sendBroadcast() পদ্ধতিটি ব্যবহার করুন:

কোটলিন

sendBroadcast(Intent("reload-voice-commands"))

জাভা

sendBroadcast(new Intent("reload-voice-commands"));

রানটাইমে ভয়েস কমান্ড সক্ষম এবং অক্ষম করুন

রানটাইমে আপনি ভয়েস কমান্ড সক্রিয় এবং নিষ্ক্রিয় করতে পারেন। এটি করার জন্য, onCreatePanelMenu() পদ্ধতি থেকে নিম্নরূপ একটি উপযুক্ত মান প্রদান করুন:

  • সক্রিয় করতে মানটিকে true সেট করুন।
  • নিষ্ক্রিয় করতে মানটি false সেট করুন।

ডিবাগ মোড

ভয়েস কমান্ডের জন্য ডিবাগ মোড সক্রিয় করতে, পছন্দসই কার্যকলাপে getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS) কল করুন। ডিবাগ মোড নিম্নলিখিত বৈশিষ্ট্যগুলি সক্রিয় করে:

  • লগক্যাটে ডিবাগিংয়ের জন্য স্বীকৃত বাক্যাংশ সহ লগ থাকে।
  • যখন একটি অচেনা কমান্ড সনাক্ত করা হয় তখন UI ওভারলে প্রদর্শিত হয়, যেমনটি দেখানো হয়েছে:
  • কাচের ভয়েস রিকগনিশন অচেনা কমান্ডের ছবি।

কোটলিন

class VoiceCommandsActivity : AppCompatActivity() {

    companion object {
        const val FEATURE_VOICE_COMMANDS = 14
        const val FEATURE_DEBUG_VOICE_COMMANDS = 15
        const val REQUEST_PERMISSION_CODE = 200
        val PERMISSIONS = arrayOf(Manifest.permission.RECORD_AUDIO)
        val TAG = VoiceCommandsActivity::class.java.simpleName
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        window.requestFeature(FEATURE_VOICE_COMMANDS)
        window.requestFeature(FEATURE_DEBUG_VOICE_COMMANDS)
        setContentView(R.layout.activity_voice_commands)

        // Requesting permissions to enable voice commands menu
        ActivityCompat.requestPermissions(
            this,
            PERMISSIONS,
            REQUEST_PERMISSION_CODE
        )
    }
    .
    .
    .
}

জাভা

public class VoiceCommandsActivity extends AppCompatActivity {

  private static final String TAG = VoiceCommandsActivity.class.getSimpleName();
  private static final int FEATURE_VOICE_COMMANDS = 14;
  private static final int FEATURE_DEBUG_VOICE_COMMANDS = 15;
  private static final int REQUEST_PERMISSION_CODE = 200;
  private static final String[] PERMISSIONS = new String[]{Manifest.permission.RECORD_AUDIO};

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(FEATURE_VOICE_COMMANDS);
    getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS);
    setContentView(R.layout.activity_voice_commands);

    // Requesting permissions to enable voice commands menu
    ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION_CODE);
  }
  .
  .
  .
}

বাস্তবায়নের বিশদ বিবরণের জন্য, নমুনা ভয়েস কমান্ড রিলোডিং অ্যাপটি পড়ুন।

টেক্সট-টু-স্পিচ (TTS)

টেক্সট-টু-স্পিচ কার্যকারিতা ডিজিটাল টেক্সটকে সিন্থেসাইজেস স্পিচ আউটপুটে রূপান্তর করে। আরও তথ্যের জন্য, অ্যান্ড্রয়েড ডেভেলপারস ডকুমেন্টেশন টেক্সটটুস্পিচ দেখুন।

Glass EE2 তে Google Text-to-Speech ইঞ্জিন ইনস্টল করা আছে। এটি ডিফল্ট TTS ইঞ্জিন হিসেবে সেট করা আছে এবং অফলাইনে কাজ করে।

নিম্নলিখিত লোকেলগুলি গুগল টেক্সট-টু-স্পিচ ইঞ্জিনের সাথে একত্রিত:

বাংলা
ম্যান্ডারিন চাইনিজ
চেক
ড্যানিশ
জার্মান
গ্রীক
ইংরেজী
স্পেনীয়
এস্তোনীয়
ফিনিশ
ফরাসি
গুজরাটি
হিন্দি
হাঙ্গেরীয়
ইন্দোনেশীয়
ইতালীয়
জাপানি
জাভানি
অস্ট্রোনেশীয়
অস্ট্রোএশীয়
কন্নড়
কোরিয়ান
মালায়ালাম
নরওয়েজীয়
ডাচ
পোলীশ
পর্তুগীজ
রুশ
স্লোভাক
সুদানী
সুইডিশ
তামিল
তেলেগু
থাই
তুর্কী
ইউক্রেনীয়
ভিয়েতনামী

ক্যামেরা

গ্লাস এন্টারপ্রাইজ এডিশন ২-তে ৮ মেগাপিক্সেলের ফিক্সড-ফোকাস ক্যামেরা রয়েছে যার অ্যাপারচার f/২.৪, অ্যাসপেক্ট রেশিও ৪:৩ সেন্সর এবং ৮৩° ডায়াগোনাল ফিল্ড অফ ভিউ (ল্যান্ডস্কেপ ওরিয়েন্টেশনে ৭১° x ৫৭°) রয়েছে। আমরা আপনাকে স্ট্যান্ডার্ড ক্যামেরাএক্স বা ক্যামেরা২ এপিআই ব্যবহার করার পরামর্শ দিচ্ছি।

বাস্তবায়নের বিশদ বিবরণের জন্য, নমুনা ক্যামেরা অ্যাপটি পড়ুন।

ক্যামেরা বোতাম

ক্যামেরা বোতামটি হল গ্লাস এন্টারপ্রাইজ এডিশন ২ ডিভাইসের কব্জায় থাকা ফিজিক্যাল বোতাম। এটি একটি স্ট্যান্ডার্ড কীবোর্ড অ্যাকশনের মতোই পরিচালনা করা যেতে পারে এবং KeyEvent#KEYCODE_CAMERA কীকোড দ্বারা সনাক্ত করা যেতে পারে।

OPM1.200313.001 OS আপডেট অনুসারে, লঞ্চার অ্যাপ্লিকেশন থেকে নিম্নলিখিত ক্রিয়াগুলির উদ্দেশ্য পাঠানো হয়:

সেন্সর

Glass EE2-তে অ্যাপ্লিকেশন তৈরির সময় ডেভেলপারদের কাছে বিভিন্ন ধরণের সেন্সর উপলব্ধ থাকে।

নিম্নলিখিত স্ট্যান্ডার্ড অ্যান্ড্রয়েড সেন্সরগুলি গ্লাসে সমর্থিত:

নিম্নলিখিত অ্যান্ড্রয়েড সেন্সরগুলি গ্লাসে সমর্থিত নয়:

নিম্নলিখিত চিত্রে গ্লাস সেন্সর স্থানাঙ্ক সিস্টেমটি দেখানো হয়েছে। এটি গ্লাস ডিসপ্লের সাথে সম্পর্কিত। আরও তথ্যের জন্য, সেন্সর স্থানাঙ্ক সিস্টেম দেখুন।

গ্লাস সেন্সর স্থানাঙ্ক সিস্টেমটি এখানে দেখানো হয়েছে, গ্লাস ডিসপ্লের সাপেক্ষে।

অ্যাক্সিলোমিটার, জাইরোস্কোপ এবং ম্যাগনেটোমিটার গ্লাস ডিভাইসের অপটিক্স পডে অবস্থিত, যা ব্যবহারকারীরা তাদের দৃষ্টির সাথে ডিভাইসটিকে সারিবদ্ধ করার জন্য ঘোরান। আপনি সরাসরি অপটিক্স পডের কোণ পরিমাপ করতে পারবেন না, তাই কম্পাস হেডিংয়ের মতো অ্যাপ্লিকেশনের জন্য এই সেন্সরগুলির কোণ ব্যবহার করার সময় এটি সম্পর্কে সচেতন থাকুন।

ব্যাটারি লাইফ সংরক্ষণের জন্য, শুধুমাত্র যখন আপনার প্রয়োজন তখনই সেন্সরগুলি শুনুন। সেন্সরগুলি কখন শুরু করবেন এবং কখন বন্ধ করবেন তা নির্ধারণ করার সময় অ্যাপটির প্রয়োজনীয়তা এবং জীবনচক্র বিবেচনা করুন।

সেন্সর ইভেন্ট কলব্যাকগুলি UI থ্রেডে চলে, তাই ইভেন্টগুলি প্রক্রিয়া করুন এবং যত তাড়াতাড়ি সম্ভব রিটার্ন করুন। যদি প্রক্রিয়াকরণে খুব বেশি সময় লাগে, তাহলে সেন্সর ইভেন্টগুলিকে একটি সারিতে ঠেলে দিন এবং সেগুলি পরিচালনা করার জন্য একটি ব্যাকগ্রাউন্ড থ্রেড ব্যবহার করুন।

মাথার গতি ট্র্যাক করার জন্য ৫০ হার্জ প্রায়শই যথেষ্ট নমুনা হার।

সেন্সর কীভাবে ব্যবহার করবেন সে সম্পর্কে আরও তথ্যের জন্য, অ্যান্ড্রয়েড ডেভেলপার গাইড দেখুন।

অবস্থান পরিষেবা

গ্লাস এন্টারপ্রাইজ এডিশন ২ ডিভাইসটিতে জিপিএস মডিউল নেই এবং এটি ব্যবহারকারীর অবস্থান প্রদান করে না। তবে, এতে অবস্থান পরিষেবা বাস্তবায়িত হয়েছে, যা কাছাকাছি ওয়াই-ফাই নেটওয়ার্ক এবং ব্লুটুথ ডিভাইসের তালিকা প্রদর্শনের জন্য প্রয়োজনীয়।

যদি আপনার অ্যাপ্লিকেশনটিতে ডিভাইস মালিকের বিশেষাধিকার থাকে, তাহলে আপনি এটি ব্যবহার করে সংশ্লিষ্ট সুরক্ষিত সেটিংসের মান প্রোগ্রাম্যাটিকভাবে পরিবর্তন করতে পারেন:

কোটলিন

val devicePolicyManager = context
    .getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
if (devicePolicyManager.isDeviceOwnerApp(context.getPackageName())) {
    val componentName = ComponentName(context, MyDeviceAdmin::class.java)
    devicePolicyManager.setSecureSetting(
        componentName,
        Settings.Secure.LOCATION_MODE,
        Settings.Secure.LOCATION_MODE_SENSORS_ONLY.toString()
    )
}

জাভা

final DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context
    .getSystemService(Context.DEVICE_POLICY_SERVICE);
if (devicePolicyManager.isDeviceOwnerApp(context.getPackageName())) {
  final ComponentName componentName = new ComponentName(context, MyDeviceAdmin.class);
  devicePolicyManager.setSecureSetting(componentName, Settings.Secure.LOCATION_MODE,
      String.valueOf(Settings.Secure.LOCATION_MODE_SENSORS_ONLY));
}

আপনি যদি কোনও তৃতীয় পক্ষের MDM সমাধান ব্যবহার করেন, তাহলে MDM সমাধানটি অবশ্যই আপনার জন্য এই সেটিংস পরিবর্তন করতে সক্ষম হবে।