إعداد البرنامج التجريبي

يستخدم تقييم الأجهزة البرامج التالية:

  • Audacity (مثبَّت على الكمبيوتر)
  • MATLAB (مثبَّت على الكمبيوتر الشخصي)
  • تطبيق اختبار تقنية "اللمس" (مثبَّت على جهاز الاختبار)

لمعرفة المزيد من المعلومات عن متطلبات النظام، يُرجى الاطّلاع على Audacity لنظام التشغيل Windows وAudacity لنظام التشغيل Mac وMATLAB.

إعداد Audacity

يجب إعداد Audacity لتلقّي الإدخال من بطاقة الصوت Sound Blaster بمعدّل قياس معيّن للبيانات. بعد توصيل Sound Blaster بمنفذ USB في جهاز الكمبيوتر، افتح Audacity واتّبِع التعليمات التالية.

  1. اختَر الصوت (USB Sound Blaster HD) كمصدر ميكروفون الإدخال من خلال توصيل مخرج CCLD بمنفذ إدخال "الصوت في" في Sound Blaster.

    إدخال الميكروفون

    الشكل 1: اختيار إدخال الميكروفون

  2. اضبط معدّل أخذ العينات على 48 كيلوهرتز من خلال اختيار 48000 في قائمة Project Rate (معدل المشروع).

    معدّل البيانات في الملف الصوتي

    الشكل 2: ضبط معدّل البيانات في الملف الصوتي

تنزيل MATLAB

  1. نزِّل ملف MATLAB.

  2. استخرِج الملف وابحث عن Effect1NEffect2_V1p0_2020PM.m (للتأثير 1 و التأثير 2) وEffect3_V1p0_2020PM.m (للتأثير 3).

إعداد التطبيق التجريبي على الهاتف

يوضّح هذا القسم كيفية إعداد التطبيق التجريبي على الهاتف.

الاستعداد للتطبيق التجريبي

  1. انسخ رمز المصدر من كتل الرموز البرمجية Java وKotlin أدناه. يمكنك اختيار الطريقة الأنسب لك.
  2. اكتب الرمز البرمجي الخاص بك باتّباع مَعلمات واجهة المستخدم الموضّحة في الشكل 3. عدِّل تفاصيل رمز مصدر التنسيق ليتوافق مع هاتفك إذا لزم الأمر.
  3. تأكَّد من أنّ واجهة المستخدم تتضمّن ثلاثة أزرار يمكن النقر عليها ومقياس رسومي لتحديد المنطقة التي سيتم تحديد موضع مقياس التسارع فيها.

    • تمثّل منطقة تحديد موقع أداة التسارع المساحة الحقيقية لشاشة الجهاز التي يتم لمسها عادةً باليد.
    • أثناء هذا القياس، يمكنك تحريك مقياس التسارع ضمن المنطقة الخضراء الزاهية للعثور على منطقة الشاشة التي تلتقط الإشارة الأقوى.
  4. ثبِّت الرمز على جهاز Android.

  5. ننصح بشدة بضبط وضع التنقّل في النظام على وضع الإيماءات إذا تم ضبط الوضع التلقائي على الأزرار.

    • من خلال ضبط وضع الإيماءات، يمكنك وضع مقياس التسارع في أسفل الهاتف قدر الإمكان بدون أن تقاطعك واجهات المستخدم الرسومية لتنقّل في نظام الهاتف.

رمز مصدر Java

package com.example.hapticeffectassessment;

import static android.os.VibrationEffect.EFFECT_CLICK;

import android.graphics.Color;
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

 private static final long oneShotTiming = 20;
 private static final int oneShotAmplitude = 255;

 private static final long[] waveformTimings = {500, 500};
 private static final int[] waveformAmplitudes = {128, 255};

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

   Vibrator vibrator = getSystemService(Vibrator.class);

   // Click R.id.button1 button to generate Effect 1
   findViewById(R.id.button1).setOnClickListener(
       view -> vibrator.vibrate(VibrationEffect.createPredefined(EFFECT_CLICK)));

   // Click R.id.button2 button to generate Effect 2
   findViewById(R.id.button2).setOnClickListener(
       view -> vibrator.vibrate(VibrationEffect.createOneShot(oneShotTiming, oneShotAmplitude)));

   // Click R.id.button3 button to generate Effect 3
   findViewById(R.id.button3).setOnClickListener(view -> {
     vibrator.vibrate(VibrationEffect.createWaveform(waveformTimings, waveformAmplitudes, -1));

     // See quick results of Effect 3
     Button button = (Button) view;
     if (vibrator.hasAmplitudeControl()) {
       button.setText("Effect 3: PASS");
       button.setBackgroundColor(Color.GREEN);
       button.setTextColor(Color.BLACK);
     } else {
       button.setText("Effect 3: FAIL");
       button.setBackgroundColor(Color.RED);
       button.setTextColor(Color.WHITE);
     }
   });
 }
}

