Pemrograman dan transmisi data ke Arduino melalui udara menggunakan ESP8266. Bagian Tiga. Halo, ANDROID

Saya menawarkan kepada Anda, para pembaca GeekTimes, artikel lain dari siklus penggunaan chip ESP8266 sebagai jembatan nirkabel untuk mikrokontroler AVR, menggunakan platform perangkat keras Arduino Uno (Nano) sebagai contoh. Kali ini, untuk penerbangan ke bulan untuk mengontrol platform, kami menggunakan perangkat berbasis ANDROID, bukan komputer. Misalnya, sebuah smartphone.



Detail di bawah potongan:

Untuk pekerjaan kami, kami akan menggunakan alat yang dijelaskan dalam artikel sebelumnya - programmer nirkabel BABUINO dan modul MPDE (modul untuk program dan pertukaran data) yang dikirimkan dalam ESP8266.

Ternyata dari umpan balik dari pengguna, programmer sendiri, secara umum, datang ke pengadilan dan beberapa orang bahkan berhasil menggunakannya. Yah, pada dasarnya, masalahnya sangat nyaman; Saya meluncurkan aplikasi di bawah Windows, memilih file hex dari folder yang diinginkan dan itu saja - dalam beberapa detik program di perangkat yang tepat tanpa kabel. Hal lain adalah sia-sia, dengan semangat yang berlebihan, saya menyerang pengguna perangkat lunak ARDUINO yang menulis di Wiring C dan menggunakan IDE ARDUINO dengan sketsa dan perpustakaannya. Tentu saja, semua orang melakukan apa yang nyaman baginya - apakah di Arduin Wiring C atau C dari AVR studio. Tetapi pada akhirnya, beberapa pengguna karena suatu alasan segera memutuskan bahwa pemrogram sama sekali tidak kompatibel dengan perangkat lunak ARDUINO.

Sebenarnya, tidak ada masalah kompatibilitas, tentu saja. Benar-benar juga mengkompilasi sketsa Anda di tempat yang nyaman bagi Anda ke keadaan file hex dan dengan mudah mengirimkannya melalui programmer nirkabel ke Arduino UNO atau NANO Anda.

Pertukaran data dalam perangkat lunak ARDUINO juga tidak menyebabkan masalah. Tulis garis ajaib:

Serial.begin (9600);

dan kemudian sesuatu seperti:

acceptByte = Serial.read (); // baca byte dari buffer

atau:

Serial.write (acceptByte); // catatan byte

Dan Anda dapat bertukar byte stream melalui WI-FI dengan cukup tenang. Untuk mikrokontroler AVR mengirim ke ESP8266 dan menerima byte dari sana melalui port serial UART, yang, seperti yang bisa kita lihat, setiap kemanusiaan dapat mengkonfigurasi pekerjaan yang di Arduino.

Sekarang kembali ke topik artikel ini. Untuk mengendalikan robot melalui smartphone, tentu saja, Anda harus menulis aplikasi yang sesuai untuk smartphone ini.

Sebagai orang yang mempresentasikan proses ini sebulan yang lalu dengan sangat samar, saya sekarang dapat menyatakan dengan penuh tanggung jawab bahwa masalahnya pada dasarnya tidak rumit. Kecuali tentu saja, Anda memiliki setidaknya beberapa pengetahuan dasar di bidang Java.

Untuk saat menulis aplikasi Android, kode sumber ditulis dalam Java, dan kemudian dikompilasi ke dalam bytecode Java standar menggunakan alat Java tradisional. Kemudian hal-hal menarik lainnya terjadi pada kode, tetapi kami tidak memerlukan detail ini di sini.

Sepertinya masih ada kemungkinan untuk menulis aplikasi dalam C untuk pekerja hardcore terkenal yang mendapat skor dalam nanodetik, dan juga di suatu tempat ada semacam paket untuk menerjemahkan kode Anda dari Python, tetapi saya tidak bisa mengatakan apa pun di sini, karena saya telah membuat pilihan yang tepat untuk waktu yang lama .

Jadi, Java dan paket perangkat lunak Android Studio - lingkungan pengembangan terintegrasi (IDE) untuk bekerja dengan platform Android berdasarkan pada perangkat lunak IntelliJ IDEA dari JetBrains, alat pengembangan resmi untuk aplikasi Android.