رمز مصدر Kotlin

package com.example.hapticeffectassessment

import android.graphics.Color
import android.os.Bundle
import android.os.VibrationEffect
import android.os.VibrationEffect.EFFECT_CLICK
import android.os.Vibrator
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivityKt : AppCompatActivity() {

 private val oneShotTiming: Long = 20
 private val oneShotAmplitude = 255

 private val waveformTimings = longArrayOf(500, 500)
 private val waveformAmplitudes = intArrayOf(128, 255)

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

   val vibrator = getSystemService(Vibrator::class.java)

   // Click button1 to generate Effect 1
   button1.setOnClickListener {
     vibrator.vibrate(VibrationEffect.createPredefined(EFFECT_CLICK))
   }

   // Click button2 to generate Effect 2
   button2.setOnClickListener {
     vibrator.vibrate(VibrationEffect.createOneShot(oneShotTiming, oneShotAmplitude))
   }

   // Click button3 to generate Effect 3
   button3.setOnClickListener {
     vibrator.vibrate(
       VibrationEffect.createWaveform(waveformTimings, waveformAmplitudes, -1))

     // See quick results of Effect 3
     if (vibrator.hasAmplitudeControl()) {
       button3.text = "Effect 3: PASS"
       button3.setBackgroundColor(Color.GREEN)
       button3.setTextColor(Color.BLACK)
     } else {
       button3.text = "Effect 3: FAIL"
       button3.setBackgroundColor(Color.RED)
       button3.setTextColor(Color.WHITE)
     }
   }
 }
}

رمز مصدر التنسيق (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity">

   <Button
       android:id="@+id/button1"
       android:layout_width="350dp"
       android:layout_height="60dp"
       android:layout_marginStart="32dp"
       android:layout_marginTop="5dp"
       android:layout_marginEnd="32dp"
       android:text="Effect 1"
       android:textSize="18sp"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent" />

   <Button
       android:id="@+id/button2"
       android:layout_width="350dp"
       android:layout_height="60dp"
       android:layout_marginStart="32dp"
       android:layout_marginTop="5dp"
       android:layout_marginEnd="32dp"
       android:text="Effect 2"
       android:textSize="18sp"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@+id/button1" />

   <Button
       android:id="@+id/button3"
       android:layout_width="350dp"
       android:layout_height="60dp"
       android:layout_marginStart="32dp"
       android:layout_marginTop="5dp"
       android:layout_marginEnd="32dp"
       android:text="Effect 3"
       android:textSize="18sp"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@+id/button2" />

   <View
       android:id="@+id/divider"
       android:layout_width="363dp"
       android:layout_height="1dp"
       android:layout_marginStart="32dp"
       android:layout_marginTop="10dp"
       android:layout_marginEnd="32dp"
       android:background="?android:attr/listDivider"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintHorizontal_bias="0.5"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@+id/button3" />

   <androidx.constraintlayout.widget.ConstraintLayout
       android:layout_width="363dp"
       android:layout_height="0dp"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintHorizontal_bias="0.5"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@+id/divider">

       <ImageView
           android:id="@+id/imageView"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:adjustViewBounds="true"
           android:scaleType="fitXY"
           app:layout_constraintBottom_toBottomOf="parent"
           app:layout_constraintEnd_toEndOf="parent"
           app:layout_constraintHorizontal_bias="0.5"
           app:layout_constraintStart_toStartOf="parent"
           app:layout_constraintTop_toTopOf="parent"
           app:srcCompat="@drawable/bluebar" />
   </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

مقياس التسارع

الشكل 3: إرفاق مقياس التسارع على طول المنطقة المقترَحة في واجهة المستخدِم GUI