Jika Anda sudah bekerja dengan perangkat lunak IntelliJ IDEA, Anda akan terkejut dengan antarmuka yang sudah dikenal.

Saya berkenalan dengan dasar-dasar membangun aplikasi dari buku B. Phillips dan C. Stewart - pemrograman “ANDROID” untuk para profesional. ”Seperti yang saya pahami, para profesional mempertimbangkan pembaca yang setidaknya sedikit akrab dengan Java SE. Saya tidak menemukan, dan untuk keperluan kami sepuluh bab pertama buku akan cukup, untungnya, semua contoh kode diberikan di dalamnya ketika bekerja dengan Android Studio tersebut.

Aplikasi debugging dapat dilakukan pada emulator perangkat lunak atau langsung pada smartphone dengan mengalihkannya ke "mode pengembang".

Dalam artikel sebelumnya, kontrol troli melalui aplikasi windows pada Windows dijelaskan. Artinya, semua kode untuk membuat koneksi HTTP dan UDP, serta logika kontrol, sudah ada dalam teori. Oleh karena itu, setelah mengadopsi slogan Oracle “Ditulis di satu tempat, ia bekerja di mana-mana”, kami hanya memindahkan kelas-kelas ini ke program baru untuk aplikasi Android. Tetapi GUI adalah antarmuka pengguna grafis, untuk alasan yang jelas, Anda harus meninggalkannya. Namun di sisi lain, di Android semuanya dilakukan dengan sangat mirip dan cukup cepat, jadi kami tidak akan tinggal di pihak yang kalah.

Tusukkan jari ke layar



Jadi, kami membuat proyek baru "FourWheelRobotControl" di Android Studio.
Ini adalah aplikasi sederhana dan akan terdiri dari aktivitas

Kelas MainActivity.java
import android.content.Context; import android.hardware.Sensor; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.ImageButton; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private ImageButton mButtonUP; private ImageButton mButtonDOWN; private ImageButton mButtonLEFT; private ImageButton mButtonRIGHT; public static byte direction = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new HTTP_client(40000); new Udp_client(); mButtonUP = (ImageButton) findViewById(R.id.imageButtonUP); mButtonUP.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { direction = 3; } } if (event.getAction() == MotionEvent.ACTION_UP) { direction = 100; } return false; } }); mButtonDOWN = (ImageButton) findViewById(R.id.imageButtonDown); mButtonDOWN.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { direction = 4; Toast.makeText(MainActivity.this, " " + direction, Toast.LENGTH_SHORT).show(); } if (event.getAction() == MotionEvent.ACTION_UP) { direction = 100; } return false; } }); mButtonLEFT = (ImageButton) findViewById(R.id.imageButtonLeft); mButtonLEFT.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { direction = 1; Toast.makeText(MainActivity.this, " " + direction, Toast.LENGTH_SHORT).show(); } if (event.getAction() == MotionEvent.ACTION_UP) { direction = 100; } return false; } }); mButtonRIGHT = (ImageButton) findViewById(R.id.imageButtonRight); mButtonRIGHT.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { direction = 2; Toast.makeText(MainActivity.this, " " + direction, Toast.LENGTH_SHORT).show(); } if (event.getAction() == MotionEvent.ACTION_UP) { direction = 100; } return false; } }); } 

dan tata letak:

tata letak
  /spoiler/ activity_main.xml <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.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="mikhail_akhmetov.fourweelsrobotcontrol.MainActivity"> <ImageButton android:id="@+id/imageButtonRight" style="@android:style/Widget.Holo.ImageButton" android:layout_width="52dp" android:layout_height="52dp" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:background="@android:color/holo_orange_dark" app:layout_constraintBottom_toTopOf="@+id/linearLayout" app:layout_constraintHorizontal_bias="0.417" app:layout_constraintLeft_toRightOf="@+id/imageButtonLeft" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.513" app:srcCompat="@android:drawable/ic_media_ff"/> <ImageButton android:id="@+id/imageButtonUP" style="@android:style/Widget.ImageButton" android:layout_width="52dp" android:layout_height="52dp" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" android:background="@android:color/holo_orange_dark" app:layout_constraintBottom_toTopOf="@+id/imageButtonDown" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.486" app:srcCompat="@android:drawable/arrow_up_float"/> <ImageButton android:id="@+id/imageButtonDown" style="@android:style/Widget.ImageButton" android:layout_width="52dp" android:layout_height="52dp" android:layout_marginBottom="57dp" android:layout_marginLeft="8dp" android:background="@android:color/holo_orange_dark" android:fadingEdge="horizontal" app:layout_constraintBottom_toTopOf="@+id/linearLayout" app:layout_constraintHorizontal_bias="0.487" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:srcCompat="@android:drawable/arrow_down_float" android:layout_marginStart="8dp"/> <ImageButton android:id="@+id/imageButtonLeft" style="@android:style/Widget.ImageButton" android:layout_width="52dp" android:layout_height="52dp" android:layout_marginLeft="94dp" android:layout_marginStart="94dp" android:background="@android:color/holo_orange_dark" app:layout_constraintBottom_toTopOf="@+id/linearLayout" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.513" app:srcCompat="@android:drawable/ic_media_rew" /> <LinearLayout android:id="@+id/linearLayout" android:layout_width="368dp" android:layout_height="227dp" android:layout_marginBottom="11dp" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:orientation="vertical" android:weightSum="1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"> <TextView android:id="@+id/textViewX" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.28" /> <TextView android:id="@+id/textViewY" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.28" /> <TextView android:id="@+id/textViewZ" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.23" /> </LinearLayout> </android.support.constraint.ConstraintLayout> 


Tidak perlu menulis dengan pena, secara otomatis dihasilkan setelah kreasi Anda di editor.

Sekarang kami hanya mentransfer dua kelas dari program yang diberikan dalam artikel sebelumnya:

HTTP_client.java
 import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; public class HTTP_client extends Thread{ int port; String s; public static String host_address="192.168.1.138";//    public String Greetings_from_S; HTTP_client(int port) { this.port = port; start(); } public void run() { try (Socket socket = new Socket(host_address,port)){ PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); pw.println("stop data\r");//  ,    pw.println("data\r");// Greetings with SERVER Greetings_from_S = br.readLine(); if (Greetings_from_S.equals("ready")) { new Udp_client(); } } catch (Exception e) { e.printStackTrace(); } } } 


Udp_clent.java
 import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class Udp_client extends Thread { int i =0; byte [] data = {0}; int udp_port=50000; InetAddress addr; DatagramSocket ds; public Udp_client() { try { ds = new DatagramSocket(); addr = InetAddress.getByName(HTTP_client.host_address); } catch (Exception e) { } start(); } public void run() { while (true) { byte temp = MainActivity.direction; String s = "" + MainActivity.direction; data = s.getBytes(); if(temp!=100 ) { DatagramPacket pack = new DatagramPacket(data, data.length, addr, udp_port); try { ds.send(pack); i=0; Thread.sleep(200); } catch (Exception e) { } } else { if(i==0) { s = "" + 0; data = s.getBytes(); DatagramPacket pack = new DatagramPacket(data, data.length, addr, udp_port); try { ds.send(pack); Thread.sleep(200); } catch (Exception e) { } } i=1;//     } } } } 

Inti dari program ini tetap sama. MainActivity pertama kali meluncurkan klien HTTP dan UDP, dan kemudian menangkap penekanan tombol dan depresi, mengirimkan kode push arah untuk membentuk paket UDP. Dan dari sana semuanya sudah - "maju", "kembali", "kiri", "kanan" dan ketika Anda menekan "berhenti" mereka pergi melalui WI-FI dalam kereta.

Selain semua ini, kita perlu sedikit memodifikasi file yang disebut manifes, yang, sekali lagi, sebagian besar dihasilkan dengan sendirinya.

Manifes adalah file XML dengan metadata yang menggambarkan aplikasi Android Anda. File manifes selalu disebut AndroidManifest.xml dan terletak di direktori app / manifes proyek Anda.

Benar, ada sangat sedikit pekerjaan untuk kita.

melarang rotasi layar:

 android:screenOrientation="portrait" 

Kami mengizinkan pekerjaan di Internet:

 <uses-permission android:name="android.permission.INTERNET"/> 

Dan ini dia sepenuhnya.

AndroidManifest.xml
 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="mikhail_akhmetov.fourweelsrobotcontrol"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.INTERNET"/> </manifest> 


Saat memulai, kita akan melihat sesuatu seperti:



Pada dasarnya itu saja. Sekarang troli dapat dikendalikan dari ponsel. Aplikasi ini sangat sederhana, karena ini adalah aplikasi demo tanpa "peluit dan penipuan," seperti mencari keranjang di jaringan rumah, menghubungkan, memutuskan sambungan, dan fitur berguna lainnya yang membuat hidup lebih mudah, tetapi membuat kode sulit dimengerti.

Di sisi lain, pengoperasian dengan tombol di layar sama
"Cara minum hanya vodka, bahkan dari leher - tidak ada di dalamnya kecuali merana dan ribut."
Dan Venya Erofeev benar dalam hal ini, tentu saja.

Jauh lebih menarik, misalnya, untuk mengarahkan kereta dengan bantuan akselerometer standar pada smartphone yang sama.

Selain itu, fitur ini juga diimplementasikan dengan sangat sederhana, melalui niat yang disebut. Benar, membuat niat Anda sendiri lebih sulit daripada menggunakan yang sudah jadi. Untungnya, tidak ada yang melarang menggunakan yang sudah jadi.

ACCELEROMETER DI MASSA



Karenanya, kode kami di MainActivity (dan hanya di dalamnya) akan berubah minimal.

Tambahkan variabel untuk accelerometer:

 private SensorManager mSensorManager; private Sensor mOrientation; private float xy_angle; private float xz_angle; 

Kami mendapatkan sensor itu sendiri dari sistem dan mendaftarkannya sebagai pendengar.

 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); //    mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); //    mSensorManager.registerListener(this, mOrientation, SensorManager.SENSOR_DELAY_NORMAL); 

Kami mengimplementasikan antarmuka pendengar itu sendiri:

 public class MainActivity implements SensorEventListener 

Dan kita akan menulis empat metode wajib yang akan kita gunakan hanya yang terakhir. Metode yang berhasil ketika mengubah pembacaan accelerometer. Sebenarnya, saya ingin menginterogasi accelerometer sendiri, seperti periferal normal dengan periode sekitar 100 ms, karena ada kecurigaan (karena nama onChanged) bahwa metode ini bekerja terlalu sering. Tapi semuanya ada pribadi dan buah ara untuk antarmuka Anda akan melewati.

 @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { //    } @Override protected void onResume() { super.onResume(); } @Override protected void onPause() { super.onPause(); } @Override public void onSensorChanged(SensorEvent event) {} //   

Akibatnya, MainActivity.java akan mengambil formulir berikut
 import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.content.Context; import android.hardware.Sensor; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.ImageButton; import android.widget.TextView; public class MainActivity extends AppCompatActivity implements SensorEventListener { private ImageButton mButtonUP; private ImageButton mButtonDOWN; private ImageButton mButtonLEFT; private ImageButton mButtonRIGHT; public static byte direction = 100; private SensorManager mSensorManager; private Sensor mOrientation; private float xy_angle; private float xz_angle; private int x; private int y; private TextView xyView; private TextView xzView; private TextView zyView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new HTTP_client(40000); new Udp_client(); mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); //    mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); //    mSensorManager.registerListener(this, mOrientation, SensorManager.SENSOR_DELAY_NORMAL); xyView = (TextView) findViewById(R.id.textViewX); // xzView = (TextView) findViewById(R.id.textViewY); //       zyView = (TextView) findViewById(R.id.textViewZ);//   "direction" mButtonUP = (ImageButton) findViewById(R.id.imageButtonUP); mButtonDOWN = (ImageButton) findViewById(R.id.imageButtonDown); mButtonLEFT = (ImageButton) findViewById(R.id.imageButtonLeft); mButtonRIGHT = (ImageButton) findViewById(R.id.imageButtonRight); //    } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { //    } @Override protected void onResume() { super.onResume(); } @Override protected void onPause() { super.onPause(); } @Override public void onSensorChanged(SensorEvent event) { //   xy_angle = event.values[0]*10; // XY xz_angle = event.values[1]*10; // XZ x=-(int) xy_angle*1; y=-(int) xz_angle*1; xyView.setText(" x = "+ String.valueOf(x)); xzView.setText(" y = "+String.valueOf(y)); zyView.setText(" direction "+String.valueOf(direction)); if(y>-40&&y<-20){ direction=100;//   ,   ,     if (x>10){//   10  30  20  direction=(byte)(x+30); if (direction>60){direction=60;} } if(x<-10){ direction=(byte)(-x+50); if (direction>80){direction=80;} } } else { if (y > -20) {//  ,  -20: 20  40  direction = (byte) (y / 2 + 10); if (direction > 20) { direction = 20; } ; } if (y < -40) {//  ,  -40: -80  40  direction = (byte) (-y - 20); if (direction > 40) { direction = 40; } ; } } } } //   direction 100  // 1-20  ,   -20 // 21-40  ,   -40 // 41-60 ,  10 // 61-80 ,   -10 


Program menampilkan sensor dalam dua sumbu pada layar smartphone. Alih-alih sumbu ketiga, yang tidak digunakan, variabel arah "arah" ditampilkan. Dan data yang sama berjalan dalam bentuk aliran byte ke troli. Namun, karena alirannya murni byte, akan sulit untuk menentukan di mana perintah "forward" atau "stop" berada. Karena itu, saya bertindak sederhana: setiap arah dan sudut kemiringan memiliki rentang angka sendiri. Secara kasar, 1-20 adalah "maju" dengan kecepatan yang sesuai, 21-40 adalah "mundur" dan seterusnya. Tentu saja, itu mungkin untuk mengirimkan data murni melalui UDP, dan perintah kontrol itu sendiri harus ditetapkan melalui protokol TCP, dan ini tentunya akan lebih benar. Tetapi untuk ini, Anda perlu mengedit program pada ESP8266 itu sendiri, yang saya belum inginkan.

Jadi, kereta itu berguling-guling di sekitar apartemen, bereaksi sensitif terhadap lereng GalaxyS7 saya, tetapi bahkan ini, seperti yang sering dikatakan Venya, masih belum.

“Sekarang aku menawarkan yang terakhir dan yang terbaik. "Mahkota kerja, di atas semua imbalan," seperti kata penyair. Singkatnya, saya menawarkan koktail "Offal Off", minuman yang menaungi segalanya. Ini bukan minuman lagi - itu adalah musik dari bola. „

Di zaman Siri dan Alexa ini, adakah yang bisa memutar tangan Anda? Biarkan kontrol suara patuh!

Dan SEKARANG MENDENGARKANKU!



Saya kutip:

Sebenarnya, bekerja dengan pengenalan suara dan sintesis suara di Android sangat sederhana. Semua perhitungan rumit disembunyikan dari kami di perpustakaan yang agak elegan dengan API sederhana. Anda dapat menguasai pelajaran ini bahkan jika Anda memiliki pengetahuan pemrograman yang sangat dangkal untuk Android.

Faktanya, semuanya ternyata canggung bagi saya, tetapi kemungkinan besar karena saya menggunakan opsi paling sederhana, dan tidak menggali API ini dengan benar. Semuanya juga dilakukan melalui niat, dengan bantuan yang kita beralih ke mesin suara Google, yaitu fungsi pengenalan ucapannya. Karena itu, Anda memerlukan Internet yang berfungsi.

Sekali lagi hanya perubahan MainActivity.java, meskipun saya mengubah tata letak sedikit lebih (empat tombol sekarang benar-benar tidak berguna di sana, satu sudah cukup).

Berikut ini telah ditambahkan ke MainActivity.java:

Maksud yang sama:

 Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, ", ,  -??? "); startActivityForResult(intent, Print_Words); 

Dan apa yang dikembalikan:

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //    : if (requestCode==Print_Words && resultCode==RESULT_OK) { //     ,   : ArrayList<String>result=data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); //     TextView: stroka_otveta = result.toString(); } 

Dan dia mengembalikan serangkaian kata-kata yang mirip, dan dalam bentuk "sampah", dengan segala macam tanda kurung dan koma. Dan Anda hanya perlu memilih kata yang mirip dengan yang Anda katakan. Baik dan sesuai, jika kata "maju" tertangkap, maka kita maju, jika "benar" maka ke kanan dan seterusnya. Tentu saja, kita harus memperhitungkan di mana melalui "E", di mana koma tambahan terpasang (saya memotong tanda kurung, tetapi saya tidak memiliki kekuatan yang cukup untuk koma).

Secara total, teks MainActivity.java sendiri menjadi demikian
 import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.ImageButton; import android.widget.TextView; import java.util.ArrayList; import android.content.Intent; import android.speech.RecognizerIntent; public class MainActivity extends AppCompatActivity { private ImageButton mButtonUP; public static byte direction = 100; public String stroka_otveta; private static final int Print_Words = 100; private TextView EnteredText1; private TextView EnteredText2; public static TextView EnteredText3; private boolean slovo_raspoznano =false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Udp_client(); new HTTP_client(40000); EnteredText1 = (TextView) findViewById(R.id.textViewX); // EnteredText2 = (TextView) findViewById(R.id.textViewY); // EnteredText3 = (TextView) findViewById(R.id.textViewZ); // mButtonUP = (ImageButton) findViewById(R.id.imageButtonUP); mButtonUP.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN){ if(HTTP_client.ok){ // RecognizerIntent        : EnteredText3.setText(" http  "); Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, ", ,  -??? "); startActivityForResult(intent, Print_Words); } else { EnteredText3.setText("  "); } } if (event.getAction() == MotionEvent.ACTION_UP ){ } return false; } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //    : if (requestCode==Print_Words && resultCode==RESULT_OK) { //     ,   : ArrayList<String>result=data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); //     TextView: stroka_otveta = result.toString(); } StringBuffer sb = new StringBuffer(stroka_otveta); sb.deleteCharAt(stroka_otveta.length()-1); sb.deleteCharAt(0); stroka_otveta=sb.toString(); String[] words = stroka_otveta.split("\\s"); //        () //    for(int i = 0; i< words.length;i++) { if(words[i].equals(",")||words[i].equals("")) { direction = 1; slovo_raspoznano=true; stroka_otveta=words[i]; } if(words[i].equals(",")||words[i].equals("")){ direction=2; slovo_raspoznano=true; stroka_otveta=words[i]; } if(words[i].equals(",")|| words[i].equals("")){ direction=4; slovo_raspoznano=true; stroka_otveta=words[i]; } if(words[i].equals(",")|| words[i].equals(",")|| words[i].equals("") || words[i].equals("")){ direction=3; slovo_raspoznano=true; stroka_otveta=words[i]; } if(words[i].equals(",")|| words[i].equals(",")|| words[i].equals("") || words[i].equals("")){ direction=100; slovo_raspoznano=true; stroka_otveta=words[i]; } } if(!slovo_raspoznano){ direction=100; stroka_otveta=" ,   ... "; } EnteredText1.setText(" "+direction+" " +stroka_otveta); slovo_raspoznano=false; super.onActivityResult(requestCode, resultCode, data); } } 

Nah, sampai tata letak tumpukan dengan satu tombol

activity_main.xml.
  <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.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="mikhail_akhmetov.fourwheelsrobotandroidvoice.MainActivity"> <ImageButton android:id="@+id/imageButtonUP" style="@android:style/Widget.ImageButton" android:layout_width="160dp" android:layout_height="146dp" android:layout_marginTop="8dp" android:background="@android:color/holo_orange_dark" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@android:drawable/arrow_up_float" android:layout_marginBottom="8dp" app:layout_constraintBottom_toTopOf="@+id/linearLayout"/> <LinearLayout android:id="@+id/linearLayout" android:layout_width="368dp" android:layout_height="227dp" android:layout_marginBottom="11dp" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:orientation="vertical" android:weightSum="1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"> <TextView android:id="@+id/textViewTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="   " android:textColor="@android:color/holo_red_dark"/> <TextView android:id="@+id/textViewX" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.28" /> <TextView android:id="@+id/textViewY" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.28" /> <TextView android:id="@+id/textViewZ" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.23" /> </LinearLayout> </android.support.constraint.ConstraintLayout> 

Hal yang paling menakjubkan adalah bahwa itu benar-benar mengendarai dan mendengarkan suara (sebagai aturan). Tapi, tentu saja, antarmuka rem; saat Anda berkata, sampai diakui dan akan kembali; Singkatnya, pilih kecepatan kecil di muka atau ruangan itu sebaliknya.

Itu saja untuk hari ini, saya akan senang jika saya menyukainya.

Source: https://habr.com/ru/post/id409107/


All Articles